//! x86 port I/O and model-specific registers — the low-level primitives the //! serial port and the APIC talk to hardware through. pub fn outb(port: u16, value: u8) void { asm volatile ("outb %[value], %[port]" : : [value] "{al}" (value), [port] "{dx}" (port), ); } pub fn inb(port: u16) u8 { return asm volatile ("inb %[port], %[value]" : [value] "={al}" (-> u8), : [port] "{dx}" (port), ); } pub fn outw(port: u16, value: u16) void { asm volatile ("outw %[value], %[port]" : : [value] "{ax}" (value), [port] "{dx}" (port), ); } pub fn inw(port: u16) u16 { return asm volatile ("inw %[port], %[value]" : [value] "={ax}" (-> u16), : [port] "{dx}" (port), ); } pub fn outl(port: u16, value: u32) void { asm volatile ("outl %[value], %[port]" : : [value] "{eax}" (value), [port] "{dx}" (port), ); } pub fn inl(port: u16) u32 { return asm volatile ("inl %[port], %[value]" : [value] "={eax}" (-> u32), : [port] "{dx}" (port), ); } /// Read a model-specific register (returns edx:eax combined). pub fn rdmsr(msr: u32) u64 { var low: u32 = undefined; var high: u32 = undefined; asm volatile ("rdmsr" : [low] "={eax}" (low), [high] "={edx}" (high), : [msr] "{ecx}" (msr), ); return (@as(u64, high) << 32) | low; } pub fn wrmsr(msr: u32, value: u64) void { asm volatile ("wrmsr" : : [msr] "{ecx}" (msr), [low] "{eax}" (@as(u32, @truncate(value))), [high] "{edx}" (@as(u32, @truncate(value >> 32))), ); }