## 1. 一些实用资源
-如果有意研读LunaixOS的内核代码和其中的设计,以下资料可能会对此有用。
+如果有意研读LunaixOS的内核代码和其中的设计,或欲开始属于自己的OS开发之道,以下资料可能会对此有用。
+ [最新的LunaixOS源代码分析教程](docs/tutorial/0-教程介绍和环境搭建.md)
+ [内核虚拟内存的详细布局](docs/img/lunaix-os-mem.png)
+ [LunaixOS启动流程概览](docs/img/boot_sequence.jpeg)
+ LunaixOS总体架构概览(WIP)
++ [作者修改的QEMU](https://github.com/Minep/qemu) (添加了一些额外用于调试的功能)
## 2. 当前进度以及支持的功能
-该操作系统支持x86架构,运行在保护模式中,采用宏内核架构,目前仅支持单核心。架构与内核的解耦合工作正在进行中。
+Lunaix内核具有支持多种不同的指令集架构的能力,目前支持如下:
-在下述列表中,则列出目前所支持的所用功能和特性。列表项按照项目时间戳进行升序排列。
++ x86_32
++ x86_64
+
+Lunaix全部特性一览:
+ 使用Multiboot进行引导启动
+ + Multiboot 1
+ + Multiboot 2 (WIP)
+ APIC/IOAPIC作为中断管理器和计时器
+ ACPI
+ 虚拟内存
-+ 内存管理与按需分页
-+ 键盘输入
+ + 架构中性设计
+ + 按需分页
+ + Copy-on-Write
++ 内存管理
+ 进程模型
-+ 54个常见的Linux/POSIX系统调用([附录1](#appendix1))
-+ 用户模式
++ 61个常见的Linux/POSIX系统调用([附录1](#appendix1))
++ 用户/内核态隔离
+ 信号机制
+ PCI 3.0
+ PCIe 1.1 (WIP)
-+ Serial ATA AHCI
-+ 文件系统
++ 块设备驱动
+ + Serial ATA AHCI
+ + ATA设备
+ + ATAPI封装的SCSI协议
++ 文件系统(POSIX.1-2008, section 5 & 10)
+ 虚拟文件系统
+ + 内核态文件系统(twifs, Lunaix自己的sysfs)
+ + 设备文件系统(devfs, Lunaix自己的udev)
+ + 进程文件系统(procfs)
+ ISO9660
- + 原生
- + Rock Ridge拓展
+ + ECMA-119
+ + IEEE P1282(Rock Ridge拓展)
+ 远程GDB串口调试 (COM1@9600Bd)
+ 用户程序加载与执行
-+ 动态链接 (WIP)
+ 通用设备抽象层
-+ 通用图形设备抽象层
- + 标准VGA实现
-+ 虚拟终端设备接口(兼容 POSIX.1-2008)
+ + 架构中性的设备支持位于:`lunaix-os/hal`
+ + 16550 UART
+ + ACPI (不完全实现)
+ + 架构耦合的设备支持位于:`lunaix-os/arch/<ARCH>/hal`
+ + x86
+ + APIC/IOAPIC 组合
+ + MC146818 RTC
+ + i8042 PS/2
+ + RNG(使用`rdrand`)
++ 通用图形设备抽象层 (Draft)
+ + 参考:`lunaix-os/hal/gfxa`
++ 虚拟终端设备接口(POSIX.1-2008, section 11)
+ + 参考:`lunaix-os/hal/term`
+ 线程模型
-
-已经测试过的环境:
-
-+ QEMU (>=7.0.0)
-+ Bochs(SATA功能不支持)
-+ Virtualbox
-+ Dell G3 3779
+ + 用户线程支持(pthread系列)
+ + 内核线程支持(抢占式内核设计)
## 3. 目录结构
## 4. 编译与构建
+**!如果想要立刻构建并运行,请参考4.6!**
+
构建该项目需要满足以下条件:
+ gcc 工具链
### 4.1 使用 GNU CC 工具链
-正如同大多数OS一样,LunaixOS 是一个混合了 C 和汇编的产物。这就意味着你得要使用一些标准的C编译器来构建Lunaix。在这里,我推荐使用 GNU CC 工具链来进行构建。至于其他的工具链,如llvm,也可以去尝试,但对此我就不能作任何的保证了。
+正如同大多数OS一样,LunaixOS 是一个混合了 C 和汇编的产物。这就意味着你得要使用一些标准的C编译器来构建Lunaix。在这里,我推荐使用 GNU CC 工具链来进行构建。因为Lunaix 在编写时使用了大量的GNU CC 相关编译器属性修饰 (`__attribute__`) 。假若使用其他工具链,如LLVM,我对此就不能做出任何保证了。
如果你使用的是基于 x86 指令集的Linux系统,不论是64位还是32位,**其本机自带的gcc就足以编译Lunaix**。 当然了,如果说你的平台是其他非x86的,你也可以指定使用某个针对x86_32的gcc套件来进行交叉编译——在`make`时通过`CX_PREFIX`变量来指定gcc套件的前缀。如下例所示,我们可以在任意平台上,如risc-v,单独使用一个面向x86_32的gcc来进行交叉编译:
make CX_PREFIX=i686-linux-gnu- all
```
-由于目前Lunaix仅支持x86_32微架构, `CX_PREFIX` 指向的gcc必须具有针对x86_32架构进行交叉编译的能力。
-
### 4.2 Docker镜像
对于开发环境,本项目也提供了Docker镜像封装。开箱即用,无需配置,非常适合懒人或惜时者。详细使用方法请转到:[Lunaix OSDK项目](https://github.com/Minep/os-devkit)。
### 4.3 构建选项
+
假若条件满足,那么可以直接执行`make all`进行构建,完成后可在生成的`build`目录下找到可引导的iso。
本项目支持的make命令:
| 命令 | 用途 |
| ------------------------ | ----------------------------------------------- |
-| `make all` | 构建镜像(`-O2`,但禁用CSE相关的优化项 **※** ) |
-| `make instable` | 构建镜像(`-O2`,开启CSE相关优化) |
-| `make all-debug` | 构建适合调试用的镜像(`-Og`) |
-| `make run` | 使用QEMU运行build目录下的镜像 |
-| `make debug-qemu` | 构建并使用QEMU进行调试 |
-| `make debug-bochs` | 构建并使用Bochs进行调试 |
-| `make debug-qemu-vscode` | 用于vscode整合 |
-| `make clean` | 删除build目录 |
+| `make all` | 等价于 `make image` |
+| `make image` | 构建ISO镜像,可直接启动,使用ISO9660文件系统 |
+| `make kernel` | 构建内核ELF镜像,无法直接启动,需要引导程序 |
+| `make clean` | 删除构建缓存,用于重新构建 |
+| `make config` | 配置Lunaix |
-**※:由于在`-O2`模式下,GCC会进行CSE优化,这导致LunaixOS会出现一些非常奇怪、离谱的bug,从而影响到基本运行。具体原因有待调查。**
+与make命令配套的环境变量,Lunaix的makefile会自动检测这些环境变量,以更改构建行为
-### 4.4 设置内核启动参数
++ `MODE={debug|release}` 使用debug模式构建(-Og)或者release模式(-O2)
++ `ARCH=<isa>` 为指定的指令集架构编译Lunaix。 所使用的配置选项均为选定架构默认,该环境变量
+ 存在的目的就是方便用户进行快速编译,而无需钻研Lunaix的种种配置项。
-在 make 的时候通过`CMDLINE`变量可以设置内核启动参数列表。该列表可以包含多个参数,通过一个或多个空格来分割。每个参数可以为键值对 `<key>=<val>` 或者是开关标志位 `<flag>`。目前 Lunaix 支持以下参数:
+### 4.4 Lunaix的功能配置
-+ `console=<dev>` 设置系统终端的输入输出设备(tty设备)。其中 `<dev>` 是设备文件路径 (注意,这里的设备文件路径是针对Lunaix,而非Linux)。关于LunaixOS设备文件系统的介绍可参考 Lunaix Wiki(WIP)
+Lunaix是一个可配置的内核,允许用户在编译前选择应当包含或移除的功能。
-如果`CMDLINE`未指定,则将会载入默认参数:
+使用`make config`来进行基于命令行的交互配置。呈现方式采用Shell的形式,所有的配置项按照类似于文件树的形式组织,如单个配置项为一个“文件”,多个配置项组成的配置组为一个目录,呈现形式为方括号`[]`包裹起来的项目。在提示符中输入`usage`并回车可以查看具体的使用方法。
+
+一个最常用的配置可能就是`architecture_support/arch`了,也就是配置Lunaix所面向的指令集。比如,编译一个在x86_64平台上运行的Lunaix,在提示符中输入(**注意等号两侧的空格,这是不能省略的**):
```
-console=/dev/ttyFB0
+/architecture_support/arch = x86_64
```
-其中,`/dev/ttyFB0` 指向基于VGA文本模式的tty设备,也就是平时启动QEMU时看到的黑色窗口。
-
-当然,读者也可以使用 `/dev/ttyS0` 来作为默认tty设备,来验证 Lunaix 的灵活性与兼容性。该路径指向第一个串口设备。可以通过telnet协议在`12345`端口上进行访问——端口号可以自行修改QEMU启动参数(位于:`makeinc/qemu.mkinc`)来变更。
-
-**注意:** 根据操作系统和键盘布局的不同,telnet客户端对一些关键键位的映射(如退格,回车)可能有所差别(如某些版本的Linux会将退格键映射为`0x7f`,也就是ASCII的`<DEL>`字符,而非我们熟知`0x08`)。如果读者想要通过串口方式把玩Lunaix,请修改`usr/init/init.c`里面的终端初始化代码,将`VERASE`设置为正确的映射(修改方式可以参考 POSIX termios 的使用方式。由于Lunaix的终端接口的实现是完全兼容POSIX的,读者可以直接去查阅Linux自带的帮助`man termios`,无需作任何的转换)
-
-## 5. 运行,分支以及 Issue
+之后输入`exit`保存并推出。而后正常编译。
-### 5.1 虚拟磁盘(非必须)
-你可以绑定一个虚拟磁盘镜像,可以使用如下命令快速创建一个:
+### 4.5 设置内核启动参数
-```bash
-qemu-img create -f vdi machine/disk0.vdi 128M
-```
+在 make 的时候通过`CMDLINE`变量可以设置内核启动参数列表。该列表可以包含多个参数,通过一个或多个空格来分割。每个参数可以为键值对 `<key>=<val>` 或者是开关标志位 `<flag>`。目前 Lunaix 支持以下参数:
-如果你想要使用别的磁盘镜像,需要修改`configs/make-debug-tool`
++ `console=<dev>` 设置系统终端的输入输出设备(tty设备)。其中 `<dev>` 是设备文件路径 (注意,这里的设备文件路径是针对Lunaix,而非Linux)。关于LunaixOS设备文件系统的介绍可参考 Lunaix Wiki(WIP)
-找到这一行:
+如果`CMDLINE`未指定,则将会载入默认参数:
```
--drive id=disk,file="machine/disk0.vdi",if=none \
+console=/dev/ttyFB0
```
-然后把`machine/disk0.vdi`替换成你的磁盘路径。
+其中,`/dev/ttyFB0` 指向基于VGA文本模式的tty设备,也就是平时启动QEMU时看到的黑色窗口。
-有很多办法去创建一个虚拟磁盘,比如[qemu-img](https://qemu-project.gitlab.io/qemu/system/images.html)。
+当然,读者也可以使用 `/dev/ttyS0` 来作为默认tty设备,来验证 Lunaix 的灵活性与兼容性。该路径指向第一个串口设备。可以通过telnet协议在`12345`端口上进行访问——端口号可以自行修改QEMU启动参数(位于:`makeinc/qemu.mkinc`)来变更。
-### 5.2 代码稳定性
+**注意:** 根据操作系统和键盘布局的不同,telnet客户端对一些关键键位的映射(如退格,回车)可能有所差别(如某些版本的Linux会将退格键映射为`0x7f`,也就是ASCII的`<DEL>`字符,而非我们熟知`0x08`)。如果读者想要通过串口方式把玩Lunaix,请修改`usr/init/init.c`里面的终端初始化代码,将`VERASE`设置为正确的映射(修改方式可以参考 POSIX termios 的使用方式。由于Lunaix的终端接口的实现是完全兼容POSIX的,读者可以直接去查阅Linux自带的帮助`man termios`,无需作任何的转换)
-主分支一般是稳定的。因为在大多数情况下,我都会尽量保证本机运行无误后,push到该分支中。至于其他的分支,则是作为标记或者是开发中的功能。前者标记用分支一般会很快删掉;后者开发分支不能保证稳定性,这些分支的代码有可能没有经过测试,但可以作为Lunaix当前开发进度的参考。
+### 4.6 测试与体验 Lunaix
-该系统是经过虚拟机和真机测试。如果发现在使用`make all`之后,虚拟机中运行报错,则一般是编译器优化问题。这个问题笔者一般很快就会修复,如果你使用别的版本的gcc(笔者版本11.2),出现了此问题,欢迎提issue。请参考[附录3:Issue的提交](#appendix3)
+用户可以使用脚本`live_debug.sh` 来快速运行Lunaix。 该脚本自动按照默认的选项构建Lunaix,而后调用 `scripts/qemu.py` 根据配置文件生成QEMU启动参数
+(配置文件位于`scripts/qemus/`)
-下面列出一些可能会出现的问题。
+由于该脚本的主要用途是方便作者进行调试,所以在QEMU窗口打开后还需要进行以下动作:
-#### 问题#1: QEMU下8042控制器提示找不到
+1. 使用telnet连接到`localhost:12345`,这里是Lunaix进行标准输入输出所使用的UART映射(QEMU为guest提供UART实现,并将其利用telnet协议重定向到宿主机)
+2. 在GDB窗口中输入`c`然后回车,此时Lunaix开始运行。这样做的目的是允许在QEMU进行模拟前,事先打好感兴趣的断点。
-è¿\99æ\98¯QEMUé\85\8dç½®ACPIæ\97¶ç\9a\84ä¸\80个bugï¼\8cå\9c¨7.0.0ç\89\88ä¸ä¿®å¤\8däº\86。
+该è\84\9aæ\9c¬ç\9a\84è¿\90è¡\8cé\9c\80è¦\81设置 `ARCH=<isa>` ç\8e¯å¢\83å\8f\98é\87\8fï¼\8cå\85¶å\80¼é\9c\80è¦\81ä¸\8eç¼\96è¯\91æ\97¶å\88¶å®\9aç\9a\84å\80¼ä¸\80è\87´。
-#### 问题#2:多进程运行时,偶尔会出现General Protection错误
+## 5. 运行,分支以及 Issue
-这很大概率是出现了竞态条件。虽然是相当不可能的。但如果出现了,还是请提issue。
+### 5.1 代码稳定性
-#### 问题#3:Bochs无法运行,提示找不到AHCI控制器
+主分支一般是稳定的。因为在大多数情况下,我都会尽量保证本机运行无误后,push到该分支中。至于其他的分支,则是作为标记或者是开发中的功能。前者标记用分支一般会很快删掉;后者开发分支不能保证稳定性,这些分支的代码有可能没有经过测试,但可以作为Lunaix当前开发进度的参考。
-正常,**因为Bochs不支持SATA**。请使用QEMU或VirtualBox。
+该系统是经过虚拟机和真机测试。如果发现在使用`make all`之后,虚拟机中运行报错,则一般是编译器优化问题。这个问题笔者一般很快就会修复,如果你使用别的版本的gcc(笔者版本11.2),出现了此问题,欢迎提issue。请参考[附录3:Issue的提交](#appendix3)
## 6. 调试 Lunaix 内核
## 7. 参考教程
-**没有!!** 本教程以及该操作系统均为原创,没有基于任何市面上现行的操作系统开发教程,且并非是基于任何的开源内核的二次开发。
+#### 没有!!
+
+本教程以及该操作系统的所有的架构设计与实现**均为原创**。
+
+对此,作者可以保证,该项目是做到了三个 “没有”:
+
++ **没有** 参考任何现行的,关于操作系统开发的,教程或书籍。
++ **没有** 参考任何开源内核的源代码(包括Linux)
++ **没有** 基于任何开源内核的二次开发行为。
为了制作LunaixOS,作者耗费大量时间和精力钻研技术文档,手册,理论书籍以及现行工业标准,从而尽量保证了知识的一手性。(这样一来,读者和听众们也算是拿到了二手的知识,而不是三手,四手,甚至n手的知识)。
#### 网站
-+ [OSDev](https://wiki.osdev.org/Main_Page) - 杂七杂八的参考,很多过来人的经验。作者主要用于上古资料查询以及收集;技术文献,手册,标准的粗略总结;以及开发环境/工具链的搭建。
++ [OSDev](https://wiki.osdev.org/Main_Page) - 杂七杂八的参考,很多过来人的经验。作者主要用于上古资料查询以及收集;技术文献,手册,标准的粗略总结;以及开发环境/工具链的搭建。当然,上面的内容假设了x86_32架构的生态,对于其他的ISA支持,该网站便失去了其价值了。
+ [FreeVGA](http://www.osdever.net/FreeVGA/home.htm) - 98年的资源!关于VGA编程技术的宝藏网站。
+ GNU CC 和 GNU LD 的官方文档。
+ [PCI Lookup](https://www.pcilookup.com/) - PCI设备编号查询
.builder/
.config.json
+link/lunaix.ld
+
.gdb_history
**.o
"${workspaceFolder}/includes",
"${workspaceFolder}/includes/usr",
"${workspaceFolder}/usr/includes",
- "${workspaceFolder}/arch/i386/includes",
+ "${workspaceFolder}/arch/x86/includes",
],
"compilerArgs": [
"-ffreestanding",
- "-D__ARCH__=i386",
- "-D__LUNAIXOS_DEBUG__",
+ "-m32",
"-include .builder/configs.h"
],
"defines": [],
- "compilerPath": "${HOME}/opt/i686-gcc-12/bin/i686-elf-gcc",
+ "compilerPath": "/usr/bin/gcc",
+ "cStandard": "gnu99",
+ "intelliSenseMode": "gcc-x86"
+ },
+ {
+ "name": "OS-DEV64",
+ "includePath": [
+ "${workspaceFolder}/includes",
+ "${workspaceFolder}/includes/usr",
+ "${workspaceFolder}/usr/includes",
+ "${workspaceFolder}/arch/x86/includes",
+ ],
+ "compilerArgs": [
+ "-ffreestanding",
+ "-m64",
+ "-include .builder/configs.h"
+ ],
+ "defines": [],
+ "compilerPath": "/usr/bin/gcc",
"cStandard": "gnu99",
"intelliSenseMode": "gcc-x86"
}
type(str)
seq_num = int(time.time() / 3600)
- default("dev-2024_%d"%(seq_num))
+ default("%s dev-2024_%d"%(v(arch), seq_num))
@Collection
def debug_and_testing():
use({
config("arch"): {
- "i386": "i386",
+ "i386": "x86",
+ "x86_64": "x86",
"aarch64": "arm",
"rv64": "riscv"
}
-include("i386/LConfig")
+include("x86/LConfig")
@Collection
def architecture_support():
""" Config ISA support """
type(["i386", "x86_64", "aarch64", "rv64"])
default("i386")
+
+ env_val = env("ARCH")
+ if env_val is not None:
+ set_value(env_val)
+
+ @Term
+ @ReadOnly
+ def arch_bits():
+ type(["64", "32"])
+ match v(arch):
+ case "i386":
+ default("32")
+ case "aarch64":
+ default("64")
+ case "rv64":
+ default("64")
+ case "x86_64":
+ default("64")
+ case _:
+ default("32")
+
\ No newline at end of file
+ Add implementation to function signature defined in header files under
`includes/lunaix/generic`
-+ Add implementation of syscall dispatching (Reference: `arhc/i386/syscall.S`)
++ Add implementation of syscall dispatching (Reference: `arhc/x86/syscall.S`)
+ Add implementation of interrupt handler dispatching (Reference:
- `arhc/i386/exceptions/intrhnds.S`)
+ `arhc/x86/exceptions/intrhnds.S`)
+ Add implementation of context switching, signal handling. (Reference:
- `arhc/i386/exceptions/interrupt.S`)
+ `arhc/x86/exceptions/interrupt.S`)
**TODO: make this procedure more standalone**
## Preparing the Flows
struct hart_state* parent_state;
} compact;
-void
-hart_flow_redirect(struct hart_state* state, ptr_t pc, ptr_t sp);
-
ptr_t
hart_pc(struct hart_state* state);
#ifndef __LUNAIX_ARCH_MEMPART_H
#define __LUNAIX_ARCH_MEMPART_H
-#define MEM_PAGE 0x1000UL
-#define MEM_1M 0x100000UL
-#define MEM_4M 0x400000UL
-#define MEM_HUGE 0x400000UL
-#define MEM_1G 0x40000000UL
#define END_POINT(name) (name + name##_SIZE - 1)
#include "pagetable.h"
#define KSTACK_PAGES 3
-#define KSTACK_SIZE (KSTACK_PAGES * MEM_PAGE)
+#define KSTACK_SIZE (KSTACK_PAGES * PAGE_SIZE)
/*
Regardless architecture we need to draw the line very carefully, and must
+++ /dev/null
-use("hal")
-
-sources([
- "exceptions/interrupts.c",
- "exceptions/i386_isrdef.c",
- "exceptions/intr_routines.c",
- "exceptions/i386_isrm.c",
-
- "exceptions/interrupt.S",
- "exceptions/intrhnds.S",
-])
-
-sources([
- "boot/mb_parser.c",
- "boot/kpt_setup.c",
- "boot/init32.c",
-
- "boot/boot.S",
- "boot/prologue.S"
-])
-
-sources([
- "mm/fault.c",
- "mm/tlb.c",
- "mm/pmm.c",
- "mm/gdt.c",
- "mm/vmutils.c"
-])
-
-sources([
- "klib/fast_crc.c",
- "klib/fast_str.c",
- "hart.c",
- "arch.c",
- "gdbstub.c",
- "trace.c",
-
- "syscall.S",
- "failsafe.S"
-])
-
-headers([
- "includes"
-])
-
-compile_opts([
- "-m32"
-])
-
-linking_opts([
- "-m32"
-])
\ No newline at end of file
+++ /dev/null
-
-@Group
-def x86_configurations():
- @Term
- def x86_enable_sse_feature():
- """
- Config whether to allow using SSE feature for certain
- optimization
- """
-
- type(bool)
- default(False)
-
- add_to_collection(architecture_support)
-
-
- @Term
- def x86_boot_options():
- type(["multiboot"])
- # type(["multiboot", "none"])
- default("multiboot")
-
- return v(arch) == "i386"
\ No newline at end of file
+++ /dev/null
-/* Generated from i386_isrdef.c.j2. Do NOT modify */
-
-#include <lunaix/types.h>
-#include <sys/i386_intr.h>
-
-#define IDT_INTERRUPT 0x70
-#define KERNEL_CS 0x8
-#define IDT_ATTR(dpl, type) (((type) << 5) | ((dpl & 3) << 13) | (1 << 15))
-#define IDT_ENTRY 256
-
-#define DECLARE_ISR(iv) extern void _asm_isr##iv();
-
-#define ISR_INSTALL(idt, iv, isr, dpl) \
- _idt[iv] = ((ptr_t)isr & 0xffff0000) | IDT_ATTR(dpl, IDT_INTERRUPT); \
- _idt[iv] <<= 32; \
- _idt[iv] |= (KERNEL_CS << 16) | ((ptr_t)isr & 0x0000ffff); \
-
-u64_t _idt[IDT_ENTRY];
-u16_t _idt_limit = sizeof(_idt) - 1;
-
-DECLARE_ISR(0)
-DECLARE_ISR(1)
-DECLARE_ISR(2)
-DECLARE_ISR(3)
-DECLARE_ISR(4)
-DECLARE_ISR(5)
-DECLARE_ISR(6)
-DECLARE_ISR(7)
-DECLARE_ISR(8)
-DECLARE_ISR(9)
-DECLARE_ISR(10)
-DECLARE_ISR(11)
-DECLARE_ISR(12)
-DECLARE_ISR(13)
-DECLARE_ISR(14)
-DECLARE_ISR(15)
-DECLARE_ISR(16)
-DECLARE_ISR(17)
-DECLARE_ISR(18)
-DECLARE_ISR(19)
-DECLARE_ISR(20)
-DECLARE_ISR(21)
-DECLARE_ISR(22)
-DECLARE_ISR(23)
-DECLARE_ISR(24)
-DECLARE_ISR(25)
-DECLARE_ISR(26)
-DECLARE_ISR(27)
-DECLARE_ISR(28)
-DECLARE_ISR(29)
-DECLARE_ISR(30)
-DECLARE_ISR(31)
-DECLARE_ISR(32)
-DECLARE_ISR(33)
-DECLARE_ISR(34)
-DECLARE_ISR(35)
-DECLARE_ISR(36)
-DECLARE_ISR(37)
-DECLARE_ISR(38)
-DECLARE_ISR(39)
-DECLARE_ISR(40)
-DECLARE_ISR(41)
-DECLARE_ISR(42)
-DECLARE_ISR(43)
-DECLARE_ISR(44)
-DECLARE_ISR(45)
-DECLARE_ISR(46)
-DECLARE_ISR(47)
-DECLARE_ISR(48)
-DECLARE_ISR(49)
-DECLARE_ISR(50)
-DECLARE_ISR(51)
-DECLARE_ISR(52)
-DECLARE_ISR(53)
-DECLARE_ISR(54)
-DECLARE_ISR(55)
-DECLARE_ISR(56)
-DECLARE_ISR(57)
-DECLARE_ISR(58)
-DECLARE_ISR(59)
-DECLARE_ISR(60)
-DECLARE_ISR(61)
-DECLARE_ISR(62)
-DECLARE_ISR(63)
-DECLARE_ISR(64)
-DECLARE_ISR(65)
-DECLARE_ISR(66)
-DECLARE_ISR(67)
-DECLARE_ISR(68)
-DECLARE_ISR(69)
-DECLARE_ISR(70)
-DECLARE_ISR(71)
-DECLARE_ISR(72)
-DECLARE_ISR(73)
-DECLARE_ISR(74)
-DECLARE_ISR(75)
-DECLARE_ISR(76)
-DECLARE_ISR(77)
-DECLARE_ISR(78)
-DECLARE_ISR(79)
-DECLARE_ISR(80)
-DECLARE_ISR(81)
-DECLARE_ISR(82)
-DECLARE_ISR(83)
-DECLARE_ISR(84)
-DECLARE_ISR(85)
-DECLARE_ISR(86)
-DECLARE_ISR(87)
-DECLARE_ISR(88)
-DECLARE_ISR(89)
-DECLARE_ISR(90)
-DECLARE_ISR(91)
-DECLARE_ISR(92)
-DECLARE_ISR(93)
-DECLARE_ISR(94)
-DECLARE_ISR(95)
-DECLARE_ISR(96)
-DECLARE_ISR(97)
-DECLARE_ISR(98)
-DECLARE_ISR(99)
-DECLARE_ISR(100)
-DECLARE_ISR(101)
-DECLARE_ISR(102)
-DECLARE_ISR(103)
-DECLARE_ISR(104)
-DECLARE_ISR(105)
-DECLARE_ISR(106)
-DECLARE_ISR(107)
-DECLARE_ISR(108)
-DECLARE_ISR(109)
-DECLARE_ISR(110)
-DECLARE_ISR(111)
-DECLARE_ISR(112)
-DECLARE_ISR(113)
-DECLARE_ISR(114)
-DECLARE_ISR(115)
-DECLARE_ISR(116)
-DECLARE_ISR(117)
-DECLARE_ISR(118)
-DECLARE_ISR(119)
-DECLARE_ISR(120)
-DECLARE_ISR(121)
-DECLARE_ISR(122)
-DECLARE_ISR(123)
-DECLARE_ISR(124)
-DECLARE_ISR(125)
-DECLARE_ISR(126)
-DECLARE_ISR(127)
-DECLARE_ISR(128)
-DECLARE_ISR(129)
-DECLARE_ISR(130)
-DECLARE_ISR(131)
-DECLARE_ISR(132)
-DECLARE_ISR(133)
-DECLARE_ISR(134)
-DECLARE_ISR(135)
-DECLARE_ISR(136)
-DECLARE_ISR(137)
-DECLARE_ISR(138)
-DECLARE_ISR(139)
-DECLARE_ISR(140)
-DECLARE_ISR(141)
-DECLARE_ISR(142)
-DECLARE_ISR(143)
-DECLARE_ISR(144)
-DECLARE_ISR(145)
-DECLARE_ISR(146)
-DECLARE_ISR(147)
-DECLARE_ISR(148)
-DECLARE_ISR(149)
-DECLARE_ISR(150)
-DECLARE_ISR(151)
-DECLARE_ISR(152)
-DECLARE_ISR(153)
-DECLARE_ISR(154)
-DECLARE_ISR(155)
-DECLARE_ISR(156)
-DECLARE_ISR(157)
-DECLARE_ISR(158)
-DECLARE_ISR(159)
-DECLARE_ISR(160)
-DECLARE_ISR(161)
-DECLARE_ISR(162)
-DECLARE_ISR(163)
-DECLARE_ISR(164)
-DECLARE_ISR(165)
-DECLARE_ISR(166)
-DECLARE_ISR(167)
-DECLARE_ISR(168)
-DECLARE_ISR(169)
-DECLARE_ISR(170)
-DECLARE_ISR(171)
-DECLARE_ISR(172)
-DECLARE_ISR(173)
-DECLARE_ISR(174)
-DECLARE_ISR(175)
-DECLARE_ISR(176)
-DECLARE_ISR(177)
-DECLARE_ISR(178)
-DECLARE_ISR(179)
-DECLARE_ISR(180)
-DECLARE_ISR(181)
-DECLARE_ISR(182)
-DECLARE_ISR(183)
-DECLARE_ISR(184)
-DECLARE_ISR(185)
-DECLARE_ISR(186)
-DECLARE_ISR(187)
-DECLARE_ISR(188)
-DECLARE_ISR(189)
-DECLARE_ISR(190)
-DECLARE_ISR(191)
-DECLARE_ISR(192)
-DECLARE_ISR(193)
-DECLARE_ISR(194)
-DECLARE_ISR(195)
-DECLARE_ISR(196)
-DECLARE_ISR(197)
-DECLARE_ISR(198)
-DECLARE_ISR(199)
-DECLARE_ISR(200)
-DECLARE_ISR(201)
-DECLARE_ISR(202)
-DECLARE_ISR(203)
-DECLARE_ISR(204)
-DECLARE_ISR(205)
-DECLARE_ISR(206)
-DECLARE_ISR(207)
-DECLARE_ISR(208)
-DECLARE_ISR(209)
-DECLARE_ISR(210)
-DECLARE_ISR(211)
-DECLARE_ISR(212)
-DECLARE_ISR(213)
-DECLARE_ISR(214)
-DECLARE_ISR(215)
-DECLARE_ISR(216)
-DECLARE_ISR(217)
-DECLARE_ISR(218)
-DECLARE_ISR(219)
-DECLARE_ISR(220)
-DECLARE_ISR(221)
-DECLARE_ISR(222)
-DECLARE_ISR(223)
-DECLARE_ISR(224)
-DECLARE_ISR(225)
-DECLARE_ISR(226)
-DECLARE_ISR(227)
-DECLARE_ISR(228)
-DECLARE_ISR(229)
-DECLARE_ISR(230)
-DECLARE_ISR(231)
-DECLARE_ISR(232)
-DECLARE_ISR(233)
-DECLARE_ISR(234)
-DECLARE_ISR(235)
-DECLARE_ISR(236)
-DECLARE_ISR(237)
-DECLARE_ISR(238)
-DECLARE_ISR(239)
-DECLARE_ISR(240)
-DECLARE_ISR(241)
-DECLARE_ISR(242)
-DECLARE_ISR(243)
-DECLARE_ISR(244)
-DECLARE_ISR(245)
-DECLARE_ISR(246)
-DECLARE_ISR(247)
-DECLARE_ISR(248)
-DECLARE_ISR(249)
-DECLARE_ISR(250)
-DECLARE_ISR(251)
-DECLARE_ISR(252)
-DECLARE_ISR(253)
-DECLARE_ISR(254)
-DECLARE_ISR(255)
-
-void
-exception_install_handler()
-{
- ISR_INSTALL(_idt, 0, _asm_isr0, 0)
- ISR_INSTALL(_idt, 1, _asm_isr1, 0)
- ISR_INSTALL(_idt, 2, _asm_isr2, 0)
- ISR_INSTALL(_idt, 3, _asm_isr3, 0)
- ISR_INSTALL(_idt, 4, _asm_isr4, 0)
- ISR_INSTALL(_idt, 5, _asm_isr5, 0)
- ISR_INSTALL(_idt, 6, _asm_isr6, 0)
- ISR_INSTALL(_idt, 7, _asm_isr7, 0)
- ISR_INSTALL(_idt, 8, _asm_isr8, 0)
- ISR_INSTALL(_idt, 9, _asm_isr9, 0)
- ISR_INSTALL(_idt, 10, _asm_isr10, 0)
- ISR_INSTALL(_idt, 11, _asm_isr11, 0)
- ISR_INSTALL(_idt, 12, _asm_isr12, 0)
- ISR_INSTALL(_idt, 13, _asm_isr13, 0)
- ISR_INSTALL(_idt, 14, _asm_isr14, 0)
- ISR_INSTALL(_idt, 15, _asm_isr15, 0)
- ISR_INSTALL(_idt, 16, _asm_isr16, 0)
- ISR_INSTALL(_idt, 17, _asm_isr17, 0)
- ISR_INSTALL(_idt, 18, _asm_isr18, 0)
- ISR_INSTALL(_idt, 19, _asm_isr19, 0)
- ISR_INSTALL(_idt, 20, _asm_isr20, 0)
- ISR_INSTALL(_idt, 21, _asm_isr21, 0)
- ISR_INSTALL(_idt, 22, _asm_isr22, 0)
- ISR_INSTALL(_idt, 23, _asm_isr23, 0)
- ISR_INSTALL(_idt, 24, _asm_isr24, 0)
- ISR_INSTALL(_idt, 25, _asm_isr25, 0)
- ISR_INSTALL(_idt, 26, _asm_isr26, 0)
- ISR_INSTALL(_idt, 27, _asm_isr27, 0)
- ISR_INSTALL(_idt, 28, _asm_isr28, 0)
- ISR_INSTALL(_idt, 29, _asm_isr29, 0)
- ISR_INSTALL(_idt, 30, _asm_isr30, 0)
- ISR_INSTALL(_idt, 31, _asm_isr31, 0)
- ISR_INSTALL(_idt, 32, _asm_isr32, 0)
- ISR_INSTALL(_idt, 33, _asm_isr33, 3)
- ISR_INSTALL(_idt, 34, _asm_isr34, 0)
- ISR_INSTALL(_idt, 35, _asm_isr35, 0)
- ISR_INSTALL(_idt, 36, _asm_isr36, 0)
- ISR_INSTALL(_idt, 37, _asm_isr37, 0)
- ISR_INSTALL(_idt, 38, _asm_isr38, 0)
- ISR_INSTALL(_idt, 39, _asm_isr39, 0)
- ISR_INSTALL(_idt, 40, _asm_isr40, 0)
- ISR_INSTALL(_idt, 41, _asm_isr41, 0)
- ISR_INSTALL(_idt, 42, _asm_isr42, 0)
- ISR_INSTALL(_idt, 43, _asm_isr43, 0)
- ISR_INSTALL(_idt, 44, _asm_isr44, 0)
- ISR_INSTALL(_idt, 45, _asm_isr45, 0)
- ISR_INSTALL(_idt, 46, _asm_isr46, 0)
- ISR_INSTALL(_idt, 47, _asm_isr47, 0)
- ISR_INSTALL(_idt, 48, _asm_isr48, 0)
- ISR_INSTALL(_idt, 49, _asm_isr49, 0)
- ISR_INSTALL(_idt, 50, _asm_isr50, 0)
- ISR_INSTALL(_idt, 51, _asm_isr51, 0)
- ISR_INSTALL(_idt, 52, _asm_isr52, 0)
- ISR_INSTALL(_idt, 53, _asm_isr53, 0)
- ISR_INSTALL(_idt, 54, _asm_isr54, 0)
- ISR_INSTALL(_idt, 55, _asm_isr55, 0)
- ISR_INSTALL(_idt, 56, _asm_isr56, 0)
- ISR_INSTALL(_idt, 57, _asm_isr57, 0)
- ISR_INSTALL(_idt, 58, _asm_isr58, 0)
- ISR_INSTALL(_idt, 59, _asm_isr59, 0)
- ISR_INSTALL(_idt, 60, _asm_isr60, 0)
- ISR_INSTALL(_idt, 61, _asm_isr61, 0)
- ISR_INSTALL(_idt, 62, _asm_isr62, 0)
- ISR_INSTALL(_idt, 63, _asm_isr63, 0)
- ISR_INSTALL(_idt, 64, _asm_isr64, 0)
- ISR_INSTALL(_idt, 65, _asm_isr65, 0)
- ISR_INSTALL(_idt, 66, _asm_isr66, 0)
- ISR_INSTALL(_idt, 67, _asm_isr67, 0)
- ISR_INSTALL(_idt, 68, _asm_isr68, 0)
- ISR_INSTALL(_idt, 69, _asm_isr69, 0)
- ISR_INSTALL(_idt, 70, _asm_isr70, 0)
- ISR_INSTALL(_idt, 71, _asm_isr71, 0)
- ISR_INSTALL(_idt, 72, _asm_isr72, 0)
- ISR_INSTALL(_idt, 73, _asm_isr73, 0)
- ISR_INSTALL(_idt, 74, _asm_isr74, 0)
- ISR_INSTALL(_idt, 75, _asm_isr75, 0)
- ISR_INSTALL(_idt, 76, _asm_isr76, 0)
- ISR_INSTALL(_idt, 77, _asm_isr77, 0)
- ISR_INSTALL(_idt, 78, _asm_isr78, 0)
- ISR_INSTALL(_idt, 79, _asm_isr79, 0)
- ISR_INSTALL(_idt, 80, _asm_isr80, 0)
- ISR_INSTALL(_idt, 81, _asm_isr81, 0)
- ISR_INSTALL(_idt, 82, _asm_isr82, 0)
- ISR_INSTALL(_idt, 83, _asm_isr83, 0)
- ISR_INSTALL(_idt, 84, _asm_isr84, 0)
- ISR_INSTALL(_idt, 85, _asm_isr85, 0)
- ISR_INSTALL(_idt, 86, _asm_isr86, 0)
- ISR_INSTALL(_idt, 87, _asm_isr87, 0)
- ISR_INSTALL(_idt, 88, _asm_isr88, 0)
- ISR_INSTALL(_idt, 89, _asm_isr89, 0)
- ISR_INSTALL(_idt, 90, _asm_isr90, 0)
- ISR_INSTALL(_idt, 91, _asm_isr91, 0)
- ISR_INSTALL(_idt, 92, _asm_isr92, 0)
- ISR_INSTALL(_idt, 93, _asm_isr93, 0)
- ISR_INSTALL(_idt, 94, _asm_isr94, 0)
- ISR_INSTALL(_idt, 95, _asm_isr95, 0)
- ISR_INSTALL(_idt, 96, _asm_isr96, 0)
- ISR_INSTALL(_idt, 97, _asm_isr97, 0)
- ISR_INSTALL(_idt, 98, _asm_isr98, 0)
- ISR_INSTALL(_idt, 99, _asm_isr99, 0)
- ISR_INSTALL(_idt, 100, _asm_isr100, 0)
- ISR_INSTALL(_idt, 101, _asm_isr101, 0)
- ISR_INSTALL(_idt, 102, _asm_isr102, 0)
- ISR_INSTALL(_idt, 103, _asm_isr103, 0)
- ISR_INSTALL(_idt, 104, _asm_isr104, 0)
- ISR_INSTALL(_idt, 105, _asm_isr105, 0)
- ISR_INSTALL(_idt, 106, _asm_isr106, 0)
- ISR_INSTALL(_idt, 107, _asm_isr107, 0)
- ISR_INSTALL(_idt, 108, _asm_isr108, 0)
- ISR_INSTALL(_idt, 109, _asm_isr109, 0)
- ISR_INSTALL(_idt, 110, _asm_isr110, 0)
- ISR_INSTALL(_idt, 111, _asm_isr111, 0)
- ISR_INSTALL(_idt, 112, _asm_isr112, 0)
- ISR_INSTALL(_idt, 113, _asm_isr113, 0)
- ISR_INSTALL(_idt, 114, _asm_isr114, 0)
- ISR_INSTALL(_idt, 115, _asm_isr115, 0)
- ISR_INSTALL(_idt, 116, _asm_isr116, 0)
- ISR_INSTALL(_idt, 117, _asm_isr117, 0)
- ISR_INSTALL(_idt, 118, _asm_isr118, 0)
- ISR_INSTALL(_idt, 119, _asm_isr119, 0)
- ISR_INSTALL(_idt, 120, _asm_isr120, 0)
- ISR_INSTALL(_idt, 121, _asm_isr121, 0)
- ISR_INSTALL(_idt, 122, _asm_isr122, 0)
- ISR_INSTALL(_idt, 123, _asm_isr123, 0)
- ISR_INSTALL(_idt, 124, _asm_isr124, 0)
- ISR_INSTALL(_idt, 125, _asm_isr125, 0)
- ISR_INSTALL(_idt, 126, _asm_isr126, 0)
- ISR_INSTALL(_idt, 127, _asm_isr127, 0)
- ISR_INSTALL(_idt, 128, _asm_isr128, 0)
- ISR_INSTALL(_idt, 129, _asm_isr129, 0)
- ISR_INSTALL(_idt, 130, _asm_isr130, 0)
- ISR_INSTALL(_idt, 131, _asm_isr131, 0)
- ISR_INSTALL(_idt, 132, _asm_isr132, 0)
- ISR_INSTALL(_idt, 133, _asm_isr133, 0)
- ISR_INSTALL(_idt, 134, _asm_isr134, 0)
- ISR_INSTALL(_idt, 135, _asm_isr135, 0)
- ISR_INSTALL(_idt, 136, _asm_isr136, 0)
- ISR_INSTALL(_idt, 137, _asm_isr137, 0)
- ISR_INSTALL(_idt, 138, _asm_isr138, 0)
- ISR_INSTALL(_idt, 139, _asm_isr139, 0)
- ISR_INSTALL(_idt, 140, _asm_isr140, 0)
- ISR_INSTALL(_idt, 141, _asm_isr141, 0)
- ISR_INSTALL(_idt, 142, _asm_isr142, 0)
- ISR_INSTALL(_idt, 143, _asm_isr143, 0)
- ISR_INSTALL(_idt, 144, _asm_isr144, 0)
- ISR_INSTALL(_idt, 145, _asm_isr145, 0)
- ISR_INSTALL(_idt, 146, _asm_isr146, 0)
- ISR_INSTALL(_idt, 147, _asm_isr147, 0)
- ISR_INSTALL(_idt, 148, _asm_isr148, 0)
- ISR_INSTALL(_idt, 149, _asm_isr149, 0)
- ISR_INSTALL(_idt, 150, _asm_isr150, 0)
- ISR_INSTALL(_idt, 151, _asm_isr151, 0)
- ISR_INSTALL(_idt, 152, _asm_isr152, 0)
- ISR_INSTALL(_idt, 153, _asm_isr153, 0)
- ISR_INSTALL(_idt, 154, _asm_isr154, 0)
- ISR_INSTALL(_idt, 155, _asm_isr155, 0)
- ISR_INSTALL(_idt, 156, _asm_isr156, 0)
- ISR_INSTALL(_idt, 157, _asm_isr157, 0)
- ISR_INSTALL(_idt, 158, _asm_isr158, 0)
- ISR_INSTALL(_idt, 159, _asm_isr159, 0)
- ISR_INSTALL(_idt, 160, _asm_isr160, 0)
- ISR_INSTALL(_idt, 161, _asm_isr161, 0)
- ISR_INSTALL(_idt, 162, _asm_isr162, 0)
- ISR_INSTALL(_idt, 163, _asm_isr163, 0)
- ISR_INSTALL(_idt, 164, _asm_isr164, 0)
- ISR_INSTALL(_idt, 165, _asm_isr165, 0)
- ISR_INSTALL(_idt, 166, _asm_isr166, 0)
- ISR_INSTALL(_idt, 167, _asm_isr167, 0)
- ISR_INSTALL(_idt, 168, _asm_isr168, 0)
- ISR_INSTALL(_idt, 169, _asm_isr169, 0)
- ISR_INSTALL(_idt, 170, _asm_isr170, 0)
- ISR_INSTALL(_idt, 171, _asm_isr171, 0)
- ISR_INSTALL(_idt, 172, _asm_isr172, 0)
- ISR_INSTALL(_idt, 173, _asm_isr173, 0)
- ISR_INSTALL(_idt, 174, _asm_isr174, 0)
- ISR_INSTALL(_idt, 175, _asm_isr175, 0)
- ISR_INSTALL(_idt, 176, _asm_isr176, 0)
- ISR_INSTALL(_idt, 177, _asm_isr177, 0)
- ISR_INSTALL(_idt, 178, _asm_isr178, 0)
- ISR_INSTALL(_idt, 179, _asm_isr179, 0)
- ISR_INSTALL(_idt, 180, _asm_isr180, 0)
- ISR_INSTALL(_idt, 181, _asm_isr181, 0)
- ISR_INSTALL(_idt, 182, _asm_isr182, 0)
- ISR_INSTALL(_idt, 183, _asm_isr183, 0)
- ISR_INSTALL(_idt, 184, _asm_isr184, 0)
- ISR_INSTALL(_idt, 185, _asm_isr185, 0)
- ISR_INSTALL(_idt, 186, _asm_isr186, 0)
- ISR_INSTALL(_idt, 187, _asm_isr187, 0)
- ISR_INSTALL(_idt, 188, _asm_isr188, 0)
- ISR_INSTALL(_idt, 189, _asm_isr189, 0)
- ISR_INSTALL(_idt, 190, _asm_isr190, 0)
- ISR_INSTALL(_idt, 191, _asm_isr191, 0)
- ISR_INSTALL(_idt, 192, _asm_isr192, 0)
- ISR_INSTALL(_idt, 193, _asm_isr193, 0)
- ISR_INSTALL(_idt, 194, _asm_isr194, 0)
- ISR_INSTALL(_idt, 195, _asm_isr195, 0)
- ISR_INSTALL(_idt, 196, _asm_isr196, 0)
- ISR_INSTALL(_idt, 197, _asm_isr197, 0)
- ISR_INSTALL(_idt, 198, _asm_isr198, 0)
- ISR_INSTALL(_idt, 199, _asm_isr199, 0)
- ISR_INSTALL(_idt, 200, _asm_isr200, 0)
- ISR_INSTALL(_idt, 201, _asm_isr201, 0)
- ISR_INSTALL(_idt, 202, _asm_isr202, 0)
- ISR_INSTALL(_idt, 203, _asm_isr203, 0)
- ISR_INSTALL(_idt, 204, _asm_isr204, 0)
- ISR_INSTALL(_idt, 205, _asm_isr205, 0)
- ISR_INSTALL(_idt, 206, _asm_isr206, 0)
- ISR_INSTALL(_idt, 207, _asm_isr207, 0)
- ISR_INSTALL(_idt, 208, _asm_isr208, 0)
- ISR_INSTALL(_idt, 209, _asm_isr209, 0)
- ISR_INSTALL(_idt, 210, _asm_isr210, 0)
- ISR_INSTALL(_idt, 211, _asm_isr211, 0)
- ISR_INSTALL(_idt, 212, _asm_isr212, 0)
- ISR_INSTALL(_idt, 213, _asm_isr213, 0)
- ISR_INSTALL(_idt, 214, _asm_isr214, 0)
- ISR_INSTALL(_idt, 215, _asm_isr215, 0)
- ISR_INSTALL(_idt, 216, _asm_isr216, 0)
- ISR_INSTALL(_idt, 217, _asm_isr217, 0)
- ISR_INSTALL(_idt, 218, _asm_isr218, 0)
- ISR_INSTALL(_idt, 219, _asm_isr219, 0)
- ISR_INSTALL(_idt, 220, _asm_isr220, 0)
- ISR_INSTALL(_idt, 221, _asm_isr221, 0)
- ISR_INSTALL(_idt, 222, _asm_isr222, 0)
- ISR_INSTALL(_idt, 223, _asm_isr223, 0)
- ISR_INSTALL(_idt, 224, _asm_isr224, 0)
- ISR_INSTALL(_idt, 225, _asm_isr225, 0)
- ISR_INSTALL(_idt, 226, _asm_isr226, 0)
- ISR_INSTALL(_idt, 227, _asm_isr227, 0)
- ISR_INSTALL(_idt, 228, _asm_isr228, 0)
- ISR_INSTALL(_idt, 229, _asm_isr229, 0)
- ISR_INSTALL(_idt, 230, _asm_isr230, 0)
- ISR_INSTALL(_idt, 231, _asm_isr231, 0)
- ISR_INSTALL(_idt, 232, _asm_isr232, 0)
- ISR_INSTALL(_idt, 233, _asm_isr233, 0)
- ISR_INSTALL(_idt, 234, _asm_isr234, 0)
- ISR_INSTALL(_idt, 235, _asm_isr235, 0)
- ISR_INSTALL(_idt, 236, _asm_isr236, 0)
- ISR_INSTALL(_idt, 237, _asm_isr237, 0)
- ISR_INSTALL(_idt, 238, _asm_isr238, 0)
- ISR_INSTALL(_idt, 239, _asm_isr239, 0)
- ISR_INSTALL(_idt, 240, _asm_isr240, 0)
- ISR_INSTALL(_idt, 241, _asm_isr241, 0)
- ISR_INSTALL(_idt, 242, _asm_isr242, 0)
- ISR_INSTALL(_idt, 243, _asm_isr243, 0)
- ISR_INSTALL(_idt, 244, _asm_isr244, 0)
- ISR_INSTALL(_idt, 245, _asm_isr245, 0)
- ISR_INSTALL(_idt, 246, _asm_isr246, 0)
- ISR_INSTALL(_idt, 247, _asm_isr247, 0)
- ISR_INSTALL(_idt, 248, _asm_isr248, 0)
- ISR_INSTALL(_idt, 249, _asm_isr249, 0)
- ISR_INSTALL(_idt, 250, _asm_isr250, 0)
- ISR_INSTALL(_idt, 251, _asm_isr251, 0)
- ISR_INSTALL(_idt, 252, _asm_isr252, 0)
- ISR_INSTALL(_idt, 253, _asm_isr253, 0)
- ISR_INSTALL(_idt, 254, _asm_isr254, 0)
- ISR_INSTALL(_idt, 255, _asm_isr255, 0)
-}
\ No newline at end of file
+++ /dev/null
-#ifndef __LUNAIX_I386ABI_H
-#define __LUNAIX_I386ABI_H
-
-#include "sys/x86_isa.h"
-
-#define stack_alignment 0xfffffff0
-
-#ifndef __ASM__
-#define align_stack(ptr) ((ptr) & stack_alignment)
-#define store_retval(retval) current_thread->hstate->registers.eax = (retval)
-
-#define store_retval_to(th, retval) (th)->hstate->registers.eax = (retval)
-
-static inline void must_inline
-j_usr(ptr_t sp, ptr_t pc)
-{
- asm volatile("movw %0, %%ax\n"
- "movw %%ax, %%es\n"
- "movw %%ax, %%ds\n"
- "movw %%ax, %%fs\n"
- "movw %%ax, %%gs\n"
- "pushl %0\n"
- "pushl %1\n"
- "pushl %2\n"
- "pushl %3\n"
- "retf" ::"i"(UDATA_SEG),
- "r"(sp),
- "i"(UCODE_SEG),
- "r"(pc)
- : "eax", "memory");
-}
-
-
-static inline void must_inline noret
-switch_context() {
- asm volatile("jmp do_switch\n");
- unreachable;
-}
-
-#define push_arg1(stack_ptr, arg) *((typeof((arg))*)(stack_ptr)--) = arg
-#define push_arg2(stack_ptr, arg1, arg2) \
- { \
- *((typeof((arg1))*)(stack_ptr)--) = arg1; \
- *((typeof((arg2))*)(stack_ptr)--) = arg2; \
- }
-#define push_arg3(stack_ptr, arg1, arg2, arg3) \
- { \
- *((typeof((arg1))*)(stack_ptr)--) = arg1; \
- *((typeof((arg2))*)(stack_ptr)--) = arg2; \
- *((typeof((arg3))*)(stack_ptr)--) = arg3; \
- }
-#define push_arg4(stack_ptr, arg1, arg2, arg3, arg4) \
- { \
- *((typeof((arg1))*)(stack_ptr)--) = arg1; \
- *((typeof((arg2))*)(stack_ptr)--) = arg2; \
- *((typeof((arg3))*)(stack_ptr)--) = arg3; \
- *((typeof((arg4))*)(stack_ptr)--) = arg4; \
- }
-
-
-static inline ptr_t must_inline
-abi_get_callframe()
-{
- ptr_t val;
- asm("movl %%ebp, %0" : "=r"(val)::);
- return val;
-}
-
-static inline ptr_t
-abi_get_retaddr()
-{
- return *((ptr_t*)abi_get_callframe() + 1);
-}
-
-static inline ptr_t
-abi_get_retaddrat(ptr_t fp)
-{
- return *((ptr_t*)fp + 1);
-}
-#endif
-#endif /* __LUNAIX_ABI_H */
+++ /dev/null
-#ifndef __LUNAIX_BSTAGE_H
-#define __LUNAIX_BSTAGE_H
-
-#define boot_text __attribute__((section(".boot.text")))
-#define boot_data __attribute__((section(".boot.data")))
-#define boot_bss __attribute__((section(".boot.bss")))
-
-#endif /* __LUNAIX_BSTAGE_H */
+++ /dev/null
-#ifndef __LUNAIX_I386_INTR_H
-#define __LUNAIX_I386_INTR_H
-
-void
-exception_install_handler();
-
-void
-intr_routine_init();
-
-#endif /* __LUNAIX_I386_INTR_H */
+++ /dev/null
-#ifndef __LUNAIX_MEMPART_H
-#define __LUNAIX_MEMPART_H
-
-#define MEM_PAGE 0x1000UL
-#define MEM_1M 0x100000UL
-#define MEM_4M 0x400000UL
-#define MEM_HUGE 0x400000UL
-#define MEM_1G 0x40000000UL
-
-#define END_POINT(name) (name + name##_SIZE - 1)
-
-#define KSTACK_AREA 0x100000UL
-#define KSTACK_AREA_SIZE 0x300000UL
-#define KSTACK_AREA_END END_POINT(KSTACK_AREA)
-
-#define USR_EXEC 0x400000UL
-#define USR_EXEC_SIZE 0x20000000UL
-#define USR_EXEC_END END_POINT(USR_EXEC)
-
-#define USR_MMAP 0x20400000UL
-#define USR_MMAP_SIZE 0x9fbc0000UL
-#define USR_MMAP_END END_POINT(USR_MMAP)
-
-#define USR_STACK 0xbffc0000UL
-#define USR_STACK_SIZE 0x40000UL
-#define USR_STACK_END END_POINT(USR_STACK)
-
-#define KERNEL_IMG 0xc0000000UL
-#define KERNEL_IMG_SIZE 0x4000000UL
-#define KERNEL_IMG_END END_POINT(KERNEL_IMG)
-
-#define PG_MOUNT_1 0xc4000000UL
-#define PG_MOUNT_1_SIZE 0x1000UL
-#define PG_MOUNT_1_END END_POINT(PG_MOUNT_1)
-
-#define PG_MOUNT_2 0xc4001000UL
-#define PG_MOUNT_2_SIZE 0x1000UL
-#define PG_MOUNT_2_END END_POINT(PG_MOUNT_2)
-
-#define PG_MOUNT_3 0xc4002000UL
-#define PG_MOUNT_3_SIZE 0x1000UL
-#define PG_MOUNT_3_END END_POINT(PG_MOUNT_3)
-
-#define PG_MOUNT_4 0xc4003000UL
-#define PG_MOUNT_4_SIZE 0x1000UL
-#define PG_MOUNT_4_END END_POINT(PG_MOUNT_4)
-
-#define PG_MOUNT_VAR 0xc4004000UL
-#define PG_MOUNT_VAR_SIZE 0x3fc000UL
-#define PG_MOUNT_VAR_END END_POINT(PG_MOUNT_VAR)
-
-#define VMAP 0xc4400000UL
-#define VMAP_SIZE 0x3b400000UL
-#define VMAP_END END_POINT(VMAP)
-
-#define VMS_MOUNT_1 0xff800000UL
-#define VMS_MOUNT_1_SIZE 0x400000UL
-#define VMS_MOUNT_1_END END_POINT(VMS_MOUNT_1)
-
-#endif
\ No newline at end of file
+++ /dev/null
-#ifndef __LUNAIX_I386_ASM_H
-#define __LUNAIX_I386_ASM_H
-
-#define KCODE_SEG 0x08
-#define KDATA_SEG 0x10
-#define UCODE_SEG 0x1B
-#define UDATA_SEG 0x23
-#define TSS_SEG 0x28
-
-#define tss_esp0_off 4
-
-#ifndef __ASM__
-#include <lunaix/types.h>
-
-#define IRQ_TRIG_EDGE 0b0
-#define IRQ_TRIG_LEVEL 0b1
-
-#define IRQ_TYPE_FIXED (0b01 << 1)
-#define IRQ_TYPE_NMI (0b11 << 1)
-#define IRQ_TYPE (0b11 << 1)
-
-#define IRQ_VE_HI (0b1 << 3)
-#define IRQ_VE_LO (0b0 << 3)
-
-#define IRQ_DEFAULT (IRQ_TRIG_EDGE | IRQ_TYPE_FIXED | IRQ_VE_HI)
-
-
-struct x86_tss
-{
- u32_t link;
- u32_t esp0;
- u16_t ss0;
- u8_t __padding[94];
-} __attribute__((packed));
-
-void tss_update_esp(u32_t esp0);
-
-struct x86_intc
-{
- char* name;
- void* data;
-
- void (*irq_attach)(struct x86_intc*,
- int irq,
- int iv,
- cpu_t dest,
- u32_t flags);
- void (*notify_eoi)(struct x86_intc*, cpu_t id, int iv);
-};
-
-
-#endif
-
-#endif /* __LUNAIX_I386_ASM_H */
+++ /dev/null
-#include <klibc/string.h>
-
-void*
-memcpy(void* dest, const void* src, unsigned long num)
-{
- if (!num)
- return dest;
-
- asm volatile("movl %1, %%edi\n"
- "rep movsb\n" ::"S"(src),
- "r"(dest),
- "c"(num)
- : "edi", "memory");
- return dest;
-}
-
-void*
-memset(void* ptr, int value, unsigned long num)
-{
- asm volatile("movl %1, %%edi\n"
- "rep stosb\n" ::"c"(num),
- "r"(ptr),
- "a"(value)
- : "edi", "memory");
- return ptr;
-}
\ No newline at end of file
+++ /dev/null
-#include <lunaix/trace.h>
-
-void
-trace_print_transistion_short(struct hart_state* hstate)
-{
- trace_log(" trigger: iv=%d, ecause=%p",
- hart_vector_stamp(hstate),
- hart_ecause(hstate));
-}
-
-void
-trace_print_transition_full(struct hart_state* hstate)
-{
- trace_log("hart state transition");
- trace_log(" vector=%d, ecause=0x%x",
- hart_vector_stamp(hstate),
- hart_ecause(hstate));
- trace_log(" eflags=0x%x", hstate->execp->eflags);
- trace_log(" sp=%p, [seg_sel=0x%04x]",
- hstate->execp->esp,
- hstate->execp->esp);
- trace_log(" ip=%p, seg_sel=0x%04x",
- hstate->execp->eip,
- hstate->execp->cs);
-}
-
-void
-trace_dump_state(struct hart_state* hstate)
-{
- struct regcontext* rh = &hstate->registers;
- struct exec_param* ep = hstate->execp;
- trace_log("hart state dump (depth=%d)", hstate->depth);
- trace_log(" eax=0x%08x, ebx=0x%08x, ecx=0x%08x",
- rh->eax, rh->ebx, rh->ecx);
- trace_log(" edx=0x%08x, ebp=0x%08x",
- rh->edx, rh->ebp);
- trace_log(" ds=0x%04x, edi=0x%08x",
- rh->ds, rh->edi);
- trace_log(" es=0x%04x, esi=0x%08x",
- rh->es, rh->esi);
- trace_log(" fs=0x%04x, gs=0x%x",
- rh->fs, rh->gs);
- trace_log(" cs=0x%04x, ip=0x%08x",
- ep->cs, ep->eip);
- trace_log(" [ss=0x%04x],sp=0x%08x",
- ep->ss, ep->eip);
- trace_log(" eflags=0x%08x",
- ep->eflags);
-}
\ No newline at end of file
--- /dev/null
+use("hal")
+
+sources([
+ "exceptions/interrupts.c",
+ "exceptions/isrdef.c",
+ "exceptions/intr_routines.c",
+ "exceptions/isrm.c",
+ "exceptions/intrhnds.S",
+])
+
+sources([
+ "boot/mb_parser.c",
+ "boot/kpt_setup.c",
+ "boot/boot_helper.c"
+])
+
+sources([
+ "mm/fault.c",
+ "mm/tlb.c",
+ "mm/pmm.c",
+ "mm/gdt.c",
+ "mm/vmutils.c"
+])
+
+sources([
+ "klib/fast_crc.c",
+ "klib/fast_str.c",
+ "exec/exec.c",
+ "hart.c",
+ "arch.c",
+ "gdbstub.c",
+ "trace.c",
+ "hart.c",
+ "failsafe.S"
+])
+
+sources({
+ config("arch"): {
+ "x86_64": [
+ "hart64.c",
+ "syscall64.S",
+ "exceptions/interrupt64.S",
+ "boot/x86_64/boot64.S",
+ "boot/x86_64/init64.c",
+ "boot/x86_64/prologue64.S",
+ "boot/x86_64/kremap64.c",
+ "exec/elf64.c"
+ ],
+ "i386": [
+ "hart32.c",
+ "syscall32.S",
+ "exceptions/interrupt32.S",
+ "boot/i386/boot32.S",
+ "boot/i386/init32.c",
+ "boot/i386/prologue32.S",
+ "boot/i386/kremap32.c",
+ "exec/elf32.c"
+ ]
+ }
+})
+
+headers([
+ "includes"
+])
+
+
+if config("arch") == "x86_64":
+ compile_opts([
+ "-m64",
+ "-fno-unwind-tables",
+ "-fno-asynchronous-unwind-tables",
+ "-mcmodel=large"
+ ])
+ linking_opts([
+ "-m64",
+ ])
+else:
+ compile_opts("-m32")
+ linking_opts("-m32")
+
+if not config("x86_enable_sse_feature"):
+ compile_opts("-mno-sse")
\ No newline at end of file
--- /dev/null
+
+@Group
+def x86_configurations():
+
+ add_to_collection(architecture_support)
+
+ @Term
+ def x86_enable_sse_feature():
+ """
+ Config whether to allow using SSE feature for certain
+ optimization
+ """
+
+ type(bool)
+ default(False)
+
+
+ @Term
+ def x86_bl():
+ """
+ Select the bootloader interface
+
+ Supported interface
+ mb: multiboot compliant
+ mb2: multiboot2 compliant
+ none: do not use any interface
+ """
+
+ type(["mb"])
+ # type(["mb", "mb2", "none"])
+ default("mb")
+
+
+ return v(arch) in ["i386", "x86_64"]
\ No newline at end of file
#include <lunaix/generic/isrm.h>
#include <lunaix/spike.h>
+#include <lunaix/process.h>
-#include "sys/i386_intr.h"
+#include "sys/int_handler.h"
+#include "sys/x86_isa.h"
#include "sys/hart.h"
#include "hal/apic_timer.h"
// TODO select alternatives...
panick("no timer to use.");
+}
+
+void
+update_tss()
+{
+ extern struct x86_tss _tss;
+#ifdef CONFIG_ARCH_X86_64
+ _tss.rsps[0] = (ptr_t)current_thread->hstate;
+#else
+ _tss.esp0 = (u32_t)current_thread->hstate;
+#endif
}
\ No newline at end of file
--- /dev/null
+#include <lunaix/boot_generic.h>
+#include <lunaix/mm/pagetable.h>
+
+#include "sys/mm/mm_defs.h"
+
+#ifdef CONFIG_ARCH_X86_64
+
+void
+boot_begin_arch_reserve(struct boot_handoff* bhctx)
+{
+ return;
+}
+
+
+void
+boot_clean_arch_reserve(struct boot_handoff* bhctx)
+{
+ return;
+}
+
+#else
+
+#include <lunaix/mm/vmm.h>
+
+void
+boot_begin_arch_reserve(struct boot_handoff* bhctx)
+{
+ // Identity-map the first 3GiB address spaces
+ pte_t* ptep = mkl0tep(mkptep_va(VMS_SELF, 0));
+ pte_t pte = mkpte_prot(KERNEL_DATA);
+ size_t count = page_count(KERNEL_RESIDENT, L0T_SIZE);
+
+ vmm_set_ptes_contig(ptep, pte_mkhuge(pte), L0T_SIZE, count);
+}
+
+
+void
+boot_clean_arch_reserve(struct boot_handoff* bhctx)
+{
+ pte_t* ptep = mkl0tep(mkptep_va(VMS_SELF, 0));
+ size_t count = page_count(KERNEL_RESIDENT, L0T_SIZE);
+ vmm_unset_ptes(ptep, count);
+}
+
+
+#endif
\ No newline at end of file
-#define __ASM__ 1
-#include <sys/boot/multiboot.h>
+#define __ASM__
-#define MB_FLAGS (MULTIBOOT_MEMORY_INFO | MULTIBOOT_PAGE_ALIGN)
-#define KPG_SIZE 10*4096
-
-.section .multiboot
- .long MULTIBOOT_MAGIC
- .long MB_FLAGS
- .long CHECKSUM(MB_FLAGS)
+#if defined(CONFIG_X86_BL_MB) || defined(CONFIG_X86_BL_MB2)
+#include "sys/boot/multiboot.S.inc"
+#endif
.section .boot.bss
/* 根据System V ABI,栈地址必须16字节对齐 */
-#include "archinit.h"
-#include <sys/crx.h>
-#include <sys/cpu.h>
+#include "sys/boot/archinit.h"
+#include "sys/crx.h"
+#include "sys/cpu.h"
void boot_text
x86_init(struct multiboot_info* mb)
#include <sys/boot/bstage.h>
#include <sys/mm/mm_defs.h>
-// Provided by linker (see linker.ld)
-extern u8_t __kexec_start[];
-extern u8_t __kexec_end[];
-extern u8_t __kexec_text_start[];
-extern u8_t __kexec_text_end[];
-extern u8_t __kboot_start[];
-extern u8_t __kboot_end[];
+bridge_farsym(__kexec_start);
+bridge_farsym(__kexec_end);
+bridge_farsym(__kexec_text_start);
+bridge_farsym(__kexec_text_end);
// define the initial page table layout
+struct kernel_map;
+
+static struct kernel_map kernel_pt __section(".kpg");
+export_symbol(debug, boot, kernel_pt);
+
struct kernel_map {
pte_t l0t[_PAGE_LEVEL_SIZE];
pte_t pg_mnt[_PAGE_LEVEL_SIZE];
} kernel_lfts[16];
} align(4);
-static struct kernel_map kernel_pt __section(".kpg");
-export_symbol(debug, boot, kernel_pt);
-
-
-void boot_text
-_init_page()
+static void boot_text
+do_remap()
{
struct kernel_map* kpt_pa = (struct kernel_map*)to_kphysical(&kernel_pt);
-
- pte_t* kl0tep = (pte_t*) &kpt_pa->l0t[pfn_at(KERNEL_RESIDENT, L0T_SIZE)];
- pte_t* kl1tep = (pte_t*) kpt_pa->kernel_lfts;
+
+ size_t mia_casa_i = pfn_at(KERNEL_RESIDENT, L0T_SIZE);
+ pte_t* klptep = (pte_t*) &kpt_pa->l0t[mia_casa_i];
+ pte_t* ktep = (pte_t*) kpt_pa->kernel_lfts;
pte_t* boot_l0tep = (pte_t*) kpt_pa;
set_pte(boot_l0tep, pte_mkhuge(mkpte_prot(KERNEL_DATA)));
// --- 将内核重映射至高半区 ---
// Hook the kernel reserved LFTs onto L0T
- pte_t pte = mkpte((ptr_t)kl1tep, KERNEL_DATA);
+ pte_t pte = mkpte((ptr_t)ktep, KERNEL_DATA);
for (u32_t i = 0; i < KEXEC_RSVD; i++) {
pte = pte_setpaddr(pte, (ptr_t)&kpt_pa->kernel_lfts[i]);
- set_pte(kl0tep, pte);
+ set_pte(klptep, pte);
- kl0tep++;
+ klptep++;
}
// Ensure the size of kernel is within the reservation
pfn_t kimg_pagecount =
- pfn((ptr_t)__kexec_end - (ptr_t)__kexec_start);
+ pfn(__far(__kexec_end) - __far(__kexec_start));
if (kimg_pagecount > KEXEC_RSVD * _PAGE_LEVEL_SIZE) {
// ERROR: require more pages
// here should do something else other than head into blocking
// Now, map the kernel
- pfn_t kimg_end = pfn(to_kphysical(__kexec_end));
- pfn_t i = pfn(to_kphysical(__kexec_text_start));
- kl1tep += i;
+ pfn_t kimg_end = pfn(to_kphysical(__far(__kexec_end)));
+ pfn_t i = pfn(to_kphysical(__far(__kexec_text_start)));
+ ktep += i;
// kernel .text
pte = pte_setprot(pte, KERNEL_EXEC);
- pfn_t ktext_end = pfn(to_kphysical(__kexec_text_end));
+ pfn_t ktext_end = pfn(to_kphysical(__far(__kexec_text_end)));
for (; i < ktext_end; i++) {
pte = pte_setpaddr(pte, page_addr(i));
- set_pte(kl1tep, pte);
+ set_pte(ktep, pte);
- kl1tep++;
+ ktep++;
}
// all remaining kernel sections
pte = pte_setprot(pte, KERNEL_DATA);
for (; i < kimg_end; i++) {
pte = pte_setpaddr(pte, page_addr(i));
- set_pte(kl1tep, pte);
+ set_pte(ktep, pte);
- kl1tep++;
+ ktep++;
}
// XXX: Mapping the kernel .rodata section?
set_pte(kmntep, mkpte((ptr_t)kpt_pa->pg_mnt, KERNEL_DATA));
// Build up self-reference
+ int level = (VMS_SELF / L0T_SIZE) & _PAGE_LEVEL_MASK;
+
pte = mkpte_root((ptr_t)kpt_pa, KERNEL_DATA);
- set_pte(boot_l0tep + _PAGE_LEVEL_MASK, pte);
+ set_pte(&boot_l0tep[level], pte);
}
ptr_t boot_text
-kpg_init()
+remap_kernel()
{
ptr_t kmap_pa = to_kphysical(&kernel_pt);
for (size_t i = 0; i < sizeof(kernel_pt); i++) {
((u8_t*)kmap_pa)[i] = 0;
}
- _init_page();
+ do_remap();
return kmap_pa;
}
\ No newline at end of file
__kinit_stack_end:
.skip 2048, 0
__kinit_stack_top:
- # TODO
- # This stack was too small that corrupt the ambient kernel structures.
- # (took me days to figure this out!)
- # We should spent more time to implement a good strategy to detect such
- # run-over (we can check these invariants when we trapped in some non-recoverable
- # state and provide good feedback to user)
+
.section .text
.global hhk_entry_
movw %cx, %ss
/* 更新 CS:EIP */
- pushw $KCODE_SEG
+ pushl $KCODE_SEG
pushl $_after_gdt
retf
--- /dev/null
+#define __BOOT_CODE__
+
+#include <lunaix/mm/pagetable.h>
+#include <lunaix/compiler.h>
+
+#include <sys/boot/bstage.h>
+#include <sys/mm/mm_defs.h>
+
+
+ptr_t boot_text
+kpg_init()
+{
+ return remap_kernel();
+}
\ No newline at end of file
#include <sys/mm/mempart.h>
#define BHCTX_ALLOC 4096
+#define MEM_1M 0x100000UL
+
u8_t bhctx_buffer[BHCTX_ALLOC] boot_bss;
void* buffer)
{
struct multiboot_mmap_entry* mb_mmap =
- (struct multiboot_mmap_entry*)mb->mmap_addr;
+ (struct multiboot_mmap_entry*)__ptr(mb->mmap_addr);
size_t mmap_len = mb->mmap_length / sizeof(struct multiboot_mmap_entry);
struct boot_mmapent* bmmap = (struct boot_mmapent*)buffer;
}
struct boot_modent* modents = (struct boot_modent*)buffer;
- struct multiboot_mod_list* mods = (struct multiboot_mod_list*)mb->mods_addr;
+ struct multiboot_mod_list* mods =
+ (struct multiboot_mod_list*)__ptr(mb->mods_addr);
- ptr_t mod_str_ptr = (ptr_t)&modents[mb->mods_count];
+ ptr_t mod_str_ptr = __ptr(&modents[mb->mods_count]);
for (size_t i = 0; i < mb->mods_count; i++) {
struct multiboot_mod_list* mod = &mods[i];
modents[i] = (struct boot_modent){ .start = mod->mod_start,
.end = mod->mod_end,
.str = (char*)mod_str_ptr };
- mod_str_ptr += mb_strcpy((char*)mod_str_ptr, (char*)mod->cmdline);
+
+ mod_str_ptr += mb_strcpy((char*)mod_str_ptr,
+ (char*)__ptr(mod->cmdline));
}
bhctx->mods.mods_num = mb->mods_count;
/* Parse cmdline */
if ((mb->flags & MULTIBOOT_INFO_CMDLINE)) {
bhctx_ex +=
- mb_parse_cmdline(bhctx, (void*)bhctx_ex, (char*)mb->cmdline);
+ mb_parse_cmdline(bhctx, (void*)bhctx_ex, (char*)__ptr(mb->cmdline));
bhctx_ex = align_addr(bhctx_ex);
}
--- /dev/null
+#define __ASM__
+
+#if defined(CONFIG_X86_BL_MB) || defined(CONFIG_X86_BL_MB2)
+#include "sys/boot/multiboot.S.inc"
+#endif
+
+#include "sys/mm/mempart64.h"
+
+.section .boot.bss
+ .align 8
+ __tmp_gdt:
+ .long 0x0
+ .long 0x0
+ .long 0x0000ffff
+ .long 0x00ef9a00
+ .long 0x0000ffff
+ .long 0x00cf9200
+
+.section .boot.bss
+
+ .align 16
+ .skip 512, 0
+ __boot_stack_top:
+
+.section .boot.bss
+
+ .align 4096
+ _tmp_l0:
+ .skip 4096
+ _tmp_l1:
+ .skip 4096
+
+.section .boot.text
+ .global start_
+ .type start_, @function
+
+ start_:
+ .code32
+ cld
+ cli
+
+ movl $__boot_stack_top, %esp
+ pushl $0
+ pushl %ebx
+
+ # first, setup a simple initial page table
+ # to enable transition to IA32e
+
+ # L0 linkage to L1, RWX
+ movl $0x3, %eax
+ movl $_tmp_l1, %ebx
+ orl %eax, %ebx
+ movl %ebx, _tmp_l0
+ xorl %ebx, %ebx
+ movl %ebx, _tmp_l0 + 4
+
+ # Entry 0
+ orl $(1 << 7), %eax
+ movl %eax, _tmp_l1
+ movl %ebx, _tmp_l1 + 4
+
+ # Entry 1
+ addl $0x40000000, %eax
+ movl %eax, _tmp_l1 + 8
+ movl %ebx, _tmp_l1 + 12
+
+ # Entry 2
+ addl $0x40000000, %eax
+ movl %eax, _tmp_l1 + 16
+ movl %ebx, _tmp_l1 + 20
+
+ # Entry 3
+ addl $0x40000000, %eax
+ movl %eax, _tmp_l1 + 24
+ movl %ebx, _tmp_l1 + 28
+
+ movl $_tmp_l0, %eax
+ movl %eax, %cr3
+
+ # now, commencing transition
+
+ movl %cr4, %eax
+ orl $(1 << 5), %eax # PAE
+ movl %eax, %cr4
+
+ movl $0xc0000080, %ecx
+ rdmsr
+ orl $(1 << 8), %eax # IA32_EFER.LME
+ orl $(1 << 11), %eax # IA32_EFER.NXE
+ wrmsr
+
+ movl %cr0, %eax
+ orl $(1 << 31), %eax # PG
+ movl %eax, %cr0
+
+ jmp _ia32e_compat
+
+ # clear the pipeline,
+ # although cpu might already cleared for us upon mode switching
+ .nop
+ .nop
+ .nop
+ .nop
+
+ # x86_64 compatibility mode
+ # load a temporary gdt for getting into long mode
+ _ia32e_compat:
+ .code32
+ subl $16, %esp
+ movl $__tmp_gdt, 2(%esp)
+ movw $23, (%esp)
+ lgdtl (%esp)
+
+ addl $16, %esp
+
+ # do a far jump to switch cs
+ pushl $0x08
+ pushl $_ia32e
+ retf
+
+ _ia32e:
+ .code64
+ movw $0x10, %cx
+ movw %cx, %ds
+ movw %cx, %ss
+
+ popq %rbx
+ movq %rbx, %rdi
+ call x86_init
+
+ movabsq $hhk_entry_, %rax
+ pushq %rax
+ retq
\ No newline at end of file
--- /dev/null
+#include "sys/boot/archinit.h"
+#include "sys/crx.h"
+#include "sys/cpu.h"
+
+void boot_text
+x86_init(struct multiboot_info* mb)
+{
+ mb_parse(mb);
+
+ cr4_setfeature(CR4_PCIDE);
+
+ ptr_t pagetable = kpg_init();
+ cpu_chvmspace(pagetable);
+
+ cr0_unsetfeature(CR0_WP | CR0_EM);
+ cr0_setfeature(CR0_MP);
+}
\ No newline at end of file
--- /dev/null
+#define __BOOT_CODE__
+
+#include <lunaix/mm/pagetable.h>
+#include <lunaix/compiler.h>
+
+#include <sys/boot/bstage.h>
+#include <sys/mm/mm_defs.h>
+
+#define RSVD_PAGES 32
+
+bridge_farsym(__kexec_start);
+bridge_farsym(__kexec_end);
+bridge_farsym(__kexec_text_start);
+bridge_farsym(__kexec_text_end);
+
+// define the initial page table layout
+struct kernel_map;
+
+static struct kernel_map kpt __section(".kpg");
+export_symbol(debug, boot, kpt);
+
+struct kernel_map {
+ pte_t l0t[_PAGE_LEVEL_SIZE]; // root table
+ pte_t l1t_rsvd[_PAGE_LEVEL_SIZE]; // 0~4G reservation
+
+ struct {
+ pte_t _lft[_PAGE_LEVEL_SIZE];
+ } krsvd[RSVD_PAGES];
+} align(8);
+
+struct allocator
+{
+ struct kernel_map* kpt_pa;
+ int pt_usage;
+};
+
+static inline ptr_t
+alloc_rsvd_page(struct allocator* _alloc)
+{
+ if (_alloc->pt_usage >= KEXEC_RSVD) {
+ asm ("ud2");
+ }
+
+ return __ptr(&_alloc->kpt_pa->krsvd[_alloc->pt_usage++]);
+}
+
+static pte_t* boot_text
+prealloc_pt(struct allocator* _allc, ptr_t va,
+ pte_attr_t prot, size_t to_gran)
+{
+ int lvl_i;
+ pte_t *ptep, pte;
+ size_t gran = L0T_SIZE;
+
+ ptep = (pte_t*)&_allc->kpt_pa->l0t[0];
+
+ for (int i = 0; i < _PTW_LEVEL && gran > to_gran; i++)
+ {
+ lvl_i = va_level_index(va, gran);
+ ptep = &ptep[lvl_i];
+ pte = pte_at(ptep);
+
+ gran = gran >> _PAGE_LEVEL_SHIFT;
+
+ if (pte_isnull(pte)) {
+ pte = mkpte(alloc_rsvd_page(_allc), KERNEL_DATA);
+ if (to_gran == gran) {
+ pte = pte_setprot(pte, prot);
+ }
+
+ set_pte(ptep, pte);
+ }
+ ptep = (pte_t*) pte_paddr(pte);
+ }
+
+ return ptep;
+}
+
+static void boot_text
+do_remap()
+{
+ struct kernel_map* kpt_pa = (struct kernel_map*)to_kphysical(&kpt);
+
+ pte_t* boot_l0tep = (pte_t*) kpt_pa;
+ pte_t *klptep, pte;
+
+ // identity map the first 4G for legacy compatibility
+ pte_t* l1_rsvd = (pte_t*) kpt_pa->l1t_rsvd;
+ pte_t id_map = pte_mkhuge(mkpte_prot(KERNEL_DATA));
+
+ set_pte(boot_l0tep, mkpte((ptr_t)l1_rsvd, KERNEL_DATA));
+
+ for (int i = 0; i < 4; i++, l1_rsvd++)
+ {
+ id_map = pte_setpaddr(id_map, (ptr_t)i << 30);
+ set_pte(l1_rsvd, id_map);
+ }
+
+ // Remap the kernel to -2GiB
+
+ int table_usage = 0;
+ unsigned int lvl_i = 0;
+ struct allocator alloc = {
+ .kpt_pa = kpt_pa,
+ .pt_usage = 0
+ };
+
+ prealloc_pt(&alloc, VMAP, KERNEL_DATA, L1T_SIZE);
+
+ prealloc_pt(&alloc, PG_MOUNT_1, KERNEL_DATA, LFT_SIZE);
+
+
+ ptr_t kstart = page_aligned(__far(__kexec_text_start));
+
+#if LnT_ENABLED(3)
+ size_t gran = L3T_SIZE;
+#else
+ size_t gran = L2T_SIZE;
+#endif
+
+ prealloc_pt(&alloc, PMAP, KERNEL_DATA, gran);
+ klptep = prealloc_pt(&alloc, kstart, KERNEL_DATA, gran);
+ klptep += va_level_index(kstart, gran);
+
+ pte = mkpte(0, KERNEL_DATA);
+ for (int i = alloc.pt_usage; i < KEXEC_RSVD; i++)
+ {
+ pte = pte_setpaddr(pte, (ptr_t)&kpt_pa->krsvd[i]);
+ set_pte(klptep++, pte);
+ }
+
+ // this is the first LFT we hooked on.
+ // all these LFT are contig in physical address
+ klptep = (pte_t*) &kpt_pa->krsvd[alloc.pt_usage];
+
+ // Ensure the size of kernel is within the reservation
+ int remain = KEXEC_RSVD - table_usage;
+ pfn_t kimg_pagecount =
+ pfn(__far(__kexec_end) - __far(__kexec_start));
+ if (kimg_pagecount > remain * _PAGE_LEVEL_SIZE) {
+ // ERROR: require more pages
+ // here should do something else other than head into blocking
+ asm("ud2");
+ }
+
+ // kernel .text
+ pfn_t ktext_end = pfn(to_kphysical(__far(__kexec_text_end)));
+ pfn_t i = pfn(to_kphysical(kstart));
+
+ klptep += i;
+ pte = pte_setprot(pte, KERNEL_EXEC);
+ for (; i < ktext_end; i++) {
+ pte = pte_setpaddr(pte, page_addr(i));
+ set_pte(klptep, pte);
+
+ klptep++;
+ }
+
+ pfn_t kimg_end = pfn(to_kphysical(__far(__kexec_end)));
+
+ // all remaining kernel sections
+ pte = pte_setprot(pte, KERNEL_DATA);
+ for (; i < kimg_end; i++) {
+ pte = pte_setpaddr(pte, page_addr(i));
+ set_pte(klptep, pte);
+
+ klptep++;
+ }
+
+ // Build up self-reference
+ lvl_i = va_level_index(VMS_SELF, L0T_SIZE);
+ pte = mkpte_root(__ptr(kpt_pa), KERNEL_DATA);
+ set_pte(boot_l0tep + lvl_i, pte);
+}
+
+
+ptr_t boot_text
+remap_kernel()
+{
+ ptr_t kmap_pa = to_kphysical(&kpt);
+ for (size_t i = 0; i < sizeof(kpt); i++) {
+ ((u8_t*)kmap_pa)[i] = 0;
+ }
+
+ do_remap();
+
+ return kmap_pa;
+}
\ No newline at end of file
--- /dev/null
+/* 高半核入口点 - 0xC0000000 */
+
+#define __ASM__
+#include <sys/abi.h>
+#include <sys/failsafe.h>
+
+.section .bss.kstack
+ .global __kinit_stack_end
+
+ .align 16
+ __kinit_stack_end:
+ .skip 2048, 0
+ __kinit_stack_top:
+
+
+.section .text
+ .global hhk_entry_
+ hhk_entry_:
+
+ movq $__kinit_stack_top, %rsp
+ andq $stack_alignment, %rsp
+
+ movq $__kinit_stack_end, %rax
+ movl $STACK_SANITY, (%rax)
+ movl $STACK_SANITY, 4(%rax)
+ movl $STACK_SANITY, 8(%rax)
+ movl $STACK_SANITY, 12(%rax)
+
+ andq $stack_alignment, %rsp
+ subq $16, %rsp
+
+ # replace the temporary gdt
+ call _init_gdt
+
+ movq $_gdt, 2(%rsp)
+ movw _gdt_limit, %ax
+ movw %ax, (%rsp)
+ lgdt (%rsp)
+
+ # do a far jump to switch cs
+ pushq $KCODE_SEG
+ pushq $_after_gdt
+ retfq
+
+ _after_gdt:
+
+ # initialize segment registers
+ # we will not touch them again in x86_64
+ movw $KDATA_SEG, %cx
+ movw %cx, %es
+ movw %cx, %ds
+ movw %cx, %ss
+
+ # perform arch-specific initialization before diving into kernel
+ call arch_preinit
+
+ # 加载 IDT
+ movq $_idt, 2(%rsp)
+ movw _idt_limit, %ax
+ movw %ax, (%rsp)
+ lidt (%rsp)
+
+ /* 加载TSS段选择器 */
+ movw $TSS_SEG, %ax
+ ltr %ax
+
+ xorq %rbp, %rbp
+ movq $bhctx_buffer, %rdi # mb_parser.c
+ call kernel_bootstrap
+
+ 1:
+ hlt
+ jmp 1b
\ No newline at end of file
#define __ASM__
#include <sys/hart.h>
#include <sys/abi.h>
-#include <sys/interrupt.S.inc>
+#include <sys/interrupt32.S.inc>
#include <lunaix/syscall.h>
+#define tss_esp0_off 4
#define __ASM_INTR_DIAGNOSIS
#ifdef __ASM_INTR_DIAGNOSIS
interrupt_wrapper:
cld
- subl $4, %esp
+ subl $4, %esp # prealloc slot for parent linkage
pushl %esp
subl $16, %esp
由于这中间没有进行地址空间的交换,所以第二次跳转使用的是同一个内核栈,而之前默认tss.esp0的值是永远指向最顶部
这样一来就有可能会覆盖更早的上下文信息(比如嵌套的信号捕获函数)
*/
- movl thread_hstate(%ebx), %ecx # __current->hstate
- movl %ecx, (tss_esp0_off + _tss)
+ pushl %eax
+ call update_tss
+ popl %eax
jmp handle_signal
1:
--- /dev/null
+#define __ASM__
+#include <sys/hart.h>
+#include <sys/abi.h>
+#include <sys/interrupt64.S.inc>
+
+#include <lunaix/syscall.h>
+
+.section .bss
+ .align 16
+ tmp_store:
+ .skip 8
+ lo_tmp_stack:
+ .skip 256
+ tmp_stack:
+
+
+/*
+ This perhaps the ugliest part in the project.
+ It contains code to handle arbitrary depth of
+ nested interrupt and all those corner cases and
+ nasty gotchas.
+
+ Be aware the twists, offsets and hidden dependencies!
+
+*/
+
+.section .text
+ .type interrupt_wrapper, @function
+ .global interrupt_wrapper
+ interrupt_wrapper:
+ cld
+
+ subq $8, %rsp
+ pushq %rsp
+
+ pushq %r15
+ pushq %r14
+ pushq %r13
+ pushq %r12
+ pushq %r11
+ pushq %r10
+ pushq %r9
+ pushq %r8
+
+ pushq %rsi
+ pushq %rbp
+ pushq %rdi
+ pushq %rdx
+ pushq %rcx
+ pushq %rbx
+ pushq %rax
+
+ pushq $0 // placeholder for depth accounting
+
+ movq ics(%rsp), %rax /* 取出 %cs */
+ andq $0x3, %rax /* 判断 RPL */
+ jz 1f
+
+ /* crossing the user/kernel boundary */
+ # x86_64 ignore {d,e}s, Lunaix does not use {f,g}s
+
+ movq current_thread, %rbx
+ movq iursp(%rsp), %rax
+
+ # Save x87 context to user stack, rather than kernel's memory.
+ # XXX what will happen if we triggered a page fault during fxsave?
+ # FIXME I think we should defer this to scheduler, and pratice lazy save/load
+ # Doing this will also make it safe from nested interrupt due to potential
+ # page fault when saving
+ # FIXME Also, generalise it to any FPU context, without constraining it to x87.
+
+ #andl $stack_alignment, %eax
+ #subl $512, %eax
+ #fxsave (%eax)
+
+ # 保存用户栈顶指针。因为我们允许同级中断的产生,所以需要该手段跟踪用户栈的地址。
+ movq %rax, thread_ustack_top(%rbx) # 存入__current->ustack_top
+
+ /* kernel space same-level switch */
+ 1:
+ movq %rsp, %rax
+ andq $stack_alignment, %rsp
+
+ movq %rax, %rdi
+
+ xorq %rbp, %rbp # marks the boundary of stack walking
+ call intr_handler
+
+ .global soft_iret
+ soft_iret:
+ movq %rax, %rsp
+
+ movq ics(%rsp), %rax
+ andq $3, %rax
+ jz 1f
+
+ # # FIXME x87 fpu context
+ # movl current_thread, %eax
+ # movl thread_ustack_top(%eax), %eax
+ # test %eax, %eax
+ # jz 1f
+ # fxrstor (%eax)
+
+1:
+ popq %rax # discard struct hart_state::depth
+
+ popq %rax
+ popq %rbx
+ popq %rcx
+ popq %rdx
+ popq %rdi
+ popq %rbp
+ popq %rsi
+
+ popq %r8
+ popq %r9
+ popq %r10
+ popq %r11
+ popq %r12
+ popq %r13
+ popq %r14
+ popq %r15
+
+ popq %rsp
+
+ movq %rax, tmp_store
+ movq current_thread, %rax
+
+ # nested intr: restore saved context
+ popq thread_hstate(%rax)
+
+ movq tmp_store, %rax
+
+ addq $16, %rsp # skip: err_code and vector
+
+ # calculate stack after iretq
+ # Thank god they finally make things consistent in x86_64
+ addq $40, %rsp
+ movq %rsp, (_tss + rsp_0)
+ subq $40, %rsp
+
+ iretq
+
+ .type do_switch, @function
+ .global do_switch
+ do_switch:
+ # Assumption: __current already hold the target process
+
+ call proc_vmroot
+
+ movq %rax, %rbx
+ movq %cr3, %rax
+ xorq %rbx, %rax # avoid setting cr3 if just local thread switch.
+ jz 1f
+
+ movq %rbx, %cr3
+
+ 1:
+ # the address space could be changed. A temporary stack
+ # is required to prevent corrupt existing stack
+ movq $tmp_stack, %rsp
+
+ call signal_dispatch # kernel/signal.c
+
+ movq current_thread, %rbx
+ test %rax, %rax # do we have signal to handle?
+ jz 1f
+
+ /*
+ 将tss.esp0设置为上次调度前的esp值。
+ 当处理信号时,上下文信息是不会恢复的,而是保存在用户栈中,然后直接跳转进位于用户空间的sig_wrapper进行
+ 信号的处理。当用户自定义的信号处理函数返回时,sigreturn的系统调用才开始进行上下文的恢复(或者说是进行
+ 另一次调度。
+ 由于这中间没有进行地址空间的交换,所以第二次跳转使用的是同一个内核栈,而之前默认tss.esp0的值是永远指向最顶部
+ 这样一来就有可能会覆盖更早的上下文信息(比如嵌套的信号捕获函数)
+ */
+ pushq %rax
+ call update_tss
+
+ popq %rax
+ jmp handle_signal
+
+ 1:
+ movq thread_hstate(%rbx), %rax
+ jmp soft_iret
+
+ .type handle_signal, @function
+ .global handle_signal
+ handle_signal:
+ # 注意1:任何对proc_sig的布局改动,都须及时的保证这里的一致性!
+ # 注意2:handle_signal在调用之前,须确保proc_sig已经写入用户栈!
+ # arg1 in %rax: addr of proc_sig structure in user stack
+ movq psig_saved_hstate(%rax), %rbx # %rbx = &proc_sig->saved_hstate
+
+ pushq $UDATA_SEG
+ pushq %rax # esp
+
+ movq iexecp(%rbx), %rbx
+ pushq exrflags(%rbx) # proc_sig->saved_hstate->execp->eflags
+
+ pushq $UCODE_SEG # cs
+ pushq psig_sigact(%rax) # %rip = proc_sig->sigact
+
+ iretq
\ No newline at end of file
#include <sys/cpu.h>
-#include <sys/i386_intr.h>
+#include <sys/int_handler.h>
#include <sys/hart.h>
#include "sys/x86_isa.h"
}
}
-void
+struct hart_state*
intr_handler(struct hart_state* state)
{
update_thread_context(state);
goto done;
}
- ERROR("INT %u: (%x) [%p: %p] Unknown",
- execp->vector,
- execp->err_code,
- execp->cs,
- execp->eip);
-
done:
if (execp->vector > IV_BASE_END) {
isrm_notify_eoi(0, execp->vector);
}
- return;
+ return state;
}
\ No newline at end of file
#include <klibc/strfmt.h>
#include "sys/apic.h"
-#include <sys/i386_intr.h>
+#include <sys/int_handler.h>
LOG_MODULE("INTR")
void
intr_routine_sys_panic(const struct hart_state* state)
{
+#ifdef CONFIG_ARCH_X86_64
+ __print_panic_msg((char*)(state->registers.rdi), state);
+#else
__print_panic_msg((char*)(state->registers.edi), state);
+#endif
}
void
-/* Generated from i386_intrhnds.S.j2. Do NOT modify */
+/* Generated from int_handlerhnds.S.j2. Do NOT modify */
#define __ASM__
+#ifdef CONFIG_ARCH_I386
.macro isr_template vector, no_error_code=1
.global _asm_isr\vector
.type _asm_isr\vector, @function
+ .align 16
_asm_isr\vector:
.if \no_error_code
pushl $0x0
pushl $\vector
jmp interrupt_wrapper
.endm
+#else
+.macro isr_template vector, no_error_code=1
+ .global _asm_isr\vector
+ .type _asm_isr\vector, @function
+ .align 16
+ _asm_isr\vector:
+ .if \no_error_code
+ pushq $0x0
+ .endif
+ pushq $\vector
+ jmp interrupt_wrapper
+.endm
+#endif
+
.section .text
isr_template 0, no_error_code=1
isr_template 1, no_error_code=1
--- /dev/null
+/* Generated from i386_isrdef.c.j2. Do NOT modify */
+
+#include <lunaix/types.h>
+#include "sys/int_handler.h"
+#include "sys/vectors.h"
+#include "sys/x86_isa.h"
+
+#define IDT_INTERRUPT 0x70
+#define IDT_ATTR(dpl, type) (((type) << 5) | ((dpl & 3) << 13) | (1 << 15))
+#define IDT_ENTRY 256
+
+#define __expand_iv(iv) _asm_isr##iv()
+#define DECLARE_ISR(iv) extern void __expand_iv(iv);
+
+#ifndef CONFIG_ARCH_X86_64
+
+static inline void
+install_idte(struct x86_sysdesc* idt, int iv, ptr_t isr, int dpl)
+{
+ struct x86_sysdesc* idte = &idt[iv];
+
+ idte->hi = ((ptr_t)isr & 0xffff0000) | IDT_ATTR(dpl, IDT_INTERRUPT);
+ idte->lo = (KCODE_SEG << 16) | ((ptr_t)isr & 0x0000ffff);
+}
+struct x86_sysdesc _idt[IDT_ENTRY];
+u16_t _idt_limit = sizeof(_idt) - 1;
+
+#else
+
+static inline must_inline void
+install_idte(struct x86_sysdesc* idt, int iv, ptr_t isr, int dpl)
+{
+ struct x86_sysdesc* idte = &idt[iv];
+
+ idte->hi = isr >> 32;
+
+ idte->lo = (isr & 0xffff0000UL) | IDT_ATTR(dpl, IDT_INTERRUPT);
+
+ idte->lo <<= 32;
+ idte->lo |= (KCODE_SEG << 16) | (isr & 0x0000ffffUL);
+}
+
+struct x86_sysdesc _idt[IDT_ENTRY];
+u16_t _idt_limit = sizeof(_idt) - 1;
+
+#endif
+
+DECLARE_ISR(0)
+DECLARE_ISR(33)
+
+void
+exception_install_handler()
+{
+ ptr_t start = (ptr_t)_asm_isr0;
+
+ for (int i = 0; i < 256; i++) {
+ install_idte(_idt, i, start, 0);
+ start += 16;
+ }
+
+ install_idte(_idt, 33, (ptr_t)_asm_isr33, 3);
+
+#ifdef CONFIG_ARCH_X86_64
+ // TODO set different IST to some exception so it can get a
+ // better and safe stack to work with
+#endif
+}
\ No newline at end of file
--- /dev/null
+#include <lunaix/exebi/elf.h>
+
+#define EM_386 3
+
+int
+elf_check_arch(const struct elf* elf)
+{
+ const struct elf_ehdr* ehdr = &elf->eheader;
+
+ return *(u32_t*)(ehdr->e_ident) == ELFMAGIC_LE &&
+ ehdr->e_ident[EI_CLASS] == ELFCLASS32 &&
+ ehdr->e_ident[EI_DATA] == ELFDATA2LSB && ehdr->e_machine == EM_386;
+}
\ No newline at end of file
--- /dev/null
+#include <lunaix/exebi/elf.h>
+
+#define EM_X86_64 62
+
+int
+elf_check_arch(const struct elf* elf)
+{
+ const struct elf_ehdr* ehdr = &elf->eheader;
+
+ return *(u32_t*)(ehdr->e_ident) == ELFMAGIC_LE &&
+ ehdr->e_ident[EI_CLASS] == ELFCLASS64 &&
+ ehdr->e_ident[EI_DATA] == ELFDATA2LSB &&
+ ehdr->e_machine == EM_X86_64;
+}
\ No newline at end of file
--- /dev/null
+#include <lunaix/exec.h>
+#include <lunaix/mm/valloc.h>
+#include <klibc/string.h>
+
+int
+exec_arch_prepare_entry(struct thread* thread, struct exec_host* container)
+{
+ struct hart_state* hstate;
+
+ hstate = thread->hstate;
+
+#ifdef CONFIG_ARCH_X86_64
+ hstate->execp->rip = container->exe.entry;
+ hstate->execp->rsp = container->stack_top;
+
+#else
+ hstate->execp->eip = container->exe.entry;
+ hstate->execp->esp = container->stack_top;
+
+#endif
+
+ return 0;
+}
\ No newline at end of file
arch_gdbstub_save_regs(struct gdb_state* state, struct hart_state* hstate)
{
/* Load Registers */
+#ifndef CONFIG_ARCH_X86_64
state->registers[GDB_CPU_I386_REG_EAX] = hstate->registers.eax;
state->registers[GDB_CPU_I386_REG_ECX] = hstate->registers.ecx;
state->registers[GDB_CPU_I386_REG_EDX] = hstate->registers.edx;
state->registers[GDB_CPU_I386_REG_EBX] = hstate->registers.ebx;
- state->registers[GDB_CPU_I386_REG_ESP] = hstate->esp;
+ state->registers[GDB_CPU_I386_REG_ESP] = hstate->sp;
state->registers[GDB_CPU_I386_REG_EBP] = hstate->registers.ebp;
state->registers[GDB_CPU_I386_REG_ESI] = hstate->registers.esi;
state->registers[GDB_CPU_I386_REG_EDI] = hstate->registers.edi;
state->registers[GDB_CPU_I386_REG_ES] = hstate->registers.es;
state->registers[GDB_CPU_I386_REG_FS] = hstate->registers.fs;
state->registers[GDB_CPU_I386_REG_GS] = hstate->registers.gs;
+#else
+ // TODO
+#endif
}
void
arch_gdbstub_restore_regs(struct gdb_state* state, struct hart_state* hstate)
{
/* Restore Registers */
+#ifndef CONFIG_ARCH_X86_64
hstate->registers.eax = state->registers[GDB_CPU_I386_REG_EAX];
hstate->registers.ecx = state->registers[GDB_CPU_I386_REG_ECX];
hstate->registers.edx = state->registers[GDB_CPU_I386_REG_EDX];
hstate->registers.ebx = state->registers[GDB_CPU_I386_REG_EBX];
- hstate->esp = state->registers[GDB_CPU_I386_REG_ESP];
+ hstate->sp = state->registers[GDB_CPU_I386_REG_ESP];
hstate->registers.ebp = state->registers[GDB_CPU_I386_REG_EBP];
hstate->registers.esi = state->registers[GDB_CPU_I386_REG_ESI];
hstate->registers.edi = state->registers[GDB_CPU_I386_REG_EDI];
hstate->registers.es = state->registers[GDB_CPU_I386_REG_ES];
hstate->registers.fs = state->registers[GDB_CPU_I386_REG_FS];
hstate->registers.gs = state->registers[GDB_CPU_I386_REG_GS];
+#else
+ // TODO
+#endif
}
static inline void
rng_fill(void* data, size_t len)
{
+#ifdef CONFIG_ARCH_X86_64
+ asm volatile("1:\n"
+ "rdrand %%rax\n"
+ "movq %%rax, (%0)\n"
+ "addq $8, %%rax\n"
+ "subq $8, %1\n"
+ "jnz 1b"
+ ::
+ "r"((ptr_t)data),
+ "r"((len & ~0x7))
+ :
+ "%eax");
+#else
asm volatile("1:\n"
"rdrand %%eax\n"
"movl %%eax, (%0)\n"
"addl $4, %%eax\n"
"subl $4, %1\n"
- "jnz 1b" ::"r"((ptr_t)data),
+ "jnz 1b"
+ ::
+ "r"((ptr_t)data),
"r"((len & ~0x3))
- : "%eax");
+ :
+ "%eax");
+#endif
}
static int
static int
__rand_rd(struct device* dev, void* buf, size_t offset, size_t len)
{
- if (unlikely(len < 4)) {
+ if (unlikely(len < sizeof(ptr_t))) {
int tmp_buf = 0;
- rng_fill(&tmp_buf, 4);
+ rng_fill(&tmp_buf, sizeof(ptr_t));
memcpy(buf, &tmp_buf, len);
} else {
rng_fill(buf, len);
--- /dev/null
+#include <lunaix/hart_state.h>
+#include <lunaix/mm/vmm.h>
+#include <klibc/string.h>
+
+#include <sys/mm/mempart.h>
+
+bool
+install_hart_transition(ptr_t vm_mnt, struct hart_transition* ht)
+{
+ pte_t pte;
+ if (!vmm_lookupat(vm_mnt, ht->inject, &pte)) {
+ return false;
+ }
+
+ mount_page(PG_MOUNT_4, pte_paddr(pte));
+
+ ptr_t mount_inject = PG_MOUNT_4 + va_offset(ht->inject);
+ memcpy((void*)mount_inject, &ht->transfer, sizeof(ht->transfer));
+
+ unmount_page(PG_MOUNT_4);
+ return true;
+}
\ No newline at end of file
+#ifdef CONFIG_ARCH_I386
+
#include <lunaix/process.h>
#include <lunaix/hart_state.h>
#include <lunaix/mm/vmm.h>
.esp0 = 0,
.ss0 = KDATA_SEG };
-bool
-install_hart_transition(ptr_t vm_mnt, struct hart_transition* ht)
-{
- pte_t pte;
- if (!vmm_lookupat(vm_mnt, ht->inject, &pte)) {
- return false;
- }
-
- mount_page(PG_MOUNT_4, pte_paddr(pte));
-
- ptr_t mount_inject = PG_MOUNT_4 + va_offset(ht->inject);
- memcpy((void*)mount_inject, &ht->transfer, sizeof(ht->transfer));
-
- unmount_page(PG_MOUNT_4);
- return true;
-}
-
void
hart_prepare_transition(struct hart_transition* ht,
ptr_t kstack_tp, ptr_t ustack_pt,
.ss = data_seg, .esp = align_stack(ustack_pt),
.eflags = mstate
};
-}
\ No newline at end of file
+}
+
+#endif
\ No newline at end of file
--- /dev/null
+#ifdef CONFIG_ARCH_X86_64
+
+#include <lunaix/process.h>
+#include <lunaix/hart_state.h>
+#include <lunaix/mm/vmm.h>
+#include <klibc/string.h>
+
+#include <sys/mm/mempart.h>
+#include <sys/abi.h>
+
+volatile struct x86_tss _tss = { };
+
+void
+hart_prepare_transition(struct hart_transition* ht,
+ ptr_t kstack_tp, ptr_t ustack_pt,
+ ptr_t entry, bool to_user)
+{
+ ptr_t stack = ustack_pt;
+ ptr_t offset = (ptr_t)&ht->transfer.eret - (ptr_t)&ht->transfer;
+ ht->inject = align_stack(kstack_tp - sizeof(ht->transfer));
+
+ ht->transfer.state = (struct hart_state){
+ .registers = { },
+ .execp = (struct exec_param*)(ht->inject + offset)
+ };
+
+ int code_seg = KCODE_SEG, data_seg = KDATA_SEG;
+ int mstate = cpu_ldstate();
+ if (to_user) {
+ code_seg = UCODE_SEG, data_seg = UDATA_SEG;
+ mstate |= 0x200; // enable interrupt
+ }
+ else {
+ stack = kstack_tp;
+ }
+
+ ht->transfer.eret = (struct exec_param) {
+ .cs = code_seg, .rip = entry,
+ .ss = data_seg, .rsp = align_stack(stack),
+ .rflags = mstate
+ };
+}
+
+#endif
\ No newline at end of file
--- /dev/null
+#ifndef __LUNAIX_BASE_DEFS_LD_INC
+#define __LUNAIX_BASE_DEFS_LD_INC
+
+#define __LD__
+#include <sys/mm/mempart.h>
+
+#define KEXEC_BASE KERNEL_IMG
+#define PAGE_GRAN 4K
+
+#define ENTRY_POINT start_
+
+#ifdef CONFIG_X86_BL_MB
+# define LOAD_OFF 0x100000
+#else
+# error "unknown boot option, can't infer load_off"
+#endif
+
+#endif /* __LUNAIX_BASE_DEFS_LD_INC */
--- /dev/null
+#ifndef __LUNAIX_BOOT_SECS_LD_INC
+#define __LUNAIX_BOOT_SECS_LD_INC
+
+#include "base_defs.ld.inc"
+
+__kboot_start = .;
+
+.boot.text BLOCK(PAGE_GRAN) :
+{
+#if defined(CONFIG_X86_BL_MB) || defined(CONFIG_X86_BL_MB2)
+ *(.multiboot)
+#endif
+
+ *(.boot.text)
+}
+
+.boot.bss BLOCK(PAGE_GRAN) :
+{
+ *(.boot.bss)
+}
+
+.boot.data BLOCK(PAGE_GRAN) :
+{
+ *(.boot.data)
+}
+
+__kboot_end = ALIGN(PAGE_GRAN);
+
+#endif /* __LUNAIX_BOOT_SECS_LD_INC */
--- /dev/null
+#ifndef __LUNAIX_I386ABI_H
+#define __LUNAIX_I386ABI_H
+
+#ifdef CONFIG_ARCH_X86_64
+# include "abi64.h"
+#else
+# include "abi32.h"
+#endif
+
+#ifndef __ASM__
+#define align_stack(ptr) ((ptr) & stack_alignment)
+
+static inline void must_inline noret
+switch_context() {
+ asm volatile("jmp do_switch\n");
+ unreachable;
+}
+
+
+static inline ptr_t
+abi_get_retaddr()
+{
+ return *((ptr_t*)abi_get_callframe() + 1);
+}
+
+static inline ptr_t
+abi_get_retaddrat(ptr_t fp)
+{
+ return *((ptr_t*)fp + 1);
+}
+
+#endif
+#endif /* __LUNAIX_ABI_H */
--- /dev/null
+#ifndef __LUNAIX_ARCH_ABI32_H
+#define __LUNAIX_ARCH_ABI32_H
+
+#include "sys/x86_isa.h"
+
+#define stack_alignment 0xfffffff0
+
+#ifndef __ASM__
+#define store_retval(retval) current_thread->hstate->registers.eax = (retval)
+
+#define store_retval_to(th, retval) (th)->hstate->registers.eax = (retval)
+
+static inline void must_inline
+j_usr(ptr_t sp, ptr_t pc)
+{
+ asm volatile("movw %0, %%ax\n"
+ "movw %%ax, %%es\n"
+ "movw %%ax, %%ds\n"
+ "movw %%ax, %%fs\n"
+ "movw %%ax, %%gs\n"
+ "pushl %0\n"
+ "pushl %1\n"
+ "pushl %2\n"
+ "pushl %3\n"
+ "retf" ::"i"(UDATA_SEG),
+ "r"(sp),
+ "i"(UCODE_SEG),
+ "r"(pc)
+ : "eax", "memory");
+}
+
+static inline ptr_t must_inline
+abi_get_callframe()
+{
+ ptr_t val;
+ asm("movl %%ebp, %0" : "=r"(val)::);
+ return val;
+}
+
+#endif
+#endif /* __LUNAIX_ARCH_ABI32_H */
--- /dev/null
+#ifndef __LUNAIX_ARCH_ABI64_H
+#define __LUNAIX_ARCH_ABI64_H
+
+#include "sys/x86_isa.h"
+
+#define stack_alignment 0xfffffffffffffff0UL
+
+#ifndef __ASM__
+#define store_retval(retval) current_thread->hstate->registers.rax = (retval)
+
+#define store_retval_to(th, retval) (th)->hstate->registers.rax = (retval)
+
+static inline void must_inline
+j_usr(ptr_t sp, ptr_t pc)
+{
+ asm volatile(
+ "pushq %0\n"
+ "pushq %1\n"
+ "pushq %2\n"
+ "pushq %3\n"
+ "retfq"
+ ::
+ "i"(UDATA_SEG),
+ "r"(sp),
+ "i"(UCODE_SEG),
+ "r"(pc)
+ :
+ "memory");
+}
+
+static inline ptr_t must_inline
+abi_get_callframe()
+{
+ ptr_t val;
+ asm("movq %%rbp, %0" : "=r"(val)::);
+ return val;
+}
+
+#endif
+#endif /* __LUNAIX_ARCH_ABI64_H */
#define __LUNAIX_ARCHINIT_H
#include <lunaix/types.h>
-#include <sys/boot/bstage.h>
-#include <sys/boot/multiboot.h>
+#include "bstage.h"
+#include "multiboot.h"
ptr_t boot_text
kpg_init();
--- /dev/null
+#ifndef __LUNAIX_BSTAGE_H
+#define __LUNAIX_BSTAGE_H
+#include <lunaix/types.h>
+
+#define boot_text __attribute__((section(".boot.text")))
+#define boot_data __attribute__((section(".boot.data")))
+#define boot_bss __attribute__((section(".boot.bss")))
+
+/*
+ Bridge the far symbol to the vicinity.
+
+ Which is a workaround for relocation
+ issue where symbol define in kernel
+ code is too far away from the boot code.
+*/
+#ifdef CONFIG_ARCH_X86_64
+#define bridge_farsym(far_sym) \
+ asm( \
+ ".section .boot.bss\n" \
+ ".align 8\n" \
+ ".globl __lc_" #far_sym "\n" \
+ "__lc_" #far_sym ":\n" \
+ ".8byte " #far_sym "\n" \
+ ".previous\n" \
+ ); \
+ extern unsigned long __lc_##far_sym[];
+#define __far(far_sym) (__lc_##far_sym[0])
+
+#else
+#define bridge_farsym(far_sym) extern u8_t far_sym[];
+#define __far(far_sym) ((ptr_t)far_sym)
+
+#endif
+
+ptr_t remap_kernel();
+
+#endif /* __LUNAIX_BSTAGE_H */
-#ifndef MULTIBOOT_HEADER
-#define MULTIBOOT_HEADER 1
+#ifndef LUNAIX_MULTIBOOT_HEADER
+#define LUNAIX_MULTIBOOT_HEADER 1
// References https://www.gnu.org/software/grub/manual/multiboot/multiboot.html
-#define MULTIBOOT_MAGIC 0x1BADB002
-#define CHECKSUM(flags) -(MULTIBOOT_MAGIC + flags)
-
/* This should be in %eax. */
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
};
#define MB_MMAP_ENTRY_SIZE sizeof(multiboot_memory_map_t)
-
#endif
-#endif
\ No newline at end of file
+#endif
--- /dev/null
+/* multiboot2.h - Multiboot 2 header file. */
+/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY
+ * DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+ * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef LUNAIX_MULTIBOOT_HEADER
+#define LUNAIX_MULTIBOOT_HEADER 1
+
+/* How many bytes from the start of the file we search for the header. */
+#define MULTIBOOT_SEARCH 32768
+#define MULTIBOOT_HEADER_ALIGN 8
+
+/* This should be in %eax. */
+#define MULTIBOOT_BOOTLOADER_MAGIC 0x36d76289
+
+/* Alignment of multiboot modules. */
+#define MULTIBOOT_MOD_ALIGN 0x00001000
+
+/* Alignment of the multiboot info structure. */
+#define MULTIBOOT_INFO_ALIGN 0x00000008
+
+/* Flags set in the ’flags’ member of the multiboot header. */
+
+#define MULTIBOOT_TAG_ALIGN 8
+#define MULTIBOOT_TAG_TYPE_END 0
+#define MULTIBOOT_TAG_TYPE_CMDLINE 1
+#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2
+#define MULTIBOOT_TAG_TYPE_MODULE 3
+#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4
+#define MULTIBOOT_TAG_TYPE_BOOTDEV 5
+#define MULTIBOOT_TAG_TYPE_MMAP 6
+#define MULTIBOOT_TAG_TYPE_VBE 7
+#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
+#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9
+#define MULTIBOOT_TAG_TYPE_APM 10
+#define MULTIBOOT_TAG_TYPE_EFI32 11
+#define MULTIBOOT_TAG_TYPE_EFI64 12
+#define MULTIBOOT_TAG_TYPE_SMBIOS 13
+#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14
+#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15
+#define MULTIBOOT_TAG_TYPE_NETWORK 16
+#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
+#define MULTIBOOT_TAG_TYPE_EFI_BS 18
+#define MULTIBOOT_TAG_TYPE_EFI32_IH 19
+#define MULTIBOOT_TAG_TYPE_EFI64_IH 20
+#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21
+
+#define MULTIBOOT_HEADER_TAG_END 0
+#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
+#define MULTIBOOT_HEADER_TAG_ADDRESS 2
+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
+#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
+#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
+#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
+#define MULTIBOOT_HEADER_TAG_EFI_BS 7
+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8
+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
+#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10
+
+#define MULTIBOOT_ARCHITECTURE_I386 0
+#define MULTIBOOT_ARCHITECTURE_MIPS32 4
+#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
+
+#define MULTIBOOT_LOAD_PREFERENCE_NONE 0
+#define MULTIBOOT_LOAD_PREFERENCE_LOW 1
+#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
+
+#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
+#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
+
+#ifndef __ASM__
+
+typedef unsigned char multiboot_uint8_t;
+typedef unsigned short multiboot_uint16_t;
+typedef unsigned int multiboot_uint32_t;
+typedef unsigned long long multiboot_uint64_t;
+
+struct multiboot_header
+{
+ /* Must be MULTIBOOT_MAGIC - see above. */
+ multiboot_uint32_t magic;
+
+ /* ISA */
+ multiboot_uint32_t architecture;
+
+ /* Total header length. */
+ multiboot_uint32_t header_length;
+
+ /* The above fields plus this one must equal 0 mod 2^32. */
+ multiboot_uint32_t checksum;
+};
+
+struct multiboot_header_tag
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+};
+
+struct multiboot_header_tag_information_request
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t requests[0];
+};
+
+struct multiboot_header_tag_address
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t header_addr;
+ multiboot_uint32_t load_addr;
+ multiboot_uint32_t load_end_addr;
+ multiboot_uint32_t bss_end_addr;
+};
+
+struct multiboot_header_tag_entry_address
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t entry_addr;
+};
+
+struct multiboot_header_tag_console_flags
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t console_flags;
+};
+
+struct multiboot_header_tag_framebuffer
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t width;
+ multiboot_uint32_t height;
+ multiboot_uint32_t depth;
+};
+
+struct multiboot_header_tag_module_align
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+};
+
+struct multiboot_header_tag_relocatable
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t min_addr;
+ multiboot_uint32_t max_addr;
+ multiboot_uint32_t align;
+ multiboot_uint32_t preference;
+};
+
+struct multiboot_color
+{
+ multiboot_uint8_t red;
+ multiboot_uint8_t green;
+ multiboot_uint8_t blue;
+};
+
+struct multiboot_mmap_entry
+{
+ multiboot_uint64_t addr;
+ multiboot_uint64_t len;
+#define MULTIBOOT_MEMORY_AVAILABLE 1
+#define MULTIBOOT_MEMORY_RESERVED 2
+#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
+#define MULTIBOOT_MEMORY_NVS 4
+#define MULTIBOOT_MEMORY_BADRAM 5
+ multiboot_uint32_t type;
+ multiboot_uint32_t zero;
+};
+typedef struct multiboot_mmap_entry multiboot_memory_map_t;
+
+struct multiboot_tag
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+};
+
+struct multiboot_tag_string
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ char string[0];
+};
+
+struct multiboot_tag_module
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t mod_start;
+ multiboot_uint32_t mod_end;
+ char cmdline[0];
+};
+
+struct multiboot_tag_basic_meminfo
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t mem_lower;
+ multiboot_uint32_t mem_upper;
+};
+
+struct multiboot_tag_bootdev
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t biosdev;
+ multiboot_uint32_t slice;
+ multiboot_uint32_t part;
+};
+
+struct multiboot_tag_mmap
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t entry_size;
+ multiboot_uint32_t entry_version;
+ struct multiboot_mmap_entry entries[0];
+};
+
+struct multiboot_vbe_info_block
+{
+ multiboot_uint8_t external_specification[512];
+};
+
+struct multiboot_vbe_mode_info_block
+{
+ multiboot_uint8_t external_specification[256];
+};
+
+struct multiboot_tag_vbe
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+
+ multiboot_uint16_t vbe_mode;
+ multiboot_uint16_t vbe_interface_seg;
+ multiboot_uint16_t vbe_interface_off;
+ multiboot_uint16_t vbe_interface_len;
+
+ struct multiboot_vbe_info_block vbe_control_info;
+ struct multiboot_vbe_mode_info_block vbe_mode_info;
+};
+
+struct multiboot_tag_framebuffer_common
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+
+ multiboot_uint64_t framebuffer_addr;
+ multiboot_uint32_t framebuffer_pitch;
+ multiboot_uint32_t framebuffer_width;
+ multiboot_uint32_t framebuffer_height;
+ multiboot_uint8_t framebuffer_bpp;
+#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
+#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
+#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
+ multiboot_uint8_t framebuffer_type;
+ multiboot_uint16_t reserved;
+};
+
+struct multiboot_tag_framebuffer
+{
+ struct multiboot_tag_framebuffer_common common;
+
+ union
+ {
+ struct
+ {
+ multiboot_uint16_t framebuffer_palette_num_colors;
+ struct multiboot_color framebuffer_palette[0];
+ };
+ struct
+ {
+ multiboot_uint8_t framebuffer_red_field_position;
+ multiboot_uint8_t framebuffer_red_mask_size;
+ multiboot_uint8_t framebuffer_green_field_position;
+ multiboot_uint8_t framebuffer_green_mask_size;
+ multiboot_uint8_t framebuffer_blue_field_position;
+ multiboot_uint8_t framebuffer_blue_mask_size;
+ };
+ };
+};
+
+struct multiboot_tag_elf_sections
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t num;
+ multiboot_uint32_t entsize;
+ multiboot_uint32_t shndx;
+ char sections[0];
+};
+
+struct multiboot_tag_apm
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint16_t version;
+ multiboot_uint16_t cseg;
+ multiboot_uint32_t offset;
+ multiboot_uint16_t cseg_16;
+ multiboot_uint16_t dseg;
+ multiboot_uint16_t flags;
+ multiboot_uint16_t cseg_len;
+ multiboot_uint16_t cseg_16_len;
+ multiboot_uint16_t dseg_len;
+};
+
+struct multiboot_tag_efi32
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t pointer;
+};
+
+struct multiboot_tag_efi64
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint64_t pointer;
+};
+
+struct multiboot_tag_smbios
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint8_t major;
+ multiboot_uint8_t minor;
+ multiboot_uint8_t reserved[6];
+ multiboot_uint8_t tables[0];
+};
+
+struct multiboot_tag_old_acpi
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint8_t rsdp[0];
+};
+
+struct multiboot_tag_new_acpi
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint8_t rsdp[0];
+};
+
+struct multiboot_tag_network
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint8_t dhcpack[0];
+};
+
+struct multiboot_tag_efi_mmap
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t descr_size;
+ multiboot_uint32_t descr_vers;
+ multiboot_uint8_t efi_mmap[0];
+};
+
+struct multiboot_tag_efi32_ih
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t pointer;
+};
+
+struct multiboot_tag_efi64_ih
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint64_t pointer;
+};
+
+struct multiboot_tag_load_base_addr
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t load_base_addr;
+};
+
+#endif /* ! __ASM__ */
+
+#endif /* ! MULTIBOOT_HEADER */
\ No newline at end of file
--- /dev/null
+#define __ASM__
+
+#include "multiboot.h"
+
+.section .multiboot
+__mb_start:
+ .4byte MULTIBOOT_MAGIC
+
+#ifdef CONFIG_X86_BL_MB
+ #define MB_FLAGS (MULTIBOOT_MEMORY_INFO | MULTIBOOT_PAGE_ALIGN)
+ .4byte MB_FLAGS
+ .4byte -(MULTIBOOT_MAGIC + MB_FLAGS)
+
+#elif CONFIG_X86_BL_MB2
+ #define HDR_LEN (__mb_end - __mb_start)
+
+ .4byte 0
+ .4byte HDR_LEN
+ .4byte -(MULTIBOOT_MAGIC + HDR_LEN)
+
+ .align MULTIBOOT_TAG_ALIGN
+ __mbir_tag_start:
+ .2byte MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST
+ .2byte 0
+ .4byte __mbir_tag_end - __mbir_tag_start
+ .4byte MULTIBOOT_TAG_TYPE_CMDLINE
+ .4byte MULTIBOOT_TAG_TYPE_MMAP
+ .4byte MULTIBOOT_TAG_TYPE_BASIC_MEMINFO
+ .4byte MULTIBOOT_TAG_TYPE_MODULE
+ __mbir_tag_end:
+
+ .align MULTIBOOT_TAG_ALIGN
+ .2byte MULTIBOOT_HEADER_TAG_END
+ .2byte 0
+ .4byte 8
+
+#endif
+
+__mb_end:
\ No newline at end of file
--- /dev/null
+#ifndef LUNAIX_MULTIBOOT_H
+#define LUNAIX_MULTIBOOT_H 1
+
+#ifdef CONFIG_X86_BL_MB
+# include "mb.h"
+# define MULTIBOOT_MAGIC 0x1BADB002
+#elif CONFIG_X86_BL_MB2
+# include "mb2.h"
+# define MULTIBOOT_MAGIC 0xe85250d6
+#else
+#error "Multiboot interfacing is not enabled"
+#endif
+
+#endif
\ No newline at end of file
#include <lunaix/types.h>
+#ifdef CONFIG_ARCH_X86_64
+# define _POP "popq "
+# define _MOV "movq "
+#else
+# define _POP "popl "
+# define _MOV "movl "
+#endif
+
/**
* @brief Get processor ID string
*
void
cpu_trap_panic(char* message);
-
/**
* @brief Load current processor state
*
{
ptr_t val;
asm volatile("pushf\n"
- "popl %0\n"
+ _POP "%0\n"
: "=r"(val)::);
return val;
}
cpu_ldconfig()
{
reg_t val;
- asm volatile("movl %%cr0,%0" : "=r"(val));
+ asm volatile(_MOV "%%cr0,%0" : "=r"(val));
return val;
}
static inline void
cpu_chconfig(reg_t val)
{
- asm("mov %0, %%cr0" ::"r"(val));
+ asm(_MOV "%0, %%cr0" ::"r"(val));
}
/**
static inline void
cpu_chvmspace(reg_t val)
{
- asm("mov %0, %%cr3" ::"r"(val));
+ asm(_MOV "%0, %%cr3" ::"r"(val));
+}
+
+/**
+ * @brief Read exeception address
+ *
+ * @return ptr_t
+ */
+static inline ptr_t
+cpu_ldeaddr()
+{
+ ptr_t val;
+ asm volatile(_MOV "%%cr2,%0" : "=r"(val));
+ return val;
}
+
static inline void
cpu_enable_interrupt()
{
asm("hlt");
}
-/**
- * @brief Read exeception address
- *
- * @return ptr_t
- */
-static inline ptr_t
-cpu_ldeaddr()
-{
- ptr_t val;
- asm volatile("movl %%cr2,%0" : "=r"(val));
- return val;
-}
-
#endif /* __LUNAIX_CPU_H */
#define CR0_EM ( 1UL << 2 )
#define CR0_MP ( 1UL << 1 )
+#ifdef CONFIG_ARCH_X86_64
+
+#define crx_addflag(crx, flag) \
+ asm( \
+ "movq %%" #crx ", %%rax\n" \
+ "orq %0, %%rax\n" \
+ "movq %%rax, %%" #crx "\n" \
+ ::"r"(flag) \
+ :"rax" \
+ );
+
+#define crx_rmflag(crx, flag) \
+ asm( \
+ "movq %%" #crx ", %%rax\n" \
+ "andq %0, %%rax\n" \
+ "movq %%rax, %%" #crx "\n" \
+ ::"r"(~(flag)) \
+ :"rax" \
+ );
+
+#else
+
#define crx_addflag(crx, flag) \
asm( \
"movl %%" #crx ", %%eax\n" \
:"eax" \
);
+#endif
+
static inline void
cr4_setfeature(unsigned long feature)
{
--- /dev/null
+#ifndef __LUNAIX_ARCH_ELF_H
+#define __LUNAIX_ARCH_ELF_H
+
+#include <lunaix/types.h>
+
+#define ELFCLASS32 1
+#define ELFCLASS64 2
+
+#define ELFDATA2LSB 1
+#define ELFDATA2MSB 2
+
+#ifdef CONFIG_ARCH_X86_64
+typedef unsigned long elf_ptr_t;
+typedef unsigned short elf_hlf_t;
+typedef unsigned long elf_off_t;
+typedef int elf_swd_t;
+typedef unsigned int elf_wrd_t;
+typedef unsigned long elf_xwrd_t;
+typedef long elf_sxwrd_t;
+#else
+typedef unsigned int elf_ptr_t;
+typedef unsigned short elf_hlf_t;
+typedef unsigned int elf_off_t;
+typedef unsigned int elf_swd_t;
+typedef unsigned int elf_wrd_t;
+#endif
+
+struct elf_ehdr
+{
+ u8_t e_ident[16];
+ elf_hlf_t e_type;
+ elf_hlf_t e_machine;
+ elf_wrd_t e_version;
+ elf_ptr_t e_entry;
+ elf_off_t e_phoff;
+ elf_off_t e_shoff;
+ elf_wrd_t e_flags;
+ elf_hlf_t e_ehsize;
+ elf_hlf_t e_phentsize;
+ elf_hlf_t e_phnum;
+ elf_hlf_t e_shentsize;
+ elf_hlf_t e_shnum;
+ elf_hlf_t e_shstrndx;
+};
+
+struct elf_phdr
+{
+#ifdef CONFIG_ARCH_X86_64
+ elf_wrd_t p_type;
+ elf_wrd_t p_flags;
+ elf_off_t p_offset;
+ elf_ptr_t p_va;
+ elf_ptr_t p_pa;
+ elf_xwrd_t p_filesz;
+ elf_xwrd_t p_memsz;
+ elf_xwrd_t p_align;
+#else
+ elf_wrd_t p_type;
+ elf_off_t p_offset;
+ elf_ptr_t p_va;
+ elf_ptr_t p_pa;
+ elf_wrd_t p_filesz;
+ elf_wrd_t p_memsz;
+ elf_wrd_t p_flags;
+ elf_wrd_t p_align;
+#endif
+};
+
+#endif /* __LUNAIX_ARCH_ELF_H */
failsafe_diagnostic() {
// asm ("jmp __fatal_state");
extern int failsafe_stack_top[];
- asm (
+#ifdef CONFIG_ARCH_X86_64
+ asm (
+ "movq %%rsp, %%rax\n"
+ "movq %%rbp, %%rbx\n"
+
+ "movq %0, %%rsp\n"
+
+ "pushq %%rax\n"
+ "pushq %%rbx\n"
+
+ "call do_failsafe_unrecoverable\n"
+ ::"r"(failsafe_stack_top)
+ :"memory"
+ );
+#else
+ asm (
"movl %%esp, %%eax\n"
"movl %%ebp, %%ebx\n"
::"r"(failsafe_stack_top)
:"memory"
);
+#endif
unreachable;
}
#include <lunaix/compiler.h>
#include <sys/cpu.h>
-struct exec_param;
+struct hart_state;
+
+#ifdef CONFIG_ARCH_X86_64
+struct regcontext
+{
+ reg_t rax;
+ reg_t rbx;
+ reg_t rcx;
+ reg_t rdx;
+ reg_t rdi;
+ reg_t rbp;
+ reg_t rsi;
+ reg_t r8;
+ reg_t r9;
+ reg_t r10;
+ reg_t r11;
+ reg_t r12;
+ reg_t r13;
+ reg_t r14;
+ reg_t r15;
+} compact;
+
+struct exec_param
+{
+ struct hart_state* parent_state;
+ reg_t vector;
+ reg_t err_code;
+ reg_t rip;
+ reg_t cs;
+ reg_t rflags;
+ reg_t rsp;
+ reg_t ss;
+} compact;
+
+
+#else
struct regcontext
{
reg_t eax;
reg_t gs;
} compact;
-struct hart_state
-{
- unsigned int depth;
- struct regcontext registers;
- union
- {
- reg_t esp;
- volatile struct exec_param* execp;
- };
-} compact;
-
struct exec_param
{
struct hart_state* parent_state;
reg_t ss;
} compact;
+#endif
+
+
+struct hart_state
+{
+ reg_t depth;
+ struct regcontext registers;
+ union
+ {
+ reg_t sp;
+ volatile struct exec_param* execp;
+ };
+} compact;
+
+static inline int
+hart_vector_stamp(struct hart_state* hstate) {
+ return hstate->execp->vector;
+}
+
+static inline unsigned int
+hart_ecause(struct hart_state* hstate) {
+ return hstate->execp->err_code;
+}
+
+static inline struct hart_state*
+hart_parent_state(struct hart_state* hstate)
+{
+ return hstate->execp->parent_state;
+}
static inline void
-hart_flow_redirect(struct hart_state* hstate, ptr_t pc, ptr_t sp)
+hart_push_state(struct hart_state* p_hstate, struct hart_state* hstate)
{
- hstate->execp->eip = pc;
- hstate->execp->esp = sp;
+ hstate->execp->parent_state = p_hstate;
}
+
+#ifdef CONFIG_ARCH_X86_64
static inline ptr_t
hart_pc(struct hart_state* hstate)
{
- return hstate->execp->eip;
+ return hstate->execp->rip;
}
static inline ptr_t
hart_sp(struct hart_state* hstate)
{
- return hstate->execp->esp;
+ return hstate->execp->rsp;
}
static inline bool
static inline ptr_t
hart_stack_frame(struct hart_state* hstate)
{
- return hstate->registers.ebp;
+ return hstate->registers.rbp;
}
-static inline int
-hart_vector_stamp(struct hart_state* hstate) {
- return hstate->execp->vector;
+#else
+static inline ptr_t
+hart_pc(struct hart_state* hstate)
+{
+ return hstate->execp->eip;
}
-static inline unsigned int
-hart_ecause(struct hart_state* hstate) {
- return hstate->execp->err_code;
+static inline ptr_t
+hart_sp(struct hart_state* hstate)
+{
+ return hstate->execp->esp;
}
-static inline struct hart_state*
-hart_parent_state(struct hart_state* hstate)
+static inline bool
+kernel_context(struct hart_state* hstate)
{
- return hstate->execp->parent_state;
+ return !((hstate->execp->cs) & 0b11);
}
-static inline void
-hart_push_state(struct hart_state* p_hstate, struct hart_state* hstate)
+static inline ptr_t
+hart_stack_frame(struct hart_state* hstate)
{
- hstate->execp->parent_state = p_hstate;
+ return hstate->registers.ebp;
}
#endif
+#endif
+
#endif /* __LUNAIX_ARCH_HART_H */
--- /dev/null
+#ifndef __LUNAIX_INT_HANDLER_H
+#define __LUNAIX_INT_HANDLER_H
+
+void
+exception_install_handler();
+
+void
+intr_routine_init();
+
+#endif /* __LUNAIX_INT_HANDLER_H */
--- /dev/null
+
+#define regsize 8
+#define regsize32 4
+
+/* stack layout: saved interrupt context */
+ .struct 0
+idepth:
+ .struct idepth + regsize
+irax:
+ .struct irax + regsize
+irbx:
+ .struct irbx + regsize
+ircx:
+ .struct ircx + regsize
+irdx:
+ .struct irdx + regsize
+irdi:
+ .struct irdi + regsize
+irbp:
+ .struct irbp + regsize
+irsi:
+ .struct irsi + regsize
+ir8:
+ .struct ir8 + regsize
+ir9:
+ .struct ir9 + regsize
+ir10:
+ .struct ir10 + regsize
+ir11:
+ .struct ir11 + regsize
+ir12:
+ .struct ir12 + regsize
+ir13:
+ .struct ir13 + regsize
+ir14:
+ .struct ir14 + regsize
+ir15:
+ .struct ir15 + regsize
+iexecp:
+irsp:
+ .struct irsp + regsize
+isave_parent:
+ .struct isave_parent + regsize
+ivec:
+ .struct ivec + regsize
+iecode:
+ .struct iecode + regsize
+irip:
+ .struct irip + regsize
+ics:
+ .struct ics + regsize
+irflags:
+ .struct irflags + regsize
+iursp:
+ .struct iursp + regsize
+iuss:
+
+
+/* stack layout: execution (flow-control) state context */
+ .struct 0
+exsave_prev:
+ .struct exsave_prev + regsize
+exvec:
+ .struct exvec + regsize
+execode:
+ .struct execode + regsize
+exrip:
+ .struct exrip + regsize
+excs:
+ .struct excs + regsize
+exrflags:
+ .struct exrflags + regsize
+exursp:
+ .struct exursp + regsize
+exuss:
+
+/* struct layout: critical section of struct proc_info */
+ .struct 0
+thread_hstate:
+ .struct thread_hstate + regsize
+thread_ustack_top:
+
+/* struct layout: proc_sig */
+ .struct 0
+psig_signum:
+ .struct psig_signum + regsize32
+psig_sigact:
+ .struct psig_sigact + regsize
+psig_sighand:
+ .struct psig_sighand + regsize
+psig_saved_hstate:
+
+/* struct layout: x86_tss */
+ .struct 0
+ .struct regsize32
+rsp_0:
+ .struct rsp_0 + regsize
+rsp_1:
+ .struct rsp_1 + regsize
+rsp_2:
+ .struct rsp_2 + regsize
+rsp_3:
+ .struct rsp_3 + regsize
+ist_null:
+ .struct ist_null + regsize
+ist_1:
+
_pte_prot |= _PTE_W;
}
- if ((vmr_prot & PROT_EXEC)) {
- _pte_prot |= _PTE_X;
+ if (!(vmr_prot & PROT_EXEC)) {
+ _pte_prot |= _PTE_NX;
}
return _pte_prot;
--- /dev/null
+#ifndef __LUNAIX_MEMPART_H
+#define __LUNAIX_MEMPART_H
+
+#ifdef CONFIG_ARCH_X86_64
+# include "mempart64.h"
+#else
+# include "mempart32.h"
+#endif
+
+#endif
\ No newline at end of file
--- /dev/null
+#ifndef __LUNAIX_MEMPART32_H
+#define __LUNAIX_MEMPART32_H
+
+#define END_POINT(name) (name + name##_SIZE - 1)
+
+#ifdef __LD__
+#define __ulong(val) val
+#else
+#define __ulong(val) val##UL
+#endif
+
+#define KSTACK_AREA __ulong(0x100000)
+#define KSTACK_AREA_SIZE __ulong(0x300000)
+#define KSTACK_AREA_END END_POINT(KSTACK_AREA)
+
+#define USR_EXEC __ulong(0x400000)
+#define USR_EXEC_SIZE __ulong(0x20000000)
+#define USR_EXEC_END END_POINT(USR_EXEC)
+
+#define USR_MMAP __ulong(0x20400000)
+#define USR_MMAP_SIZE __ulong(0x9fbc0000)
+#define USR_MMAP_END END_POINT(USR_MMAP)
+
+#define USR_STACK __ulong(0xbffc0000)
+#define USR_STACK_SIZE __ulong(0x40000)
+#define USR_STACK_SIZE_THREAD __ulong(0x40000)
+#define USR_STACK_END END_POINT(USR_STACK)
+
+#define KERNEL_RESIDENT __ulong(0xc0000000)
+
+#define KERNEL_IMG KERNEL_RESIDENT
+#define KERNEL_IMG_SIZE __ulong(0x4000000)
+#define KERNEL_IMG_END END_POINT(KERNEL_IMG)
+
+#define PG_MOUNT_1 __ulong(0xc4000000)
+#define PG_MOUNT_1_SIZE __ulong(0x1000)
+#define PG_MOUNT_1_END END_POINT(PG_MOUNT_1)
+
+#define PG_MOUNT_2 __ulong(0xc4001000)
+#define PG_MOUNT_2_SIZE __ulong(0x1000)
+#define PG_MOUNT_2_END END_POINT(PG_MOUNT_2)
+
+#define PG_MOUNT_3 __ulong(0xc4002000)
+#define PG_MOUNT_3_SIZE __ulong(0x1000)
+#define PG_MOUNT_3_END END_POINT(PG_MOUNT_3)
+
+#define PG_MOUNT_4 __ulong(0xc4003000)
+#define PG_MOUNT_4_SIZE __ulong(0x1000)
+#define PG_MOUNT_4_END END_POINT(PG_MOUNT_4)
+
+#define PG_MOUNT_VAR __ulong(0xc4004000)
+#define PG_MOUNT_VAR_SIZE __ulong(0x3fc000)
+#define PG_MOUNT_VAR_END END_POINT(PG_MOUNT_VAR)
+
+#define VMAP __ulong(0xc4400000)
+#define VMAP_SIZE __ulong(0x3b400000)
+#define VMAP_END END_POINT(VMAP)
+
+#define PMAP VMAP
+
+#define VMS_MOUNT_1 __ulong(0xff800000)
+#define VMS_MOUNT_1_SIZE __ulong(0x400000)
+#define VMS_MOUNT_1_END END_POINT(VMS_MOUNT_1)
+
+#define VMS_SELF_MOUNT __ulong(0xffc00000)
+
+#endif /* __LUNAIX_MEMPART32_H */
--- /dev/null
+#ifndef __LUNAIX_MEMPART64_H
+#define __LUNAIX_MEMPART64_H
+
+#define END_POINT(name) (name + name##_SIZE - 1)
+
+#ifdef __LD__
+#define __ulong(val) val
+#else
+#define __ulong(val) val##UL
+#endif
+
+#define KSTACK_AREA __ulong(0x0000000100000000)
+#define KSTACK_AREA_SIZE __ulong(0x0000000040000000)
+#define KSTACK_AREA_END END_POINT(KSTACK_AREA)
+
+#define USR_EXEC __ulong(0x0000008000000000)
+#define USR_EXEC_SIZE __ulong(0x0000002000000000)
+#define USR_EXEC_END END_POINT(USR_EXEC)
+
+#define USR_MMAP __ulong(0x0000010000000000)
+#define USR_MMAP_SIZE __ulong(0x0000008000000000)
+#define USR_MMAP_END END_POINT(USR_MMAP)
+
+#define USR_STACK __ulong(0x00007f8000000000)
+#define USR_STACK_SIZE __ulong(0x0000001fc0000000)
+#define USR_STACK_SIZE_THREAD __ulong(0x0000000000200000)
+#define USR_STACK_END END_POINT(USR_STACK)
+
+
+// la casa del kernel
+
+#define KERNEL_RESIDENT __ulong(0xfffffd8000000000) // -2.5T
+#define VMAP KERNEL_RESIDENT // -2.5T
+#define VMAP_SIZE __ulong(0x0000010000000000)
+#define VMAP_END END_POINT(VMAP)
+
+#define VMS_MOUNT_1 __ulong(0xfffffe8000000000) // -1.5T
+#define VMS_MOUNT_1_SIZE __ulong(0x0000008000000000)
+#define VMS_MOUNT_1_END END_POINT(VMS_MOUNT_1)
+
+#define VMS_SELF_MOUNT __ulong(0xffffff0000000000) // -1T
+
+#define KMAP __ulong(0xffffff8000000000)
+#define PG_MOUNT_1 KMAP // -512G
+#define PG_MOUNT_1_SIZE __ulong(0x0000000000001000)
+#define PG_MOUNT_1_END END_POINT(PG_MOUNT_1)
+
+#define PG_MOUNT_2 __ulong(0xffffff8000001000)
+#define PG_MOUNT_2_SIZE __ulong(0x0000000000001000)
+#define PG_MOUNT_2_END END_POINT(PG_MOUNT_2)
+
+#define PG_MOUNT_3 __ulong(0xffffff8000002000)
+#define PG_MOUNT_3_SIZE __ulong(0x0000000000001000)
+#define PG_MOUNT_3_END END_POINT(PG_MOUNT_3)
+
+#define PG_MOUNT_4 __ulong(0xffffff8000003000)
+#define PG_MOUNT_4_SIZE __ulong(0x0000000000001000)
+#define PG_MOUNT_4_END END_POINT(PG_MOUNT_4)
+
+#define PG_MOUNT_VAR __ulong(0xffffff8000004000)
+#define PG_MOUNT_VAR_SIZE __ulong(0x000000003fffc000)
+#define PG_MOUNT_VAR_END END_POINT(PG_MOUNT_VAR)
+
+#define PMAP __ulong(0xffffff8040000000)
+
+#define KERNEL_IMG __ulong(0xffffffff80000000) // -2G
+#define KERNEL_IMG_SIZE __ulong(0x0000000080000000)
+#define KERNEL_IMG_END END_POINT(KERNEL_IMG)
+
+
+#endif
\ No newline at end of file
#ifndef __LUNAIX_MM_DEFS_H
#define __LUNAIX_MM_DEFS_H
-
#include "mempart.h"
#include "pagetable.h"
-#define KSTACK_PAGES 3
-#define KSTACK_SIZE (KSTACK_PAGES * MEM_PAGE)
-
/*
Regardless architecture we need to draw the line very carefully, and must
take the size of VM into account. In general, we aims to achieve
In light of upcomming x86_64 support (for Level 4&5 Paging):
* #510 entry of PML4 (0x0000ff0000000000, ~512GiB)
* #510 entry of PML5 (0x01fe000000000000, ~256TiB)
+
+
+ KERNEL_RESIDENT - a high-mem region, kernel should be
+ KSTACK_PAGES - kernel stack, pages allocated to
+ KEXEC_RSVD - page reserved for kernel images
*/
-// Where the kernel getting re-mapped.
-#define KERNEL_RESIDENT 0xc0000000UL
-// Pages reserved for kernel image
-#define KEXEC_RSVD 16
+#ifdef CONFIG_ARCH_X86_64
+# define KSTACK_PAGES 4
+# define KEXEC_RSVD 32
+#else
+# define KSTACK_PAGES 2
+# define KEXEC_RSVD 16
+#endif
+
+#define KSTACK_SIZE (KSTACK_PAGES * PAGE_SIZE)
#define kernel_addr(addr) ((addr) >= KERNEL_RESIDENT || (addr) < USR_EXEC)
-#define to_kphysical(k_va) ((ptr_t)(k_va) - KERNEL_RESIDENT)
-#define to_kvirtual(k_pa) ((ptr_t)(k_pa) - KERNEL_RESIDENT)
+#define to_kphysical(k_va) ((ptr_t)(k_va) - KERNEL_IMG)
+#define to_kvirtual(k_pa) ((ptr_t)(k_pa) + KERNEL_IMG)
#endif /* __LUNAIX_MM_DEFS_H */
/* ******** Page Table Manipulation ******** */
-// Levels of page table to traverse for a single page walk
-#define _PTW_LEVEL 2
+#ifdef CONFIG_ARCH_X86_64
-#define _PAGE_BASE_SHIFT 12
-#define _PAGE_BASE_SIZE ( 1UL << _PAGE_BASE_SHIFT )
-#define _PAGE_BASE_MASK ( _PAGE_BASE_SIZE - 1)
+#include "pt_def64.h"
-#define _PAGE_LEVEL_SHIFT 10
-#define _PAGE_LEVEL_SIZE ( 1UL << _PAGE_LEVEL_SHIFT )
-#define _PAGE_LEVEL_MASK ( _PAGE_LEVEL_SIZE - 1 )
-#define _PAGE_Ln_SIZE(n) ( 1UL << (_PAGE_BASE_SHIFT + _PAGE_LEVEL_SHIFT * (_PTW_LEVEL - (n) - 1)) )
+#else
-// Note: we set VMS_SIZE = VMS_MASK as it is impossible
-// to express 4Gi in 32bit unsigned integer
+#include "pt_def32.h"
-#define VMS_MASK ( -1UL )
-#define VMS_SIZE VMS_MASK
-
-/* General size of a LnT huge page */
-
-#define L0T_SIZE _PAGE_Ln_SIZE(0)
-#define L1T_SIZE _PAGE_Ln_SIZE(1)
-#define L2T_SIZE _PAGE_Ln_SIZE(1)
-#define L3T_SIZE _PAGE_Ln_SIZE(1)
-#define LFT_SIZE _PAGE_Ln_SIZE(1)
+#endif
/* General mask to get page offset of a LnT huge page */
// max translation level supported
#define MAX_LEVEL _PTW_LEVEL
-
-/* ******** PTE Manipulation ******** */
-
-struct __pte {
- unsigned int val;
-} align(4);
-
#ifndef pte_t
typedef struct __pte pte_t;
#endif
-typedef unsigned int pfn_t;
-typedef unsigned int pte_attr_t;
-
-#define _PTE_P (1 << 0)
-#define _PTE_W (1 << 1)
-#define _PTE_U (1 << 2)
-#define _PTE_WT (1 << 3)
-#define _PTE_CD (1 << 4)
-#define _PTE_A (1 << 5)
-#define _PTE_D (1 << 6)
-#define _PTE_PS (1 << 7)
-#define _PTE_PAT (1 << 7)
-#define _PTE_G (1 << 8)
-#define _PTE_X (0)
-#define _PTE_R (0)
#define _PTE_PROT_MASK ( _PTE_W | _PTE_U | _PTE_X )
#define KERNEL_PAGE ( _PTE_P )
#define KERNEL_EXEC ( KERNEL_PAGE | _PTE_X )
-#define KERNEL_DATA ( KERNEL_PAGE | _PTE_W )
-#define KERNEL_RDONLY ( KERNEL_PAGE )
+#define KERNEL_DATA ( KERNEL_PAGE | _PTE_W | _PTE_NX )
+#define KERNEL_RDONLY ( KERNEL_PAGE | _PTE_NX )
+#define KERNEL_ROEXEC ( KERNEL_PAGE | _PTE_X )
#define USER_PAGE ( _PTE_P | _PTE_U )
#define USER_EXEC ( USER_PAGE | _PTE_X )
-#define USER_DATA ( USER_PAGE | _PTE_W )
-#define USER_RDONLY ( USER_PAGE )
+#define USER_DATA ( USER_PAGE | _PTE_W | _PTE_NX )
+#define USER_RDONLY ( USER_PAGE | _PTE_NX )
+#define USER_ROEXEC ( USER_PAGE | _PTE_X )
#define SELF_MAP ( KERNEL_DATA | _PTE_WT | _PTE_CD )
#define __mkpte_from(pte_val) ((pte_t){ .val = (pte_val) })
-#define __MEMGUARD 0xdeadc0deUL
#define null_pte ( __mkpte_from(0) )
#define guard_pte ( __mkpte_from(__MEMGUARD) )
static inline ptr_t
pte_paddr(pte_t pte)
{
- return pte.val & ~_PAGE_BASE_MASK;
+ return __paddr(pte.val) & ~_PAGE_BASE_MASK;
}
static inline pfn_t
pte_ppfn(pte_t pte)
{
- return pte.val >> _PAGE_BASE_SHIFT;
+ return __paddr(pte.val) >> _PAGE_BASE_SHIFT;
}
static inline pte_t
static inline pte_t
pte_mkexec(pte_t pte)
{
- return __mkpte_from(pte.val | _PTE_X);
+ return __mkpte_from(pte.val & ~_PTE_NX);
}
static inline pte_t
pte_mknonexec(pte_t pte)
{
- return __mkpte_from(pte.val & ~_PTE_X);
+ return __mkpte_from(pte.val | _PTE_NX);
}
static inline bool
pte_isexec(pte_t pte)
{
- return !!(pte.val & _PTE_X);
+ return !(pte.val & _PTE_NX);
}
static inline pte_t
#include <lunaix/ds/llist.h>
#include "mm_defs.h"
-#define PPLIST_STARTVM VMAP
+#define PPLIST_STARTVM PMAP
struct ppage_arch
{
--- /dev/null
+#ifdef CONFIG_ARCH_I386
+
+#ifndef __LUNAIX_PT_DEF32_H
+#define __LUNAIX_PT_DEF32_H
+
+#define _PTW_LEVEL 2
+
+#define _PAGE_BASE_SHIFT 12
+#define _PAGE_BASE_SIZE ( 1UL << _PAGE_BASE_SHIFT )
+#define _PAGE_BASE_MASK ( _PAGE_BASE_SIZE - 1)
+
+#define _PAGE_LEVEL_SHIFT 10
+#define _PAGE_LEVEL_SIZE ( 1UL << _PAGE_LEVEL_SHIFT )
+#define _PAGE_LEVEL_MASK ( _PAGE_LEVEL_SIZE - 1 )
+#define _PAGE_Ln_SIZE(n) ( 1UL << (_PAGE_BASE_SHIFT + _PAGE_LEVEL_SHIFT * (_PTW_LEVEL - (n) - 1)) )
+
+// Note: we set VMS_SIZE = VMS_MASK as it is impossible
+// to express 4Gi in 32bit unsigned integer
+
+#define VMS_BITS 32
+#define PMS_BITS 32
+
+#define VMS_SIZE ( -1UL )
+#define VMS_MASK ( -1UL )
+#define PMS_SIZE ( -1UL )
+#define PMS_MASK ( -1UL )
+
+/* General size of a LnT huge page */
+
+#define L0T_SIZE _PAGE_Ln_SIZE(0)
+#define L1T_SIZE _PAGE_Ln_SIZE(1)
+#define L2T_SIZE _PAGE_Ln_SIZE(1)
+#define L3T_SIZE _PAGE_Ln_SIZE(1)
+#define LFT_SIZE _PAGE_Ln_SIZE(1)
+
+struct __pte {
+ unsigned int val;
+} align(4);
+
+#define _PTE_P (1 << 0)
+#define _PTE_W (1 << 1)
+#define _PTE_U (1 << 2)
+#define _PTE_WT (1 << 3)
+#define _PTE_CD (1 << 4)
+#define _PTE_A (1 << 5)
+#define _PTE_D (1 << 6)
+#define _PTE_PS (1 << 7)
+#define _PTE_PAT (1 << 7)
+#define _PTE_G (1 << 8)
+#define _PTE_X (0)
+#define _PTE_NX (0)
+#define _PTE_R (0)
+
+#define __MEMGUARD 0xdeadc0deUL
+
+typedef unsigned int pte_attr_t;
+typedef unsigned int pfn_t;
+
+#define __index(va) ( (va) & VMS_MASK )
+#define __vaddr(va) ( va )
+#define __paddr(pa) ( (pa) & PMS_MASK )
+
+#endif /* __LUNAIX_PT_DEF32_H */
+#endif
--- /dev/null
+#ifdef CONFIG_ARCH_X86_64
+#ifndef __LUNAIX_PT_DEF64_H
+#define __LUNAIX_PT_DEF64_H
+
+#include <lunaix/types.h>
+
+#define _PTW_LEVEL 4
+
+
+// Note: we set VMS_SIZE = VMS_MASK as it is impossible
+// to express 4Gi in 32bit unsigned integer
+
+#define _PAGE_BASE_SHIFT 12
+
+#define _PAGE_BASE_SIZE ( 1UL << _PAGE_BASE_SHIFT )
+#define _PAGE_BASE_MASK ( (_PAGE_BASE_SIZE - 1) & 0x000fffffffffffffUL )
+
+#define _PAGE_LEVEL_SHIFT 9
+#define _PAGE_LEVEL_SIZE ( 1UL << _PAGE_LEVEL_SHIFT )
+#define _PAGE_LEVEL_MASK ( _PAGE_LEVEL_SIZE - 1 )
+#define _PAGE_Ln_SIZE(n) ( 1UL << (_PAGE_BASE_SHIFT + _PAGE_LEVEL_SHIFT * (_PTW_LEVEL - (n) - 1)) )
+
+#define VMS_BITS 48
+#define PMS_BITS 52
+
+#define VMS_SIZE ( 1UL << VMS_BITS)
+#define VMS_MASK ( VMS_SIZE - 1 )
+#define PMS_SIZE ( 1UL << PMS_BITS )
+#define PMS_MASK ( PMS_SIZE - 1 )
+
+/* General size of a LnT huge page */
+
+#define L0T_SIZE _PAGE_Ln_SIZE(0)
+#define L1T_SIZE _PAGE_Ln_SIZE(1)
+#define L2T_SIZE _PAGE_Ln_SIZE(2)
+#define L3T_SIZE _PAGE_Ln_SIZE(3)
+#define LFT_SIZE _PAGE_Ln_SIZE(3)
+
+
+struct __pte {
+ unsigned long val;
+} align(8);
+
+#define _PTE_P (1UL << 0)
+#define _PTE_W (1UL << 1)
+#define _PTE_U (1UL << 2)
+#define _PTE_WT (1UL << 3)
+#define _PTE_CD (1UL << 4)
+#define _PTE_A (1UL << 5)
+#define _PTE_D (1UL << 6)
+#define _PTE_PS (1UL << 7)
+#define _PTE_PAT (1UL << 7)
+#define _PTE_G (1UL << 8)
+#define _PTE_NX (1UL << 63)
+#define _PTE_X (0)
+#define _PTE_R (0)
+
+#define __MEMGUARD 0xf0f0f0f0f0f0f0f0UL
+
+typedef unsigned long pte_attr_t;
+typedef unsigned long pfn_t;
+
+// always do sign extend on x86_64
+
+#define __index(va) ( (va) & VMS_MASK )
+#define __vaddr(va) \
+ ( (__index(va) ^ ((VMS_MASK + 1) >> 1)) - ((VMS_MASK + 1) >> 1) )
+#define __paddr(pa) ( (pa) & PMS_MASK )
+
+#endif /* __LUNAIX_PT_DEF64_H */
+#endif
\ No newline at end of file
#include <lunaix/spike.h>
#include <lunaix/types.h>
+#ifdef CONFIG_ARCH_I386
#define do_udiv64(n, base) \
({ \
unsigned long __upper, __low, __high, __mod, __base; \
} \
__mod; \
})
+#else
+ #define do_udiv64(n, base) \
+ ({ \
+ n = (n) / (base); \
+ (n) % (base); \
+ })
+#endif
static inline u64_t
udiv64(u64_t n, unsigned int base)
--- /dev/null
+#ifndef __LUNAIX_ARCH_SYSCALL_UTILS_H
+#define __LUNAIX_ARCH_SYSCALL_UTILS_H
+
+#include <lunaix/types.h>
+#include <klibc/string.h>
+
+static inline void
+convert_valist(va_list* ap_ref, sc_va_list syscall_ap)
+{
+#ifdef CONFIG_ARCH_X86_64
+ memcpy(ap_ref, syscall_ap, sizeof(va_list));
+#else
+ *ap_ref = *syscall_ap;
+#endif
+}
+
+#endif /* __LUNAIX_ARCH_SYSCALL_UTILS_H */
--- /dev/null
+#ifndef __LUNAIX_I386_ASM_H
+#define __LUNAIX_I386_ASM_H
+
+#define SEL_INDEX(i) ((i) << 3)
+#define SEL_RPL(rpl) ((rpl) & 0b11)
+
+#define KCODE_SEG (SEL_INDEX(1) | SEL_RPL(0))
+#define UCODE_SEG (SEL_INDEX(2) | SEL_RPL(3))
+
+#ifdef CONFIG_ARCH_I386
+ #define KDATA_SEG (SEL_INDEX(3) | SEL_RPL(0))
+ #define UDATA_SEG (SEL_INDEX(4) | SEL_RPL(3))
+ #define TSS_SEG (SEL_INDEX(5) | SEL_RPL(0))
+
+#else
+ #define KDATA_SEG (SEL_INDEX(3) | SEL_RPL(0))
+ #define UDATA_SEG (SEL_INDEX(4) | SEL_RPL(3))
+ #define TSS_SEG (SEL_INDEX(5) | SEL_RPL(0))
+
+#endif
+
+
+#ifndef __ASM__
+#include <lunaix/types.h>
+
+#define IRQ_TRIG_EDGE 0b0
+#define IRQ_TRIG_LEVEL 0b1
+
+#define IRQ_TYPE_FIXED (0b01 << 1)
+#define IRQ_TYPE_NMI (0b11 << 1)
+#define IRQ_TYPE (0b11 << 1)
+
+#define IRQ_VE_HI (0b1 << 3)
+#define IRQ_VE_LO (0b0 << 3)
+
+#define IRQ_DEFAULT (IRQ_TRIG_EDGE | IRQ_TYPE_FIXED | IRQ_VE_HI)
+
+
+struct x86_intc
+{
+ char* name;
+ void* data;
+
+ void (*irq_attach)(struct x86_intc*,
+ int irq,
+ int iv,
+ cpu_t dest,
+ u32_t flags);
+ void (*notify_eoi)(struct x86_intc*, cpu_t id, int iv);
+};
+
+#ifdef CONFIG_ARCH_X86_64
+
+struct x86_tss
+{
+ u32_t rsvd_1;
+ ptr_t rsps[3];
+ union {
+ struct {
+ ptr_t ist_null;
+ ptr_t valid_ists[7];
+ };
+ ptr_t ists[8];
+ };
+
+ u8_t rsvd_3[12];
+} compact;
+
+struct x86_sysdesc {
+ u64_t lo;
+ u64_t hi;
+} compact;
+
+typedef u64_t x86_segdesc_t;
+
+#else
+
+struct x86_tss
+{
+ u32_t link;
+ u32_t esp0;
+ u16_t ss0;
+ u8_t __padding[94];
+} compact;
+
+struct x86_sysdesc {
+ u32_t lo;
+ u32_t hi;
+} compact;
+
+typedef struct x86_sysdesc x86_segdesc_t;
+
+#endif
+
+#endif
+#endif /* __LUNAIX_I386_ASM_H */
--- /dev/null
+#include <klibc/string.h>
+
+#ifdef CONFIG_ARCH_X86_64
+void*
+memcpy(void* dest, const void* src, unsigned long num)
+{
+ if (!num)
+ return dest;
+
+ asm volatile("movq %1, %%rdi\n"
+ "rep movsb\n" ::"S"(src),
+ "r"(dest),
+ "c"(num)
+ : "rdi", "memory");
+ return dest;
+}
+
+void*
+memset(void* ptr, int value, unsigned long num)
+{
+ asm volatile("movq %1, %%rdi\n"
+ "rep stosb\n" ::"c"(num),
+ "r"(ptr),
+ "a"(value)
+ : "rdi", "memory");
+ return ptr;
+}
+
+#else
+void*
+memcpy(void* dest, const void* src, unsigned long num)
+{
+ if (!num)
+ return dest;
+
+ asm volatile("movl %1, %%edi\n"
+ "rep movsb\n" ::"S"(src),
+ "r"(dest),
+ "c"(num)
+ : "edi", "memory");
+ return dest;
+}
+
+void*
+memset(void* ptr, int value, unsigned long num)
+{
+ asm volatile("movl %1, %%edi\n"
+ "rep stosb\n" ::"c"(num),
+ "r"(ptr),
+ "a"(value)
+ : "edi", "memory");
+ return ptr;
+}
+
+#endif
+
fault->fault_ptep = mkptep_va(VMS_SELF, ptr);
fault->fault_data = ictx->execp->err_code;
- fault->fault_instn = ictx->execp->eip;
+ fault->fault_instn = hart_pc(ictx);
fault->fault_va = ptr;
return true;
#define SEG_CODE_EXRDC 0x0E // Execute/Read, conforming
#define SEG_CODE_EXRDCA 0x0F // Execute/Read, conforming, accessed
+#define BIT64 (SD_64BITS(1) | SD_32BITS(0))
+#define BIT32 (SD_64BITS(0) | SD_32BITS(1))
+
#define SEG_R0_CODE \
SD_TYPE(SEG_CODE_EXRD) | SD_CODE_DATA(1) | SD_DPL(0) | SD_PRESENT(1) | \
- SD_AVL(0) | SD_64BITS(0) | SD_32BITS(1) | SD_4K_GRAN(1)
+ SD_AVL(0) | SD_4K_GRAN(1)
#define SEG_R0_DATA \
SD_TYPE(SEG_DATA_RDWR) | SD_CODE_DATA(1) | SD_DPL(0) | SD_PRESENT(1) | \
- SD_AVL(0) | SD_64BITS(0) | SD_32BITS(1) | SD_4K_GRAN(1)
+ SD_AVL(0) | SD_4K_GRAN(1)
#define SEG_R3_CODE \
SD_TYPE(SEG_CODE_EXRD) | SD_CODE_DATA(1) | SD_DPL(3) | SD_PRESENT(1) | \
- SD_AVL(0) | SD_64BITS(0) | SD_32BITS(1) | SD_4K_GRAN(1)
+ SD_AVL(0) | SD_4K_GRAN(1)
#define SEG_R3_DATA \
SD_TYPE(SEG_DATA_RDWR) | SD_CODE_DATA(1) | SD_DPL(3) | SD_PRESENT(1) | \
- SD_AVL(0) | SD_64BITS(0) | SD_32BITS(1) | SD_4K_GRAN(1)
+ SD_AVL(0) | SD_4K_GRAN(1)
#define SEG_TSS SD_TYPE(9) | SD_DPL(0) | SD_PRESENT(1)
-#define GDT_ENTRY 6
-u64_t _gdt[GDT_ENTRY];
+#ifdef CONFIG_ARCH_X86_64
+
+x86_segdesc_t _gdt[8];
u16_t _gdt_limit = sizeof(_gdt) - 1;
-void
-_set_gdt_entry(u32_t index, u32_t base, u32_t limit, u32_t flags)
+static inline void
+_set_gdt_entry(int index, int dpl, unsigned int flags)
{
- _gdt[index] =
+ u64_t desc = 0;
+ desc |= flags | BIT64;
+ desc |= 0xf << 16;
+ desc = desc << 32;
+ desc |= 0xffff;
+
+ _gdt[index] = desc;
+}
+
+static inline void
+_set_tss(int index, ptr_t base, size_t size)
+{
+ struct x86_sysdesc* tssd;
+ u32_t attr;
+
+ size = size - 1;
+ tssd = (struct x86_sysdesc*)&_gdt[index];
+ tssd->hi = base >> 32;
+
+ attr = SD_4K_GRAN(1) | SD_PRESENT(1) | SD_TYPE(9) | SD_DPL(0);
+ attr |= (SEG_LIM_H(size) << 16);
+
+ tssd->lo = (SEG_BASE_H(base) | attr | SEG_BASE_M(base)) << 32;
+ tssd->lo |= SEG_BASE_L(base) | SEG_LIM_L(size);
+}
+
+#else
+
+x86_segdesc_t _gdt[6];
+u16_t _gdt_limit = sizeof(_gdt) - 1;
+
+static inline void
+_set_gdt_entry(u32_t index, ptr_t base, u32_t limit, u32_t flags)
+{
+ x86_segdesc_t* gdte = &_gdt[index];
+
+ flags |= BIT32;
+
+ gdte->hi =
SEG_BASE_H(base) | flags | SEG_LIM_H(limit) | SEG_BASE_M(base);
- _gdt[index] <<= 32;
- _gdt[index] |= SEG_BASE_L(base) | SEG_LIM_L(limit);
+ gdte->lo |= SEG_BASE_L(base) | SEG_LIM_L(limit);
}
-extern struct x86_tss _tss;
+static inline void
+_set_tss(int index, ptr_t base, size_t size)
+{
+ _set_gdt_entry(index, base, size - 1, SEG_TSS);
+}
+
+#endif
+
void
_init_gdt()
{
+ extern struct x86_tss _tss;
+
+#ifdef CONFIG_ARCH_X86_64
+ _gdt[0] = 0;
+ _set_gdt_entry(1, 0, SEG_R0_CODE); // kernel code
+ _set_gdt_entry(2, 3, SEG_R3_CODE); // user code
+ _set_gdt_entry(3, 0, SEG_R0_DATA); // generic data
+ _set_gdt_entry(4, 4, SEG_R3_DATA); // generic data
+ _set_tss(5, (ptr_t)&_tss, sizeof(_tss));
+#else
_set_gdt_entry(0, 0, 0, 0);
_set_gdt_entry(1, 0, 0xfffff, SEG_R0_CODE);
- _set_gdt_entry(2, 0, 0xfffff, SEG_R0_DATA);
- _set_gdt_entry(3, 0, 0xfffff, SEG_R3_CODE);
+ _set_gdt_entry(2, 0, 0xfffff, SEG_R3_CODE);
+ _set_gdt_entry(3, 0, 0xfffff, SEG_R0_DATA);
_set_gdt_entry(4, 0, 0xfffff, SEG_R3_DATA);
- _set_gdt_entry(5, (u32_t)&_tss, sizeof(struct x86_tss) - 1, SEG_TSS);
+ _set_tss(5, (u32_t)&_tss, sizeof(struct x86_tss) - 1);
+#endif
}
\ No newline at end of file
ptr_t kexec_end = to_kphysical(__kexec_end);
ptr_t aligned_pplist = MAX(ent->start, kexec_end);
+#ifdef CONFIG_ARCH_X86_64
+ aligned_pplist = napot_upaligned(aligned_pplist, L2T_SIZE);
+#else
aligned_pplist = napot_upaligned(aligned_pplist, L0T_SIZE);
+#endif
if (aligned_pplist + pool_size > ent->start + ent->size) {
return 0;
// regardless the actual physical memory size
// anchor the pplist at vmap location (right after kernel)
- memory->pplist = (struct ppage*)VMAP;
+ memory->pplist = (struct ppage*)PMAP;
memory->list_len = ppfn_total;
- pfn_t nhuge = page_count(pool_size, L0T_SIZE);
- pte_t* ptep = mkl0tep_va(VMS_SELF, VMAP);
+ pfn_t nhuge;
+ pte_t* ptep;
+
pte_t pte = mkpte(aligned_pplist, KERNEL_DATA);
-
- vmm_set_ptes_contig(ptep, pte_mkhuge(pte), L0T_SIZE, nhuge);
- tlb_flush_kernel(VMAP);
- // shift the actual vmap start address
+#ifdef CONFIG_ARCH_X86_64
+ nhuge = page_count(pool_size, L2T_SIZE);
+ ptep = mkl2tep_va(VMS_SELF, PMAP);
+ vmm_set_ptes_contig(ptep, pte_mkhuge(pte), L2T_SIZE, nhuge);
+#else
+ nhuge = page_count(pool_size, L0T_SIZE);
+ ptep = mkl0tep_va(VMS_SELF, PMAP);
+
+ // since VMAP and PMAP share same address space
+ // we need to shift VMAP to make room
vmap_set_start(VMAP + nhuge * L0T_SIZE);
+ vmm_set_ptes_contig(ptep, pte_mkhuge(pte), L0T_SIZE, nhuge);
+#endif
+ tlb_flush_kernel(PMAP);
return aligned_pplist;
}
\ No newline at end of file
size_t cnt_wordsz = leaflet_size(new_leaflet) / sizeof(ptr_t);
+#ifdef CONFIG_ARCH_X86_64
+ asm volatile("movq %1, %%rdi\n"
+ "movq %2, %%rsi\n"
+ "rep movsq\n" ::"c"(cnt_wordsz),
+ "r"(dest_va),
+ "r"(src_va)
+ : "memory", "%edi", "%esi");
+
+#else
asm volatile("movl %1, %%edi\n"
"movl %2, %%esi\n"
"rep movsl\n" ::"c"(cnt_wordsz),
"r"(src_va)
: "memory", "%edi", "%esi");
+#endif
+
leaflet_unmount(leaflet);
vunmap(dest_va, new_leaflet);
.type syscall_hndlr, @function
.global syscall_hndlr
syscall_hndlr:
- pushl %ebp
- movl %esp, %ebp
- movl 8(%esp), %ebx // struct hart_state*
+ pushl %ebp
+ movl %esp, %ebp
+ movl 8(%esp), %ebx // struct hart_state*
- addl $4, %ebx
- movl (%ebx), %eax /* eax: call code as well as the return value from syscall */
- cmpl $__SYSCALL_MAX, %eax
- jae 2f
+ addl $4, %ebx
+ movl (%ebx), %eax /* eax: call code as well as the return value from syscall */
+ cmpl $__SYSCALL_MAX, %eax
+ jae 2f
- shll $2, %eax
- addl $syscall_table, %eax
- cmpl $0, (%eax)
- jne 1f
+ shll $2, %eax
+ addl $syscall_table, %eax
+ cmpl $0, (%eax)
+ jne 1f
2:
- neg %eax
- movl %ebp, %esp
- popl %ebp
+ neg %eax
+ movl %ebp, %esp
+ popl %ebp
ret
1:
- pushl %ebx
- pushl 24(%ebx) /* esi - #5 arg */
- pushl 16(%ebx) /* edi - #4 arg */
- pushl 12(%ebx) /* edx - #3 arg */
- pushl 8(%ebx) /* ecx - #2 arg */
- pushl 4(%ebx) /* ebx - #1 arg */
+ pushl %ebx
+ pushl 24(%ebx) /* esi - #5 arg */
+ pushl 16(%ebx) /* edi - #4 arg */
+ pushl 12(%ebx) /* edx - #3 arg */
+ pushl 8(%ebx) /* ecx - #2 arg */
+ pushl 4(%ebx) /* ebx - #1 arg */
- call *(%eax)
+ call *(%eax)
- addl $20, %esp /* remove the parameters from stack */
+ addl $20, %esp /* remove the parameters from stack */
- popl %ebx
- movl %eax, (%ebx) /* save the return value */
+ popl %ebx
+ movl %eax, (%ebx) /* save the return value */
- movl %ebp, %esp
- popl %ebp
+ movl %ebp, %esp
+ popl %ebp
ret
\ No newline at end of file
--- /dev/null
+#define __ASM__
+#include <lunaix/syscall.h>
+#include "sys/interrupt64.S.inc"
+
+.section .data
+ /*
+ 注意,这里的顺序非常重要。每个系统调用在这个地址表里的索引等于其调用号。
+ */
+ syscall_table:
+ 1:
+ .8byte 0
+ .8byte __lxsys_fork /* 1 */
+ .8byte __lxsys_yield
+ .8byte __lxsys_sbrk
+ .8byte __lxsys_brk
+ .8byte __lxsys_getpid /* 5 */
+ .8byte __lxsys_getppid
+ .8byte __lxsys_sleep
+ .8byte __lxsys_exit
+ .8byte __lxsys_wait
+ .8byte __lxsys_waitpid /* 10 */
+ .8byte __lxsys_sigreturn
+ .8byte __lxsys_sigprocmask
+ .8byte __lxsys_sys_sigaction
+ .8byte __lxsys_pause
+ .8byte __lxsys_kill /* 15 */
+ .8byte __lxsys_alarm
+ .8byte __lxsys_sigpending
+ .8byte __lxsys_sigsuspend
+ .8byte __lxsys_open
+ .8byte __lxsys_close /* 20 */
+ .8byte __lxsys_read
+ .8byte __lxsys_write
+ .8byte __lxsys_sys_readdir
+ .8byte __lxsys_mkdir
+ .8byte __lxsys_lseek /* 25 */
+ .8byte __lxsys_geterrno
+ .8byte __lxsys_readlink
+ .8byte __lxsys_readlinkat
+ .8byte __lxsys_rmdir
+ .8byte __lxsys_unlink /* 30 */
+ .8byte __lxsys_unlinkat
+ .8byte __lxsys_link
+ .8byte __lxsys_fsync
+ .8byte __lxsys_dup
+ .8byte __lxsys_dup2 /* 35 */
+ .8byte __lxsys_realpathat
+ .8byte __lxsys_symlink
+ .8byte __lxsys_chdir
+ .8byte __lxsys_fchdir
+ .8byte __lxsys_getcwd /* 40 */
+ .8byte __lxsys_rename
+ .8byte __lxsys_mount
+ .8byte __lxsys_unmount
+ .8byte __lxsys_getxattr
+ .8byte __lxsys_setxattr /* 45 */
+ .8byte __lxsys_fgetxattr
+ .8byte __lxsys_fsetxattr
+ .8byte __lxsys_ioctl
+ .8byte __lxsys_getpgid
+ .8byte __lxsys_setpgid /* 50 */
+ .8byte __lxsys_syslog
+ .8byte __lxsys_sys_mmap
+ .8byte __lxsys_munmap
+ .8byte __lxsys_execve
+ .8byte __lxsys_fstat /* 55 */
+ .8byte __lxsys_pollctl
+ .8byte __lxsys_th_create
+ .8byte __lxsys_th_self
+ .8byte __lxsys_th_exit
+ .8byte __lxsys_th_join /* 60 */
+ .8byte __lxsys_th_kill
+ .8byte __lxsys_th_detach
+ .8byte __lxsys_th_sigmask
+ 2:
+ .rept __SYSCALL_MAX - (2b - 1b) / 8
+ .8byte 0
+ .endr
+
+
+.section .text
+ .type syscall_hndlr, @function
+ .global syscall_hndlr
+ syscall_hndlr:
+ pushq %rbp
+ movq %rsp, %rbp
+ pushq %rbx
+
+ movq %rdi, %rbx // struct hart_state*
+
+ movq irax(%rbx), %rax /* rax: call code as well as the return value from syscall */
+ cmpq $__SYSCALL_MAX, %rax
+ jae 2f
+
+ shlq $3, %rax // %rax * 8
+ movabsq $syscall_table, %r8
+ addq %r8, %rax
+ cmpq $0, (%rax)
+ jne 1f
+ 2:
+ negq %rax
+ popq %rbx
+ movq %rbp, %rsp
+ popq %rbp
+
+ ret
+
+ 1:
+
+ movq irbx(%rbx), %rdi /* rbx -> rdi #1 arg */
+ movq ircx(%rbx), %rsi /* rcx -> rsi #2 arg */
+ movq irdx(%rbx), %rdx /* rdx -> rdx #3 arg */
+ movq irdi(%rbx), %rcx /* rdi -> rcx #4 arg */
+ movq irsi(%rbx), %r8 /* rsi -> r8 #5 arg */
+
+ call *(%rax)
+
+ movq %rax, irax(%rbx) /* save the return value */
+
+ popq %rbx
+ movq %rbp, %rsp
+ popq %rbp
+
+ ret
\ No newline at end of file
--- /dev/null
+#include <lunaix/trace.h>
+
+void
+trace_print_transistion_short(struct hart_state* hstate)
+{
+ trace_log(" trigger: iv=%d, ecause=%p",
+ hart_vector_stamp(hstate),
+ hart_ecause(hstate));
+}
+
+#ifdef CONFIG_ARCH_X86_64
+
+void
+trace_print_transition_full(struct hart_state* hstate)
+{
+ trace_log("hart state transition");
+ trace_log(" vector=%d, ecause=0x%x",
+ hart_vector_stamp(hstate),
+ hart_ecause(hstate));
+
+ trace_log(" rflags=0x%016lx", hstate->execp->rflags);
+ trace_log(" sp=0x%016lx, seg_sel=0x%04x",
+ hstate->execp->rsp,
+ hstate->execp->ss);
+ trace_log(" ip=0x%016lx, seg_sel=0x%04x",
+ hstate->execp->rip,
+ hstate->execp->cs);
+}
+
+void
+trace_dump_state(struct hart_state* hstate)
+{
+ struct regcontext* rh = &hstate->registers;
+ struct exec_param* ep = hstate->execp;
+ trace_log("hart state dump (depth=%d)", hstate->depth);
+ trace_log(" rax=0x%016lx, rbx=0x%016lx",
+ rh->rax, rh->rbx);
+ trace_log(" rcx=0x%016lx, rdx=0x%016lx",
+ rh->rcx, rh->rdx);
+ trace_log(" rdi=0x%016lx, rsi=0x%016lx",
+ rh->rdi, rh->rsi);
+
+ trace_log(" r8=0x%016lx, r9=0x%016lx",
+ rh->r8, rh->r9);
+ trace_log(" r10=0x%016lx, r11=0x%016lx",
+ rh->r10, rh->r11);
+ trace_log(" r12=0x%016lx, r13=0x%016lx",
+ rh->r12, rh->r13);
+ trace_log(" r14=0x%016lx, r15=0x%016lx",
+ rh->r14, rh->r15);
+
+ trace_log(" cs=0x%04x, rip=0x%016lx",
+ ep->cs, ep->rip);
+ trace_log(" ss=0x%04x, rsp=0x%016lx",
+ ep->ss, ep->rsp);
+ trace_log(" rflags=0x%016lx",
+ ep->rflags);
+}
+
+#else
+
+void
+trace_print_transition_full(struct hart_state* hstate)
+{
+ trace_log("hart state transition");
+ trace_log(" vector=%d, ecause=0x%x",
+ hart_vector_stamp(hstate),
+ hart_ecause(hstate));
+ trace_log(" eflags=0x%x", hstate->execp->eflags);
+ trace_log(" sp=%p, [seg_sel=0x%04x]",
+ hstate->execp->esp,
+ hstate->execp->ss);
+ trace_log(" ip=%p, seg_sel=0x%04x",
+ hstate->execp->eip,
+ hstate->execp->cs);
+}
+
+void
+trace_dump_state(struct hart_state* hstate)
+{
+ struct regcontext* rh = &hstate->registers;
+ struct exec_param* ep = hstate->execp;
+ trace_log("hart state dump (depth=%d)", hstate->depth);
+ trace_log(" eax=0x%08x, ebx=0x%08x, ecx=0x%08x",
+ rh->eax, rh->ebx, rh->ecx);
+ trace_log(" edx=0x%08x, ebp=0x%08x",
+ rh->edx, rh->ebp);
+ trace_log(" ds=0x%04x, edi=0x%08x",
+ rh->ds, rh->edi);
+ trace_log(" es=0x%04x, esi=0x%08x",
+ rh->es, rh->esi);
+ trace_log(" fs=0x%04x, gs=0x%x",
+ rh->fs, rh->gs);
+ trace_log(" cs=0x%04x, ip=0x%08x",
+ ep->cs, ep->eip);
+ trace_log(" [ss=0x%04x],sp=0x%08x",
+ ep->ss, ep->esp);
+ trace_log(" eflags=0x%08x",
+ ep->eflags);
+}
+
+#endif
\ No newline at end of file
size_t entry_n = (rsdt->header.length - sizeof(acpi_sdthdr_t)) >> 2;
for (size_t i = 0; i < entry_n; i++) {
- acpi_sdthdr_t* sdthdr =
- (acpi_sdthdr_t*)((acpi_apic_t**)&(rsdt->entry))[i];
+ acpi_sdthdr_t* sdthdr = __acpi_sdthdr(rsdt->entry[i]);
switch (sdthdr->signature) {
case ACPI_MADT_SIG:
- madt_parse((acpi_madt_t*)sdthdr, ctx);
+ madt_parse(__acpi_madt(sdthdr), ctx);
break;
case ACPI_FADT_SIG:
// FADT just a plain structure, no need to parse.
- ctx->fadt = *(acpi_fadt_t*)sdthdr;
+ ctx->fadt = *__acpi_fadt(sdthdr);
break;
case ACPI_MCFG_SIG:
mcfg_parse(sdthdr, ctx);
size_t so_idx = 0;
while (ics_start < ics_end) {
- acpi_ics_hdr_t* entry = (acpi_ics_hdr_t*)ics_start;
+ acpi_ics_hdr_t* entry = __acpi_ics_hdr(ics_start);
switch (entry->type) {
case ACPI_MADT_LAPIC:
- toc->madt.apic = (acpi_apic_t*)entry;
+ toc->madt.apic = __acpi_apic(entry);
break;
case ACPI_MADT_IOAPIC:
- toc->madt.ioapic = (acpi_ioapic_t*)entry;
+ toc->madt.ioapic = __acpi_ioapic(entry);
break;
case ACPI_MADT_INTSO: {
- acpi_intso_t* intso_tbl = (acpi_intso_t*)entry;
+ acpi_intso_t* intso_tbl = __acpi_intso(entry);
toc->madt.irq_exception[intso_tbl->source] = intso_tbl;
break;
}
void
mcfg_parse(acpi_sdthdr_t* mcfg, acpi_context* toc)
{
- size_t alloc_num = (mcfg->length - sizeof(acpi_sdthdr_t) - 8) /
- sizeof(struct acpi_mcfg_alloc);
+ size_t alloc_num = (mcfg->length - sizeof(acpi_sdthdr_t) - 8);
+ alloc_num = alloc_num / sizeof(struct acpi_mcfg_alloc);
+
struct acpi_mcfg_alloc* allocs =
(struct acpi_mcfg_alloc*)((ptr_t)mcfg + (sizeof(acpi_sdthdr_t) + 8));
#include <lunaix/owloysius.h>
#include <lunaix/status.h>
-#include <sys/mm/mempart.h>
+#include <sys/mm/pagetable.h>
#include <hal/serial.h>
#include <hal/term.h>
static int
__serial_read_page(struct device* dev, void* buf, off_t fpos)
{
- return serial_readbuf(serial_device(dev), (u8_t*)buf, MEM_PAGE);
+ return serial_readbuf(serial_device(dev), (u8_t*)buf, PAGE_SIZE);
}
static int
static int
__serial_write_page(struct device* dev, void* buf, off_t fpos)
{
- return serial_writebuf(serial_device(dev), (u8_t*)buf, MEM_PAGE);
+ return serial_writebuf(serial_device(dev), (u8_t*)buf, PAGE_SIZE);
}
static int
#define UART_rDLM 1
#define UART_INTRX 0x1
-#define UART_DLAB (1 << 7)
#define UART_LOOP (1 << 4)
#define UART_rIE_ERBFI 1
#define UART_rLC_PAREN (1 << 3)
#define UART_rLC_PAREVN (1 << 4)
#define UART_rLC_SETBRK (1 << 6)
+#define UART_rLC_DLAB (1 << 7)
#define UART_rLS_THRE (1 << 5)
#define UART_rLS_DR 1
{
u32_t rlc = uart->read_reg(uart, UART_rLC);
- uart->write_reg(uart, UART_rLC, UART_DLAB | rlc);
+ uart->write_reg(uart, UART_rLC, UART_rLC_DLAB | rlc);
u8_t ls = (div & 0xff), ms = (div & 0xff00) >> 8;
uart->write_reg(uart, UART_rLS, ls);
uart->write_reg(uart, UART_rMS, ms);
- uart->write_reg(uart, UART_rLC, rlc & ~UART_DLAB);
+ uart->write_reg(uart, UART_rLC, rlc & ~UART_rLC_DLAB);
return 0;
}
return RXTX_DONE;
}
+#define UART_LCR_RESET \
+ (UART_rLC_STOPB | \
+ UART_rLC_PAREN | \
+ UART_rLC_PAREVN | \
+ UART_rLC_DLAB | 0b11)
+
static void
uart_set_control_mode(struct uart16550* uart, tcflag_t cflags)
{
uart->cntl_save.rie |= (!!(cflags & _CREAD)) * UART_rIE_ERBFI;
uart_setie(uart);
- uart->cntl_save.rlc &= ~(UART_rLC_STOPB | UART_rLC_PAREN | UART_rLC_PAREVN | 0b11);
+ uart->cntl_save.rlc &= ~UART_LCR_RESET;
uart->cntl_save.rlc |= (!!(cflags & _CSTOPB)) * UART_rLC_STOPB;
uart->cntl_save.rlc |= (!!(cflags & _CPARENB)) * UART_rLC_PAREN;
uart->cntl_save.rlc |= (!(cflags & _CPARODD)) * UART_rLC_PAREVN;
u8_t time_info[3];
u16_t boot_arch;
} ACPI_TABLE_PACKED acpi_fadt_t;
+#define __acpi_fadt(acpi_ptr) ((acpi_fadt_t*)__ptr(acpi_ptr))
// TODO: FADT parser & support
u8_t type;
u8_t length;
} ACPI_TABLE_PACKED acpi_ics_hdr_t;
+#define __acpi_ics_hdr(acpi_ptr) ((acpi_ics_hdr_t*)__ptr(acpi_ptr))
/**
* @brief ACPI Processor Local APIC Structure (PLAS)
u8_t apic_id;
u32_t flags;
} ACPI_TABLE_PACKED acpi_apic_t;
+#define __acpi_apic(acpi_ptr) ((acpi_apic_t*)__ptr(acpi_ptr))
/**
* @brief ACPI IO APIC Structure (IOAS)
// for a slave IOAPIC)
u32_t gis_offset;
} ACPI_TABLE_PACKED acpi_ioapic_t;
+#define __acpi_ioapic(acpi_ptr) ((acpi_ioapic_t*)__ptr(acpi_ptr))
/**
* @brief ACPI Interrupt Source Override (INTSO)
u32_t gsi;
u16_t flags;
} ACPI_TABLE_PACKED acpi_intso_t;
+#define __acpi_intso(acpi_ptr) ((acpi_intso_t*)__ptr(acpi_ptr))
typedef struct
{
acpi_sdthdr_t header;
- void* apic_addr;
+ u32_t apic_addr;
u32_t flags;
// Here is a bunch of packed ICS reside here back-to-back.
} ACPI_TABLE_PACKED acpi_madt_t;
+#define __acpi_madt(acpi_ptr) ((acpi_madt_t*)__ptr(acpi_ptr))
typedef struct
{
- void* apic_addr;
+ u32_t apic_addr;
acpi_apic_t* apic;
acpi_ioapic_t* ioapic;
acpi_intso_t** irq_exception;
u32_t vendor_id;
u32_t vendor_rev;
} ACPI_TABLE_PACKED acpi_sdthdr_t;
+#define __acpi_sdthdr(acpi_ptr) ((acpi_sdthdr_t*)__ptr(acpi_ptr))
typedef struct acpi_rsdt
{
acpi_sdthdr_t header;
- acpi_sdthdr_t* entry;
+ u32_t entry[0];
} ACPI_TABLE_PACKED acpi_rsdt_t;
#endif /* __LUNAIX_ACPI_SDT_H */
#ifndef __LUNAIX_IAUTILS_H
#define __LUNAIX_IAUTILS_H
-char* itoa(int value, char* str, int base);
+char* itoa(long value, char* str, int base);
#endif /* __LUNAIX_IAUTILS_H */
u32_t ent_size;
u32_t ent_cksum;
// reserved start here
-} PACKED;
+} compact;
struct gpt_entry
{
u64_t end_lba;
u64_t attr_flags;
char name[72];
-} PACKED;
+} compact;
int
blkpart_probegpt(struct device* master);
boot_end(struct boot_handoff*);
void
-boot_cleanup();
+boot_begin_arch_reserve(struct boot_handoff*);
+
+void
+boot_clean_arch_reserve(struct boot_handoff*);
static inline bool
free_memregion(struct boot_mmapent* mmapent)
#define unreachable __builtin_unreachable()
#define no_inline __attribute__((noinline))
+#define defualt weak
+
#define clz(bits) __builtin_clz(bits)
#define sadd_overflow(a, b, of) __builtin_sadd_overflow(a, b, of)
#define umul_overflow(a, b, of) __builtin_umul_overflow(a, b, of)
#define cacheline_align align(cacheline_size)
#define export_symbol(domain, namespace, symbol)\
- typeof(symbol)* must_emit __SYMEXPORT_Z##domain##_N##namespace##_S##symbol = &(symbol)
+ typeof(symbol)* must_emit __SYMEXPORT_Z##domain##_N##namespace##_S##symbol \
+ = &(symbol)
inline static void noret
spin()
--- /dev/null
+/**
+ * @file elf.h
+ * @author Lunaixsky (lunaxisky@qq.com)
+ * @brief
+ * @version 0.1
+ * @date 2024-07-05
+ *
+ * Define generic structure that described in Executable and Linking Format
+ * specification.
+ *
+ * Define interface on manipulate such structure
+ *
+ * @copyright Copyright (c) 2024
+ *
+ */
+
+#ifndef __LUNAIX_ELF32_H
+#define __LUNAIX_ELF32_H
+
+#include <lunaix/types.h>
+#include <sys/exebi/elf.h>
+
+#define ET_EXEC 2
+#define ET_DYN 3
+
+#define PT_LOAD 1
+#define PT_INTERP 3
+
+#define PF_X 0x1
+#define PF_W 0x2
+#define PF_R 0x4
+
+#define EV_CURRENT 1
+
+// [0x7f, 'E', 'L', 'F']
+#define ELFMAGIC_LE 0x464c457fU
+
+#define EI_CLASS 4
+#define EI_DATA 5
+
+#define NO_LOADER 0
+#define DEFAULT_LOADER "usr/ld"
+
+struct elf_ehdr;
+struct elf_phdr;
+
+struct elf
+{
+ const void* elf_file;
+ struct elf_ehdr eheader;
+ struct elf_phdr* pheaders;
+};
+
+#define declare_elf32(elf, elf_vfile) \
+ struct elf elf = { .elf_file = elf_vfile, .pheaders = (void*)0 }
+
+int
+elf_check_exec(const struct elf* elf, int type);
+
+int
+elf_check_arch(const struct elf* elf);
+
+int
+elf_open(struct elf* elf, const char* path);
+
+int
+elf_openat(struct elf* elf, void* elf_vfile);
+
+int
+elf_static_linked(const struct elf* elf);
+
+int
+elf_close(struct elf* elf);
+
+/**
+ * @brief Try to find the PT_INTERP section. If found, copy it's content to
+ * path_out
+ *
+ * @param elf Opened elf32 descriptor
+ * @param path_out
+ * @param len size of path_out buffer
+ * @return int
+ */
+int
+elf_find_loader(const struct elf* elf, char* path_out, size_t len);
+
+int
+elf_read_ehdr(struct elf* elf);
+
+int
+elf_read_phdr(struct elf* elf);
+
+/**
+ * @brief Estimate how much memeory will be acquired if we load all loadable
+ * sections.、
+ *
+ * @param elf
+ * @return size_t
+ */
+size_t
+elf_loadable_memsz(const struct elf* elf);
+
+#define SIZE_EHDR sizeof(struct elf_ehdr)
+#define SIZE_PHDR sizeof(struct elf_phdr)
+
+#endif /* __LUNAIX_ELF32_H */
+++ /dev/null
-#ifndef __LUNAIX_ELF32_H
-#define __LUNAIX_ELF32_H
-
-#include <lunaix/types.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_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
-
-#define NO_LOADER 0
-#define DEFAULT_LOADER "usr/ld"
-
-struct elf32_ehdr
-{
- u8_t 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;
-};
-
-struct elf32
-{
- const void* elf_file;
- struct elf32_ehdr eheader;
- struct elf32_phdr* pheaders;
-};
-
-#define declare_elf32(elf, elf_vfile) \
- struct elf32 elf = { .elf_file = elf_vfile, .pheaders = (void*)0 }
-
-int
-elf32_check_exec(const struct elf32* elf, int type);
-
-int
-elf32_check_arch(const struct elf32* elf);
-
-int
-elf32_open(struct elf32* elf, const char* path);
-
-int
-elf32_openat(struct elf32* elf, void* elf_vfile);
-
-int
-elf32_static_linked(const struct elf32* elf);
-
-int
-elf32_close(struct elf32* elf);
-
-/**
- * @brief Try to find the PT_INTERP section. If found, copy it's content to
- * path_out
- *
- * @param elf Opened elf32 descriptor
- * @param path_out
- * @param len size of path_out buffer
- * @return int
- */
-int
-elf32_find_loader(const struct elf32* elf, char* path_out, size_t len);
-
-int
-elf32_read_ehdr(struct elf32* elf);
-
-int
-elf32_read_phdr(struct elf32* elf);
-
-/**
- * @brief Estimate how much memeory will be acquired if we load all loadable
- * sections.、
- *
- * @param elf
- * @return size_t
- */
-size_t
-elf32_loadable_memsz(const struct elf32* elf);
-
-#define SIZE_EHDR sizeof(struct elf32_ehdr)
-#define SIZE_PHDR sizeof(struct elf32_phdr)
-
-#endif /* __LUNAIX_ELF32_H */
#include <lunaix/process.h>
#include <lunaix/types.h>
+#define MAX_PARAM_LEN 1024
+#define MAX_PARAM_SIZE 4096
+
#define MAX_VAR_PAGES 8
#define DEFAULT_HEAP_PAGES 16
-struct exec_context;
-
struct load_context
{
- struct exec_container* container;
+ struct exec_host* container;
ptr_t base;
ptr_t end;
ptr_t mem_sz;
ptr_t entry;
};
-struct exec_container
+struct exec_arrptr
+{
+ unsigned int len;
+ unsigned int size;
+ ptr_t raw;
+ ptr_t copied;
+};
+
+
+struct exec_host
{
struct proc_info* proc;
ptr_t vms_mnt;
struct load_context exe;
- // argv prependums
- const char* argv_pp[2];
- const char** argv;
- const char** envp;
+ struct exec_arrptr argv;
+ struct exec_arrptr envp;
ptr_t stack_top;
char** envp;
} compact;
-#ifndef __USR_WRAPPER__
+int
+exec_arch_prepare_entry(struct thread* thread, struct exec_host* container);
int
-exec_load_byname(struct exec_container* container, const char* filename);
+exec_load_byname(struct exec_host* container, const char* filename);
int
-exec_load(struct exec_container* container, struct v_file* executable);
+exec_load(struct exec_host* container, struct v_file* executable);
int
exec_kexecve(const char* filename, const char* argv[], const char* envp[]);
void
-exec_init_container(struct exec_container* param,
+exec_init_container(struct exec_host* param,
struct thread* thread,
ptr_t vms,
const char** argv,
const char** envp);
-#endif
-
#endif /* __LUNAIX_LOADER_H */
u8_t type;
u8_t std_id[5]; // CD001
u8_t version;
-} PACKED;
+} compact;
struct iso_vol_boot
{
u8_t sys_id[32];
u8_t boot_id[32];
u8_t reserved; // align to data line width
-} PACKED;
+} compact;
struct iso_datetime
{
u8_t sec[2];
u8_t ms[2];
u8_t gmt;
-} PACKED;
+} compact;
// 32bits both-byte-order integer
typedef struct iso_bbo32
{
u32_t le; // little-endian
u32_t be; // big-endian
-} PACKED iso_bbo32_t;
+} compact iso_bbo32_t;
// 16bits both-byte-order integer
typedef struct iso_bbo16
{
u16_t le; // little-endian
u16_t be; // big-endian
-} PACKED iso_bbo16_t;
+} compact iso_bbo16_t;
// (8.4) Describe a primary volume space
struct iso_vol_primary
struct iso_datetime ex_time; // expiration
struct iso_datetime ef_time; // effective
u8_t fstruct_ver; // file structure version, don't care!
-} PACKED; // size 1124
+} compact; // size 1124
// Layout for Supplementary Vol. is almost identical to primary vol.
// We ignore it for now. (see section 8.5, table 6)
u8_t part_id[32];
iso_bbo32_t part_addr;
iso_bbo32_t part_size;
-} PACKED;
+} compact;
// (6.10.4) MDU with variable record
struct iso_var_mdu
{
u8_t len;
u8_t content[0];
-} PACKED;
+} compact;
struct iso_datetime2
{
u8_t min;
u8_t sec;
u8_t gmt;
-} PACKED;
+} compact;
// (9.1) Directory Record [Embedded into Variable MDU]
struct iso_drecord
u8_t gap_sz; // size of gap if FU is interleaved.
iso_bbo16_t vol_seq;
struct iso_var_mdu name;
-} PACKED;
+} compact;
struct iso_xattr
{
u8_t payload[0];
// There is also a escape sequence after payload,
// It however marked as optional, hence we ignore it.
-} PACKED;
+} compact;
///
/// -------- IEEE P1281 SUSP ---------
u16_t signature;
u8_t length;
u8_t version;
-} PACKED;
+} compact;
struct isosu_er
{
u8_t src_len;
u8_t ext_ver;
u8_t id_des_src[0];
-} PACKED;
+} compact;
///
/// -------- Rock Ridge Extension --------
iso_bbo32_t uid;
iso_bbo32_t gid;
iso_bbo32_t sn;
-} PACKED;
+} compact;
struct isorr_pn
{
struct isosu_base header;
iso_bbo32_t dev_hi;
iso_bbo32_t dev_lo;
-} PACKED;
+} compact;
struct isorr_sl
{
struct isosu_base header;
u8_t flags;
char symlink[0];
-} PACKED;
+} compact;
struct isorr_nm
{
struct isosu_base header;
u8_t flags;
char name[0];
-} PACKED;
+} compact;
struct isorr_tf
{
struct isosu_base header;
u8_t flags;
char times[0];
-} PACKED;
+} compact;
///
/// -------- VFS integration ---------
#include <lunaix/types.h>
-#define twimap_index(twimap, type) ((type)((twimap)->index))
-#define twimap_data(twimap, type) ((type)((twimap)->data))
+#define twimap_index(twimap, type) ((type)__ptr((twimap)->index))
+#define twimap_data(twimap, type) ((type)__ptr((twimap)->data))
extern struct v_file_ops twimap_file_ops;
// mapped file offset
off_t foff;
// mapped file length
- u32_t flen; // XXX it seems that we don't need this actually..
ptr_t start;
ptr_t end;
u32_t attr;
+ size_t flen;
void** index; // fast reference, to accelerate access to this very region.
struct proc_mm* pvms; // process vm
off_t offset; // mapped file offset
size_t mlen; // mapped memory length
+ size_t flen; // mapped file length
u32_t proct; // protections
u32_t flags; // other options
u32_t type; // region type
typedef struct __pte pte_t;
+#include <sys/mm/mempart.h>
#include <sys/mm/pagetable.h>
#include <sys/cpu.h>
-#define _LnTEP_AT(vm_mnt, sz) ( ((vm_mnt) | L0T_MASK) & ~(sz) )
-#define _L0TEP_AT(vm_mnt) ( ((vm_mnt) | L0T_MASK) & ~LFT_MASK )
-#define _L1TEP_AT(vm_mnt) ( ((vm_mnt) | L0T_MASK) & ~L3T_MASK )
-#define _L2TEP_AT(vm_mnt) ( ((vm_mnt) | L0T_MASK) & ~L2T_MASK )
-#define _L3TEP_AT(vm_mnt) ( ((vm_mnt) | L0T_MASK) & ~L1T_MASK )
-#define _LFTEP_AT(vm_mnt) ( ((vm_mnt) | L0T_MASK) & ~L0T_MASK )
+#define VMS_SELF VMS_SELF_MOUNT
+#define VMS_SELF_L0TI (__index(VMS_SELF_MOUNT) / L0T_SIZE)
+
+#define _LnT_LEVEL_SIZE(n) ( L##n##T_SIZE / PAGE_SIZE )
+#define _LFTEP_SELF ( __index(VMS_SELF) )
+#define _L3TEP_SELF ( _LFTEP_SELF | (_LFTEP_SELF / _LnT_LEVEL_SIZE(3)) )
+#define _L2TEP_SELF ( _L3TEP_SELF | (_LFTEP_SELF / _LnT_LEVEL_SIZE(2)) )
+#define _L1TEP_SELF ( _L2TEP_SELF | (_LFTEP_SELF / _LnT_LEVEL_SIZE(1)) )
+#define _L0TEP_SELF ( _L1TEP_SELF | (_LFTEP_SELF / _LnT_LEVEL_SIZE(0)) )
+
+#define _L0TEP_AT(vm_mnt) ( ((vm_mnt) | (_L0TEP_SELF & L0T_MASK)) )
+#define _L1TEP_AT(vm_mnt) ( ((vm_mnt) | (_L1TEP_SELF & L0T_MASK)) )
+#define _L2TEP_AT(vm_mnt) ( ((vm_mnt) | (_L2TEP_SELF & L0T_MASK)) )
+#define _L3TEP_AT(vm_mnt) ( ((vm_mnt) | (_L3TEP_SELF & L0T_MASK)) )
+#define _LFTEP_AT(vm_mnt) ( ((vm_mnt) | (_LFTEP_SELF & L0T_MASK)) )
#define _VM_OF(ptep) ( (ptr_t)(ptep) & ~L0T_MASK )
#define _VM_PFN_OF(ptep) ( ((ptr_t)(ptep) & L0T_MASK) / sizeof(pte_t) )
-#define VMS_SELF ( ~L0T_MASK & VMS_MASK )
#define __LnTI_OF(ptep, n)\
- (_VM_PFN_OF(ptep) * LFT_SIZE / L##n##T_SIZE)
+ ( __index(_VM_PFN_OF(ptep) * LFT_SIZE / L##n##T_SIZE) )
#define __LnTEP(ptep, va, n)\
- ( (pte_t*)_L##n##TEP_AT(_VM_OF(ptep)) + (((va) & VMS_MASK) / L##n##T_SIZE) )
+ ( (pte_t*)_L##n##TEP_AT(_VM_OF(ptep)) + (__index(va) / L##n##T_SIZE) )
#define __LnTEP_OF(ptep, n)\
( (pte_t*)_L##n##TEP_AT(_VM_OF(ptep)) + __LnTI_OF(ptep, n))
#define _has_LnT(n) (L##n##T_SIZE != LFT_SIZE)
#define LnT_ENABLED(n) _has_LnT(n)
-#define ptep_with_level(ptep, lvl_size) \
- ({ \
- ptr_t __p = _LnTEP_AT(_VM_OF(ptep), lvl_size); \
- ((ptr_t)(ptep) & __p) == __p; \
- })
-
extern pte_t
alloc_kpage_at(pte_t* ptep, pte_t pte, int order);
static inline ptr_t
ptep_va(pte_t* ptep, size_t lvl_size)
{
- return ((ptr_t)ptep) / sizeof(pte_t) * lvl_size;
+ return __vaddr(ptep_pfn(ptep) * lvl_size);
}
static inline ptr_t
ptep_vm_mnt(pte_t* ptep)
{
- return _VM_OF(ptep);
+ return __vaddr(_VM_OF(ptep));
}
/**
static inline pfn_t
pfn(ptr_t addr) {
- return (addr / PAGE_SIZE) & VMS_MASK;
+ return __index(addr) / PAGE_SIZE;
}
static inline size_t
static inline ptr_t
page_addr(ptr_t pfn) {
- return pfn * PAGE_SIZE;
+ return __vaddr(pfn * PAGE_SIZE);
}
static inline ptr_t
static inline pfn_t
pfn_at(ptr_t va, size_t lvl_size) {
- return va / lvl_size;
+ return __index(va) / lvl_size;
}
return mkl0tep(mkptep_va(mnt, va));
}
+static inline pte_t*
+mkl1tep_va(ptr_t mnt, ptr_t va)
+{
+ return mkl1tep(mkptep_va(mnt, va));
+}
+
+static inline pte_t*
+mkl2tep_va(ptr_t mnt, ptr_t va)
+{
+ return mkl2tep(mkptep_va(mnt, va));
+}
+
+static inline pte_t*
+mkl3tep_va(ptr_t mnt, ptr_t va)
+{
+ return mkl3tep(mkptep_va(mnt, va));
+}
+
static inline bool
pt_last_level(int level)
{
static inline ptr_t
va_mntpoint(ptr_t va)
{
- return _VM_OF(va);
+ return __vaddr(_VM_OF(va));
}
-static inline ptr_t
-va_actual(ptr_t va)
+static inline unsigned int
+va_level_index(ptr_t va, size_t lvl_size)
+{
+ return (va / lvl_size) & _PAGE_LEVEL_MASK;
+}
+
+static inline bool
+l0tep_implie(pte_t* ptep, ptr_t addr)
+{
+ return ptep_va(ptep, L0T_SIZE) == __vaddr(addr);
+}
+
+static inline bool
+is_ptep(ptr_t addr)
+{
+ ptr_t mnt = va_mntpoint(addr);
+ return mnt == VMS_MOUNT_1 || mnt == VMS_SELF;
+}
+
+static inline bool
+vmnt_packed(pte_t* ptep)
+{
+ return is_ptep(__ptr(ptep));
+}
+
+static inline bool
+active_vms(ptr_t vmnt)
+{
+ return vmnt == VMS_SELF;
+}
+
+static inline bool
+l0tep_impile_vmnts(pte_t* ptep)
{
- return page_addr(_VM_OF(va) ^ va);
+ return l0tep_implie(ptep, VMS_SELF) ||
+ l0tep_implie(ptep, VMS_MOUNT_1);
}
#endif /* __LUNAIX_PAGETABLE_H */
{
/*
Any change to *critical section*, including layout, size
- must be reflected in arch/i386/interrupt.S.inc to avoid
+ must be reflected in arch/x86/interrupt.S.inc to avoid
disaster!
*/
struct
#ifndef __LUNAIX_SIGNAL_H
#define __LUNAIX_SIGNAL_H
+#include <lunaix/types.h>
#include <usr/lunaix/signal_defs.h>
#define _SIG_NUM 16
#include <lunaix/process.h>
#include <lunaix/syscall.h>
+#include <sys/syscall_utils.h>
-#define DO_STATUS(errno) SYSCALL_ESTATUS(syscall_result(errno))
-#define DO_STATUS_OR_RETURN(errno) ({ errno < 0 ? DO_STATUS(errno) : errno; })
+#define DO_STATUS(errno) SYSCALL_ESTATUS(syscall_result(errno))
+#define DO_STATUS_OR_RETURN(errno) \
+ ({ errno < 0 ? DO_STATUS(errno) : errno; })
#endif /* __LUNAIX_SYSCALL_UTILS_H */
#include <stdarg.h>
#include <usr/lunaix/types.h>
-#define PACKED __attribute__((packed))
-
// TODO: WTERMSIG
// TODO: replace the integer type with these. To make thing more portable.
typedef unsigned char u8_t;
typedef unsigned short u16_t;
typedef unsigned int u32_t;
-typedef unsigned long long u64_t;
typedef unsigned long ptr_t;
typedef unsigned long reg_t;
+#ifndef CONFIG_ARCH_BITS_64
+typedef unsigned long long u64_t;
+#else
+typedef unsigned long u64_t;
+#endif
+
typedef int pid_t;
typedef signed long ssize_t;
(ptr) ? (type*)((char*)__mptr - offsetof(type, member)) : 0; \
})
+#define __ptr(val) ((ptr_t)(val))
+
+typedef va_list* sc_va_list;
+
#endif /* __LUNAIX_TYPES_H */
#define MS_INVALIDATE 0x4
#define MS_INVALIDATE_ALL 0x8
+struct usr_mmap_param
+{
+ void* addr;
+ unsigned long length;
+ int proct;
+ int flags;
+ int fd;
+ unsigned long offset;
+};
+
#endif /* __LUNAIX_MANN_FLAGS_H */
#define __SYSCALL_th_detach 62
#define __SYSCALL_th_sigmask 63
-#define __SYSCALL_MAX 0x100
+#define __SYSCALL_MAX 0x200
#endif /* __LUNAIX_SYSCALLID_H */
#include "types.h"
-struct uthread_info {
- void* th_stack_top;
- size_t th_stack_sz;
+struct uthread_param {
+ void* th_handler;
+ void* arg1;
};
#endif /* __LUNAIX_USR_THREADS_H */
-include os.mkinc
include toolchain.mkinc
+include lunabuild.mkinc
-include .builder/lbuild.mkinc
+include $(lbuild_mkinc)
kbin_dir := $(BUILD_DIR)
kbin := $(BUILD_NAME)
ksrc_deps := $(addsuffix .d,$(_LBUILD_SRCS))
khdr_opts := $(addprefix -include ,$(_LBUILD_HDRS))
kinc_opts := $(addprefix -I,$(_LBUILD_INCS))
-config_h += -include.builder/configs.h
+config_h += -include $(lbuild_config_h)
tmp_kbin := $(BUILD_DIR)/tmpk.bin
ksymtable := lunaix_ksyms.o
+klinking := link/lunaix.ld
CFLAGS += $(khdr_opts) $(kinc_opts) $(config_h) -MMD -MP
-include $(ksrc_deps)
-%.S.o: %.S kernel.mk
+all_linkable = $(filter-out $(klinking),$(1))
+
+%.S.o: %.S $(khdr_files) kernel.mk
$(call status_,AS,$<)
@$(CC) $(CFLAGS) -c $< -o $@
$(call status_,CC,$<)
@$(CC) $(CFLAGS) -c $< -o $@
-$(tmp_kbin): $(ksrc_objs)
+
+$(klinking): link/lunaix.ldx
+ $(call status_,PP,$<)
+ @$(CC) $(CFLAGS) -x c -E -P $< -o $@
+
+
+$(tmp_kbin): $(klinking) $(ksrc_objs)
$(call status_,LD,$@)
- @$(CC) -T link/linker.ld $(config_h) $(LDFLAGS) -o $@ $^
+
+ @$(CC) -T $(klinking) $(config_h) $(LDFLAGS) -o $@ \
+ $(call all_linkable,$^)
+
$(ksymtable): $(tmp_kbin)
$(call status_,KSYM,$@)
@scripts/gen_ksymtable.sh DdRrTtAGg $< > .lunaix_ksymtable.S
+
@$(CC) $(CFLAGS) -c .lunaix_ksymtable.S -o $@
+
.PHONY: __do_relink
-__do_relink: $(ksrc_objs) $(ksymtable)
+__do_relink: $(klinking) $(ksrc_objs) $(ksymtable)
$(call status_,LD,$(kbin))
- @$(CC) -T link/linker.ld $(config_h) $(LDFLAGS) -o $(kbin) $^
+
+ @$(CC) -T $(klinking) $(config_h) $(LDFLAGS) -o $(kbin) \
+ $(call all_linkable,$^)
+
@rm $(tmp_kbin)
+
.PHONY: all
all: __do_relink
+
clean:
@rm -f $(ksrc_objs)
@rm -f $(ksrc_deps)
+ @rm -f $(klinking)
@rm -f .lunaix_ksymtable.S $(ksymtable)
\ No newline at end of file
boot_begin(struct boot_handoff* bhctx)
{
bhctx->prepare(bhctx);
-
- // Identity-map the first 3GiB address spaces
- pte_t* ptep = mkl0tep(mkptep_va(VMS_SELF, 0));
- pte_t pte = mkpte_prot(KERNEL_DATA);
- size_t count = page_count(KERNEL_RESIDENT, L0T_SIZE);
-
- vmm_set_ptes_contig(ptep, pte_mkhuge(pte), L0T_SIZE, count);
+ boot_begin_arch_reserve(bhctx);
+
// 将内核占据的页,包括前1MB,hhk_init 设为已占用
size_t pg_count = leaf_count(to_kphysical(__kexec_end));
pmm_onhold_range(0, pg_count);
}
bhctx->release(bhctx);
-}
-/**
- * @brief Clean up the boot stage code and data
- *
- */
-void
-boot_cleanup()
-{
- pte_t* ptep = mkl0tep(mkptep_va(VMS_SELF, 0));
- size_t count = page_count(KERNEL_RESIDENT, L0T_SIZE);
- vmm_unset_ptes(ptep, count);
+ boot_clean_arch_reserve(bhctx);
}
void
ksym_getstr(struct ksym_entry* sym)
{
if (!sym) {
- return "???";
+ return NULL;
}
return sym->label;
}
static inline bool valid_fp(ptr_t ptr) {
- ptr_t start = ROUNDUP(current_thread->kstack - KSTACK_SIZE, MEM_PAGE);
+ ptr_t start = ROUNDUP(current_thread->kstack - KSTACK_SIZE, PAGE_SIZE);
return (start < ptr && ptr < current_thread->kstack)
|| arch_valid_fp(ptr);
static inline void
trace_print_code_entry(ptr_t sym_pc, ptr_t inst_pc, char* sym)
{
- if (sym_pc) {
+ if (sym) {
trace_log("%s+%p", sym, inst_pc - sym_pc);
} else {
- trace_log("%s [%p]", sym, sym_pc);
+ trace_log("??? [%p]", inst_pc);
}
}
trace_printswctx(const struct hart_state* hstate, bool from_usr, bool to_usr)
{
- struct ksym_entry* sym = trace_sym_lookup(hstate->execp->eip);
+ struct ksym_entry* sym = trace_sym_lookup(hart_pc(hstate));
trace_log("^^^^^ --- %s", to_usr ? "user" : "kernel");
trace_print_transistion_short(hstate);
iopoll_wake_pollers(&dev->pollers);
}
-__DEFINE_LXSYSCALL3(int, ioctl, int, fd, int, req, va_list, args)
+__DEFINE_LXSYSCALL3(int, ioctl, int, fd, int, req, sc_va_list, _args)
{
int errno = -1;
struct v_fd* fd_s;
+ va_list args;
+
+ convert_valist(&args, _args);
+
if ((errno &= vfs_getfd(fd, &fd_s))) {
goto done;
}
return pld;
}
-__DEFINE_LXSYSCALL2(int, pollctl, int, action, va_list, va)
+__DEFINE_LXSYSCALL2(int, pollctl, int, action, sc_va_list, _ap)
{
int retcode = 0;
+ va_list va;
+
+ convert_valist(&va, _ap);
+
switch (action) {
case _SPOLL_ADD: {
int* ds = va_arg(va, int*);
-use("elf32")
+use("elf-generic")
sources([
"exec.c"
--- /dev/null
+sources([
+ "elfbfmt.c",
+ "ldelf.c"
+])
\ No newline at end of file
-#include <lunaix/exebi/elf32.h>
+#include <lunaix/exebi/elf.h>
#include <lunaix/fs.h>
#include <lunaix/mm/valloc.h>
#include <lunaix/spike.h>
#include <klibc/string.h>
static inline int
-elf32_read(struct v_file* elf, void* data, size_t off, size_t len)
+elf_read(struct v_file* elf, void* data, size_t off, size_t len)
{
// it is wise to do cached read
return pcache_read(elf->inode, data, len, off);
}
static int
-elf32_do_open(struct elf32* elf, struct v_file* elf_file)
+elf_do_open(struct elf* elf, struct v_file* elf_file)
{
int status = 0;
elf->pheaders = NULL;
elf->elf_file = elf_file;
- if ((status = elf32_read_ehdr(elf)) < 0) {
- elf32_close(elf);
+ if ((status = elf_read_ehdr(elf)) < 0) {
+ elf_close(elf);
return status;
}
- if ((status = elf32_read_phdr(elf)) < 0) {
- elf32_close(elf);
+ if ((status = elf_read_phdr(elf)) < 0) {
+ elf_close(elf);
return status;
}
return 0;
}
-int
-elf32_open(struct elf32* elf, const char* path)
+defualt int
+elf_open(struct elf* elf, const char* path)
{
struct v_dnode* elfdn;
struct v_file* elffile;
return error;
}
- return elf32_do_open(elf, elffile);
+ return elf_do_open(elf, elffile);
}
-int
-elf32_openat(struct elf32* elf, void* elf_vfile)
+defualt int
+elf_openat(struct elf* elf, void* elf_vfile)
{
// so the ref count kept in sync
vfs_ref_file(elf_vfile);
- return elf32_do_open(elf, elf_vfile);
+ return elf_do_open(elf, elf_vfile);
}
-int
-elf32_close(struct elf32* elf)
+defualt int
+elf_close(struct elf* elf)
{
if (elf->pheaders) {
vfree(elf->pheaders);
return 0;
}
-int
-elf32_static_linked(const struct elf32* elf)
+defualt int
+elf_static_linked(const struct elf* elf)
{
for (size_t i = 0; i < elf->eheader.e_phnum; i++) {
- struct elf32_phdr* phdre = &elf->pheaders[i];
+ struct elf_phdr* phdre = &elf->pheaders[i];
if (phdre->p_type == PT_INTERP) {
return 0;
}
return 1;
}
-size_t
-elf32_loadable_memsz(const struct elf32* elf)
+defualt size_t
+elf_loadable_memsz(const struct elf* elf)
{
// XXX: Hmmmm, I am not sure if we need this. This is designed to be handy
// if we decided to map the heap region before transfer to loader. As
size_t sz = 0;
for (size_t i = 0; i < elf->eheader.e_phnum; i++) {
- struct elf32_phdr* phdre = &elf->pheaders[i];
+ struct elf_phdr* phdre = &elf->pheaders[i];
if (phdre->p_type == PT_LOAD) {
sz += phdre->p_memsz;
}
return sz;
}
-int
-elf32_find_loader(const struct elf32* elf, char* path_out, size_t len)
+defualt int
+elf_find_loader(const struct elf* elf, char* path_out, size_t len)
{
int retval = NO_LOADER;
struct v_file* elfile = (struct v_file*)elf->elf_file;
for (size_t i = 0; i < elf->eheader.e_phnum; i++) {
- struct elf32_phdr* phdre = &elf->pheaders[i];
+ struct elf_phdr* phdre = &elf->pheaders[i];
if (phdre->p_type == PT_INTERP) {
if (len >= phdre->p_filesz) {
return EINVAL;
}
retval =
- elf32_read(elfile, path_out, phdre->p_offset, phdre->p_filesz);
+ elf_read(elfile, path_out, phdre->p_offset, phdre->p_filesz);
if (retval < 0) {
return retval;
return retval;
}
-int
-elf32_read_ehdr(struct elf32* elf)
+defualt int
+elf_read_ehdr(struct elf* elf)
{
struct v_file* elfile = (struct v_file*)elf->elf_file;
- return elf32_read(elfile, (void*)&elf->eheader, 0, SIZE_EHDR);
+ return elf_read(elfile, (void*)&elf->eheader, 0, SIZE_EHDR);
}
-int
-elf32_read_phdr(struct elf32* elf)
+defualt int
+elf_read_phdr(struct elf* elf)
{
int status = 0;
size_t entries = elf->eheader.e_phnum;
size_t tbl_sz = entries * SIZE_PHDR;
- struct elf32_phdr* phdrs = valloc(tbl_sz);
+ struct elf_phdr* phdrs = valloc(tbl_sz);
if (!phdrs) {
return ENOMEM;
}
- status = elf32_read(elfile, phdrs, elf->eheader.e_phoff, tbl_sz);
+ status = elf_read(elfile, phdrs, elf->eheader.e_phoff, tbl_sz);
if (status < 0) {
vfree(phdrs);
return entries;
}
-int
-elf32_check_exec(const struct elf32* elf, int type)
+defualt int
+elf_check_exec(const struct elf* elf, int type)
{
- const struct elf32_ehdr* ehdr = &elf->eheader;
+ const struct elf_ehdr* ehdr = &elf->eheader;
return (ehdr->e_entry) && ehdr->e_type == type;
}
-int
-elf32_check_arch(const struct elf32* elf)
+defualt int
+elf_check_arch(const struct elf* elf)
{
- const struct elf32_ehdr* ehdr = &elf->eheader;
+ const struct elf_ehdr* ehdr = &elf->eheader;
- return *(u32_t*)(ehdr->e_ident) == ELFMAGIC &&
- ehdr->e_ident[EI_CLASS] == ELFCLASS32 &&
- ehdr->e_ident[EI_DATA] == ELFDATA2LSB && ehdr->e_machine == EM_386;
+ return *(u32_t*)(ehdr->e_ident) == ELFMAGIC_LE;
}
\ No newline at end of file
-#include <lunaix/exebi/elf32.h>
+#include <lunaix/exebi/elf.h>
#include <lunaix/load.h>
#include <lunaix/mm/mmap.h>
#include <lunaix/mm/valloc.h>
#include <sys/mm/mempart.h>
int
-elf32_smap(struct load_context* ldctx,
- const struct elf32* elf,
- struct elf32_phdr* phdre,
+elf_smap(struct load_context* ldctx,
+ const struct elf* elf,
+ struct elf_phdr* phdre,
uintptr_t base_va)
{
struct v_file* elfile = (struct v_file*)elf->elf_file;
}
uintptr_t va = phdre->p_va + base_va;
- struct exec_container* container = ldctx->container;
+ struct exec_host* container = ldctx->container;
struct mmap_param param = { .vms_mnt = container->vms_mnt,
.pvms = vmspace(container->proc),
.proct = proct,
.offset = page_aligned(phdre->p_offset),
.mlen = page_upaligned(phdre->p_memsz),
+ .flen = phdre->p_filesz,
.flags = MAP_FIXED | MAP_PRIVATE,
.type = REGION_TYPE_CODE };
int errno = 0;
char* ldpath = NULL;
- struct elf32 elf;
- struct exec_container* container = context->container;
+ struct elf elf;
+ struct exec_host* container = context->container;
- if ((errno = elf32_openat(&elf, exefile))) {
+ if ((errno = elf_openat(&elf, exefile))) {
goto done;
}
- if (!elf32_check_arch(&elf)) {
+ if (!elf_check_arch(&elf)) {
errno = EINVAL;
goto done;
}
- if (!(elf32_check_exec(&elf, ET_EXEC) || elf32_check_exec(&elf, ET_DYN))) {
+ if (!(elf_check_exec(&elf, ET_EXEC) || elf_check_exec(&elf, ET_DYN))) {
errno = ENOEXEC;
goto done;
}
ldpath = valloc(256);
- errno = elf32_find_loader(&elf, ldpath, 256);
+ errno = elf_find_loader(&elf, ldpath, 256);
uintptr_t load_base = 0;
if (errno < 0) {
}
if (errno != NO_LOADER) {
- container->argv_pp[1] = ldpath;
-
// close old elf
- if ((errno = elf32_close(&elf))) {
+ if ((errno = elf_close(&elf))) {
goto done;
}
// open the loader instead
- if ((errno = elf32_open(&elf, ldpath))) {
+ if ((errno = elf_open(&elf, ldpath))) {
goto done;
}
// Is this the valid loader?
- if (!elf32_static_linked(&elf) || !elf32_check_exec(&elf, ET_DYN)) {
+ if (!elf_static_linked(&elf) || !elf_check_exec(&elf, ET_DYN)) {
errno = ELIBBAD;
goto done_close_elf32;
}
struct v_file* elfile = (struct v_file*)elf.elf_file;
for (size_t i = 0; i < elf.eheader.e_phnum && !errno; i++) {
- struct elf32_phdr* phdr = &elf.pheaders[i];
+ struct elf_phdr* phdr = &elf.pheaders[i];
if (phdr->p_type != PT_LOAD) {
continue;
break;
}
- errno = elf32_smap(context, &elf, phdr, load_base);
+ errno = elf_smap(context, &elf, phdr, load_base);
}
done_close_elf32:
- elf32_close(&elf);
+ elf_close(&elf);
done:
- if (!container->argv_pp[1]) {
- vfree_safe(ldpath);
- }
+ vfree_safe(ldpath);
return errno;
}
+++ /dev/null
-sources([
- "elf32bfmt.c",
- "ldelf32.c"
-])
\ No newline at end of file
#include <klibc/string.h>
+#define _push(ptr, type, val) \
+ do { \
+ ptr = __ptr(&((type*)ptr)[-1]); \
+ *((type*)ptr) = (val); \
+ } while(0)
+
+static int
+__place_arrayptrs(struct exec_host* container, struct exec_arrptr* param)
+{
+ int len;
+ ptr_t usp, usp_top;
+ ptr_t* ptrs;
+ unsigned int* reloc_off;
+
+ usp_top = container->stack_top;
+ usp = usp_top;
+ ptrs = (ptr_t*)param->raw;
+
+ if (!param->len) {
+ _push(usp, unsigned int, 0);
+
+ goto done;
+ }
+
+ len = param->len;
+ reloc_off = valloc(len * sizeof(unsigned int));
+
+ char* el;
+ size_t el_sz, sz_acc = 0;
+ for (int i = 0; i < len; i++)
+ {
+ el= (char*)ptrs[i];
+ el_sz = strnlen(el, MAX_PARAM_SIZE) + 1;
+
+ usp -= el_sz;
+ sz_acc += el_sz;
+ strncpy((char*)usp, el, el_sz);
+
+ reloc_off[i] = sz_acc;
+ }
+
+ param->size = sz_acc;
+
+ ptr_t* toc = (ptr_t*)(usp) - 1;
+ toc[0] = 0;
+
+ toc = &toc[-1];
+ for (int i = 0, j = len - 1; i < len; i++, j--)
+ {
+ toc[-i] = usp_top - (ptr_t)reloc_off[j];
+ }
+
+ toc[-len] = (ptr_t)len;
+
+ usp = __ptr(&toc[-len]);
+ param->copied = __ptr(&toc[-len + 1]);
+
+ vfree(reloc_off);
+
+done:
+ container->stack_top = usp;
+ return 0;
+}
+
void
-exec_init_container(struct exec_container* param,
+exec_init_container(struct exec_host* param,
struct thread* thread,
ptr_t vms,
const char** argv,
{
assert(thread->ustack);
ptr_t ustack_top = align_stack(thread->ustack->end - 1);
- *param = (struct exec_container){ .proc = thread->process,
- .vms_mnt = vms,
- .exe = { .container = param },
- .argv_pp = { 0, 0 },
- .argv = argv,
- .envp = envp,
- .stack_top = ustack_top };
+ *param = (struct exec_host)
+ {
+ .proc = thread->process,
+ .vms_mnt = vms,
+ .exe = {
+ .container = param
+ },
+ .argv = {
+ .raw = __ptr(argv)
+ },
+ .envp = {
+ .raw = __ptr(envp)
+ },
+ .stack_top = ustack_top
+ };
}
-size_t
-args_ptr_size(const char** paramv)
-{
- size_t sz = 0;
- while (*paramv) {
- sz++;
- paramv++;
- }
-
- return (sz + 1) * sizeof(ptr_t);
-}
-
-static ptr_t
-copy_to_ustack(ptr_t stack_top, ptr_t* paramv)
+int
+count_length(struct exec_arrptr* param)
{
- ptr_t ptr;
- size_t sz = 0;
-
- while ((ptr = *paramv)) {
- sz = strlen((const char*)ptr) + 1;
-
- stack_top -= sz;
- memcpy((void*)stack_top, (const void*)ptr, sz);
- *paramv = stack_top;
+ int i = 0;
+ ptr_t* arr = (ptr_t*)param->raw;
- paramv++;
+ if (!arr) {
+ param->len = 0;
+ return 0;
}
- return stack_top;
+ for (; i < MAX_PARAM_LEN && arr[i]; i++);
+
+ param->len = i;
+ return i > 0 && arr[i] ? E2BIG : 0;
}
static void
-save_process_cmd(struct proc_info* proc, ptr_t* argv)
+save_process_cmd(struct proc_info* proc, struct exec_arrptr* argv)
{
- ptr_t ptr, *_argv = argv;
- size_t total_sz = 0;
- while ((ptr = *_argv)) {
- total_sz += strlen((const char*)ptr) + 1;
- _argv++;
- }
+ ptr_t ptr, *argv_ptrs;
+ char* cmd_;
if (proc->cmd) {
vfree(proc->cmd);
}
- char* cmd_ = (char*)valloc(total_sz);
- proc->cmd = cmd_;
- proc->cmd_len = total_sz;
+ argv_ptrs = (ptr_t*)argv->copied;
+ cmd_ = (char*)valloc(argv->size);
- while ((ptr = *argv)) {
+ proc->cmd = cmd_;
+ while ((ptr = *argv_ptrs)) {
cmd_ = strcpy(cmd_, (const char*)ptr);
cmd_[-1] = ' ';
- argv++;
+ argv_ptrs++;
}
cmd_[-1] = '\0';
+
+ proc->cmd_len = argv->size;
}
-// externed from mm/dmm.c
-extern int
-create_heap(struct proc_mm* pvms, ptr_t addr);
-int
-exec_load(struct exec_container* container, struct v_file* executable)
+static int
+__place_params(struct exec_host* container)
{
int errno = 0;
- const char **argv = container->argv, **envp = container->envp;
- const char** argv_extra = container->argv_pp;
-
- argv_extra[0] = executable->dnode->name.value;
-
- if ((errno = load_executable(&container->exe, executable))) {
+ errno = __place_arrayptrs(container, &container->envp);
+ if (errno) {
goto done;
}
+ errno = __place_arrayptrs(container, &container->argv);
+
+done:
+ return errno;
+}
+
+int
+exec_load(struct exec_host* container, struct v_file* executable)
+{
+ int errno = 0;
+
+ struct exec_arrptr* argv = &container->argv;
+ struct exec_arrptr* envp = &container->envp;
+
struct proc_info* proc = container->proc;
struct proc_mm* pvms = vmspace(proc);
pvms->heap = NULL;
}
- if (!argv_extra[1]) {
- // If loading a statically linked file, then heap remapping we can do,
- // otherwise delayed.
- create_heap(vmspace(proc), page_aligned(container->exe.end));
- }
-
- if (container->vms_mnt == VMS_SELF) {
- // we are loading executable into current addr space
-
- ptr_t ustack = container->stack_top;
- size_t argv_len = 0, envp_len = 0;
- ptr_t argv_ptr = 0, envp_ptr = 0;
-
- if (envp) {
- argv_len = args_ptr_size(envp);
- ustack -= envp_len;
- envp_ptr = ustack;
-
- memcpy((void*)ustack, (const void*)envp, envp_len);
- ustack = copy_to_ustack(ustack, (ptr_t*)ustack);
- } else {
- ustack -= sizeof(ptr_t);
- *((ptr_t*)ustack) = 0;
- }
-
- if (argv) {
- argv_len = args_ptr_size(argv);
- ustack -= argv_len;
-
- memcpy((void*)ustack, (const void**)argv, argv_len);
- } else {
- ustack -= sizeof(ptr_t);
- *((ptr_t*)ustack) = 0;
- }
-
- for (size_t i = 0; i < 2 && argv_extra[i]; i++) {
- ustack -= sizeof(ptr_t);
- *((ptr_t*)ustack) = (ptr_t)argv_extra[i];
- argv_len += sizeof(ptr_t);
- }
-
- argv_ptr = ustack;
- ustack = copy_to_ustack(ustack, (ptr_t*)ustack);
-
- save_process_cmd(proc, (ptr_t*)argv_ptr);
-
- // four args (arg{c|v}, env{c|p}) for main
- struct uexec_param* exec_param = &((struct uexec_param*)ustack)[-1];
-
- container->stack_top = (ptr_t)exec_param;
-
- *exec_param =
- (struct uexec_param){ .argc = (argv_len - 1) / sizeof(ptr_t),
- .argv = (char**)argv_ptr,
- .envc = (envp_len - 1) / sizeof(ptr_t),
- .envp = (char**)envp_ptr };
- } else {
+ if (!active_vms(container->vms_mnt)) {
/*
- TODO Inject to remote user stack with our procvm_remote toolsets
- Need a better way to factorise the argv/envp length calculating
+ TODO Setup remote mapping of user stack for later use
*/
fail("not implemented");
}
+ if ((errno = count_length(argv))) {
+ goto done;
+ }
+
+ if ((errno = count_length(envp))) {
+ goto done;
+ }
+
+ errno = __place_params(container);
+ if (errno) {
+ goto done;
+ }
+
+ save_process_cmd(proc, argv);
+
+ errno = load_executable(&container->exe, executable);
+ if (errno) {
+ goto done;
+ }
+
done:
return errno;
}
int
-exec_load_byname(struct exec_container* container, const char* filename)
+exec_load_byname(struct exec_host* container, const char* filename)
{
int errno = 0;
struct v_dnode* dnode;
exec_kexecve(const char* filename, const char* argv[], const char* envp[])
{
int errno = 0;
- struct exec_container container;
+ struct exec_host container;
+
+ assert(argv && envp);
exec_init_container(&container, current_thread, VMS_SELF, argv, envp);
envp[])
{
int errno = 0;
- struct exec_container container;
+ struct exec_host container;
+
+ if (!argv || !envp) {
+ errno = EINVAL;
+ goto done;
+ }
exec_init_container(
&container, current_thread, VMS_SELF, argv, envp);
// we will jump to new entry point (_u_start) upon syscall's
// return so execve 'will not return' from the perspective of it's invoker
- hart_flow_redirect(current_thread->hstate,
- container.exe.entry, container.stack_top);
+ exec_arch_prepare_entry(current_thread, &container);
// these become meaningless once execved!
current_thread->ustack_top = 0;
__version_rd(struct twimap* map)
{
twimap_printf(map,
- "LunaixOS version %s (gnu-cc %s) %s %s",
- CONFIG_LUNAIX_VER,
- __VERSION__,
- __DATE__,
- __TIME__);
+ "Lunaix "
+ CONFIG_LUNAIX_VER
+ " (gnu-cc " __VERSION__ ") " __DATE__ " " __TIME__);
}
void
#include <lunaix/spike.h>
#include <klibc/string.h>
-#include <sys/mm/mempart.h>
+#include <sys/mm/pagetable.h>
int
iso9660_open(struct v_inode* this, struct v_file* file)
int
iso9660_read_page(struct v_inode* inode, void* buffer, size_t fpos)
{
- return iso9660_read(inode, buffer, MEM_PAGE, fpos);
+ return iso9660_read(inode, buffer, PAGE_SIZE, fpos);
}
int
#include <lunaix/mm/valloc.h>
#include <lunaix/spike.h>
-#include <sys/mm/mempart.h>
+#include <sys/mm/pagetable.h>
static struct twifs_node* fs_root;
int
__twifs_fwrite_pg(struct v_inode* inode, void* buffer, size_t fpos)
{
- return __twifs_fwrite(inode, buffer, MEM_PAGE, fpos);
+ return __twifs_fwrite(inode, buffer, PAGE_SIZE, fpos);
}
int
int
__twifs_fread_pg(struct v_inode* inode, void* buffer, size_t fpos)
{
- return __twifs_fread(inode, buffer, MEM_PAGE, fpos);
+ return __twifs_fread(inode, buffer, PAGE_SIZE, fpos);
}
struct twifs_node*
#include <klibc/strfmt.h>
#include <klibc/string.h>
-#include <sys/mm/mempart.h>
+#include <sys/mm/pagetable.h>
-#define TWIMAP_BUFFER_SIZE MEM_PAGE
+#define TWIMAP_BUFFER_SIZE PAGE_SIZE
void
__twimap_default_reset(struct twimap* map)
static int
__twimap_file_read_page(struct v_inode* inode, void* buf, size_t fpos)
{
- return __twimap_file_read(inode, buf, MEM_PAGE, fpos);
+ return __twimap_file_read(inode, buf, PAGE_SIZE, fpos);
}
int
// 确保低位更加随机
_hash = _hash ^ (_hash >> VFS_HASHBITS);
// 与parent的指针值做加法,来减小碰撞的可能性。
- _hash += (u32_t)parent;
+ _hash += (u32_t)__ptr(parent);
*hash = _hash;
return &dnode_cache[_hash & VFS_HASH_MASK];
}
* and start geting into uspace
*/
boot_end(bhctx);
- boot_cleanup();
spawn_lunad();
}
kmem_init(struct boot_handoff* bhctx)
{
pte_t* ptep = mkptep_va(VMS_SELF, KERNEL_RESIDENT);
+
ptep = mkl0tep(ptep);
+ unsigned int i = ptep_vfn(ptep);
do {
+ if (l0tep_impile_vmnts(ptep)) {
+ ptep++;
+ continue;
+ }
+
#if LnT_ENABLED(1)
assert(mkl1t(ptep++, 0, KERNEL_DATA));
#elif LnT_ENABLED(2)
#else
assert(mklft(ptep++, 0, KERNEL_DATA));
#endif
- } while (ptep_vfn(ptep) < MAX_PTEN - 2);
+ } while (++i < MAX_PTEN);
// allocators
cake_init();
#include <lunaix/fs/twifs.h>
#include <lunaix/fs/twimap.h>
#include <lunaix/syscall.h>
+#include <lunaix/syscall_utils.h>
#include <lunaix/syslog.h>
#include <lunaix/device.h>
#include <lunaix/owloysius.h>
return str;
}
+static inline void
+kprintf_put(int level, const char* buf, size_t sz)
+{
+ kprec_put(&kprecs, level, buf, sz);
+
+ if (likely(sysconsole)) {
+ sysconsole->ops.write(sysconsole, buf, 0, sz);
+ }
+}
+
static inline void
kprintf_ml(const char* component, int level, const char* fmt, va_list args)
{
ksnprintf(buf, MAX_BUFSZ_HLF, "%s: %s\n", component, fmt);
size_t sz = ksnprintfv(tmp_buf, buf, MAX_BUFSZ_HLF, args);
- kprec_put(&kprecs, level, tmp_buf, sz);
-
- if (likely(sysconsole)) {
- sysconsole->ops.write(sysconsole, tmp_buf, 0, sz);
- }
+ kprintf_put(level, tmp_buf, sz);
}
void
}
}
-__DEFINE_LXSYSCALL3(void, syslog, int, level, const char*, fmt, va_list, args)
+__DEFINE_LXSYSCALL3(void, syslog, int, level,
+ const char*, buf, unsigned int, size)
{
- kprintf_ml("syslog", level, fmt, args);
+ kprintf_put(level, buf, size);
}
\ No newline at end of file
exec_initd()
{
int errno = 0;
+ const char* argv[] = { "/mnt/lunaix-os/usr/bin/init", 0 };
+ const char* envp[] = { 0 };
- if ((errno = exec_kexecve("/mnt/lunaix-os/usr/bin/init", NULL, NULL))) {
+ if ((errno = exec_kexecve(argv[0], argv, envp))) {
goto fail;
}
assert(heap);
int err = mem_adjust_inplace(&pvms->regions, heap, heap->end + incr);
if (err) {
- return (void*)DO_STATUS(err);
+ return (void*)__ptr(DO_STATUS(err));
}
return (void*)heap->end;
}
context->mm = vmspace(__current);
- if (mnt < VMS_MOUNT_1) {
+ if (!vmnt_packed(ptep)) {
refva = (ptr_t)ptep;
goto done;
}
context->ptep_fault = true;
- context->remote_fault = (mnt != VMS_SELF);
+ context->remote_fault = !active_vms(mnt);
if (context->remote_fault && context->mm) {
context->mm = context->mm->guest_mm;
assert(context->mm);
}
+ // unpack the ptep to reveal the one true va!
+
#if LnT_ENABLED(1)
ptep = (pte_t*)page_addr(ptep_pfn(ptep));
mnt = ptep_vm_mnt(ptep);
- if (mnt < VMS_MOUNT_1) {
+ if (!vmnt_packed(ptep)) {
refva = (ptr_t)ptep;
goto done;
}
#if LnT_ENABLED(2)
ptep = (pte_t*)page_addr(ptep_pfn(ptep));
mnt = ptep_vm_mnt(ptep);
- if (mnt < VMS_MOUNT_1) {
+ if (!vmnt_packed(ptep)) {
refva = (ptr_t)ptep;
goto done;
}
#if LnT_ENABLED(3)
ptep = (pte_t*)page_addr(ptep_pfn(ptep));
mnt = ptep_vm_mnt(ptep);
- if (mnt < VMS_MOUNT_1) {
+ if (!vmnt_packed(ptep)) {
refva = (ptr_t)ptep;
goto done;
}
ptep = (pte_t*)page_addr(ptep_pfn(ptep));
mnt = ptep_vm_mnt(ptep);
- assert(mnt < VMS_MOUNT_1);
+ assert(!vmnt_packed(ptep));
refva = (ptr_t)ptep;
done:
static void
__handle_named_region(struct fault_context* fault)
{
+ int errno = 0;
struct mm_region* vmr = fault->vmr;
struct v_file* file = vmr->mfile;
+ struct v_file_ops * fops = file->ops;
pte_t pte = fault->resolving;
ptr_t fault_va = page_aligned(fault->fault_va);
u32_t mseg_off = (fault_va - vmr->start);
u32_t mfile_off = mseg_off + vmr->foff;
+ size_t mapped_len = vmr->flen;
// TODO Potentially we can get different order of leaflet here
struct leaflet* region_part = alloc_leaflet(0);
pte = pte_setprot(pte, region_pteprot(vmr));
ptep_map_leaflet(fault->fault_ptep, pte, region_part);
- int errno = file->ops->read_page(file->inode, (void*)fault_va, mfile_off);
+ if (mseg_off < mapped_len) {
+ mapped_len = MIN(mapped_len - mseg_off, PAGE_SIZE);
+ }
+ else {
+ mapped_len = 0;
+ }
+
+ if (mapped_len == PAGE_SIZE) {
+ errno = fops->read_page(file->inode, (void*)fault_va, mfile_off);
+ }
+ else {
+ leaflet_wipe(region_part);
+
+ if (mapped_len) {
+ errno = fops->read(file->inode,
+ (void*)fault_va, mapped_len, mfile_off);
+ }
+ }
+
if (errno < 0) {
ERROR("fail to populate page (%d)", errno);
__handle_kernel_page(struct fault_context* fault)
{
// we must ensure only ptep fault is resolvable
- if (fault->fault_va < VMS_MOUNT_1) {
+ if (!is_ptep(fault->fault_va)) {
return;
}
leaflet_return(fault.prealloc);
}
}
+
+ tlb_flush_kernel(fault.fault_va);
}
\ No newline at end of file
((param->proct | param->flags) & 0x3f) | (param->type & ~0xffff));
region->mfile = file;
+ region->flen = param->flen;
region->foff = param->offset;
region->proc_vms = param->pvms;
}
}
- while (&pos->head != regions && length) {
+ size_t remaining = length;
+ while (&pos->head != regions && remaining) {
n = container_of(pos->head.next, typeof(*pos), head);
- __unmap_overlapped_cases(mnt, pos, &cur_addr, &length);
+ if (pos->start > cur_addr + length) {
+ break;
+ }
+
+ __unmap_overlapped_cases(mnt, pos, &cur_addr, &remaining);
pos = n;
}
return 0;
}
-__DEFINE_LXSYSCALL3(void*, sys_mmap, void*, addr, size_t, length, va_list, lst)
+__DEFINE_LXSYSCALL1(void*, sys_mmap, struct usr_mmap_param*, mparam)
{
- int proct = va_arg(lst, int);
- int fd = va_arg(lst, u32_t);
- off_t offset = va_arg(lst, off_t);
- int options = va_arg(lst, int);
- int errno = 0;
- void* result = (void*)-1;
-
- ptr_t addr_ptr = (ptr_t)addr;
+ off_t offset;
+ size_t length;
+ int proct, fd, options;
+ int errno;
+ void* result;
+ ptr_t addr_ptr;
+
+ proct = mparam->proct;
+ fd = mparam->fd;
+ offset = mparam->offset;
+ options = mparam->flags;
+ addr_ptr = __ptr(mparam->addr);
+ length = mparam->length;
+
+ errno = 0;
+ result = (void*)-1;
if (!length || length > BS_SIZE || va_offset(addr_ptr)) {
errno = EINVAL;
}
}
+ length = ROUNDUP(length, PAGE_SIZE);
struct mmap_param param = { .flags = options,
- .mlen = ROUNDUP(length, PAGE_SIZE),
+ .mlen = length,
+ .flen = length,
.offset = offset,
.type = REGION_TYPE_GENERAL,
.proct = proct,
pte_t* ptep_kernel = mkl0tep(mkptep_va(src_mnt, KERNEL_RESIDENT));
// Build the self-reference on dest vms
- pte_t* ptep_sms = mkptep_va(VMS_SELF, (ptr_t)ptep_dest);
- pte_t* ptep_ssm = mkptep_va(VMS_SELF, (ptr_t)ptep_sms);
+
+ /*
+ * -- What the heck are ptep_ssm and ptep_sms ? --
+ *
+ * ptep_dest point to the pagetable itself that is mounted
+ * at dest_mnt (or simply mnt):
+ * mnt -> self -> self -> self -> L0TE@offset
+ *
+ * ptep_sms shallowed the recursion chain:
+ * self -> mnt -> self -> self -> L0TE@self
+ *
+ * ptep_ssm shallowed the recursion chain:
+ * self -> self -> mnt -> self -> L0TE@self
+ *
+ * Now, here is the problem, back to x86_32, the translation is
+ * a depth-3 recursion:
+ * L0T -> LFT -> Page
+ *
+ * So ptep_ssm will terminate at mnt and give us a leaf
+ * slot for allocate a fresh page table for mnt:
+ * self -> self -> L0TE@mnt
+ *
+ * but in x86_64 translation has extra two more step:
+ * L0T -> L1T -> L2T -> LFT -> Page
+ *
+ * So we must continue push down....
+ * ptep_sssms shallowed the recursion chain:
+ * self -> self -> self -> mnt -> L0TE@self
+ *
+ * ptep_ssssm shallowed the recursion chain:
+ * self -> self -> self -> self -> L0TE@mnt
+ *
+ * Note: PML4: 2 extra steps
+ * PML5: 3 extra steps
+ */
+ pte_t* ptep_ssm = mkl0tep_va(VMS_SELF, dest_mnt);
+ pte_t* ptep_sms = mkl1tep_va(VMS_SELF, dest_mnt) + VMS_SELF_L0TI;
pte_t pte_sms = mkpte_prot(KERNEL_DATA);
pte_sms = alloc_kpage_at(ptep_ssm, pte_sms, 0);
set_pte(ptep_sms, pte_sms);
tlb_flush_kernel((ptr_t)dest_mnt);
+ tlb_flush_kernel((ptr_t)ptep_sms);
if (only_kernel) {
ptep = ptep_kernel;
}
cont:
- if (ptep_vfn(ptep) == MAX_PTEN - 1) {
+ while (ptep_vfn(ptep) == MAX_PTEN - 1) {
assert(level > 0);
ptep = ptep_step_out(ptep);
ptep_dest = ptep_step_out(ptep_dest);
assert(ptep_dest == ptepd_kernel);
// Carry over the kernel (exclude last two entry)
- while (ptep_vfn(ptep) < MAX_PTEN - 2) {
+ unsigned int i = ptep_vfn(ptep);
+ while (i++ < MAX_PTEN) {
pte_t pte = *ptep;
+
+ if (l0tep_impile_vmnts(ptep)) {
+ goto _cont;
+ }
+
assert(!pte_isnull(pte));
// Ensure it is a next level pagetable,
set_pte(ptep_dest, pte);
leaflet_borrow(leaflet);
-
+
+ _cont:
ptep++;
ptep_dest++;
}
- return pte_paddr(*(ptep_dest + 1));
+ return pte_paddr(pte_sms);
}
static void
{
struct leaflet* leaflet;
pte_t* ptep_head = mkl0tep(mkptep_va(vm_mnt, 0));
+ pte_t* ptep_self = mkl0tep(mkptep_va(vm_mnt, VMS_SELF));
pte_t* ptep_kernel = mkl0tep(mkptep_va(vm_mnt, KERNEL_RESIDENT));
int level = 0;
}
cont:
- if (ptep_vfn(ptep) == MAX_PTEN - 1) {
+ while (ptep_vfn(ptep) == MAX_PTEN - 1) {
ptep = ptep_step_out(ptep);
leaflet = pte_leaflet_aligned(pte_at(ptep));
ptep++;
}
- leaflet = pte_leaflet_aligned(ptep_head[MAX_PTEN - 1]);
+ leaflet = pte_leaflet_aligned(pte_at(ptep_self));
leaflet_return(leaflet);
}
void
procvm_unmount_self(struct proc_mm* mm)
{
- assert(mm->vm_mnt == VMS_SELF);
+ assert(active_vms(mm->vm_mnt));
mm->vm_mnt = 0;
}
ptr_t vm_mnt = mm->vm_mnt;
assert(vm_mnt);
- pfn_t size_pn = pfn(size + MEM_PAGE);
+ pfn_t size_pn = pfn(size + PAGE_SIZE);
assert(size_pn < REMOTEVM_MAX_PAGES);
struct mm_region* region = region_get(&mm->regions, remote_base);
struct mm_region* region = valloc(sizeof(struct mm_region));
*region = (struct mm_region){ .attr = attr,
.start = start,
- .end = ROUNDUP(start + length, MEM_PAGE) };
+ .end = ROUNDUP(start + length, PAGE_SIZE) };
return region;
}
goto fail;
}
- struct exec_container container;
+ struct exec_host container;
exec_init_container(&container, main_thread, VMS_MOUNT_1, argv, envp);
if ((errno = exec_load_byname(&container, path))) {
goto fail;
__alloc_user_thread_stack(struct proc_info* proc,
struct mm_region** stack_region, ptr_t vm_mnt)
{
- ptr_t th_stack_top = (proc->thread_count + 1) * USR_STACK_SIZE;
- th_stack_top = ROUNDUP(USR_STACK_END - th_stack_top, MEM_PAGE);
+ ptr_t th_stack_top = (proc->thread_count + 1) * USR_STACK_SIZE_THREAD;
+ th_stack_top = ROUNDUP(USR_STACK_END - th_stack_top, PAGE_SIZE);
struct mm_region* vmr;
struct proc_mm* mm = vmspace(proc);
struct mmap_param param = { .vms_mnt = vm_mnt,
.pvms = mm,
- .mlen = USR_STACK_SIZE,
+ .mlen = USR_STACK_SIZE_THREAD,
.proct = PROT_READ | PROT_WRITE,
.flags = MAP_ANON | MAP_PRIVATE,
.type = REGION_TYPE_STACK };
return 0;
}
- set_pte(mkptep_va(vm_mnt, vmr->start), guard_pte);
+ pte_t* guardp = mkptep_va(vm_mnt, vmr->start);
+ set_pte(guardp, guard_pte);
*stack_region = vmr;
- ptr_t stack_top = align_stack(th_stack_top + USR_STACK_SIZE - 1);
+ ptr_t stack_top = align_stack(th_stack_top + USR_STACK_SIZE_THREAD - 1);
return stack_top;
}
pfn_t kstack_end = pfn(KSTACK_AREA);
pte_t* ptep = mkptep_pn(vm_mnt, kstack_top);
while (ptep_pfn(ptep) > kstack_end) {
- ptep -= KSTACK_PAGES;
+ ptep -= KSTACK_PAGES + 1;
- // first page in the kernel stack is guardian page
- pte_t pte = *(ptep + 1);
+ pte_t pte = pte_at(ptep + 1);
if (pte_isnull(pte)) {
goto found;
}
return 0;
found:;
- // KSTACK_PAGES = 3, removal one guardian pte, give order 1 page
- struct leaflet* leaflet = alloc_leaflet(1);
+ unsigned int po = count_order(KSTACK_PAGES);
+ struct leaflet* leaflet = alloc_leaflet(po);
if (!leaflet) {
WARN("failed to create kernel stack: nomem\n");
th->kstack = kstack;
th->ustack = ustack_region;
+
+ if (ustack_region) {
+ th->ustack_top = align_stack(ustack_region->end - 1);
+ }
return th;
}
if (!kernel_addr(entry)) {
assert(th->ustack);
- ptr_t ustack_top = align_stack(th->ustack->end - 1);
- ustack_top -= 16; // pre_allocate a 16 byte for inject parameter
- hart_user_transfer(&transition, th->kstack, ustack_top, entry);
-
- th->ustack_top = ustack_top;
+ hart_user_transfer(&transition, th->kstack, th->ustack_top, entry);
}
else {
hart_kernel_transfer(&transition, th->kstack, entry);
return NULL;
}
-__DEFINE_LXSYSCALL4(int, th_create, tid_t*, tid, struct uthread_info*, thinfo,
- void*, entry, void*, param)
+__DEFINE_LXSYSCALL3(int, th_create, tid_t*, tid,
+ struct uthread_param*, thparam, void*, entry)
{
struct thread* th = create_thread(__current, true);
if (!th) {
return EAGAIN;
}
- start_thread(th, (ptr_t)entry);
+ ptr_t ustack_top;
+
+ ustack_top = th->ustack_top;
+ ustack_top = align_stack(ustack_top - sizeof(*thparam));
- ptr_t ustack_top = th->ustack_top;
- *((void**)ustack_top) = param;
+ memcpy((void*)ustack_top, thparam, sizeof(*thparam));
- thinfo->th_stack_sz = region_size(th->ustack);
- thinfo->th_stack_top = (void*)ustack_top;
+ th->ustack_top = ustack_top;
+ start_thread(th, (ptr_t)entry);
if (tid) {
*tid = th->tid;
char base_char[] = "0123456789abcdefghijklmnopqrstuvwxyz";
static char*
-__uitoa_internal(unsigned int value, char* str, int base, unsigned int* size)
+__uitoa_internal(unsigned long value, char* str, int base, unsigned int* size)
{
unsigned int ptr = 0;
do {
str[ptr] = base_char[value % base];
- value = value / base;
+ value = value / (unsigned long)base;
ptr++;
} while (value);
}
static char*
-__itoa_internal(int value, char* str, int base, unsigned int* size)
+__itoa_internal(long value, char* str, int base, unsigned int* size)
{
if (value < 0 && base == 10) {
str[0] = '-';
- unsigned int _v = (unsigned int)(-value);
+ unsigned long _v = (unsigned long)(-value);
__uitoa_internal(_v, str + 1, base, size);
} else {
__uitoa_internal(value, str, base, size);
}
char*
-itoa(int value, char* str, int base)
+itoa(long value, char* str, int base)
{
return __itoa_internal(value, str, base, NULL);
}
\ No newline at end of file
--- /dev/null
+#ifndef __LUNAIX_BASE_LD_INC
+#define __LUNAIX_BASE_LD_INC
+
+#define __LD__
+#include <linking/base_defs.ld.inc>
+
+#endif /* __LUNAIX_BASE_LD_INC */
--- /dev/null
+.text BLOCK(PAGE_GRAN) : AT ( ADDR(.text) - KEXEC_BASE )
+{
+ *(.text)
+}
+
+.kf.preempt BLOCK(PAGE_GRAN) : AT ( ADDR(.kf.preempt) - KEXEC_BASE )
+{
+ PROVIDE(__kf_preempt_start = .);
+
+ KEEP(*(.kf.preempt));
+
+ PROVIDE(__kf_preempt_end = .);
+}
+
+PROVIDE(__kexec_text_end = .);
+
+.data BLOCK(PAGE_GRAN) : AT ( ADDR(.data) - KEXEC_BASE )
+{
+ *(.data)
+}
+
+.rodata BLOCK(PAGE_GRAN) : AT ( ADDR(.rodata) - KEXEC_BASE )
+{
+ *(.rodata)
+ *(.rodata.*)
+}
+
+.kpg BLOCK(PAGE_GRAN) : AT ( ADDR(.kpg) - KEXEC_BASE )
+{
+ *(.kpg)
+}
\ No newline at end of file
--- /dev/null
+#include "base.ldx"
+
+.lga BLOCK(PAGE_GRAN) : AT ( ADDR(.lga) - KEXEC_BASE )
+{
+ PROVIDE(__lga_twiplugin_inits_start = .);
+
+ KEEP(*(.lga.twiplugin_inits));
+
+ PROVIDE(__lga_twiplugin_inits_end = .);
+
+ /* ---- */
+
+ /* align to 8 bytes, so it can cover both 32 and 64 bits address line*/
+ . = ALIGN(8);
+
+ PROVIDE(__lga_devdefs_start = .);
+
+ KEEP(*(.lga.devdefs));
+
+ PROVIDE(__lga_devdefs_end = .);
+
+ /* ---- */
+
+ . = ALIGN(8);
+
+ PROVIDE(__lga_dev_ld_kboot_start = .);
+
+ KEEP(*(.lga.devdefs.ld_kboot));
+
+ PROVIDE(__lga_dev_ld_kboot_end = .);
+
+ /* ---- */
+
+ . = ALIGN(8);
+
+ PROVIDE(__lga_dev_ld_sysconf_start = .);
+
+ KEEP(*(.lga.devdefs.ld_sysconf));
+
+ PROVIDE(__lga_dev_ld_sysconf_end = .);
+
+ /* ---- */
+
+ . = ALIGN(8);
+
+ PROVIDE(__lga_dev_ld_timedev_start = .);
+
+ KEEP(*(.lga.devdefs.ld_timedev));
+
+ PROVIDE(__lga_dev_ld_timedev_end = .);
+
+ /* ---- */
+
+ . = ALIGN(8);
+
+ PROVIDE(__lga_dev_ld_post_start = .);
+
+ KEEP(*(.lga.devdefs.ld_post));
+
+ PROVIDE(__lga_dev_ld_post_end = .);
+
+ /* ---- */
+
+ . = ALIGN(8);
+
+ PROVIDE(__lga_fs_start = .);
+
+ KEEP(*(.lga.fs));
+
+ PROVIDE(__lga_fs_end = .);
+
+ /* ---- */
+
+ . = ALIGN(8);
+
+ PROVIDE(__lga_lunainit_on_earlyboot_start = .);
+
+ KEEP(*(.lga.lunainit.c_earlyboot));
+
+ PROVIDE(__lga_lunainit_on_earlyboot_end = .);
+
+ /* ---- */
+
+ . = ALIGN(8);
+
+ PROVIDE(__lga_lunainit_on_boot_start = .);
+
+ KEEP(*(.lga.lunainit.c_boot));
+
+ PROVIDE(__lga_lunainit_on_boot_end = .);
+
+ /* ---- */
+
+ . = ALIGN(8);
+
+ PROVIDE(__lga_lunainit_on_postboot_start = .);
+
+ KEEP(*(.lga.lunainit.c_postboot));
+
+ PROVIDE(__lga_lunainit_on_postboot_end = .);
+}
\ No newline at end of file
+++ /dev/null
-ENTRY(start_)
-
-SECTIONS {
- . = 0x100000;
- __kboot_start = .;
-
- /* 这里是我们的高半核初始化代码段和数据段 */
- .boot.text BLOCK(4K) :
- {
- *(.multiboot)
- *(.boot.text)
- }
-
- .boot.bss BLOCK(4K) :
- {
- *(.boot.bss)
- }
-
- .boot.data BLOCK(4K) :
- {
- *(.boot.data)
- }
-
- .boot.rodata BLOCK(4K) :
- {
- *(.boot.rodata)
- }
-
- .boot.bss BLOCK(4K) :
- {
- *(.boot.rodata)
- }
- __kboot_end = ALIGN(4K);
-
- /* ---- boot end ---- */
-
- /* ---- kernel start ---- */
-
- . += 0xC0000000;
-
- /* 好了,我们的内核…… */
-
- PROVIDE(__kexec_text_start = ALIGN(4K));
-
- .text BLOCK(4K) : AT ( ADDR(.text) - 0xC0000000 )
- {
- __kexec_start = .;
-
- *(.text)
- }
-
- .kf.preempt BLOCK(4K) : AT ( ADDR(.kf.preempt) - 0xC0000000 )
- {
- PROVIDE(__kf_preempt_start = .);
-
- KEEP(*(.kf.preempt));
-
- PROVIDE(__kf_preempt_end = .);
- }
-
- PROVIDE(__kexec_text_end = .);
-
- .data BLOCK(4K) : AT ( ADDR(.data) - 0xC0000000 )
- {
- *(.data)
- }
-
- .rodata BLOCK(4K) : AT ( ADDR(.rodata) - 0xC0000000 )
- {
- *(.rodata)
- }
-
- .kpg BLOCK(4K) : AT ( ADDR(.kpg) - 0xC0000000 )
- {
- *(.kpg)
- }
-
- . = ALIGN(4K);
-
- /* for generated array, we align to address line size */
-
- .lga BLOCK(4K) : AT ( ADDR(.lga) - 0xC0000000 )
- {
- PROVIDE(__lga_twiplugin_inits_start = .);
-
- KEEP(*(.lga.twiplugin_inits));
-
- PROVIDE(__lga_twiplugin_inits_end = .);
-
- /* ---- */
-
- /* align to 8 bytes, so it can cover both 32 and 64 bits address line*/
- . = ALIGN(8);
-
- PROVIDE(__lga_devdefs_start = .);
-
- KEEP(*(.lga.devdefs));
-
- PROVIDE(__lga_devdefs_end = .);
-
- /* ---- */
-
- . = ALIGN(8);
-
- PROVIDE(__lga_dev_ld_kboot_start = .);
-
- KEEP(*(.lga.devdefs.ld_kboot));
-
- PROVIDE(__lga_dev_ld_kboot_end = .);
-
- /* ---- */
-
- . = ALIGN(8);
-
- PROVIDE(__lga_dev_ld_sysconf_start = .);
-
- KEEP(*(.lga.devdefs.ld_sysconf));
-
- PROVIDE(__lga_dev_ld_sysconf_end = .);
-
- /* ---- */
-
- . = ALIGN(8);
-
- PROVIDE(__lga_dev_ld_timedev_start = .);
-
- KEEP(*(.lga.devdefs.ld_timedev));
-
- PROVIDE(__lga_dev_ld_timedev_end = .);
-
- /* ---- */
-
- . = ALIGN(8);
-
- PROVIDE(__lga_dev_ld_post_start = .);
-
- KEEP(*(.lga.devdefs.ld_post));
-
- PROVIDE(__lga_dev_ld_post_end = .);
-
- /* ---- */
-
- . = ALIGN(8);
-
- PROVIDE(__lga_fs_start = .);
-
- KEEP(*(.lga.fs));
-
- PROVIDE(__lga_fs_end = .);
-
- /* ---- */
-
- . = ALIGN(8);
-
- PROVIDE(__lga_lunainit_on_earlyboot_start = .);
-
- KEEP(*(.lga.lunainit.c_earlyboot));
-
- PROVIDE(__lga_lunainit_on_earlyboot_end = .);
-
- /* ---- */
-
- . = ALIGN(8);
-
- PROVIDE(__lga_lunainit_on_boot_start = .);
-
- KEEP(*(.lga.lunainit.c_boot));
-
- PROVIDE(__lga_lunainit_on_boot_end = .);
-
- /* ---- */
-
- . = ALIGN(8);
-
- PROVIDE(__lga_lunainit_on_postboot_start = .);
-
- KEEP(*(.lga.lunainit.c_postboot));
-
- PROVIDE(__lga_lunainit_on_postboot_end = .);
-
- }
-
- .ksymtable BLOCK(4K) : AT ( ADDR(.ksymtable) - 0xC0000000 )
- {
- *(.ksymtable)
- }
-
- .bss BLOCK(4K) : AT ( ADDR(.bss) - 0xC0000000 )
- {
- *(.bss)
- }
-
- .bss.kstack BLOCK(4K) : AT ( ADDR(.bss.kstack) - 0xC0000000)
- {
- PROVIDE(__bsskstack_start = .);
-
- *(.bss.kstack)
-
- PROVIDE(__bsskstack_end = .);
- }
-
- __kexec_end = ALIGN(4K);
-}
\ No newline at end of file
--- /dev/null
+#define __LD__
+#include "base.ldx"
+
+ENTRY(ENTRY_POINT)
+
+SECTIONS {
+ . = LOAD_OFF;
+
+ #include <linking/boot_secs.ldx>
+
+ /* ---- kernel start ---- */
+
+ . += KEXEC_BASE;
+
+ PROVIDE(__kexec_text_start = ALIGN(PAGE_GRAN));
+ __kexec_start = ALIGN(PAGE_GRAN);
+
+
+ /* kernel executable sections */
+
+ #include "kernel.ldx"
+
+
+ /* link-time allocated array */
+
+ #include "lga.ldx"
+
+
+ /* All other stuff */
+
+ .ksymtable BLOCK(PAGE_GRAN) : AT ( ADDR(.ksymtable) - KEXEC_BASE )
+ {
+ *(.ksymtable)
+ }
+
+ .bss BLOCK(PAGE_GRAN) : AT ( ADDR(.bss) - KEXEC_BASE )
+ {
+ *(.bss)
+ }
+
+ .bss.kstack BLOCK(PAGE_GRAN) : AT ( ADDR(.bss.kstack) - KEXEC_BASE )
+ {
+ PROVIDE(__bsskstack_start = .);
+
+ *(.bss.kstack)
+
+ PROVIDE(__bsskstack_end = .);
+ }
+
+ __kexec_end = ALIGN(PAGE_GRAN);
+}
\ No newline at end of file
--- /dev/null
+#!/usr/bin/env bash
+
+hmp_port=45454
+gdb_port=1234
+default_cmd="console=/dev/ttyS0"
+
+make CMDLINE=${default_cmd} ARCH=${ARCH} MODE=debug image -j5 || exit -1
+
+./scripts/qemu.py \
+ scripts/qemus/qemu_x86_dev.json \
+ --qemu-dir "${QEMU_DIR}" \
+ -v KIMG=build/lunaix.iso \
+ -v QMPORT=${hmp_port} \
+ -v GDB_PORT=${gdb_port} \
+ -v ARCH=${ARCH} &
+
+QMPORT=${hmp_port} gdb build/bin/kernel.bin -ex "target remote localhost:${gdb_port}"
\ No newline at end of file
mkinc_dir := $(CURDIR)/makeinc
-include $(mkinc_dir)/os.mkinc
include $(mkinc_dir)/toolchain.mkinc
-include $(mkinc_dir)/qemu.mkinc
include $(mkinc_dir)/utils.mkinc
+include $(mkinc_dir)/lunabuild.mkinc
ARCH ?= i386
+MODE ?= debug
export ARCH
DEPS := $(CC) $(LD) $(AR) xorriso grub-mkrescue
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
+kimg := $(kbuild_dir)/lunaix.iso
$(DEPS):
@echo -n "checking $@ .... "
echo "failed" && exit 1;\
fi
-all_lconfigs = $(shell find . -name "LConfig")
-
$(kbuild_dir):
@mkdir -p $(kbin_dir)
@mkdir -p $(os_img_dir)
@mkdir -p $(os_img_dir)/boot/grub
@mkdir -p $(os_img_dir)/usr
-.builder/configs.h: $(all_lconfigs)
- @echo restarting configuration...
- @echo
- @./scripts/build-tools/luna_build.py --config --lconfig-file LConfig -o $(@D)
-
-.builder/lbuild.mkinc: .builder/configs.h
- @./scripts/build-tools/luna_build.py LBuild --lconfig-file LConfig -o $(@D)
-
.PHONY: kernel
export BUILD_DIR=$(kbin_dir)
export BUILD_NAME=$(kbin)
-kernel: .builder/lbuild.mkinc
+kernel: $(lbuild_mkinc)
$(call status,TASK,$(notdir $@))
+
@$(MAKE) $(MKFLAGS) -I $(mkinc_dir) -f kernel.mk all
+.NOTPARALLEL:
.PHONY: image
export KCMD=$(CMDLINE)
-export _OS_NAME=$(OS_NAME)
-image: usr/build kernel
+export LBUILD ARCH MODE
+image: $(kbuild_dir) kernel usr/build
$(call status,TASK,$(notdir $@))
+ $(call status,PACK,$(kimg))
+
@./scripts/grub/config-grub.sh $(os_img_dir)/boot/grub/grub.cfg
@cp -r usr/build/* $(os_img_dir)/usr
@cp -r $(kbin_dir)/* $(os_img_dir)/boot
@grub-mkrescue -o $(kimg) $(os_img_dir)\
- -- -volid "$(OS_ID) $(OS_VER)" -system_id "$(OS_NAME)"
+ -- -volid "$(OS_ID) $(OS_VER)" -system_id "$(OS_NAME)" \
+ -report_about FAILURE -abort_on FAILURE
usr/build: user
-check: $(DEPS) check-cc scripts/grub/GRUB_TEMPLATE
-
-prepare: check $(os_img_dir)
-
-export BUILD_MODE=release
-bootable: $(kbuild_dir) image
-
-export BUILD_MODE=debug
-bootable-debug: $(kbuild_dir) image
+prepare: $(os_img_dir)
+export LBUILD ARCH MODE
user:
- $(call status,$@)
+ $(call status,TASK,$@)
@$(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: bootable-debug
-
clean:
@$(MAKE) -C usr clean -I $(mkinc_dir)
@$(MAKE) -f kernel.mk clean -I $(mkinc_dir)
@rm -rf $(kbuild_dir) || exit 1
- @rm -f .builder/lbuild.mkinc || exit 1
-
-run: all
- @qemu-system-i386 $(call get_qemu_options,$(kimg))
- @sleep 1
- @telnet 127.0.0.1 $(QEMU_MON_PORT)
-
-debug-qemu: all-debug
- @objcopy --only-keep-debug $(kbin) $(kbuild_dir)/kernel.dbg
- @qemu-system-i386 $(call get_qemu_options,$(kimg))
- @sleep 1
- @QMPORT=$(QEMU_MON_PORT) gdb $(kbin) -ex "target remote localhost:1234"
-
-debug-qemu-vscode: all-debug
- @qemu-system-i386 $(call get_qemu_options,$(kimg))
- @sleep 0.5
- @telnet 127.0.0.1 $(QEMU_MON_PORT)
-
-debug-bochs: all-debug
- @bochs -q -f bochs.cfg
-
-debug-metal:
- @printf "@cmc" > $(PORT)
- @gdb -s $(kbuild_dir)/kernel.dbg -ex "target remote $(PORT)"
\ No newline at end of file
+ @rm -rf .builder || exit 1
\ No newline at end of file
--- /dev/null
+lbuild_dir := $(CURDIR)/.builder
+lbuild_config_h := $(lbuild_dir)/configs.h
+lbuild_mkinc := $(lbuild_dir)/lbuild.mkinc
+lconfig_save := $(CURDIR)/.config.json
+
+lbuild_opts := --lconfig-file LConfig
+
+all_lconfigs = $(shell find $(CURDIR) -name "LConfig")
+
+export
+$(lconfig_save): $(all_lconfigs)
+ @echo restarting configuration...
+ @$(LBUILD) --config $(lbuild_opts) --config-save $(lconfig_save) --force\
+ -o $(lbuild_dir)/
+
+export
+$(lbuild_config_h): $(lconfig_save)
+ @$(LBUILD) --config $(lbuild_opts) --config-save $(lconfig_save) -o $(@D)
+
+export
+$(lbuild_mkinc): $(lbuild_config_h)
+ @$(LBUILD) LBuild $(lbuild_opts) -o $(@D)
+
+.PHONY: config
+export
+config: $(all_lconfigs)
+ @$(LBUILD) --config $(lbuild_opts) --config-save $(lconfig_save) --force\
+ -o $(lbuild_dir)/
+++ /dev/null
-OS_NAME := lunaix
-OS_ID := LunaixOS
-OS_VER := dev$(shell date +%Y%m%d)
-
-INCLUDES := -Iincludes -Iincludes/usr
\ No newline at end of file
+++ /dev/null
-QEMU_MON_TERM := gnome-terminal
-QEMU_MON_PORT := 45454
-
-get_qemu_options = -s -S -m 1G \
- -smp 1 \
- -rtc base=utc \
- -no-reboot \
- -machine q35 \
- -cpu pentium3,rdrand \
- -no-shutdown \
- -d cpu_reset \
- -d trace:ide_dma_cb \
- -vga std,retrace=precise \
- -serial telnet::12345,server,nowait,logfile=lunaix_ttyS0.log\
- -drive id=cdrom,file="$(1)",readonly=on,if=none,format=raw \
- -device ahci,id=ahci \
- -device ide-cd,drive=cdrom,bus=ahci.0 \
- -monitor telnet::$(QEMU_MON_PORT),server,nowait,logfile=qm.log &
\ No newline at end of file
CC := $(CX_PREFIX)gcc
AS := $(CX_PREFIX)as
AR := $(CX_PREFIX)ar
+LBUILD ?= $(shell realpath ./scripts/build-tools/luna_build.py)
O := -O2
W := -Wall -Wextra -Werror \
CFLAGS := -std=gnu99 $(OFLAGS) $(W)
-ifeq ($(BUILD_MODE),debug)
+ifeq ($(MODE),debug)
O = -Og
CFLAGS += -g
endif
def resolve(self):
self.execute(self.__path)
- self.__env.add_sources(self.__do_process(self.__srcs))
- self.__env.add_headers(self.__do_process(self.__hdrs))
+ self.__env.add_sources(self.__srcs)
+ self.__env.add_headers(self.__hdrs)
def __do_process(self, list):
resolved = []
def __resolve_value(self, source):
resolved = source
- while not isinstance(resolved, str):
+ while isinstance(resolved, dict):
if isinstance(resolved, dict):
resolved = self.expand_select(resolved)
else:
self.__raise(f"entry with unknown type: {resolved}")
- resolved = resolved.strip()
- resolved = join_path(self.__dir, resolved)
+ if isinstance(resolved, list):
+ rs = []
+ for file in resolved:
+ file = join_path(self.__dir, file)
+ file = self.__env.to_wspath(file)
+ rs.append(file)
+ else:
+ rs = join_path(self.__dir, resolved)
+ rs = [self.__env.to_wspath(rs)]
- return self.__env.to_wspath(resolved)
+ return rs
def import_buildfile(self, path):
path = self.__resolve_value(path)
- path = self.__env.to_wspath(path)
-
- if (os.path.isdir(path)):
- path = os.path.join(path, "LBuild")
-
- if not os.path.exists(path):
- self.__raise("Build file not exist: %s", path)
+ for p in path:
+ if (os.path.isdir(p)):
+ p = os.path.join(p, "LBuild")
+
+ if not os.path.exists(p):
+ self.__raise("Build file not exist: %s", p)
- if os.path.abspath(path) == os.path.abspath(self.__path):
- self.__raise("self dependency detected")
+ if os.path.abspath(p) == os.path.abspath(self.__path):
+ self.__raise("self dependency detected")
- LunaBuildFile(self.__env, path).resolve()
+ LunaBuildFile(self.__env, p).resolve()
def export_sources(self, src):
- if not isinstance(src, list):
- src = [src]
+ src = self.__resolve_value(src)
self.__srcs += src
def export_headers(self, hdr):
- if not isinstance(hdr, list):
- hdr = [hdr]
+ hdr = self.__resolve_value(hdr)
self.__hdrs += hdr
def check_config(self, name):
def v(env, caller, term):
node = env.lookup_node(term.__name__)
env.dependency().add(node, caller)
-
- return env.lookup_value(node.get_name())
+ return env.resolve_symbol(node.get_name())
@contextual(caller_type=[LCModuleNode])
def include(env, caller, file):
def default(env, caller, val):
caller.set_default(val)
+@contextual(caller_type=[LCTermNode])
+def set_value(env, caller, val):
+ caller.set_value(val)
+
@builtin()
def env(env, key, default=None):
return os.getenv(key, default)
\ No newline at end of file
import os.path as path
import ast, json
-from .lcnodes import LCModuleNode
+from .lcnodes import LCModuleNode, LCTermNode
from .api import (
ConfigLoadException,
Renderable
if current in self._edges:
for x in self._edges[current]:
q.append(x)
- current.evaluate()
+ if current != start:
+ current.evaluate()
class ConfigTypeFactory:
def __init__(self) -> None:
def lookup_value(self, key):
return self.__config_val[key]
+ def resolve_symbol(self, sym):
+ term_node = self.__node_table[sym]
+ if isinstance(term_node, LCTermNode):
+ if not term_node.is_ready():
+ term_node.evaluate()
+ return term_node.get_value()
+ raise Exception(f"fail to resolve symbol: {sym}, not resolvable")
+
def dependency(self):
return self.__deps_graph
self._default = None
self._type = None
self._rdonly = False
+ self._ready = False
super().__init__(fo, astn)
self.__assert_type(val)
self._value = val
+
+ self._ready = True
self.__update_value()
self._env.dependency().cascade(self)
+
def set_default(self, val):
self.__assert_type(val)
def get_value(self):
return self._value
+ def is_ready(self):
+ return self._ready
+
def evaluate(self):
super().evaluate()
self.__update_value()
env.register_builtin_func(builtin.default)
env.register_builtin_func(builtin.include)
env.register_builtin_func(builtin.env)
+ env.register_builtin_func(builtin.set_value)
env.type_factory().regitser(lcfg_type.PrimitiveType)
env.type_factory().regitser(lcfg_type.MultipleChoiceType)
return env
-def do_config(lcfg_env):
+def do_config(opt, lcfg_env):
+ redo_config = not exists(opt.config_save) or opt.force
+ if not redo_config:
+ return
+
shell = InteractiveShell(lcfg_env)
if not shell.render_loop():
print("Configuration aborted.")
exit(-1)
- lcfg_env.export()
- lcfg_env.save()
-
def do_buildfile_gen(opts, lcfg_env):
root_path = abspath(opts.root)
ws_path = dirname(root_path)
parser = ArgumentParser()
parser.add_argument("--config", action="store_true", default=False)
parser.add_argument("--lconfig-file", default="LConfig")
+ parser.add_argument("--config-save", default=".config.json")
+ parser.add_argument("--force", action="store_true", default=False)
parser.add_argument("root", nargs="?", default="LBuild")
parser.add_argument("-o", "--out-dir", required=True)
mkdir(out_dir)
lcfg_env = prepare_lconfig_env(out_dir)
- lcfg_env.resolve_module(opts.lconfig_file)
- lcfg_env.update()
- lcfg_env.load()
-
+ require_config = exists(opts.lconfig_file)
+ try:
+ if require_config:
+ lcfg_env.resolve_module(opts.lconfig_file)
+ lcfg_env.update()
+ lcfg_env.load()
+ except Exception as e:
+ print(e)
+
if opts.config:
- do_config(lcfg_env)
+ if require_config:
+ do_config(opts, lcfg_env)
+ else:
+ print("No configuration file detected, skipping...")
+ lcfg_env.save(opts.config_save)
+ lcfg_env.export()
else:
do_buildfile_gen(opts, lcfg_env)
bin=$2
nm_out=$(nm -nfbsd "$bin")
+class_info=$(readelf -h "$bin" | grep 'Class:' | awk '{print $2}')
+
allsyms=($nm_out)
allsyms_len=${#allsyms[@]}
+dtype="4byte"
+if [ "$class_info" == 'ELF64' ]; then
+ dtype="8byte"
+fi
+
syms_idx=()
for (( i=0; i<allsyms_len; i+=3));
echo '.section .ksymtable, "a", @progbits'
echo " .global __lunaix_ksymtable"
echo " __lunaix_ksymtable:"
-echo " .long $syms_len"
+echo " .$dtype $syms_len"
echo " .align 8"
for i in "${syms_idx[@]}"
type=${allsyms[$i + 1]}
sym=${allsyms[$i + 2]}
- echo "$(cat <<EOF
- .long 0x$addr
- .long __S$sym
+ cat <<EOF
+ .$dtype 0x$addr
+ .$dtype __S$sym
.align 8
EOF
-)"
assoc_array["$sym"]=1
done
for sym_str in "${!assoc_array[@]}"
do
- echo "$(cat <<EOF
+ cat <<EOF
__S$sym_str:
.asciz "$sym_str"
.align 8
EOF
-)"
done
\ No newline at end of file
default=0
timeout=0
-menuentry "$_OS_NAME" {
+menuentry "lunaix" {
multiboot /boot/kernel.bin $KCMD
}
\ No newline at end of file
--- /dev/null
+#!/usr/bin/env python
+
+import subprocess, time, os, re, argparse, json
+from pathlib import PurePosixPath
+
+g_lookup = {}
+
+subsitution = re.compile(r"\$[A-Za-z_][A-Za-z0-9_]*")
+
+def do_expand(val, path):
+ global g_lookup
+
+ parts = []
+ prev_pos = 0
+ iters = subsitution.finditer(val)
+ for _, m in enumerate(iters, start=1):
+ start_pos = m.start()
+ end_pos = m.end()
+
+ parts.append(val[prev_pos:start_pos])
+
+ key = val[start_pos + 1:end_pos]
+ if key not in g_lookup:
+ raise Exception(
+ f"reference key {key} (config: {path}) is not defined")
+
+ parts.append(g_lookup[key])
+ prev_pos = end_pos
+
+ parts.append(val[prev_pos:])
+ return "".join(parts)
+
+def get_config(opt, path, default=None, required=False):
+ _path = PurePosixPath(path)
+ for p in _path.parts:
+ if p in opt:
+ opt = opt[p]
+ continue
+ if required:
+ raise Exception(f"config: {path} is required")
+ return default
+
+ if not isinstance(opt, str):
+ return opt
+
+ return do_expand(opt, path)
+
+def join_attrs(attrs):
+ return ",".join(attrs)
+
+def parse_protocol(opt):
+ protocol = get_config(opt, "protocol", "telnet")
+ addr = get_config(opt, "addr", ":12345")
+ logfile = get_config(opt, "logfile")
+
+ return (f"{protocol}:{addr}", logfile)
+
+class QEMUPeripherals:
+ def __init__(self, name, opt) -> None:
+ self.name = name
+ self._opt = opt
+
+ def get_qemu_opts(self) -> list:
+ pass
+
+class BasicSerialDevice(QEMUPeripherals):
+ def __init__(self, opt) -> None:
+ super().__init__("serial", opt)
+
+ def get_qemu_opts(self):
+ link, logfile = parse_protocol(self._opt)
+
+ cmds = [ link, "server", "nowait" ]
+ if logfile:
+ cmds.append(f"logfile={logfile}")
+ return [ "-serial", join_attrs(cmds) ]
+
+class PCISerialDevice(QEMUPeripherals):
+ def __init__(self, opt) -> None:
+ super().__init__("pci-serial", opt)
+
+ def get_qemu_opts(self):
+ name = f"chrdev.{hex(self.__hash__())[2:]}"
+ cmds = [ "pci-serial", f"chardev={name}" ]
+ chrdev = [ "file", f"id={name}" ]
+
+ logfile = get_config(self._opt, "logfile", required=True)
+ chrdev.append(f"path={logfile}")
+ ()
+ return [
+ "-chardev", join_attrs(chrdev),
+ "-device", join_attrs(cmds)
+ ]
+
+class AHCIBus(QEMUPeripherals):
+ def __init__(self, opt) -> None:
+ super().__init__("ahci", opt)
+
+ def get_qemu_opts(self):
+ opt = self._opt
+ name: str = get_config(opt, "name", required=True)
+ name = name.strip().replace(" ", "_")
+ cmds = [ "-device", f"ahci,id={name}" ]
+
+ for i, disk in enumerate(get_config(opt, "disks", default=[])):
+ d_type = get_config(disk, "type", default="ide-hd")
+ d_img = get_config(disk, "img", required=True)
+ d_ro = get_config(disk, "ro", default=False)
+ d_fmt = get_config(disk, "format", default="raw")
+ d_id = f"disk_{i}"
+
+ cmds += [
+ "-drive", join_attrs([
+ f"id={d_id},"
+ f"file={d_img}",
+ f"readonly={'on' if d_ro else 'off'}",
+ f"if=none",
+ f"format={d_fmt}"
+ ]),
+ "-device", join_attrs([
+ d_type,
+ f"drive={d_id}",
+ f"bus={name}.{i}"
+ ])
+ ]
+
+ return cmds
+
+class RTCDevice(QEMUPeripherals):
+ def __init__(self, opt) -> None:
+ super().__init__("rtc", opt)
+
+ def get_qemu_opts(self):
+ opt = self._opt
+ base = get_config(opt, "base", default="utc")
+ return [ "-rtc", f"base={base}" ]
+
+class QEMUMonitor(QEMUPeripherals):
+ def __init__(self, opt) -> None:
+ super().__init__("monitor", opt)
+
+ def get_qemu_opts(self):
+ link, logfile = parse_protocol(self._opt)
+
+ return [
+ "-monitor", join_attrs([
+ link,
+ "server",
+ "nowait",
+ f"logfile={logfile}"
+ ])
+ ]
+
+class QEMUExec:
+ devices = {
+ "basic_serial": BasicSerialDevice,
+ "ahci": AHCIBus,
+ "rtc": RTCDevice,
+ "hmp": QEMUMonitor,
+ "pci-serial": PCISerialDevice
+ }
+
+ def __init__(self, options) -> None:
+ self._opt = options
+ self._devices = []
+
+ for dev in get_config(options, "devices", default=[]):
+ dev_class = get_config(dev, "class")
+ if dev_class not in QEMUExec.devices:
+ raise Exception(f"device class: {dev_class} is not defined")
+
+ self._devices.append(QEMUExec.devices[dev_class](dev))
+
+ def get_qemu_exec_name(self):
+ pass
+
+ def get_qemu_arch_opts(self):
+ cmds = [
+ "-machine", get_config(self._opt, "machine"),
+ "-cpu", join_attrs([
+ get_config(self._opt, "cpu/type", required=True),
+ *get_config(self._opt, "cpu/features", default=[]),
+ ])
+ ]
+
+ return cmds
+
+ def get_qemu_debug_opts(self):
+ cmds = [ "-no-reboot", "-no-shutdown" ]
+ debug = get_config(self._opt, "debug")
+ if not debug:
+ return cmds
+
+ cmds.append("-S")
+ cmds += [ "-gdb", f"tcp::{get_config(debug, 'gdb_port', default=1234)}" ]
+
+ trace_opts = get_config(debug, "traced", [])
+ for trace in trace_opts:
+ cmds += [ "-d", f"trace:{trace}"]
+
+ return cmds
+
+ def get_qemu_general_opts(self):
+ return [
+ "-m", get_config(self._opt, "memory", required=True),
+ "-smp", get_config(self._opt, "ncpu", default=1)
+ ]
+
+ def add_peripheral(self, peripheral):
+ self._devices.append(peripheral)
+
+ def start(self, qemu_dir_override=""):
+ qemu_path = self.get_qemu_exec_name()
+ qemu_path = os.path.join(qemu_dir_override, qemu_path)
+ cmds = [
+ qemu_path,
+ *self.get_qemu_arch_opts(),
+ *self.get_qemu_debug_opts()
+ ]
+
+ for dev in self._devices:
+ cmds += dev.get_qemu_opts()
+
+ print(" ".join(cmds), "\n")
+
+ handle = subprocess.Popen(cmds)
+
+ while True:
+ ret_code = handle.poll()
+ if ret_code is not None:
+ return ret_code
+ time.sleep(5)
+
+class QEMUx86Exec(QEMUExec):
+ def __init__(self, options) -> None:
+ super().__init__(options)
+
+ def get_qemu_exec_name(self):
+ if get_config(self._opt, "arch") in ["i386", "x86_32"]:
+ return "qemu-system-i386"
+ else:
+ return "qemu-system-x86_64"
+
+def main():
+ global g_lookup
+
+ arg = argparse.ArgumentParser()
+
+ arg.add_argument("config_file")
+ arg.add_argument("--qemu-dir", default="")
+ arg.add_argument("-v", "--values", action='append', default=[])
+
+ arg_opt = arg.parse_args()
+
+ opts = {}
+ with open(arg_opt.config_file, 'r') as f:
+ opts.update(json.loads(f.read()))
+
+ for kv in arg_opt.values:
+ [k, v] = kv.split('=')
+ g_lookup[k] = v
+
+ arch = get_config(opts, "arch")
+
+ q = None
+ if arch in ["i386", "x86_32", "x86_64"]:
+ q = QEMUx86Exec(opts)
+ else:
+ raise Exception(f"undefined arch: {arch}")
+
+ q.start(arg_opt.qemu_dir)
+
+if __name__ == "__main__":
+ try:
+ main()
+ except Exception as e:
+ print(e)
\ No newline at end of file
--- /dev/null
+{
+ "arch": "$ARCH",
+ "memory": "1G",
+ "machine": "q35",
+ "cpu": {
+ "type": "base",
+ "features": [
+ "rdrand",
+ "clflush",
+ "lm",
+ "nx",
+ "syscall",
+ "mca",
+ "pse36",
+ "pcid",
+ "invpcid",
+ "cmov",
+ "apic"
+ ]
+ },
+ "debug": {
+ "gdb_port": "$GDB_PORT",
+ "traced": [
+ "x86_recv_fault",
+ "ide_dma_cb"
+ ]
+ },
+ "devices": [
+ {
+ "class": "basic_serial",
+ "protocol": "telnet",
+ "addr": ":12345",
+ "logfile": "lunaix_ttyS0.log"
+ },
+ {
+ "class": "rtc",
+ "base": "utc"
+ },
+ {
+ "class": "ahci",
+ "name": "ahci_0",
+ "disks": [
+ {
+ "type": "ide-cd",
+ "img": "$KIMG",
+ "ro": true,
+ "format": "raw"
+ }
+ ]
+ },
+ {
+ "class": "hmp",
+ "protocol": "telnet",
+ "addr": ":$QMPORT",
+ "logfile": "qm.log"
+ }
+ ]
+}
\ No newline at end of file
*.o
build/
-.vscode/
\ No newline at end of file
+.vscode/
+
+uexec.ld
\ No newline at end of file
--- /dev/null
+sources([
+ "testp",
+ "ls",
+ "signal_demo",
+ "cat",
+ "stat",
+ "test_pthread"
+])
+
+compile_opts([
+ "-ffreestanding",
+ "-fno-pie"
+])
+
+linking_opts([
+ "-nostdlib",
+ "-nolibc",
+ "-z noexecstack",
+ "-no-pie",
+])
+
+linking_opts([
+ "-Wl,--build-id=none"
+])
+
+if config("arch") == "x86_64":
+ compile_opts([
+ "-m64",
+ "-fno-unwind-tables",
+ "-fno-asynchronous-unwind-tables",
+ "-mcmodel=large"
+ ])
+ linking_opts([
+ "-m64",
+ ])
+else:
+ compile_opts("-m32")
+ linking_opts("-m32")
--- /dev/null
+@Term
+def arch():
+ """
+ set the ISA target
+ """
+ type(["i386", "x86_64", "aarch64", "rv64"])
+ default("i386")
+
+ env_val = env("ARCH")
+ if env_val is not None:
+ set_value(env_val)
\ No newline at end of file
+++ /dev/null
-testp
-ls
-signal_demo
-cat
-stat
-test_pthread
\ No newline at end of file
return 0;
}
+const char* sh_argv[] = { "/usr/bin/sh", 0 };
+const char* sh_envp[] = { 0 };
+
int
main(int argc, const char** argv)
{
pid_t pid;
int err = 0;
if (!(pid = fork())) {
- err = execve("/usr/bin/sh", NULL, NULL);
+
+
+ err = execve(sh_argv[0], sh_argv, sh_envp);
printf("fail to execute (%d)\n", errno);
_exit(err);
}
--- /dev/null
+sources([
+ "src/string.c",
+ "src/termios.c",
+ "src/itoa.c",
+ "src/_vprintf.c",
+ "src/readdir.c",
+ "src/pthread.c",
+ "src/printf.c"
+])
+
+sources([
+ "src/posix/signal.c",
+ "src/posix/mount.c",
+ "src/posix/errno.c",
+ "src/posix/ioctl.c",
+ "src/posix/fcntl.c",
+ "src/posix/dirent.c",
+ "src/posix/unistd.c",
+ "src/posix/mann.c",
+ "src/posix/lunaix.c"
+])
+
+use({
+ env("ARCH"): {
+ "i386": "arch/i386",
+ "x86_64": "arch/x86_64",
+ }
+})
\ No newline at end of file
--- /dev/null
+sources([
+ "crt0.S",
+ "syscall.S",
+ "trampoline.S",
+])
+
+compile_opts("-m32")
+linking_opts("-m32")
\ No newline at end of file
.section .text
.global _start
_start:
- xorl %eax, %eax
xorl %ebp, %ebp
+ movl %esp, %eax
+ andl $-16, %esp
+
+ leal 4(%eax), %ebx
+ pushl %ebx
+ pushl (%eax)
+
fninit
+
+ xorl %eax, %eax
call main
1:
+++ /dev/null
-#include "syscall.h"
-#include <lunaix/dirent_defs.h>
-
-__LXSYSCALL2(int, sys_readdir, int, fd, struct lx_dirent*, dent)
+++ /dev/null
-#include "syscall.h"
-#include <errno.h>
-
-__LXSYSCALL(int, geterrno);
\ No newline at end of file
+++ /dev/null
-#include "syscall.h"
-#include <fcntl.h>
-
-__LXSYSCALL2(int, open, const char*, path, int, options)
-
-__LXSYSCALL2(int, fstat, int, fd, struct file_stat*, stat)
+++ /dev/null
-#include "syscall.h"
-#include <lunaix/ioctl.h>
-
-__LXSYSCALL2_VARG(int, ioctl, int, fd, int, req);
\ No newline at end of file
+++ /dev/null
-#include "syscall.h"
-#include <lunaix/types.h>
-
-__LXSYSCALL(void, yield);
-
-__LXSYSCALL1(pid_t, wait, int*, status);
-
-__LXSYSCALL3(pid_t, waitpid, pid_t, pid, int*, status, int, options);
-
-__LXSYSCALL2_VARG(void, syslog, int, level, const char*, fmt);
-
-__LXSYSCALL3(int, realpathat, int, fd, char*, buf, size_t, size)
+++ /dev/null
-#include "syscall.h"
-#include <lunaix/types.h>
-
-__LXSYSCALL2_VARG(void*, sys_mmap, void*, addr, size_t, length);
-
-void*
-mmap(void* addr, size_t length, int proct, int flags, int fd, off_t offset)
-{
- return sys_mmap(addr, length, proct, fd, offset, flags);
-}
-
-__LXSYSCALL2(void, munmap, void*, addr, size_t, length)
+++ /dev/null
-#include "syscall.h"
-
-__LXSYSCALL4(int,
- mount,
- const char*,
- source,
- const char*,
- target,
- const char*,
- fstype,
- int,
- options)
-
-__LXSYSCALL1(int, unmount, const char*, target)
\ No newline at end of file
#define LUNAIX_SYSCALL 33
#define regsize 4
- .struct 8
-saved_registers:
- .struct saved_registers + 5 * regsize
+ .struct 2 * regsize # eip, ebp
id:
.struct id + regsize
a1:
.section .text
.type do_lunaix_syscall, @function
.global do_lunaix_syscall
+
do_lunaix_syscall:
push %ebp
movl %esp, %ebp
pushl %ebx
- pushl %ecx
- pushl %edx
pushl %edi
pushl %esi
-
- movl id(%esp), %eax
- movl a1(%esp), %ebx
- movl a2(%esp), %ecx
- movl a3(%esp), %edx
- movl a4(%esp), %edi
- movl a5(%esp), %esi
+
+ movl id(%ebp), %eax
+ movl a1(%ebp), %ebx
+ movl a2(%ebp), %ecx
+ movl a3(%ebp), %edx
+ movl a4(%ebp), %edi
+ movl a5(%ebp), %esi
int $LUNAIX_SYSCALL
popl %esi
popl %edi
- popl %edx
- popl %ecx
popl %ebx
leave
+++ /dev/null
-#ifndef __LUNAIX_SYSCALL_H
-#define __LUNAIX_SYSCALL_H
-#include <lunaix/syscallid.h>
-
-#define asmlinkage __attribute__((regparm(0)))
-
-#define __PARAM_MAP1(t1, p1) t1 p1
-#define __PARAM_MAP2(t1, p1, ...) t1 p1, __PARAM_MAP1(__VA_ARGS__)
-#define __PARAM_MAP3(t1, p1, ...) t1 p1, __PARAM_MAP2(__VA_ARGS__)
-#define __PARAM_MAP4(t1, p1, ...) t1 p1, __PARAM_MAP3(__VA_ARGS__)
-#define __PARAM_MAP5(t1, p1, ...) t1 p1, __PARAM_MAP4(__VA_ARGS__)
-#define __PARAM_MAP6(t1, p1, ...) t1 p1, __PARAM_MAP5(__VA_ARGS__)
-
-#define ___DOINT33(callcode, rettype) \
- int v; \
- asm volatile("int %1\n" : "=a"(v) : "i"(33), "a"(callcode)); \
- return (rettype)v;
-
-#define __LXSYSCALL(rettype, name) \
- rettype name() \
- { \
- ___DOINT33(__SYSCALL_##name, rettype) \
- }
-
-#define __LXSYSCALL1(rettype, name, t1, p1) \
- rettype name(__PARAM_MAP1(t1, p1)) \
- { \
- asm("" ::"b"(p1)); \
- ___DOINT33(__SYSCALL_##name, rettype) \
- }
-
-#define __LXSYSCALL2(rettype, name, t1, p1, t2, p2) \
- rettype name(__PARAM_MAP2(t1, p1, t2, p2)) \
- { \
- asm("\n" ::"b"(p1), "c"(p2)); \
- ___DOINT33(__SYSCALL_##name, rettype) \
- }
-
-#define __LXSYSCALL3(rettype, name, t1, p1, t2, p2, t3, p3) \
- rettype name(__PARAM_MAP3(t1, p1, t2, p2, t3, p3)) \
- { \
- asm("\n" ::"b"(p1), "c"(p2), "d"(p3)); \
- ___DOINT33(__SYSCALL_##name, rettype) \
- }
-
-#define __LXSYSCALL4(rettype, name, t1, p1, t2, p2, t3, p3, t4, p4) \
- rettype name(__PARAM_MAP4(t1, p1, t2, p2, t3, p3, t4, p4)) \
- { \
- asm("\n" ::"b"(p1), "c"(p2), "d"(p3), "D"(p4)); \
- ___DOINT33(__SYSCALL_##name, rettype) \
- }
-
-#define __LXSYSCALL5(rettype, name, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5) \
- rettype name(__PARAM_MAP5(t1, p1, t2, p2, t3, p3, t4, p4, t5, p5)) \
- { \
- asm("" ::"r"(p5), "b"(p1), "c"(p2), "d"(p3), "D"(p4), "S"(p5)); \
- ___DOINT33(__SYSCALL_##name, rettype) \
- }
-
-#define __LXSYSCALL2_VARG(rettype, name, t1, p1, t2, p2) \
- __attribute__((noinline)) rettype name(__PARAM_MAP2(t1, p1, t2, p2), ...) \
- { \
- /* No inlining! This depends on the call frame assumption */ \
- void* _last = (void*)&p2 + sizeof(void*); \
- asm("\n" ::"b"(p1), "c"(p2), "d"(_last)); \
- ___DOINT33(__SYSCALL_##name, rettype) \
- }
-
-#endif /* __LUNAIX_SYSCALL_H */
movl $__SYSCALL_sigreturn, %eax
popl %ebx
+ int $33
+
+ .global th_trampoline
+ th_trampoline:
+ movl (%esp), %eax
+ movl 4(%esp), %ebx
+ pushl %ebx
+
+ call *(%eax)
+
+ movl %eax, %ebx
+ movl $__SYSCALL_th_exit, %eax
int $33
\ No newline at end of file
+++ /dev/null
-#include "syscall.h"
-#include <lunaix/types.h>
-
-__LXSYSCALL(pid_t, fork)
-
-__LXSYSCALL1(int, brk, void*, addr)
-
-__LXSYSCALL1(void*, sbrk, ssize_t, size)
-
-__LXSYSCALL(pid_t, getpid)
-
-__LXSYSCALL(pid_t, getppid)
-
-__LXSYSCALL(pid_t, getpgid)
-
-__LXSYSCALL2(pid_t, setpgid, pid_t, pid, pid_t, pgid)
-
-__LXSYSCALL1(void, _exit, int, status)
-
-__LXSYSCALL1(unsigned int, sleep, unsigned int, seconds)
-
-__LXSYSCALL(int, pause)
-
-__LXSYSCALL1(unsigned int, alarm, unsigned int, seconds)
-
-__LXSYSCALL2(int, link, const char*, oldpath, const char*, newpath)
-
-__LXSYSCALL1(int, rmdir, const char*, pathname)
-
-__LXSYSCALL3(int, read, int, fd, void*, buf, size_t, count)
-
-__LXSYSCALL3(int, write, int, fd, void*, buf, size_t, count)
-
-__LXSYSCALL3(int, readlink, const char*, path, char*, buf, size_t, size)
-
-__LXSYSCALL3(int, lseek, int, fd, off_t, offset, int, options)
-
-__LXSYSCALL1(int, unlink, const char*, pathname)
-
-__LXSYSCALL1(int, close, int, fd)
-
-__LXSYSCALL2(int, dup2, int, oldfd, int, newfd)
-
-__LXSYSCALL1(int, dup, int, oldfd)
-
-__LXSYSCALL1(int, fsync, int, fildes)
-
-__LXSYSCALL2(int, symlink, const char*, pathname, const char*, link_target)
-
-__LXSYSCALL1(int, chdir, const char*, path)
-
-__LXSYSCALL1(int, fchdir, int, fd)
-
-__LXSYSCALL2(char*, getcwd, char*, buf, size_t, size)
-
-__LXSYSCALL2(int, rename, const char*, oldpath, const char*, newpath)
-
-__LXSYSCALL4(int,
- getxattr,
- const char*,
- path,
- const char*,
- name,
- void*,
- value,
- size_t,
- len)
-
-__LXSYSCALL4(int,
- setxattr,
- const char*,
- path,
- const char*,
- name,
- void*,
- value,
- size_t,
- len)
-
-__LXSYSCALL4(int,
- fgetxattr,
- int,
- fd,
- const char*,
- name,
- void*,
- value,
- size_t,
- len)
-
-__LXSYSCALL4(int,
- fsetxattr,
- int,
- fd,
- const char*,
- name,
- void*,
- value,
- size_t,
- len)
-
-__LXSYSCALL4(int,
- readlinkat,
- int,
- dirfd,
- const char*,
- pathname,
- char*,
- buf,
- size_t,
- size)
-
-__LXSYSCALL2(int, unlinkat, int, fd, const char*, pathname)
-
-__LXSYSCALL1(int, mkdir, const char*, path)
-
-__LXSYSCALL3(int,
- execve,
- const char*,
- filename,
- const char**,
- argv,
- const char**,
- envp)
\ No newline at end of file
--- /dev/null
+sources([
+ "crt0.S",
+ "syscall.S",
+ "trampoline.S",
+])
+
+compile_opts("-m64")
+linking_opts("-m64")
\ No newline at end of file
--- /dev/null
+#define __ASM__
+#include <lunaix/syscallid.h>
+
+.section .data
+ .global environ
+ environ:
+ .long 0
+
+.section .text
+ .global _start
+ _start:
+ xorq %rbp, %rbp
+
+ movq %rsp, %rax
+ movq (%rax), %rdi
+ leaq 8(%rax), %rsi
+
+ fninit
+ xorq %rax, %rax
+ call main
+
+ 1:
+ movq %rax, %rbx
+ movq $__SYSCALL__exit, %rax
+ int $33
+
+ ud2 // should not reach
\ No newline at end of file
--- /dev/null
+#include <lunaix/syscallid.h>
+
+#define LUNAIX_SYSCALL 33
+#define regsize 8
+
+ .struct 2 * regsize # rip, rbp
+id:
+ .struct id + regsize
+a1:
+ .struct a1 + regsize
+a2:
+ .struct a2 + regsize
+a3:
+ .struct a3 + regsize
+a4:
+ .struct a4 + regsize
+a5:
+
+.section .text
+ .type do_lunaix_syscall, @function
+ .global do_lunaix_syscall
+
+ do_lunaix_syscall:
+ pushq %rbp
+ movq %rsp, %rbp
+
+ pushq %rbx
+
+ movq %rcx, %r10
+
+ movq %rdi, %rax
+ movq %rsi, %rbx
+ movq %rdx, %rcx
+ movq %r10, %rdx
+ movq %r8, %rdi
+ movq %r9, %rsi
+
+ int $LUNAIX_SYSCALL
+
+ popq %rbx
+
+ leave
+ ret
\ No newline at end of file
--- /dev/null
+#include <lunaix/syscallid.h>
+
+.section .text
+ /*
+ stack structure:
+
+ ...saved_state \
+ void* sighand; > struct siguctx
+ void* sigact; /
+ int sig_num; <--- %rsp
+ */
+ .global sigtrampoline
+ sigtrampoline:
+ movq %rsp, %rax
+ andq $-16, %rsp
+ pushq %rax
+
+ movl (%rax), %edi // signum
+ xorq %rsi, %rsi // siginfo = NULL
+ leaq 4(%rax), %rdx // (struct siguctx*)&sigact
+ call sig_dohandling
+
+ movq $__SYSCALL_sigreturn, %rax
+ popq %rbx
+ int $33
+
+ .global th_trampoline
+ th_trampoline:
+ movq (%rsp), %rax
+ movq 8(%rsp), %rdi
+
+ callq %rax
+
+ movq %rax, %rbx
+ movq $__SYSCALL_th_exit, %rax
+ int $33
\ No newline at end of file
#include <lunaix/mann_flags.h>
#include <lunaix/types.h>
-extern void* mmap(void* addr, size_t length, int proct, int flags, int fd, off_t offset);
+void* mmap(void* addr, size_t length, int proct, int flags, int fd, off_t offset);
-extern void munmap(void* addr, size_t length);
+int munmap(void* addr, size_t length);
#endif /* __LUNAIX_MANN_H */
#include <lunaix/syscallid.h>
-extern unsigned long
+extern unsigned long
do_lunaix_syscall(unsigned long call_id, ...);
#endif /* __LUNAIX_OSDEPS_SYSCALL_H */
#ifndef __LUNAIX_USTDIO_H
#define __LUNAIX_USTDIO_H
+#include <stdarg.h>
+
#define stdout 0
#define stdin 1
-extern int
+int
printf(const char* fmt, ...);
+int
+vsnprintf(char* buffer, unsigned int size, const char* fmt, va_list ap);
+
+int
+snprintf(char* buffer, unsigned int size, const char* fmt, ...);
+
#endif /* __LUNAIX_USTDIO_H */
+include lunabuild.mkinc
+
+include $(lbuild_mkinc)
+
libc_include := $(CURDIR)/includes
-ARCH ?= i386
BUILD_DIR ?= bin
BUILD_NAME ?= liblunac
src_dirs := src
src_dirs += arch/$(ARCH)
-src_files := $(foreach f, $(src_dirs), $(shell find $(f) -name "*.[cS]"))
-obj_files := $(addsuffix .o, $(src_files))
+obj_files := $(addsuffix .o, $(_LBUILD_SRCS))
build_lib := $(BUILD_DIR)/lib
build_include := $(BUILD_DIR)/includes
libc_include_opt = $(addprefix -I, $(libc_include))
-global_include_opt = $(addprefix -I, $(INCLUDES))
+global_include_opt = $(addprefix -I, $(INCLUDES) $(_LBUILD_INCS))
check_folders := $(src_dirs)
check_folders += $(build_lib) $(build_include)
@$(AR) rcs $@ $^
clean:
+ @rm -rf $(lbuild_dir)
@rm -f $(obj_files)
headers: $(libc_include)
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <stdio.h>
#define NUMBUFSIZ 24
return ptr;
}
+
+int
+vsnprintf(char* buffer, unsigned int size, const char* fmt, va_list ap)
+{
+ return __vprintf_internal(buffer, fmt, size, ap);
+}
+
+int
+snprintf(char* buffer, unsigned int size, const char* fmt, ...)
+{
+ va_list l;
+ va_start(l, fmt);
+ int r = __vprintf_internal(buffer, fmt, size, l);
+ va_end(l);
+ return r;
+}
\ No newline at end of file
--- /dev/null
+#include <lunaix/syscall.h>
+#include <lunaix/dirent_defs.h>
+
+int
+sys_readdir(int fd, struct lx_dirent* dirent)
+{
+ return do_lunaix_syscall(__SYSCALL_sys_readdir, fd, dirent);
+}
\ No newline at end of file
--- /dev/null
+#include <lunaix/syscall.h>
+#include <errno.h>
+
+int
+geterrno()
+{
+ return do_lunaix_syscall(__SYSCALL_geterrno);
+}
\ No newline at end of file
--- /dev/null
+#include <lunaix/syscall.h>
+#include <fcntl.h>
+
+int
+open(const char* path, int options)
+{
+ return do_lunaix_syscall(__SYSCALL_open, path, options);
+}
+
+int
+fstat(int fd, struct file_stat* stat)
+{
+ return do_lunaix_syscall(__SYSCALL_fstat, fd, stat);
+}
\ No newline at end of file
--- /dev/null
+#include <lunaix/syscall.h>
+#include <lunaix/ioctl.h>
+#include <stdarg.h>
+
+int __attribute__((noinline))
+ioctl(int fd, int req, ...)
+{
+ va_list ap;
+ va_start(ap, req);
+
+ int ret = do_lunaix_syscall(__SYSCALL_ioctl, fd, req, &ap);
+
+ va_end(ap);
+ return ret;
+}
\ No newline at end of file
--- /dev/null
+#include <lunaix/syscall.h>
+#include <lunaix/types.h>
+#include <stdio.h>
+
+void
+yield()
+{
+ do_lunaix_syscall(__SYSCALL_yield);
+}
+
+pid_t
+wait(int* status)
+{
+ return do_lunaix_syscall(__SYSCALL_wait, status);
+}
+
+pid_t
+waitpid(pid_t pid, int* status, int options)
+{
+ return do_lunaix_syscall(__SYSCALL_waitpid, pid, status, options);
+}
+
+void
+syslog(int level, const char* fmt, ...)
+{
+ char buf[1024];
+ va_list ap;
+ va_start(ap, fmt);
+
+ unsigned int size = vsnprintf(buf, 1024, fmt, ap);
+ do_lunaix_syscall(__SYSCALL_syslog, level, buf, size);
+
+ va_end(ap);
+}
+
+int
+realpathat(int fd, char* buf, size_t size)
+{
+ return do_lunaix_syscall(__SYSCALL_realpathat, fd, buf, size);
+}
\ No newline at end of file
--- /dev/null
+#include <lunaix/syscall.h>
+#include <lunaix/mann.h>
+#include <lunaix/types.h>
+
+void*
+mmap(void* addr, size_t length, int proct, int flags, int fd, off_t offset)
+{
+ struct usr_mmap_param mparam = {
+ .addr = addr,
+ .length = length,
+ .proct = proct,
+ .flags = flags,
+ .fd = fd,
+ .offset = offset
+ };
+
+ return (void*)do_lunaix_syscall(__SYSCALL_sys_mmap, &mparam);
+}
+
+int
+munmap(void* addr, size_t length)
+{
+ return do_lunaix_syscall(__SYSCALL_munmap, addr, length);
+}
--- /dev/null
+#include <lunaix/syscall.h>
+
+int
+mount(const char* source, const char* target,
+ const char* fstype, int options)
+{
+ return do_lunaix_syscall(__SYSCALL_mount, source, target, fstype, options);
+}
+
+int
+unmount(const char* target)
+{
+ return do_lunaix_syscall(__SYSCALL_unmount, target);
+}
\ No newline at end of file
-#include "syscall.h"
+#include <lunaix/syscall.h>
#include <lunaix/signal_defs.h>
#include <lunaix/types.h>
-__LXSYSCALL1(int, sigpending, sigset_t, *set);
-__LXSYSCALL1(int, sigsuspend, const sigset_t, *mask);
+int
+sigpending(sigset_t *set)
+{
+ return do_lunaix_syscall(__SYSCALL_sigpending, set);
+}
-__LXSYSCALL3(int,
- sigprocmask,
- int,
- how,
- const sigset_t,
- *set,
- sigset_t,
- *oldset);
+int
+sigsuspend(const sigset_t *mask)
+{
+ return do_lunaix_syscall(__SYSCALL_sigsuspend, mask);
+}
-__LXSYSCALL2(int, sys_sigaction, int, signum, struct sigaction*, action);
+int
+sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
+{
+ return do_lunaix_syscall(__SYSCALL_sigprocmask, how, set, oldset);
+}
+
+int
+sys_sigaction(int signum, struct sigaction* action)
+{
+ return do_lunaix_syscall(__SYSCALL_sys_sigaction, signum, action);
+}
-__LXSYSCALL2(int, kill, pid_t, pid, int, signum);
+int
+kill(pid_t pid, int signum)
+{
+ return do_lunaix_syscall(__SYSCALL_kill, pid, signum);
+}
extern void
sigtrampoline();
+extern pid_t
+getpid();
+
sighandler_t
signal(int signum, sighandler_t handler)
{
return handler;
}
-extern pid_t
-getpid();
-
int
raise(int signum)
{
--- /dev/null
+#include <lunaix/syscall.h>
+#include <lunaix/types.h>
+
+pid_t
+fork()
+{
+ return do_lunaix_syscall(__SYSCALL_fork);
+}
+
+int
+brk(void* addr)
+{
+ return do_lunaix_syscall(__SYSCALL_brk, addr);
+}
+
+void*
+sbrk(ssize_t size)
+{
+ return (void*)do_lunaix_syscall(__SYSCALL_sbrk, size);
+}
+
+pid_t
+getpid()
+{
+ return do_lunaix_syscall(__SYSCALL_getpid);
+}
+
+pid_t
+getppid()
+{
+ return do_lunaix_syscall(__SYSCALL_getppid);
+}
+
+pid_t
+getpgid()
+{
+ return do_lunaix_syscall(__SYSCALL_getpgid);
+}
+
+pid_t
+setpgid(pid_t pid, pid_t pgid)
+{
+ return do_lunaix_syscall(__SYSCALL_setpgid, pid, pgid);
+}
+void
+_exit(int status)
+{
+ do_lunaix_syscall(__SYSCALL__exit, status);
+}
+
+unsigned int
+sleep(unsigned int seconds)
+{
+ return do_lunaix_syscall(__SYSCALL_sleep, seconds);
+}
+
+int
+pause()
+{
+ return do_lunaix_syscall(__SYSCALL_pause);
+}
+
+unsigned int
+alarm(unsigned int seconds)
+{
+ return do_lunaix_syscall(__SYSCALL_alarm, seconds);
+}
+
+int
+link(const char* oldpath, const char* newpath)
+{
+ return do_lunaix_syscall(__SYSCALL_link, oldpath, newpath);
+}
+
+int
+rmdir(const char* pathname)
+{
+ return do_lunaix_syscall(__SYSCALL_rmdir, pathname);
+}
+
+int
+read(int fd, void* buf, size_t count)
+{
+ return do_lunaix_syscall(__SYSCALL_read, fd, buf, count);
+}
+
+int
+write(int fd, void* buf, size_t count)
+{
+ return do_lunaix_syscall(__SYSCALL_write, fd, buf, count);
+}
+
+int
+readlink(const char* path, char* buf, size_t size)
+{
+ return do_lunaix_syscall(__SYSCALL_readlink, path, buf, size);
+}
+
+int
+lseek(int fd, off_t offset, int options)
+{
+ return do_lunaix_syscall(__SYSCALL_lseek, fd, offset, options);
+}
+
+int
+unlink(const char* pathname)
+{
+ return do_lunaix_syscall(__SYSCALL_unlink, pathname);
+}
+
+int
+close(int fd)
+{
+ return do_lunaix_syscall(__SYSCALL_close, fd);
+}
+
+int
+dup2(int oldfd, int newfd)
+{
+ return do_lunaix_syscall(__SYSCALL_dup2, oldfd, newfd);
+}
+
+int
+dup(int oldfd)
+{
+ return do_lunaix_syscall(__SYSCALL_dup, oldfd);
+}
+
+int
+fsync(int fildes)
+{
+ return do_lunaix_syscall(__SYSCALL_fsync, fildes);
+}
+
+int
+symlink(const char* pathname, const char* link_target)
+{
+ return do_lunaix_syscall(__SYSCALL_symlink, pathname, link_target);
+}
+
+int
+chdir(const char* path)
+{
+ return do_lunaix_syscall(__SYSCALL_chdir, path);
+}
+
+int
+fchdir(int fd)
+{
+ return do_lunaix_syscall(__SYSCALL_fchdir, fd);
+}
+
+char*
+getcwd(char* buf, size_t size)
+{
+ return (char*)do_lunaix_syscall(__SYSCALL_getcwd, buf, size);
+}
+
+int
+rename(const char* oldpath, const char* newpath)
+{
+ return do_lunaix_syscall(__SYSCALL_rename, oldpath, newpath);
+}
+
+int
+getxattr(const char* path, const char* name, void* value, size_t len)
+{
+ return do_lunaix_syscall(__SYSCALL_getxattr, path, name, value, len);
+}
+
+int
+setxattr(const char* path, const char* name, void* value, size_t len)
+{
+ return do_lunaix_syscall(__SYSCALL_setxattr, path, name, value, len);
+}
+
+int
+fgetxattr(int fd, const char* name, void* value, size_t len)
+{
+ return do_lunaix_syscall(__SYSCALL_fgetxattr, fd, name, value, len);
+}
+
+int
+fsetxattr(int fd, const char* name, void* value, size_t len)
+{
+ return do_lunaix_syscall(__SYSCALL_fsetxattr, fd, name, value, len);
+}
+
+int
+readlinkat(int dirfd, const char* pathname, char* buf, size_t size)
+{
+ return do_lunaix_syscall(__SYSCALL_readlinkat, dirfd, pathname, buf, size);
+}
+
+int
+unlinkat(int fd, const char* pathname)
+{
+ return do_lunaix_syscall(__SYSCALL_unlinkat, fd, pathname);
+}
+
+int
+mkdir(const char* path)
+{
+ return do_lunaix_syscall(__SYSCALL_mkdir, path);
+}
+
+int
+execve(const char* filename, const char** argv, const char** envp)
+{
+ return do_lunaix_syscall(__SYSCALL_execve, filename, argv, envp);
+}
#include <lunaix/syscall.h>
#include <pthread.h>
-static void*
-__pthread_routine_wrapper(void *(*start_routine)(void*), void* arg)
-{
- void* ret = start_routine(arg);
-
- do_lunaix_syscall(__SYSCALL_th_exit, ret);
-
- return ret; // should not reach
-}
-
int
pthread_create(pthread_t* thread,
const pthread_attr_t* attr,
void *(*start_routine)(void*), void* arg)
{
// FIXME attr currently not used
+ int ret;
+ struct uthread_param th_param;
- struct uthread_info th_info;
- int ret = do_lunaix_syscall(__SYSCALL_th_create, thread, &th_info, __pthread_routine_wrapper, NULL);
-
- if (ret) {
- return ret;
- }
-
- // FIXME we should encapsulate these parameter into struct
- // and pass it as a single thread param.
-
- void** th_stack = (void**) th_info.th_stack_top;
- th_stack[1] = (void*)start_routine;
- th_stack[2] = arg;
+ th_param.th_handler = start_routine;
+ th_param.arg1 = arg;
+ extern void th_trampoline();
+ ret = do_lunaix_syscall(__SYSCALL_th_create, thread,
+ &th_param, th_trampoline);
return ret;
}
include utils.mkinc
include toolchain.mkinc
+include lunabuild.mkinc
-task := all
+include $(lbuild_mkinc)
+
+ifndef ARCH
+$(error ARCH is not set)
+endif
-# TODO make this use LBuild
-CFLAGS += -m32 -ffreestanding -fno-pie
-LDFLAGS += -m32 -nostdlib -nolibc -z noexecstack -no-pie -Wl,--build-id=none
+task := all
sys_include := $(CURDIR)/includes
build_dir := $(CURDIR)/build
libc_name := liblunac
libc_files := $(libc_name).a
libc := $(addprefix $(build_dir)/lib/,$(libc_files))
-ldscript := $(CURDIR)/link-usr.ld
-common_param := CC AR INCLUDES BUILD_DIR BUILD_NAME CFLAGS LDFLAGS
+common_param := CC AR INCLUDES BUILD_DIR BUILD_NAME\
+ CFLAGS LDFLAGS ARCH LBUILD
INCLUDES := $(sys_include)
BUILD_DIR := $(build_dir)
BUILD_NAME := $(libc_name).a
+mkapp-list := $(addprefix app-, $(shell cat apps.list))
+mkexec-list := $(addprefix $(build_dir)/bin/, $(_LBUILD_SRCS))
+
+uexec_ld := $(CURDIR)/uexec.ld
+
+# Directory structure prerequisites
$(build_dir)/bin:
@mkdir -p $(build_dir)/bin
$(build_dir)/includes:
@mkdir -p $(build_dir)/includes
+# LibC
export $(common_param)
$(build_dir)/$(libc_name).a: $(build_dir)/bin $(build_dir)/lib $(build_dir)/includes
$(call status,TASK,$(BUILD_NAME))
@$(MAKE) $(MKFLAGS) -C libc/ $(task)
-app-list = $(shell cat apps.list)
-exec-list = $(shell cat execs.list)
+$(uexec_ld): $(uexec_ld)x
+ @$(CC) -include $(lbuild_config_h) -x c -P -E $< -o $@
-mkapp-list := $(addprefix app-, $(app-list))
-mkexec-list := $(addprefix $(build_dir)/bin/, $(exec-list))
-
-export LD_SCRIPT := $(ldscript)
+# Application (with standalone makefile)
+export LD_SCRIPT := $(uexec_ld)
export LIBC := $(libc)
-app-%:
+export $(common_param)
+app-%: $(uexec_ld)
$(call status,TASK,$*)
@$(MAKE) $(MKFLAGS) -C $* $(task) BUILD_NAME="$*"
+app: task := all
+app: INCLUDES += $(build_dir)/includes
+app: $(mkapp-list)
+
+
+# Programs (single file)
exec_%.o: %.c
$(call status,CC,$<)
@$(CC) $(CFLAGS) $(addprefix -I,$(INCLUDES)) -c $< -o $@
-$(build_dir)/bin/%: exec_%.o
+$(build_dir)/bin/%: exec_%.o $(uexec_ld)
$(call status,LD,$(@F))
- @$(CC) -T $(ldscript) -o $@ $< $(libc) $(LDFLAGS)
-
-app: task := all
-app: INCLUDES += $(build_dir)/includes
-app: $(mkapp-list)
+ @$(CC) -T $(uexec_ld) -o $@ $< $(libc) $(LDFLAGS)
exec: task := all
exec: INCLUDES += $(build_dir)/includes
exec: $(mkexec-list)
+
+# General recipes
clean: task := clean
clean: $(mkapp-list)
- @rm -rf $(build_dir)
+ @rm -rf $(build_dir) $(lbuild_dir) $(uexec_ld)
@$(MAKE) $(MKFLAGS) -C libc/ $(task)
+.NOTPARALLEL:
all: task := all
all: $(build_dir)/$(libc_name).a exec app
\ No newline at end of file
return strcpy(str, str + l);
}
-void
-parse_cmdline(char* line, char** cmd, char** arg_part)
+int
+parse_cmdline(char* line, char** args)
{
strrtrim(line);
line = strltrim_safe(line);
}
l++;
}
- *cmd = line;
- if (c) {
- *arg_part = strltrim_safe(line + l);
+
+ args[0] = line;
+ if (c && l) {
+ args[1] = strltrim_safe(line + l);
} else {
- *arg_part = NULL;
+ args[1] = NULL;
}
+
+ return !!l;
}
void
}
void
-sh_exec(const char* name, const char** argv)
+sh_exec(const char** argv)
{
+ const char* envp[] = { 0 };
+ char* name = argv[0];
if (!strcmp(name, "cd")) {
- chdir(argv[0] ? argv[0] : ".");
+ chdir(argv[1] ? argv[1] : ".");
sh_printerr();
return;
}
pid_t p;
if (!(p = fork())) {
- if (execve(name, argv, NULL)) {
+ if (execve(name, argv, envp)) {
sh_printerr();
}
_exit(1);
// stdout (by default, unless user did smth) is the tty we are currently at
ioctl(stdout, TIOCSPGRP, getpgid());
- char* argv[] = {0, 0};
+ char* argv[] = {0, 0, 0};
while (1) {
getcwd(pwd, 512);
buf[sz] = '\0';
// currently, this shell only support single argument
- parse_cmdline(buf, &cmd, &argv[0]);
-
- if (cmd[0] == 0) {
+ if (!parse_cmdline(buf, argv)) {
printf("\n");
goto cont;
}
// cmd=="exit"
- if (*(unsigned int*)cmd == 0x74697865U) {
+ if (*(unsigned int*)argv[0] == 0x74697865U) {
break;
}
- sh_exec(cmd, (const char**)&argv);
+ sh_exec((const char**)argv);
cont:
printf("\n");
}
Test payloads
*/
+#define __int(ptr) ((int)(unsigned long)(ptr))
+#define __ptr(ptr) ((void*)(unsigned long)(ptr))
+
static void*
__print_and_sleep_randsec(void* value)
{
pthread_t tid = pthread_self();
- printf("thread %d: gets number %d\n", tid, (int)value);
+ printf("thread %d: gets number %d\n", tid, __int(value));
int fd = open("/dev/rand", O_RDONLY | O_DIRECT);
if (fd < 0) {
__print_and_sleep_seq(void* value)
{
pthread_t tid = pthread_self();
- printf("thread %d: gets number %d\n", tid, (int)value);
+ printf("thread %d: gets number %d\n", tid, __int(value));
- int second = (int)value % 30;
+ int second = __int(value) % 30;
printf("thread %d: going to sleep %ds\n", tid, second);
sleep(second);
__print_and_sleep(void* value)
{
pthread_t tid = pthread_self();
- printf("thread %d: gets number %d\n", tid, (int)value);
+ printf("thread %d: gets number %d\n", tid, __int(value));
sleep(1);
printf("thread %d: exit\n", tid);
int err;
pthread_t created;
for (int i = 0; i < amount; i++) {
- err = pthread_create(&created, NULL, fn, (void*)i);
+ err = pthread_create(&created, NULL, fn, __ptr(i));
if (err) {
printf("unable to create thread: %d\n", err);
continue;
void* v;
for (int i = 0; i < param; i++)
{
- err = pthread_create(&created, NULL, __print_and_sleep, (void*)i);
+ err = pthread_create(&created, NULL, __print_and_sleep, __ptr(i));
if (err) {
printf("unable to create thread: %d\n", err);
}
do { \
printf("** [%s] test start\n", note); \
pthread_test_##testn(__VA_ARGS__); \
- printf("** [%s] test passed\n"); \
+ printf("** [%s] test passed\n", note); \
} while (0)
int main()
ENTRY(_start)
+#ifdef CONFIG_ARCH_X86_64
+# define EXEC_START 0x0000008000000000
+#else
+# define EXEC_START 0x400000
+#endif
+
SECTIONS {
- . = 0x400000;
+ . = EXEC_START;
.text BLOCK(4K) : {
*(.text)