win-pvdrivers

view xenpci/gnttbl.c @ 766:6300617040e0

Big changes - not ready for production use.
Removed all the custom DMA handling code as it was completely incompatible with the Windows verifier.
Added liblfds (using the lock free stack) from liblfds.org so that grant's can be obtained at DIRQL.
Fixed xennet and xenvbd to support the changes.
xenusb and xenscsi almost certainly will not yet work after the changes.
author James Harper <james.harper@bendigoit.com.au>
date Sun Jan 31 21:28:42 2010 +1100 (2010-01-31)
parents a88fe72e3597
children 5e3af133e8a6
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;
27 stack_push(xpdd->gnttab_ss, (PVOID)ref);
28 }
30 grant_ref_t
31 GntTbl_GetRef(PVOID Context)
32 {
33 PXENPCI_DEVICE_DATA xpdd = Context;
34 unsigned int ref;
35 PVOID ptr_ref;
37 if (!stack_pop(xpdd->gnttab_ss, &ptr_ref))
38 {
39 KdPrint((__DRIVER_NAME " No free grant refs\n"));
40 return INVALID_GRANT_REF;
41 }
42 ref = (grant_ref_t)ptr_ref;
44 return ref;
45 }
47 int
48 GntTbl_Map(PVOID Context, unsigned int start_idx, unsigned int end_idx)
49 {
50 PXENPCI_DEVICE_DATA xpdd = Context;
51 struct xen_add_to_physmap xatp;
52 unsigned int i = end_idx;
54 /* Loop backwards, so that the first hypercall has the largest index, ensuring that the table will grow only once. */
55 do {
56 xatp.domid = DOMID_SELF;
57 xatp.idx = i;
58 xatp.space = XENMAPSPACE_grant_table;
59 xatp.gpfn = (xen_pfn_t)(xpdd->gnttab_table_physical.QuadPart >> PAGE_SHIFT) + i;
60 if (HYPERVISOR_memory_op(xpdd, XENMEM_add_to_physmap, &xatp))
61 {
62 KdPrint((__DRIVER_NAME " ***ERROR MAPPING FRAME***\n"));
63 }
64 } while (i-- > start_idx);
66 return 0;
67 }
69 grant_ref_t
70 GntTbl_GrantAccess(
71 PVOID Context,
72 domid_t domid,
73 uint32_t frame, // xen api limits pfn to 32bit, so no guests over 8TB
74 int readonly,
75 grant_ref_t ref)
76 {
77 PXENPCI_DEVICE_DATA xpdd = Context;
79 //KdPrint((__DRIVER_NAME " --> GntTbl_GrantAccess\n"));
81 //KdPrint((__DRIVER_NAME " Granting access to frame %08x\n", frame));
83 if (ref == INVALID_GRANT_REF)
84 ref = GntTbl_GetRef(Context);
85 if (ref == INVALID_GRANT_REF)
86 return ref;
88 xpdd->gnttab_table[ref].frame = frame;
89 xpdd->gnttab_table[ref].domid = domid;
91 if (xpdd->gnttab_table[ref].flags)
92 KdPrint((__DRIVER_NAME " WARNING: Attempting to re-use grant entry that is already in use!\n"));
93 ASSERT(!xpdd->gnttab_table[ref].flags);
95 KeMemoryBarrier();
96 readonly *= GTF_readonly;
97 xpdd->gnttab_table[ref].flags = GTF_permit_access | (uint16_t)readonly;
99 //KdPrint((__DRIVER_NAME " <-- GntTbl_GrantAccess (ref = %d)\n", ref));
101 return ref;
102 }
104 BOOLEAN
105 GntTbl_EndAccess(
106 PVOID Context,
107 grant_ref_t ref,
108 BOOLEAN keepref)
109 {
110 PXENPCI_DEVICE_DATA xpdd = Context;
111 unsigned short flags, nflags;
113 //KdPrint((__DRIVER_NAME " --> GntTbl_EndAccess\n"));
115 ASSERT(ref != INVALID_GRANT_REF);
117 nflags = xpdd->gnttab_table[ref].flags;
118 do {
119 if ((flags = nflags) & (GTF_reading|GTF_writing))
120 {
121 KdPrint((__DRIVER_NAME " WARNING: g.e. %d still in use!\n", ref));
122 return FALSE;
123 }
124 } while ((nflags = InterlockedCompareExchange16(
125 (volatile SHORT *)&xpdd->gnttab_table[ref].flags, 0, flags)) != flags);
127 if (!keepref)
128 GntTbl_PutRef(Context, ref);
129 //KdPrint((__DRIVER_NAME " <-- GntTbl_EndAccess\n"));
130 return TRUE;
131 }
133 static unsigned int
134 GntTbl_QueryMaxFrames(PXENPCI_DEVICE_DATA xpdd)
135 {
136 struct gnttab_query_size query;
137 int rc;
139 query.dom = DOMID_SELF;
141 rc = HYPERVISOR_grant_table_op(xpdd, GNTTABOP_query_size, &query, 1);
142 if ((rc < 0) || (query.status != GNTST_okay))
143 {
144 KdPrint((__DRIVER_NAME " ***CANNOT QUERY MAX GRANT FRAME***\n"));
145 return 4; /* Legacy max supported number of frames */
146 }
147 return query.max_nr_frames;
148 }
150 VOID
151 GntTbl_Init(PXENPCI_DEVICE_DATA xpdd)
152 {
153 int i;
154 int grant_entries;
156 FUNCTION_ENTER();
158 xpdd->grant_frames = GntTbl_QueryMaxFrames(xpdd);
159 KdPrint((__DRIVER_NAME " grant_frames = %d\n", xpdd->grant_frames));
160 grant_entries = min(NR_GRANT_ENTRIES, (xpdd->grant_frames * PAGE_SIZE / sizeof(grant_entry_t)));
161 KdPrint((__DRIVER_NAME " grant_entries = %d\n", grant_entries));
163 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
164 xpdd->gnttab_table_copy = ExAllocatePoolWithTag(NonPagedPool, xpdd->grant_frames * PAGE_SIZE, XENPCI_POOL_TAG);
165 ASSERT(xpdd->gnttab_table_copy); // lazy
166 xpdd->gnttab_table_physical = XenPci_AllocMMIO(xpdd, PAGE_SIZE * xpdd->grant_frames);
167 xpdd->gnttab_table = MmMapIoSpace(xpdd->gnttab_table_physical, PAGE_SIZE * xpdd->grant_frames, MmNonCached);
168 if (!xpdd->gnttab_table)
169 {
170 KdPrint((__DRIVER_NAME " Error Mapping Grant Table Shared Memory\n"));
171 // this should be a show stopper...
172 return;
173 }
175 stack_new(&xpdd->gnttab_ss, grant_entries);
177 for (i = NR_RESERVED_ENTRIES; i < grant_entries; i++)
178 stack_push(xpdd->gnttab_ss, (PVOID)i);
180 GntTbl_Map(xpdd, 0, xpdd->grant_frames - 1);
182 RtlZeroMemory(xpdd->gnttab_table, PAGE_SIZE * xpdd->grant_frames);
184 FUNCTION_EXIT();
185 }
187 VOID
188 GntTbl_Suspend(PXENPCI_DEVICE_DATA xpdd)
189 {
190 memcpy(xpdd->gnttab_table_copy, xpdd->gnttab_table, xpdd->grant_frames * PAGE_SIZE);
191 }
193 VOID
194 GntTbl_Resume(PXENPCI_DEVICE_DATA xpdd)
195 {
196 ULONG new_grant_frames;
197 ULONG result;
199 FUNCTION_ENTER();
201 new_grant_frames = GntTbl_QueryMaxFrames(xpdd);
202 KdPrint((__DRIVER_NAME " new_grant_frames = %d\n", new_grant_frames));
203 ASSERT(new_grant_frames >= xpdd->grant_frames); // lazy
204 result = GntTbl_Map(xpdd, 0, xpdd->grant_frames - 1);
205 KdPrint((__DRIVER_NAME " GntTbl_Map result = %d\n", result));
206 memcpy(xpdd->gnttab_table, xpdd->gnttab_table_copy, xpdd->grant_frames * PAGE_SIZE);
208 FUNCTION_EXIT();
209 }