win-pvdrivers

view xenpci/gnttbl.c @ 547:ac614e49832c

Fixed another typo
author James Harper <james.harper@bendigoit.com.au>
date Sun Mar 08 14:37:45 2009 +1100 (2009-03-08)
parents 1d39de3ab8d6
children a88fe72e3597
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 OldIrql = PASSIVE_LEVEL;
28 if (xpdd->suspend_state != SUSPEND_STATE_HIGH_IRQL)
29 {
30 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
31 KeAcquireSpinLock(&xpdd->grant_lock, &OldIrql);
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, OldIrql);
38 }
39 }
41 grant_ref_t
42 GntTbl_GetRef(PVOID Context)
43 {
44 PXENPCI_DEVICE_DATA xpdd = Context;
45 unsigned int ref;
46 KIRQL OldIrql = PASSIVE_LEVEL;
47 int suspend_state = xpdd->suspend_state;
49 UNREFERENCED_PARAMETER(OldIrql);
51 if (suspend_state != SUSPEND_STATE_HIGH_IRQL)
52 {
53 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
54 KeAcquireSpinLock(&xpdd->grant_lock, &OldIrql);
55 }
56 if (!xpdd->gnttab_list_free)
57 {
58 if (suspend_state != SUSPEND_STATE_HIGH_IRQL)
59 KeReleaseSpinLock(&xpdd->grant_lock, OldIrql);
60 KdPrint((__DRIVER_NAME " No free grant refs\n"));
61 return INVALID_GRANT_REF;
62 }
63 xpdd->gnttab_list_free--;
64 ref = xpdd->gnttab_list[xpdd->gnttab_list_free];
65 if (suspend_state != SUSPEND_STATE_HIGH_IRQL)
66 KeReleaseSpinLock(&xpdd->grant_lock, OldIrql);
68 return ref;
69 }
71 int
72 GntTbl_Map(PVOID Context, unsigned int start_idx, unsigned int end_idx)
73 {
74 PXENPCI_DEVICE_DATA xpdd = Context;
75 struct xen_add_to_physmap xatp;
76 unsigned int i = end_idx;
78 /* Loop backwards, so that the first hypercall has the largest index, ensuring that the table will grow only once. */
79 do {
80 xatp.domid = DOMID_SELF;
81 xatp.idx = i;
82 xatp.space = XENMAPSPACE_grant_table;
83 xatp.gpfn = (xen_pfn_t)(xpdd->gnttab_table_physical.QuadPart >> PAGE_SHIFT) + i;
84 if (HYPERVISOR_memory_op(xpdd, XENMEM_add_to_physmap, &xatp))
85 {
86 KdPrint((__DRIVER_NAME " ***ERROR MAPPING FRAME***\n"));
87 }
88 } while (i-- > start_idx);
90 return 0;
91 }
93 grant_ref_t
94 GntTbl_GrantAccess(
95 PVOID Context,
96 domid_t domid,
97 uint32_t frame, // xen api limits pfn to 32bit, so no guests over 8TB
98 int readonly,
99 grant_ref_t ref)
100 {
101 PXENPCI_DEVICE_DATA xpdd = Context;
103 //KdPrint((__DRIVER_NAME " --> GntTbl_GrantAccess\n"));
105 //KdPrint((__DRIVER_NAME " Granting access to frame %08x\n", frame));
107 if (ref == INVALID_GRANT_REF)
108 ref = GntTbl_GetRef(Context);
109 if (ref == INVALID_GRANT_REF)
110 return ref;
112 xpdd->gnttab_table[ref].frame = frame;
113 xpdd->gnttab_table[ref].domid = domid;
115 if (xpdd->gnttab_table[ref].flags)
116 KdPrint((__DRIVER_NAME " WARNING: Attempting to re-use grant entry that is already in use!\n"));
117 ASSERT(!xpdd->gnttab_table[ref].flags);
119 KeMemoryBarrier();
120 readonly *= GTF_readonly;
121 xpdd->gnttab_table[ref].flags = GTF_permit_access | (uint16_t)readonly;
123 //KdPrint((__DRIVER_NAME " <-- GntTbl_GrantAccess (ref = %d)\n", ref));
125 return ref;
126 }
128 BOOLEAN
129 GntTbl_EndAccess(
130 PVOID Context,
131 grant_ref_t ref,
132 BOOLEAN keepref)
133 {
134 PXENPCI_DEVICE_DATA xpdd = Context;
135 unsigned short flags, nflags;
137 //KdPrint((__DRIVER_NAME " --> GntTbl_EndAccess\n"));
139 ASSERT(ref != INVALID_GRANT_REF);
141 nflags = xpdd->gnttab_table[ref].flags;
142 do {
143 if ((flags = nflags) & (GTF_reading|GTF_writing))
144 {
145 KdPrint((__DRIVER_NAME " WARNING: g.e. %d still in use!\n", ref));
146 return FALSE;
147 }
148 } while ((nflags = InterlockedCompareExchange16(
149 (volatile SHORT *)&xpdd->gnttab_table[ref].flags, 0, flags)) != flags);
151 if (!keepref)
152 GntTbl_PutRef(Context, ref);
153 //KdPrint((__DRIVER_NAME " <-- GntTbl_EndAccess\n"));
154 return TRUE;
155 }
157 static unsigned int
158 GntTbl_QueryMaxFrames(PXENPCI_DEVICE_DATA xpdd)
159 {
160 struct gnttab_query_size query;
161 int rc;
163 query.dom = DOMID_SELF;
165 rc = HYPERVISOR_grant_table_op(xpdd, GNTTABOP_query_size, &query, 1);
166 if ((rc < 0) || (query.status != GNTST_okay))
167 {
168 KdPrint((__DRIVER_NAME " ***CANNOT QUERY MAX GRANT FRAME***\n"));
169 return 4; /* Legacy max supported number of frames */
170 }
171 return query.max_nr_frames;
172 }
174 VOID
175 GntTbl_Init(PXENPCI_DEVICE_DATA xpdd)
176 {
177 int i;
178 int grant_entries;
180 FUNCTION_ENTER();
182 KeInitializeSpinLock(&xpdd->grant_lock);
184 xpdd->grant_frames = GntTbl_QueryMaxFrames(xpdd);
185 KdPrint((__DRIVER_NAME " grant_frames = %d\n", xpdd->grant_frames));
186 grant_entries = min(NR_GRANT_ENTRIES, (xpdd->grant_frames * PAGE_SIZE / sizeof(grant_entry_t)));
187 KdPrint((__DRIVER_NAME " grant_entries = %d\n", grant_entries));
189 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
190 xpdd->gnttab_table_copy = ExAllocatePoolWithTag(NonPagedPool, xpdd->grant_frames * PAGE_SIZE, XENPCI_POOL_TAG);
191 ASSERT(xpdd->gnttab_table_copy); // lazy
192 xpdd->gnttab_list = ExAllocatePoolWithTag(NonPagedPool, sizeof(grant_ref_t) * grant_entries, XENPCI_POOL_TAG);
193 ASSERT(xpdd->gnttab_list); // lazy
194 xpdd->gnttab_table_physical = XenPci_AllocMMIO(xpdd, PAGE_SIZE * xpdd->grant_frames);
195 xpdd->gnttab_table = MmMapIoSpace(xpdd->gnttab_table_physical, PAGE_SIZE * xpdd->grant_frames, MmNonCached);
196 if (!xpdd->gnttab_table)
197 {
198 KdPrint((__DRIVER_NAME " Error Mapping Grant Table Shared Memory\n"));
199 // this should be a show stopper...
200 return;
201 }
203 RtlZeroMemory(xpdd->gnttab_list, sizeof(grant_ref_t) * grant_entries);
204 xpdd->gnttab_list_free = 0;
205 for (i = NR_RESERVED_ENTRIES; i < grant_entries; i++)
206 GntTbl_PutRef(xpdd, i);
208 GntTbl_Map(xpdd, 0, xpdd->grant_frames - 1);
210 RtlZeroMemory(xpdd->gnttab_table, PAGE_SIZE * xpdd->grant_frames);
212 FUNCTION_EXIT();
213 }
215 VOID
216 GntTbl_Suspend(PXENPCI_DEVICE_DATA xpdd)
217 {
218 memcpy(xpdd->gnttab_table_copy, xpdd->gnttab_table, xpdd->grant_frames * PAGE_SIZE);
219 }
221 VOID
222 GntTbl_Resume(PXENPCI_DEVICE_DATA xpdd)
223 {
224 ULONG new_grant_frames;
225 ULONG result;
227 FUNCTION_ENTER();
229 new_grant_frames = GntTbl_QueryMaxFrames(xpdd);
230 KdPrint((__DRIVER_NAME " new_grant_frames = %d\n", new_grant_frames));
231 ASSERT(new_grant_frames >= xpdd->grant_frames); // lazy
232 result = GntTbl_Map(xpdd, 0, xpdd->grant_frames - 1);
233 KdPrint((__DRIVER_NAME " GntTbl_Map result = %d\n", result));
234 memcpy(xpdd->gnttab_table, xpdd->gnttab_table_copy, xpdd->grant_frames * PAGE_SIZE);
236 FUNCTION_EXIT();
237 }