win-pvdrivers

view xenpci/gnttbl.c @ 363:097ab7d19ea2

Merge bug fixer from WDF to WDM.
author Wayne Gong <wayne.gong@oracle.com>
date Mon Jul 07 14:03:39 2008 +0800 (2008-07-07)
parents 2be08f708250
children 25814a68e426
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;
28 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
29 KeAcquireSpinLock(&xpdd->grant_lock, &OldIrql);
30 xpdd->gnttab_list[ref] = xpdd->gnttab_list[0];
31 xpdd->gnttab_list[0] = ref;
32 KeReleaseSpinLock(&xpdd->grant_lock, OldIrql);
33 }
35 grant_ref_t
36 GntTbl_GetRef(PVOID Context)
37 {
38 PXENPCI_DEVICE_DATA xpdd = Context;
39 unsigned int ref;
40 KIRQL OldIrql;
42 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
43 KeAcquireSpinLock(&xpdd->grant_lock, &OldIrql);
44 ref = xpdd->gnttab_list[0];
45 xpdd->gnttab_list[0] = xpdd->gnttab_list[ref];
46 KeReleaseSpinLock(&xpdd->grant_lock, OldIrql);
48 return ref;
49 }
51 int
52 GntTbl_Map(PVOID Context, unsigned int start_idx, unsigned int end_idx)
53 {
54 PXENPCI_DEVICE_DATA xpdd = Context;
55 struct xen_add_to_physmap xatp;
56 unsigned int i = end_idx;
58 /* Loop backwards, so that the first hypercall has the largest index, ensuring that the table will grow only once. */
59 do {
60 xatp.domid = DOMID_SELF;
61 xatp.idx = i;
62 xatp.space = XENMAPSPACE_grant_table;
63 xatp.gpfn = (xen_pfn_t)(xpdd->gnttab_table_physical.QuadPart >> PAGE_SHIFT) + i;
64 if (HYPERVISOR_memory_op(xpdd, XENMEM_add_to_physmap, &xatp))
65 {
66 KdPrint((__DRIVER_NAME " ***ERROR MAPPING FRAME***\n"));
67 }
68 } while (i-- > start_idx);
70 return 0;
71 }
73 grant_ref_t
74 GntTbl_GrantAccess(
75 PVOID Context,
76 domid_t domid,
77 uint32_t frame, // xen api limits pfn to 32bit, so no guests over 8TB
78 int readonly,
79 grant_ref_t ref)
80 {
81 PXENPCI_DEVICE_DATA xpdd = Context;
83 //KdPrint((__DRIVER_NAME " --> GntTbl_GrantAccess\n"));
85 //KdPrint((__DRIVER_NAME " Granting access to frame %08x\n", frame));
87 if (ref == 0)
88 ref = GntTbl_GetRef(Context);
89 xpdd->gnttab_table[ref].frame = frame;
90 xpdd->gnttab_table[ref].domid = domid;
92 if (xpdd->gnttab_table[ref].flags)
93 KdPrint((__DRIVER_NAME " WARNING: Attempting to re-use grant entry that is already in use!\n"));
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 #ifdef __MINGW32__
105 /* from linux/include/asm-i386/cmpxchg.h */
106 static inline short InterlockedCompareExchange16(
107 short volatile *dest,
108 short exch,
109 short comp)
110 {
111 unsigned long prev;
113 __asm__ __volatile__("lock;"
114 "cmpxchgw %w1,%2"
115 : "=a"(prev)
116 : "r"(exch), "m"(*(dest)), "0"(comp)
117 : "memory");
119 KdPrint((__FUNC__ " Check that I work as expected!\n"));
121 return prev;
122 }
123 #endif
125 BOOLEAN
126 GntTbl_EndAccess(
127 PVOID Context,
128 grant_ref_t ref,
129 BOOLEAN keepref)
130 {
131 PXENPCI_DEVICE_DATA xpdd = Context;
132 unsigned short flags, nflags;
134 //KdPrint((__DRIVER_NAME " --> GntTbl_EndAccess\n"));
136 nflags = xpdd->gnttab_table[ref].flags;
137 do {
138 if ((flags = nflags) & (GTF_reading|GTF_writing))
139 {
140 KdPrint((__DRIVER_NAME "WARNING: g.e. still in use!\n"));
141 return FALSE;
142 }
143 } while ((nflags = InterlockedCompareExchange16(
144 (volatile SHORT *)&xpdd->gnttab_table[ref].flags, 0, flags)) != flags);
146 if (!keepref)
147 GntTbl_PutRef(Context, ref);
148 //KdPrint((__DRIVER_NAME " <-- GntTbl_EndAccess\n"));
149 return TRUE;
150 }
152 #if defined(_X86_)
153 static unsigned int
154 GntTbl_QueryMaxFrames(PXENPCI_DEVICE_DATA xpdd)
155 {
156 struct gnttab_query_size query;
157 int rc;
159 query.dom = DOMID_SELF;
161 rc = HYPERVISOR_grant_table_op(xpdd,GNTTABOP_query_size, &query, 1);
162 if ((rc < 0) || (query.status != GNTST_okay))
163 {
164 KdPrint((__DRIVER_NAME " ***CANNOT QUERY MAX GRANT FRAME***\n"));
165 return 4; /* Legacy max supported number of frames */
166 }
167 return query.max_nr_frames;
168 }
169 #endif
171 VOID
172 GntTbl_Init(PXENPCI_DEVICE_DATA xpdd)
173 {
174 int i;
175 int max_grant_frames = NR_GRANT_FRAMES;
176 int max_grant_entries = NR_GRANT_ENTRIES;
177 //KdPrint((__DRIVER_NAME " --> GntTbl_Init\n"));
179 KeInitializeSpinLock(&xpdd->grant_lock);
181 #if defined(_X86_)
182 max_grant_frames = GntTbl_QueryMaxFrames(xpdd);
183 max_grant_entries = min(NR_GRANT_ENTRIES,(max_grant_frames * PAGE_SIZE / sizeof(grant_entry_t)));
184 KdPrint((__DRIVER_NAME " max_grant_entries : %d\n",max_grant_entries));
185 #else
186 #if defined(_AMD64_)
187 KdPrint((__DRIVER_NAME " AMD64 cannot support HYPERVISOR_grant_table_op now\n"));
188 #endif
189 #endif
191 xpdd->gnttab_list = ExAllocatePoolWithTag(NonPagedPool, sizeof(grant_ref_t) * max_grant_entries, XENPCI_POOL_TAG);// Where to free?
192 for (i = NR_RESERVED_ENTRIES; i < max_grant_entries; i++)
193 GntTbl_PutRef(xpdd, i);
195 xpdd->gnttab_table_physical = XenPci_AllocMMIO(xpdd,
196 PAGE_SIZE * max_grant_frames);
197 xpdd->gnttab_table = MmMapIoSpace(xpdd->gnttab_table_physical,
198 PAGE_SIZE * max_grant_frames, MmNonCached);
199 if (!xpdd->gnttab_table)
200 {
201 KdPrint((__DRIVER_NAME " Error Mapping Grant Table Shared Memory\n"));
202 return;
203 }
204 GntTbl_Map(xpdd, 0, max_grant_frames - 1);
206 //KdPrint((__DRIVER_NAME " <-- GntTbl_Init table mapped at %p\n", gnttab_table));
207 }