ableos update
This commit is contained in:
parent
e53d7896a7
commit
fb0dcc786d
94
Cargo.lock
generated
94
Cargo.lock
generated
|
@ -2,6 +2,15 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "able_graphics_library"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "git+https://git.ablecorp.us/ableos/ableos_userland#70a65fc10d2caafe370be90eb0e31aa7d9347218"
|
||||||
|
dependencies = [
|
||||||
|
"embedded-graphics",
|
||||||
|
"versioning",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ahash"
|
name = "ahash"
|
||||||
version = "0.7.6"
|
version = "0.7.6"
|
||||||
|
@ -65,6 +74,12 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "az"
|
||||||
|
version = "1.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bit"
|
name = "bit"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
@ -125,7 +140,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clparse"
|
name = "clparse"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://git.ablecorp.us/ableos/ableos_userland#8fa6c705f23ae310e3c4395a61823449ed5a1d02"
|
source = "git+https://git.ablecorp.us/ableos/ableos_userland#70a65fc10d2caafe370be90eb0e31aa7d9347218"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hashbrown 0.13.2",
|
"hashbrown 0.13.2",
|
||||||
"log",
|
"log",
|
||||||
|
@ -228,6 +243,29 @@ version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
|
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "embedded-graphics"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "750082c65094fbcc4baf9ba31583ce9a8bb7f52cadfb96f6164b1bc7f922f32b"
|
||||||
|
dependencies = [
|
||||||
|
"az",
|
||||||
|
"byteorder",
|
||||||
|
"embedded-graphics-core",
|
||||||
|
"float-cmp",
|
||||||
|
"micromath",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "embedded-graphics-core"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b8b1239db5f3eeb7e33e35bd10bd014e7b2537b17e071f726a09351431337cfa"
|
||||||
|
dependencies = [
|
||||||
|
"az",
|
||||||
|
"byteorder",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "env_logger"
|
name = "env_logger"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
|
@ -294,6 +332,15 @@ dependencies = [
|
||||||
"log",
|
"log",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "float-cmp"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e1267f4ac4f343772758f7b1bdcbe767c218bbab93bb432acbf5162bbf85a6c4"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.2.8"
|
version = "0.2.8"
|
||||||
|
@ -416,9 +463,11 @@ dependencies = [
|
||||||
name = "kernel"
|
name = "kernel"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"able_graphics_library",
|
||||||
"clparse",
|
"clparse",
|
||||||
"crossbeam-queue",
|
"crossbeam-queue",
|
||||||
"derive_more",
|
"derive_more",
|
||||||
|
"embedded-graphics",
|
||||||
"error-stack 0.3.1",
|
"error-stack 0.3.1",
|
||||||
"hashbrown 0.13.2",
|
"hashbrown 0.13.2",
|
||||||
"limine",
|
"limine",
|
||||||
|
@ -429,6 +478,7 @@ dependencies = [
|
||||||
"spin",
|
"spin",
|
||||||
"uart_16550",
|
"uart_16550",
|
||||||
"versioning",
|
"versioning",
|
||||||
|
"virtio-drivers",
|
||||||
"wasmi",
|
"wasmi",
|
||||||
"x2apic",
|
"x2apic",
|
||||||
"x86_64",
|
"x86_64",
|
||||||
|
@ -492,6 +542,12 @@ version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "micromath"
|
||||||
|
version = "1.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bc4010833aea396656c2f91ee704d51a6f1329ec2ab56ffd00bfd56f7481ea94"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-integer"
|
name = "num-integer"
|
||||||
version = "0.1.45"
|
version = "0.1.45"
|
||||||
|
@ -791,11 +847,22 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "versioning"
|
name = "versioning"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
source = "git+https://git.ablecorp.us/ableos/ableos_userland#8fa6c705f23ae310e3c4395a61823449ed5a1d02"
|
source = "git+https://git.ablecorp.us/ableos/ableos_userland#70a65fc10d2caafe370be90eb0e31aa7d9347218"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "virtio-drivers"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42299957c6f61af586fe3eae398c16ec07f33a02579fa1d41ae96156ce437029"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"log",
|
||||||
|
"zerocopy",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "volatile"
|
name = "volatile"
|
||||||
version = "0.4.6"
|
version = "0.4.6"
|
||||||
|
@ -1108,7 +1175,28 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "xml"
|
name = "xml"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://git.ablecorp.us/ableos/ableos_userland#8fa6c705f23ae310e3c4395a61823449ed5a1d02"
|
source = "git+https://git.ablecorp.us/ableos/ableos_userland#70a65fc10d2caafe370be90eb0e31aa7d9347218"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "332f188cc1bcf1fe1064b8c58d150f497e697f49774aa846f2dc949d9a25f236"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"zerocopy-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6505e6815af7de1746a08f69c69606bb45695a17149517680f3b2149713b19a3"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
|
@ -5,6 +5,11 @@ version = "0.2.0"
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|
||||||
|
|
||||||
|
embedded-graphics = "0.7.1"
|
||||||
|
|
||||||
|
|
||||||
error-stack = { version = "0.3", default-features = false }
|
error-stack = { version = "0.3", default-features = false }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
spin = "0.9"
|
spin = "0.9"
|
||||||
|
@ -14,6 +19,7 @@ xml = { git = "https://git.ablecorp.us/ableos/ableos_userland" }
|
||||||
|
|
||||||
clparse = { git = "https://git.ablecorp.us/ableos/ableos_userland", default-features = false }
|
clparse = { git = "https://git.ablecorp.us/ableos/ableos_userland", default-features = false }
|
||||||
versioning = { git = "https://git.ablecorp.us/ableos/ableos_userland" }
|
versioning = { git = "https://git.ablecorp.us/ableos/ableos_userland" }
|
||||||
|
able_graphics_library = { git = "https://git.ablecorp.us/ableos/ableos_userland" }
|
||||||
wasmi = { version = "0.29.0", default-features = false }
|
wasmi = { version = "0.29.0", default-features = false }
|
||||||
hashbrown = "*"
|
hashbrown = "*"
|
||||||
|
|
||||||
|
@ -43,6 +49,7 @@ features = [
|
||||||
limine = { version = "0.1", git = "https://github.com/limine-bootloader/limine-rs" }
|
limine = { version = "0.1", git = "https://github.com/limine-bootloader/limine-rs" }
|
||||||
x86_64 = "0.14"
|
x86_64 = "0.14"
|
||||||
x2apic = "0.4"
|
x2apic = "0.4"
|
||||||
|
virtio-drivers = "0.4.0"
|
||||||
# rdrand = "*"
|
# rdrand = "*"
|
||||||
rdrand = { version = "0.8", default-features = false }
|
rdrand = { version = "0.8", default-features = false }
|
||||||
|
|
||||||
|
|
924
kernel/src/arch/x86_64/cpuid.rs
Normal file
924
kernel/src/arch/x86_64/cpuid.rs
Normal file
|
@ -0,0 +1,924 @@
|
||||||
|
use core::{arch::asm, fmt, ops::Deref, slice, str};
|
||||||
|
|
||||||
|
#[repr(u32)]
|
||||||
|
pub enum RequestType {
|
||||||
|
BasicInformation = 0x00000000,
|
||||||
|
VersionInformation = 0x00000001,
|
||||||
|
ThermalPowerManagementInformation = 0x00000006,
|
||||||
|
StructuredExtendedInformation = 0x00000007,
|
||||||
|
ExtendedFunctionInformation = 0x80000000,
|
||||||
|
ExtendedProcessorSignature = 0x80000001,
|
||||||
|
BrandString1 = 0x80000002,
|
||||||
|
BrandString2 = 0x80000003,
|
||||||
|
BrandString3 = 0x80000004,
|
||||||
|
// reserved = 0x80000005,
|
||||||
|
CacheLine = 0x80000006,
|
||||||
|
TimeStampCounter = 0x80000007,
|
||||||
|
PhysicalAddressSize = 0x80000008,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cpuid(code: RequestType) -> (u32, u32, u32, u32) {
|
||||||
|
let eax;
|
||||||
|
let ebx;
|
||||||
|
let ecx;
|
||||||
|
let edx;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
asm!(
|
||||||
|
"movq %rbx, {0:r}",
|
||||||
|
"cpuid",
|
||||||
|
"xchgq %rbx, {0:r}",
|
||||||
|
lateout(reg) ebx,
|
||||||
|
inlateout("eax") code as u32 => eax,
|
||||||
|
inlateout("ecx") 0 => ecx,
|
||||||
|
lateout("edx") edx,
|
||||||
|
options(nostack, preserves_flags, att_syntax),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
(eax, ebx, ecx, edx)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The main entrypoint to the CPU information
|
||||||
|
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
|
||||||
|
pub fn master() -> Option<Master> {
|
||||||
|
Some(Master::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
// This matches the Intel Architecture guide, with bits 31 -> 0.
|
||||||
|
// The bit positions are inclusive.
|
||||||
|
fn bits_of(val: u32, start_bit: u8, end_bit: u8) -> u32 {
|
||||||
|
let mut silly = 0;
|
||||||
|
|
||||||
|
for _ in start_bit..end_bit + 1 {
|
||||||
|
silly <<= 1;
|
||||||
|
silly |= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
(val >> start_bit) & silly
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_bytes(v: &u32) -> &[u8] {
|
||||||
|
let start = v as *const u32 as *const u8;
|
||||||
|
// TODO: use u32::BYTES
|
||||||
|
unsafe { slice::from_raw_parts(start, 4) }
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! bit {
|
||||||
|
($reg:ident, {$($idx:expr => $name:ident),+}) => {
|
||||||
|
$(pub fn $name(self) -> bool {
|
||||||
|
((self.$reg >> $idx) & 1) != 0
|
||||||
|
})+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! dump {
|
||||||
|
($me:expr, $f: expr, $sname:expr, {$($name:ident),+}) => {
|
||||||
|
$f.debug_struct($sname)
|
||||||
|
$(.field(stringify!($name), &$me.$name()))+
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! delegate_flag {
|
||||||
|
($item:ident, {$($name:ident),+}) => {
|
||||||
|
$(pub fn $name(&self) -> bool {
|
||||||
|
self.$item.map(|i| i.$name()).unwrap_or(false)
|
||||||
|
})+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! master_attr_reader {
|
||||||
|
($name:ident, $kind:ty) => {
|
||||||
|
pub fn $name(&self) -> Option<&$kind> {
|
||||||
|
self.$name.as_ref()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct VersionInformation {
|
||||||
|
eax: u32,
|
||||||
|
ebx: u32,
|
||||||
|
ecx: u32,
|
||||||
|
edx: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VersionInformation {
|
||||||
|
pub fn new() -> VersionInformation {
|
||||||
|
let (a, b, c, d) = cpuid(RequestType::VersionInformation);
|
||||||
|
VersionInformation {
|
||||||
|
eax: a,
|
||||||
|
ebx: b,
|
||||||
|
ecx: c,
|
||||||
|
edx: d,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn family_id(self) -> u32 {
|
||||||
|
let family_id = bits_of(self.eax, 8, 11);
|
||||||
|
let extended_family_id = bits_of(self.eax, 20, 27);
|
||||||
|
|
||||||
|
if family_id != 0x0F {
|
||||||
|
family_id
|
||||||
|
} else {
|
||||||
|
extended_family_id + family_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn model_id(self) -> u32 {
|
||||||
|
let family_id = self.family_id();
|
||||||
|
let model_id = bits_of(self.eax, 4, 7);
|
||||||
|
let extended_model_id = bits_of(self.eax, 16, 19);
|
||||||
|
|
||||||
|
if family_id == 0x06 || family_id == 0x0F {
|
||||||
|
(extended_model_id << 4) + model_id
|
||||||
|
} else {
|
||||||
|
model_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stepping(self) -> u32 {
|
||||||
|
bits_of(self.eax, 0, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn processor_signature(self) -> u32 {
|
||||||
|
self.eax
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn brand_string(self) -> Option<&'static str> {
|
||||||
|
let brand_index = bits_of(self.ebx, 0, 7);
|
||||||
|
let processor_signature = self.processor_signature();
|
||||||
|
|
||||||
|
match brand_index {
|
||||||
|
0x00 => None,
|
||||||
|
0x01 => Some("Intel(R) Celeron(R)"),
|
||||||
|
0x02 => Some("Intel(R) Pentium(R) III"),
|
||||||
|
0x03 => {
|
||||||
|
if processor_signature == 0x06B1 {
|
||||||
|
Some("Intel(R) Celeron(R)")
|
||||||
|
} else {
|
||||||
|
Some("Intel(R) Pentium(R) III Xeon(R)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
0x04 => Some("Intel(R) Pentium(R) III"),
|
||||||
|
0x06 => Some("Mobile Intel(R) Pentium(R) III-M"),
|
||||||
|
0x07 => Some("Mobile Intel(R) Celeron(R)"),
|
||||||
|
0x08 => Some("Intel(R) Pentium(R) 4"),
|
||||||
|
0x09 => Some("Intel(R) Pentium(R) 4"),
|
||||||
|
0x0A => Some("Intel(R) Celeron(R)"),
|
||||||
|
0x0B => {
|
||||||
|
if processor_signature == 0x0F13 {
|
||||||
|
Some("Intel(R) Xeon(R) MP")
|
||||||
|
} else {
|
||||||
|
Some("Intel(R) Xeon(R)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
0x0C => Some("Intel(R) Xeon(R) MP"),
|
||||||
|
0x0E => {
|
||||||
|
if processor_signature == 0x0F13 {
|
||||||
|
Some("Intel(R) Xeon(R)")
|
||||||
|
} else {
|
||||||
|
Some("Mobile Intel(R) Pentium(R) 4-M")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
0x0F => Some("Mobile Intel(R) Celeron(R)"),
|
||||||
|
0x11 => Some("Mobile Genuine Intel(R)"),
|
||||||
|
0x12 => Some("Intel(R) Celeron(R) M"),
|
||||||
|
0x13 => Some("Mobile Intel(R) Celeron(R)"),
|
||||||
|
0x14 => Some("Intel(R) Celeron(R)"),
|
||||||
|
0x15 => Some("Mobile Genuine Intel(R)"),
|
||||||
|
0x16 => Some("Intel(R) Pentium(R) M"),
|
||||||
|
0x17 => Some("Mobile Intel(R) Celeron(R)"),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bit!(ecx, {
|
||||||
|
0 => sse3,
|
||||||
|
1 => pclmulqdq,
|
||||||
|
2 => dtes64,
|
||||||
|
3 => monitor,
|
||||||
|
4 => ds_cpl,
|
||||||
|
5 => vmx,
|
||||||
|
6 => smx,
|
||||||
|
7 => eist,
|
||||||
|
8 => tm2,
|
||||||
|
9 => ssse3,
|
||||||
|
10 => cnxt_id,
|
||||||
|
11 => sdbg,
|
||||||
|
12 => fma,
|
||||||
|
13 => cmpxchg16b,
|
||||||
|
14 => xtpr_update_control,
|
||||||
|
15 => pdcm,
|
||||||
|
// 16 - reserved
|
||||||
|
17 => pcid,
|
||||||
|
18 => dca,
|
||||||
|
19 => sse4_1,
|
||||||
|
20 => sse4_2,
|
||||||
|
21 => x2apic,
|
||||||
|
22 => movbe,
|
||||||
|
23 => popcnt,
|
||||||
|
24 => tsc_deadline,
|
||||||
|
25 => aesni,
|
||||||
|
26 => xsave,
|
||||||
|
27 => osxsave,
|
||||||
|
28 => avx,
|
||||||
|
29 => f16c,
|
||||||
|
30 => rdrand
|
||||||
|
// 31 - unused
|
||||||
|
});
|
||||||
|
|
||||||
|
bit!(edx, {
|
||||||
|
0 => fpu,
|
||||||
|
1 => vme,
|
||||||
|
2 => de,
|
||||||
|
3 => pse,
|
||||||
|
4 => tsc,
|
||||||
|
5 => msr,
|
||||||
|
6 => pae,
|
||||||
|
7 => mce,
|
||||||
|
8 => cx8,
|
||||||
|
9 => apic,
|
||||||
|
// 10 - reserved
|
||||||
|
11 => sep,
|
||||||
|
12 => mtrr,
|
||||||
|
13 => pge,
|
||||||
|
14 => mca,
|
||||||
|
15 => cmov,
|
||||||
|
16 => pat,
|
||||||
|
17 => pse_36,
|
||||||
|
18 => psn,
|
||||||
|
19 => clfsh,
|
||||||
|
// 20 - reserved
|
||||||
|
21 => ds,
|
||||||
|
22 => acpi,
|
||||||
|
23 => mmx,
|
||||||
|
24 => fxsr,
|
||||||
|
25 => sse,
|
||||||
|
26 => sse2,
|
||||||
|
27 => ss,
|
||||||
|
28 => htt,
|
||||||
|
29 => tm,
|
||||||
|
// 30 -reserved
|
||||||
|
31 => pbe
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for VersionInformation {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
dump!(self, f, "VersionInformation", {
|
||||||
|
family_id,
|
||||||
|
model_id,
|
||||||
|
stepping,
|
||||||
|
brand_string,
|
||||||
|
sse3,
|
||||||
|
pclmulqdq,
|
||||||
|
dtes64,
|
||||||
|
monitor,
|
||||||
|
ds_cpl,
|
||||||
|
vmx,
|
||||||
|
smx,
|
||||||
|
eist,
|
||||||
|
tm2,
|
||||||
|
ssse3,
|
||||||
|
cnxt_id,
|
||||||
|
sdbg,
|
||||||
|
fma,
|
||||||
|
cmpxchg16b,
|
||||||
|
xtpr_update_control,
|
||||||
|
pdcm,
|
||||||
|
pcid,
|
||||||
|
dca,
|
||||||
|
sse4_1,
|
||||||
|
sse4_2,
|
||||||
|
x2apic,
|
||||||
|
movbe,
|
||||||
|
popcnt,
|
||||||
|
tsc_deadline,
|
||||||
|
aesni,
|
||||||
|
xsave,
|
||||||
|
osxsave,
|
||||||
|
avx,
|
||||||
|
f16c,
|
||||||
|
rdrand,
|
||||||
|
fpu,
|
||||||
|
vme,
|
||||||
|
de,
|
||||||
|
pse,
|
||||||
|
tsc,
|
||||||
|
msr,
|
||||||
|
pae,
|
||||||
|
mce,
|
||||||
|
cx8,
|
||||||
|
apic,
|
||||||
|
sep,
|
||||||
|
mtrr,
|
||||||
|
pge,
|
||||||
|
mca,
|
||||||
|
cmov,
|
||||||
|
pat,
|
||||||
|
pse_36,
|
||||||
|
psn,
|
||||||
|
clfsh,
|
||||||
|
ds,
|
||||||
|
acpi,
|
||||||
|
mmx,
|
||||||
|
fxsr,
|
||||||
|
sse,
|
||||||
|
sse2,
|
||||||
|
ss,
|
||||||
|
htt,
|
||||||
|
tm,
|
||||||
|
pbe
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct ExtendedProcessorSignature {
|
||||||
|
ecx: u32,
|
||||||
|
edx: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExtendedProcessorSignature {
|
||||||
|
fn new() -> ExtendedProcessorSignature {
|
||||||
|
let (_, _, c, d) = cpuid(RequestType::ExtendedProcessorSignature);
|
||||||
|
ExtendedProcessorSignature { ecx: c, edx: d }
|
||||||
|
}
|
||||||
|
|
||||||
|
bit!(ecx, {
|
||||||
|
0 => lahf_sahf_in_64_bit,
|
||||||
|
// 1-4 reserved
|
||||||
|
5 => lzcnt,
|
||||||
|
// 6-7 reserved
|
||||||
|
8 => prefetchw
|
||||||
|
// 9-31 reserved
|
||||||
|
});
|
||||||
|
|
||||||
|
bit!(edx, {
|
||||||
|
// 0-10 reserved
|
||||||
|
11 => syscall_sysret_in_64_bit,
|
||||||
|
// 12-19 reserved
|
||||||
|
20 => execute_disable,
|
||||||
|
// 21-25 reserved
|
||||||
|
26 => gigabyte_pages,
|
||||||
|
27 => rdtscp_and_ia32_tsc_aux,
|
||||||
|
// 28 reserved
|
||||||
|
29 => intel_64_bit_architecture
|
||||||
|
// 30-31 reserved
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for ExtendedProcessorSignature {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
dump!(self, f, "ThermalPowerManagementInformation", {
|
||||||
|
lahf_sahf_in_64_bit,
|
||||||
|
lzcnt,
|
||||||
|
prefetchw,
|
||||||
|
syscall_sysret_in_64_bit,
|
||||||
|
execute_disable,
|
||||||
|
gigabyte_pages,
|
||||||
|
rdtscp_and_ia32_tsc_aux,
|
||||||
|
intel_64_bit_architecture
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3 calls of 4 registers of 4 bytes
|
||||||
|
const BRAND_STRING_LENGTH: usize = 3 * 4 * 4;
|
||||||
|
|
||||||
|
pub struct BrandString {
|
||||||
|
bytes: [u8; BRAND_STRING_LENGTH],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BrandString {
|
||||||
|
fn new() -> BrandString {
|
||||||
|
fn append_bytes(a: RequestType, bytes: &mut [u8]) {
|
||||||
|
let (a, b, c, d) = cpuid(a);
|
||||||
|
|
||||||
|
let result_bytes = as_bytes(&a)
|
||||||
|
.iter()
|
||||||
|
.chain(as_bytes(&b).iter())
|
||||||
|
.chain(as_bytes(&c).iter())
|
||||||
|
.chain(as_bytes(&d).iter());
|
||||||
|
|
||||||
|
for (output, input) in bytes.iter_mut().zip(result_bytes) {
|
||||||
|
*output = *input
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut brand_string = BrandString {
|
||||||
|
bytes: [0; BRAND_STRING_LENGTH],
|
||||||
|
};
|
||||||
|
append_bytes(RequestType::BrandString1, &mut brand_string.bytes[0..]);
|
||||||
|
append_bytes(RequestType::BrandString2, &mut brand_string.bytes[16..]);
|
||||||
|
append_bytes(RequestType::BrandString3, &mut brand_string.bytes[32..]);
|
||||||
|
brand_string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for BrandString {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
let mut bytes = [0; BRAND_STRING_LENGTH];
|
||||||
|
for (d, s) in bytes.iter_mut().zip(self.bytes.iter()) {
|
||||||
|
*d = *s;
|
||||||
|
}
|
||||||
|
BrandString { bytes: bytes }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for BrandString {
|
||||||
|
type Target = str;
|
||||||
|
|
||||||
|
fn deref(&self) -> &str {
|
||||||
|
let nul_terminator = self.bytes.iter().position(|&b| b == 0).unwrap_or(0);
|
||||||
|
let usable_bytes = &self.bytes[..nul_terminator];
|
||||||
|
unsafe { str::from_utf8_unchecked(usable_bytes) }.trim()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for BrandString {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
(self as &str).fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for BrandString {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
(self as &str).fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct ThermalPowerManagementInformation {
|
||||||
|
eax: u32,
|
||||||
|
ebx: u32,
|
||||||
|
ecx: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ThermalPowerManagementInformation {
|
||||||
|
fn new() -> ThermalPowerManagementInformation {
|
||||||
|
let (a, b, c, _) = cpuid(RequestType::ThermalPowerManagementInformation);
|
||||||
|
ThermalPowerManagementInformation {
|
||||||
|
eax: a,
|
||||||
|
ebx: b,
|
||||||
|
ecx: c,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bit!(eax, {
|
||||||
|
0 => digital_temperature_sensor,
|
||||||
|
1 => intel_turbo_boost,
|
||||||
|
2 => arat,
|
||||||
|
// 3 - reserved
|
||||||
|
4 => pln,
|
||||||
|
5 => ecmd,
|
||||||
|
6 => ptm,
|
||||||
|
7 => hwp,
|
||||||
|
8 => hwp_notification,
|
||||||
|
9 => hwp_activity_window,
|
||||||
|
10 => hwp_energy_performance_preference,
|
||||||
|
// 12 - reserved
|
||||||
|
13 => hdc
|
||||||
|
});
|
||||||
|
|
||||||
|
pub fn number_of_interrupt_thresholds(self) -> u32 {
|
||||||
|
bits_of(self.ebx, 0, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
bit!(ecx, {
|
||||||
|
0 => hardware_coordination_feedback,
|
||||||
|
// 1-2 - reserved
|
||||||
|
3 => performance_energy_bias
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for ThermalPowerManagementInformation {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
dump!(self, f, "ThermalPowerManagementInformation", {
|
||||||
|
digital_temperature_sensor,
|
||||||
|
intel_turbo_boost,
|
||||||
|
arat,
|
||||||
|
pln,
|
||||||
|
ecmd,
|
||||||
|
ptm,
|
||||||
|
hwp,
|
||||||
|
hwp_notification,
|
||||||
|
hwp_activity_window,
|
||||||
|
hwp_energy_performance_preference,
|
||||||
|
hdc,
|
||||||
|
|
||||||
|
number_of_interrupt_thresholds,
|
||||||
|
|
||||||
|
hardware_coordination_feedback,
|
||||||
|
performance_energy_bias
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct StructuredExtendedInformation {
|
||||||
|
ebx: u32,
|
||||||
|
ecx: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StructuredExtendedInformation {
|
||||||
|
fn new() -> StructuredExtendedInformation {
|
||||||
|
let (_, b, c, _) = cpuid(RequestType::StructuredExtendedInformation);
|
||||||
|
StructuredExtendedInformation { ebx: b, ecx: c }
|
||||||
|
}
|
||||||
|
|
||||||
|
bit!(ebx, {
|
||||||
|
0 => fsgsbase,
|
||||||
|
1 => ia32_tsc_adjust_msr,
|
||||||
|
// 2 - reserved
|
||||||
|
3 => bmi1,
|
||||||
|
4 => hle,
|
||||||
|
5 => avx2,
|
||||||
|
// 6 - reserved
|
||||||
|
7 => smep,
|
||||||
|
8 => bmi2,
|
||||||
|
9 => enhanced_rep_movsb_stosb,
|
||||||
|
10 => invpcid,
|
||||||
|
11 => rtm,
|
||||||
|
12 => pqm,
|
||||||
|
13 => deprecates_fpu_cs_ds,
|
||||||
|
// 14 - reserved
|
||||||
|
15 => pqe,
|
||||||
|
// 16-17 - reserved
|
||||||
|
18 => rdseed,
|
||||||
|
19 => adx,
|
||||||
|
20 => smap,
|
||||||
|
// 21-24 - reserved
|
||||||
|
25 => intel_processor_trace
|
||||||
|
// 26-31 - reserved
|
||||||
|
});
|
||||||
|
|
||||||
|
bit!(ecx, {
|
||||||
|
0 => prefetchwt1
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for StructuredExtendedInformation {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
dump!(self, f, "StructuredExtendedInformation", {
|
||||||
|
fsgsbase,
|
||||||
|
ia32_tsc_adjust_msr,
|
||||||
|
bmi1,
|
||||||
|
hle,
|
||||||
|
avx2,
|
||||||
|
smep,
|
||||||
|
bmi2,
|
||||||
|
enhanced_rep_movsb_stosb,
|
||||||
|
invpcid,
|
||||||
|
rtm,
|
||||||
|
pqm,
|
||||||
|
deprecates_fpu_cs_ds,
|
||||||
|
pqe,
|
||||||
|
rdseed,
|
||||||
|
adx,
|
||||||
|
smap,
|
||||||
|
intel_processor_trace,
|
||||||
|
prefetchwt1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub enum CacheLineAssociativity {
|
||||||
|
Disabled,
|
||||||
|
DirectMapped,
|
||||||
|
TwoWay,
|
||||||
|
FourWay,
|
||||||
|
EightWay,
|
||||||
|
SixteenWay,
|
||||||
|
Full,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct CacheLine(u32);
|
||||||
|
|
||||||
|
impl CacheLine {
|
||||||
|
fn new() -> CacheLine {
|
||||||
|
let (_, _, c, _) = cpuid(RequestType::CacheLine);
|
||||||
|
CacheLine(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cache_line_size(self) -> u32 {
|
||||||
|
bits_of(self.0, 0, 7)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn l2_associativity(self) -> Option<CacheLineAssociativity> {
|
||||||
|
match bits_of(self.0, 12, 15) {
|
||||||
|
0x00 => Some(CacheLineAssociativity::Disabled),
|
||||||
|
0x01 => Some(CacheLineAssociativity::DirectMapped),
|
||||||
|
0x02 => Some(CacheLineAssociativity::TwoWay),
|
||||||
|
0x04 => Some(CacheLineAssociativity::FourWay),
|
||||||
|
0x06 => Some(CacheLineAssociativity::EightWay),
|
||||||
|
0x08 => Some(CacheLineAssociativity::SixteenWay),
|
||||||
|
0x0F => Some(CacheLineAssociativity::Full),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cache_size(self) -> u32 {
|
||||||
|
bits_of(self.0, 16, 31)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for CacheLine {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
dump!(self, f, "CacheLine", {
|
||||||
|
cache_line_size,
|
||||||
|
l2_associativity,
|
||||||
|
cache_size
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct TimeStampCounter {
|
||||||
|
edx: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TimeStampCounter {
|
||||||
|
fn new() -> TimeStampCounter {
|
||||||
|
let (_, _, _, d) = cpuid(RequestType::TimeStampCounter);
|
||||||
|
TimeStampCounter { edx: d }
|
||||||
|
}
|
||||||
|
|
||||||
|
bit!(edx, {
|
||||||
|
// 0-7 - reserved
|
||||||
|
8 => invariant_tsc
|
||||||
|
// 9-31 - reserved
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for TimeStampCounter {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
dump!(self, f, "TimeStampCounter", { invariant_tsc })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct PhysicalAddressSize(u32);
|
||||||
|
|
||||||
|
impl PhysicalAddressSize {
|
||||||
|
fn new() -> PhysicalAddressSize {
|
||||||
|
let (a, _, _, _) = cpuid(RequestType::PhysicalAddressSize);
|
||||||
|
PhysicalAddressSize(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn physical_address_bits(self) -> u32 {
|
||||||
|
bits_of(self.0, 0, 7)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn linear_address_bits(self) -> u32 {
|
||||||
|
bits_of(self.0, 8, 15)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for PhysicalAddressSize {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
dump!(self, f, "PhysicalAddressSize", {
|
||||||
|
physical_address_bits,
|
||||||
|
linear_address_bits
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Information about the currently running processor
|
||||||
|
///
|
||||||
|
/// Feature flags match the feature mnemonic listed in the Intel
|
||||||
|
/// Instruction Set Reference. This struct provides a facade for flags
|
||||||
|
/// so the consumer doesn't need to worry about which particular CPUID
|
||||||
|
/// leaf provides the information.
|
||||||
|
///
|
||||||
|
/// For data beyond simple feature flags, you will need to retrieve
|
||||||
|
/// the nested struct and call the appropriate methods on it.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Master {
|
||||||
|
// TODO: Rename struct
|
||||||
|
version_information: Option<VersionInformation>,
|
||||||
|
thermal_power_management_information: Option<ThermalPowerManagementInformation>,
|
||||||
|
structured_extended_information: Option<StructuredExtendedInformation>,
|
||||||
|
extended_processor_signature: Option<ExtendedProcessorSignature>,
|
||||||
|
brand_string: Option<BrandString>,
|
||||||
|
cache_line: Option<CacheLine>,
|
||||||
|
time_stamp_counter: Option<TimeStampCounter>,
|
||||||
|
physical_address_size: Option<PhysicalAddressSize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Master {
|
||||||
|
pub fn new() -> Master {
|
||||||
|
fn when_supported<F, T>(max: u32, kind: RequestType, then: F) -> Option<T>
|
||||||
|
where
|
||||||
|
F: FnOnce() -> T,
|
||||||
|
{
|
||||||
|
if max >= kind as u32 {
|
||||||
|
Some(then())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let (max_value, _, _, _) = cpuid(RequestType::BasicInformation);
|
||||||
|
|
||||||
|
let vi = when_supported(max_value, RequestType::VersionInformation, || {
|
||||||
|
VersionInformation::new()
|
||||||
|
});
|
||||||
|
let tpm = when_supported(
|
||||||
|
max_value,
|
||||||
|
RequestType::ThermalPowerManagementInformation,
|
||||||
|
|| ThermalPowerManagementInformation::new(),
|
||||||
|
);
|
||||||
|
let sei = when_supported(
|
||||||
|
max_value,
|
||||||
|
RequestType::StructuredExtendedInformation,
|
||||||
|
|| StructuredExtendedInformation::new(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Extended information
|
||||||
|
|
||||||
|
let (max_value, _, _, _) = cpuid(RequestType::ExtendedFunctionInformation);
|
||||||
|
|
||||||
|
let eps = when_supported(max_value, RequestType::ExtendedProcessorSignature, || {
|
||||||
|
ExtendedProcessorSignature::new()
|
||||||
|
});
|
||||||
|
let brand_string =
|
||||||
|
when_supported(max_value, RequestType::BrandString3, || BrandString::new());
|
||||||
|
let cache_line = when_supported(max_value, RequestType::CacheLine, || CacheLine::new());
|
||||||
|
let tsc = when_supported(max_value, RequestType::TimeStampCounter, || {
|
||||||
|
TimeStampCounter::new()
|
||||||
|
});
|
||||||
|
let pas = when_supported(max_value, RequestType::PhysicalAddressSize, || {
|
||||||
|
PhysicalAddressSize::new()
|
||||||
|
});
|
||||||
|
|
||||||
|
Master {
|
||||||
|
version_information: vi,
|
||||||
|
thermal_power_management_information: tpm,
|
||||||
|
structured_extended_information: sei,
|
||||||
|
extended_processor_signature: eps,
|
||||||
|
brand_string: brand_string,
|
||||||
|
cache_line: cache_line,
|
||||||
|
time_stamp_counter: tsc,
|
||||||
|
physical_address_size: pas,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
master_attr_reader!(version_information, VersionInformation);
|
||||||
|
master_attr_reader!(
|
||||||
|
thermal_power_management_information,
|
||||||
|
ThermalPowerManagementInformation
|
||||||
|
);
|
||||||
|
master_attr_reader!(
|
||||||
|
structured_extended_information,
|
||||||
|
StructuredExtendedInformation
|
||||||
|
);
|
||||||
|
master_attr_reader!(extended_processor_signature, ExtendedProcessorSignature);
|
||||||
|
master_attr_reader!(cache_line, CacheLine);
|
||||||
|
master_attr_reader!(time_stamp_counter, TimeStampCounter);
|
||||||
|
master_attr_reader!(physical_address_size, PhysicalAddressSize);
|
||||||
|
|
||||||
|
pub fn brand_string(&self) -> Option<&str> {
|
||||||
|
self.brand_string
|
||||||
|
.as_ref()
|
||||||
|
.map(|bs| bs as &str)
|
||||||
|
.or(self.version_information.and_then(|vi| vi.brand_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate_flag!(version_information, {
|
||||||
|
sse3,
|
||||||
|
pclmulqdq,
|
||||||
|
dtes64,
|
||||||
|
monitor,
|
||||||
|
ds_cpl,
|
||||||
|
vmx,
|
||||||
|
smx,
|
||||||
|
eist,
|
||||||
|
tm2,
|
||||||
|
ssse3,
|
||||||
|
cnxt_id,
|
||||||
|
sdbg,
|
||||||
|
fma,
|
||||||
|
cmpxchg16b,
|
||||||
|
xtpr_update_control,
|
||||||
|
pdcm,
|
||||||
|
pcid,
|
||||||
|
dca,
|
||||||
|
sse4_1,
|
||||||
|
sse4_2,
|
||||||
|
x2apic,
|
||||||
|
movbe,
|
||||||
|
popcnt,
|
||||||
|
tsc_deadline,
|
||||||
|
aesni,
|
||||||
|
xsave,
|
||||||
|
osxsave,
|
||||||
|
avx,
|
||||||
|
f16c,
|
||||||
|
rdrand,
|
||||||
|
fpu,
|
||||||
|
vme,
|
||||||
|
de,
|
||||||
|
pse,
|
||||||
|
tsc,
|
||||||
|
msr,
|
||||||
|
pae,
|
||||||
|
mce,
|
||||||
|
cx8,
|
||||||
|
apic,
|
||||||
|
sep,
|
||||||
|
mtrr,
|
||||||
|
pge,
|
||||||
|
mca,
|
||||||
|
cmov,
|
||||||
|
pat,
|
||||||
|
pse_36,
|
||||||
|
psn,
|
||||||
|
clfsh,
|
||||||
|
ds,
|
||||||
|
acpi,
|
||||||
|
mmx,
|
||||||
|
fxsr,
|
||||||
|
sse,
|
||||||
|
sse2,
|
||||||
|
ss,
|
||||||
|
htt,
|
||||||
|
tm,
|
||||||
|
pbe
|
||||||
|
});
|
||||||
|
|
||||||
|
delegate_flag!(thermal_power_management_information, {
|
||||||
|
digital_temperature_sensor,
|
||||||
|
intel_turbo_boost,
|
||||||
|
arat,
|
||||||
|
pln,
|
||||||
|
ecmd,
|
||||||
|
ptm,
|
||||||
|
hwp,
|
||||||
|
hwp_notification,
|
||||||
|
hwp_activity_window,
|
||||||
|
hwp_energy_performance_preference,
|
||||||
|
hdc,
|
||||||
|
hardware_coordination_feedback,
|
||||||
|
performance_energy_bias
|
||||||
|
});
|
||||||
|
|
||||||
|
delegate_flag!(structured_extended_information, {
|
||||||
|
fsgsbase,
|
||||||
|
ia32_tsc_adjust_msr,
|
||||||
|
bmi1,
|
||||||
|
hle,
|
||||||
|
avx2,
|
||||||
|
smep,
|
||||||
|
bmi2,
|
||||||
|
enhanced_rep_movsb_stosb,
|
||||||
|
invpcid,
|
||||||
|
rtm,
|
||||||
|
pqm,
|
||||||
|
deprecates_fpu_cs_ds,
|
||||||
|
pqe,
|
||||||
|
rdseed,
|
||||||
|
adx,
|
||||||
|
smap,
|
||||||
|
intel_processor_trace,
|
||||||
|
prefetchwt1
|
||||||
|
});
|
||||||
|
|
||||||
|
delegate_flag!(extended_processor_signature, {
|
||||||
|
lahf_sahf_in_64_bit,
|
||||||
|
lzcnt,
|
||||||
|
prefetchw,
|
||||||
|
syscall_sysret_in_64_bit,
|
||||||
|
execute_disable,
|
||||||
|
gigabyte_pages,
|
||||||
|
rdtscp_and_ia32_tsc_aux,
|
||||||
|
intel_64_bit_architecture
|
||||||
|
});
|
||||||
|
|
||||||
|
delegate_flag!(time_stamp_counter, { invariant_tsc });
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
cfg_if! {
|
||||||
|
if #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] {
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn basic_genuine_intel() {
|
||||||
|
let (_, b, c, d) = cpuid(RequestType::BasicInformation);
|
||||||
|
|
||||||
|
assert_eq!(b"Genu", as_bytes(&b));
|
||||||
|
assert_eq!(b"ntel", as_bytes(&c));
|
||||||
|
assert_eq!(b"ineI", as_bytes(&d));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn brand_string_contains_intel() {
|
||||||
|
assert!(master().unwrap().brand_string().unwrap().contains("Intel(R)"))
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {}
|
||||||
|
}
|
||||||
|
*/
|
56
kernel/src/arch/x86_64/graphics.rs
Normal file
56
kernel/src/arch/x86_64/graphics.rs
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
use virtio_drivers::transport::Transport;
|
||||||
|
|
||||||
|
use crate::arch::virtio::AbleosHal;
|
||||||
|
|
||||||
|
use {embedded_graphics::pixelcolor::Rgb888, virtio_drivers::device::gpu::VirtIOGpu};
|
||||||
|
|
||||||
|
use {
|
||||||
|
able_graphics_library::raw_pixel::Display,
|
||||||
|
embedded_graphics::prelude::*,
|
||||||
|
limine::FramebufferRequest,
|
||||||
|
spin::{Lazy, Mutex},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub static DISPLAY: Lazy<Mutex<Display>> = Lazy::new(|| {
|
||||||
|
static FB_REQ: FramebufferRequest = FramebufferRequest::new(0);
|
||||||
|
let fb1 = &FB_REQ.get_response().get().unwrap().framebuffers()[0];
|
||||||
|
let m = Mutex::new(Display {
|
||||||
|
fb: fb1.address.as_ptr().unwrap().cast(),
|
||||||
|
size: Size::new(fb1.width as u32, fb1.height as u32),
|
||||||
|
color: Rgb888::WHITE,
|
||||||
|
});
|
||||||
|
log::info!("Graphics initialised");
|
||||||
|
m
|
||||||
|
});
|
||||||
|
|
||||||
|
pub fn init() {
|
||||||
|
Lazy::force(&DISPLAY);
|
||||||
|
}
|
||||||
|
pub fn virtio_gpu<T: Transport>(transport: T) {
|
||||||
|
let mut gpu = VirtIOGpu::<AbleosHal, T>::new(transport).expect("failed to create gpu driver");
|
||||||
|
let (width, height) = gpu.resolution().expect("failed to get resolution");
|
||||||
|
let width = width as usize;
|
||||||
|
let height = height as usize;
|
||||||
|
log::info!("GPU resolution is {}x{}", width, height);
|
||||||
|
let fb = gpu.setup_framebuffer().expect("failed to get fb");
|
||||||
|
for y in 0..height {
|
||||||
|
for x in 0..width {
|
||||||
|
let idx = (y * width + x) * 4;
|
||||||
|
fb[idx] = x as u8;
|
||||||
|
fb[idx + 1] = y as u8;
|
||||||
|
fb[idx + 2] = (x + y) as u8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gpu.flush().expect("failed to flush");
|
||||||
|
//delay some time
|
||||||
|
log::info!("virtio-gpu show graphics....");
|
||||||
|
for _ in 0..100000 {
|
||||||
|
for _ in 0..100000 {
|
||||||
|
unsafe {
|
||||||
|
core::arch::asm!("nop");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log::info!("virtio-gpu test finished");
|
||||||
|
}
|
|
@ -1,6 +1,10 @@
|
||||||
use spin::{Lazy, Mutex};
|
use {
|
||||||
use x2apic::lapic::{LocalApic, LocalApicBuilder};
|
spin::{Lazy, Mutex},
|
||||||
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode};
|
x2apic::lapic::{LocalApic, LocalApicBuilder},
|
||||||
|
x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode},
|
||||||
|
};
|
||||||
|
|
||||||
|
use log::info;
|
||||||
|
|
||||||
use crate::interp::wasm;
|
use crate::interp::wasm;
|
||||||
|
|
||||||
|
@ -14,6 +18,7 @@ pub unsafe fn init() {
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
enum Interrupt {
|
enum Interrupt {
|
||||||
Timer = 32,
|
Timer = 32,
|
||||||
|
Keyboard = 33,
|
||||||
ApicErr = u8::MAX - 1,
|
ApicErr = u8::MAX - 1,
|
||||||
Spurious = u8::MAX,
|
Spurious = u8::MAX,
|
||||||
}
|
}
|
||||||
|
@ -46,6 +51,7 @@ static IDT: Lazy<InterruptDescriptorTable> = Lazy::new(|| {
|
||||||
idt[Interrupt::Spurious as usize].set_handler_fn(spurious);
|
idt[Interrupt::Spurious as usize].set_handler_fn(spurious);
|
||||||
|
|
||||||
idt[Interrupt::Timer as usize].set_handler_fn(timer);
|
idt[Interrupt::Timer as usize].set_handler_fn(timer);
|
||||||
|
|
||||||
idt
|
idt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,46 +1,48 @@
|
||||||
//! Logging (as in terms of console / serial output)
|
//! Logging (as in terms of console / serial output)
|
||||||
|
|
||||||
use core::fmt::Write;
|
use {
|
||||||
use limine::{TerminalRequest, TerminalResponse};
|
core::fmt::Write,
|
||||||
use spin::{Lazy, Mutex};
|
limine::{TerminalRequest, TerminalResponse},
|
||||||
use uart_16550::SerialPort;
|
spin::{Lazy, Mutex},
|
||||||
|
uart_16550::SerialPort,
|
||||||
|
};
|
||||||
|
|
||||||
static SERIAL_CONSOLE: Mutex<SerialPort> = Mutex::new(unsafe { SerialPort::new(0x3f8) });
|
static SERIAL_CONSOLE: Mutex<SerialPort> = Mutex::new(unsafe { SerialPort::new(0x3F8) });
|
||||||
static TERMINAL_LOGGER: Lazy<Mutex<TermLogger>> = Lazy::new(|| Mutex::new(TermLogger::new()));
|
// static TERMINAL_LOGGER: Lazy<Mutex<TermLogger>> = Lazy::new(|| Mutex::new(TermLogger::new()));
|
||||||
|
|
||||||
pub fn init() {
|
pub fn init() {
|
||||||
SERIAL_CONSOLE.lock().init();
|
SERIAL_CONSOLE.lock().init();
|
||||||
Lazy::force(&TERMINAL_LOGGER);
|
// Lazy::force(&TERMINAL_LOGGER);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log(args: core::fmt::Arguments<'_>) -> core::fmt::Result {
|
pub fn log(args: core::fmt::Arguments<'_>) -> core::fmt::Result {
|
||||||
x86_64::instructions::interrupts::without_interrupts(|| {
|
x86_64::instructions::interrupts::without_interrupts(|| {
|
||||||
TERMINAL_LOGGER.lock().write_fmt(args)?;
|
// TERMINAL_LOGGER.lock().write_fmt(args)?;
|
||||||
SERIAL_CONSOLE.lock().write_fmt(args)
|
SERIAL_CONSOLE.lock().write_fmt(args)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TermLogger(&'static TerminalResponse);
|
// struct TermLogger(&'static TerminalResponse);
|
||||||
unsafe impl Send for TermLogger {}
|
// unsafe impl Send for TermLogger {}
|
||||||
impl TermLogger {
|
// impl TermLogger {
|
||||||
pub fn new() -> Self {
|
// pub fn new() -> Self {
|
||||||
static TERM_REQ: TerminalRequest = TerminalRequest::new(0);
|
// static TERM_REQ: TerminalRequest = TerminalRequest::new(0);
|
||||||
Self(
|
// Self(
|
||||||
TERM_REQ
|
// TERM_REQ
|
||||||
.get_response()
|
// .get_response()
|
||||||
.get()
|
// .get()
|
||||||
.expect("failed to get terminal response"),
|
// .expect("failed to get terminal response"),
|
||||||
)
|
// )
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl Write for TermLogger {
|
// impl Write for TermLogger {
|
||||||
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
// fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||||
if let (Some(w), ts) = (self.0.write(), self.0.terminals()) {
|
// if let (Some(w), ts) = (self.0.write(), self.0.terminals()) {
|
||||||
for term in ts {
|
// for term in ts {
|
||||||
w(term, s);
|
// w(term, s);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
Ok(())
|
// Ok(())
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
|
@ -1,15 +1,26 @@
|
||||||
|
use {limine::SmpRequest, xml::XMLElement};
|
||||||
|
|
||||||
|
use embedded_graphics::pixelcolor::Rgb888;
|
||||||
|
|
||||||
|
use crate::{arch::x86_64::graphics::DISPLAY, kmain::DEVICE_TREE};
|
||||||
|
|
||||||
pub mod memory;
|
pub mod memory;
|
||||||
|
|
||||||
|
mod cpuid;
|
||||||
mod gdt;
|
mod gdt;
|
||||||
|
mod graphics;
|
||||||
pub(crate) mod interrupts;
|
pub(crate) mod interrupts;
|
||||||
mod logging;
|
mod logging;
|
||||||
|
pub mod pci;
|
||||||
|
pub mod virtio;
|
||||||
|
|
||||||
pub use logging::log;
|
pub use {logging::log, memory::PAGE_SIZE};
|
||||||
pub use memory::PAGE_SIZE;
|
|
||||||
|
|
||||||
use crate::allocator;
|
use {
|
||||||
use limine::{HhdmRequest, KernelFileRequest, MemmapRequest, ModuleRequest};
|
crate::allocator,
|
||||||
use x86_64::VirtAddr;
|
limine::{HhdmRequest, KernelFileRequest, MemmapRequest, ModuleRequest},
|
||||||
|
x86_64::VirtAddr,
|
||||||
|
};
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn _initial_kernel_heap_start();
|
fn _initial_kernel_heap_start();
|
||||||
|
@ -51,6 +62,65 @@ unsafe extern "C" fn _kernel_start() -> ! {
|
||||||
static KFILE_REQ: KernelFileRequest = KernelFileRequest::new(0);
|
static KFILE_REQ: KernelFileRequest = KernelFileRequest::new(0);
|
||||||
static MOD_REQ: ModuleRequest = ModuleRequest::new(0);
|
static MOD_REQ: ModuleRequest = ModuleRequest::new(0);
|
||||||
|
|
||||||
|
static SMP: SmpRequest = SmpRequest::new(0);
|
||||||
|
let smp = SMP.get_response().get().unwrap();
|
||||||
|
use crate::alloc::string::ToString;
|
||||||
|
|
||||||
|
let cpuinfo = cpuid::master().unwrap();
|
||||||
|
let brand_string = cpuinfo.brand_string().unwrap_or("Unknown").to_string();
|
||||||
|
DEVICE_TREE.force_unlock();
|
||||||
|
|
||||||
|
pci::init();
|
||||||
|
|
||||||
|
let mut dt = DEVICE_TREE.lock();
|
||||||
|
|
||||||
|
let cpus = dt.devices.get_mut("CPUs").unwrap();
|
||||||
|
let mut cpu = XMLElement::new("cpu");
|
||||||
|
let core_count = smp.cpu_count.to_string();
|
||||||
|
cpu.set_attribute("core count", core_count);
|
||||||
|
cpu.set_attribute("brand string", brand_string);
|
||||||
|
|
||||||
|
let cpu_speed = 0;
|
||||||
|
|
||||||
|
cpu.set_attribute("speed", "Unknown");
|
||||||
|
|
||||||
|
if false {
|
||||||
|
// disable() // disable interrupts (if still not done)
|
||||||
|
let i = 0;
|
||||||
|
let start = cpuinfo.time_stamp_counter();
|
||||||
|
|
||||||
|
log::info!("{:?}", start.unwrap().invariant_tsc());
|
||||||
|
for x in 0..1000 {}
|
||||||
|
let end = cpuinfo.time_stamp_counter();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut cpu_features = xml::XMLElement::new("CPU Features");
|
||||||
|
{
|
||||||
|
let x2 = cpuinfo.x2apic();
|
||||||
|
let apic = cpuinfo.apic();
|
||||||
|
let avx = cpuinfo.avx();
|
||||||
|
|
||||||
|
cpu_features.set_attribute("apic", apic.to_string());
|
||||||
|
cpu_features.set_attribute("avx", apic.to_string());
|
||||||
|
cpu_features.set_attribute("x2apic", x2.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu.set_child(cpu_features);
|
||||||
|
cpus.push(cpu);
|
||||||
|
drop(dt);
|
||||||
|
|
||||||
|
// Graphics test
|
||||||
|
{
|
||||||
|
let mut dis = DISPLAY.lock();
|
||||||
|
use {able_graphics_library::raw_pixel, embedded_graphics::prelude::RgbColor};
|
||||||
|
|
||||||
|
dis.set_color(Rgb888::GREEN);
|
||||||
|
|
||||||
|
dis.line(1, 1, 10, 10, 4);
|
||||||
|
dis.line(1, 200, 100, 10, 1);
|
||||||
|
dis.line(1, 1, 200, 10, 1);
|
||||||
|
}
|
||||||
|
|
||||||
crate::kmain::kmain(
|
crate::kmain::kmain(
|
||||||
KFILE_REQ
|
KFILE_REQ
|
||||||
.get_response()
|
.get_response()
|
||||||
|
@ -84,8 +154,7 @@ pub fn sloop() -> ! {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hardware_random_u64() -> u64 {
|
pub fn hardware_random_u64() -> u64 {
|
||||||
use log::trace;
|
use {log::trace, rdrand::RdRand};
|
||||||
use rdrand::RdRand;
|
|
||||||
let gen = RdRand::new().unwrap();
|
let gen = RdRand::new().unwrap();
|
||||||
let ret = gen.try_next_u64().unwrap();
|
let ret = gen.try_next_u64().unwrap();
|
||||||
trace!("Random {}", ret);
|
trace!("Random {}", ret);
|
||||||
|
|
490
kernel/src/arch/x86_64/pci/mod.rs
Normal file
490
kernel/src/arch/x86_64/pci/mod.rs
Normal file
|
@ -0,0 +1,490 @@
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
/// A struct containing info about a PCI device.
|
||||||
|
pub struct PciDeviceInfo {
|
||||||
|
pub header_type: u8,
|
||||||
|
pub device: u8,
|
||||||
|
pub bus: u8,
|
||||||
|
pub device_id: DeviceID,
|
||||||
|
pub full_class: PciFullClass,
|
||||||
|
pub rev_id: u8,
|
||||||
|
}
|
||||||
|
use crate::alloc::string::ToString;
|
||||||
|
/// Enumerate PCI devices and run initialisation routines on ones we support
|
||||||
|
pub fn init() {
|
||||||
|
let mut dt = DEVICE_TREE.lock();
|
||||||
|
dt.devices
|
||||||
|
.insert("Unidentified PCI".to_string(), alloc::vec![]);
|
||||||
|
let mut devices = alloc::vec![];
|
||||||
|
|
||||||
|
for bus in 0..=255 {
|
||||||
|
for device in 0..32 {
|
||||||
|
if let Some(device_info) = check_device(bus, device) {
|
||||||
|
let vendor = device_info.device_id.vendor;
|
||||||
|
let id = device_info.device_id.id;
|
||||||
|
use Vendor::*;
|
||||||
|
let (dev_type, dev_name) = match (vendor, id) {
|
||||||
|
(VirtIO, 4176) => ("GPUs", "VirtIO PCI GPU"),
|
||||||
|
(CirrusLogic, 184) => ("GPUs", "Cirrus SVGA"), //GD 5446?
|
||||||
|
(_, _) => ("Unidentified PCI", "UNKNOWN DEVICE"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut dev = xml::XMLElement::new(dev_name);
|
||||||
|
let mut pci_info = xml::XMLElement::new("PCI Info");
|
||||||
|
pci_info.set_attribute("id", id);
|
||||||
|
pci_info.set_attribute("device", device_info.device);
|
||||||
|
pci_info.set_attribute("vendor", vendor);
|
||||||
|
pci_info.set_attribute("class", device_info.full_class.to_string());
|
||||||
|
dev.set_child(pci_info);
|
||||||
|
devices.push((dev_type, dev));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (dev_type, dev) in devices {
|
||||||
|
if let Some(abc) = dt.devices.get_mut(dev_type) {
|
||||||
|
abc.push(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_device(bus: u8, device: u8) -> Option<PciDeviceInfo> {
|
||||||
|
assert!(device < 32);
|
||||||
|
let (device_id, vendor_id) = get_ids(bus, device, 0);
|
||||||
|
if vendor_id == 0xFFFF {
|
||||||
|
// Device doesn't exist
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let reg2 = unsafe { pci_config_read(bus, device, 0, 0x8) };
|
||||||
|
let class = ((reg2 >> 16) & 0x0000FFFF) as u16;
|
||||||
|
let pci_class = PciFullClass::from_u16(class);
|
||||||
|
let header_type = get_header_type(bus, device, 0);
|
||||||
|
|
||||||
|
Some(PciDeviceInfo {
|
||||||
|
header_type,
|
||||||
|
device,
|
||||||
|
bus,
|
||||||
|
device_id: DeviceID {
|
||||||
|
vendor: vendor_id.into(),
|
||||||
|
id: device_id,
|
||||||
|
},
|
||||||
|
full_class: pci_class,
|
||||||
|
rev_id: (reg2 & 0x000000FF) as u8,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct DeviceID {
|
||||||
|
pub vendor: Vendor,
|
||||||
|
pub id: u16,
|
||||||
|
}
|
||||||
|
impl DeviceID {
|
||||||
|
pub const fn new(vendor: Vendor, id: u16) -> Self {
|
||||||
|
Self { vendor, id }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Debug, Copy, Clone, Eq)]
|
||||||
|
#[repr(u16)]
|
||||||
|
pub enum Vendor {
|
||||||
|
ThreeDfxInteractiveInc = 0x121A,
|
||||||
|
ThreeDLabs = 0x3D3D,
|
||||||
|
AllianceSemiconductorCorp = 0x1142,
|
||||||
|
ARKLogicInc = 0xEDD8,
|
||||||
|
ATITechnologiesInc = 0x1002,
|
||||||
|
AvanceLogicIncALI = 0x1005,
|
||||||
|
ChipsandTechnologies = 0x102C,
|
||||||
|
CirrusLogic = 0x1013,
|
||||||
|
Compaq = 0x0E11,
|
||||||
|
CyrixCorp = 0x1078,
|
||||||
|
DiamondMultimediaSystems = 0x1092,
|
||||||
|
DigitalEquipmentCorp = 0x1011,
|
||||||
|
Iit = 0x1061,
|
||||||
|
IntegratedMicroSolutionsInc = 0x10E0,
|
||||||
|
IntelCorp = 0x8086,
|
||||||
|
IntergraphicsSystems = 0x10EA,
|
||||||
|
MacronixInc = 0x10D9,
|
||||||
|
MatroxGraphicsInc = 0x102B,
|
||||||
|
MiroComputersProductsAG = 0x1031,
|
||||||
|
NationalSemiconductorCorp = 0x100B,
|
||||||
|
NeoMagicCorp = 0x10C8,
|
||||||
|
Number9ComputerCompany = 0x105D,
|
||||||
|
NVidiaCorporation = 0x10DE,
|
||||||
|
NVidiaSgsthomson = 0x12D2,
|
||||||
|
OakTechnologyInc = 0x104E,
|
||||||
|
Qemu = 0x1234,
|
||||||
|
QuantumDesignsHKLtd = 0x1098,
|
||||||
|
Real3D = 0x003D,
|
||||||
|
Rendition = 0x1163,
|
||||||
|
S3Inc = 0x5333,
|
||||||
|
SierraSemiconductor = 0x10A8,
|
||||||
|
SiliconIntegratedSystemsSiS = 0x1039,
|
||||||
|
SiliconMotionInc = 0x126F,
|
||||||
|
STBSystemsInc = 0x10B4,
|
||||||
|
TexasInstruments = 0x104C,
|
||||||
|
ToshibaAmericaInfoSystems = 0x1179,
|
||||||
|
TridentMicrosystems = 0x1023,
|
||||||
|
TsengLabsInc = 0x100C,
|
||||||
|
TundraSemiconductorCorp = 0x10E3,
|
||||||
|
VIATechnologiesInc = 0x1106,
|
||||||
|
VirtIO = 0x1AF4,
|
||||||
|
VMWareInc = 0x15AD,
|
||||||
|
Weitek = 0x100E,
|
||||||
|
Unknown(u16),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u16> for Vendor {
|
||||||
|
fn from(vendor_id: u16) -> Self {
|
||||||
|
use Vendor::*;
|
||||||
|
match vendor_id {
|
||||||
|
0x121A => ThreeDfxInteractiveInc,
|
||||||
|
0x3D3D => ThreeDLabs,
|
||||||
|
0x1142 => AllianceSemiconductorCorp,
|
||||||
|
0xEDD8 => ARKLogicInc,
|
||||||
|
0x1002 => ATITechnologiesInc,
|
||||||
|
0x1005 => AvanceLogicIncALI,
|
||||||
|
0x102C => ChipsandTechnologies,
|
||||||
|
0x1013 => CirrusLogic,
|
||||||
|
0x0E11 => Compaq,
|
||||||
|
0x1078 => CyrixCorp,
|
||||||
|
0x1092 => DiamondMultimediaSystems,
|
||||||
|
0x1011 => DigitalEquipmentCorp,
|
||||||
|
0x1061 => Iit,
|
||||||
|
0x10E0 => IntegratedMicroSolutionsInc,
|
||||||
|
0x8086 => IntelCorp,
|
||||||
|
0x10EA => IntergraphicsSystems,
|
||||||
|
0x10D9 => MacronixInc,
|
||||||
|
0x102B => MatroxGraphicsInc,
|
||||||
|
0x1031 => MiroComputersProductsAG,
|
||||||
|
0x100B => NationalSemiconductorCorp,
|
||||||
|
0x10C8 => NeoMagicCorp,
|
||||||
|
0x105D => Number9ComputerCompany,
|
||||||
|
0x10DE => NVidiaCorporation,
|
||||||
|
0x12D2 => NVidiaSgsthomson,
|
||||||
|
0x104E => OakTechnologyInc,
|
||||||
|
0x1234 => Qemu,
|
||||||
|
0x1098 => QuantumDesignsHKLtd,
|
||||||
|
0x003D => Real3D,
|
||||||
|
0x1163 => Rendition,
|
||||||
|
0x5333 => S3Inc,
|
||||||
|
0x10A8 => SierraSemiconductor,
|
||||||
|
0x1039 => SiliconIntegratedSystemsSiS,
|
||||||
|
0x126F => SiliconMotionInc,
|
||||||
|
0x10B4 => STBSystemsInc,
|
||||||
|
0x104C => TexasInstruments,
|
||||||
|
0x1179 => ToshibaAmericaInfoSystems,
|
||||||
|
0x1023 => TridentMicrosystems,
|
||||||
|
0x100C => TsengLabsInc,
|
||||||
|
0x10E3 => TundraSemiconductorCorp,
|
||||||
|
0x1106 => VIATechnologiesInc,
|
||||||
|
0x1AF4 => VirtIO,
|
||||||
|
0x15AD => VMWareInc,
|
||||||
|
0x100E => Weitek,
|
||||||
|
id => Unknown(id),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<u16> for Vendor {
|
||||||
|
fn into(self) -> u16 {
|
||||||
|
use Vendor::*;
|
||||||
|
match self {
|
||||||
|
ThreeDfxInteractiveInc => 0x121A,
|
||||||
|
ThreeDLabs => 0x3D3D,
|
||||||
|
AllianceSemiconductorCorp => 0x1142,
|
||||||
|
ARKLogicInc => 0xEDD8,
|
||||||
|
ATITechnologiesInc => 0x1002,
|
||||||
|
AvanceLogicIncALI => 0x1005,
|
||||||
|
ChipsandTechnologies => 0x102C,
|
||||||
|
CirrusLogic => 0x1013,
|
||||||
|
Compaq => 0x0E11,
|
||||||
|
CyrixCorp => 0x1078,
|
||||||
|
DiamondMultimediaSystems => 0x1092,
|
||||||
|
DigitalEquipmentCorp => 0x1011,
|
||||||
|
Iit => 0x1061,
|
||||||
|
IntegratedMicroSolutionsInc => 0x10E0,
|
||||||
|
IntelCorp => 0x8086,
|
||||||
|
IntergraphicsSystems => 0x10EA,
|
||||||
|
MacronixInc => 0x10D9,
|
||||||
|
MatroxGraphicsInc => 0x102B,
|
||||||
|
MiroComputersProductsAG => 0x1031,
|
||||||
|
NationalSemiconductorCorp => 0x100B,
|
||||||
|
NeoMagicCorp => 0x10C8,
|
||||||
|
Number9ComputerCompany => 0x105D,
|
||||||
|
NVidiaCorporation => 0x10DE,
|
||||||
|
NVidiaSgsthomson => 0x12D2,
|
||||||
|
OakTechnologyInc => 0x104E,
|
||||||
|
Qemu => 0x1234,
|
||||||
|
QuantumDesignsHKLtd => 0x1098,
|
||||||
|
Real3D => 0x003D,
|
||||||
|
Rendition => 0x1163,
|
||||||
|
S3Inc => 0x5333,
|
||||||
|
SierraSemiconductor => 0x10A8,
|
||||||
|
SiliconIntegratedSystemsSiS => 0x1039,
|
||||||
|
SiliconMotionInc => 0x126F,
|
||||||
|
STBSystemsInc => 0x10B4,
|
||||||
|
TexasInstruments => 0x104C,
|
||||||
|
ToshibaAmericaInfoSystems => 0x1179,
|
||||||
|
TridentMicrosystems => 0x1023,
|
||||||
|
TsengLabsInc => 0x100C,
|
||||||
|
TundraSemiconductorCorp => 0x10E3,
|
||||||
|
VIATechnologiesInc => 0x1106,
|
||||||
|
VirtIO => 0x1AF4,
|
||||||
|
VMWareInc => 0x15AD,
|
||||||
|
Weitek => 0x100E,
|
||||||
|
Unknown(id) => id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl core::fmt::Display for Vendor {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
use Vendor::*;
|
||||||
|
|
||||||
|
match self {
|
||||||
|
Qemu => write!(f, "QEMU (0x1234)"),
|
||||||
|
VirtIO => write!(f, "VirtIO (0x1AF4)"),
|
||||||
|
VMWareInc => write!(f, "VMWARE (0x15AD)"),
|
||||||
|
S3Inc => write!(f, "S3 Incorporated (0x5333)"),
|
||||||
|
IntelCorp => write!(f, "Intel Corp. (0x8086)"),
|
||||||
|
ATITechnologiesInc => write!(f, "ATI (0x1002)"),
|
||||||
|
Unknown(id) => write!(f, "Unknown ({:#6})", id),
|
||||||
|
other => write!(f, "{other:?}"),
|
||||||
|
}?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
use core::fmt::Display;
|
||||||
|
|
||||||
|
use crate::kmain::DEVICE_TREE;
|
||||||
|
|
||||||
|
use {alloc::fmt::format, x86_64::instructions::port::Port};
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types, dead_code)]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
#[repr(C)]
|
||||||
|
/// Class specification for a PCI device
|
||||||
|
pub enum PciClass {
|
||||||
|
Unclassified = 0x00,
|
||||||
|
MassStorage = 0x01,
|
||||||
|
Network = 0x02,
|
||||||
|
Display = 0x03,
|
||||||
|
Multimedia = 0x04,
|
||||||
|
Memory = 0x05,
|
||||||
|
Bridge = 0x06,
|
||||||
|
Unknown = 0xFF,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for PciClass {
|
||||||
|
/// Convert a u8 into the corresponding PciClass
|
||||||
|
fn from(n: u8) -> Self {
|
||||||
|
use PciClass::*;
|
||||||
|
match n {
|
||||||
|
0x00 => Unclassified,
|
||||||
|
0x01 => MassStorage,
|
||||||
|
0x02 => Network,
|
||||||
|
0x03 => Display,
|
||||||
|
0x04 => Multimedia,
|
||||||
|
0x05 => Memory,
|
||||||
|
0x06 => Bridge,
|
||||||
|
_ => Unknown,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types, dead_code)]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
#[repr(C)]
|
||||||
|
/// Full class specification (type and subtype) for a PCI device.
|
||||||
|
///
|
||||||
|
/// Uses non-camel-case types for readability.
|
||||||
|
pub enum PciFullClass {
|
||||||
|
Unclassified_NonVgaCompatible = 0x0000,
|
||||||
|
Unclassified_VgaCompatible = 0x0001,
|
||||||
|
|
||||||
|
MassStorage_ScsiBus = 0x0100,
|
||||||
|
MassStorage_IDE = 0x0101,
|
||||||
|
MassStorage_Floppy = 0x0102,
|
||||||
|
MassStorage_IpiBus = 0x0103,
|
||||||
|
MassStorage_RAID = 0x0104,
|
||||||
|
MassStorage_ATA = 0x0105,
|
||||||
|
MassStorage_SATA = 0x0106,
|
||||||
|
MassStorage_SerialSCSI = 0x0107,
|
||||||
|
MassStorage_NVM = 0x0108,
|
||||||
|
MassStorage_Other = 0x0180,
|
||||||
|
|
||||||
|
Network_Ethernet = 0x0200,
|
||||||
|
Network_TokenRing = 0x0201,
|
||||||
|
Network_FDDI = 0x0202,
|
||||||
|
Network_ATM = 0x0203,
|
||||||
|
Network_ISDN = 0x0204,
|
||||||
|
Network_WorldFlip = 0x0205,
|
||||||
|
Network_PICMG = 0x0206,
|
||||||
|
Network_Infiniband = 0x0207,
|
||||||
|
Network_Fabric = 0x0208,
|
||||||
|
Network_Other = 0x0280,
|
||||||
|
|
||||||
|
Display_VGA = 0x0300,
|
||||||
|
Display_XGA = 0x0301,
|
||||||
|
Display_3D = 0x0302,
|
||||||
|
Display_Other = 0x0380,
|
||||||
|
|
||||||
|
Multimedia_Video = 0x0400,
|
||||||
|
Multimedia_AudioController = 0x0401,
|
||||||
|
Multimedia_Telephony = 0x0402,
|
||||||
|
Multimedia_AudioDevice = 0x0403,
|
||||||
|
Multimedia_Other = 0x0480,
|
||||||
|
|
||||||
|
Memory_RAM = 0x0500,
|
||||||
|
Memory_Flash = 0x0501,
|
||||||
|
Memory_Other = 0x0580,
|
||||||
|
|
||||||
|
Bridge_Host = 0x0600,
|
||||||
|
Bridge_ISA = 0x0601,
|
||||||
|
Bridge_EISA = 0x0602,
|
||||||
|
Bridge_MCA = 0x0603,
|
||||||
|
Bridge_PciToPci = 0x0604,
|
||||||
|
Bridge_PCMCIA = 0x0605,
|
||||||
|
Bridge_NuBus = 0x0606,
|
||||||
|
Bridge_CardBus = 0x0607,
|
||||||
|
Bridge_RACEway = 0x0608,
|
||||||
|
Bridge_PciToPciSemiTransparent = 0x0609,
|
||||||
|
Bridge_InfinibandToPci = 0x060A,
|
||||||
|
Bridge_Other = 0x0680,
|
||||||
|
|
||||||
|
Unknown = 0xFFFF,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PciFullClass {
|
||||||
|
// listen, i know this sucks, but i didn't want to include
|
||||||
|
// `num`, `num-traits` and `num-derive` as dependencies for
|
||||||
|
// this crate just for a convenience function
|
||||||
|
/// Convert a u16 into the corresponding PciFullClass
|
||||||
|
pub fn from_u16(n: u16) -> PciFullClass {
|
||||||
|
match n {
|
||||||
|
0x0000 => PciFullClass::Unclassified_NonVgaCompatible,
|
||||||
|
0x0001 => PciFullClass::Unclassified_VgaCompatible,
|
||||||
|
|
||||||
|
0x0100 => PciFullClass::MassStorage_ScsiBus,
|
||||||
|
0x0101 => PciFullClass::MassStorage_IDE,
|
||||||
|
0x0102 => PciFullClass::MassStorage_Floppy,
|
||||||
|
0x0103 => PciFullClass::MassStorage_IpiBus,
|
||||||
|
0x0104 => PciFullClass::MassStorage_RAID,
|
||||||
|
0x0105 => PciFullClass::MassStorage_ATA,
|
||||||
|
0x0106 => PciFullClass::MassStorage_SATA,
|
||||||
|
0x0107 => PciFullClass::MassStorage_SerialSCSI,
|
||||||
|
0x0108 => PciFullClass::MassStorage_NVM,
|
||||||
|
0x0180 => PciFullClass::MassStorage_Other,
|
||||||
|
|
||||||
|
0x0200 => PciFullClass::Network_Ethernet,
|
||||||
|
0x0201 => PciFullClass::Network_TokenRing,
|
||||||
|
0x0202 => PciFullClass::Network_FDDI,
|
||||||
|
0x0203 => PciFullClass::Network_ATM,
|
||||||
|
0x0204 => PciFullClass::Network_ISDN,
|
||||||
|
0x0205 => PciFullClass::Network_WorldFlip,
|
||||||
|
0x0206 => PciFullClass::Network_PICMG,
|
||||||
|
0x0207 => PciFullClass::Network_Infiniband,
|
||||||
|
0x0208 => PciFullClass::Network_Fabric,
|
||||||
|
0x0280 => PciFullClass::Network_Other,
|
||||||
|
|
||||||
|
0x0300 => PciFullClass::Display_VGA,
|
||||||
|
0x0301 => PciFullClass::Display_XGA,
|
||||||
|
0x0302 => PciFullClass::Display_3D,
|
||||||
|
0x0380 => PciFullClass::Display_Other,
|
||||||
|
|
||||||
|
0x0400 => PciFullClass::Multimedia_Video,
|
||||||
|
0x0401 => PciFullClass::Multimedia_AudioController,
|
||||||
|
0x0402 => PciFullClass::Multimedia_Telephony,
|
||||||
|
0x0403 => PciFullClass::Multimedia_AudioDevice,
|
||||||
|
0x0480 => PciFullClass::Multimedia_Other,
|
||||||
|
|
||||||
|
0x0500 => PciFullClass::Memory_RAM,
|
||||||
|
0x0501 => PciFullClass::Memory_Flash,
|
||||||
|
0x0580 => PciFullClass::Memory_Other,
|
||||||
|
|
||||||
|
0x0600 => PciFullClass::Bridge_Host,
|
||||||
|
0x0601 => PciFullClass::Bridge_ISA,
|
||||||
|
0x0602 => PciFullClass::Bridge_EISA,
|
||||||
|
0x0603 => PciFullClass::Bridge_MCA,
|
||||||
|
0x0604 => PciFullClass::Bridge_PciToPci,
|
||||||
|
0x0605 => PciFullClass::Bridge_PCMCIA,
|
||||||
|
0x0606 => PciFullClass::Bridge_NuBus,
|
||||||
|
0x0607 => PciFullClass::Bridge_CardBus,
|
||||||
|
0x0608 => PciFullClass::Bridge_RACEway,
|
||||||
|
0x0609 => PciFullClass::Bridge_PciToPciSemiTransparent,
|
||||||
|
0x060A => PciFullClass::Bridge_InfinibandToPci,
|
||||||
|
0x0680 => PciFullClass::Bridge_Other,
|
||||||
|
|
||||||
|
_ => PciFullClass::Unknown,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a PciFullClass to its u16 representation
|
||||||
|
pub fn as_u16(&self) -> u16 {
|
||||||
|
*self as u16
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u16> for PciFullClass {
|
||||||
|
/// Convert a u16 into the corresponding PciFullClass
|
||||||
|
fn from(n: u16) -> Self {
|
||||||
|
Self::from_u16(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for PciFullClass {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
write!(f, "{:?} ({:#06X})", self, self.as_u16())?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn pci_config_read(bus: u8, device: u8, func: u8, offset: u8) -> u32 {
|
||||||
|
let bus = bus as u32;
|
||||||
|
let device = device as u32;
|
||||||
|
let func = func as u32;
|
||||||
|
let offset = offset as u32;
|
||||||
|
// construct address param
|
||||||
|
let address =
|
||||||
|
((bus << 16) | (device << 11) | (func << 8) | (offset & 0xFC) | 0x80000000) as u32;
|
||||||
|
|
||||||
|
// write address
|
||||||
|
Port::new(0xCF8).write(address);
|
||||||
|
|
||||||
|
// read data
|
||||||
|
Port::new(0xCFC).read()
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn pci_config_write(bus: u8, device: u8, func: u8, offset: u8, value: u32) {
|
||||||
|
let bus = bus as u32;
|
||||||
|
let device = device as u32;
|
||||||
|
let func = func as u32;
|
||||||
|
let offset = offset as u32;
|
||||||
|
// construct address param
|
||||||
|
let address =
|
||||||
|
((bus << 16) | (device << 11) | (func << 8) | (offset & 0xFC) | 0x80000000) as u32;
|
||||||
|
|
||||||
|
// write address
|
||||||
|
Port::new(0xCF8).write(address);
|
||||||
|
|
||||||
|
// write data
|
||||||
|
Port::new(0xCFC).write(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_header_type(bus: u8, device: u8, function: u8) -> u8 {
|
||||||
|
assert!(device < 32);
|
||||||
|
assert!(function < 8);
|
||||||
|
let res = unsafe { pci_config_read(bus, device, function, 0x0C) };
|
||||||
|
((res >> 16) & 0xFF) as u8
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_ids(bus: u8, device: u8, function: u8) -> (u16, u16) {
|
||||||
|
assert!(device < 32);
|
||||||
|
assert!(function < 8);
|
||||||
|
let res = unsafe { pci_config_read(bus, device, function, 0) };
|
||||||
|
let dev_id = ((res >> 16) & 0xFFFF) as u16;
|
||||||
|
let vnd_id = (res & 0xFFFF) as u16;
|
||||||
|
(dev_id, vnd_id)
|
||||||
|
}
|
38
kernel/src/arch/x86_64/virtio/mod.rs
Normal file
38
kernel/src/arch/x86_64/virtio/mod.rs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
use {
|
||||||
|
alloc::alloc::{alloc_zeroed, dealloc, handle_alloc_error},
|
||||||
|
core::{alloc::Layout, ptr::NonNull},
|
||||||
|
virtio_drivers::{BufferDirection, Hal, PhysAddr, PAGE_SIZE},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn test() {
|
||||||
|
let ps = virtio_drivers::PAGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AbleosHal;
|
||||||
|
|
||||||
|
unsafe impl Hal for AbleosHal {
|
||||||
|
fn dma_alloc(pages: usize, _direction: BufferDirection) -> (PhysAddr, NonNull<u8>) {
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn dma_dealloc(_paddr: PhysAddr, vaddr: NonNull<u8>, pages: usize) -> i32 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn mmio_phys_to_virt(paddr: PhysAddr, _size: usize) -> NonNull<u8> {
|
||||||
|
NonNull::new(paddr as _).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn share(buffer: NonNull<[u8]>, _direction: BufferDirection) -> PhysAddr {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn unshare(_paddr: PhysAddr, _buffer: NonNull<[u8]>, _direction: BufferDirection) {
|
||||||
|
// Nothing to do, as the host already has access to all memory and we didn't copy the buffer
|
||||||
|
// anywhere else.
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn virt_to_phys(vaddr: usize) -> PhysAddr {
|
||||||
|
vaddr
|
||||||
|
}
|
71
kernel/src/device_tree.rs
Normal file
71
kernel/src/device_tree.rs
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
use alloc::{string::String, vec::Vec};
|
||||||
|
|
||||||
|
use {crate::alloc::string::ToString, core::fmt, hashbrown::HashMap, xml::XMLElement};
|
||||||
|
pub type Device = xml::XMLElement;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DeviceTree {
|
||||||
|
pub devices: HashMap<String, Vec<Device>>,
|
||||||
|
}
|
||||||
|
impl DeviceTree {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let mut dt = Self {
|
||||||
|
devices: HashMap::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Human input devices
|
||||||
|
{
|
||||||
|
dt.devices.insert("Mice".to_string(), Vec::new());
|
||||||
|
dt.devices.insert("Keyboards".to_string(), Vec::new());
|
||||||
|
dt.devices.insert("Controllers".to_string(), Vec::new());
|
||||||
|
// Human Input Devices that do not fit into other catagories go in this spot
|
||||||
|
dt.devices.insert("Generic HIDs".to_string(), Vec::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
dt.devices.insert("Disk Drives".to_string(), Vec::new());
|
||||||
|
dt.devices.insert("CD Drives".to_string(), Vec::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
dt.devices.insert("Batteries".to_string(), Vec::new());
|
||||||
|
dt.devices.insert("Monitors".to_string(), Vec::new());
|
||||||
|
dt.devices.insert("GPUs".to_string(), Vec::new());
|
||||||
|
dt.devices.insert("CPUs".to_string(), Vec::new());
|
||||||
|
|
||||||
|
dt.devices.insert("USB".to_string(), Vec::new());
|
||||||
|
dt.devices.insert("Serial Ports".to_string(), Vec::new());
|
||||||
|
dt.devices.insert("Cameras".to_string(), Vec::new());
|
||||||
|
dt.devices
|
||||||
|
.insert("Biometric Devices".to_string(), Vec::new());
|
||||||
|
|
||||||
|
dt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
use crate::utils::TAB;
|
||||||
|
|
||||||
|
impl fmt::Display for DeviceTree {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
for (device_type, devices) in &self.devices {
|
||||||
|
writeln!(f, "\r{TAB}{}/\r", device_type)?;
|
||||||
|
for device in devices {
|
||||||
|
writeln!(f, "{TAB}{TAB}{}/\r", device.name)?;
|
||||||
|
for attr in &device.attributes {
|
||||||
|
writeln!(f, "{TAB}{TAB}{TAB}{}\r", attr)?;
|
||||||
|
}
|
||||||
|
for child in &device.children {
|
||||||
|
writeln!(f, "{TAB}{TAB}{TAB}{}\r", child.name)?;
|
||||||
|
for attr in &child.attributes {
|
||||||
|
writeln!(f, "{TAB}{TAB}{TAB}{TAB}{}\r", attr)?;
|
||||||
|
}
|
||||||
|
for child in &child.children {
|
||||||
|
writeln!(f, "{TAB}{TAB}{TAB}{TAB}{}\r", child.name)?;
|
||||||
|
for attr in &child.attributes {
|
||||||
|
writeln!(f, "{TAB}{TAB}{TAB}{TAB}{TAB}{}\r", attr)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,14 +2,13 @@
|
||||||
|
|
||||||
// use std::collections::HashMap;
|
// use std::collections::HashMap;
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
use {
|
||||||
use log::{info, trace};
|
alloc::vec::Vec,
|
||||||
use spin::{Lazy, Mutex};
|
log::{info, trace},
|
||||||
|
spin::{Lazy, Mutex},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::arch::{hardware_random_u64, sloop};
|
use crate::{arch, device_tree::DeviceTree, schedule::Scheduler};
|
||||||
use crate::handle::Handle;
|
|
||||||
use crate::schedule::Scheduler;
|
|
||||||
use crate::{interp, task};
|
|
||||||
|
|
||||||
use crate::alloc::string::ToString;
|
use crate::alloc::string::ToString;
|
||||||
|
|
||||||
|
@ -23,13 +22,13 @@ pub fn kmain(cmdline: &str, bootstrap: Option<&'static [u8]>) -> ! {
|
||||||
let kcmd = clparse::Arguments::parse(cmdline.to_string()).unwrap();
|
let kcmd = clparse::Arguments::parse(cmdline.to_string()).unwrap();
|
||||||
log::info!("Cmdline: {kcmd:?}");
|
log::info!("Cmdline: {kcmd:?}");
|
||||||
|
|
||||||
// if kcmd.arguments.get("baka") == Some(&"true".to_string()) {
|
if kcmd.arguments.get("baka") == Some(&"true".to_string()) {
|
||||||
// let _ = crate::arch::log(format_args!(include_str!("../data/⑨. バカ")));
|
let _ = crate::arch::log(format_args!(include_str!("../data/⑨. バカ")));
|
||||||
// }
|
}
|
||||||
|
|
||||||
// if kcmd.arguments.get("foobles") == Some(&"true".to_string()) {
|
if kcmd.arguments.get("foobles") == Some(&"true".to_string()) {
|
||||||
// let _ = crate::arch::log(format_args!("foobles\n"));
|
let _ = crate::arch::log(format_args!("foobles\n\r"));
|
||||||
// }
|
}
|
||||||
|
|
||||||
let bootstrap = bootstrap/*.expect("no bootstrap found")*/;
|
let bootstrap = bootstrap/*.expect("no bootstrap found")*/;
|
||||||
match bootstrap {
|
match bootstrap {
|
||||||
|
@ -38,24 +37,9 @@ pub fn kmain(cmdline: &str, bootstrap: Option<&'static [u8]>) -> ! {
|
||||||
info!("No bootstrap module loaded.")
|
info!("No bootstrap module loaded.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let mut dt = DEVICE_TREE.lock();
|
||||||
|
|
||||||
// use xml::XMLElement;
|
info!("Device Tree {}", &dt);
|
||||||
// let kcmd = XMLElement::new("cmdline");
|
|
||||||
// let hnd = Handle::new();
|
|
||||||
// kcmd.set_attribute("")
|
|
||||||
// OBJECTS.lock().insert(hnd, kcmd);
|
|
||||||
|
|
||||||
let abc = interp::wasm();
|
|
||||||
|
|
||||||
trace!("{:?}", abc);
|
|
||||||
|
|
||||||
// let sch = SCHEDULER;
|
|
||||||
// let mut sch = sch.lock();
|
|
||||||
// let wc = interp::build_wasm_context(alloc::vec::Vec::new()).unwrap();
|
|
||||||
// sch.schedule(wc, crate::schedule::ContextWake::None);
|
|
||||||
|
|
||||||
// sch.run();
|
|
||||||
|
|
||||||
crate::arch::sloop()
|
crate::arch::sloop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,3 +47,8 @@ pub const SCHEDULER: Lazy<Mutex<Scheduler>> = Lazy::new(|| {
|
||||||
let mut sch = Scheduler::new();
|
let mut sch = Scheduler::new();
|
||||||
Mutex::new(sch)
|
Mutex::new(sch)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
pub static DEVICE_TREE: Lazy<Mutex<DeviceTree>> = Lazy::new(|| {
|
||||||
|
let mut dt = DeviceTree::new();
|
||||||
|
Mutex::new(dt)
|
||||||
|
});
|
||||||
|
|
|
@ -16,6 +16,7 @@ extern crate alloc;
|
||||||
|
|
||||||
mod allocator;
|
mod allocator;
|
||||||
mod arch;
|
mod arch;
|
||||||
|
pub mod device_tree;
|
||||||
pub mod handle;
|
pub mod handle;
|
||||||
pub mod interp;
|
pub mod interp;
|
||||||
mod kmain;
|
mod kmain;
|
||||||
|
@ -23,6 +24,7 @@ mod logger;
|
||||||
mod memory;
|
mod memory;
|
||||||
mod schedule;
|
mod schedule;
|
||||||
mod task;
|
mod task;
|
||||||
|
pub mod utils;
|
||||||
|
|
||||||
use versioning::Version;
|
use versioning::Version;
|
||||||
|
|
||||||
|
|
1
kernel/src/utils.rs
Normal file
1
kernel/src/utils.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pub const TAB: &str = " ";
|
|
@ -2,7 +2,7 @@ ${ABLEOS_KERNEL}=boot:///kernel
|
||||||
# TODO: Make a boot background image for ableOS
|
# TODO: Make a boot background image for ableOS
|
||||||
|
|
||||||
DEFAULT_ENTRY=1
|
DEFAULT_ENTRY=1
|
||||||
TIMEOUT=50
|
TIMEOUT=0
|
||||||
VERBOSE=yes
|
VERBOSE=yes
|
||||||
INTERFACE_RESOLUTION=1024x768
|
INTERFACE_RESOLUTION=1024x768
|
||||||
# Terminal related settings
|
# Terminal related settings
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use error_stack::{bail, report, Context, IntoReport, Result, ResultExt};
|
use {
|
||||||
use fatfs::{FileSystem, FormatVolumeOptions, FsOptions, ReadWriteSeek};
|
error_stack::{bail, report, Context, IntoReport, Result, ResultExt},
|
||||||
use std::{fmt::Display, fs::File, io, path::Path, process::Command};
|
fatfs::{FileSystem, FormatVolumeOptions, FsOptions, ReadWriteSeek},
|
||||||
|
std::{fmt::Display, fs::File, io, path::Path, process::Command},
|
||||||
|
};
|
||||||
|
|
||||||
fn main() -> Result<(), Error> {
|
fn main() -> Result<(), Error> {
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
|
@ -153,19 +155,32 @@ fn run(release: bool, target: Target) -> Result<(), Error> {
|
||||||
if target == Target::X86_64 {
|
if target == Target::X86_64 {
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
com.args([
|
com.args([
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"-bios",
|
"-bios",
|
||||||
std::env::var("REPBUILD_QEMU_FIRMWARE_PATH")
|
std::env::var("REPBUILD_QEMU_FIRMWARE_PATH")
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.unwrap_or("/usr/share/ovmf/x64/OVMF_CODE.fd"),
|
.unwrap_or("/usr/share/ovmf/x64/OVMF_CODE.fd"),
|
||||||
"-drive", "file=target/disk.img,format=raw",
|
"-drive", "file=target/disk.img,format=raw",
|
||||||
"-m", "4G",
|
"-m", "4G",
|
||||||
"-serial", "stdio",
|
// "-serial", "stdio",
|
||||||
"-smp", "cores=2",
|
"-smp", "cores=4",
|
||||||
|
"-vga", "cirrus",
|
||||||
|
"-device", "virtio-gpu-pci",
|
||||||
|
|
||||||
|
"-device", "virtio-serial,id=virtio-serial0",
|
||||||
|
"-chardev", "stdio,id=char0,mux=on",
|
||||||
|
"-device", "virtconsole,chardev=char0",
|
||||||
|
"-device", "virtio-mouse-pci",
|
||||||
|
|
||||||
|
// "-device", "ati-vga", "model=rage128p"
|
||||||
]);
|
]);
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
{
|
{
|
||||||
com.args(["-enable-kvm", "-cpu", "host"]);
|
// com.args(["-enable-kvm", "-cpu", "host"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue