win-pvdrivers

annotate 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
rev   line source
james@0 1 /*
james@0 2 PV Drivers for Windows Xen HVM Domains
james@0 3 Copyright (C) 2007 James Harper
james@0 4
james@0 5 This program is free software; you can redistribute it and/or
james@0 6 modify it under the terms of the GNU General Public License
james@0 7 as published by the Free Software Foundation; either version 2
james@0 8 of the License, or (at your option) any later version.
james@0 9
james@0 10 This program is distributed in the hope that it will be useful,
james@0 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
james@0 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
james@0 13 GNU General Public License for more details.
james@0 14
james@0 15 You should have received a copy of the GNU General Public License
james@0 16 along with this program; if not, write to the Free Software
james@0 17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
james@0 18 */
james@0 19
james@0 20 #include "xenpci.h"
james@0 21
james@206 22 VOID
james@258 23 GntTbl_PutRef(PVOID Context, grant_ref_t ref)
james@0 24 {
james@258 25 PXENPCI_DEVICE_DATA xpdd = Context;
james@0 26
james@766 27 stack_push(xpdd->gnttab_ss, (PVOID)ref);
james@0 28 }
james@0 29
james@206 30 grant_ref_t
james@258 31 GntTbl_GetRef(PVOID Context)
james@0 32 {
james@258 33 PXENPCI_DEVICE_DATA xpdd = Context;
james@176 34 unsigned int ref;
james@766 35 PVOID ptr_ref;
james@766 36
james@766 37 if (!stack_pop(xpdd->gnttab_ss, &ptr_ref))
james@385 38 {
james@766 39 KdPrint((__DRIVER_NAME " No free grant refs\n"));
james@415 40 return INVALID_GRANT_REF;
james@415 41 }
james@766 42 ref = (grant_ref_t)ptr_ref;
james@176 43
andy@13 44 return ref;
james@0 45 }
james@0 46
james@279 47 int
james@258 48 GntTbl_Map(PVOID Context, unsigned int start_idx, unsigned int end_idx)
james@0 49 {
james@258 50 PXENPCI_DEVICE_DATA xpdd = Context;
james@0 51 struct xen_add_to_physmap xatp;
james@0 52 unsigned int i = end_idx;
james@0 53
james@258 54 /* Loop backwards, so that the first hypercall has the largest index, ensuring that the table will grow only once. */
james@0 55 do {
james@0 56 xatp.domid = DOMID_SELF;
james@0 57 xatp.idx = i;
james@0 58 xatp.space = XENMAPSPACE_grant_table;
andy@16 59 xatp.gpfn = (xen_pfn_t)(xpdd->gnttab_table_physical.QuadPart >> PAGE_SHIFT) + i;
james@258 60 if (HYPERVISOR_memory_op(xpdd, XENMEM_add_to_physmap, &xatp))
james@0 61 {
james@0 62 KdPrint((__DRIVER_NAME " ***ERROR MAPPING FRAME***\n"));
james@0 63 }
james@0 64 } while (i-- > start_idx);
james@0 65
james@0 66 return 0;
james@0 67 }
james@0 68
james@0 69 grant_ref_t
andy@13 70 GntTbl_GrantAccess(
james@258 71 PVOID Context,
andy@13 72 domid_t domid,
andy@265 73 uint32_t frame, // xen api limits pfn to 32bit, so no guests over 8TB
james@206 74 int readonly,
james@206 75 grant_ref_t ref)
james@0 76 {
james@258 77 PXENPCI_DEVICE_DATA xpdd = Context;
james@0 78
james@0 79 //KdPrint((__DRIVER_NAME " --> GntTbl_GrantAccess\n"));
james@0 80
james@138 81 //KdPrint((__DRIVER_NAME " Granting access to frame %08x\n", frame));
james@137 82
james@415 83 if (ref == INVALID_GRANT_REF)
james@258 84 ref = GntTbl_GetRef(Context);
james@415 85 if (ref == INVALID_GRANT_REF)
james@415 86 return ref;
james@415 87
andy@16 88 xpdd->gnttab_table[ref].frame = frame;
andy@16 89 xpdd->gnttab_table[ref].domid = domid;
james@254 90
james@254 91 if (xpdd->gnttab_table[ref].flags)
james@254 92 KdPrint((__DRIVER_NAME " WARNING: Attempting to re-use grant entry that is already in use!\n"));
james@415 93 ASSERT(!xpdd->gnttab_table[ref].flags);
james@254 94
james@0 95 KeMemoryBarrier();
james@0 96 readonly *= GTF_readonly;
andy@16 97 xpdd->gnttab_table[ref].flags = GTF_permit_access | (uint16_t)readonly;
james@0 98
james@0 99 //KdPrint((__DRIVER_NAME " <-- GntTbl_GrantAccess (ref = %d)\n", ref));
james@0 100
james@0 101 return ref;
james@0 102 }
james@0 103
james@0 104 BOOLEAN
andy@13 105 GntTbl_EndAccess(
james@258 106 PVOID Context,
james@206 107 grant_ref_t ref,
james@206 108 BOOLEAN keepref)
james@0 109 {
james@258 110 PXENPCI_DEVICE_DATA xpdd = Context;
james@0 111 unsigned short flags, nflags;
james@0 112
james@0 113 //KdPrint((__DRIVER_NAME " --> GntTbl_EndAccess\n"));
james@0 114
james@415 115 ASSERT(ref != INVALID_GRANT_REF);
james@415 116
andy@16 117 nflags = xpdd->gnttab_table[ref].flags;
james@0 118 do {
james@0 119 if ((flags = nflags) & (GTF_reading|GTF_writing))
james@0 120 {
james@533 121 KdPrint((__DRIVER_NAME " WARNING: g.e. %d still in use!\n", ref));
james@0 122 return FALSE;
james@0 123 }
andy@13 124 } while ((nflags = InterlockedCompareExchange16(
james@141 125 (volatile SHORT *)&xpdd->gnttab_table[ref].flags, 0, flags)) != flags);
james@0 126
james@206 127 if (!keepref)
james@258 128 GntTbl_PutRef(Context, ref);
james@0 129 //KdPrint((__DRIVER_NAME " <-- GntTbl_EndAccess\n"));
james@0 130 return TRUE;
james@0 131 }
james@258 132
wayne@363 133 static unsigned int
wayne@363 134 GntTbl_QueryMaxFrames(PXENPCI_DEVICE_DATA xpdd)
wayne@363 135 {
wayne@363 136 struct gnttab_query_size query;
wayne@363 137 int rc;
wayne@363 138
wayne@363 139 query.dom = DOMID_SELF;
wayne@363 140
james@536 141 rc = HYPERVISOR_grant_table_op(xpdd, GNTTABOP_query_size, &query, 1);
wayne@363 142 if ((rc < 0) || (query.status != GNTST_okay))
wayne@363 143 {
wayne@363 144 KdPrint((__DRIVER_NAME " ***CANNOT QUERY MAX GRANT FRAME***\n"));
wayne@363 145 return 4; /* Legacy max supported number of frames */
wayne@363 146 }
wayne@363 147 return query.max_nr_frames;
wayne@363 148 }
james@374 149
james@374 150 VOID
james@536 151 GntTbl_Init(PXENPCI_DEVICE_DATA xpdd)
james@374 152 {
james@374 153 int i;
james@374 154 int grant_entries;
james@536 155
james@536 156 FUNCTION_ENTER();
james@536 157
james@536 158 xpdd->grant_frames = GntTbl_QueryMaxFrames(xpdd);
james@536 159 KdPrint((__DRIVER_NAME " grant_frames = %d\n", xpdd->grant_frames));
james@536 160 grant_entries = min(NR_GRANT_ENTRIES, (xpdd->grant_frames * PAGE_SIZE / sizeof(grant_entry_t)));
james@536 161 KdPrint((__DRIVER_NAME " grant_entries = %d\n", grant_entries));
james@536 162
james@536 163 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
james@536 164 xpdd->gnttab_table_copy = ExAllocatePoolWithTag(NonPagedPool, xpdd->grant_frames * PAGE_SIZE, XENPCI_POOL_TAG);
james@536 165 ASSERT(xpdd->gnttab_table_copy); // lazy
james@536 166 xpdd->gnttab_table_physical = XenPci_AllocMMIO(xpdd, PAGE_SIZE * xpdd->grant_frames);
james@536 167 xpdd->gnttab_table = MmMapIoSpace(xpdd->gnttab_table_physical, PAGE_SIZE * xpdd->grant_frames, MmNonCached);
james@536 168 if (!xpdd->gnttab_table)
james@374 169 {
james@536 170 KdPrint((__DRIVER_NAME " Error Mapping Grant Table Shared Memory\n"));
james@536 171 // this should be a show stopper...
james@536 172 return;
james@374 173 }
james@766 174
james@766 175 stack_new(&xpdd->gnttab_ss, grant_entries);
james@374 176
james@374 177 for (i = NR_RESERVED_ENTRIES; i < grant_entries; i++)
james@766 178 stack_push(xpdd->gnttab_ss, (PVOID)i);
james@374 179
james@536 180 GntTbl_Map(xpdd, 0, xpdd->grant_frames - 1);
james@536 181
james@536 182 RtlZeroMemory(xpdd->gnttab_table, PAGE_SIZE * xpdd->grant_frames);
james@536 183
james@536 184 FUNCTION_EXIT();
james@374 185 }
wayne@363 186
james@258 187 VOID
james@536 188 GntTbl_Suspend(PXENPCI_DEVICE_DATA xpdd)
james@258 189 {
james@536 190 memcpy(xpdd->gnttab_table_copy, xpdd->gnttab_table, xpdd->grant_frames * PAGE_SIZE);
james@536 191 }
james@536 192
james@536 193 VOID
james@536 194 GntTbl_Resume(PXENPCI_DEVICE_DATA xpdd)
james@536 195 {
james@536 196 ULONG new_grant_frames;
james@536 197 ULONG result;
james@258 198
james@536 199 FUNCTION_ENTER();
james@374 200
james@536 201 new_grant_frames = GntTbl_QueryMaxFrames(xpdd);
james@536 202 KdPrint((__DRIVER_NAME " new_grant_frames = %d\n", new_grant_frames));
james@536 203 ASSERT(new_grant_frames >= xpdd->grant_frames); // lazy
james@536 204 result = GntTbl_Map(xpdd, 0, xpdd->grant_frames - 1);
james@536 205 KdPrint((__DRIVER_NAME " GntTbl_Map result = %d\n", result));
james@536 206 memcpy(xpdd->gnttab_table, xpdd->gnttab_table_copy, xpdd->grant_frames * PAGE_SIZE);
james@536 207
james@536 208 FUNCTION_EXIT();
james@258 209 }