win-pvdrivers

view xenpci/gnttbl.c @ 643:1794a52f415d

Added tag 0.10.0.94 for changeset 51de599aa482
author James Harper <james.harper@bendigoit.com.au>
date Mon Aug 24 21:21:37 2009 +1000 (2009-08-24)
parents a88fe72e3597
children 6300617040e0
line source
1 /*
2 PV Drivers for Windows Xen HVM Domains
3 Copyright (C) 2007 James Harper
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
20 #include "xenpci.h"
22 VOID
23 GntTbl_PutRef(PVOID Context, grant_ref_t ref)
24 {
25 PXENPCI_DEVICE_DATA xpdd = Context;
26 KIRQL old_irql = 0; /* prevents compiler warnings due to Acquire done in if statement */
28 if (xpdd->suspend_state != SUSPEND_STATE_HIGH_IRQL)
29 {
30 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
31 KeAcquireSpinLock(&xpdd->grant_lock, &old_irql);
32 }
33 xpdd->gnttab_list[xpdd->gnttab_list_free] = ref;
34 xpdd->gnttab_list_free++;
35 if (xpdd->suspend_state != SUSPEND_STATE_HIGH_IRQL)
36 {
37 KeReleaseSpinLock(&xpdd->grant_lock, old_irql);
38 }
39 }
41 grant_ref_t
42 GntTbl_GetRef(PVOID Context)
43 {
44 PXENPCI_DEVICE_DATA xpdd = Context;
45 unsigned int ref;
46 KIRQL old_irql = 0; /* prevents compiler warnings due to Acquire done in if statement */
47 int suspend_state = xpdd->suspend_state;
49 if (suspend_state != SUSPEND_STATE_HIGH_IRQL)
50 {
51 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
52 KeAcquireSpinLock(&xpdd->grant_lock, &old_irql);
53 }
54 if (!xpdd->gnttab_list_free)
55 {
56 if (suspend_state != SUSPEND_STATE_HIGH_IRQL)
57 KeReleaseSpinLock(&xpdd->grant_lock, old_irql);
58 KdPrint((__DRIVER_NAME " No free grant refs\n"));
59 return INVALID_GRANT_REF;
60 }
61 xpdd->gnttab_list_free--;
62 ref = xpdd->gnttab_list[xpdd->gnttab_list_free];
63 if (suspend_state != SUSPEND_STATE_HIGH_IRQL)
64 KeReleaseSpinLock(&xpdd->grant_lock, old_irql);
66 return ref;
67 }
69 int
70 GntTbl_Map(PVOID Context, unsigned int start_idx, unsigned int end_idx)
71 {
72 PXENPCI_DEVICE_DATA xpdd = Context;
73 struct xen_add_to_physmap xatp;
74 unsigned int i = end_idx;
76 /* Loop backwards, so that the first hypercall has the largest index, ensuring that the table will grow only once. */
77 do {
78 xatp.domid = DOMID_SELF;
79 xatp.idx = i;
80 xatp.space = XENMAPSPACE_grant_table;
81 xatp.gpfn = (xen_pfn_t)(xpdd->gnttab_table_physical.QuadPart >> PAGE_SHIFT) + i;
82 if (HYPERVISOR_memory_op(xpdd, XENMEM_add_to_physmap, &xatp))
83 {
84 KdPrint((__DRIVER_NAME " ***ERROR MAPPING FRAME***\n"));
85 }
86 } while (i-- > start_idx);
88 return 0;
89 }
91 grant_ref_t
92 GntTbl_GrantAccess(
93 PVOID Context,
94 domid_t domid,
95 uint32_t frame, // xen api limits pfn to 32bit, so no guests over 8TB
96 int readonly,
97 grant_ref_t ref)
98 {
99 PXENPCI_DEVICE_DATA xpdd = Context;
101 //KdPrint((__DRIVER_NAME " --> GntTbl_GrantAccess\n"));
103 //KdPrint((__DRIVER_NAME " Granting access to frame %08x\n", frame));
105 if (ref == INVALID_GRANT_REF)
106 ref = GntTbl_GetRef(Context);
107 if (ref == INVALID_GRANT_REF)
108 return ref;
110 xpdd->gnttab_table[ref].frame = frame;
111 xpdd->gnttab_table[ref].domid = domid;
113 if (xpdd->gnttab_table[ref].flags)
114 KdPrint((__DRIVER_NAME " WARNING: Attempting to re-use grant entry that is already in use!\n"));
115 ASSERT(!xpdd->gnttab_table[ref].flags);
117 KeMemoryBarrier();
118 readonly *= GTF_readonly;
119 xpdd->gnttab_table[ref].flags = GTF_permit_access | (uint16_t)readonly;
121 //KdPrint((__DRIVER_NAME " <-- GntTbl_GrantAccess (ref = %d)\n", ref));
123 return ref;
124 }
126 BOOLEAN
127 GntTbl_EndAccess(
128 PVOID Context,
129 grant_ref_t ref,
130 BOOLEAN keepref)
131 {
132 PXENPCI_DEVICE_DATA xpdd = Context;
133 unsigned short flags, nflags;
135 //KdPrint((__DRIVER_NAME " --> GntTbl_EndAccess\n"));
137 ASSERT(ref != INVALID_GRANT_REF);
139 nflags = xpdd->gnttab_table[ref].flags;
140 do {
141 if ((flags = nflags) & (GTF_reading|GTF_writing))
142 {
143 KdPrint((__DRIVER_NAME " WARNING: g.e. %d still in use!\n", ref));
144 return FALSE;
145 }
146 } while ((nflags = InterlockedCompareExchange16(
147 (volatile SHORT *)&xpdd->gnttab_table[ref].flags, 0, flags)) != flags);
149 if (!keepref)
150 GntTbl_PutRef(Context, ref);
151 //KdPrint((__DRIVER_NAME " <-- GntTbl_EndAccess\n"));
152 return TRUE;
153 }
155 static unsigned int
156 GntTbl_QueryMaxFrames(PXENPCI_DEVICE_DATA xpdd)
157 {
158 struct gnttab_query_size query;
159 int rc;
161 query.dom = DOMID_SELF;
163 rc = HYPERVISOR_grant_table_op(xpdd, GNTTABOP_query_size, &query, 1);
164 if ((rc < 0) || (query.status != GNTST_okay))
165 {
166 KdPrint((__DRIVER_NAME " ***CANNOT QUERY MAX GRANT FRAME***\n"));
167 return 4; /* Legacy max supported number of frames */
168 }
169 return query.max_nr_frames;
170 }
172 VOID
173 GntTbl_Init(PXENPCI_DEVICE_DATA xpdd)
174 {
175 int i;
176 int grant_entries;
178 FUNCTION_ENTER();
180 KeInitializeSpinLock(&xpdd->grant_lock);
182 xpdd->grant_frames = GntTbl_QueryMaxFrames(xpdd);
183 KdPrint((__DRIVER_NAME " grant_frames = %d\n", xpdd->grant_frames));
184 grant_entries = min(NR_GRANT_ENTRIES, (xpdd->grant_frames * PAGE_SIZE / sizeof(grant_entry_t)));
185 KdPrint((__DRIVER_NAME " grant_entries = %d\n", grant_entries));
187 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
188 xpdd->gnttab_table_copy = ExAllocatePoolWithTag(NonPagedPool, xpdd->grant_frames * PAGE_SIZE, XENPCI_POOL_TAG);
189 ASSERT(xpdd->gnttab_table_copy); // lazy
190 xpdd->gnttab_list = ExAllocatePoolWithTag(NonPagedPool, sizeof(grant_ref_t) * grant_entries, XENPCI_POOL_TAG);
191 ASSERT(xpdd->gnttab_list); // lazy
192 xpdd->gnttab_table_physical = XenPci_AllocMMIO(xpdd, PAGE_SIZE * xpdd->grant_frames);
193 xpdd->gnttab_table = MmMapIoSpace(xpdd->gnttab_table_physical, PAGE_SIZE * xpdd->grant_frames, MmNonCached);
194 if (!xpdd->gnttab_table)
195 {
196 KdPrint((__DRIVER_NAME " Error Mapping Grant Table Shared Memory\n"));
197 // this should be a show stopper...
198 return;
199 }
201 RtlZeroMemory(xpdd->gnttab_list, sizeof(grant_ref_t) * grant_entries);
202 xpdd->gnttab_list_free = 0;
203 for (i = NR_RESERVED_ENTRIES; i < grant_entries; i++)
204 GntTbl_PutRef(xpdd, i);
206 GntTbl_Map(xpdd, 0, xpdd->grant_frames - 1);
208 RtlZeroMemory(xpdd->gnttab_table, PAGE_SIZE * xpdd->grant_frames);
210 FUNCTION_EXIT();
211 }
213 VOID
214 GntTbl_Suspend(PXENPCI_DEVICE_DATA xpdd)
215 {
216 memcpy(xpdd->gnttab_table_copy, xpdd->gnttab_table, xpdd->grant_frames * PAGE_SIZE);
217 }
219 VOID
220 GntTbl_Resume(PXENPCI_DEVICE_DATA xpdd)
221 {
222 ULONG new_grant_frames;
223 ULONG result;
225 FUNCTION_ENTER();
227 new_grant_frames = GntTbl_QueryMaxFrames(xpdd);
228 KdPrint((__DRIVER_NAME " new_grant_frames = %d\n", new_grant_frames));
229 ASSERT(new_grant_frames >= xpdd->grant_frames); // lazy
230 result = GntTbl_Map(xpdd, 0, xpdd->grant_frames - 1);
231 KdPrint((__DRIVER_NAME " GntTbl_Map result = %d\n", result));
232 memcpy(xpdd->gnttab_table, xpdd->gnttab_table_copy, xpdd->grant_frames * PAGE_SIZE);
234 FUNCTION_EXIT();
235 }