x86/
io.rs

1//! I/O port functionality.
2
3use core::arch::asm;
4
5/// Write 8 bits to port
6///
7/// # Safety
8/// Needs IO privileges.
9#[inline]
10pub unsafe fn outb(port: u16, val: u8) {
11    asm!("outb %al, %dx", in("al") val, in("dx") port, options(att_syntax));
12}
13
14/// Read 8 bits from port
15///
16/// # Safety
17/// Needs IO privileges.
18#[inline]
19pub unsafe fn inb(port: u16) -> u8 {
20    let ret: u8;
21    asm!("inb %dx, %al", in("dx") port, out("al") ret, options(att_syntax));
22    ret
23}
24
25/// Write 16 bits to port
26///
27/// # Safety
28/// Needs IO privileges.
29#[inline]
30pub unsafe fn outw(port: u16, val: u16) {
31    asm!("outw %ax, %dx", in("ax") val, in("dx") port, options(att_syntax));
32}
33
34/// Read 16 bits from port
35///
36/// # Safety
37/// Needs IO privileges.
38#[inline]
39pub unsafe fn inw(port: u16) -> u16 {
40    let ret: u16;
41    asm!("inw %dx, %ax", in("dx") port, out("ax") ret, options(att_syntax));
42    ret
43}
44
45/// Write 32 bits to port
46///
47/// # Safety
48/// Needs IO privileges.
49#[inline]
50pub unsafe fn outl(port: u16, val: u32) {
51    asm!("outl %eax, %dx", in("eax") val, in("dx") port, options(att_syntax));
52}
53
54/// Read 32 bits from port
55///
56/// # Safety
57/// Needs IO privileges.
58#[inline]
59pub unsafe fn inl(port: u16) -> u32 {
60    let ret: u32;
61    asm!("inl %dx, %eax", out("eax") ret, in("dx") port, options(att_syntax));
62    ret
63}
64
65#[cfg(all(test, feature = "vmtest"))]
66mod x86testing {
67    use super::*;
68    use x86test::*;
69
70    #[x86test(ioport(0x0, 0xaf))]
71    fn check_outb() {
72        unsafe {
73            outb(0x0, 0xaf);
74            // hypervisor will fail here if port 0x0 doesn't see 0xaf
75        }
76    }
77
78    #[x86test(ioport(0x0, 0xaf))]
79    #[should_panic]
80    fn check_outb_wrong_value() {
81        unsafe {
82            outb(0x0, 0xff);
83        }
84    }
85
86    #[x86test(ioport(0x1, 0xad))]
87    fn check_inb() {
88        unsafe {
89            kassert!(
90                inb(0x1) == 0xad,
91                "`inb` instruction didn't read the correct value"
92            );
93        }
94    }
95
96    #[x86test(ioport(0x2, 0xad))]
97    #[should_panic]
98    fn check_inb_wrong_port() {
99        unsafe {
100            kassert!(
101                inb(0x1) == 0xad,
102                "`inb` instruction didn't read the correct value"
103            );
104        }
105    }
106
107    #[x86test(ioport(0x2, 0x99))]
108    fn check_outw() {
109        unsafe {
110            super::outw(0x2, 0x99);
111            // hypervisor will fail here if port 0x2 doesn't see 0x99
112        }
113    }
114
115    #[x86test(ioport(0x3, 0xfefe))]
116    fn check_inw() {
117        unsafe {
118            kassert!(
119                inw(0x3) == 0xfefe,
120                "`inw` instruction didn't read the correct value"
121            );
122        }
123    }
124
125    #[x86test(ioport(0x5, 0xbeefaaaa))]
126    fn check_outl() {
127        unsafe {
128            outl(0x5, 0xbeefaaaa);
129            // hypervisor will fail here if port 0x5 doesn't see 0xbeefaaaa
130        }
131    }
132
133    #[x86test(ioport(0x4, 0xdeadbeef))]
134    fn check_inl() {
135        unsafe {
136            kassert!(
137                inl(0x4) == 0xdeadbeef,
138                "`inl` instruction didn't read the correct value"
139            );
140        }
141    }
142}