1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
// Copyright (c) 2017 Stefan Lankes, RWTH Aachen University
//                    Colin Finck, RWTH Aachen University
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

macro_rules! align_down {
	($value:expr, $alignment:expr) => {
		($value) & !($alignment - 1)
	};
}

macro_rules! align_up {
	($value:expr, $alignment:expr) => {
		align_down!($value + ($alignment - 1), $alignment)
	};
}

/// Print formatted text to our console.
///
/// From http://blog.phil-opp.com/rust-os/printing-to-screen.html, but tweaked
/// for HermitCore.
#[macro_export]
macro_rules! print {
	($($arg:tt)+) => ({
        $crate::_print(format_args!($($arg)*));
	});
}

/// Print formatted text to our console, followed by a newline.
#[macro_export]
macro_rules! println {
    () => (print!("\n"));
	($($arg:tt)+) => (print!("{}\n", format_args!($($arg)+)));
}

macro_rules! switch_to_kernel {
	() => {
		crate::arch::irq::disable();
		#[allow(unused)]
		unsafe {
			let user_stack_pointer;
			// Store the user stack pointer and switch to the kernel stack
			llvm_asm!(
				"mov %rsp, $0; mov $1, %rsp"
				: "=r"(user_stack_pointer) : "r"(get_kernel_stack()) :: "volatile"
			);
			core_scheduler().set_current_user_stack(user_stack_pointer);
		}
		crate::arch::irq::enable();
	}
}

macro_rules! switch_to_user {
	() => {
		use crate::arch::kernel::percore::*;

		crate::arch::irq::disable();
		let user_stack_pointer = core_scheduler().get_current_user_stack();
		#[allow(unused)]
		unsafe {
			// Switch to the user stack
			llvm_asm!("mov $0, %rsp" :: "r"(user_stack_pointer) :: "volatile");
		}
		crate::arch::irq::enable();
	}
}

macro_rules! kernel_function {
	($f:ident($($x:tt)*)) => {{
		use crate::arch::kernel::percore::*;

		#[allow(unused)]
		unsafe {
			crate::arch::irq::disable();
			let user_stack_pointer;
			// Store the user stack pointer and switch to the kernel stack
			llvm_asm!(
				"mov %rsp, $0; mov $1, %rsp"
				: "=r"(user_stack_pointer)
				: "r"(get_kernel_stack())
				:: "volatile"
			);
			core_scheduler().set_current_user_stack(user_stack_pointer);
			crate::arch::irq::enable();

			let ret = $f($($x)*);

			crate::arch::irq::disable();
			// Switch to the user stack
			llvm_asm!("mov $0, %rsp"
				:: "r"(core_scheduler().get_current_user_stack())
				:: "volatile"
			);
			crate::arch::irq::enable();

			ret
		}
	}};
}