win-pvdrivers

view xenpci/gnttbl.c @ 776:5e3af133e8a6

Fix an x64 compile error. A few more to go though...
author James Harper <james.harper@bendigoit.com.au>
date Sun Feb 07 09:53:21 2010 +1100 (2010-02-07)
parents 6300617040e0
children 467005e7f509
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)(ULONG_PTR)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 }