From 9559c7672f2041772fdf187112530a2eeeaa852e Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Thu, 25 Sep 2014 13:54:09 +0200 Subject: [PATCH] core: Document I/O access subsystem This adds doxygen-style documentation for I/O access subsystem which covers MMIO as well as PIO. Signed-off-by: Jan Kiszka --- Documentation/Doxyfile | 4 +- hypervisor/arch/x86/include/asm/io.h | 51 ++++++++---- hypervisor/include/jailhouse/mmio.h | 113 +++++++++++++++++++-------- 3 files changed, 120 insertions(+), 48 deletions(-) diff --git a/Documentation/Doxyfile b/Documentation/Doxyfile index 3758b1a..4da26b1 100644 --- a/Documentation/Doxyfile +++ b/Documentation/Doxyfile @@ -265,7 +265,9 @@ INCLUDE_PATH = INCLUDE_FILE_PATTERNS = PREDEFINED = \ __attribute__(x)= \ - DEFINE_SPINLOCK(s)="spinlock_t s" + DEFINE_SPINLOCK(s)="spinlock_t s" \ + DEFINE_MMIO_READ(s)="static inline u##s mmio_read##s(void *address);" \ + DEFINE_MMIO_WRITE(s)="static inline void mmio_write##s(void *address, u##s value);" EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES TAGFILES = diff --git a/hypervisor/arch/x86/include/asm/io.h b/hypervisor/arch/x86/include/asm/io.h index 7bb0765..8b7fc03 100644 --- a/hypervisor/arch/x86/include/asm/io.h +++ b/hypervisor/arch/x86/include/asm/io.h @@ -12,11 +12,19 @@ #include -static inline void outb(u8 v, u16 port) -{ - asm volatile("outb %0,%1" : : "a" (v), "dN" (port)); -} +/** + * @ingroup IO + * @defgroup PIO x86 I/O Accessors + * @{ + */ +/** + * Read 8 (b), 16(w) or 32-bit (l) value from a port. + * @param port Port number. + * + * @return Read value. + * @{ + */ static inline u8 inb(u16 port) { u8 v; @@ -25,11 +33,6 @@ static inline u8 inb(u16 port) return v; } -static inline void outw(u16 value, u16 port) -{ - asm volatile("outw %w0,%w1" : : "a" (value), "Nd" (port)); -} - static inline u16 inw(u16 port) { u16 v; @@ -38,11 +41,6 @@ static inline u16 inw(u16 port) return v; } -static inline void outl(u32 value, u16 port) -{ - asm volatile("outl %0,%1" : : "a" (value), "Nd" (port)); -} - static inline u32 inl(u16 port) { u32 v; @@ -50,3 +48,28 @@ static inline u32 inl(u16 port) asm volatile("inl %1,%0" : "=a" (v) : "dN" (port)); return v; } +/** @} */ + +/** + * Write 8 (b), 16(w) or 32-bit (l) value to a port. + * @param value Value to write + * @param port Port number. + * @{ + */ +static inline void outb(u8 value, u16 port) +{ + asm volatile("outb %0,%1" : : "a" (value), "dN" (port)); +} + +static inline void outw(u16 value, u16 port) +{ + asm volatile("outw %w0,%w1" : : "a" (value), "Nd" (port)); +} + +static inline void outl(u32 value, u16 port) +{ + asm volatile("outl %0,%1" : : "a" (value), "Nd" (port)); +} +/** @} */ + +/** @} */ diff --git a/hypervisor/include/jailhouse/mmio.h b/hypervisor/include/jailhouse/mmio.h index 410487e..1777529 100644 --- a/hypervisor/include/jailhouse/mmio.h +++ b/hypervisor/include/jailhouse/mmio.h @@ -15,82 +15,129 @@ #include +/** + * @defgroup IO I/O Access Subsystem + * + * This subsystem provides accessors to I/O and supports the interpretation of + * intercepted I/O accesses of cells. + * + * @{ + */ + +/** Information about interpreted MMIO access. */ struct mmio_access { + /** Length of the MMIO access instruction, 0 for invalid or unsupported + * access. */ unsigned int inst_len; + /** Size of the access. */ unsigned int size; + /** Architecture-specific number of the register that holds the output + * value or should receive the input. */ unsigned int reg; }; +/** + * Define MMIO read accessor. + * @param size Access size. + */ #define DEFINE_MMIO_READ(size) \ static inline u##size mmio_read##size(void *address) \ { \ return *(volatile u##size *)address; \ } + +/** + * Read 8, 16, 32 or 64-bit value from a memory-mapped I/O register. + * @param address Virtual address of the register. + * + * @return Read value. + * @{ + */ DEFINE_MMIO_READ(8) DEFINE_MMIO_READ(16) DEFINE_MMIO_READ(32) DEFINE_MMIO_READ(64) +/** @} */ +/** + * Define MMIO write accessor. + * @param size Access size. + */ #define DEFINE_MMIO_WRITE(size) \ static inline void mmio_write##size(void *address, u##size value) \ { \ *(volatile u##size *)address = value; \ } + +/** + * Write 8, 16, 32 or 64-bit value to a memory-mapped I/O register. + * @param address Virtual address of the register. + * @param value Value to write. + * @{ + */ DEFINE_MMIO_WRITE(8) DEFINE_MMIO_WRITE(16) DEFINE_MMIO_WRITE(32) DEFINE_MMIO_WRITE(64) - -struct mmio_access mmio_parse(unsigned long pc, - const struct guest_paging_structures *pg_structs, - bool is_write); +/** @} */ /** - * mmio_read32_field() - Read value of 32-bit register field - * @addr: Register address. - * @mask: Bit mask. Shifted value must be provided which describes both - * starting bit position (1st non-zero bit) and length of the field. + * Read value from 32 or 64-bit MMIO register field. + * @param address Virtual address of the register. + * @param mask Bitmask to defining the field. Only successive bits + * must be set. * - * Return: Field value of register. + * @return Field value of register, shifted so that the first non-zero bit in + * @c mask becomes bit 0. + * @{ */ -static inline u32 mmio_read32_field(void *addr, u32 mask) +static inline u32 mmio_read32_field(void *address, u32 mask) { - return (mmio_read32(addr) & mask) >> (__builtin_ffs(mask) - 1); + return (mmio_read32(address) & mask) >> (__builtin_ffs(mask) - 1); } +static inline u64 mmio_read64_field(void *address, u64 mask) +{ + return (mmio_read64(address) & mask) >> (__builtin_ffsl(mask) - 1); +} +/** @} */ + /** - * mmio_write32_field() - Write value of 32-bit register field - * @addr: Register address. - * @mask: Bit mask. See mmio_read32_field() for more details. - * @value: Register field value (must be the same length as mask). + * Write value to 32 or 64-bit MMIO register field. + * @param address Virtual address of the register. + * @param mask Bitmask to defining the field. Only successive bits + * must be set. + * @param value Register field value. * - * Update field value of 32-bit register, leaving all other fields unmodified. - - * Return: None. + * This updates only the field value of the register, leaving all other + * register bits unmodified. Thus, it performs a read-modify-write cycle. + * @{ */ -static inline void mmio_write32_field(void *addr, u32 mask, u32 value) +static inline void mmio_write32_field(void *address, u32 mask, u32 value) { - mmio_write32(addr, (mmio_read32(addr) & ~mask) | + mmio_write32(address, (mmio_read32(address) & ~mask) | ((value << (__builtin_ffs(mask) - 1)) & mask)); } -/** - * mmio_read64_field() - Read value of 64-bit register field. - * See mmio_read32_field() for more details. - */ -static inline u64 mmio_read64_field(void *addr, u64 mask) +static inline void mmio_write64_field(void *address, u64 mask, u64 value) { - return (mmio_read64(addr) & mask) >> (__builtin_ffsl(mask) - 1); + mmio_write64(address, (mmio_read64(address) & ~mask) | + ((value << (__builtin_ffsl(mask) - 1)) & mask)); } +/** @} */ /** - * mmio_write64_field() - Write value of 64-bit register field. - * See mmio_write32_field() for more details. + * Parse an intercepted MMIO access of a cell CPU. + * @param pc Program counter of the access instruction. + * @param pg_structs Currently active guest (cell) paging structures. + * @param is_write True if write access, false for read. + * + * @return MMIO access information. mmio_access::inst_len is 0 on invalid or + * unsupported access. */ -static inline void mmio_write64_field(void *addr, u64 mask, u64 value) -{ - mmio_write64(addr, (mmio_read64(addr) & ~mask) | - ((value << (__builtin_ffsl(mask) - 1)) & mask)); -} +struct mmio_access mmio_parse(unsigned long pc, + const struct guest_paging_structures *pg_structs, + bool is_write); +/** @} */ #endif /* !_JAILHOUSE_MMIO_H */ -- 2.39.2