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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
//! Hosted "hardware" abstraction layer implementation

use lazy_static::lazy_static;
use std::thread::{self, Thread};
use std::time::Duration;

use slos_hal::{SystemConsole, SystemCpu, SystemHardware, SystemKmainHooks};
use slos_helpers::UnsafeContainer;

pub mod console;
pub mod interrupts;

lazy_static! {
	/// Global instance of the [`HostedSystem`]
	pub static ref SYSTEM: UnsafeContainer<HostedSystem> = UnsafeContainer::new(Default::default());
}

/// Hosted "hardware" abstraction layer implementation
#[derive(Debug)]
pub struct HostedSystem {
	/// Whether to make kmain return in its next iteration
	pub return_next_iter: bool,

	/// Queue of pending interrupts
	pub pending_interrupts: Vec<interrupts::HostedInterrupt>,

	/// Whether interrupts are enabled
	pub interrupts_enabled: bool,

	/// Whether the hosted machine is halted until the next interrupt
	pub halted: bool,

	/// kmain [`std::thread::Thread`]
	pub kmain_thread: Option<Thread>,
}

impl HostedSystem {
	/// If halted, and current thread is kmain, park thread
	///
	/// This will also unhalt and unpark if `return_next_iter` has been set.
	/// Sleeps for ~50ms on each iteration as to reduce host CPU load.
	pub fn park_if_halted(&mut self) {
		while self.halted {
			if let Some(kmain_thread) = &self.kmain_thread {
				if thread::current().id() == kmain_thread.id() {
					thread::park()
				}
			}

			if self.return_next_iter {
				error!("return_next_iter set, unparking and unhalting");
				self.halted = false;
				if let Some(kmain_thread) = &self.kmain_thread {
					kmain_thread.unpark();
				}

				break;
			}

			thread::sleep(Duration::from_millis(50));
		}
	}
}

impl Default for HostedSystem {
	fn default() -> Self {
		Self {
			return_next_iter: false,
			pending_interrupts: Vec::new(),
			interrupts_enabled: false,
			halted: false,
			kmain_thread: None,
		}
	}
}

impl SystemCpu for HostedSystem {
	fn interrupts_disable(&mut self) {
		self.interrupts_enabled = false;
	}

	fn interrupts_enable(&mut self) {
		self.interrupts_enabled = true;
	}

	fn interrupts_are_enabled(&self) -> bool {
		self.interrupts_enabled
	}

	fn halt(&mut self) {
		self.halted = true;
		self.park_if_halted();
	}
}

impl SystemKmainHooks for HostedSystem {
	fn hook_kmain_loop_head(&mut self) {
		self.park_if_halted();
	}

	fn hook_kmain_loop_inner_part(&mut self) {
		self.park_if_halted();
	}
}

impl SystemHardware for HostedSystem {
	fn system_name(&self) -> &'static str {
		env!("CARGO_PKG_NAME")
	}

	fn console(&mut self) -> &'static mut dyn SystemConsole {
		console::CONSOLE.get()
	}

	fn has_requested_return(&self) -> bool {
		self.return_next_iter
	}

	fn current_cpu(&mut self) -> &'static mut dyn SystemCpu {
		SYSTEM.get()
	}

	fn virtualization(&self) -> Option<(&'static str, ())> {
		Some((env!("CARGO_PKG_NAME"), ()))
	}
}