Squashed some bugs; implemented first iteration of kernel items
This commit is contained in:
parent
a2311366f2
commit
04ee0a1cb2
13 changed files with 245 additions and 111 deletions
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
|
@ -4,6 +4,7 @@
|
|||
"rust-analyzer.linkedProjects": [
|
||||
"kernel/Cargo.toml",
|
||||
"kernel/aphrodite_proc_macros/Cargo.toml",
|
||||
"kernel/aphrodite_common/Cargo.toml"
|
||||
"kernel/aphrodite_common/Cargo.toml",
|
||||
"user/Cargo.toml"
|
||||
],
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
display_library: x, options="gui_debug"
|
||||
port_e9_hack: enabled=1
|
||||
cpu: reset_on_triple_fault=0, model=tigerlake
|
||||
cpu: reset_on_triple_fault=0, model=corei7_icelake_u
|
||||
magic_break: enabled=1
|
||||
|
||||
ata0-master: type=cdrom, path=../kernel/aphrodite.iso, status=inserted
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# config.aphro for aphrodite devel-6a2a677-out-of-tree
|
||||
CFG_VERSION=devel-6a2a677-out-of-tree
|
||||
CONT_WITH_DIFFERENT_VERSION=false
|
||||
CONT_WITH_DIFFERENT_VERSION=true
|
||||
|
||||
# Begin metadata
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
RUSTFLAGS='-Clink-arg=--script=link.x' cargo expand --target i686-unknown-none.json --release -Zbuild-std --bin entrypoint
|
||||
RUSTFLAGS='-Clink-arg=--script=link.x' cargo expand --target i686-unknown-none.json --release -Zbuild-std --bin entrypoint_x86
|
|
@ -220,18 +220,18 @@ extern "C" fn _start() -> ! {
|
|||
ptr = (ptr + current_tag.tag_len as usize + 7) & !7;
|
||||
if ptr>end_addr {
|
||||
cfg_match! {
|
||||
cfg(all(CONFIG_PREUSER_ERROR_ON_INVALID_LENGTH = "true", CONFIG_PREUSER_PANIC_ON_INVALID_LENGTH = "false")) => {
|
||||
all(CONFIG_PREUSER_ERROR_ON_INVALID_LENGTH = "true", CONFIG_PREUSER_PANIC_ON_INVALID_LENGTH = "false") => {
|
||||
serrorsln("Current tag length would put pointer out-of-bounds; CONFIG_PREUSER_ERROR_ON_INVALID_LENGTH is set, continuing");
|
||||
}
|
||||
cfg(all(CONFIG_PREUSER_WARN_ON_INVALID_LENGTH = "true", CONFIG_PREUSER_PANIC_ON_INVALID_LENGTH = "false")) => {
|
||||
all(CONFIG_PREUSER_WARN_ON_INVALID_LENGTH = "true", CONFIG_PREUSER_PANIC_ON_INVALID_LENGTH = "false") => {
|
||||
swarningsln("Current tag length would put pointer out-of-bounds; CONFIG_PREUSER_WARN_ON_INVALID_LENGTH is set, continuing");
|
||||
}
|
||||
}
|
||||
cfg_match! {
|
||||
cfg(not(CONFIG_PREUSER_PANIC_ON_INVALID_LENGTH = "false")) => {
|
||||
not(CONFIG_PREUSER_PANIC_ON_INVALID_LENGTH = "false") => {
|
||||
panic!("current tag length would put pointer out-of-bounds")
|
||||
}
|
||||
cfg(CONFIG_PREUSER_EXIT_LOOP_ON_INVALID_LENGTH = "true") => {
|
||||
CONFIG_PREUSER_EXIT_LOOP_ON_INVALID_LENGTH = "true" => {
|
||||
sinfos("Exiting loop as current tag length would put pointer out-of-bounds ");
|
||||
sinfosnpln("and CONFIG_PREUSER_EXIT_LOOP_ON_INVALID_LENGTH is set");
|
||||
break;
|
||||
|
@ -263,7 +263,7 @@ extern "C" fn _start() -> ! {
|
|||
sdebugs("Framebuffer bpp: ");
|
||||
sdebugbnpln(&aphrodite::u8_as_u8_slice(framebuffer_info.bpp));
|
||||
|
||||
sdebugsln("Beginning output to screen...");
|
||||
sdebugsln("Beginning test output to screen...");
|
||||
|
||||
let ega: &dyn aphrodite::display::TextDisplay = &framebuffer_info;
|
||||
framebuffer_info.disable_cursor();
|
||||
|
@ -272,11 +272,11 @@ extern "C" fn _start() -> ! {
|
|||
toutputsln("Testing EGA Text framebuffer...", ega).unwrap();
|
||||
toutputsln("Testing EGA Text framebuffer...", ega).unwrap();
|
||||
|
||||
aphrodite::indep_boot_entry::indep_boot_entry(Some(ega), &BI);
|
||||
aphrodite::indep_boot_entry::IndepBootEntry(Some(ega), &BI);
|
||||
}
|
||||
}
|
||||
|
||||
aphrodite::indep_boot_entry::indep_boot_entry(None, &BI);
|
||||
aphrodite::indep_boot_entry::IndepBootEntry(None, &BI);
|
||||
}
|
||||
|
||||
#[unsafe(link_section = ".panic")]
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
use syn::{parse::Parse, Ident};
|
||||
use strum::IntoEnumIterator;
|
||||
use strum_macros::EnumIter;
|
||||
|
||||
#[derive(Debug, Clone, Copy, EnumIter)]
|
||||
pub enum KernelItem {
|
||||
IndepBootEntry,
|
||||
ArchBootEntry,
|
||||
SyscallSetup,
|
||||
MemMapGen,
|
||||
MemMapAlloc,
|
||||
PreuserModLoad,
|
||||
InitEnv,
|
||||
KernelFSMount,
|
||||
StorageFSMount,
|
||||
PreuserMod,
|
||||
RamLoader,
|
||||
UserInit,
|
||||
UserModLoad,
|
||||
ProcessFSMount
|
||||
}
|
||||
|
||||
impl Parse for KernelItem {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
let ident: Ident = input.parse()?;
|
||||
|
||||
for variant in Self::iter() {
|
||||
let name = format!("{:?}", variant);
|
||||
|
||||
if ident.to_string().as_str() == name {
|
||||
return Ok(variant);
|
||||
}
|
||||
}
|
||||
|
||||
Err(syn::Error::new(ident.span(), "Expected one of aphrodite_common::KernelItem's variants"))
|
||||
}
|
||||
}
|
|
@ -13,7 +13,11 @@ const MEM_TEST_SIZES: [usize; 8] = [1, 2, 4, 8, 16, 32, 64, 128];
|
|||
|
||||
/// The real entrypoint to the kernel. `internel/arch/*/entry.rs` files eventually call this.
|
||||
#[kernel_item(IndepBootEntry)]
|
||||
pub fn indep_boot_entry(display: Option<&dyn crate::display::TextDisplay>, BI: &crate::boot::BootInfo) -> ! {
|
||||
fn indep_boot_entry(
|
||||
display: Option<&dyn crate::display::TextDisplay>,
|
||||
#[allow(non_snake_case)]
|
||||
BI: &crate::boot::BootInfo,
|
||||
) -> ! {
|
||||
crate::arch::output::sdebugsln("Entrypoint called");
|
||||
|
||||
let display = display.unwrap();
|
||||
|
@ -21,18 +25,19 @@ pub fn indep_boot_entry(display: Option<&dyn crate::display::TextDisplay>, BI: &
|
|||
display.clear_screen(COLOR_DEFAULT);
|
||||
sreset();
|
||||
|
||||
let mut mem_map = BI.memory_map.unwrap();
|
||||
let allocator_res = crate::mem::MemoryMapAlloc::new(&mut mem_map);
|
||||
if allocator_res.is_err() {
|
||||
panic!("{}", allocator_res.unwrap_err());
|
||||
}
|
||||
let allocator = allocator_res.unwrap();
|
||||
let mem_map = BI.memory_map.unwrap();
|
||||
crate::mem::MemMapAllocInit(mem_map).unwrap();
|
||||
let allocator = crate::mem::MemMapAlloc().unwrap();
|
||||
|
||||
tdebugsln("Testing allocator...", display).unwrap();
|
||||
|
||||
for size in MEM_TEST_SIZES {
|
||||
tdebugs("Number of allocations: ", display).unwrap();
|
||||
tdebugbnpln(&crate::u64_as_u8_slice(allocator.number_of_allocations()), display).unwrap();
|
||||
tdebugbnpln(
|
||||
&crate::u64_as_u8_slice(allocator.number_of_allocations()),
|
||||
display,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
tdebugs("Allocating ", display).unwrap();
|
||||
tdebugbnp(&crate::usize_as_u8_slice(size), display).unwrap();
|
||||
|
@ -40,7 +45,7 @@ pub fn indep_boot_entry(display: Option<&dyn crate::display::TextDisplay>, BI: &
|
|||
|
||||
let allocation = allocator.allocate(Layout::from_size_align(size, 1).unwrap());
|
||||
if let Err(_) = allocation {
|
||||
terrors("Failed to allocate: ",display).unwrap();
|
||||
terrors("Failed to allocate: ", display).unwrap();
|
||||
unsafe { crate::mem::LAST_MEMMAP_ERR.unwrap_err().display_np(display) }
|
||||
panic!("Allocation failure");
|
||||
} else if let Ok(ptr) = allocation {
|
||||
|
@ -49,7 +54,12 @@ pub fn indep_boot_entry(display: Option<&dyn crate::display::TextDisplay>, BI: &
|
|||
tdebugsnpln(".", display).unwrap();
|
||||
tdebugsln("", display).unwrap();
|
||||
tdebugsln("Deallocating memory...", display).unwrap();
|
||||
unsafe { allocator.deallocate(ptr.as_non_null_ptr(), Layout::from_size_align(size, 1).unwrap()) }
|
||||
unsafe {
|
||||
allocator.deallocate(
|
||||
ptr.as_non_null_ptr(),
|
||||
Layout::from_size_align(size, 1).unwrap(),
|
||||
)
|
||||
}
|
||||
if let Err(err) = unsafe { crate::mem::LAST_MEMMAP_ERR } {
|
||||
terrors("Failed to deallocate: ", display).unwrap();
|
||||
err.display_np(display);
|
||||
|
@ -59,4 +69,4 @@ pub fn indep_boot_entry(display: Option<&dyn crate::display::TextDisplay>, BI: &
|
|||
tdebugsln("", display).unwrap();
|
||||
}
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
//! Memory allocation.
|
||||
|
||||
use core::{
|
||||
alloc::{Allocator, GlobalAlloc}, fmt::Debug, num::NonZero, ops::Range, ptr::{null_mut, NonNull}
|
||||
alloc::{Allocator, GlobalAlloc},
|
||||
fmt::Debug,
|
||||
mem::MaybeUninit,
|
||||
num::NonZero,
|
||||
ops::Range,
|
||||
ptr::{NonNull, null_mut},
|
||||
};
|
||||
|
||||
use crate::boot::MemoryType;
|
||||
use crate::boot::{MemoryMap, MemoryType};
|
||||
|
||||
use aphrodite_proc_macros::*;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct Allocation {
|
||||
/// Whether this allocation is used. This is used so that the
|
||||
/// entire allocation table doesn't need to be shifted back
|
||||
/// entire allocation table doesn't need to be shifted back
|
||||
/// on every allocation.
|
||||
pub used: bool,
|
||||
/// The starting address of the allocation.
|
||||
|
@ -50,12 +57,48 @@ impl Iterator for AllocationIter {
|
|||
crate::arch::output::sdebugsln("Providing allocation from iterator");
|
||||
|
||||
Some(&unsafe {
|
||||
*((self.ptr as usize + (size_of::<Allocation>() * (self.idx as usize-1)))
|
||||
*((self.ptr as usize + (size_of::<Allocation>() * (self.idx as usize - 1)))
|
||||
as *const Allocation)
|
||||
} as *const Allocation as *mut Allocation)
|
||||
}
|
||||
}
|
||||
|
||||
static mut ALLOCATOR: MaybeUninit<MemoryMapAlloc<'static>> = MaybeUninit::uninit();
|
||||
static mut ALLOCATOR_MEMMAP: MaybeUninit<MemoryMap> = MaybeUninit::uninit();
|
||||
static mut ALLOCATOR_INITALIZED: bool = false;
|
||||
|
||||
#[kernel_item(MemMapAlloc)]
|
||||
fn get_allocator() -> Option<&'static MemoryMapAlloc<'static>> {
|
||||
if unsafe { ALLOCATOR_INITALIZED } {
|
||||
#[allow(static_mut_refs)]
|
||||
return Some(unsafe { ALLOCATOR.assume_init_ref() });
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
#[kernel_item(MemMapAllocInit)]
|
||||
fn memory_map_alloc_init(
|
||||
memmap: crate::boot::MemoryMap,
|
||||
) -> Result<(), crate::Error<'static>> {
|
||||
#[allow(static_mut_refs)]
|
||||
unsafe {
|
||||
ALLOCATOR_MEMMAP.write(memmap);
|
||||
}
|
||||
#[allow(static_mut_refs)]
|
||||
let alloc = MemoryMapAlloc::new(unsafe { ALLOCATOR_MEMMAP.assume_init_mut() })?;
|
||||
|
||||
#[allow(static_mut_refs)]
|
||||
unsafe {
|
||||
ALLOCATOR.write(alloc);
|
||||
}
|
||||
unsafe {
|
||||
ALLOCATOR_INITALIZED = true;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// A implementation of a physical memory allocator that uses a [crate::boot::MemoryMap].
|
||||
pub struct MemoryMapAlloc<'a> {
|
||||
/// The memory map to use to allocate memory.
|
||||
|
@ -84,7 +127,12 @@ const EXTEND_ALLOCATION_OTHER_ALLOCATION: i16 = -6;
|
|||
impl<'a> Debug for MemoryMapAlloc<'a> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
f.write_str("MemoryMapAlloc with ")?;
|
||||
f.write_str(core::str::from_utf8(&crate::u64_as_u8_slice(unsafe { *self.allocationheader }.num_allocations)).unwrap())?;
|
||||
f.write_str(
|
||||
core::str::from_utf8(&crate::u64_as_u8_slice(
|
||||
unsafe { *self.allocationheader }.num_allocations,
|
||||
))
|
||||
.unwrap(),
|
||||
)?;
|
||||
f.write_str(" allocations")?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -115,7 +163,9 @@ impl<'a> MemoryMapAlloc<'a> {
|
|||
(),
|
||||
);
|
||||
out.allocations = core::ptr::from_raw_parts_mut(
|
||||
core::ptr::without_provenance_mut::<()>(mapping.start as usize+size_of::<AllocationHeader>()),
|
||||
core::ptr::without_provenance_mut::<()>(
|
||||
mapping.start as usize + size_of::<AllocationHeader>(),
|
||||
),
|
||||
(),
|
||||
);
|
||||
out.max_allocations_size = mapping.len;
|
||||
|
@ -126,7 +176,9 @@ impl<'a> MemoryMapAlloc<'a> {
|
|||
(),
|
||||
);
|
||||
out.allocations = core::ptr::from_raw_parts_mut(
|
||||
core::ptr::without_provenance_mut::<()>(mapping.start as usize+size_of::<AllocationHeader>()),
|
||||
core::ptr::without_provenance_mut::<()>(
|
||||
mapping.start as usize + size_of::<AllocationHeader>(),
|
||||
),
|
||||
(),
|
||||
);
|
||||
out.max_allocations_size = mapping.len;
|
||||
|
@ -149,7 +201,7 @@ impl<'a> MemoryMapAlloc<'a> {
|
|||
used: true,
|
||||
addr: out.allocations as usize as u64,
|
||||
len: (size_of::<Allocation>() * 32) as u64,
|
||||
num_allocations: 1
|
||||
num_allocations: 1,
|
||||
}
|
||||
}
|
||||
Ok(out)
|
||||
|
@ -182,10 +234,10 @@ impl<'a> MemoryMapAlloc<'a> {
|
|||
|
||||
let num_allocations = unsafe { *self.allocationheader }.num_allocations;
|
||||
|
||||
if unsafe { *self.allocations }.len
|
||||
< (size_of::<Allocation>() as u64 * (num_allocations))
|
||||
{
|
||||
if unsafe { *self.allocationheader }.len + size_of::<Allocation>() as u64 >= self.max_allocations_size {
|
||||
if unsafe { *self.allocations }.len < (size_of::<Allocation>() as u64 * (num_allocations)) {
|
||||
if unsafe { *self.allocationheader }.len + size_of::<Allocation>() as u64
|
||||
>= self.max_allocations_size
|
||||
{
|
||||
return Err(crate::Error::new(
|
||||
"not enough space for another allocation",
|
||||
TOO_MANY_ALLOCATIONS,
|
||||
|
@ -202,7 +254,7 @@ impl<'a> MemoryMapAlloc<'a> {
|
|||
let new_alloc = (self.allocations as usize
|
||||
+ (size_of::<Allocation>() * (num_allocations) as usize))
|
||||
as *const Allocation as *mut Allocation;
|
||||
|
||||
|
||||
unsafe { (*new_alloc) = allocation }
|
||||
|
||||
Ok(())
|
||||
|
@ -266,7 +318,9 @@ impl<'a> MemoryMapAlloc<'a> {
|
|||
|
||||
/// Check to see if any allocations contain the given address. Returns true if so.
|
||||
fn check_addr(&self, addr: u64) -> bool {
|
||||
if addr >= (self.allocationheader as u64) && addr < (self.allocationheader as u64+unsafe { *self.allocationheader }.len) {
|
||||
if addr >= (self.allocationheader as u64)
|
||||
&& addr < (self.allocationheader as u64 + unsafe { *self.allocationheader }.len)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
for ele in self.allocations_iter() {
|
||||
|
@ -345,11 +399,17 @@ unsafe impl<'a> Allocator for MemoryMapAlloc<'a> {
|
|||
allocatable = alloc;
|
||||
}
|
||||
if allocatable {
|
||||
addr = mapping.start+mapping.len-layout.size() as u64;
|
||||
while self.check_range(addr..addr+layout.size() as u64) && (addr as usize % layout.align() != 0) && addr >= mapping.start {
|
||||
addr -= layout.size() as u64/crate::cfg_int!("CONFIG_ALLOC_PRECISION", u64);
|
||||
addr = mapping.start + mapping.len - layout.size() as u64;
|
||||
while self.check_range(addr..addr + layout.size() as u64)
|
||||
&& (addr as usize % layout.align() != 0)
|
||||
&& addr >= mapping.start
|
||||
{
|
||||
addr -= layout.size() as u64 / crate::cfg_int!("CONFIG_ALLOC_PRECISION", u64);
|
||||
}
|
||||
if (!self.check_range(addr..addr+layout.size() as u64)) && (addr as usize % layout.align() == 0) && addr >= mapping.start {
|
||||
if (!self.check_range(addr..addr + layout.size() as u64))
|
||||
&& (addr as usize % layout.align() == 0)
|
||||
&& addr >= mapping.start
|
||||
{
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
|
@ -364,7 +424,11 @@ unsafe impl<'a> Allocator for MemoryMapAlloc<'a> {
|
|||
}
|
||||
return Err(core::alloc::AllocError {});
|
||||
}
|
||||
if let Err(err) = self.add_allocation(Allocation { used: true, addr, len: layout.size() as u64 }) {
|
||||
if let Err(err) = self.add_allocation(Allocation {
|
||||
used: true,
|
||||
addr,
|
||||
len: layout.size() as u64,
|
||||
}) {
|
||||
unsafe { LAST_MEMMAP_ERR = Err(err) }
|
||||
return Err(core::alloc::AllocError {});
|
||||
}
|
||||
|
@ -387,7 +451,9 @@ unsafe impl<'a> Allocator for MemoryMapAlloc<'a> {
|
|||
}
|
||||
return;
|
||||
}
|
||||
crate::arch::output::sdebugbln(&crate::u64_as_u8_slice(unsafe { *self.allocationheader }.num_allocations));
|
||||
crate::arch::output::sdebugbln(&crate::u64_as_u8_slice(
|
||||
unsafe { *self.allocationheader }.num_allocations,
|
||||
));
|
||||
for allocation in self.allocations_iter() {
|
||||
crate::arch::output::sdebugsln("Allocation");
|
||||
let alloc = unsafe { *allocation }.clone();
|
||||
|
@ -401,7 +467,12 @@ unsafe impl<'a> Allocator for MemoryMapAlloc<'a> {
|
|||
}
|
||||
}
|
||||
// Memory not allocated, something is up, this is put after the loop to prevent a costly call to check_addr
|
||||
unsafe { LAST_MEMMAP_ERR = Err(crate::Error::new("memory not allocated", MEMORY_NOT_ALLOCATED)) }
|
||||
unsafe {
|
||||
LAST_MEMMAP_ERR = Err(crate::Error::new(
|
||||
"memory not allocated",
|
||||
MEMORY_NOT_ALLOCATED,
|
||||
))
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,59 +1,69 @@
|
|||
use proc_macro::TokenStream;
|
||||
use quote::{quote_spanned, ToTokens};
|
||||
use syn::{parse::{Parse, ParseStream}, spanned::Spanned, ItemFn, Signature, Token};
|
||||
use quote::{ToTokens, quote};
|
||||
use syn::{
|
||||
ItemFn, Signature, Token,
|
||||
parse::{Parse, ParseStream}
|
||||
};
|
||||
|
||||
struct KernelItemNameInput {
|
||||
item: aphrodite_common::KernelItem
|
||||
item: syn::Ident,
|
||||
}
|
||||
|
||||
impl Parse for KernelItemNameInput {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
let item: aphrodite_common::KernelItem = input.parse()?;
|
||||
let item: syn::Ident = input.parse()?;
|
||||
Ok(KernelItemNameInput { item })
|
||||
}
|
||||
}
|
||||
|
||||
fn to_tokens(signature: Signature, tokens: &mut TokenStream) {
|
||||
signature.constness.to_tokens(&mut (*tokens).clone().into());
|
||||
signature.asyncness.to_tokens(&mut (*tokens).clone().into());
|
||||
signature.unsafety.to_tokens(&mut (*tokens).clone().into());
|
||||
signature.abi.to_tokens(&mut (*tokens).clone().into());
|
||||
signature.fn_token.to_tokens(&mut (*tokens).clone().into());
|
||||
signature.generics.to_tokens(&mut (*tokens).clone().into());
|
||||
signature.paren_token.surround(&mut (*tokens).clone().into(), |tokens| {
|
||||
signature.inputs.to_tokens(tokens);
|
||||
if let Some(variadic) = &signature.variadic {
|
||||
if !signature.inputs.empty_or_trailing() {
|
||||
<Token![,]>::default().to_tokens(tokens);
|
||||
fn to_tokens(signature: Signature, tokens: &mut proc_macro2::TokenStream) {
|
||||
let ts = tokens;
|
||||
signature.constness.to_tokens(ts.into());
|
||||
signature.asyncness.to_tokens(ts.into());
|
||||
signature.unsafety.to_tokens(ts.into());
|
||||
signature.abi.to_tokens(ts.into());
|
||||
signature.fn_token.to_tokens(ts.into());
|
||||
signature.generics.to_tokens(ts.into());
|
||||
signature
|
||||
.paren_token
|
||||
.surround(ts.into(), |tokens| {
|
||||
signature.inputs.to_tokens(tokens);
|
||||
if let Some(variadic) = &signature.variadic {
|
||||
if !signature.inputs.empty_or_trailing() {
|
||||
<Token![,]>::default().to_tokens(tokens);
|
||||
}
|
||||
variadic.to_tokens(tokens);
|
||||
}
|
||||
variadic.to_tokens(tokens);
|
||||
}
|
||||
});
|
||||
signature.output.to_tokens(&mut (*tokens).clone().into());
|
||||
signature.generics.where_clause.to_tokens(&mut (*tokens).clone().into());
|
||||
});
|
||||
signature.output.to_tokens(ts.into());
|
||||
signature
|
||||
.generics
|
||||
.where_clause
|
||||
.to_tokens(ts.into());
|
||||
}
|
||||
|
||||
fn to_token_stream(signature: Signature) -> TokenStream {
|
||||
let mut tokens = proc_macro::TokenStream::new();
|
||||
fn to_token_stream(signature: Signature) -> proc_macro2::TokenStream {
|
||||
let mut tokens = proc_macro2::TokenStream::new();
|
||||
to_tokens(signature, &mut tokens);
|
||||
tokens.into()
|
||||
}
|
||||
|
||||
/// Implement a kernel item.
|
||||
/// Implement a kernel item.
|
||||
#[proc_macro_attribute]
|
||||
pub fn kernel_item(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let item_name_input: KernelItemNameInput = syn::parse_macro_input!(attr);
|
||||
let item_name = format!("{:?}", item_name_input.item);
|
||||
let name: KernelItemNameInput = syn::parse_macro_input!(attr);
|
||||
let item_name = name.item;
|
||||
|
||||
let input_fn: ItemFn = syn::parse_macro_input!(item as ItemFn);
|
||||
let input_fn = syn::parse_macro_input!(item as ItemFn);
|
||||
let fn_name = input_fn.clone().sig.ident;
|
||||
let fn_sig = to_token_stream(input_fn.clone().sig);
|
||||
|
||||
quote_spanned!(input_fn.span()=>{
|
||||
// The #item_name kernel item.
|
||||
quote!{
|
||||
/// The #item_name kernel item.
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const #item_name: #fn_sig = #fn_name;
|
||||
|
||||
#input_fn
|
||||
}).into()
|
||||
}
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
|
6
user/Cargo.toml
Normal file
6
user/Cargo.toml
Normal file
|
@ -0,0 +1,6 @@
|
|||
[package]
|
||||
name = "user"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
6
user/src/arch/mod.rs
Normal file
6
user/src/arch/mod.rs
Normal file
|
@ -0,0 +1,6 @@
|
|||
//! Architecture-specific stuff, mainly syscall methods.
|
||||
|
||||
#[macro_use]
|
||||
mod x86;
|
||||
|
||||
pub use x86::*;
|
62
user/src/arch/x86/mod.rs
Normal file
62
user/src/arch/x86/mod.rs
Normal file
|
@ -0,0 +1,62 @@
|
|||
//! x86 syscall method.
|
||||
|
||||
/// Syscall method.
|
||||
#[macro_export]
|
||||
macro_rules! syscall {
|
||||
($id: expr) => {
|
||||
unsafe {
|
||||
let out = 0u32;
|
||||
asm!(
|
||||
"int 0xA0",
|
||||
id = in("eax") const $id,
|
||||
out("eax") out
|
||||
)
|
||||
out
|
||||
}
|
||||
};
|
||||
($id: expr, $d0: expr) => {
|
||||
unsafe {
|
||||
let out = 0u32;
|
||||
let d0 = $d0;
|
||||
asm!(
|
||||
"int 0xA0",
|
||||
id = in("eax") const $id,
|
||||
d0 = in("ebx") $d0,
|
||||
out("eax") out
|
||||
)
|
||||
out
|
||||
}
|
||||
};
|
||||
($id: expr, $d0: expr, $d1: expr) => {
|
||||
unsafe {
|
||||
let out = 0u32;
|
||||
let d0 = $d0;
|
||||
let d1 = $d1;
|
||||
asm!(
|
||||
"int 0xA0",
|
||||
id = in("eax") const $id,
|
||||
d0 = in("ebx") $d0,
|
||||
d1 = in("ecx") $d1,
|
||||
out("eax") out
|
||||
)
|
||||
out
|
||||
}
|
||||
};
|
||||
($id: expr, $d0: expr, $d1: expr, $d2: expr) => {
|
||||
unsafe {
|
||||
let out = 0u32;
|
||||
let d0 = $d0;
|
||||
let d1 = $d1;
|
||||
let d2 = $d2;
|
||||
asm!(
|
||||
"int 0xA0",
|
||||
id = in("eax") const $id,
|
||||
d0 = in("ebx") $d0,
|
||||
d1 = in("ecx") $d1,
|
||||
d2 = in("edx") $d2,
|
||||
out("eax") out
|
||||
)
|
||||
out
|
||||
}
|
||||
}
|
||||
}
|
5
user/src/lib.rs
Normal file
5
user/src/lib.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
#[warn(missing_docs)]
|
||||
|
||||
mod arch;
|
||||
|
||||
use arch::*;
|
Loading…
Add table
Reference in a new issue