ia64/xen-unstable

changeset 1030:079ff40b60d2

bitkeeper revision 1.670 (3ffaf723Sn5FVTMBSOvb9binR3cthQ)

network.c, dev.c, pgalloc.h, flushtlb.h, domain.c, smp.c:
Fixed heinous TLB-flush and network bugs.
author kaf24@scramble.cl.cam.ac.uk
date Tue Jan 06 17:57:55 2004 +0000 (2004-01-06)
parents 7de4b6630bf4
children 8711bea9eaa1 b57ab0c5101f
files xen/arch/i386/smp.c xen/common/domain.c xen/include/asm-i386/flushtlb.h xen/include/asm-i386/pgalloc.h xen/net/dev.c xenolinux-2.4.23-sparse/arch/xeno/drivers/network/network.c
line diff
     1.1 --- a/xen/arch/i386/smp.c	Mon Jan 05 22:55:26 2004 +0000
     1.2 +++ b/xen/arch/i386/smp.c	Tue Jan 06 17:57:55 2004 +0000
     1.3 @@ -269,8 +269,34 @@ asmlinkage void smp_invalidate_interrupt
     1.4      local_flush_tlb();
     1.5  }
     1.6  
     1.7 +int try_flush_tlb_mask(unsigned long mask)
     1.8 +{
     1.9 +    if ( mask & (1 << smp_processor_id()) )
    1.10 +    {
    1.11 +        local_flush_tlb();
    1.12 +        mask &= ~(1 << smp_processor_id());
    1.13 +    }
    1.14 +
    1.15 +    if ( mask != 0 )
    1.16 +    {
    1.17 +        if ( unlikely(!spin_trylock(&tlbstate_lock)) )
    1.18 +            return 0;
    1.19 +        flush_cpumask = mask;
    1.20 +        send_IPI_mask(mask, INVALIDATE_TLB_VECTOR);
    1.21 +        while ( flush_cpumask != 0 )
    1.22 +        {
    1.23 +            rep_nop();
    1.24 +            barrier();
    1.25 +        }
    1.26 +        spin_unlock(&tlbstate_lock);
    1.27 +    }
    1.28 +
    1.29 +    return 1;
    1.30 +}
    1.31 +
    1.32  void flush_tlb_mask(unsigned long mask)
    1.33  {
    1.34 +    /* WARNING: Only try_flush_tlb_mask() is safe in IRQ context. */
    1.35      if ( unlikely(in_irq()) )
    1.36          BUG();
    1.37      
     2.1 --- a/xen/common/domain.c	Mon Jan 05 22:55:26 2004 +0000
     2.2 +++ b/xen/common/domain.c	Tue Jan 06 17:57:55 2004 +0000
     2.3 @@ -17,7 +17,6 @@
     2.4  #include <xeno/blkdev.h>
     2.5  #include <xeno/console.h>
     2.6  #include <xeno/vbd.h>
     2.7 -
     2.8  #include <asm/i387.h>
     2.9  
    2.10  /*
    2.11 @@ -237,12 +236,12 @@ struct pfn_info *alloc_domain_page(struc
    2.12      if ( unlikely(page == NULL) )
    2.13          return NULL;
    2.14  
    2.15 -    if ( unlikely((mask = page->u.cpu_mask) != 0) )
    2.16 +    if ( (mask = page->u.cpu_mask) != 0 )
    2.17      {
    2.18          pfn_stamp = page->tlbflush_timestamp;
    2.19          for ( i = 0; (mask != 0) && (i < NR_CPUS); i++ )
    2.20          {
    2.21 -            if ( unlikely(mask & (1<<i)) )
    2.22 +            if ( mask & (1<<i) )
    2.23              {
    2.24                  cpu_stamp = tlbflush_time[i];
    2.25                  if ( !NEED_FLUSH(cpu_stamp, pfn_stamp) )
    2.26 @@ -252,13 +251,12 @@ struct pfn_info *alloc_domain_page(struc
    2.27  
    2.28          if ( unlikely(mask != 0) )
    2.29          {
    2.30 -            if ( unlikely(in_irq()) )
    2.31 -            {
    2.32 -                DPRINTK("Returning NULL from alloc_domain_page: in_irq\n");
    2.33 +            /* In IRQ ctxt, flushing is best-effort only, to avoid deadlock. */
    2.34 +            if ( likely(!in_irq()) )
    2.35 +                flush_tlb_mask(mask);
    2.36 +            else if ( unlikely(!try_flush_tlb_mask(mask)) )
    2.37                  goto free_and_exit;
    2.38 -            }
    2.39              perfc_incrc(need_flush_tlb_flush);
    2.40 -            flush_tlb_mask(mask);
    2.41          }
    2.42      }
    2.43  
     3.1 --- a/xen/include/asm-i386/flushtlb.h	Mon Jan 05 22:55:26 2004 +0000
     3.2 +++ b/xen/include/asm-i386/flushtlb.h	Tue Jan 06 17:57:55 2004 +0000
     3.3 @@ -24,8 +24,8 @@
     3.4   * used for a purpose that may have caused the CPU's TLB to become tainted.
     3.5   */
     3.6  #define NEED_FLUSH(_cpu_stamp, _lastuse_stamp) \
     3.7 - (((_cpu_stamp) > (_lastuse_stamp)) ||         \
     3.8 -  (((_lastuse_stamp) - (_cpu_stamp)) > (2*GLOBAL_FLUSH_PERIOD)))
     3.9 + (((_cpu_stamp) <= (_lastuse_stamp)) &&        \
    3.10 +  (((_lastuse_stamp) - (_cpu_stamp)) <= (2*GLOBAL_FLUSH_PERIOD)))
    3.11  
    3.12  extern unsigned long tlbflush_mask;
    3.13  extern unsigned long tlbflush_clock;
     4.1 --- a/xen/include/asm-i386/pgalloc.h	Mon Jan 05 22:55:26 2004 +0000
     4.2 +++ b/xen/include/asm-i386/pgalloc.h	Tue Jan 06 17:57:55 2004 +0000
     4.3 @@ -47,17 +47,19 @@
     4.4  
     4.5  #ifndef CONFIG_SMP
     4.6  
     4.7 -#define flush_tlb()           __flush_tlb()
     4.8 -#define flush_tlb_all()       __flush_tlb()
     4.9 -#define flush_tlb_all_pge()   __flush_tlb_pge()
    4.10 -#define local_flush_tlb()     __flush_tlb()
    4.11 -#define flush_tlb_cpu(_cpu)   __flush_tlb()
    4.12 -#define flush_tlb_mask(_mask) __flush_tlb()
    4.13 +#define flush_tlb()               __flush_tlb()
    4.14 +#define flush_tlb_all()           __flush_tlb()
    4.15 +#define flush_tlb_all_pge()       __flush_tlb_pge()
    4.16 +#define local_flush_tlb()         __flush_tlb()
    4.17 +#define flush_tlb_cpu(_cpu)       __flush_tlb()
    4.18 +#define flush_tlb_mask(_mask)     __flush_tlb()
    4.19 +#define try_flush_tlb_mask(_mask) __flush_tlb()
    4.20  
    4.21  #else
    4.22  
    4.23  #include <xeno/smp.h>
    4.24  
    4.25 +extern int try_flush_tlb_mask(unsigned long mask);
    4.26  extern void flush_tlb_mask(unsigned long mask);
    4.27  extern void flush_tlb_all_pge(void);
    4.28  
     5.1 --- a/xen/net/dev.c	Mon Jan 05 22:55:26 2004 +0000
     5.2 +++ b/xen/net/dev.c	Tue Jan 06 17:57:55 2004 +0000
     5.3 @@ -535,6 +535,7 @@ void deliver_packet(struct sk_buff *skb,
     5.4                            (pte & ~PAGE_MASK) | _PAGE_RW | _PAGE_PRESENT |
     5.5                            ((new_page - frame_table) << PAGE_SHIFT))) != pte )
     5.6      {
     5.7 +        DPRINTK("PTE was modified or reused! %08lx %08lx\n", pte, *ptep);
     5.8          unmap_domain_mem(ptep);
     5.9          /* At some point maybe should have 'new_page' in error response. */
    5.10          put_page_and_type(new_page);
    5.11 @@ -2112,6 +2113,9 @@ static void get_rx_bufs(net_vif_t *vif)
    5.12              goto rx_unmap_and_continue;
    5.13          }
    5.14              
    5.15 +        buf_page->tlbflush_timestamp = tlbflush_clock;
    5.16 +        buf_page->u.cpu_mask = 1 << p->processor;
    5.17 +
    5.18          /* Remove from the domain's allocation list. */
    5.19          spin_lock(&p->page_list_lock);
    5.20          list_del(&buf_page->list);
    5.21 @@ -2167,7 +2171,7 @@ long flush_bufs_for_vif(net_vif_t *vif)
    5.22      for ( i = vif->rx_req_cons; 
    5.23            (i != shared_idxs->rx_req_prod) &&
    5.24                ((i-vif->rx_resp_prod) != RX_RING_SIZE);
    5.25 -          i++ );
    5.26 +          i++ )
    5.27      {
    5.28          make_rx_response(vif, shared_rings->rx_ring[MASK_NET_RX_IDX(i)].req.id,
    5.29                           0, RING_STATUS_DROPPED, 0);
    5.30 @@ -2179,6 +2183,7 @@ long flush_bufs_for_vif(net_vif_t *vif)
    5.31  
    5.32          /* Give the buffer page back to the domain. */
    5.33          page = &frame_table[rx->buf_pfn];
    5.34 +        page->u.domain = p;
    5.35          spin_lock(&p->page_list_lock);
    5.36          list_add(&page->list, &p->page_list);
    5.37          page->count_and_flags = PGC_allocated | 2;
    5.38 @@ -2194,7 +2199,10 @@ long flush_bufs_for_vif(net_vif_t *vif)
    5.39               unlikely(cmpxchg(ptep, pte, (rx->buf_pfn<<PAGE_SHIFT) | 
    5.40                                (pte & ~PAGE_MASK) | _PAGE_RW | _PAGE_PRESENT)
    5.41                        != pte) )
    5.42 +        {
    5.43 +            DPRINTK("PTE was modified or reused! %08lx %08lx\n", pte, *ptep);
    5.44              put_page_and_type(page);
    5.45 +        }
    5.46          unmap_domain_mem(ptep);
    5.47  
    5.48          put_page_and_type(&frame_table[rx->pte_ptr >> PAGE_SHIFT]);
     6.1 --- a/xenolinux-2.4.23-sparse/arch/xeno/drivers/network/network.c	Mon Jan 05 22:55:26 2004 +0000
     6.2 +++ b/xenolinux-2.4.23-sparse/arch/xeno/drivers/network/network.c	Tue Jan 06 17:57:55 2004 +0000
     6.3 @@ -60,8 +60,8 @@ struct net_private
     6.4       * {tx,rx}_skbs store outstanding skbuffs. The first entry in each
     6.5       * array is an index into a chain of free entries.
     6.6       */
     6.7 -    struct sk_buff *tx_skbs[TX_RING_SIZE];
     6.8 -    struct sk_buff *rx_skbs[RX_RING_SIZE];
     6.9 +    struct sk_buff *tx_skbs[TX_RING_SIZE+1];
    6.10 +    struct sk_buff *rx_skbs[RX_RING_SIZE+1];
    6.11  };
    6.12  
    6.13  /* Access macros for acquiring freeing slots in {tx,rx}_skbs[]. */
    6.14 @@ -145,9 +145,9 @@ static int network_open(struct net_devic
    6.15      memset(np->net_idx, 0, sizeof(*np->net_idx));
    6.16  
    6.17      /* Initialise {tx,rx}_skbs to be a free chain containing every entry. */
    6.18 -    for ( i = 0; i < TX_RING_SIZE; i++ )
    6.19 +    for ( i = 0; i <= TX_RING_SIZE; i++ )
    6.20          np->tx_skbs[i] = (void *)(i+1);
    6.21 -    for ( i = 0; i < RX_RING_SIZE; i++ )
    6.22 +    for ( i = 0; i <= RX_RING_SIZE; i++ )
    6.23          np->rx_skbs[i] = (void *)(i+1);
    6.24  
    6.25      wmb();