ia64/xen-unstable

view xen/include/xen/grant_table.h @ 19658:28a197617286

Fix up the synchronisation around grant table map track handles.
At present, we're not doing any at all, so if a domain e.g. tries to
do two map operations at the same time from different vcpus then you
could end up with both operations getting back the same maptrack
handle.

Fix this problem by just shoving an enormous lock around grant table
operations. This is unlikely to be heavily contended, because netback
and blkback both restrict themselves to mapping on a single vcpu at a
time (globally for netback, and per-device for blkback), and most of
the interesting bits are already protected by the remote domain's
grant table lock anyway.

The unconteded acquisition cost might be significant for some
workloads. If that were the case, it might be worth only acquiring
the lock only for multi-vcpu domains, since we only manipulate the
maptrack table in the context of one of the domain's vcpus. I've not
done that optimisation here, because I didn't want to think about what
would happen if e.g. a cpu got hot-unplugged from a domain while it
was performing a map operation.

Signed-off-by: Steven Smith <steven.smith@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed May 27 11:29:38 2009 +0100 (2009-05-27)
parents d8d0f32090cb
children 2e83c670f680
line source
1 /******************************************************************************
2 * include/xen/grant_table.h
3 *
4 * Mechanism for granting foreign access to page frames, and receiving
5 * page-ownership transfers.
6 *
7 * Copyright (c) 2004-2005 K A Fraser
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
24 #ifndef __XEN_GRANT_TABLE_H__
25 #define __XEN_GRANT_TABLE_H__
27 #include <xen/config.h>
28 #include <public/grant_table.h>
29 #include <asm/grant_table.h>
31 /* Active grant entry - used for shadowing GTF_permit_access grants. */
32 struct active_grant_entry {
33 u32 pin; /* Reference count information. */
34 domid_t domid; /* Domain being granted access. */
35 unsigned long gfn; /* Guest's idea of the frame being granted. */
36 unsigned long frame; /* Frame being granted. */
37 };
39 /* Count of writable host-CPU mappings. */
40 #define GNTPIN_hstw_shift (0)
41 #define GNTPIN_hstw_inc (1 << GNTPIN_hstw_shift)
42 #define GNTPIN_hstw_mask (0xFFU << GNTPIN_hstw_shift)
43 /* Count of read-only host-CPU mappings. */
44 #define GNTPIN_hstr_shift (8)
45 #define GNTPIN_hstr_inc (1 << GNTPIN_hstr_shift)
46 #define GNTPIN_hstr_mask (0xFFU << GNTPIN_hstr_shift)
47 /* Count of writable device-bus mappings. */
48 #define GNTPIN_devw_shift (16)
49 #define GNTPIN_devw_inc (1 << GNTPIN_devw_shift)
50 #define GNTPIN_devw_mask (0xFFU << GNTPIN_devw_shift)
51 /* Count of read-only device-bus mappings. */
52 #define GNTPIN_devr_shift (24)
53 #define GNTPIN_devr_inc (1 << GNTPIN_devr_shift)
54 #define GNTPIN_devr_mask (0xFFU << GNTPIN_devr_shift)
56 /* Initial size of a grant table. */
57 #define INITIAL_NR_GRANT_ENTRIES ((INITIAL_NR_GRANT_FRAMES << PAGE_SHIFT) / \
58 sizeof(grant_entry_t))
60 #ifndef DEFAULT_MAX_NR_GRANT_FRAMES /* to allow arch to override */
61 /* Default maximum size of a grant table. [POLICY] */
62 #define DEFAULT_MAX_NR_GRANT_FRAMES 32
63 #endif
64 #ifndef max_nr_grant_frames /* to allow arch to override */
65 /* The maximum size of a grant table. */
66 extern unsigned int max_nr_grant_frames;
67 #endif
69 /*
70 * Tracks a mapping of another domain's grant reference. Each domain has a
71 * table of these, indexes into which are returned as a 'mapping handle'.
72 */
73 struct grant_mapping {
74 u32 ref; /* grant ref */
75 u16 flags; /* 0-4: GNTMAP_* ; 5-15: unused */
76 domid_t domid; /* granting domain */
77 };
79 /* Fairly arbitrary. [POLICY] */
80 #define MAPTRACK_MAX_ENTRIES 16384
82 /* Per-domain grant information. */
83 struct grant_table {
84 /* Table size. Number of frames shared with guest */
85 unsigned int nr_grant_frames;
86 /* Shared grant table (see include/public/grant_table.h). */
87 struct grant_entry **shared;
88 /* Active grant table. */
89 struct active_grant_entry **active;
90 /* Mapping tracking table. */
91 struct grant_mapping **maptrack;
92 unsigned int maptrack_head;
93 unsigned int maptrack_limit;
94 /* Lock protecting maptrack-related fields. */
95 spinlock_t maptrack_lock;
96 /* Lock protecting updates to active and shared grant tables. */
97 spinlock_t lock;
98 };
100 /* Create/destroy per-domain grant table context. */
101 int grant_table_create(
102 struct domain *d);
103 void grant_table_destroy(
104 struct domain *d);
106 /* Domain death release of granted mappings of other domains' memory. */
107 void
108 gnttab_release_mappings(
109 struct domain *d);
111 /* Increase the size of a domain's grant table.
112 * Caller must hold d's grant table lock.
113 */
114 int
115 gnttab_grow_table(struct domain *d, unsigned int req_nr_frames);
117 /* Number of grant table frames. Caller must hold d's grant table lock. */
118 static inline unsigned int nr_grant_frames(struct grant_table *gt)
119 {
120 return gt->nr_grant_frames;
121 }
123 /* Number of grant table entries. Caller must hold d's grant table lock. */
124 static inline unsigned int nr_grant_entries(struct grant_table *gt)
125 {
126 return (nr_grant_frames(gt) << PAGE_SHIFT) / sizeof(grant_entry_t);
127 }
129 static inline unsigned int
130 num_act_frames_from_sha_frames(const unsigned int num)
131 {
132 /* How many frames are needed for the active grant table,
133 * given the size of the shared grant table?
134 *
135 * act_per_page = PAGE_SIZE / sizeof(active_grant_entry_t);
136 * sha_per_page = PAGE_SIZE / sizeof(grant_entry_t);
137 * num_sha_entries = num * sha_per_page;
138 * num_act_frames = (num_sha_entries + (act_per_page-1)) / act_per_page;
139 */
140 return ((num * (PAGE_SIZE / sizeof(grant_entry_t))) +
141 ((PAGE_SIZE / sizeof(struct active_grant_entry))-1))
142 / (PAGE_SIZE / sizeof(struct active_grant_entry));
143 }
145 static inline unsigned int
146 nr_active_grant_frames(struct grant_table *gt)
147 {
148 return num_act_frames_from_sha_frames(nr_grant_frames(gt));
149 }
151 #endif /* __XEN_GRANT_TABLE_H__ */