mirror of
https://github.com/llenotre/maestro.git
synced 2024-10-06 00:47:40 +03:00
Merge db625a1683
into b79bb4288b
This commit is contained in:
commit
bb33890d6f
43
.github/workflows/check.yml
vendored
43
.github/workflows/check.yml
vendored
@ -35,42 +35,51 @@ jobs:
|
|||||||
- name: Integration tests
|
- name: Integration tests
|
||||||
working-directory: inttest
|
working-directory: inttest
|
||||||
run: cargo fmt --check
|
run: cargo fmt --check
|
||||||
documentation:
|
book:
|
||||||
runs-on: [self-hosted, linux]
|
runs-on: [self-hosted, linux]
|
||||||
needs: clippy
|
needs: clippy
|
||||||
steps:
|
steps:
|
||||||
- name: Build book
|
- name: Build book
|
||||||
run: mdbook build doc/
|
run: mdbook build doc/
|
||||||
|
documentation:
|
||||||
|
runs-on: [self-hosted, linux]
|
||||||
|
needs: clippy
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
arch: ["x86", "x86_64"]
|
||||||
|
steps:
|
||||||
- name: Build references
|
- name: Build references
|
||||||
working-directory: kernel
|
working-directory: kernel
|
||||||
run: ci/doc.sh
|
run: cargo doc --target target/${{ matrix.arch }}/${{ matrix.arch }}.json
|
||||||
build:
|
build:
|
||||||
runs-on: [self-hosted, linux]
|
runs-on: [self-hosted, linux]
|
||||||
needs: clippy
|
needs: clippy
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
arch: ["x86", "x86_64"]
|
||||||
steps:
|
steps:
|
||||||
- name: Debug
|
- name: Debug
|
||||||
working-directory: kernel
|
working-directory: kernel
|
||||||
run: ci/build.sh
|
run: cargo build --target target/${{ matrix.arch }}/${{ matrix.arch }}.json
|
||||||
- name: Check Multiboot2 for x86 (debug)
|
- name: Check Multiboot2 for x86 (debug)
|
||||||
working-directory: kernel
|
working-directory: kernel
|
||||||
run: grub-file --is-x86-multiboot2 target/x86/debug/maestro
|
run: grub-file --is-x86-multiboot2 target/x86/debug/maestro
|
||||||
- name: Release
|
- name: Release
|
||||||
working-directory: kernel
|
working-directory: kernel
|
||||||
env:
|
run: cargo build --target target/${{ matrix.arch }}/${{ matrix.arch }}.json --release
|
||||||
CARGOFLAGS: --release
|
|
||||||
run: ci/build.sh
|
|
||||||
- name: Check Multiboot2 for x86 (release)
|
- name: Check Multiboot2 for x86 (release)
|
||||||
working-directory: kernel
|
working-directory: kernel
|
||||||
run: grub-file --is-x86-multiboot2 target/x86/release/maestro
|
run: grub-file --is-x86-multiboot2 target/x86/release/maestro
|
||||||
strace:
|
strace:
|
||||||
runs-on: [self-hosted, linux]
|
runs-on: [self-hosted, linux]
|
||||||
needs: build
|
needs: build
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
arch: ["x86", "x86_64"]
|
||||||
steps:
|
steps:
|
||||||
- name: Build
|
- name: Build
|
||||||
working-directory: kernel
|
working-directory: kernel
|
||||||
env:
|
run: cargo build --target target/${{ matrix.arch }}/${{ matrix.arch }}.json --features strace
|
||||||
CARGOFLAGS: --features strace
|
|
||||||
run: ci/build.sh
|
|
||||||
- name: Check Multiboot2 for x86
|
- name: Check Multiboot2 for x86
|
||||||
working-directory: kernel
|
working-directory: kernel
|
||||||
run: grub-file --is-x86-multiboot2 target/x86/debug/maestro
|
run: grub-file --is-x86-multiboot2 target/x86/debug/maestro
|
||||||
@ -87,6 +96,9 @@ jobs:
|
|||||||
selftest:
|
selftest:
|
||||||
runs-on: [self-hosted, linux]
|
runs-on: [self-hosted, linux]
|
||||||
needs: build
|
needs: build
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
arch: ["x86", "x86_64"]
|
||||||
steps:
|
steps:
|
||||||
- name: Run utils tests
|
- name: Run utils tests
|
||||||
working-directory: utils
|
working-directory: utils
|
||||||
@ -94,18 +106,31 @@ jobs:
|
|||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
- name: Run kernel tests
|
- name: Run kernel tests
|
||||||
working-directory: kernel
|
working-directory: kernel
|
||||||
|
env:
|
||||||
|
CARGOFLAGS: --target arch/${{ matrix.arch }}/${{ matrix.arch }}.json
|
||||||
run: ci/test.sh self
|
run: ci/test.sh self
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
inttest:
|
inttest:
|
||||||
runs-on: [self-hosted, linux]
|
runs-on: [self-hosted, linux]
|
||||||
needs: build
|
needs: build
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
arch:
|
||||||
|
- kernel: "x86"
|
||||||
|
user: "i686-unknown-linux-musl"
|
||||||
|
- kernel: "x86_64"
|
||||||
|
user: "x86_64-unknown-linux-musl"
|
||||||
steps:
|
steps:
|
||||||
- name: Build tests
|
- name: Build tests
|
||||||
working-directory: inttest
|
working-directory: inttest
|
||||||
|
env:
|
||||||
|
TARGET: ${{ matrix.arch.user }}
|
||||||
run: |
|
run: |
|
||||||
./build.sh
|
./build.sh
|
||||||
mv disk ../kernel/qemu_disk
|
mv disk ../kernel/qemu_disk
|
||||||
- name: Run
|
- name: Run
|
||||||
working-directory: kernel
|
working-directory: kernel
|
||||||
|
env:
|
||||||
|
CARGOFLAGS: --target arch/${{ matrix.arch.kernel }}/${{ matrix.arch.kernel }}.json
|
||||||
run: ci/test.sh int
|
run: ci/test.sh int
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
if [ -z "$TARGET" ]; then
|
if [ -z "$TARGET" ]; then
|
||||||
export TARGET=i686-unknown-linux-musl
|
export TARGET=x86_64-unknown-linux-musl
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
|
@ -4,6 +4,9 @@ build-std = ["core", "alloc"]
|
|||||||
[target.x86]
|
[target.x86]
|
||||||
runner = "scripts/qemu.sh"
|
runner = "scripts/qemu.sh"
|
||||||
|
|
||||||
|
[target.x86_64]
|
||||||
|
runner = "scripts/qemu.sh"
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
# Set default target
|
# Set default target
|
||||||
target = "arch/x86/x86.json"
|
target = "arch/x86_64/x86_64.json"
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This file is the linker script for the x86 architecture.
|
* The linker script for the x86 architecture.
|
||||||
*
|
*
|
||||||
* The kernel image is split into two parts:
|
* The kernel image is split into two parts:
|
||||||
* - The boot part, in lower memory (sections with the `.boot` prefix)
|
* - The boot part, in lower memory (sections with the `.boot` prefix)
|
||||||
@ -27,10 +27,11 @@
|
|||||||
* the kernel image is relocated to higher memory.
|
* the kernel image is relocated to higher memory.
|
||||||
* After running the kernel code, the booting code isn't useful anymore.
|
* After running the kernel code, the booting code isn't useful anymore.
|
||||||
*
|
*
|
||||||
* Sections need to be aligned on the page boundary to be protected against writing (for those
|
* Sections need to be aligned on the page boundary to be protected against
|
||||||
* where it applies).
|
* writing (for those where it applies).
|
||||||
*
|
*
|
||||||
* BSS sections are located right after read-only sections to limit damages if the stack(s) they contain overflows.
|
* BSS sections are located right after read-only sections to limit damages if
|
||||||
|
* the stack(s) they contain overflows.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ENTRY(multiboot_entry)
|
ENTRY(multiboot_entry)
|
||||||
|
74
kernel/arch/x86_64/linker.ld
Normal file
74
kernel/arch/x86_64/linker.ld
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 Luc Lenôtre
|
||||||
|
*
|
||||||
|
* This file is part of Maestro.
|
||||||
|
*
|
||||||
|
* Maestro is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, either version 3 of the License, or (at your option) any later
|
||||||
|
* version.
|
||||||
|
*
|
||||||
|
* Maestro is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* Maestro. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The linker script for the x86_64 architecture.
|
||||||
|
*
|
||||||
|
* For more information about the organization of this particular file, check
|
||||||
|
* the documentation in the linker script for the x86 architecture.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ENTRY(multiboot_entry)
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = 0x100000;
|
||||||
|
|
||||||
|
.boot.text : ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(.boot.text)
|
||||||
|
}
|
||||||
|
|
||||||
|
.boot.stack : ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(.boot.stack)
|
||||||
|
}
|
||||||
|
|
||||||
|
.boot.data : ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(.boot.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
. = 0xc0200000;
|
||||||
|
|
||||||
|
.text : AT (ADDR (.text) - 0xc0000000) ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(.text*)
|
||||||
|
}
|
||||||
|
|
||||||
|
.rodata : AT (ADDR (.rodata) - 0xc0000000) ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(.rodata*)
|
||||||
|
}
|
||||||
|
|
||||||
|
.user : AT (ADDR (.user) - 0xc0000000) ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(.user*)
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss : AT (ADDR (.bss) - 0xc0000000) ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(COMMON)
|
||||||
|
*(.bss*)
|
||||||
|
}
|
||||||
|
|
||||||
|
.data : AT (ADDR (.data) - 0xc0000000) ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(.data*)
|
||||||
|
}
|
||||||
|
}
|
16
kernel/arch/x86_64/x86_64.json
Normal file
16
kernel/arch/x86_64/x86_64.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"arch": "x86_64",
|
||||||
|
"data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
|
||||||
|
"disable-redzone": true,
|
||||||
|
"dynamic-linking": true,
|
||||||
|
"executables": true,
|
||||||
|
"features": "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-avx,-avx2,+soft-float",
|
||||||
|
"linker": "x86_64-elf-ld",
|
||||||
|
"linker-flavor": "ld",
|
||||||
|
"llvm-target": "x86_64-unknown-none",
|
||||||
|
"os": "none",
|
||||||
|
"panic-strategy": "abort",
|
||||||
|
"target-c-int-width": "32",
|
||||||
|
"target-endian": "little",
|
||||||
|
"target-pointer-width": "64"
|
||||||
|
}
|
@ -1,11 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
EXIT_CODE=0
|
|
||||||
|
|
||||||
for arch in $(ls -1 arch/); do
|
|
||||||
echo "Build for architecture $arch..."
|
|
||||||
cargo build --target arch/$arch/$arch.json $CARGOFLAGS
|
|
||||||
EXIT_CODE=$(($EXIT_CODE + $?))
|
|
||||||
done
|
|
||||||
|
|
||||||
exit $EXIT_CODE
|
|
@ -1,11 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
EXIT_CODE=0
|
|
||||||
|
|
||||||
for arch in $(ls -1 arch/); do
|
|
||||||
echo "Build documentation for architecture $arch..."
|
|
||||||
cargo doc --target arch/$arch/$arch.json $CARGOFLAGS
|
|
||||||
EXIT_CODE=$(($EXIT_CODE + $?))
|
|
||||||
done
|
|
||||||
|
|
||||||
exit $EXIT_CODE
|
|
@ -11,7 +11,7 @@ setsid cargo run $CARGOFLAGS >qemu.log 2>&1 &
|
|||||||
QEMU_PID=$!
|
QEMU_PID=$!
|
||||||
|
|
||||||
if [ -z "$ARCH" ]; then
|
if [ -z "$ARCH" ]; then
|
||||||
ARCH="x86"
|
ARCH="x86_64"
|
||||||
fi
|
fi
|
||||||
KERN_PATH="target/$ARCH/debug/maestro"
|
KERN_PATH="target/$ARCH/debug/maestro"
|
||||||
|
|
||||||
|
238
kernel/src/boot.rs
Normal file
238
kernel/src/boot.rs
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 Luc Lenôtre
|
||||||
|
*
|
||||||
|
* This file is part of Maestro.
|
||||||
|
*
|
||||||
|
* Maestro is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, either version 3 of the License, or (at your option) any later
|
||||||
|
* version.
|
||||||
|
*
|
||||||
|
* Maestro is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* Maestro. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
gdt,
|
||||||
|
memory::{
|
||||||
|
vmem::x86::{FLAG_PAGE_SIZE, FLAG_PRESENT, FLAG_WRITE},
|
||||||
|
PhysAddr,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use core::arch::global_asm;
|
||||||
|
use utils::limits::PAGE_SIZE;
|
||||||
|
|
||||||
|
/// The value of the Multiboot2 magic.
|
||||||
|
const MULTIBOOT_MAGIC: u32 = 0xe85250d6;
|
||||||
|
|
||||||
|
/// Multiboot header tag: End
|
||||||
|
const MULTIBOOT_HEADER_TAG_END: u16 = 0;
|
||||||
|
/// Multiboot header tag: The kernel's entry point address
|
||||||
|
const MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS: u16 = 3;
|
||||||
|
|
||||||
|
/// The physical address of the GDT.
|
||||||
|
const GDT_PHYS_ADDR: PhysAddr = PhysAddr(0x800);
|
||||||
|
|
||||||
|
/// The header of a multiboot2 tag.
|
||||||
|
#[repr(C, align(8))]
|
||||||
|
struct MultibootTagHdr {
|
||||||
|
/// The tag's type.
|
||||||
|
r#type: u16,
|
||||||
|
/// The tag's flags.
|
||||||
|
///
|
||||||
|
/// Currently, has only one flag:
|
||||||
|
/// - `0`: if set, the tag may be considered as optional by the bootloader.
|
||||||
|
flags: u16,
|
||||||
|
/// The size of the tag in bytes.
|
||||||
|
size: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Layout of the multiboot2 tag indicating the entry point of the kernel.
|
||||||
|
#[repr(C, align(8))]
|
||||||
|
struct MultibootEntryAddrTag {
|
||||||
|
/// The tag's header.
|
||||||
|
hdr: MultibootTagHdr,
|
||||||
|
/// The entry point's physical address.
|
||||||
|
entry_addr: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Layout of the multiboot2 header.
|
||||||
|
#[repr(C, align(8))]
|
||||||
|
struct MultibootHeader {
|
||||||
|
// Mandatory fields
|
||||||
|
/// Multiboot magic number.
|
||||||
|
magic: u32,
|
||||||
|
/// The CPU architecture to boot for.
|
||||||
|
architecture: u32,
|
||||||
|
/// The size of this header in bytes.
|
||||||
|
header_length: u32,
|
||||||
|
/// The checksum of the previous fields.
|
||||||
|
checksum: u32,
|
||||||
|
|
||||||
|
/// The entry point tag.
|
||||||
|
entry_addr_tag: MultibootEntryAddrTag,
|
||||||
|
/// The end tag.
|
||||||
|
end_tag: MultibootTagHdr,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The header used to provide multiboot2 with the necessary information to boot the kernel.
|
||||||
|
#[no_mangle]
|
||||||
|
#[link_section = ".boot.rodata"]
|
||||||
|
pub static MULTIBOOT_HEADER: MultibootHeader = MultibootHeader {
|
||||||
|
magic: MULTIBOOT_MAGIC,
|
||||||
|
// x86
|
||||||
|
architecture: 0,
|
||||||
|
header_length: size_of::<MultibootHeader>() as _,
|
||||||
|
// Compute checksum of the previous values
|
||||||
|
checksum: 0.wrapping_sub(MULTIBOOT_MAGIC + 0 + size_of::<MultibootHeader>()),
|
||||||
|
|
||||||
|
entry_addr_tag: MultibootEntryAddrTag {
|
||||||
|
hdr: MultibootTagHdr {
|
||||||
|
r#type: MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS,
|
||||||
|
flags: 0,
|
||||||
|
size: size_of::<MultibootEntryAddrTag>(),
|
||||||
|
},
|
||||||
|
entry_addr: multiboot_entry as _,
|
||||||
|
},
|
||||||
|
end_tag: MultibootTagHdr {
|
||||||
|
r#type: MULTIBOOT_HEADER_TAG_END,
|
||||||
|
flags: 0,
|
||||||
|
size: size_of::<MultibootTagHdr>(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The initial Global Descriptor Table.
|
||||||
|
#[no_mangle]
|
||||||
|
#[link_section = ".boot.rodata"]
|
||||||
|
pub static INIT_GDT: [gdt::Entry; 9] = [
|
||||||
|
// First entry, empty
|
||||||
|
gdt::Entry::default(),
|
||||||
|
// Kernel code segment
|
||||||
|
gdt::Entry::new(0, !0, 0b10011010, 0b1100),
|
||||||
|
// Kernel data segment
|
||||||
|
gdt::Entry::new(0, !0, 0b10010010, 0b1100),
|
||||||
|
// User code segment
|
||||||
|
gdt::Entry::new(0, !0, 0b11111010, 0b1100),
|
||||||
|
// User data segment
|
||||||
|
gdt::Entry::new(0, !0, 0b11110010, 0b1100),
|
||||||
|
// TSS
|
||||||
|
gdt::Entry::default(),
|
||||||
|
// TLS entries
|
||||||
|
gdt::Entry::default(),
|
||||||
|
gdt::Entry::default(),
|
||||||
|
gdt::Entry::default(),
|
||||||
|
];
|
||||||
|
|
||||||
|
/// A page directory.
|
||||||
|
#[repr(C, align(8))]
|
||||||
|
struct PageDir([u32; 1024]);
|
||||||
|
|
||||||
|
impl PageDir {
|
||||||
|
/// Initializes a page directory to remap the kernel to the higher half of the memory.
|
||||||
|
pub const fn higher_half() -> Self {
|
||||||
|
let mut dir = [0; 1024];
|
||||||
|
for i in 0..256 {
|
||||||
|
let addr = (i * PAGE_SIZE * 1024) as u32;
|
||||||
|
let ent = addr | FLAG_PAGE_SIZE | FLAG_WRITE | FLAG_PRESENT;
|
||||||
|
dir[i] = ent;
|
||||||
|
dir[i + 768] = ent;
|
||||||
|
}
|
||||||
|
Self(dir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The page directory used to remap the kernel to higher memory.
|
||||||
|
#[no_mangle]
|
||||||
|
#[link_section = ".boot.rodata"]
|
||||||
|
pub static REMAP_DIR: PageDir = PageDir::higher_half();
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
/// The kernel's entry point.
|
||||||
|
fn multiboot_entry();
|
||||||
|
}
|
||||||
|
|
||||||
|
global_asm!(
|
||||||
|
r"
|
||||||
|
.global multiboot_entry
|
||||||
|
.type multiboot_entry, @function
|
||||||
|
|
||||||
|
.section .boot.text
|
||||||
|
|
||||||
|
multiboot_entry:
|
||||||
|
mov esp, boot_stack_begin
|
||||||
|
xor ebp, ebp
|
||||||
|
pushl 0
|
||||||
|
popf
|
||||||
|
|
||||||
|
push ebx
|
||||||
|
push eax
|
||||||
|
call setup_gdt
|
||||||
|
call remap
|
||||||
|
|
||||||
|
call kernel_main
|
||||||
|
# `kernel_main` cannot return
|
||||||
|
ud2
|
||||||
|
|
||||||
|
setup_gdt:
|
||||||
|
# Copy GDT to its physical address
|
||||||
|
mov esi, INIT_GDT
|
||||||
|
mov edi, {GDT_PHYS_ADDR}
|
||||||
|
mov ecx, {GDT_SIZE}
|
||||||
|
rep movsb
|
||||||
|
|
||||||
|
# Load GDT
|
||||||
|
pushl {GDT_PHYS_ADDR}
|
||||||
|
pushw ({GDT_SIZE} - 1)
|
||||||
|
lgdt [esp]
|
||||||
|
add esp, 6
|
||||||
|
jmp 8, complete_flush
|
||||||
|
complete_flush:
|
||||||
|
mov ax, GDT_KERNEL_DS
|
||||||
|
mov ds, ax
|
||||||
|
mov es, ax
|
||||||
|
mov ss, ax
|
||||||
|
|
||||||
|
mov ax, 0
|
||||||
|
mov fs, ax
|
||||||
|
mov gs, ax
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remaps the first gigabyte of memory to the last one, enabling paging and PSE.
|
||||||
|
*/
|
||||||
|
remap:
|
||||||
|
# Set page directory
|
||||||
|
mov cr3, {REMAP_DIR_ADDR}
|
||||||
|
|
||||||
|
# Enable PSE
|
||||||
|
mov eax, cr4
|
||||||
|
or eax, 0x00000010
|
||||||
|
mov cr4, eax
|
||||||
|
|
||||||
|
# Enable paging
|
||||||
|
mov eax, cr0
|
||||||
|
or eax, 0x80010000
|
||||||
|
mov cr0, eax
|
||||||
|
|
||||||
|
# Update stack
|
||||||
|
add esp, 0xc0000000
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
.section .boot.stack
|
||||||
|
|
||||||
|
.align 8
|
||||||
|
|
||||||
|
boot_stack:
|
||||||
|
.size boot_stack, STACK_SIZE
|
||||||
|
.skip STACK_SIZE
|
||||||
|
boot_stack_begin:
|
||||||
|
",
|
||||||
|
GDT_SIZE = size_of_val(&INIT_GDT),
|
||||||
|
REMAP_DIR_ADDR = &REMAP_DIR
|
||||||
|
);
|
@ -1,107 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2024 Luc Lenôtre
|
|
||||||
*
|
|
||||||
* This file is part of Maestro.
|
|
||||||
*
|
|
||||||
* Maestro is free software: you can redistribute it and/or modify it under the
|
|
||||||
* terms of the GNU General Public License as published by the Free Software
|
|
||||||
* Foundation, either version 3 of the License, or (at your option) any later
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
* Maestro is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* Maestro. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
.global a20_handle
|
|
||||||
|
|
||||||
.type a20_handle, @function
|
|
||||||
.type a20_check, @function
|
|
||||||
.type a20_wait_read, @function
|
|
||||||
.type a20_wait_write, @function
|
|
||||||
|
|
||||||
.section .boot.text, "ax"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Ensures that the A20 line is enabled.
|
|
||||||
*/
|
|
||||||
a20_handle:
|
|
||||||
call a20_check
|
|
||||||
test $0, %eax
|
|
||||||
je a20_handle_
|
|
||||||
ret
|
|
||||||
a20_handle_:
|
|
||||||
call a20_enable
|
|
||||||
ret
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Checks whether the a20 line is enabled or not.
|
|
||||||
*/
|
|
||||||
a20_check:
|
|
||||||
pusha
|
|
||||||
mov $0x888888, %edi
|
|
||||||
mov $0x088888, %esi
|
|
||||||
mov %edi, (%edi)
|
|
||||||
mov %esi, (%esi)
|
|
||||||
cmpsl
|
|
||||||
popa
|
|
||||||
jne a20_enabled
|
|
||||||
xor %eax, %eax
|
|
||||||
ret
|
|
||||||
a20_enabled:
|
|
||||||
mov $1, %eax
|
|
||||||
ret
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Enables the a20 line using the PS2 controller.
|
|
||||||
* Note: Interrupts must be disabled for this function.
|
|
||||||
*/
|
|
||||||
a20_enable:
|
|
||||||
pushf
|
|
||||||
cli
|
|
||||||
|
|
||||||
call a20_wait_write
|
|
||||||
mov $0xad, %al
|
|
||||||
outb %al, $0x64
|
|
||||||
|
|
||||||
call a20_wait_write
|
|
||||||
mov $0xd0, %al
|
|
||||||
outb %al, $0x64
|
|
||||||
|
|
||||||
call a20_wait_read
|
|
||||||
inb $0x60, %al
|
|
||||||
push %eax
|
|
||||||
|
|
||||||
call a20_wait_write
|
|
||||||
mov $0xd1, %al
|
|
||||||
outb %al, $0x64
|
|
||||||
|
|
||||||
pop %eax
|
|
||||||
or $2, %al
|
|
||||||
outb %al, $0x60
|
|
||||||
|
|
||||||
call a20_wait_write
|
|
||||||
|
|
||||||
popf
|
|
||||||
ret
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Waits for the PS2 controller to be available for reading.
|
|
||||||
*/
|
|
||||||
a20_wait_read:
|
|
||||||
in $0x64, %al
|
|
||||||
test $1, %al
|
|
||||||
jz a20_wait_read
|
|
||||||
ret
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Waits for the PS2 controller to be available for writing.
|
|
||||||
*/
|
|
||||||
a20_wait_write:
|
|
||||||
in $0x64, %al
|
|
||||||
test $2, %al
|
|
||||||
jnz a20_wait_write
|
|
||||||
ret
|
|
@ -1,114 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2024 Luc Lenôtre
|
|
||||||
*
|
|
||||||
* This file is part of Maestro.
|
|
||||||
*
|
|
||||||
* Maestro is free software: you can redistribute it and/or modify it under the
|
|
||||||
* terms of the GNU General Public License as published by the Free Software
|
|
||||||
* Foundation, either version 3 of the License, or (at your option) any later
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
* Maestro is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* Maestro. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
.section .boot.text, "ax"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Constants used by Multiboot2 to detect the kernel.
|
|
||||||
*/
|
|
||||||
.set MULTIBOOT_MAGIC, 0xe85250d6
|
|
||||||
.set MULTIBOOT_ARCHITECTURE, 0
|
|
||||||
.set HEADER_LENGTH, (header_end - header)
|
|
||||||
.set CHECKSUM, -(MULTIBOOT_MAGIC + MULTIBOOT_ARCHITECTURE + HEADER_LENGTH)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Multiboot header tags constants.
|
|
||||||
*/
|
|
||||||
.set MULTIBOOT_HEADER_TAG_END, 0
|
|
||||||
.set MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS, 3
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The Multiboot2 kernel header.
|
|
||||||
*/
|
|
||||||
.align 8
|
|
||||||
header:
|
|
||||||
.long MULTIBOOT_MAGIC
|
|
||||||
.long MULTIBOOT_ARCHITECTURE
|
|
||||||
.long HEADER_LENGTH
|
|
||||||
.long CHECKSUM
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The entry tag, setting the entry point of the kernel.
|
|
||||||
*/
|
|
||||||
.align 8
|
|
||||||
entry_address_tag:
|
|
||||||
.short MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS
|
|
||||||
.short 1
|
|
||||||
.long (entry_address_tag_end - entry_address_tag)
|
|
||||||
.long multiboot_entry
|
|
||||||
entry_address_tag_end:
|
|
||||||
|
|
||||||
.align 8
|
|
||||||
.short MULTIBOOT_HEADER_TAG_END
|
|
||||||
.short 0
|
|
||||||
.long 8
|
|
||||||
header_end:
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The size of the kernel stack.
|
|
||||||
*/
|
|
||||||
.set STACK_SIZE, 32768
|
|
||||||
|
|
||||||
.global boot_stack
|
|
||||||
.global boot_stack_begin
|
|
||||||
|
|
||||||
.global multiboot_entry
|
|
||||||
.type multiboot_entry, @function
|
|
||||||
|
|
||||||
.extern setup_gdt
|
|
||||||
.extern _init
|
|
||||||
.extern _fini
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The entry point of the kernel.
|
|
||||||
*/
|
|
||||||
multiboot_entry:
|
|
||||||
mov $boot_stack_begin, %esp
|
|
||||||
xor %ebp, %ebp
|
|
||||||
pushl $0
|
|
||||||
popf
|
|
||||||
cli
|
|
||||||
|
|
||||||
push %eax
|
|
||||||
push %ebx
|
|
||||||
call a20_handle
|
|
||||||
call setup_gdt
|
|
||||||
call kernel_remap
|
|
||||||
pop %ebx
|
|
||||||
pop %eax
|
|
||||||
|
|
||||||
mov $(0xc0000000 + boot_stack_begin), %esp
|
|
||||||
push %ebx
|
|
||||||
push %eax
|
|
||||||
call kernel_main
|
|
||||||
# `kernel_main` cannot return
|
|
||||||
ud2
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.section .boot.stack, "aw"
|
|
||||||
|
|
||||||
.align 8
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The kernel stack.
|
|
||||||
*/
|
|
||||||
boot_stack:
|
|
||||||
.size boot_stack, STACK_SIZE
|
|
||||||
.skip STACK_SIZE
|
|
||||||
boot_stack_begin:
|
|
@ -1,191 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2024 Luc Lenôtre
|
|
||||||
*
|
|
||||||
* This file is part of Maestro.
|
|
||||||
*
|
|
||||||
* Maestro is free software: you can redistribute it and/or modify it under the
|
|
||||||
* terms of the GNU General Public License as published by the Free Software
|
|
||||||
* Foundation, either version 3 of the License, or (at your option) any later
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
* Maestro is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* Maestro. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
.global GDT_KERNEL_CS
|
|
||||||
.global GDT_KERNEL_DS
|
|
||||||
.global GDT_USER_CS
|
|
||||||
.global GDT_USER_DS
|
|
||||||
.global GDT_TSS
|
|
||||||
|
|
||||||
.global GDT_DESC_VIRT_PTR
|
|
||||||
|
|
||||||
.global setup_gdt
|
|
||||||
.global gdt_move
|
|
||||||
|
|
||||||
.type setup_gdt, @function
|
|
||||||
.type gdt_copy, @function
|
|
||||||
.type gdt_move, @function
|
|
||||||
|
|
||||||
.section .boot.data, "aw"
|
|
||||||
|
|
||||||
.align 8
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The beginning of the GDT.
|
|
||||||
* Every segment covers the whole memory space.
|
|
||||||
*/
|
|
||||||
gdt_start:
|
|
||||||
.quad 0
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Segment for the kernel code.
|
|
||||||
*/
|
|
||||||
gdt_kernel_code:
|
|
||||||
.word 0xffff
|
|
||||||
.word 0
|
|
||||||
.byte 0
|
|
||||||
.byte 0b10011010
|
|
||||||
.byte 0b11001111
|
|
||||||
.byte 0
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Segment for the kernel data.
|
|
||||||
*/
|
|
||||||
gdt_kernel_data:
|
|
||||||
.word 0xffff
|
|
||||||
.word 0
|
|
||||||
.byte 0
|
|
||||||
.byte 0b10010010
|
|
||||||
.byte 0b11001111
|
|
||||||
.byte 0
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Segment for the user code.
|
|
||||||
*/
|
|
||||||
gdt_user_code:
|
|
||||||
.word 0xffff
|
|
||||||
.word 0
|
|
||||||
.byte 0
|
|
||||||
.byte 0b11111010
|
|
||||||
.byte 0b11001111
|
|
||||||
.byte 0
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Segment for the user data.
|
|
||||||
*/
|
|
||||||
gdt_user_data:
|
|
||||||
.word 0xffff
|
|
||||||
.word 0
|
|
||||||
.byte 0
|
|
||||||
.byte 0b11110010
|
|
||||||
.byte 0b11001111
|
|
||||||
.byte 0
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reserved space for the Task State Segment.
|
|
||||||
*/
|
|
||||||
gdt_tss:
|
|
||||||
.quad 0
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TLS GDT entries.
|
|
||||||
*/
|
|
||||||
gdt_tls:
|
|
||||||
.quad 0
|
|
||||||
.quad 0
|
|
||||||
.quad 0
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The GDT descriptor.
|
|
||||||
*/
|
|
||||||
gdt:
|
|
||||||
.word gdt - gdt_start - 1
|
|
||||||
.long gdt_start
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Offsets into the GDT for each segment.
|
|
||||||
*/
|
|
||||||
.set GDT_KERNEL_CS, (gdt_kernel_code - gdt_start)
|
|
||||||
.set GDT_KERNEL_DS, (gdt_kernel_data - gdt_start)
|
|
||||||
.set GDT_USER_CS, (gdt_user_code - gdt_start)
|
|
||||||
.set GDT_USER_DS, (gdt_user_data - gdt_start)
|
|
||||||
.set GDT_TSS, (gdt_tss - gdt_start)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Physical address to the GDT.
|
|
||||||
*/
|
|
||||||
.set GDT_PHYS_PTR, 0x800
|
|
||||||
/*
|
|
||||||
* The size of the GDT in bytes.
|
|
||||||
*/
|
|
||||||
.set GDT_SIZE, (gdt - gdt_start)
|
|
||||||
/*
|
|
||||||
* Physical address to the GDT descriptor.
|
|
||||||
*/
|
|
||||||
.set GDT_DESC_PHYS_PTR, (GDT_PHYS_PTR + (gdt - gdt_start))
|
|
||||||
/*
|
|
||||||
* Virtual address to the GDT.
|
|
||||||
*/
|
|
||||||
.set GDT_VIRT_PTR, (0xc0000000 + GDT_PHYS_PTR)
|
|
||||||
/*
|
|
||||||
* Virtual address to the GDT descriptor.
|
|
||||||
*/
|
|
||||||
.set GDT_DESC_VIRT_PTR, (GDT_VIRT_PTR + (gdt - gdt_start))
|
|
||||||
|
|
||||||
.section .boot.text, "ax"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Switches the CPU to protected mode.
|
|
||||||
*/
|
|
||||||
setup_gdt:
|
|
||||||
cli
|
|
||||||
|
|
||||||
call gdt_copy
|
|
||||||
mov $GDT_DESC_PHYS_PTR, %eax
|
|
||||||
movl $GDT_PHYS_PTR, 2(%eax)
|
|
||||||
|
|
||||||
lgdt GDT_DESC_PHYS_PTR
|
|
||||||
|
|
||||||
mov %cr0, %eax
|
|
||||||
or $1, %al
|
|
||||||
mov %eax, %cr0
|
|
||||||
|
|
||||||
jmp $GDT_KERNEL_CS, $complete_flush
|
|
||||||
complete_flush:
|
|
||||||
mov $GDT_KERNEL_DS, %ax
|
|
||||||
mov %ax, %ds
|
|
||||||
mov %ax, %es
|
|
||||||
mov %ax, %ss
|
|
||||||
|
|
||||||
mov $0, %ax
|
|
||||||
mov %ax, %fs
|
|
||||||
mov %ax, %gs
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copies the GDT to its physical address.
|
|
||||||
*/
|
|
||||||
gdt_copy:
|
|
||||||
mov $gdt_start, %esi
|
|
||||||
mov $GDT_PHYS_PTR, %edi
|
|
||||||
mov $(GDT_SIZE + 6), %ecx
|
|
||||||
rep movsb
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Moves the GDT to the new virtual address after kernel relocation.
|
|
||||||
*/
|
|
||||||
gdt_move:
|
|
||||||
mov $GDT_DESC_VIRT_PTR, %eax
|
|
||||||
movl $GDT_VIRT_PTR, 2(%eax)
|
|
||||||
|
|
||||||
lgdt GDT_DESC_VIRT_PTR
|
|
||||||
|
|
||||||
ret
|
|
@ -1,113 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2024 Luc Lenôtre
|
|
||||||
*
|
|
||||||
* This file is part of Maestro.
|
|
||||||
*
|
|
||||||
* Maestro is free software: you can redistribute it and/or modify it under the
|
|
||||||
* terms of the GNU General Public License as published by the Free Software
|
|
||||||
* Foundation, either version 3 of the License, or (at your option) any later
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
* Maestro is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* Maestro. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file handles kernel remapping in order to place it in High Memory.
|
|
||||||
* To do so, paging is enabled using a page directory that remaps the whole
|
|
||||||
* kernel.
|
|
||||||
*
|
|
||||||
* The created page directory has to be replaced when kernel memory management
|
|
||||||
* is ready.
|
|
||||||
*/
|
|
||||||
|
|
||||||
.section .boot.text, "ax"
|
|
||||||
|
|
||||||
.global kernel_remap
|
|
||||||
|
|
||||||
.type kernel_remap, @function
|
|
||||||
.type pse_enable, @function
|
|
||||||
|
|
||||||
.extern gdt_move
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Remaps the first gigabyte of memory to the last one.
|
|
||||||
*
|
|
||||||
* This function enables PSE.
|
|
||||||
*/
|
|
||||||
kernel_remap:
|
|
||||||
push %ebx
|
|
||||||
|
|
||||||
// Zero page directory
|
|
||||||
xor %eax, %eax
|
|
||||||
mov $remap_dir, %esi
|
|
||||||
L1:
|
|
||||||
movl $0, (%esi)
|
|
||||||
add $4, %esi
|
|
||||||
add $1, %eax
|
|
||||||
cmp $768, %eax
|
|
||||||
jne L1
|
|
||||||
|
|
||||||
// Fill entries
|
|
||||||
xor %eax, %eax
|
|
||||||
mov $remap_dir, %esi
|
|
||||||
L2:
|
|
||||||
// (i * PAGE_SIZE * 1024)
|
|
||||||
mov %eax, %ebx
|
|
||||||
mov $22, %cl
|
|
||||||
shl %cl, %ebx
|
|
||||||
// PAGE_SIZE | WRITE | PRESENT
|
|
||||||
or $(128 + 2 + 1), %ebx
|
|
||||||
movl %ebx, (%esi)
|
|
||||||
movl %ebx, (4 * 768)(%esi)
|
|
||||||
add $4, %esi
|
|
||||||
add $1, %eax
|
|
||||||
cmp $256, %eax
|
|
||||||
jne L2
|
|
||||||
|
|
||||||
push $remap_dir
|
|
||||||
call pse_enable
|
|
||||||
add $4, %esp
|
|
||||||
|
|
||||||
call gdt_move
|
|
||||||
|
|
||||||
pop %ebx
|
|
||||||
ret
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Enables Page Size Extension (PSE) and paging using the given page directory.
|
|
||||||
*/
|
|
||||||
pse_enable:
|
|
||||||
push %ebp
|
|
||||||
mov %esp, %ebp
|
|
||||||
push %eax
|
|
||||||
|
|
||||||
mov 8(%ebp), %eax
|
|
||||||
mov %eax, %cr3
|
|
||||||
|
|
||||||
mov %cr4, %eax
|
|
||||||
or $0x00000010, %eax
|
|
||||||
mov %eax, %cr4
|
|
||||||
|
|
||||||
mov %cr0, %eax
|
|
||||||
or $0x80010000, %eax
|
|
||||||
mov %eax, %cr0
|
|
||||||
|
|
||||||
pop %eax
|
|
||||||
mov %ebp, %esp
|
|
||||||
pop %ebp
|
|
||||||
ret
|
|
||||||
|
|
||||||
.section .boot.data, "aw"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The page directory used for kernel remapping.
|
|
||||||
*/
|
|
||||||
.align 4096
|
|
||||||
remap_dir:
|
|
||||||
.size remap_dir, 4096
|
|
||||||
.skip 4096
|
|
@ -41,21 +41,32 @@ pub const TSS_OFFSET: usize = 40;
|
|||||||
/// The offset of Thread Local Storage (TLS) entries.
|
/// The offset of Thread Local Storage (TLS) entries.
|
||||||
pub const TLS_OFFSET: usize = 48;
|
pub const TLS_OFFSET: usize = 48;
|
||||||
|
|
||||||
/// Structure representing a GDT entry.
|
/// A GDT entry.
|
||||||
#[repr(transparent)]
|
#[repr(C, align(8))]
|
||||||
#[derive(Clone, Copy, Default)]
|
#[derive(Clone, Copy, Default)]
|
||||||
pub struct Entry(pub u64);
|
pub struct Entry(pub u64);
|
||||||
|
|
||||||
impl Entry {
|
impl Entry {
|
||||||
|
/// Creates a new entry with the give information.
|
||||||
|
#[inline(always)]
|
||||||
|
pub const fn new(base: u32, limit: u32, access_byte: u8, flags: u8) -> Self {
|
||||||
|
let mut ent = Self(0);
|
||||||
|
ent.set_base(base);
|
||||||
|
ent.set_limit(limit);
|
||||||
|
ent.set_access_byte(access_byte);
|
||||||
|
ent.set_flags(flags);
|
||||||
|
ent
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the entry's base address.
|
/// Returns the entry's base address.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn get_base(&self) -> u32 {
|
pub const fn get_base(&self) -> u32 {
|
||||||
(((self.0 >> 16) & 0xffffff) | ((self.0 >> 32) & 0xff000000)) as _
|
(((self.0 >> 16) & 0xffffff) | ((self.0 >> 32) & 0xff000000)) as _
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the entry's base address.
|
/// Sets the entry's base address.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn set_base(&mut self, base: u32) {
|
pub const fn set_base(&mut self, base: u32) {
|
||||||
self.0 &= !(0xffffff << 16);
|
self.0 &= !(0xffffff << 16);
|
||||||
self.0 &= !(0xff << 56);
|
self.0 &= !(0xff << 56);
|
||||||
|
|
||||||
@ -65,7 +76,7 @@ impl Entry {
|
|||||||
|
|
||||||
/// Returns the entry's limit.
|
/// Returns the entry's limit.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn get_limit(&self) -> u32 {
|
pub const fn get_limit(&self) -> u32 {
|
||||||
((self.0 & 0xffff) | (((self.0 >> 48) & 0xf) << 16)) as _
|
((self.0 & 0xffff) | (((self.0 >> 48) & 0xf) << 16)) as _
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +84,7 @@ impl Entry {
|
|||||||
///
|
///
|
||||||
/// If the given limit is more than `pow(2, 20) - 1`, the value is truncated.
|
/// If the given limit is more than `pow(2, 20) - 1`, the value is truncated.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn set_limit(&mut self, limit: u32) {
|
pub const fn set_limit(&mut self, limit: u32) {
|
||||||
self.0 &= !0xffff;
|
self.0 &= !0xffff;
|
||||||
self.0 &= !(0xf << 48);
|
self.0 &= !(0xf << 48);
|
||||||
|
|
||||||
@ -83,39 +94,39 @@ impl Entry {
|
|||||||
|
|
||||||
/// Returns the value of the access byte.
|
/// Returns the value of the access byte.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn get_access_byte(&self) -> u8 {
|
pub const fn get_access_byte(&self) -> u8 {
|
||||||
((self.0 >> 40) & 0xff) as _
|
((self.0 >> 40) & 0xff) as _
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the value of the access byte.
|
/// Sets the value of the access byte.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn set_access_byte(&mut self, byte: u8) {
|
pub const fn set_access_byte(&mut self, byte: u8) {
|
||||||
self.0 &= !(0xff << 40);
|
self.0 &= !(0xff << 40);
|
||||||
self.0 |= (byte as u64) << 40;
|
self.0 |= (byte as u64) << 40;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the flags.
|
/// Returns the flags.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn get_flags(&self) -> u8 {
|
pub const fn get_flags(&self) -> u8 {
|
||||||
((self.0 >> 52) & 0x0f) as _
|
((self.0 >> 52) & 0x0f) as _
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the flags.
|
/// Sets the flags.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn set_flags(&mut self, flags: u8) {
|
pub const fn et_flags(&mut self, flags: u8) {
|
||||||
self.0 &= !(0x0f << 52);
|
self.0 &= !(0x0f << 52);
|
||||||
self.0 |= ((flags as u64) & 0x0f) << 52;
|
self.0 |= ((flags as u64) & 0x0f) << 52;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tells whether the entry is present.
|
/// Tells whether the entry is present.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn is_present(&self) -> bool {
|
pub const fn is_present(&self) -> bool {
|
||||||
(self.0 >> 47 & 1) != 0
|
(self.0 >> 47 & 1) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the entry present or not.
|
/// Sets the entry present or not.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn set_present(&mut self, present: bool) {
|
pub const fn set_present(&mut self, present: bool) {
|
||||||
if present {
|
if present {
|
||||||
self.0 |= 1 << 47;
|
self.0 |= 1 << 47;
|
||||||
} else {
|
} else {
|
||||||
|
@ -52,6 +52,7 @@
|
|||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
pub mod acpi;
|
pub mod acpi;
|
||||||
|
mod boot;
|
||||||
pub mod cmdline;
|
pub mod cmdline;
|
||||||
pub mod cpu;
|
pub mod cpu;
|
||||||
pub mod crypto;
|
pub mod crypto;
|
||||||
@ -60,7 +61,7 @@ pub mod device;
|
|||||||
pub mod elf;
|
pub mod elf;
|
||||||
pub mod event;
|
pub mod event;
|
||||||
pub mod file;
|
pub mod file;
|
||||||
#[cfg(target_arch = "x86")]
|
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||||
pub mod gdt;
|
pub mod gdt;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod idt;
|
pub mod idt;
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
//! The virtual memory makes the kernel able to isolate processes, which is
|
//! The virtual memory makes the kernel able to isolate processes, which is
|
||||||
//! essential for modern systems.
|
//! essential for modern systems.
|
||||||
|
|
||||||
#[cfg(target_arch = "x86")]
|
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||||
pub mod x86;
|
pub mod x86;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -4,14 +4,14 @@
|
|||||||
|
|
||||||
KERN_SRC=$(realpath $(dirname $0)/..)
|
KERN_SRC=$(realpath $(dirname $0)/..)
|
||||||
if [ -z "$ARCH" ]; then
|
if [ -z "$ARCH" ]; then
|
||||||
ARCH="x86"
|
ARCH="x86_64"
|
||||||
fi
|
fi
|
||||||
CARGOFLAGS="--target $KERN_SRC/kernel/arch/$ARCH/$ARCH.json $CARGOFLAGS"
|
export CARGOFLAGS="--target $KERN_SRC/kernel/arch/$ARCH/$ARCH.json $CARGOFLAGS"
|
||||||
|
|
||||||
if [ ! -z "$PROFILE" ] && [ "$PROFILE" != "debug" ]; then
|
if [ ! -z "$PROFILE" ] && [ "$PROFILE" != "debug" ]; then
|
||||||
CARGOFLAGS="$CARGOFLAGS --profile $PROFILE"
|
CARGOFLAGS="$CARGOFLAGS --profile $PROFILE"
|
||||||
else
|
else
|
||||||
PROFILE="debug"
|
export PROFILE="debug"
|
||||||
fi
|
fi
|
||||||
export RUSTFLAGS="--extern kernel=$KERN_SRC/kernel/target/$ARCH/$PROFILE/libkernel.so -L $KERN_SRC/kernel/target/$ARCH/$PROFILE/deps -L $KERN_SRC/kernel/target/$PROFILE/deps $RUSTFLAGS"
|
export RUSTFLAGS="--extern kernel=$KERN_SRC/kernel/target/$ARCH/$PROFILE/libkernel.so -L $KERN_SRC/kernel/target/$ARCH/$PROFILE/deps -L $KERN_SRC/kernel/target/$PROFILE/deps $RUSTFLAGS"
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "nightly-2024-09-18"
|
channel = "nightly-2024-09-18"
|
||||||
components = ["rustfmt", "rustc-dev", "rust-src", "clippy", "miri"]
|
components = ["rustfmt", "rustc-dev", "rust-src", "clippy", "miri"]
|
||||||
targets = ["i686-unknown-linux-musl"]
|
|
||||||
profile = "minimal"
|
profile = "minimal"
|
||||||
|
Loading…
Reference in New Issue
Block a user