aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2012-05-30 16:18:53 -0400
committerJoerg Roedel <joerg.roedel@amd.com>2012-06-25 07:48:15 -0400
commitd72e31c9374627068df29da8085ca18c92ae35d3 (patch)
treeed8bb77e31c0dd2c2b9c84d31ef6860c6ff03e51 /include/linux
parent74416e1e07660798379ce10a210bf4fd35b84f9f (diff)
iommu: IOMMU Groups
IOMMU device groups are currently a rather vague associative notion with assembly required by the user or user level driver provider to do anything useful. This patch intends to grow the IOMMU group concept into something a bit more consumable. To do this, we first create an object representing the group, struct iommu_group. This structure is allocated (iommu_group_alloc) and filled (iommu_group_add_device) by the iommu driver. The iommu driver is free to add devices to the group using it's own set of policies. This allows inclusion of devices based on physical hardware or topology limitations of the platform, as well as soft requirements, such as multi-function trust levels or peer-to-peer protection of the interconnects. Each device may only belong to a single iommu group, which is linked from struct device.iommu_group. IOMMU groups are maintained using kobject reference counting, allowing for automatic removal of empty, unreferenced groups. It is the responsibility of the iommu driver to remove devices from the group (iommu_group_remove_device). IOMMU groups also include a userspace representation in sysfs under /sys/kernel/iommu_groups. When allocated, each group is given a dynamically assign ID (int). The ID is managed by the core IOMMU group code to support multiple heterogeneous iommu drivers, which could potentially collide in group naming/numbering. This also keeps group IDs to small, easily managed values. A directory is created under /sys/kernel/iommu_groups for each group. A further subdirectory named "devices" contains links to each device within the group. The iommu_group file in the device's sysfs directory, which formerly contained a group number when read, is now a link to the iommu group. Example: $ ls -l /sys/kernel/iommu_groups/26/devices/ total 0 lrwxrwxrwx. 1 root root 0 Apr 17 12:57 0000:00:1e.0 -> ../../../../devices/pci0000:00/0000:00:1e.0 lrwxrwxrwx. 1 root root 0 Apr 17 12:57 0000:06:0d.0 -> ../../../../devices/pci0000:00/0000:00:1e.0/0000:06:0d.0 lrwxrwxrwx. 1 root root 0 Apr 17 12:57 0000:06:0d.1 -> ../../../../devices/pci0000:00/0000:00:1e.0/0000:06:0d.1 $ ls -l /sys/kernel/iommu_groups/26/devices/*/iommu_group [truncating perms/owner/timestamp] /sys/kernel/iommu_groups/26/devices/0000:00:1e.0/iommu_group -> ../../../kernel/iommu_groups/26 /sys/kernel/iommu_groups/26/devices/0000:06:0d.0/iommu_group -> ../../../../kernel/iommu_groups/26 /sys/kernel/iommu_groups/26/devices/0000:06:0d.1/iommu_group -> ../../../../kernel/iommu_groups/26 Groups also include several exported functions for use by user level driver providers, for example VFIO. These include: iommu_group_get(): Acquires a reference to a group from a device iommu_group_put(): Releases reference iommu_group_for_each_dev(): Iterates over group devices using callback iommu_group_[un]register_notifier(): Allows notification of device add and remove operations relevant to the group iommu_group_id(): Return the group number This patch also extends the IOMMU API to allow attaching groups to domains. This is currently a simple wrapper for iterating through devices within a group, but it's expected that the IOMMU API may eventually make groups a more integral part of domains. Groups intentionally do not try to manage group ownership. A user level driver provider must independently acquire ownership for each device within a group before making use of the group as a whole. This may change in the future if group usage becomes more pervasive across both DMA and IOMMU ops. Groups intentionally do not provide a mechanism for driver locking or otherwise manipulating driver matching/probing of devices within the group. Such interfaces are generic to devices and beyond the scope of IOMMU groups. If implemented, user level providers have ready access via iommu_group_for_each_dev and group notifiers. iommu_device_group() is removed here as it has no users. The replacement is: group = iommu_group_get(dev); id = iommu_group_id(group); iommu_group_put(group); AMD-Vi & Intel VT-d support re-added in following patches. Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/iommu.h104
1 files changed, 101 insertions, 3 deletions
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 450293f6d68b..a71df92be992 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -26,6 +26,7 @@
26#define IOMMU_CACHE (4) /* DMA cache coherency */ 26#define IOMMU_CACHE (4) /* DMA cache coherency */
27 27
28struct iommu_ops; 28struct iommu_ops;
29struct iommu_group;
29struct bus_type; 30struct bus_type;
30struct device; 31struct device;
31struct iommu_domain; 32struct iommu_domain;
@@ -60,6 +61,8 @@ struct iommu_domain {
60 * @iova_to_phys: translate iova to physical address 61 * @iova_to_phys: translate iova to physical address
61 * @domain_has_cap: domain capabilities query 62 * @domain_has_cap: domain capabilities query
62 * @commit: commit iommu domain 63 * @commit: commit iommu domain
64 * @add_device: add device to iommu grouping
65 * @remove_device: remove device from iommu grouping
63 * @pgsize_bitmap: bitmap of supported page sizes 66 * @pgsize_bitmap: bitmap of supported page sizes
64 */ 67 */
65struct iommu_ops { 68struct iommu_ops {
@@ -75,10 +78,18 @@ struct iommu_ops {
75 unsigned long iova); 78 unsigned long iova);
76 int (*domain_has_cap)(struct iommu_domain *domain, 79 int (*domain_has_cap)(struct iommu_domain *domain,
77 unsigned long cap); 80 unsigned long cap);
78 int (*device_group)(struct device *dev, unsigned int *groupid); 81 int (*add_device)(struct device *dev);
82 void (*remove_device)(struct device *dev);
79 unsigned long pgsize_bitmap; 83 unsigned long pgsize_bitmap;
80}; 84};
81 85
86#define IOMMU_GROUP_NOTIFY_ADD_DEVICE 1 /* Device added */
87#define IOMMU_GROUP_NOTIFY_DEL_DEVICE 2 /* Pre Device removed */
88#define IOMMU_GROUP_NOTIFY_BIND_DRIVER 3 /* Pre Driver bind */
89#define IOMMU_GROUP_NOTIFY_BOUND_DRIVER 4 /* Post Driver bind */
90#define IOMMU_GROUP_NOTIFY_UNBIND_DRIVER 5 /* Pre Driver unbind */
91#define IOMMU_GROUP_NOTIFY_UNBOUND_DRIVER 6 /* Post Driver unbind */
92
82extern int bus_set_iommu(struct bus_type *bus, struct iommu_ops *ops); 93extern int bus_set_iommu(struct bus_type *bus, struct iommu_ops *ops);
83extern bool iommu_present(struct bus_type *bus); 94extern bool iommu_present(struct bus_type *bus);
84extern struct iommu_domain *iommu_domain_alloc(struct bus_type *bus); 95extern struct iommu_domain *iommu_domain_alloc(struct bus_type *bus);
@@ -97,7 +108,29 @@ extern int iommu_domain_has_cap(struct iommu_domain *domain,
97 unsigned long cap); 108 unsigned long cap);
98extern void iommu_set_fault_handler(struct iommu_domain *domain, 109extern void iommu_set_fault_handler(struct iommu_domain *domain,
99 iommu_fault_handler_t handler, void *token); 110 iommu_fault_handler_t handler, void *token);
100extern int iommu_device_group(struct device *dev, unsigned int *groupid); 111
112extern int iommu_attach_group(struct iommu_domain *domain,
113 struct iommu_group *group);
114extern void iommu_detach_group(struct iommu_domain *domain,
115 struct iommu_group *group);
116extern struct iommu_group *iommu_group_alloc(void);
117extern void *iommu_group_get_iommudata(struct iommu_group *group);
118extern void iommu_group_set_iommudata(struct iommu_group *group,
119 void *iommu_data,
120 void (*release)(void *iommu_data));
121extern int iommu_group_set_name(struct iommu_group *group, const char *name);
122extern int iommu_group_add_device(struct iommu_group *group,
123 struct device *dev);
124extern void iommu_group_remove_device(struct device *dev);
125extern int iommu_group_for_each_dev(struct iommu_group *group, void *data,
126 int (*fn)(struct device *, void *));
127extern struct iommu_group *iommu_group_get(struct device *dev);
128extern void iommu_group_put(struct iommu_group *group);
129extern int iommu_group_register_notifier(struct iommu_group *group,
130 struct notifier_block *nb);
131extern int iommu_group_unregister_notifier(struct iommu_group *group,
132 struct notifier_block *nb);
133extern int iommu_group_id(struct iommu_group *group);
101 134
102/** 135/**
103 * report_iommu_fault() - report about an IOMMU fault to the IOMMU framework 136 * report_iommu_fault() - report about an IOMMU fault to the IOMMU framework
@@ -142,6 +175,7 @@ static inline int report_iommu_fault(struct iommu_domain *domain,
142#else /* CONFIG_IOMMU_API */ 175#else /* CONFIG_IOMMU_API */
143 176
144struct iommu_ops {}; 177struct iommu_ops {};
178struct iommu_group {};
145 179
146static inline bool iommu_present(struct bus_type *bus) 180static inline bool iommu_present(struct bus_type *bus)
147{ 181{
@@ -197,11 +231,75 @@ static inline void iommu_set_fault_handler(struct iommu_domain *domain,
197{ 231{
198} 232}
199 233
200static inline int iommu_device_group(struct device *dev, unsigned int *groupid) 234int iommu_attach_group(struct iommu_domain *domain, struct iommu_group *group)
235{
236 return -ENODEV;
237}
238
239void iommu_detach_group(struct iommu_domain *domain, struct iommu_group *group)
240{
241}
242
243struct iommu_group *iommu_group_alloc(void)
244{
245 return ERR_PTR(-ENODEV);
246}
247
248void *iommu_group_get_iommudata(struct iommu_group *group)
249{
250 return NULL;
251}
252
253void iommu_group_set_iommudata(struct iommu_group *group, void *iommu_data,
254 void (*release)(void *iommu_data))
255{
256}
257
258int iommu_group_set_name(struct iommu_group *group, const char *name)
259{
260 return -ENODEV;
261}
262
263int iommu_group_add_device(struct iommu_group *group, struct device *dev)
264{
265 return -ENODEV;
266}
267
268void iommu_group_remove_device(struct device *dev)
269{
270}
271
272int iommu_group_for_each_dev(struct iommu_group *group, void *data,
273 int (*fn)(struct device *, void *))
274{
275 return -ENODEV;
276}
277
278struct iommu_group *iommu_group_get(struct device *dev)
279{
280 return NULL;
281}
282
283void iommu_group_put(struct iommu_group *group)
284{
285}
286
287int iommu_group_register_notifier(struct iommu_group *group,
288 struct notifier_block *nb)
201{ 289{
202 return -ENODEV; 290 return -ENODEV;
203} 291}
204 292
293int iommu_group_unregister_notifier(struct iommu_group *group,
294 struct notifier_block *nb)
295{
296 return 0;
297}
298
299int iommu_group_id(struct iommu_group *group)
300{
301 return -ENODEV;
302}
205#endif /* CONFIG_IOMMU_API */ 303#endif /* CONFIG_IOMMU_API */
206 304
207#endif /* __LINUX_IOMMU_H */ 305#endif /* __LINUX_IOMMU_H */