win-pvdrivers

changeset 417:ef5345ea9984

Fixed the freelist overflow case in xennet.
Fixed event channel IRQ handling in evtchn.
author James Harper <james.harper@bendigoit.com.au>
date Mon Aug 18 23:14:40 2008 +1000 (2008-08-18)
parents dd729c3bd53e
children bf3359218841
files xennet/xennet_common.c xennet/xennet_rx.c xenpci/evtchn.c
line diff
     1.1 --- a/xennet/xennet_common.c	Mon Aug 18 21:14:13 2008 +1000
     1.2 +++ b/xennet/xennet_common.c	Mon Aug 18 23:14:40 2008 +1000
     1.3 @@ -230,8 +230,18 @@ XenFreelist_GetPage(freelist_t *fl)
     1.4  VOID
     1.5  XenFreelist_PutPage(freelist_t *fl, PMDL mdl)
     1.6  {
     1.7 -  fl->page_list[fl->page_free] = mdl;
     1.8 -  fl->page_free++;
     1.9 +  if (fl->page_free == PAGE_LIST_SIZE - 1)
    1.10 +  {
    1.11 +    /* our page list is full. free the buffer instead. This will be a bit sucky performancewise... */
    1.12 +    fl->xi->vectors.GntTbl_EndAccess(fl->xi->vectors.context,
    1.13 +      *(grant_ref_t *)(((UCHAR *)mdl) + MmSizeOfMdl(0, PAGE_SIZE)), 0);
    1.14 +    FreePages(mdl);
    1.15 +  }
    1.16 +  else
    1.17 +  {
    1.18 +    fl->page_list[fl->page_free] = mdl;
    1.19 +    fl->page_free++;
    1.20 +  }
    1.21  }
    1.22  
    1.23  VOID
     2.1 --- a/xennet/xennet_rx.c	Mon Aug 18 21:14:13 2008 +1000
     2.2 +++ b/xennet/xennet_rx.c	Mon Aug 18 23:14:40 2008 +1000
     2.3 @@ -83,7 +83,8 @@ get_packet_from_freelist(struct xennet_i
     2.4    if (!xi->rx_packet_free)
     2.5    {
     2.6      NdisAllocatePacket(&status, &packet, xi->packet_pool);
     2.7 -    ASSERT(status == NDIS_STATUS_SUCCESS);
     2.8 +    if (status != NDIS_STATUS_SUCCESS)
     2.9 +      return NULL;
    2.10      NDIS_SET_PACKET_HEADER_SIZE(packet, XN_HDR_SIZE);
    2.11    }
    2.12    else
    2.13 @@ -97,6 +98,12 @@ get_packet_from_freelist(struct xennet_i
    2.14  static VOID
    2.15  put_packet_on_freelist(struct xennet_info *xi, PNDIS_PACKET packet)
    2.16  {
    2.17 +  if (xi->rx_packet_free == NET_RX_RING_SIZE * 2 - 1)
    2.18 +  {
    2.19 +    //KdPrint((__DRIVER_NAME "     packet free list full - releasing packet\n"));
    2.20 +    NdisFreePacket(packet);
    2.21 +    return;
    2.22 +  }
    2.23    NdisReinitializePacket(packet);
    2.24    xi->rx_packet_list[xi->rx_packet_free] = packet;
    2.25    xi->rx_packet_free++;
    2.26 @@ -131,6 +138,12 @@ XenNet_MakePacket(struct xennet_info *xi
    2.27    if (!xi->rxpi.split_required)
    2.28    {
    2.29      packet = get_packet_from_freelist(xi);
    2.30 +    if (packet == NULL)
    2.31 +    {
    2.32 +      for (i = 0; i < xi->rxpi.mdl_count; i++)
    2.33 +        XenFreelist_PutPage(&xi->rx_freelist, xi->rxpi.mdls[i]);
    2.34 +      return NULL;
    2.35 +    }
    2.36      xi->rx_outstanding++;
    2.37      for (i = 0; i < xi->rxpi.mdl_count; i++)
    2.38        NdisChainBufferAtBack(packet, xi->rxpi.mdls[i]);
    2.39 @@ -142,6 +155,11 @@ XenNet_MakePacket(struct xennet_info *xi
    2.40      if (!out_mdl)
    2.41        return NULL;
    2.42      packet = get_packet_from_freelist(xi);
    2.43 +    if (packet == NULL)
    2.44 +    {
    2.45 +      XenFreelist_PutPage(&xi->rx_freelist, out_mdl);
    2.46 +      return NULL;
    2.47 +    }
    2.48      xi->rx_outstanding++;
    2.49      out_buffer = MmGetMdlVirtualAddress(out_mdl);
    2.50      out_offset = XN_HDR_SIZE + xi->rxpi.ip4_header_length + xi->rxpi.tcp_header_length;
    2.51 @@ -295,6 +313,11 @@ XenNet_MakePackets(
    2.52      // fallthrough
    2.53    case 17:  // UDP
    2.54      packet = XenNet_MakePacket(xi);
    2.55 +    if (packet == NULL)
    2.56 +    {
    2.57 +      xi->stat_rx_no_buffer++;
    2.58 +      return 0;
    2.59 +    }
    2.60      if (xi->rxpi.csum_calc_required)
    2.61        XenNet_SumPacketData(&xi->rxpi, packet);
    2.62      entry = (PLIST_ENTRY)&packet->MiniportReservedEx[sizeof(PVOID)];
    2.63 @@ -303,6 +326,11 @@ XenNet_MakePackets(
    2.64      return 1;
    2.65    default:
    2.66      packet = XenNet_MakePacket(xi);
    2.67 +    if (packet == NULL)
    2.68 +    {
    2.69 +      xi->stat_rx_no_buffer++;
    2.70 +      return 0;
    2.71 +    }
    2.72      entry = (PLIST_ENTRY)&packet->MiniportReservedEx[sizeof(PVOID)];
    2.73      InsertTailList(rx_packet_list, entry);
    2.74      RtlZeroMemory(&xi->rxpi, sizeof(xi->rxpi));
    2.75 @@ -325,7 +353,10 @@ XenNet_MakePackets(
    2.76      UINT buffer_length;
    2.77      packet = XenNet_MakePacket(xi);
    2.78      if (!packet)
    2.79 +    {
    2.80 +      xi->stat_rx_no_buffer++;
    2.81        break; /* we are out of memory - just drop the packets */
    2.82 +    }
    2.83      if (psh)
    2.84      {
    2.85        NdisGetFirstBufferFromPacketSafe(packet, &mdl, &buffer, &buffer_length, &total_length, NormalPagePriority);
     3.1 --- a/xenpci/evtchn.c	Mon Aug 18 21:14:13 2008 +1000
     3.2 +++ b/xenpci/evtchn.c	Mon Aug 18 23:14:40 2008 +1000
     3.3 @@ -93,7 +93,12 @@ EvtChn_AckEvent(PVOID context, evtchn_po
     3.4  static DDKAPI BOOLEAN
     3.5  EvtChn_Interrupt(PKINTERRUPT Interrupt, PVOID Context)
     3.6  {
     3.7 -  int cpu = KeGetCurrentProcessorNumber() & (MAX_VIRT_CPUS - 1);
     3.8 +/*
     3.9 +For HVM domains, Xen always triggers the event on CPU0. Because the
    3.10 +interrupt is delivered via the virtual PCI device it might get delivered
    3.11 +to CPU != 0, but we should always use vcpu_info[0]
    3.12 +*/
    3.13 +  int cpu = 0;
    3.14    vcpu_info_t *vcpu_info;
    3.15    PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)Context;
    3.16    shared_info_t *shared_info_area = xpdd->shared_info_area;