forked from AbleOS/ableos
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.
|
||||
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]]
|
||||
name = "ahash"
|
||||
version = "0.7.6"
|
||||
|
@ -65,6 +74,12 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "az"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973"
|
||||
|
||||
[[package]]
|
||||
name = "bit"
|
||||
version = "0.1.1"
|
||||
|
@ -125,7 +140,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "clparse"
|
||||
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 = [
|
||||
"hashbrown 0.13.2",
|
||||
"log",
|
||||
|
@ -228,6 +243,29 @@ version = "1.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "env_logger"
|
||||
version = "0.10.0"
|
||||
|
@ -294,6 +332,15 @@ dependencies = [
|
|||
"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]]
|
||||
name = "getrandom"
|
||||
version = "0.2.8"
|
||||
|
@ -416,9 +463,11 @@ dependencies = [
|
|||
name = "kernel"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"able_graphics_library",
|
||||
"clparse",
|
||||
"crossbeam-queue",
|
||||
"derive_more",
|
||||
"embedded-graphics",
|
||||
"error-stack 0.3.1",
|
||||
"hashbrown 0.13.2",
|
||||
"limine",
|
||||
|
@ -429,6 +478,7 @@ dependencies = [
|
|||
"spin",
|
||||
"uart_16550",
|
||||
"versioning",
|
||||
"virtio-drivers",
|
||||
"wasmi",
|
||||
"x2apic",
|
||||
"x86_64",
|
||||
|
@ -492,6 +542,12 @@ version = "2.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "micromath"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc4010833aea396656c2f91ee704d51a6f1329ec2ab56ffd00bfd56f7481ea94"
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
|
@ -791,11 +847,22 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
|||
[[package]]
|
||||
name = "versioning"
|
||||
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 = [
|
||||
"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]]
|
||||
name = "volatile"
|
||||
version = "0.4.6"
|
||||
|
@ -1108,7 +1175,28 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "xml"
|
||||
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 = [
|
||||
"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"
|
||||
|
||||
[dependencies]
|
||||
|
||||
|
||||
embedded-graphics = "0.7.1"
|
||||
|
||||
|
||||
error-stack = { version = "0.3", default-features = false }
|
||||
log = "0.4"
|
||||
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 }
|
||||
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 }
|
||||
hashbrown = "*"
|
||||
|
||||
|
@ -43,6 +49,7 @@ features = [
|
|||
limine = { version = "0.1", git = "https://github.com/limine-bootloader/limine-rs" }
|
||||
x86_64 = "0.14"
|
||||
x2apic = "0.4"
|
||||
virtio-drivers = "0.4.0"
|
||||
# rdrand = "*"
|
||||
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 x2apic::lapic::{LocalApic, LocalApicBuilder};
|
||||
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode};
|
||||
use {
|
||||
spin::{Lazy, Mutex},
|
||||
x2apic::lapic::{LocalApic, LocalApicBuilder},
|
||||
x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode},
|
||||
};
|
||||
|
||||
use log::info;
|
||||
|
||||
use crate::interp::wasm;
|
||||
|
||||
|
@ -14,6 +18,7 @@ pub unsafe fn init() {
|
|||
#[repr(u8)]
|
||||
enum Interrupt {
|
||||
Timer = 32,
|
||||
Keyboard = 33,
|
||||
ApicErr = u8::MAX - 1,
|
||||
Spurious = u8::MAX,
|
||||
}
|
||||
|
@ -46,6 +51,7 @@ static IDT: Lazy<InterruptDescriptorTable> = Lazy::new(|| {
|
|||
idt[Interrupt::Spurious as usize].set_handler_fn(spurious);
|
||||
|
||||
idt[Interrupt::Timer as usize].set_handler_fn(timer);
|
||||
|
||||
idt
|
||||
});
|
||||
|
||||
|
|
|
@ -1,46 +1,48 @@
|
|||
//! Logging (as in terms of console / serial output)
|
||||
|
||||
use core::fmt::Write;
|
||||
use limine::{TerminalRequest, TerminalResponse};
|
||||
use spin::{Lazy, Mutex};
|
||||
use uart_16550::SerialPort;
|
||||
use {
|
||||
core::fmt::Write,
|
||||
limine::{TerminalRequest, TerminalResponse},
|
||||
spin::{Lazy, Mutex},
|
||||
uart_16550::SerialPort,
|
||||
};
|
||||
|
||||
static SERIAL_CONSOLE: Mutex<SerialPort> = Mutex::new(unsafe { SerialPort::new(0x3f8) });
|
||||
static TERMINAL_LOGGER: Lazy<Mutex<TermLogger>> = Lazy::new(|| Mutex::new(TermLogger::new()));
|
||||
static SERIAL_CONSOLE: Mutex<SerialPort> = Mutex::new(unsafe { SerialPort::new(0x3F8) });
|
||||
// static TERMINAL_LOGGER: Lazy<Mutex<TermLogger>> = Lazy::new(|| Mutex::new(TermLogger::new()));
|
||||
|
||||
pub fn init() {
|
||||
SERIAL_CONSOLE.lock().init();
|
||||
Lazy::force(&TERMINAL_LOGGER);
|
||||
// Lazy::force(&TERMINAL_LOGGER);
|
||||
}
|
||||
|
||||
pub fn log(args: core::fmt::Arguments<'_>) -> core::fmt::Result {
|
||||
x86_64::instructions::interrupts::without_interrupts(|| {
|
||||
TERMINAL_LOGGER.lock().write_fmt(args)?;
|
||||
// TERMINAL_LOGGER.lock().write_fmt(args)?;
|
||||
SERIAL_CONSOLE.lock().write_fmt(args)
|
||||
})
|
||||
}
|
||||
|
||||
struct TermLogger(&'static TerminalResponse);
|
||||
unsafe impl Send for TermLogger {}
|
||||
impl TermLogger {
|
||||
pub fn new() -> Self {
|
||||
static TERM_REQ: TerminalRequest = TerminalRequest::new(0);
|
||||
Self(
|
||||
TERM_REQ
|
||||
.get_response()
|
||||
.get()
|
||||
.expect("failed to get terminal response"),
|
||||
)
|
||||
}
|
||||
}
|
||||
// struct TermLogger(&'static TerminalResponse);
|
||||
// unsafe impl Send for TermLogger {}
|
||||
// impl TermLogger {
|
||||
// pub fn new() -> Self {
|
||||
// static TERM_REQ: TerminalRequest = TerminalRequest::new(0);
|
||||
// Self(
|
||||
// TERM_REQ
|
||||
// .get_response()
|
||||
// .get()
|
||||
// .expect("failed to get terminal response"),
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
|
||||
impl Write for TermLogger {
|
||||
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||
if let (Some(w), ts) = (self.0.write(), self.0.terminals()) {
|
||||
for term in ts {
|
||||
w(term, s);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
// impl Write for TermLogger {
|
||||
// fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||
// if let (Some(w), ts) = (self.0.write(), self.0.terminals()) {
|
||||
// for term in ts {
|
||||
// w(term, s);
|
||||
// }
|
||||
// }
|
||||
// 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;
|
||||
|
||||
mod cpuid;
|
||||
mod gdt;
|
||||
mod graphics;
|
||||
pub(crate) mod interrupts;
|
||||
mod logging;
|
||||
pub mod pci;
|
||||
pub mod virtio;
|
||||
|
||||
pub use logging::log;
|
||||
pub use memory::PAGE_SIZE;
|
||||
pub use {logging::log, memory::PAGE_SIZE};
|
||||
|
||||
use crate::allocator;
|
||||
use limine::{HhdmRequest, KernelFileRequest, MemmapRequest, ModuleRequest};
|
||||
use x86_64::VirtAddr;
|
||||
use {
|
||||
crate::allocator,
|
||||
limine::{HhdmRequest, KernelFileRequest, MemmapRequest, ModuleRequest},
|
||||
x86_64::VirtAddr,
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
fn _initial_kernel_heap_start();
|
||||
|
@ -51,6 +62,65 @@ unsafe extern "C" fn _kernel_start() -> ! {
|
|||
static KFILE_REQ: KernelFileRequest = KernelFileRequest::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(
|
||||
KFILE_REQ
|
||||
.get_response()
|
||||
|
@ -84,8 +154,7 @@ pub fn sloop() -> ! {
|
|||
}
|
||||
|
||||
pub fn hardware_random_u64() -> u64 {
|
||||
use log::trace;
|
||||
use rdrand::RdRand;
|
||||
use {log::trace, rdrand::RdRand};
|
||||
let gen = RdRand::new().unwrap();
|
||||
let ret = gen.try_next_u64().unwrap();
|
||||
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(())
|
||||
}
|
||||
}
|
|
@ -18,9 +18,9 @@ use alloc::vec;
|
|||
#[derive(Debug)]
|
||||
|
||||
pub struct WasmContext {
|
||||
pub proc_id: Option<u64>,
|
||||
pub proc_id: Option<u64>,
|
||||
pub instance: Instance,
|
||||
pub store: Store<HostState>,
|
||||
pub store: Store<HostState>,
|
||||
}
|
||||
|
||||
pub fn wasm() -> Result<(), wasmi::Error> {
|
||||
|
|
|
@ -2,14 +2,13 @@
|
|||
|
||||
// use std::collections::HashMap;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use log::{info, trace};
|
||||
use spin::{Lazy, Mutex};
|
||||
use {
|
||||
alloc::vec::Vec,
|
||||
log::{info, trace},
|
||||
spin::{Lazy, Mutex},
|
||||
};
|
||||
|
||||
use crate::arch::{hardware_random_u64, sloop};
|
||||
use crate::handle::Handle;
|
||||
use crate::schedule::Scheduler;
|
||||
use crate::{interp, task};
|
||||
use crate::{arch, device_tree::DeviceTree, schedule::Scheduler};
|
||||
|
||||
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();
|
||||
log::info!("Cmdline: {kcmd:?}");
|
||||
|
||||
// if kcmd.arguments.get("baka") == Some(&"true".to_string()) {
|
||||
// let _ = crate::arch::log(format_args!(include_str!("../data/⑨. バカ")));
|
||||
// }
|
||||
if kcmd.arguments.get("baka") == Some(&"true".to_string()) {
|
||||
let _ = crate::arch::log(format_args!(include_str!("../data/⑨. バカ")));
|
||||
}
|
||||
|
||||
// if kcmd.arguments.get("foobles") == Some(&"true".to_string()) {
|
||||
// let _ = crate::arch::log(format_args!("foobles\n"));
|
||||
// }
|
||||
if kcmd.arguments.get("foobles") == Some(&"true".to_string()) {
|
||||
let _ = crate::arch::log(format_args!("foobles\n\r"));
|
||||
}
|
||||
|
||||
let bootstrap = bootstrap/*.expect("no bootstrap found")*/;
|
||||
match bootstrap {
|
||||
|
@ -38,24 +37,9 @@ pub fn kmain(cmdline: &str, bootstrap: Option<&'static [u8]>) -> ! {
|
|||
info!("No bootstrap module loaded.")
|
||||
}
|
||||
}
|
||||
let mut dt = DEVICE_TREE.lock();
|
||||
|
||||
// use xml::XMLElement;
|
||||
// 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();
|
||||
|
||||
info!("Device Tree {}", &dt);
|
||||
crate::arch::sloop()
|
||||
}
|
||||
|
||||
|
@ -63,3 +47,8 @@ pub const SCHEDULER: Lazy<Mutex<Scheduler>> = Lazy::new(|| {
|
|||
let mut sch = Scheduler::new();
|
||||
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 arch;
|
||||
pub mod device_tree;
|
||||
pub mod handle;
|
||||
pub mod interp;
|
||||
mod kmain;
|
||||
|
@ -23,6 +24,7 @@ mod logger;
|
|||
mod memory;
|
||||
mod schedule;
|
||||
mod task;
|
||||
pub mod utils;
|
||||
|
||||
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
|
||||
|
||||
DEFAULT_ENTRY=1
|
||||
TIMEOUT=50
|
||||
TIMEOUT=0
|
||||
VERBOSE=yes
|
||||
INTERFACE_RESOLUTION=1024x768
|
||||
# Terminal related settings
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use error_stack::{bail, report, Context, IntoReport, Result, ResultExt};
|
||||
use fatfs::{FileSystem, FormatVolumeOptions, FsOptions, ReadWriteSeek};
|
||||
use std::{fmt::Display, fs::File, io, path::Path, process::Command};
|
||||
use {
|
||||
error_stack::{bail, report, Context, IntoReport, Result, ResultExt},
|
||||
fatfs::{FileSystem, FormatVolumeOptions, FsOptions, ReadWriteSeek},
|
||||
std::{fmt::Display, fs::File, io, path::Path, process::Command},
|
||||
};
|
||||
|
||||
fn main() -> Result<(), Error> {
|
||||
env_logger::init();
|
||||
|
@ -153,19 +155,32 @@ fn run(release: bool, target: Target) -> Result<(), Error> {
|
|||
if target == Target::X86_64 {
|
||||
#[rustfmt::skip]
|
||||
com.args([
|
||||
|
||||
|
||||
|
||||
|
||||
"-bios",
|
||||
std::env::var("REPBUILD_QEMU_FIRMWARE_PATH")
|
||||
.as_deref()
|
||||
.unwrap_or("/usr/share/ovmf/x64/OVMF_CODE.fd"),
|
||||
"-drive", "file=target/disk.img,format=raw",
|
||||
"-m", "4G",
|
||||
"-serial", "stdio",
|
||||
"-smp", "cores=2",
|
||||
// "-serial", "stdio",
|
||||
"-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")]
|
||||
{
|
||||
com.args(["-enable-kvm", "-cpu", "host"]);
|
||||
// com.args(["-enable-kvm", "-cpu", "host"]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue