mycelium_kernel/arch/x86_64/
shell.rs

1use crate::shell::{Command, NumberFormat};
2use hal_x86_64::control_regs;
3use mycelium_util::fmt;
4
5pub const DUMP_ARCH: Command = Command::new("arch")
6    .with_help("dump architecture-specific structures")
7    .with_subcommands(&[
8        Command::new("gdt")
9            .with_help("print the global descriptor table (GDT)")
10            .with_fn(|_| {
11                let gdt = super::interrupt::GDT.get();
12                tracing::info!(GDT = ?gdt);
13                Ok(())
14            }),
15        Command::new("idt")
16            .with_help("print the interrupt descriptor table (IDT)")
17            .with_fn(|_| {
18                let idt = super::interrupt::Controller::idt();
19                tracing::info!(IDT = ?idt);
20                Ok(())
21            }),
22        Command::new("msr")
23            .with_help(
24                "print the value of the specified model-specific register (MSR)\n           \
25                MSR_NUM: the MSR number in hexadecimal or binary\n           \
26                -f, --fmt <hex|bin|dec>: format the value of the MSR in hexadecimal, \
27                decimal, or binary.",
28            )
29            .with_usage("[-f|--fmt] <MSR_NUM>")
30            .with_fn(|mut ctx| {
31                let fmt = ctx
32                    .parse_optional_flag::<NumberFormat>(&["-f", "--fmt"])?
33                    .unwrap_or(NumberFormat::Hex);
34                let num = ctx.parse_u32_hex_or_dec("<MSR_NUM>")?;
35
36                let msr = hal_x86_64::cpu::msr::Msr::try_new(num).ok_or_else(|| {
37                    ctx.other_error(
38                        "CPU does not support model-specific registers (must be pre-pentium...)",
39                    )
40                })?;
41
42                let val = msr.read_raw();
43                match fmt {
44                    NumberFormat::Binary => tracing::info!("MSR {num:#x} = {val:#b}"),
45                    NumberFormat::Decimal => tracing::info!("MSR {num:#x} = {val}"),
46                    NumberFormat::Hex => tracing::info!("MSR {num:#x} = {val:#x}"),
47                }
48                Ok(())
49            }),
50        Command::new("cpuid")
51            .with_help(
52                "print the value of the specified CPUID leaf (and subleaf)\n           \
53                LEAF: the CPUID leaf number in hexadecimal or binary\n           \
54                SUBLEAF: the CPUID subleaf number in hexadecimal or binary\n           \
55                -f, --fmt <hex|bin|dec>: format the values of the CPUID registers in hexadecimal, \
56                decimal, or binary.",
57            )
58            .with_usage("[-f|--fmt] <LEAF> [SUBLEAF]")
59            .with_fn(|mut ctx| {
60                use core::arch::x86_64::{CpuidResult, __cpuid_count};
61                let fmt = ctx
62                    .parse_optional_flag::<NumberFormat>(&["-f", "--fmt"])?
63                    .unwrap_or(NumberFormat::Hex);
64                let leaf = ctx.parse_u32_hex_or_dec("<LEAF>")?;
65                let subleaf = ctx.parse_optional_u32_hex_or_dec("[SUBLEAF]")?.unwrap_or(0);
66
67                let CpuidResult { eax, ebx, ecx, edx } = unsafe { __cpuid_count(leaf, subleaf) };
68                match fmt {
69                    NumberFormat::Binary => tracing::info!(
70                        target: "shell",
71                        eax = fmt::bin(eax),
72                        ebx = fmt::bin(ebx),
73                        ecx = fmt::bin(ecx),
74                        edx = fmt::bin(edx),
75                        "CPUID {leaf:#x}:{subleaf:x}",
76                    ),
77                    NumberFormat::Decimal => tracing::info!(
78                        target: "shell", eax, ebx, ecx, edx,
79                        "CPUID {leaf:#x}:{subleaf:x}",
80                    ),
81                    NumberFormat::Hex => tracing::info!(
82                        target: "shell",
83                        eax = fmt::hex(eax),
84                        ebx = fmt::hex(ebx),
85                        ecx = fmt::hex(ecx),
86                        edx = fmt::hex(edx),
87                        "CPUID {leaf:#x}:{subleaf:x}",
88                    ),
89                }
90                Ok(())
91            }),
92        Command::new("cr0")
93            .with_help("print the value of control register CR0")
94            .with_fn(|_| {
95                tracing::info!(
96                    target: "shell",
97                    "CR0:\n{}",
98                    control_regs::Cr0::read(),
99                );
100                Ok(())
101            }),
102        Command::new("cr2")
103            .with_help("print the value of control register CR2")
104            .with_fn(|_| {
105                tracing::info!(
106                    target: "shell",
107                    cr2 = ?control_regs::Cr2::read(),
108                    "CR2",
109                );
110                Ok(())
111            }),
112        Command::new("cr3")
113            .with_help("print the value of control register CR3")
114            .with_fn(|_| {
115                let (page, flags) = control_regs::cr3::read();
116                tracing::info!(target: "shell", ?page, ?flags, "CR3");
117                Ok(())
118            }),
119        Command::new("cr4")
120            .with_help("print the value of control register CR4")
121            .with_fn(|_| {
122                tracing::info!(
123                    target: "shell",
124                    "CR4\n{}",
125                    control_regs::Cr4::read(),
126                );
127                Ok(())
128            }),
129    ]);