ia64/xen-unstable

changeset 5317:fea2f7f8df31

bitkeeper revision 1.1668 (42a0d81fuv3OiLvByFITCzhO06k4OQ)

Merge http://xen-ia64.bkbits.net/xeno-unstable-ia64.bk
into sportsman.spdomain:/home/djm/xeno-unstable-ia64.bk
author djm@sportsman.spdomain
date Fri Jun 03 22:22:23 2005 +0000 (2005-06-03)
parents e59a94732dd2 fdf28002f13a
children fb827128345c c061e9a30cdf
files linux-2.6.11-xen-sparse/arch/xen/kernel/evtchn.c tools/libxc/xc_linux_build.c tools/libxc/xc_private.h xen/arch/x86/dom0_ops.c xen/arch/x86/extable.c xen/arch/x86/irq.c xen/common/domain.c xen/common/event_channel.c xen/include/public/event_channel.h xen/include/xen/event.h xen/include/xen/sched.h
line diff
     1.1 --- a/linux-2.6.11-xen-sparse/arch/xen/kernel/evtchn.c	Fri Jun 03 22:18:11 2005 +0000
     1.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/kernel/evtchn.c	Fri Jun 03 22:22:23 2005 +0000
     1.3 @@ -74,6 +74,33 @@ static int irq_bindcount[NR_IRQS];
     1.4  /* Bitmap indicating which PIRQs require Xen to be notified on unmask. */
     1.5  static unsigned long pirq_needs_unmask_notify[NR_PIRQS/sizeof(unsigned long)];
     1.6  
     1.7 +#ifdef CONFIG_SMP
     1.8 +
     1.9 +static u8  cpu_evtchn[NR_EVENT_CHANNELS];
    1.10 +static u32 cpu_evtchn_mask[NR_CPUS][NR_EVENT_CHANNELS/32];
    1.11 +
    1.12 +#define active_evtchns(cpu,sh,idx)              \
    1.13 +    ((sh)->evtchn_pending[idx] &                \
    1.14 +     cpu_evtchn_mask[cpu][idx] &                \
    1.15 +     ~(sh)->evtchn_mask[idx])
    1.16 +
    1.17 +static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
    1.18 +{
    1.19 +    clear_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu_evtchn[chn]]);
    1.20 +    set_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu]);
    1.21 +    cpu_evtchn[chn] = cpu;
    1.22 +}
    1.23 +
    1.24 +#else
    1.25 +
    1.26 +#define active_evtchns(cpu,sh,idx)              \
    1.27 +    ((sh)->evtchn_pending[idx] &                \
    1.28 +     ~(sh)->evtchn_mask[idx])
    1.29 +
    1.30 +#define bind_evtchn_to_cpu(chn,cpu) ((void)0)
    1.31 +
    1.32 +#endif
    1.33 +
    1.34  /* Upcall to generic IRQ layer. */
    1.35  #ifdef CONFIG_X86
    1.36  #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
    1.37 @@ -109,9 +136,9 @@ asmlinkage void evtchn_do_upcall(struct 
    1.38  {
    1.39      u32 	   l1, l2;
    1.40      unsigned int   l1i, l2i, port;
    1.41 -    int            irq;
    1.42 +    int            irq, cpu = smp_processor_id();
    1.43      shared_info_t *s = HYPERVISOR_shared_info;
    1.44 -    vcpu_info_t   *vcpu_info = &s->vcpu_data[smp_processor_id()];
    1.45 +    vcpu_info_t   *vcpu_info = &s->vcpu_data[cpu];
    1.46  
    1.47      vcpu_info->evtchn_upcall_pending = 0;
    1.48      
    1.49 @@ -122,7 +149,7 @@ asmlinkage void evtchn_do_upcall(struct 
    1.50          l1i = __ffs(l1);
    1.51          l1 &= ~(1 << l1i);
    1.52          
    1.53 -        while ( (l2 = s->evtchn_pending[l1i] & ~s->evtchn_mask[l1i]) != 0 )
    1.54 +        while ( (l2 = active_evtchns(cpu, s, l1i)) != 0 )
    1.55          {
    1.56              l2i = __ffs(l2);
    1.57              l2 &= ~(1 << l2i);
    1.58 @@ -171,6 +198,8 @@ int bind_virq_to_irq(int virq)
    1.59          irq_to_evtchn[irq]    = evtchn;
    1.60  
    1.61          per_cpu(virq_to_irq, cpu)[virq] = irq;
    1.62 +
    1.63 +        bind_evtchn_to_cpu(evtchn, cpu);
    1.64      }
    1.65  
    1.66      irq_bindcount[irq]++;
    1.67 @@ -225,8 +254,13 @@ int bind_ipi_on_cpu_to_irq(int cpu, int 
    1.68          irq_to_evtchn[irq]    = evtchn;
    1.69  
    1.70          per_cpu(ipi_to_evtchn, cpu)[ipi] = evtchn;
    1.71 -    } else
    1.72 +
    1.73 +        bind_evtchn_to_cpu(evtchn, cpu);
    1.74 +    } 
    1.75 +    else
    1.76 +    {
    1.77  	irq = evtchn_to_irq[evtchn];
    1.78 +    }
    1.79  
    1.80      irq_bindcount[irq]++;
    1.81  
    1.82 @@ -546,6 +580,11 @@ void __init init_IRQ(void)
    1.83  
    1.84      spin_lock_init(&irq_mapping_update_lock);
    1.85  
    1.86 +#ifdef CONFIG_SMP
    1.87 +    /* By default all event channels notify CPU#0. */
    1.88 +    memset(cpu_evtchn_mask[0], ~0, sizeof(cpu_evtchn_mask[0]));
    1.89 +#endif
    1.90 +
    1.91      for ( cpu = 0; cpu < NR_CPUS; cpu++ ) {
    1.92  	/* No VIRQ -> IRQ mappings. */
    1.93  	for ( i = 0; i < NR_VIRQS; i++ )
     2.1 --- a/tools/libxc/xc_linux_build.c	Fri Jun 03 22:18:11 2005 +0000
     2.2 +++ b/tools/libxc/xc_linux_build.c	Fri Jun 03 22:22:23 2005 +0000
     2.3 @@ -3,13 +3,32 @@
     2.4   */
     2.5  
     2.6  #include "xc_private.h"
     2.7 +
     2.8 +#if defined(__i386__)
     2.9  #define ELFSIZE 32
    2.10 +#endif
    2.11 +
    2.12 +#if defined(__x86_64__)
    2.13 +#define ELFSIZE 64
    2.14 +#endif
    2.15 +
    2.16 +
    2.17  #include "xc_elf.h"
    2.18  #include <stdlib.h>
    2.19  #include <zlib.h>
    2.20  
    2.21 +#if defined(__i386__)
    2.22  #define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
    2.23  #define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
    2.24 +#endif
    2.25 +
    2.26 +#if defined(__x86_64__)
    2.27 +#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_USER)
    2.28 +#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
    2.29 +#define L3_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
    2.30 +#define L4_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
    2.31 +#endif
    2.32 +
    2.33  
    2.34  #define round_pgup(_p)    (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
    2.35  #define round_pgdown(_p)  ((_p)&PAGE_MASK)
    2.36 @@ -54,9 +73,17 @@ static int setup_guest(int xc_handle,
    2.37  {
    2.38      l1_pgentry_t *vl1tab=NULL, *vl1e=NULL;
    2.39      l2_pgentry_t *vl2tab=NULL, *vl2e=NULL;
    2.40 +#if defined(__x86_64__)
    2.41 +    l3_pgentry_t *vl3tab=NULL, *vl3e=NULL;
    2.42 +    l4_pgentry_t *vl4tab=NULL, *vl4e=NULL;
    2.43 +#endif
    2.44      unsigned long *page_array = NULL;
    2.45 -    unsigned long l2tab;
    2.46 -    unsigned long l1tab;
    2.47 +    unsigned long l2tab = 0;
    2.48 +    unsigned long l1tab = 0;
    2.49 +#if defined(__x86_64__)
    2.50 +    unsigned long l3tab = 0;
    2.51 +    unsigned long l4tab = 0;
    2.52 +#endif
    2.53      unsigned long count, i;
    2.54      start_info_t *start_info;
    2.55      shared_info_t *shared_info;
    2.56 @@ -111,30 +138,45 @@ static int setup_guest(int xc_handle,
    2.57          vstartinfo_end   = vstartinfo_start + PAGE_SIZE;
    2.58          vstack_start     = vstartinfo_end;
    2.59          vstack_end       = vstack_start + PAGE_SIZE;
    2.60 -        v_end            = (vstack_end + (1<<22)-1) & ~((1<<22)-1);
    2.61 -        if ( (v_end - vstack_end) < (512 << 10) )
    2.62 -            v_end += 1 << 22; /* Add extra 4MB to get >= 512kB padding. */
    2.63 +        v_end            = (vstack_end + (1UL<<22)-1) & ~((1UL<<22)-1);
    2.64 +        if ( (v_end - vstack_end) < (512UL << 10) )
    2.65 +            v_end += 1UL << 22; /* Add extra 4MB to get >= 512kB padding. */
    2.66 +#if defined(__i386__)
    2.67          if ( (((v_end - dsi.v_start + ((1<<L2_PAGETABLE_SHIFT)-1)) >> 
    2.68                 L2_PAGETABLE_SHIFT) + 1) <= nr_pt_pages )
    2.69              break;
    2.70 +#endif
    2.71 +#if defined(__x86_64__)
    2.72 +#define NR(_l,_h,_s) \
    2.73 +    (((((_h) + ((1UL<<(_s))-1)) & ~((1UL<<(_s))-1)) - \
    2.74 +    ((_l) & ~((1UL<<(_s))-1))) >> (_s))
    2.75 +    if ( (1 + /* # L4 */
    2.76 +        NR(dsi.v_start, v_end, L4_PAGETABLE_SHIFT) + /* # L3 */
    2.77 +        NR(dsi.v_start, v_end, L3_PAGETABLE_SHIFT) + /* # L2 */
    2.78 +        NR(dsi.v_start, v_end, L2_PAGETABLE_SHIFT))  /* # L1 */
    2.79 +        <= nr_pt_pages )
    2.80 +            break;
    2.81 +#endif
    2.82      }
    2.83  
    2.84 +#define _p(a) ((void *) (a))
    2.85 +
    2.86      printf("VIRTUAL MEMORY ARRANGEMENT:\n"
    2.87 -           " Loaded kernel: %08lx->%08lx\n"
    2.88 -           " Init. ramdisk: %08lx->%08lx\n"
    2.89 -           " Phys-Mach map: %08lx->%08lx\n"
    2.90 -           " Page tables:   %08lx->%08lx\n"
    2.91 -           " Start info:    %08lx->%08lx\n"
    2.92 -           " Boot stack:    %08lx->%08lx\n"
    2.93 -           " TOTAL:         %08lx->%08lx\n",
    2.94 -           dsi.v_kernstart, dsi.v_kernend, 
    2.95 -           vinitrd_start, vinitrd_end,
    2.96 -           vphysmap_start, vphysmap_end,
    2.97 -           vpt_start, vpt_end,
    2.98 -           vstartinfo_start, vstartinfo_end,
    2.99 -           vstack_start, vstack_end,
   2.100 -           dsi.v_start, v_end);
   2.101 -    printf(" ENTRY ADDRESS: %08lx\n", dsi.v_kernentry);
   2.102 +           " Loaded kernel: %p->%p\n"
   2.103 +           " Init. ramdisk: %p->%p\n"
   2.104 +           " Phys-Mach map: %p->%p\n"
   2.105 +           " Page tables:   %p->%p\n"
   2.106 +           " Start info:    %p->%p\n"
   2.107 +           " Boot stack:    %p->%p\n"
   2.108 +           " TOTAL:         %p->%p\n",
   2.109 +           _p(dsi.v_kernstart), _p(dsi.v_kernend), 
   2.110 +           _p(vinitrd_start), _p(vinitrd_end),
   2.111 +           _p(vphysmap_start), _p(vphysmap_end),
   2.112 +           _p(vpt_start), _p(vpt_end),
   2.113 +           _p(vstartinfo_start), _p(vstartinfo_end),
   2.114 +           _p(vstack_start), _p(vstack_end),
   2.115 +           _p(dsi.v_start), _p(v_end));
   2.116 +    printf(" ENTRY ADDRESS: %p\n", _p(dsi.v_kernentry));
   2.117  
   2.118      if ( (v_end - dsi.v_start) > (nr_pages * PAGE_SIZE) )
   2.119      {
   2.120 @@ -178,6 +220,7 @@ static int setup_guest(int xc_handle,
   2.121      if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL )
   2.122          goto error_out;
   2.123  
   2.124 +#if defined(__i386__)
   2.125      /* First allocate page for page dir. */
   2.126      ppt_alloc = (vpt_start - dsi.v_start) >> PAGE_SHIFT;
   2.127      l2tab = page_array[ppt_alloc++] << PAGE_SHIFT;
   2.128 @@ -217,6 +260,74 @@ static int setup_guest(int xc_handle,
   2.129      }
   2.130      munmap(vl1tab, PAGE_SIZE);
   2.131      munmap(vl2tab, PAGE_SIZE);
   2.132 +#endif
   2.133 +#if defined(__x86_64__)
   2.134 +
   2.135 +#define alloc_pt(ltab, vltab) \
   2.136 +        ltab = page_array[ppt_alloc++] << PAGE_SHIFT; \
   2.137 +        if (vltab != NULL) { \
   2.138 +            munmap(vltab, PAGE_SIZE); \
   2.139 +        } \
   2.140 +        if ((vltab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, \
   2.141 +                          PROT_READ|PROT_WRITE, \
   2.142 +                          ltab >> PAGE_SHIFT)) == NULL) { \
   2.143 +            munmap(vltab, PAGE_SIZE); \
   2.144 +            goto error_out; \
   2.145 +        } \
   2.146 +        memset(vltab, 0, PAGE_SIZE);
   2.147 +
   2.148 +    /* First allocate page for page dir. */
   2.149 +    ppt_alloc = (vpt_start - dsi.v_start) >> PAGE_SHIFT;
   2.150 +    l4tab = page_array[ppt_alloc++] << PAGE_SHIFT;
   2.151 +    ctxt->pt_base = l4tab;
   2.152 +    
   2.153 +    /* Intiliaize page table */
   2.154 +    if ( (vl4tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
   2.155 +                                        PROT_READ|PROT_WRITE,
   2.156 +                                        l4tab >> PAGE_SHIFT)) == NULL )
   2.157 +            goto error_out;
   2.158 +    memset(vl4tab, 0, PAGE_SIZE);
   2.159 +    vl4e = &vl4tab[l4_table_offset(dsi.v_start)];
   2.160 +    
   2.161 +    for ( count = 0; count < ((v_end-dsi.v_start)>>PAGE_SHIFT); count++)
   2.162 +    {
   2.163 +        if ( !((unsigned long)vl1e & (PAGE_SIZE-1)) )
   2.164 +        {
   2.165 +            alloc_pt(l1tab, vl1tab);
   2.166 +            
   2.167 +                if ( !((unsigned long)vl2e & (PAGE_SIZE-1)) )
   2.168 +                {
   2.169 +                    alloc_pt(l2tab, vl2tab);
   2.170 +                    if ( !((unsigned long)vl3e & (PAGE_SIZE-1)) )
   2.171 +                    {
   2.172 +                        alloc_pt(l3tab, vl3tab);
   2.173 +                        vl3e = &vl3tab[l3_table_offset(dsi.v_start + (count<<PAGE_SHIFT))];
   2.174 +                        *vl4e = l3tab | L4_PROT;
   2.175 +                        vl4e++;
   2.176 +                    }
   2.177 +                    vl2e = &vl2tab[l2_table_offset(dsi.v_start + (count<<PAGE_SHIFT))];
   2.178 +                    *vl3e = l2tab | L3_PROT;
   2.179 +                    vl3e++;
   2.180 +                }
   2.181 +            vl1e = &vl1tab[l1_table_offset(dsi.v_start + (count<<PAGE_SHIFT))];
   2.182 +            *vl2e = l1tab | L2_PROT;
   2.183 +            vl2e++;
   2.184 +        }
   2.185 +        
   2.186 +        *vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT;
   2.187 +        if ( (count >= ((vpt_start-dsi.v_start)>>PAGE_SHIFT)) &&
   2.188 +            (count <  ((vpt_end  -dsi.v_start)>>PAGE_SHIFT)) ) 
   2.189 +        {
   2.190 +                *vl1e &= ~_PAGE_RW;
   2.191 +        }
   2.192 +            vl1e++;
   2.193 +    }
   2.194 +     
   2.195 +    munmap(vl1tab, PAGE_SIZE);
   2.196 +    munmap(vl2tab, PAGE_SIZE);
   2.197 +    munmap(vl3tab, PAGE_SIZE);
   2.198 +    munmap(vl4tab, PAGE_SIZE);
   2.199 +#endif
   2.200  
   2.201      /* Write the phys->machine and machine->phys table entries. */
   2.202      physmap_pfn = (vphysmap_start - dsi.v_start) >> PAGE_SHIFT;
   2.203 @@ -243,13 +354,23 @@ static int setup_guest(int xc_handle,
   2.204      }
   2.205      munmap(physmap, PAGE_SIZE);
   2.206      
   2.207 +#if defined(__i386__)
   2.208      /*
   2.209       * Pin down l2tab addr as page dir page - causes hypervisor to provide
   2.210       * correct protection for the page
   2.211       */ 
   2.212      if ( pin_table(xc_handle, MMUEXT_PIN_L2_TABLE, l2tab>>PAGE_SHIFT, dom) )
   2.213          goto error_out;
   2.214 +#endif
   2.215  
   2.216 +#if defined(__x86_64__)
   2.217 +    /*
   2.218 +     * Pin down l4tab addr as page dir page - causes hypervisor to  provide
   2.219 +     * correct protection for the page
   2.220 +     */
   2.221 +     if ( pin_table(xc_handle, MMUEXT_PIN_L4_TABLE, l4tab>>PAGE_SHIFT, dom) )
   2.222 +        goto error_out;
   2.223 +#endif
   2.224      start_info = xc_map_foreign_range(
   2.225          xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
   2.226          page_array[(vstartinfo_start-dsi.v_start)>>PAGE_SHIFT]);
   2.227 @@ -409,7 +530,7 @@ int xc_linux_build(int xc_handle,
   2.228      ctxt->user_regs.es = FLAT_KERNEL_DS;
   2.229      ctxt->user_regs.fs = FLAT_KERNEL_DS;
   2.230      ctxt->user_regs.gs = FLAT_KERNEL_DS;
   2.231 -    ctxt->user_regs.ss = FLAT_KERNEL_DS;
   2.232 +    ctxt->user_regs.ss = FLAT_KERNEL_SS;
   2.233      ctxt->user_regs.cs = FLAT_KERNEL_CS;
   2.234      ctxt->user_regs.eip = vkern_entry;
   2.235      ctxt->user_regs.esp = vstartinfo_start + 2*PAGE_SIZE;
   2.236 @@ -433,7 +554,7 @@ int xc_linux_build(int xc_handle,
   2.237      ctxt->gdt_ents = 0;
   2.238  
   2.239      /* Ring 1 stack is the initial stack. */
   2.240 -    ctxt->kernel_ss = FLAT_KERNEL_DS;
   2.241 +    ctxt->kernel_ss = FLAT_KERNEL_SS;
   2.242      ctxt->kernel_sp = vstartinfo_start + 2*PAGE_SIZE;
   2.243  
   2.244      /* No debugging. */
     3.1 --- a/tools/libxc/xc_private.h	Fri Jun 03 22:18:11 2005 +0000
     3.2 +++ b/tools/libxc/xc_private.h	Fri Jun 03 22:22:23 2005 +0000
     3.3 @@ -29,12 +29,25 @@
     3.4  #define _PAGE_PSE       0x080
     3.5  #define _PAGE_GLOBAL    0x100
     3.6  
     3.7 -
     3.8 +#if defined(__i386__)
     3.9  #define L1_PAGETABLE_SHIFT       12
    3.10  #define L2_PAGETABLE_SHIFT       22
    3.11 - 
    3.12 +#elif defined(__x86_64__)
    3.13 +#define L1_PAGETABLE_SHIFT      12
    3.14 +#define L2_PAGETABLE_SHIFT      21
    3.15 +#define L3_PAGETABLE_SHIFT      30
    3.16 +#define L4_PAGETABLE_SHIFT      39
    3.17 +#endif
    3.18 +
    3.19 +#if defined(__i386__) 
    3.20  #define ENTRIES_PER_L1_PAGETABLE 1024
    3.21  #define ENTRIES_PER_L2_PAGETABLE 1024
    3.22 +#elif defined(__x86_64__)
    3.23 +#define L1_PAGETABLE_ENTRIES    512
    3.24 +#define L2_PAGETABLE_ENTRIES    512
    3.25 +#define L3_PAGETABLE_ENTRIES    512
    3.26 +#define L4_PAGETABLE_ENTRIES    512
    3.27 +#endif
    3.28   
    3.29  #define PAGE_SHIFT              L1_PAGETABLE_SHIFT
    3.30  #define PAGE_SIZE               (1UL << PAGE_SHIFT)
    3.31 @@ -42,11 +55,26 @@
    3.32  
    3.33  typedef unsigned long l1_pgentry_t;
    3.34  typedef unsigned long l2_pgentry_t;
    3.35 +#if defined(__x86_64__)
    3.36 +typedef unsigned long l3_pgentry_t;
    3.37 +typedef unsigned long l4_pgentry_t;
    3.38 +#endif
    3.39  
    3.40 +#if defined(__i386__)
    3.41  #define l1_table_offset(_a) \
    3.42            (((_a) >> L1_PAGETABLE_SHIFT) & (ENTRIES_PER_L1_PAGETABLE - 1))
    3.43  #define l2_table_offset(_a) \
    3.44            ((_a) >> L2_PAGETABLE_SHIFT)
    3.45 +#elif defined(__x86_64__)
    3.46 +#define l1_table_offset(_a) \
    3.47 +  (((_a) >> L1_PAGETABLE_SHIFT) & (L1_PAGETABLE_ENTRIES - 1))
    3.48 +#define l2_table_offset(_a) \
    3.49 +  (((_a) >> L2_PAGETABLE_SHIFT) & (L2_PAGETABLE_ENTRIES - 1))
    3.50 +#define l3_table_offset(_a) \
    3.51 +	(((_a) >> L3_PAGETABLE_SHIFT) & (L3_PAGETABLE_ENTRIES - 1))
    3.52 +#define l4_table_offset(_a) \
    3.53 +	(((_a) >> L4_PAGETABLE_SHIFT) & (L4_PAGETABLE_ENTRIES - 1))
    3.54 +#endif
    3.55  
    3.56  #define ERROR(_m, _a...)  \
    3.57      fprintf(stderr, "ERROR: " _m "\n" , ## _a )
     4.1 --- a/xen/arch/x86/dom0_ops.c	Fri Jun 03 22:18:11 2005 +0000
     4.2 +++ b/xen/arch/x86/dom0_ops.c	Fri Jun 03 22:22:23 2005 +0000
     4.3 @@ -155,7 +155,10 @@ long arch_do_dom0_op(dom0_op_t *op, dom0
     4.4          {
     4.5              if ( (d->arch.iobmp_mask = xmalloc_array(
     4.6                  u8, IOBMP_BYTES)) == NULL )
     4.7 +            {
     4.8 +                put_domain(d);
     4.9                  break;
    4.10 +            }
    4.11              memset(d->arch.iobmp_mask, 0xFF, IOBMP_BYTES);
    4.12          }
    4.13  
     5.1 --- a/xen/arch/x86/extable.c	Fri Jun 03 22:18:11 2005 +0000
     5.2 +++ b/xen/arch/x86/extable.c	Fri Jun 03 22:22:23 2005 +0000
     5.3 @@ -6,6 +6,7 @@
     5.4  #ifdef PERF_COUNTERS
     5.5  #include <xen/sched.h>
     5.6  #include <xen/perfc.h>
     5.7 +#include <asm/current.h>
     5.8  #endif
     5.9  
    5.10  extern struct exception_table_entry __start___ex_table[];
     6.1 --- a/xen/arch/x86/irq.c	Fri Jun 03 22:18:11 2005 +0000
     6.2 +++ b/xen/arch/x86/irq.c	Fri Jun 03 22:22:23 2005 +0000
     6.3 @@ -184,22 +184,22 @@ typedef struct {
     6.4      u8 nr_guests;
     6.5      u8 in_flight;
     6.6      u8 shareable;
     6.7 -    struct vcpu *guest[IRQ_MAX_GUESTS];
     6.8 +    struct domain *guest[IRQ_MAX_GUESTS];
     6.9  } irq_guest_action_t;
    6.10  
    6.11  static void __do_IRQ_guest(int irq)
    6.12  {
    6.13      irq_desc_t         *desc = &irq_desc[irq];
    6.14      irq_guest_action_t *action = (irq_guest_action_t *)desc->action;
    6.15 -    struct vcpu        *v;
    6.16 +    struct domain      *d;
    6.17      int                 i;
    6.18  
    6.19      for ( i = 0; i < action->nr_guests; i++ )
    6.20      {
    6.21 -        v = action->guest[i];
    6.22 -        if ( !test_and_set_bit(irq, &v->domain->pirq_mask) )
    6.23 +        d = action->guest[i];
    6.24 +        if ( !test_and_set_bit(irq, &d->pirq_mask) )
    6.25              action->in_flight++;
    6.26 -        send_guest_pirq(v, irq);
    6.27 +        send_guest_pirq(d, irq);
    6.28      }
    6.29  }
    6.30  
    6.31 @@ -294,7 +294,7 @@ int pirq_guest_bind(struct vcpu *v, int 
    6.32          goto out;
    6.33      }
    6.34  
    6.35 -    action->guest[action->nr_guests++] = v;
    6.36 +    action->guest[action->nr_guests++] = v->domain;
    6.37  
    6.38   out:
    6.39      spin_unlock_irqrestore(&desc->lock, flags);
    6.40 @@ -328,7 +328,7 @@ int pirq_guest_unbind(struct domain *d, 
    6.41      else
    6.42      {
    6.43          i = 0;
    6.44 -        while ( action->guest[i] && action->guest[i]->domain != d )
    6.45 +        while ( action->guest[i] && (action->guest[i] != d) )
    6.46              i++;
    6.47          memmove(&action->guest[i], &action->guest[i+1], IRQ_MAX_GUESTS-i-1);
    6.48          action->nr_guests--;
     7.1 --- a/xen/common/domain.c	Fri Jun 03 22:18:11 2005 +0000
     7.2 +++ b/xen/common/domain.c	Fri Jun 03 22:22:23 2005 +0000
     7.3 @@ -54,9 +54,9 @@ struct domain *do_createdomain(domid_t d
     7.4          set_bit(_DOMF_idle_domain, &d->domain_flags);
     7.5  
     7.6      if ( !is_idle_task(d) &&
     7.7 -         ((init_event_channels(d) != 0) || (grant_table_create(d) != 0)) )
     7.8 +         ((evtchn_init(d) != 0) || (grant_table_create(d) != 0)) )
     7.9      {
    7.10 -        destroy_event_channels(d);
    7.11 +        evtchn_destroy(d);
    7.12          free_domain_struct(d);
    7.13          return NULL;
    7.14      }
    7.15 @@ -251,7 +251,7 @@ void domain_destruct(struct domain *d)
    7.16      *pd = d->next_in_hashbucket;
    7.17      write_unlock(&domlist_lock);
    7.18  
    7.19 -    destroy_event_channels(d);
    7.20 +    evtchn_destroy(d);
    7.21      grant_table_destroy(d);
    7.22  
    7.23      free_perdomain_pt(d);
     8.1 --- a/xen/common/event_channel.c	Fri Jun 03 22:18:11 2005 +0000
     8.2 +++ b/xen/common/event_channel.c	Fri Jun 03 22:22:23 2005 +0000
     8.3 @@ -27,50 +27,31 @@
     8.4  #include <public/xen.h>
     8.5  #include <public/event_channel.h>
     8.6  
     8.7 -#define INIT_EVENT_CHANNELS   16
     8.8 -#define MAX_EVENT_CHANNELS  1024
     8.9 -#define EVENT_CHANNELS_SPREAD 32
    8.10 +#define bucket_from_port(d,p) \
    8.11 +    ((d)->evtchn[(p)/EVTCHNS_PER_BUCKET])
    8.12 +#define port_is_valid(d,p)    \
    8.13 +    (((p) >= 0) && ((p) < MAX_EVTCHNS) && \
    8.14 +     (bucket_from_port(d,p) != NULL))
    8.15 +#define evtchn_from_port(d,p) \
    8.16 +    (&(bucket_from_port(d,p))[(p)&(EVTCHNS_PER_BUCKET-1)])
    8.17  
    8.18 -
    8.19 -static int get_free_port(struct vcpu *v)
    8.20 +static int get_free_port(struct domain *d)
    8.21  {
    8.22 -    struct domain *d = v->domain;
    8.23 -    int max, port;
    8.24 -    event_channel_t *chn;
    8.25 -
    8.26 -    max = d->max_event_channel;
    8.27 -    chn = d->event_channel;
    8.28 -
    8.29 -    for ( port = v->vcpu_id * EVENT_CHANNELS_SPREAD; port < max; port++ )
    8.30 -        if ( chn[port].state == ECS_FREE )
    8.31 -            break;
    8.32 +    struct evtchn *chn;
    8.33 +    int            port;
    8.34  
    8.35 -    if ( port >= max )
    8.36 -    {
    8.37 -        if ( max == MAX_EVENT_CHANNELS )
    8.38 -            return -ENOSPC;
    8.39 +    for ( port = 0; port_is_valid(d, port); port++ )
    8.40 +        if ( evtchn_from_port(d, port)->state == ECS_FREE )
    8.41 +            return port;
    8.42  
    8.43 -        if ( port == 0 )
    8.44 -            max = INIT_EVENT_CHANNELS;
    8.45 -        else
    8.46 -            max = port + EVENT_CHANNELS_SPREAD;
    8.47 -        
    8.48 -        chn = xmalloc_array(event_channel_t, max);
    8.49 -        if ( unlikely(chn == NULL) )
    8.50 -            return -ENOMEM;
    8.51 -
    8.52 -        memset(chn, 0, max * sizeof(event_channel_t));
    8.53 +    if ( port == MAX_EVTCHNS )
    8.54 +        return -ENOSPC;
    8.55  
    8.56 -        if ( d->event_channel != NULL )
    8.57 -        {
    8.58 -            memcpy(chn, d->event_channel, d->max_event_channel *
    8.59 -                   sizeof(event_channel_t));
    8.60 -            xfree(d->event_channel);
    8.61 -        }
    8.62 -
    8.63 -        d->event_channel     = chn;
    8.64 -        d->max_event_channel = max;
    8.65 -    }
    8.66 +    chn = xmalloc_array(struct evtchn, EVTCHNS_PER_BUCKET);
    8.67 +    if ( unlikely(chn == NULL) )
    8.68 +        return -ENOMEM;
    8.69 +    memset(chn, 0, EVTCHNS_PER_BUCKET * sizeof(*chn));
    8.70 +    bucket_from_port(d, port) = chn;
    8.71  
    8.72      return port;
    8.73  }
    8.74 @@ -78,18 +59,20 @@ static int get_free_port(struct vcpu *v)
    8.75  
    8.76  static long evtchn_alloc_unbound(evtchn_alloc_unbound_t *alloc)
    8.77  {
    8.78 +    struct evtchn *chn;
    8.79      struct domain *d = current->domain;
    8.80      int            port;
    8.81  
    8.82 -    spin_lock(&d->event_channel_lock);
    8.83 +    spin_lock(&d->evtchn_lock);
    8.84  
    8.85 -    if ( (port = get_free_port(current)) >= 0 )
    8.86 +    if ( (port = get_free_port(d)) >= 0 )
    8.87      {
    8.88 -        d->event_channel[port].state = ECS_UNBOUND;
    8.89 -        d->event_channel[port].u.unbound.remote_domid = alloc->dom;
    8.90 +        chn = evtchn_from_port(d, port);
    8.91 +        chn->state = ECS_UNBOUND;
    8.92 +        chn->u.unbound.remote_domid = alloc->dom;
    8.93      }
    8.94  
    8.95 -    spin_unlock(&d->event_channel_lock);
    8.96 +    spin_unlock(&d->evtchn_lock);
    8.97  
    8.98      if ( port < 0 )
    8.99          return port;
   8.100 @@ -102,8 +85,8 @@ static long evtchn_alloc_unbound(evtchn_
   8.101  static long evtchn_bind_interdomain(evtchn_bind_interdomain_t *bind)
   8.102  {
   8.103  #define ERROR_EXIT(_errno) do { rc = (_errno); goto out; } while ( 0 )
   8.104 +    struct evtchn *chn1, *chn2;
   8.105      struct domain *d1, *d2;
   8.106 -    struct vcpu   *v1, *v2;
   8.107      int            port1 = bind->port1, port2 = bind->port2;
   8.108      domid_t        dom1 = bind->dom1, dom2 = bind->dom2;
   8.109      long           rc = 0;
   8.110 @@ -111,9 +94,6 @@ static long evtchn_bind_interdomain(evtc
   8.111      if ( !IS_PRIV(current->domain) && (dom1 != DOMID_SELF) )
   8.112          return -EPERM;
   8.113  
   8.114 -    if ( (port1 < 0) || (port2 < 0) )
   8.115 -        return -EINVAL;
   8.116 -
   8.117      if ( dom1 == DOMID_SELF )
   8.118          dom1 = current->domain->domain_id;
   8.119      if ( dom2 == DOMID_SELF )
   8.120 @@ -127,63 +107,61 @@ static long evtchn_bind_interdomain(evtc
   8.121          return -ESRCH;
   8.122      }
   8.123  
   8.124 -    v1 = d1->vcpu[0];   /* XXX */
   8.125 -    v2 = d2->vcpu[0];   /* XXX */
   8.126 -
   8.127      /* Avoid deadlock by first acquiring lock of domain with smaller id. */
   8.128      if ( d1 < d2 )
   8.129      {
   8.130 -        spin_lock(&d1->event_channel_lock);
   8.131 -        spin_lock(&d2->event_channel_lock);
   8.132 +        spin_lock(&d1->evtchn_lock);
   8.133 +        spin_lock(&d2->evtchn_lock);
   8.134      }
   8.135      else
   8.136      {
   8.137          if ( d1 != d2 )
   8.138 -            spin_lock(&d2->event_channel_lock);
   8.139 -        spin_lock(&d1->event_channel_lock);
   8.140 +            spin_lock(&d2->evtchn_lock);
   8.141 +        spin_lock(&d1->evtchn_lock);
   8.142      }
   8.143  
   8.144      /* Obtain, or ensure that we already have, a valid <port1>. */
   8.145      if ( port1 == 0 )
   8.146      {
   8.147 -        if ( (port1 = get_free_port(v1)) < 0 )
   8.148 +        if ( (port1 = get_free_port(d1)) < 0 )
   8.149              ERROR_EXIT(port1);
   8.150      }
   8.151 -    else if ( port1 >= d1->max_event_channel )
   8.152 +    else if ( !port_is_valid(d1, port1) )
   8.153          ERROR_EXIT(-EINVAL);
   8.154 +    chn1 = evtchn_from_port(d1, port1);
   8.155  
   8.156      /* Obtain, or ensure that we already have, a valid <port2>. */
   8.157      if ( port2 == 0 )
   8.158      {
   8.159          /* Make port1 non-free while we allocate port2 (in case dom1==dom2). */
   8.160 -        u16 tmp = d1->event_channel[port1].state;
   8.161 -        d1->event_channel[port1].state = ECS_INTERDOMAIN;
   8.162 -        port2 = get_free_port(v2);
   8.163 -        d1->event_channel[port1].state = tmp;
   8.164 +        u16 state = chn1->state;
   8.165 +        chn1->state = ECS_INTERDOMAIN;
   8.166 +        port2 = get_free_port(d2);
   8.167 +        chn1->state = state;
   8.168          if ( port2 < 0 )
   8.169              ERROR_EXIT(port2);
   8.170      }
   8.171 -    else if ( port2 >= d2->max_event_channel )
   8.172 +    else if ( !port_is_valid(d2, port2) )
   8.173          ERROR_EXIT(-EINVAL);
   8.174 +    chn2 = evtchn_from_port(d2, port2);
   8.175  
   8.176      /* Validate <dom1,port1>'s current state. */
   8.177 -    switch ( d1->event_channel[port1].state )
   8.178 +    switch ( chn1->state )
   8.179      {
   8.180      case ECS_FREE:
   8.181          break;
   8.182  
   8.183      case ECS_UNBOUND:
   8.184 -        if ( d1->event_channel[port1].u.unbound.remote_domid != dom2 )
   8.185 +        if ( chn1->u.unbound.remote_domid != dom2 )
   8.186              ERROR_EXIT(-EINVAL);
   8.187          break;
   8.188  
   8.189      case ECS_INTERDOMAIN:
   8.190 -        if ( d1->event_channel[port1].u.interdomain.remote_dom != v2 )
   8.191 +        if ( chn1->u.interdomain.remote_dom != d2 )
   8.192              ERROR_EXIT(-EINVAL);
   8.193 -        if ( (d1->event_channel[port1].u.interdomain.remote_port != port2) &&
   8.194 -             (bind->port2 != 0) )
   8.195 +        if ( (chn1->u.interdomain.remote_port != port2) && (bind->port2 != 0) )
   8.196              ERROR_EXIT(-EINVAL);
   8.197 -        port2 = d1->event_channel[port1].u.interdomain.remote_port;
   8.198 +        port2 = chn1->u.interdomain.remote_port;
   8.199          goto out;
   8.200  
   8.201      default:
   8.202 @@ -191,7 +169,7 @@ static long evtchn_bind_interdomain(evtc
   8.203      }
   8.204  
   8.205      /* Validate <dom2,port2>'s current state. */
   8.206 -    switch ( d2->event_channel[port2].state )
   8.207 +    switch ( chn2->state )
   8.208      {
   8.209      case ECS_FREE:
   8.210          if ( !IS_PRIV(current->domain) && (dom2 != DOMID_SELF) )
   8.211 @@ -199,17 +177,16 @@ static long evtchn_bind_interdomain(evtc
   8.212          break;
   8.213  
   8.214      case ECS_UNBOUND:
   8.215 -        if ( d2->event_channel[port2].u.unbound.remote_domid != dom1 )
   8.216 +        if ( chn2->u.unbound.remote_domid != dom1 )
   8.217              ERROR_EXIT(-EINVAL);
   8.218          break;
   8.219  
   8.220      case ECS_INTERDOMAIN:
   8.221 -        if ( d2->event_channel[port2].u.interdomain.remote_dom != v1 )
   8.222 +        if ( chn2->u.interdomain.remote_dom != d1 )
   8.223              ERROR_EXIT(-EINVAL);
   8.224 -        if ( (d2->event_channel[port2].u.interdomain.remote_port != port1) &&
   8.225 -             (bind->port1 != 0) )
   8.226 +        if ( (chn2->u.interdomain.remote_port != port1) && (bind->port1 != 0) )
   8.227              ERROR_EXIT(-EINVAL);
   8.228 -        port1 = d2->event_channel[port2].u.interdomain.remote_port;
   8.229 +        port1 = chn2->u.interdomain.remote_port;
   8.230          goto out;
   8.231  
   8.232      default:
   8.233 @@ -220,18 +197,18 @@ static long evtchn_bind_interdomain(evtc
   8.234       * Everything checked out okay -- bind <dom1,port1> to <dom2,port2>.
   8.235       */
   8.236  
   8.237 -    d1->event_channel[port1].u.interdomain.remote_dom  = v2;
   8.238 -    d1->event_channel[port1].u.interdomain.remote_port = (u16)port2;
   8.239 -    d1->event_channel[port1].state                     = ECS_INTERDOMAIN;
   8.240 +    chn1->u.interdomain.remote_dom  = d2;
   8.241 +    chn1->u.interdomain.remote_port = (u16)port2;
   8.242 +    chn1->state                     = ECS_INTERDOMAIN;
   8.243      
   8.244 -    d2->event_channel[port2].u.interdomain.remote_dom  = v1;
   8.245 -    d2->event_channel[port2].u.interdomain.remote_port = (u16)port1;
   8.246 -    d2->event_channel[port2].state                     = ECS_INTERDOMAIN;
   8.247 +    chn2->u.interdomain.remote_dom  = d1;
   8.248 +    chn2->u.interdomain.remote_port = (u16)port1;
   8.249 +    chn2->state                     = ECS_INTERDOMAIN;
   8.250  
   8.251   out:
   8.252 -    spin_unlock(&d1->event_channel_lock);
   8.253 +    spin_unlock(&d1->evtchn_lock);
   8.254      if ( d1 != d2 )
   8.255 -        spin_unlock(&d2->event_channel_lock);
   8.256 +        spin_unlock(&d2->evtchn_lock);
   8.257      
   8.258      put_domain(d1);
   8.259      put_domain(d2);
   8.260 @@ -246,6 +223,7 @@ static long evtchn_bind_interdomain(evtc
   8.261  
   8.262  static long evtchn_bind_virq(evtchn_bind_virq_t *bind)
   8.263  {
   8.264 +    struct evtchn *chn;
   8.265      struct vcpu   *v = current;
   8.266      struct domain *d = v->domain;
   8.267      int            port, virq = bind->virq;
   8.268 @@ -253,23 +231,25 @@ static long evtchn_bind_virq(evtchn_bind
   8.269      if ( virq >= ARRAY_SIZE(v->virq_to_evtchn) )
   8.270          return -EINVAL;
   8.271  
   8.272 -    spin_lock(&d->event_channel_lock);
   8.273 +    spin_lock(&d->evtchn_lock);
   8.274  
   8.275      /*
   8.276       * Port 0 is the fallback port for VIRQs that haven't been explicitly
   8.277       * bound yet.
   8.278       */
   8.279      if ( ((port = v->virq_to_evtchn[virq]) != 0) ||
   8.280 -         ((port = get_free_port(v)) < 0) )
   8.281 +         ((port = get_free_port(d)) < 0) )
   8.282          goto out;
   8.283  
   8.284 -    d->event_channel[port].state  = ECS_VIRQ;
   8.285 -    d->event_channel[port].u.virq = virq;
   8.286 +    chn = evtchn_from_port(d, port);
   8.287 +    chn->state          = ECS_VIRQ;
   8.288 +    chn->notify_vcpu_id = v->vcpu_id;
   8.289 +    chn->u.virq         = virq;
   8.290  
   8.291      v->virq_to_evtchn[virq] = port;
   8.292  
   8.293   out:
   8.294 -    spin_unlock(&d->event_channel_lock);
   8.295 +    spin_unlock(&d->evtchn_lock);
   8.296  
   8.297      if ( port < 0 )
   8.298          return port;
   8.299 @@ -278,24 +258,26 @@ static long evtchn_bind_virq(evtchn_bind
   8.300      return 0;
   8.301  }
   8.302  
   8.303 +
   8.304  static long evtchn_bind_ipi(evtchn_bind_ipi_t *bind)
   8.305  {
   8.306 -    struct vcpu   *v = current;
   8.307 -    struct domain *d = v->domain;
   8.308 +    struct evtchn *chn;
   8.309 +    struct domain *d = current->domain;
   8.310      int            port, ipi_vcpu = bind->ipi_vcpu;
   8.311  
   8.312 -    if ( ipi_vcpu >= MAX_VIRT_CPUS )
   8.313 +    if ( (ipi_vcpu >= MAX_VIRT_CPUS) || (d->vcpu[ipi_vcpu] == NULL) )
   8.314          return -EINVAL;
   8.315  
   8.316 -    spin_lock(&d->event_channel_lock);
   8.317 +    spin_lock(&d->evtchn_lock);
   8.318  
   8.319 -    if ( (port = get_free_port(v)) >= 0 )
   8.320 +    if ( (port = get_free_port(d)) >= 0 )
   8.321      {
   8.322 -        d->event_channel[port].state      = ECS_IPI;
   8.323 -        d->event_channel[port].u.ipi_vcpu = ipi_vcpu;
   8.324 +        chn = evtchn_from_port(d, port);
   8.325 +        chn->state          = ECS_IPI;
   8.326 +        chn->notify_vcpu_id = ipi_vcpu;
   8.327      }
   8.328  
   8.329 -    spin_unlock(&d->event_channel_lock);
   8.330 +    spin_unlock(&d->evtchn_lock);
   8.331  
   8.332      if ( port < 0 )
   8.333          return port;
   8.334 @@ -307,20 +289,23 @@ static long evtchn_bind_ipi(evtchn_bind_
   8.335  
   8.336  static long evtchn_bind_pirq(evtchn_bind_pirq_t *bind)
   8.337  {
   8.338 +    struct evtchn *chn;
   8.339      struct domain *d = current->domain;
   8.340      int            port, rc, pirq = bind->pirq;
   8.341  
   8.342      if ( pirq >= ARRAY_SIZE(d->pirq_to_evtchn) )
   8.343          return -EINVAL;
   8.344  
   8.345 -    spin_lock(&d->event_channel_lock);
   8.346 +    spin_lock(&d->evtchn_lock);
   8.347  
   8.348      if ( ((rc = port = d->pirq_to_evtchn[pirq]) != 0) ||
   8.349 -         ((rc = port = get_free_port(current)) < 0) )
   8.350 +         ((rc = port = get_free_port(d)) < 0) )
   8.351          goto out;
   8.352  
   8.353 +    chn = evtchn_from_port(d, port);
   8.354 +
   8.355      d->pirq_to_evtchn[pirq] = port;
   8.356 -    rc = pirq_guest_bind(current, pirq, 
   8.357 +    rc = pirq_guest_bind(d->vcpu[chn->notify_vcpu_id], pirq, 
   8.358                           !!(bind->flags & BIND_PIRQ__WILL_SHARE));
   8.359      if ( rc != 0 )
   8.360      {
   8.361 @@ -328,11 +313,11 @@ static long evtchn_bind_pirq(evtchn_bind
   8.362          goto out;
   8.363      }
   8.364  
   8.365 -    d->event_channel[port].state  = ECS_PIRQ;
   8.366 -    d->event_channel[port].u.pirq = pirq;
   8.367 +    chn->state  = ECS_PIRQ;
   8.368 +    chn->u.pirq = pirq;
   8.369  
   8.370   out:
   8.371 -    spin_unlock(&d->event_channel_lock);
   8.372 +    spin_unlock(&d->evtchn_lock);
   8.373  
   8.374      if ( rc < 0 )
   8.375          return rc;
   8.376 @@ -344,24 +329,23 @@ static long evtchn_bind_pirq(evtchn_bind
   8.377  
   8.378  static long __evtchn_close(struct domain *d1, int port1)
   8.379  {
   8.380 -    struct domain   *d2 = NULL;
   8.381 -    struct vcpu *v;
   8.382 -    event_channel_t *chn1, *chn2;
   8.383 -    int              port2;
   8.384 -    long             rc = 0;
   8.385 +    struct domain *d2 = NULL;
   8.386 +    struct vcpu   *v;
   8.387 +    struct evtchn *chn1, *chn2;
   8.388 +    int            port2;
   8.389 +    long           rc = 0;
   8.390  
   8.391   again:
   8.392 -    spin_lock(&d1->event_channel_lock);
   8.393 +    spin_lock(&d1->evtchn_lock);
   8.394  
   8.395 -    chn1 = d1->event_channel;
   8.396 -
   8.397 -    if ( (port1 < 0) || (port1 >= d1->max_event_channel) )
   8.398 +    if ( !port_is_valid(d1, port1) )
   8.399      {
   8.400          rc = -EINVAL;
   8.401          goto out;
   8.402      }
   8.403  
   8.404 -    switch ( chn1[port1].state )
   8.405 +    chn1 = evtchn_from_port(d1, port1);
   8.406 +    switch ( chn1->state )
   8.407      {
   8.408      case ECS_FREE:
   8.409      case ECS_RESERVED:
   8.410 @@ -372,15 +356,14 @@ static long __evtchn_close(struct domain
   8.411          break;
   8.412  
   8.413      case ECS_PIRQ:
   8.414 -        if ( (rc = pirq_guest_unbind(d1, chn1[port1].u.pirq)) == 0 )
   8.415 -            d1->pirq_to_evtchn[chn1[port1].u.pirq] = 0;
   8.416 +        if ( (rc = pirq_guest_unbind(d1, chn1->u.pirq)) == 0 )
   8.417 +            d1->pirq_to_evtchn[chn1->u.pirq] = 0;
   8.418          break;
   8.419  
   8.420      case ECS_VIRQ:
   8.421 -        /* XXX could store vcpu in chn1[port1].u */
   8.422          for_each_vcpu ( d1, v )
   8.423 -            if (v->virq_to_evtchn[chn1[port1].u.virq] == port1)
   8.424 -                v->virq_to_evtchn[chn1[port1].u.virq] = 0;
   8.425 +            if ( v->virq_to_evtchn[chn1->u.virq] == port1 )
   8.426 +                v->virq_to_evtchn[chn1->u.virq] = 0;
   8.427          break;
   8.428  
   8.429      case ECS_IPI:
   8.430 @@ -389,7 +372,7 @@ static long __evtchn_close(struct domain
   8.431      case ECS_INTERDOMAIN:
   8.432          if ( d2 == NULL )
   8.433          {
   8.434 -            d2 = chn1[port1].u.interdomain.remote_dom->domain;
   8.435 +            d2 = chn1->u.interdomain.remote_dom;
   8.436  
   8.437              /* If we unlock d1 then we could lose d2. Must get a reference. */
   8.438              if ( unlikely(!get_domain(d2)) )
   8.439 @@ -404,50 +387,47 @@ static long __evtchn_close(struct domain
   8.440  
   8.441              if ( d1 < d2 )
   8.442              {
   8.443 -                spin_lock(&d2->event_channel_lock);
   8.444 +                spin_lock(&d2->evtchn_lock);
   8.445              }
   8.446              else if ( d1 != d2 )
   8.447              {
   8.448 -                spin_unlock(&d1->event_channel_lock);
   8.449 -                spin_lock(&d2->event_channel_lock);
   8.450 +                spin_unlock(&d1->evtchn_lock);
   8.451 +                spin_lock(&d2->evtchn_lock);
   8.452                  goto again;
   8.453              }
   8.454          }
   8.455 -        else if ( d2 != chn1[port1].u.interdomain.remote_dom->domain )
   8.456 +        else if ( d2 != chn1->u.interdomain.remote_dom )
   8.457          {
   8.458              rc = -EINVAL;
   8.459              goto out;
   8.460          }
   8.461      
   8.462 -        chn2  = d2->event_channel;
   8.463 -        port2 = chn1[port1].u.interdomain.remote_port;
   8.464 +        port2 = chn1->u.interdomain.remote_port;
   8.465 +        BUG_ON(!port_is_valid(d2, port2));
   8.466  
   8.467 -        if ( port2 >= d2->max_event_channel )
   8.468 -            BUG();
   8.469 -        if ( chn2[port2].state != ECS_INTERDOMAIN )
   8.470 -            BUG();
   8.471 -        if ( chn2[port2].u.interdomain.remote_dom->domain != d1 )
   8.472 -            BUG();
   8.473 +        chn2 = evtchn_from_port(d2, port2);
   8.474 +        BUG_ON(chn2->state != ECS_INTERDOMAIN);
   8.475 +        BUG_ON(chn2->u.interdomain.remote_dom != d1);
   8.476  
   8.477 -        chn2[port2].state = ECS_UNBOUND;
   8.478 -        chn2[port2].u.unbound.remote_domid = d1->domain_id;
   8.479 +        chn2->state = ECS_UNBOUND;
   8.480 +        chn2->u.unbound.remote_domid = d1->domain_id;
   8.481          break;
   8.482  
   8.483      default:
   8.484          BUG();
   8.485      }
   8.486  
   8.487 -    chn1[port1].state = ECS_FREE;
   8.488 +    chn1->state = ECS_FREE;
   8.489  
   8.490   out:
   8.491      if ( d2 != NULL )
   8.492      {
   8.493          if ( d1 != d2 )
   8.494 -            spin_unlock(&d2->event_channel_lock);
   8.495 +            spin_unlock(&d2->evtchn_lock);
   8.496          put_domain(d2);
   8.497      }
   8.498      
   8.499 -    spin_unlock(&d1->event_channel_lock);
   8.500 +    spin_unlock(&d1->evtchn_lock);
   8.501  
   8.502      return rc;
   8.503  }
   8.504 @@ -476,50 +456,52 @@ static long evtchn_close(evtchn_close_t 
   8.505  
   8.506  long evtchn_send(int lport)
   8.507  {
   8.508 -    struct domain *ld = current->domain;
   8.509 -    struct vcpu *rd;
   8.510 +    struct evtchn *lchn, *rchn;
   8.511 +    struct domain *ld = current->domain, *rd;
   8.512      int            rport, ret = 0;
   8.513  
   8.514 -    spin_lock(&ld->event_channel_lock);
   8.515 +    spin_lock(&ld->evtchn_lock);
   8.516  
   8.517 -    if ( unlikely(lport < 0) ||
   8.518 -         unlikely(lport >= ld->max_event_channel))
   8.519 +    if ( unlikely(!port_is_valid(ld, lport)) )
   8.520      {
   8.521 -        spin_unlock(&ld->event_channel_lock);
   8.522 +        spin_unlock(&ld->evtchn_lock);
   8.523          return -EINVAL;
   8.524      }
   8.525  
   8.526 -    switch ( ld->event_channel[lport].state )
   8.527 +    lchn = evtchn_from_port(ld, lport);
   8.528 +    switch ( lchn->state )
   8.529      {
   8.530      case ECS_INTERDOMAIN:
   8.531 -        rd    = ld->event_channel[lport].u.interdomain.remote_dom;
   8.532 -        rport = ld->event_channel[lport].u.interdomain.remote_port;
   8.533 -
   8.534 -        evtchn_set_pending(rd, rport);
   8.535 +        rd    = lchn->u.interdomain.remote_dom;
   8.536 +        rport = lchn->u.interdomain.remote_port;
   8.537 +        rchn  = evtchn_from_port(rd, rport);
   8.538 +        evtchn_set_pending(rd->vcpu[rchn->notify_vcpu_id], rport);
   8.539          break;
   8.540      case ECS_IPI:
   8.541 -        rd = ld->vcpu[ld->event_channel[lport].u.ipi_vcpu];
   8.542 -        if ( rd  )
   8.543 -            evtchn_set_pending(rd, lport);
   8.544 -        else
   8.545 -            ret = -EINVAL;
   8.546 +        evtchn_set_pending(ld->vcpu[lchn->notify_vcpu_id], lport);
   8.547          break;
   8.548      default:
   8.549          ret = -EINVAL;
   8.550      }
   8.551  
   8.552 -    spin_unlock(&ld->event_channel_lock);
   8.553 +    spin_unlock(&ld->evtchn_lock);
   8.554  
   8.555      return ret;
   8.556  }
   8.557  
   8.558 +void send_guest_pirq(struct domain *d, int pirq)
   8.559 +{
   8.560 +    int port = d->pirq_to_evtchn[pirq];
   8.561 +    struct evtchn *chn = evtchn_from_port(d, port);
   8.562 +    evtchn_set_pending(d->vcpu[chn->notify_vcpu_id], port);
   8.563 +}
   8.564  
   8.565  static long evtchn_status(evtchn_status_t *status)
   8.566  {
   8.567      struct domain   *d;
   8.568      domid_t          dom = status->dom;
   8.569      int              port = status->port;
   8.570 -    event_channel_t *chn;
   8.571 +    struct evtchn   *chn;
   8.572      long             rc = 0;
   8.573  
   8.574      if ( dom == DOMID_SELF )
   8.575 @@ -530,17 +512,16 @@ static long evtchn_status(evtchn_status_
   8.576      if ( (d = find_domain_by_id(dom)) == NULL )
   8.577          return -ESRCH;
   8.578  
   8.579 -    spin_lock(&d->event_channel_lock);
   8.580 +    spin_lock(&d->evtchn_lock);
   8.581  
   8.582 -    chn = d->event_channel;
   8.583 -
   8.584 -    if ( (port < 0) || (port >= d->max_event_channel) )
   8.585 +    if ( !port_is_valid(d, port) )
   8.586      {
   8.587          rc = -EINVAL;
   8.588          goto out;
   8.589      }
   8.590  
   8.591 -    switch ( chn[port].state )
   8.592 +    chn = evtchn_from_port(d, port);
   8.593 +    switch ( chn->state )
   8.594      {
   8.595      case ECS_FREE:
   8.596      case ECS_RESERVED:
   8.597 @@ -548,32 +529,32 @@ static long evtchn_status(evtchn_status_
   8.598          break;
   8.599      case ECS_UNBOUND:
   8.600          status->status = EVTCHNSTAT_unbound;
   8.601 -        status->u.unbound.dom = chn[port].u.unbound.remote_domid;
   8.602 +        status->u.unbound.dom = chn->u.unbound.remote_domid;
   8.603          break;
   8.604      case ECS_INTERDOMAIN:
   8.605          status->status = EVTCHNSTAT_interdomain;
   8.606          status->u.interdomain.dom  =
   8.607 -            chn[port].u.interdomain.remote_dom->domain->domain_id;
   8.608 -        status->u.interdomain.port = chn[port].u.interdomain.remote_port;
   8.609 +            chn->u.interdomain.remote_dom->domain_id;
   8.610 +        status->u.interdomain.port = chn->u.interdomain.remote_port;
   8.611          break;
   8.612      case ECS_PIRQ:
   8.613          status->status = EVTCHNSTAT_pirq;
   8.614 -        status->u.pirq = chn[port].u.pirq;
   8.615 +        status->u.pirq = chn->u.pirq;
   8.616          break;
   8.617      case ECS_VIRQ:
   8.618          status->status = EVTCHNSTAT_virq;
   8.619 -        status->u.virq = chn[port].u.virq;
   8.620 +        status->u.virq = chn->u.virq;
   8.621          break;
   8.622      case ECS_IPI:
   8.623          status->status     = EVTCHNSTAT_ipi;
   8.624 -        status->u.ipi_vcpu = chn[port].u.ipi_vcpu;
   8.625 +        status->u.ipi_vcpu = chn->notify_vcpu_id;
   8.626          break;
   8.627      default:
   8.628          BUG();
   8.629      }
   8.630  
   8.631   out:
   8.632 -    spin_unlock(&d->event_channel_lock);
   8.633 +    spin_unlock(&d->evtchn_lock);
   8.634      put_domain(d);
   8.635      return rc;
   8.636  }
   8.637 @@ -642,26 +623,26 @@ long do_event_channel_op(evtchn_op_t *uo
   8.638  }
   8.639  
   8.640  
   8.641 -int init_event_channels(struct domain *d)
   8.642 +int evtchn_init(struct domain *d)
   8.643  {
   8.644 -    spin_lock_init(&d->event_channel_lock);
   8.645 -    /* Call get_free_port to initialize d->event_channel */
   8.646 -    if ( get_free_port(d->vcpu[0]) != 0 )
   8.647 +    spin_lock_init(&d->evtchn_lock);
   8.648 +    if ( get_free_port(d) != 0 )
   8.649          return -EINVAL;
   8.650 -    d->event_channel[0].state = ECS_RESERVED;
   8.651 +    evtchn_from_port(d, 0)->state = ECS_RESERVED;
   8.652      return 0;
   8.653  }
   8.654  
   8.655  
   8.656 -void destroy_event_channels(struct domain *d)
   8.657 +void evtchn_destroy(struct domain *d)
   8.658  {
   8.659      int i;
   8.660 -    if ( d->event_channel != NULL )
   8.661 -    {
   8.662 -        for ( i = 0; i < d->max_event_channel; i++ )
   8.663 +
   8.664 +    for ( i = 0; port_is_valid(d, i); i++ )
   8.665              (void)__evtchn_close(d, i);
   8.666 -        xfree(d->event_channel);
   8.667 -    }
   8.668 +
   8.669 +    for ( i = 0; i < NR_EVTCHN_BUCKETS; i++ )
   8.670 +        if ( d->evtchn[i] != NULL )
   8.671 +            xfree(d->evtchn[i]);
   8.672  }
   8.673  
   8.674  /*
     9.1 --- a/xen/include/public/event_channel.h	Fri Jun 03 22:18:11 2005 +0000
     9.2 +++ b/xen/include/public/event_channel.h	Fri Jun 03 22:22:23 2005 +0000
     9.3 @@ -51,9 +51,11 @@ typedef struct {
     9.4  } PACKED evtchn_bind_interdomain_t; /* 12 bytes */
     9.5  
     9.6  /*
     9.7 - * EVTCHNOP_bind_virq: Bind a local event channel to IRQ <irq>.
     9.8 + * EVTCHNOP_bind_virq: Bind a local event channel to IRQ <irq> on calling vcpu.
     9.9   * NOTES:
    9.10 - *  1. A virtual IRQ may be bound to at most one event channel per domain.
    9.11 + *  1. A virtual IRQ may be bound to at most one event channel per vcpu.
    9.12 + *  2. The allocated event channel is bound to the calling vcpu. The binding
    9.13 + *     may not be changed.
    9.14   */
    9.15  #define EVTCHNOP_bind_virq        1
    9.16  typedef struct {
    9.17 @@ -80,6 +82,20 @@ typedef struct {
    9.18  } PACKED evtchn_bind_pirq_t; /* 12 bytes */
    9.19  
    9.20  /*
    9.21 + * EVTCHNOP_bind_ipi: Bind a local event channel to receive events.
    9.22 + * NOTES:
    9.23 + *  1. The allocated event channel is bound to the calling vcpu. The binding
    9.24 + *     may not be changed.
    9.25 + */
    9.26 +#define EVTCHNOP_bind_ipi         7
    9.27 +typedef struct {
    9.28 +    /* IN parameters. */
    9.29 +    u32 ipi_vcpu;                     /*  0 */
    9.30 +    /* OUT parameters. */
    9.31 +    u32 port;                         /*  4 */
    9.32 +} PACKED evtchn_bind_ipi_t; /* 8 bytes */
    9.33 +
    9.34 +/*
    9.35   * EVTCHNOP_close: Close the communication channel which has an endpoint at
    9.36   * <dom, port>. If the channel is interdomain then the remote end is placed in
    9.37   * the unbound state (EVTCHNSTAT_unbound), awaiting a new connection.
    9.38 @@ -145,18 +161,6 @@ typedef struct {
    9.39      } PACKED u;
    9.40  } PACKED evtchn_status_t; /* 20 bytes */
    9.41  
    9.42 -/*
    9.43 - * EVTCHNOP_bind_ipi: Bind a local event channel to receive events.
    9.44 - */
    9.45 -#define EVTCHNOP_bind_ipi         7
    9.46 -typedef struct {
    9.47 -    /* IN parameters. */
    9.48 -    u32 ipi_vcpu;                     /*  0 */
    9.49 -    /* OUT parameters. */
    9.50 -    u32 port;                         /*  4 */
    9.51 -} PACKED evtchn_bind_ipi_t; /* 8 bytes */
    9.52 -
    9.53 -
    9.54  typedef struct {
    9.55      u32 cmd; /* EVTCHNOP_* */         /*  0 */
    9.56      u32 __reserved;                   /*  4 */
    9.57 @@ -165,10 +169,10 @@ typedef struct {
    9.58          evtchn_bind_interdomain_t bind_interdomain;
    9.59          evtchn_bind_virq_t        bind_virq;
    9.60          evtchn_bind_pirq_t        bind_pirq;
    9.61 +        evtchn_bind_ipi_t         bind_ipi;
    9.62          evtchn_close_t            close;
    9.63          evtchn_send_t             send;
    9.64          evtchn_status_t           status;
    9.65 -        evtchn_bind_ipi_t         bind_ipi;
    9.66          u8                        __dummy[24];
    9.67      } PACKED u;
    9.68  } PACKED evtchn_op_t; /* 32 bytes */
    10.1 --- a/xen/include/xen/event.h	Fri Jun 03 22:18:11 2005 +0000
    10.2 +++ b/xen/include/xen/event.h	Fri Jun 03 22:22:23 2005 +0000
    10.3 @@ -53,7 +53,7 @@ static inline void evtchn_set_pending(st
    10.4  
    10.5  /*
    10.6   * send_guest_virq:
    10.7 - *  @d:        Domain to which virtual IRQ should be sent
    10.8 + *  @v:        VCPU to which virtual IRQ should be sent
    10.9   *  @virq:     Virtual IRQ number (VIRQ_*)
   10.10   */
   10.11  static inline void send_guest_virq(struct vcpu *v, int virq)
   10.12 @@ -69,10 +69,7 @@ static inline void send_guest_virq(struc
   10.13   *  @d:        Domain to which physical IRQ should be sent
   10.14   *  @pirq:     Physical IRQ number
   10.15   */
   10.16 -static inline void send_guest_pirq(struct vcpu *v, int pirq)
   10.17 -{
   10.18 -    evtchn_set_pending(v, v->domain->pirq_to_evtchn[pirq]);
   10.19 -}
   10.20 +extern void send_guest_pirq(struct domain *d, int pirq);
   10.21  
   10.22  #define event_pending(_d)                                     \
   10.23      ((_d)->vcpu_info->evtchn_upcall_pending && \
    11.1 --- a/xen/include/xen/sched.h	Fri Jun 03 22:18:11 2005 +0000
    11.2 +++ b/xen/include/xen/sched.h	Fri Jun 03 22:22:23 2005 +0000
    11.3 @@ -19,7 +19,11 @@ extern rwlock_t domlist_lock;
    11.4  /* A global pointer to the initial domain (DOM0). */
    11.5  extern struct domain *dom0;
    11.6  
    11.7 -typedef struct event_channel_st
    11.8 +#define MAX_EVTCHNS        1024
    11.9 +#define EVTCHNS_PER_BUCKET 128
   11.10 +#define NR_EVTCHN_BUCKETS  (MAX_EVTCHNS / EVTCHNS_PER_BUCKET)
   11.11 +
   11.12 +struct evtchn
   11.13  {
   11.14  #define ECS_FREE         0 /* Channel is available for use.                  */
   11.15  #define ECS_RESERVED     1 /* Channel is reserved.                           */
   11.16 @@ -28,24 +32,23 @@ typedef struct event_channel_st
   11.17  #define ECS_PIRQ         4 /* Channel is bound to a physical IRQ line.       */
   11.18  #define ECS_VIRQ         5 /* Channel is bound to a virtual IRQ line.        */
   11.19  #define ECS_IPI          6 /* Channel is bound to a virtual IPI line.        */
   11.20 -    u16 state;
   11.21 +    u16 state;             /* ECS_* */
   11.22 +    u16 notify_vcpu_id;    /* VCPU for local delivery notification */
   11.23      union {
   11.24          struct {
   11.25              domid_t remote_domid;
   11.26 -        } __attribute__ ((packed)) unbound; /* state == ECS_UNBOUND */
   11.27 +        } unbound;     /* state == ECS_UNBOUND */
   11.28          struct {
   11.29 -            u16                 remote_port;
   11.30 -            struct vcpu *remote_dom;
   11.31 -        } __attribute__ ((packed)) interdomain; /* state == ECS_INTERDOMAIN */
   11.32 -        u16 pirq; /* state == ECS_PIRQ */
   11.33 -        u16 virq; /* state == ECS_VIRQ */
   11.34 -        u32 ipi_vcpu; /* state == ECS_IPI */
   11.35 +            u16            remote_port;
   11.36 +            struct domain *remote_dom;
   11.37 +        } interdomain; /* state == ECS_INTERDOMAIN */
   11.38 +        u16 pirq;      /* state == ECS_PIRQ */
   11.39 +        u16 virq;      /* state == ECS_VIRQ */
   11.40      } u;
   11.41 -} event_channel_t;
   11.42 +};
   11.43  
   11.44 -int  init_event_channels(struct domain *d);
   11.45 -void destroy_event_channels(struct domain *d);
   11.46 -int  init_vcpu_event_channels(struct vcpu *v);
   11.47 +int  evtchn_init(struct domain *d);
   11.48 +void evtchn_destroy(struct domain *d);
   11.49  
   11.50  #define CPUMAP_RUNANYWHERE 0xFFFFFFFF
   11.51  
   11.52 @@ -109,9 +112,8 @@ struct domain
   11.53      struct domain   *next_in_hashbucket;
   11.54  
   11.55      /* Event channel information. */
   11.56 -    event_channel_t *event_channel;
   11.57 -    unsigned int     max_event_channel;
   11.58 -    spinlock_t       event_channel_lock;
   11.59 +    struct evtchn   *evtchn[NR_EVTCHN_BUCKETS];
   11.60 +    spinlock_t       evtchn_lock;
   11.61  
   11.62      grant_table_t   *grant_table;
   11.63