]> rtime.felk.cvut.cz Git - jailhouse.git/blob - hypervisor/include/jailhouse/mmio.h
core: Add generic MMIO access dispatching
[jailhouse.git] / hypervisor / include / jailhouse / mmio.h
1 /*
2  * Jailhouse, a Linux-based partitioning hypervisor
3  *
4  * Copyright (c) Siemens AG, 2013-2015
5  *
6  * Authors:
7  *  Jan Kiszka <jan.kiszka@siemens.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2.  See
10  * the COPYING file in the top-level directory.
11  */
12
13 #ifndef _JAILHOUSE_MMIO_H
14 #define _JAILHOUSE_MMIO_H
15
16 #include <jailhouse/types.h>
17 #include <asm/mmio.h>
18
19 struct cell;
20
21 /**
22  * @defgroup IO I/O Access Subsystem
23  *
24  * This subsystem provides accessors to I/O and supports the interpretation and
25  * handling of intercepted I/O accesses performed by cells.
26  *
27  * @{
28  */
29
30 /**
31  * Define MMIO read accessor.
32  * @param size          Access size.
33  */
34 #define DEFINE_MMIO_READ(size)                                          \
35 static inline u##size mmio_read##size(void *address)                    \
36 {                                                                       \
37         return *(volatile u##size *)address;                            \
38 }
39
40 /**
41  * Read 8, 16, 32 or 64-bit value from a memory-mapped I/O register.
42  * @param address       Virtual address of the register.
43  *
44  * @return Read value.
45  * @{
46  */
47 DEFINE_MMIO_READ(8)
48 DEFINE_MMIO_READ(16)
49 DEFINE_MMIO_READ(32)
50 DEFINE_MMIO_READ(64)
51 /** @} */
52
53 /**
54  * Define MMIO write accessor.
55  * @param size          Access size.
56  */
57 #define DEFINE_MMIO_WRITE(size)                                         \
58 static inline void mmio_write##size(void *address, u##size value)       \
59 {                                                                       \
60         *(volatile u##size *)address = value;                           \
61 }
62
63 /**
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.
67  * @{
68  */
69 DEFINE_MMIO_WRITE(8)
70 DEFINE_MMIO_WRITE(16)
71 DEFINE_MMIO_WRITE(32)
72 DEFINE_MMIO_WRITE(64)
73 /** @} */
74
75 /**
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
79  *                      must be set.
80  *
81  * @return Field value of register, shifted so that the first non-zero bit in
82  *         @c mask becomes bit 0.
83  * @{
84  */
85 static inline u32 mmio_read32_field(void *address, u32 mask)
86 {
87         return (mmio_read32(address) & mask) >> (__builtin_ffs(mask) - 1);
88 }
89
90 static inline u64 mmio_read64_field(void *address, u64 mask)
91 {
92         return (mmio_read64(address) & mask) >> (__builtin_ffsl(mask) - 1);
93 }
94 /** @} */
95
96 /**
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
100  *                      must be set.
101  * @param value         Register field value.
102  *
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.
105  * @{
106  */
107 static inline void mmio_write32_field(void *address, u32 mask, u32 value)
108 {
109         mmio_write32(address, (mmio_read32(address) & ~mask) |
110                         ((value << (__builtin_ffs(mask) - 1)) & mask));
111 }
112
113 static inline void mmio_write64_field(void *address, u64 mask, u64 value)
114 {
115         mmio_write64(address, (mmio_read64(address) & ~mask) |
116                         ((value << (__builtin_ffsl(mask) - 1)) & mask));
117 }
118 /** @} */
119
120 /** MMIO access result. */
121 enum mmio_result {MMIO_ERROR = -1, MMIO_UNHANDLED, MMIO_HANDLED};
122
123 /** MMIO access description. */
124 struct mmio_access {
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. */
129         unsigned int size;
130         /** True if write access. */
131         bool is_write;
132         /** The value to be written or the read value to return. */
133         unsigned long value;
134 };
135
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.
140  *
141  * @return MMIO_HANDLED on success, MMIO_ERROR otherwise.
142  */
143 typedef enum mmio_result (*mmio_handler)(void *arg, struct mmio_access *mmio);
144
145 /** MMIO region coordinates. */
146 struct mmio_region_location {
147         /** Start address of the region. */
148         unsigned long start;
149         /** Region size. */
150         unsigned long size;
151 };
152
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. */
158         void *arg;
159 };
160
161 int mmio_cell_init(struct cell *cell);
162
163 void mmio_region_register(struct cell *cell, unsigned long start,
164                           unsigned long size, mmio_handler handler,
165                           void *handler_arg);
166 void mmio_region_unregister(struct cell *cell, unsigned long start);
167
168 enum mmio_result mmio_handle_access(struct mmio_access *mmio);
169
170 void mmio_cell_exit(struct cell *cell);
171
172 unsigned int arch_mmio_count_regions(struct cell *cell);
173
174 /** @} */
175 #endif /* !_JAILHOUSE_MMIO_H */