2 * Jailhouse, a Linux-based partitioning hypervisor
4 * Copyright (c) Siemens AG, 2013-2015
7 * Jan Kiszka <jan.kiszka@siemens.com>
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
13 #ifndef _JAILHOUSE_MMIO_H
14 #define _JAILHOUSE_MMIO_H
16 #include <jailhouse/types.h>
22 * @defgroup IO I/O Access Subsystem
24 * This subsystem provides accessors to I/O and supports the interpretation and
25 * handling of intercepted I/O accesses performed by cells.
31 * Define MMIO read accessor.
32 * @param size Access size.
34 #define DEFINE_MMIO_READ(size) \
35 static inline u##size mmio_read##size(void *address) \
37 return *(volatile u##size *)address; \
41 * Read 8, 16, 32 or 64-bit value from a memory-mapped I/O register.
42 * @param address Virtual address of the register.
54 * Define MMIO write accessor.
55 * @param size Access size.
57 #define DEFINE_MMIO_WRITE(size) \
58 static inline void mmio_write##size(void *address, u##size value) \
60 *(volatile u##size *)address = value; \
64 * Write 8, 16, 32 or 64-bit value to a memory-mapped I/O register.
65 * @param address Virtual address of the register.
66 * @param value Value to write.
76 * Read value from 32 or 64-bit MMIO register field.
77 * @param address Virtual address of the register.
78 * @param mask Bitmask to defining the field. Only successive bits
81 * @return Field value of register, shifted so that the first non-zero bit in
82 * @c mask becomes bit 0.
85 static inline u32 mmio_read32_field(void *address, u32 mask)
87 return (mmio_read32(address) & mask) >> (__builtin_ffs(mask) - 1);
90 static inline u64 mmio_read64_field(void *address, u64 mask)
92 return (mmio_read64(address) & mask) >> (__builtin_ffsl(mask) - 1);
97 * Write value to 32 or 64-bit MMIO register field.
98 * @param address Virtual address of the register.
99 * @param mask Bitmask to defining the field. Only successive bits
101 * @param value Register field value.
103 * This updates only the field value of the register, leaving all other
104 * register bits unmodified. Thus, it performs a read-modify-write cycle.
107 static inline void mmio_write32_field(void *address, u32 mask, u32 value)
109 mmio_write32(address, (mmio_read32(address) & ~mask) |
110 ((value << (__builtin_ffs(mask) - 1)) & mask));
113 static inline void mmio_write64_field(void *address, u64 mask, u64 value)
115 mmio_write64(address, (mmio_read64(address) & ~mask) |
116 ((value << (__builtin_ffsl(mask) - 1)) & mask));
120 /** MMIO access result. */
121 enum mmio_result {MMIO_ERROR = -1, MMIO_UNHANDLED, MMIO_HANDLED};
123 /** MMIO access description. */
125 /** Address to access, depending on the context, an absolute address or
126 * relative offset to region start. */
127 unsigned long address;
128 /** Size of the access. */
130 /** True if write access. */
132 /** The value to be written or the read value to return. */
136 /** MMIO callback handler.
137 * @param arg Opaque argument defined via mmio_region_register().
138 * @param mmio MMIO access description. @a mmio->address will be
139 * provided as offset to the region start.
141 * @return MMIO_HANDLED on success, MMIO_ERROR otherwise.
143 typedef enum mmio_result (*mmio_handler)(void *arg, struct mmio_access *mmio);
145 /** MMIO region coordinates. */
146 struct mmio_region_location {
147 /** Start address of the region. */
153 /** MMIO region access callback description. */
154 struct mmio_region_handler {
155 /** Access handler. */
156 mmio_handler handler;
157 /** Argument to pass to the handler. */
161 int mmio_cell_init(struct cell *cell);
163 void mmio_region_register(struct cell *cell, unsigned long start,
164 unsigned long size, mmio_handler handler,
166 void mmio_region_unregister(struct cell *cell, unsigned long start);
168 enum mmio_result mmio_handle_access(struct mmio_access *mmio);
170 void mmio_cell_exit(struct cell *cell);
172 unsigned int arch_mmio_count_regions(struct cell *cell);
175 #endif /* !_JAILHOUSE_MMIO_H */