ia64/xen-unstable

changeset 2998:f80e2182e92a

bitkeeper revision 1.1159.1.425 (419a4cf9VuB3gYuI3YPyE637uwwiRA)

Extend perdomain_pt to support multiple vcpus.
Add biglock.
author cl349@freefall.cl.cam.ac.uk
date Tue Nov 16 18:54:49 2004 +0000 (2004-11-16)
parents 4f01ffe63f2d
children e8dbbf6ea1ee
files xen/arch/x86/dom0_ops.c xen/arch/x86/domain.c xen/arch/x86/memory.c xen/arch/x86/shadow.c xen/arch/x86/traps.c xen/arch/x86/x86_32/mm.c xen/arch/x86/x86_32/seg_fixup.c xen/common/dom_mem_ops.c xen/common/domain.c xen/common/grant_table.c xen/common/schedule.c xen/include/asm-x86/config.h xen/include/asm-x86/domain.h xen/include/asm-x86/ldt.h xen/include/asm-x86/processor.h xen/include/xen/sched.h
line diff
     1.1 --- a/xen/arch/x86/dom0_ops.c	Tue Nov 16 18:47:36 2004 +0000
     1.2 +++ b/xen/arch/x86/dom0_ops.c	Tue Nov 16 18:54:49 2004 +0000
     1.3 @@ -128,11 +128,11 @@ void arch_getdomaininfo_ctxt(struct exec
     1.4      c->ldt_base = d->mm.ldt_base;
     1.5      c->ldt_ents = d->mm.ldt_ents;
     1.6      c->gdt_ents = 0;
     1.7 -    if ( GET_GDT_ADDRESS(d) == GDT_VIRT_START )
     1.8 +    if ( GET_GDT_ADDRESS(d) == GDT_VIRT_START(d) )
     1.9      {
    1.10          for ( i = 0; i < 16; i++ )
    1.11              c->gdt_frames[i] = 
    1.12 -                l1_pgentry_to_pagenr(d->mm.perdomain_pt[i]);
    1.13 +                l1_pgentry_to_pagenr(d->mm.perdomain_ptes[i]);
    1.14          c->gdt_ents = GET_GDT_ENTRIES(d);
    1.15      }
    1.16      c->guestos_ss  = d->thread.guestos_ss;
     2.1 --- a/xen/arch/x86/domain.c	Tue Nov 16 18:47:36 2004 +0000
     2.2 +++ b/xen/arch/x86/domain.c	Tue Nov 16 18:54:49 2004 +0000
     2.3 @@ -90,7 +90,7 @@ void continue_cpu_idle_loop(void)
     2.4  void startup_cpu_idle_loop(void)
     2.5  {
     2.6      /* Just some sanity to ensure that the scheduler is set up okay. */
     2.7 -    ASSERT(current->id == IDLE_DOMAIN_ID);
     2.8 +    ASSERT(current->domain->id == IDLE_DOMAIN_ID);
     2.9      domain_unpause_by_systemcontroller(current->domain);
    2.10      __enter_scheduler();
    2.11  
    2.12 @@ -210,9 +210,9 @@ void machine_halt(void)
    2.13      __machine_halt(NULL);
    2.14  }
    2.15  
    2.16 -void free_perdomain_pt(struct exec_domain *d)
    2.17 +void free_perdomain_pt(struct domain *d)
    2.18  {
    2.19 -    free_xenheap_page((unsigned long)d->mm.perdomain_pt);
    2.20 +    free_xenheap_page((unsigned long)d->mm_perdomain_pt);
    2.21  }
    2.22  
    2.23  void arch_do_createdomain(struct exec_domain *ed)
    2.24 @@ -227,10 +227,11 @@ void arch_do_createdomain(struct exec_do
    2.25      machine_to_phys_mapping[virt_to_phys(d->shared_info) >> 
    2.26                             PAGE_SHIFT] = INVALID_P2M_ENTRY;
    2.27  
    2.28 -    ed->mm.perdomain_pt = (l1_pgentry_t *)alloc_xenheap_page();
    2.29 -    memset(ed->mm.perdomain_pt, 0, PAGE_SIZE);
    2.30 -    machine_to_phys_mapping[virt_to_phys(ed->mm.perdomain_pt) >> 
    2.31 +    d->mm_perdomain_pt = (l1_pgentry_t *)alloc_xenheap_page();
    2.32 +    memset(d->mm_perdomain_pt, 0, PAGE_SIZE);
    2.33 +    machine_to_phys_mapping[virt_to_phys(d->mm_perdomain_pt) >> 
    2.34                             PAGE_SHIFT] = INVALID_P2M_ENTRY;
    2.35 +    ed->mm.perdomain_ptes = d->mm_perdomain_pt;
    2.36  }
    2.37  
    2.38  int arch_final_setup_guestos(struct exec_domain *d, full_execution_context_t *c)
    2.39 @@ -761,7 +762,7 @@ int construct_dom0(struct domain *p,
    2.40      l2tab[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT] =
    2.41          mk_l2_pgentry((unsigned long)l2start | __PAGE_HYPERVISOR);
    2.42      l2tab[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] =
    2.43 -        mk_l2_pgentry(__pa(ed->mm.perdomain_pt) | __PAGE_HYPERVISOR);
    2.44 +        mk_l2_pgentry(__pa(p->mm_perdomain_pt) | __PAGE_HYPERVISOR);
    2.45      ed->mm.pagetable = mk_pagetable((unsigned long)l2start);
    2.46  
    2.47      l2tab += l2_table_offset(dsi.v_start);
     3.1 --- a/xen/arch/x86/memory.c	Tue Nov 16 18:47:36 2004 +0000
     3.2 +++ b/xen/arch/x86/memory.c	Tue Nov 16 18:54:49 2004 +0000
     3.3 @@ -206,12 +206,12 @@ static void __invalidate_shadow_ldt(stru
     3.4  
     3.5      for ( i = 16; i < 32; i++ )
     3.6      {
     3.7 -        pfn = l1_pgentry_to_pagenr(d->mm.perdomain_pt[i]);
     3.8 +        pfn = l1_pgentry_to_pagenr(d->mm.perdomain_ptes[i]);
     3.9          if ( pfn == 0 ) continue;
    3.10 -        d->mm.perdomain_pt[i] = mk_l1_pgentry(0);
    3.11 +        d->mm.perdomain_ptes[i] = mk_l1_pgentry(0);
    3.12          page = &frame_table[pfn];
    3.13          ASSERT_PAGE_IS_TYPE(page, PGT_ldt_page);
    3.14 -        ASSERT_PAGE_IS_DOMAIN(page, d);
    3.15 +        ASSERT_PAGE_IS_DOMAIN(page, d->domain);
    3.16          put_page_and_type(page);
    3.17      }
    3.18  
    3.19 @@ -263,7 +263,7 @@ int map_ldt_shadow_page(unsigned int off
    3.20                                       d, PGT_ldt_page)) )
    3.21          return 0;
    3.22  
    3.23 -    ed->mm.perdomain_pt[off + 16] = mk_l1_pgentry(l1e | _PAGE_RW);
    3.24 +    ed->mm.perdomain_ptes[off + 16] = mk_l1_pgentry(l1e | _PAGE_RW);
    3.25      ed->mm.shadow_ldt_mapcnt++;
    3.26  
    3.27      return 1;
    3.28 @@ -515,7 +515,7 @@ static int alloc_l2_table(struct pfn_inf
    3.29      pl2e[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT] =
    3.30          mk_l2_pgentry((page_nr << PAGE_SHIFT) | __PAGE_HYPERVISOR);
    3.31      pl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] =
    3.32 -        mk_l2_pgentry(__pa(page->u.inuse.domain->exec_domain[0]->mm.perdomain_pt) | 
    3.33 +        mk_l2_pgentry(__pa(page->u.inuse.domain->mm_perdomain_pt) | 
    3.34                        __PAGE_HYPERVISOR);
    3.35  #endif
    3.36  
    3.37 @@ -777,7 +777,7 @@ void put_page_type(struct pfn_info *page
    3.38           * See domain.c:relinquish_list().
    3.39           */
    3.40          ASSERT((x & PGT_validated) || 
    3.41 -               test_bit(DF_DYING, &page->u.inuse.domain->flags));
    3.42 +               test_bit(DF_DYING, &page->u.inuse.domain->d_flags));
    3.43  
    3.44          if ( unlikely((nx & PGT_count_mask) == 0) )
    3.45          {
    3.46 @@ -1296,10 +1296,14 @@ int do_mmu_update(mmu_update_t *ureqs, i
    3.47      perfc_incrc(calls_to_mmu_update); 
    3.48      perfc_addc(num_page_updates, count);
    3.49  
    3.50 +    LOCK_BIGLOCK(d);
    3.51 +
    3.52      cleanup_writable_pagetable(d, PTWR_CLEANUP_ACTIVE | PTWR_CLEANUP_INACTIVE);
    3.53  
    3.54 -    if ( unlikely(!access_ok(VERIFY_READ, ureqs, count * sizeof(req))) )
    3.55 +    if ( unlikely(!access_ok(VERIFY_READ, ureqs, count * sizeof(req))) ) {
    3.56 +        UNLOCK_BIGLOCK(d);
    3.57          return -EFAULT;
    3.58 +    }
    3.59  
    3.60      for ( i = 0; i < count; i++ )
    3.61      {
    3.62 @@ -1460,6 +1464,7 @@ int do_mmu_update(mmu_update_t *ureqs, i
    3.63      if ( unlikely(success_count != NULL) )
    3.64          put_user(count, success_count);
    3.65  
    3.66 +    UNLOCK_BIGLOCK(d);
    3.67      return rc;
    3.68  }
    3.69  
    3.70 @@ -1479,6 +1484,8 @@ int do_update_va_mapping(unsigned long p
    3.71      if ( unlikely(page_nr >= (HYPERVISOR_VIRT_START >> PAGE_SHIFT)) )
    3.72          return -EINVAL;
    3.73  
    3.74 +    LOCK_BIGLOCK(d);
    3.75 +
    3.76      cleanup_writable_pagetable(d, PTWR_CLEANUP_ACTIVE | PTWR_CLEANUP_INACTIVE);
    3.77  
    3.78      /*
    3.79 @@ -1529,6 +1536,8 @@ int do_update_va_mapping(unsigned long p
    3.80      if ( unlikely(deferred_ops & DOP_RELOAD_LDT) )
    3.81          (void)map_ldt_shadow_page(0);
    3.82      
    3.83 +    UNLOCK_BIGLOCK(d);
    3.84 +
    3.85      return err;
    3.86  }
    3.87  
    3.88 @@ -1632,7 +1641,11 @@ void ptwr_flush(const int which)
    3.89  
    3.90      /* Ensure that there are no stale writable mappings in any TLB. */
    3.91      /* NB. INVLPG is a serialising instruction: flushes pending updates. */
    3.92 +#if 0
    3.93      __flush_tlb_one(l1va); /* XXX Multi-CPU guests? */
    3.94 +#else
    3.95 +    flush_tlb_all();
    3.96 +#endif
    3.97      PTWR_PRINTK("[%c] disconnected_l1va at %p now %08lx\n",
    3.98                  PTWR_PRINT_WHICH, ptep, pte);
    3.99  
   3.100 @@ -1677,6 +1690,7 @@ void ptwr_flush(const int which)
   3.101                     (ENTRIES_PER_L1_PAGETABLE - i) * sizeof(l1_pgentry_t));
   3.102              unmap_domain_mem(pl1e);
   3.103              ptwr_info[cpu].ptinfo[which].l1va = 0;
   3.104 +            UNLOCK_BIGLOCK(d);
   3.105              domain_crash();
   3.106          }
   3.107          
   3.108 @@ -1721,7 +1735,9 @@ int ptwr_do_page_fault(unsigned long add
   3.109      l2_pgentry_t    *pl2e, nl2e;
   3.110      int              which, cpu = smp_processor_id();
   3.111      u32              l2_idx;
   3.112 +    struct domain   *d = current->domain;
   3.113  
   3.114 +    LOCK_BIGLOCK(d);
   3.115      /*
   3.116       * Attempt to read the PTE that maps the VA being accessed. By checking for
   3.117       * PDE validity in the L2 we avoid many expensive fixups in __get_user().
   3.118 @@ -1729,7 +1745,10 @@ int ptwr_do_page_fault(unsigned long add
   3.119      if ( !(l2_pgentry_val(linear_l2_table[addr>>L2_PAGETABLE_SHIFT]) &
   3.120             _PAGE_PRESENT) ||
   3.121           __get_user(pte, (unsigned long *)&linear_pg_table[addr>>PAGE_SHIFT]) )
   3.122 +    {
   3.123 +        UNLOCK_BIGLOCK(d);
   3.124          return 0;
   3.125 +    }
   3.126  
   3.127      pfn  = pte >> PAGE_SHIFT;
   3.128      page = &frame_table[pfn];
   3.129 @@ -1737,12 +1756,18 @@ int ptwr_do_page_fault(unsigned long add
   3.130      /* We are looking only for read-only mappings of p.t. pages. */
   3.131      if ( ((pte & (_PAGE_RW | _PAGE_PRESENT)) != _PAGE_PRESENT) ||
   3.132           ((page->u.inuse.type_info & PGT_type_mask) != PGT_l1_page_table) )
   3.133 +    {
   3.134 +        UNLOCK_BIGLOCK(d);
   3.135          return 0;
   3.136 +    }
   3.137      
   3.138      /* Get the L2 index at which this L1 p.t. is always mapped. */
   3.139      l2_idx = page->u.inuse.type_info & PGT_va_mask;
   3.140      if ( unlikely(l2_idx >= PGT_va_unknown) )
   3.141 +    {
   3.142 +        UNLOCK_BIGLOCK(d);
   3.143          domain_crash(); /* Urk! This L1 is mapped in multiple L2 slots! */
   3.144 +    }
   3.145      l2_idx >>= PGT_va_shift;
   3.146          
   3.147      /*
   3.148 @@ -1772,7 +1797,11 @@ int ptwr_do_page_fault(unsigned long add
   3.149      {
   3.150          nl2e = mk_l2_pgentry(l2_pgentry_val(*pl2e) & ~_PAGE_PRESENT);
   3.151          update_l2e(pl2e, *pl2e, nl2e);
   3.152 +#if 0
   3.153          flush_tlb(); /* XXX Multi-CPU guests? */
   3.154 +#else
   3.155 +        flush_tlb_all();
   3.156 +#endif
   3.157      }
   3.158      
   3.159      /* Temporarily map the L1 page, and make a copy of it. */
   3.160 @@ -1793,9 +1822,12 @@ int ptwr_do_page_fault(unsigned long add
   3.161          /* Toss the writable pagetable state and crash. */
   3.162          unmap_domain_mem(ptwr_info[cpu].ptinfo[which].pl1e);
   3.163          ptwr_info[cpu].ptinfo[which].l1va = 0;
   3.164 +        UNLOCK_BIGLOCK(d);
   3.165          domain_crash();
   3.166      }
   3.167      
   3.168 +    UNLOCK_BIGLOCK(d);
   3.169 +
   3.170      /* Maybe fall through to shadow mode to propagate writable L1. */
   3.171      return !current->mm.shadow_mode;
   3.172  }
   3.173 @@ -1952,12 +1984,12 @@ void audit_domain(struct domain *d)
   3.174      struct list_head *list_ent;
   3.175      struct pfn_info *page;
   3.176  
   3.177 -    if ( d != current )
   3.178 +    if ( d != current->domain )
   3.179          domain_pause(d);
   3.180      synchronise_pagetables(~0UL);
   3.181  
   3.182      printk("pt base=%lx sh_info=%x\n",
   3.183 -           pagetable_val(d->mm.pagetable)>>PAGE_SHIFT,
   3.184 +           pagetable_val(d->exec_domain[0]->mm.pagetable)>>PAGE_SHIFT,
   3.185             virt_to_page(d->shared_info)-frame_table);
   3.186             
   3.187      spin_lock(&d->page_alloc_lock);
   3.188 @@ -2007,7 +2039,7 @@ void audit_domain(struct domain *d)
   3.189  
   3.190      /* PHASE 1 */
   3.191  
   3.192 -    adjust(&frame_table[pagetable_val(d->mm.pagetable)>>PAGE_SHIFT], -1, 1);
   3.193 +    adjust(&frame_table[pagetable_val(d->exec_domain[0]->mm.pagetable)>>PAGE_SHIFT], -1, 1);
   3.194  
   3.195      list_ent = d->page_list.next;
   3.196      for ( i = 0; (list_ent != &d->page_list); i++ )
   3.197 @@ -2251,11 +2283,11 @@ void audit_domain(struct domain *d)
   3.198  
   3.199      spin_unlock(&d->page_alloc_lock);
   3.200  
   3.201 -    adjust(&frame_table[pagetable_val(d->mm.pagetable)>>PAGE_SHIFT], 1, 1);
   3.202 +    adjust(&frame_table[pagetable_val(d->exec_domain[0]->mm.pagetable)>>PAGE_SHIFT], 1, 1);
   3.203  
   3.204      printk("Audit %d: Done. ctot=%d ttot=%d\n", d->id, ctot, ttot );
   3.205  
   3.206 -    if ( d != current )
   3.207 +    if ( d != current->domain )
   3.208          domain_unpause(d);
   3.209  }
   3.210  
     4.1 --- a/xen/arch/x86/shadow.c	Tue Nov 16 18:47:36 2004 +0000
     4.2 +++ b/xen/arch/x86/shadow.c	Tue Nov 16 18:54:49 2004 +0000
     4.3 @@ -473,7 +473,7 @@ unsigned long shadow_l2_table(
     4.4      spl2e[SH_LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT] =
     4.5          mk_l2_pgentry((spfn << PAGE_SHIFT) | __PAGE_HYPERVISOR);
     4.6      spl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] =
     4.7 -        mk_l2_pgentry(__pa(frame_table[gpfn].u.inuse.domain->exec_domain[0]->mm.perdomain_pt) |
     4.8 +        mk_l2_pgentry(__pa(frame_table[gpfn].u.inuse.domain->mm_perdomain_pt) |
     4.9                        __PAGE_HYPERVISOR);
    4.10  #endif
    4.11  
     5.1 --- a/xen/arch/x86/traps.c	Tue Nov 16 18:47:36 2004 +0000
     5.2 +++ b/xen/arch/x86/traps.c	Tue Nov 16 18:54:49 2004 +0000
     5.3 @@ -346,6 +346,7 @@ asmlinkage void do_page_fault(struct xen
     5.4      struct domain *d = ed->domain;
     5.5      extern int map_ldt_shadow_page(unsigned int);
     5.6      int cpu = ed->processor;
     5.7 +    int ret;
     5.8  
     5.9      __asm__ __volatile__ ("movl %%cr2,%0" : "=r" (addr) : );
    5.10  
    5.11 @@ -359,7 +360,9 @@ asmlinkage void do_page_fault(struct xen
    5.12               unlikely((addr >> L2_PAGETABLE_SHIFT) ==
    5.13                        ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l2_idx) )
    5.14          {
    5.15 +            LOCK_BIGLOCK(d);
    5.16              ptwr_flush(PTWR_PT_ACTIVE);
    5.17 +            UNLOCK_BIGLOCK(d);
    5.18              return;
    5.19          }
    5.20  
    5.21 @@ -373,16 +376,19 @@ asmlinkage void do_page_fault(struct xen
    5.22           (addr < PAGE_OFFSET) && shadow_fault(addr, error_code) )
    5.23          return; /* Returns TRUE if fault was handled. */
    5.24  
    5.25 -    if ( unlikely(addr >= LDT_VIRT_START) && 
    5.26 -         (addr < (LDT_VIRT_START + (ed->mm.ldt_ents*LDT_ENTRY_SIZE))) )
    5.27 +    if ( unlikely(addr >= LDT_VIRT_START(ed)) && 
    5.28 +         (addr < (LDT_VIRT_START(ed) + (ed->mm.ldt_ents*LDT_ENTRY_SIZE))) )
    5.29      {
    5.30          /*
    5.31           * Copy a mapping from the guest's LDT, if it is valid. Otherwise we
    5.32           * send the fault up to the guest OS to be handled.
    5.33           */
    5.34 -        off  = addr - LDT_VIRT_START;
    5.35 +        LOCK_BIGLOCK(d);
    5.36 +        off  = addr - LDT_VIRT_START(ed);
    5.37          addr = ed->mm.ldt_base + off;
    5.38 -        if ( likely(map_ldt_shadow_page(off >> PAGE_SHIFT)) )
    5.39 +        ret = map_ldt_shadow_page(off >> PAGE_SHIFT);
    5.40 +        UNLOCK_BIGLOCK(d);
    5.41 +        if ( likely(ret) )
    5.42              return; /* successfully copied the mapping */
    5.43      }
    5.44  
    5.45 @@ -784,6 +790,8 @@ long do_set_trap_table(trap_info_t *trap
    5.46      trap_info_t cur;
    5.47      trap_info_t *dst = current->thread.traps;
    5.48  
    5.49 +    LOCK_BIGLOCK(current->domain);
    5.50 +
    5.51      for ( ; ; )
    5.52      {
    5.53          if ( copy_from_user(&cur, traps, sizeof(cur)) ) return -EFAULT;
    5.54 @@ -796,6 +804,8 @@ long do_set_trap_table(trap_info_t *trap
    5.55          traps++;
    5.56      }
    5.57  
    5.58 +    UNLOCK_BIGLOCK(current->domain);
    5.59 +
    5.60      return 0;
    5.61  }
    5.62  
     6.1 --- a/xen/arch/x86/x86_32/mm.c	Tue Nov 16 18:47:36 2004 +0000
     6.2 +++ b/xen/arch/x86/x86_32/mm.c	Tue Nov 16 18:54:49 2004 +0000
     6.3 @@ -216,9 +216,9 @@ void destroy_gdt(struct exec_domain *ed)
     6.4  
     6.5      for ( i = 0; i < 16; i++ )
     6.6      {
     6.7 -        if ( (pfn = l1_pgentry_to_pagenr(ed->mm.perdomain_pt[i])) != 0 )
     6.8 +        if ( (pfn = l1_pgentry_to_pagenr(ed->mm.perdomain_ptes[i])) != 0 )
     6.9              put_page_and_type(&frame_table[pfn]);
    6.10 -        ed->mm.perdomain_pt[i] = mk_l1_pgentry(0);
    6.11 +        ed->mm.perdomain_ptes[i] = mk_l1_pgentry(0);
    6.12      }
    6.13  }
    6.14  
    6.15 @@ -272,10 +272,10 @@ long set_gdt(struct exec_domain *ed,
    6.16  
    6.17      /* Install the new GDT. */
    6.18      for ( i = 0; i < nr_pages; i++ )
    6.19 -        ed->mm.perdomain_pt[i] =
    6.20 +        ed->mm.perdomain_ptes[i] =
    6.21              mk_l1_pgentry((frames[i] << PAGE_SHIFT) | __PAGE_HYPERVISOR);
    6.22  
    6.23 -    SET_GDT_ADDRESS(ed, GDT_VIRT_START);
    6.24 +    SET_GDT_ADDRESS(ed, GDT_VIRT_START(ed));
    6.25      SET_GDT_ENTRIES(ed, entries);
    6.26  
    6.27      return 0;
    6.28 @@ -299,12 +299,16 @@ long do_set_gdt(unsigned long *frame_lis
    6.29      if ( copy_from_user(frames, frame_list, nr_pages * sizeof(unsigned long)) )
    6.30          return -EFAULT;
    6.31  
    6.32 +    LOCK_BIGLOCK(current->domain);
    6.33 +
    6.34      if ( (ret = set_gdt(current, frames, entries)) == 0 )
    6.35      {
    6.36          local_flush_tlb();
    6.37          __asm__ __volatile__ ("lgdt %0" : "=m" (*current->mm.gdt));
    6.38      }
    6.39  
    6.40 +    UNLOCK_BIGLOCK(current->domain);
    6.41 +
    6.42      return ret;
    6.43  }
    6.44  
    6.45 @@ -314,27 +318,36 @@ long do_update_descriptor(
    6.46  {
    6.47      unsigned long *gdt_pent, pfn = pa >> PAGE_SHIFT, d[2];
    6.48      struct pfn_info *page;
    6.49 +    struct exec_domain *ed;
    6.50      long ret = -EINVAL;
    6.51  
    6.52      d[0] = word1;
    6.53      d[1] = word2;
    6.54  
    6.55 -    if ( (pa & 7) || (pfn >= max_page) || !check_descriptor(d) )
    6.56 +    LOCK_BIGLOCK(current->domain);
    6.57 +
    6.58 +    if ( (pa & 7) || (pfn >= max_page) || !check_descriptor(d) ) {
    6.59 +        UNLOCK_BIGLOCK(current->domain);
    6.60          return -EINVAL;
    6.61 +    }
    6.62  
    6.63      page = &frame_table[pfn];
    6.64 -    if ( unlikely(!get_page(page, current->domain)) )
    6.65 +    if ( unlikely(!get_page(page, current->domain)) ) {
    6.66 +        UNLOCK_BIGLOCK(current->domain);
    6.67          return -EINVAL;
    6.68 +    }
    6.69  
    6.70      /* Check if the given frame is in use in an unsafe context. */
    6.71      switch ( page->u.inuse.type_info & PGT_type_mask )
    6.72      {
    6.73      case PGT_gdt_page:
    6.74          /* Disallow updates of Xen-reserved descriptors in the current GDT. */
    6.75 -        if ( (l1_pgentry_to_pagenr(current->mm.perdomain_pt[0]) == pfn) &&
    6.76 -             (((pa&(PAGE_SIZE-1))>>3) >= FIRST_RESERVED_GDT_ENTRY) &&
    6.77 -             (((pa&(PAGE_SIZE-1))>>3) <= LAST_RESERVED_GDT_ENTRY) )
    6.78 -            goto out;
    6.79 +        for_each_exec_domain(current->domain, ed) {
    6.80 +            if ( (l1_pgentry_to_pagenr(ed->mm.perdomain_ptes[0]) == pfn) &&
    6.81 +                 (((pa&(PAGE_SIZE-1))>>3) >= FIRST_RESERVED_GDT_ENTRY) &&
    6.82 +                 (((pa&(PAGE_SIZE-1))>>3) <= LAST_RESERVED_GDT_ENTRY) )
    6.83 +                goto out;
    6.84 +        }
    6.85          if ( unlikely(!get_page_type(page, PGT_gdt_page)) )
    6.86              goto out;
    6.87          break;
    6.88 @@ -359,6 +372,9 @@ long do_update_descriptor(
    6.89  
    6.90   out:
    6.91      put_page(page);
    6.92 +
    6.93 +    UNLOCK_BIGLOCK(current->domain);
    6.94 +
    6.95      return ret;
    6.96  }
    6.97  
     7.1 --- a/xen/arch/x86/x86_32/seg_fixup.c	Tue Nov 16 18:47:36 2004 +0000
     7.2 +++ b/xen/arch/x86/x86_32/seg_fixup.c	Tue Nov 16 18:54:49 2004 +0000
     7.3 @@ -113,7 +113,7 @@ int get_baselimit(u16 seg, unsigned long
     7.4      /* Get base and check limit. */
     7.5      if ( ldt )
     7.6      {
     7.7 -        table = (unsigned long *)LDT_VIRT_START;
     7.8 +        table = (unsigned long *)LDT_VIRT_START(d);
     7.9          if ( idx >= d->mm.ldt_ents )
    7.10              goto fail;
    7.11      }
    7.12 @@ -179,7 +179,7 @@ int fixup_seg(u16 seg, int positive_acce
    7.13      /* Get base and check limit. */
    7.14      if ( ldt )
    7.15      {
    7.16 -        table = (unsigned long *)LDT_VIRT_START;
    7.17 +        table = (unsigned long *)LDT_VIRT_START(d);
    7.18          if ( idx >= d->mm.ldt_ents )
    7.19          {
    7.20              DPRINTK("Segment %04x out of LDT range (%d)\n",
     8.1 --- a/xen/common/dom_mem_ops.c	Tue Nov 16 18:47:36 2004 +0000
     8.2 +++ b/xen/common/dom_mem_ops.c	Tue Nov 16 18:54:49 2004 +0000
     8.3 @@ -111,6 +111,8 @@ long do_dom_mem_op(unsigned int   op,
     8.4      else if ( unlikely((d = find_domain_by_id(domid)) == NULL) )
     8.5  	return -ESRCH;
     8.6  
     8.7 +    LOCK_BIGLOCK(d);
     8.8 +
     8.9      switch ( op )
    8.10      {
    8.11      case MEMOP_increase_reservation:
    8.12 @@ -127,5 +129,7 @@ long do_dom_mem_op(unsigned int   op,
    8.13      if ( unlikely(domid != DOMID_SELF) )
    8.14  	put_domain(d);
    8.15  
    8.16 +    UNLOCK_BIGLOCK(d);
    8.17 +
    8.18      return rc;
    8.19  }
     9.1 --- a/xen/common/domain.c	Tue Nov 16 18:47:36 2004 +0000
     9.2 +++ b/xen/common/domain.c	Tue Nov 16 18:54:49 2004 +0000
     9.3 @@ -46,6 +46,8 @@ struct domain *do_createdomain(domid_t d
     9.4  
     9.5      spin_lock_init(&d->time_lock);
     9.6  
     9.7 +    spin_lock_init(&d->big_lock);
     9.8 +
     9.9      spin_lock_init(&d->page_alloc_lock);
    9.10      INIT_LIST_HEAD(&d->page_list);
    9.11      INIT_LIST_HEAD(&d->xenpage_list);
    9.12 @@ -216,7 +218,6 @@ unsigned int alloc_new_dom_mem(struct do
    9.13  void domain_destruct(struct domain *d)
    9.14  {
    9.15      struct domain **pd;
    9.16 -    struct exec_domain *ed;
    9.17      atomic_t      old, new;
    9.18  
    9.19      if ( !test_bit(DF_DYING, &d->d_flags) )
    9.20 @@ -244,8 +245,7 @@ void domain_destruct(struct domain *d)
    9.21      destroy_event_channels(d);
    9.22      grant_table_destroy(d);
    9.23  
    9.24 -    for_each_exec_domain(d, ed)
    9.25 -        free_perdomain_pt(ed);
    9.26 +    free_perdomain_pt(d);
    9.27      free_xenheap_page((unsigned long)d->shared_info);
    9.28  
    9.29      free_domain_struct(d);
    9.30 @@ -333,10 +333,7 @@ long do_boot_vcpu(unsigned long vcpu, fu
    9.31      memcpy(&ed->thread, &idle0_exec_domain.thread, sizeof(ed->thread));
    9.32  
    9.33      /* arch_do_createdomain */
    9.34 -    ed->mm.perdomain_pt = (l1_pgentry_t *)alloc_xenheap_page();
    9.35 -    memset(ed->mm.perdomain_pt, 0, PAGE_SIZE);
    9.36 -    machine_to_phys_mapping[virt_to_phys(ed->mm.perdomain_pt) >> 
    9.37 -                           PAGE_SHIFT] = INVALID_P2M_ENTRY;
    9.38 +    ed->mm.perdomain_ptes = d->mm_perdomain_pt + (ed->eid << PDPT_VCPU_SHIFT);
    9.39  
    9.40      sched_add_domain(ed);
    9.41  
    10.1 --- a/xen/common/grant_table.c	Tue Nov 16 18:47:36 2004 +0000
    10.2 +++ b/xen/common/grant_table.c	Tue Nov 16 18:54:49 2004 +0000
    10.3 @@ -440,6 +440,8 @@ do_grant_table_op(
    10.4      if ( count > 512 )
    10.5          return -EINVAL;
    10.6  
    10.7 +    LOCK_BIGLOCK(current->domain);
    10.8 +
    10.9      switch ( cmd )
   10.10      {
   10.11      case GNTTABOP_map_grant_ref:
   10.12 @@ -462,6 +464,8 @@ do_grant_table_op(
   10.13          break;
   10.14      }
   10.15  
   10.16 +    UNLOCK_BIGLOCK(current->domain);
   10.17 +
   10.18      return rc;
   10.19  }
   10.20  
    11.1 --- a/xen/common/schedule.c	Tue Nov 16 18:47:36 2004 +0000
    11.2 +++ b/xen/common/schedule.c	Tue Nov 16 18:54:49 2004 +0000
    11.3 @@ -249,7 +249,7 @@ void domain_wake(struct exec_domain *d)
    11.4  /* Block the currently-executing domain until a pertinent event occurs. */
    11.5  long do_block(void)
    11.6  {
    11.7 -    ASSERT(current->id != IDLE_DOMAIN_ID);
    11.8 +    ASSERT(current->domain->id != IDLE_DOMAIN_ID);
    11.9      current->vcpu_info->evtchn_upcall_mask = 0;
   11.10      set_bit(EDF_BLOCKED, &current->ed_flags);
   11.11      TRACE_2D(TRC_SCHED_BLOCK, current->id, current);
   11.12 @@ -374,8 +374,13 @@ void __enter_scheduler(void)
   11.13      task_slice_t        next_slice;
   11.14      s32                 r_time;     /* time for new dom to run */
   11.15  
   11.16 -    cleanup_writable_pagetable(
   11.17 -        prev->domain, PTWR_CLEANUP_ACTIVE | PTWR_CLEANUP_INACTIVE);
   11.18 +    if ( !is_idle_task(current->domain) )
   11.19 +    {
   11.20 +        LOCK_BIGLOCK(current->domain);
   11.21 +        cleanup_writable_pagetable(
   11.22 +            prev->domain, PTWR_CLEANUP_ACTIVE | PTWR_CLEANUP_INACTIVE);
   11.23 +        UNLOCK_BIGLOCK(current->domain);
   11.24 +    }
   11.25  
   11.26      perfc_incrc(sched_run);
   11.27      
    12.1 --- a/xen/include/asm-x86/config.h	Tue Nov 16 18:47:36 2004 +0000
    12.2 +++ b/xen/include/asm-x86/config.h	Tue Nov 16 18:54:49 2004 +0000
    12.3 @@ -215,10 +215,13 @@ extern void __out_of_line_bug(int line) 
    12.4  extern unsigned long xenheap_phys_end; /* user-configurable */
    12.5  #endif
    12.6  
    12.7 -#define GDT_VIRT_START        (PERDOMAIN_VIRT_START)
    12.8 -#define GDT_VIRT_END          (GDT_VIRT_START + (64*1024))
    12.9 -#define LDT_VIRT_START        (GDT_VIRT_END)
   12.10 -#define LDT_VIRT_END          (LDT_VIRT_START + (64*1024))
   12.11 +#define GDT_VIRT_START(ed)    (PERDOMAIN_VIRT_START + ((ed)->eid << PDPT_VCPU_VA_SHIFT))
   12.12 +#define GDT_VIRT_END(ed)      (GDT_VIRT_START(ed) + (64*1024))
   12.13 +#define LDT_VIRT_START(ed)    (PERDOMAIN_VIRT_START + (64*1024) + ((ed)->eid << PDPT_VCPU_VA_SHIFT))
   12.14 +#define LDT_VIRT_END(ed)      (LDT_VIRT_START(ed) + (64*1024))
   12.15 +
   12.16 +#define PDPT_VCPU_SHIFT       5
   12.17 +#define PDPT_VCPU_VA_SHIFT    (PDPT_VCPU_SHIFT + PAGE_SHIFT)
   12.18  
   12.19  #if defined(__x86_64__)
   12.20  #define ELFSIZE 64
    13.1 --- a/xen/include/asm-x86/domain.h	Tue Nov 16 18:47:36 2004 +0000
    13.2 +++ b/xen/include/asm-x86/domain.h	Tue Nov 16 18:54:49 2004 +0000
    13.3 @@ -7,7 +7,7 @@ extern void arch_do_createdomain(struct 
    13.4  extern int  arch_final_setup_guestos(
    13.5      struct exec_domain *d, full_execution_context_t *c);
    13.6  
    13.7 -extern void free_perdomain_pt(struct exec_domain *d);
    13.8 +extern void free_perdomain_pt(struct domain *d);
    13.9  
   13.10  extern void domain_relinquish_memory(struct domain *d);
   13.11  
    14.1 --- a/xen/include/asm-x86/ldt.h	Tue Nov 16 18:47:36 2004 +0000
    14.2 +++ b/xen/include/asm-x86/ldt.h	Tue Nov 16 18:54:49 2004 +0000
    14.3 @@ -17,9 +17,9 @@ static inline void load_LDT(struct exec_
    14.4      {
    14.5          cpu = smp_processor_id();
    14.6          desc = (struct desc_struct *)GET_GDT_ADDRESS(p) + __LDT(cpu);
    14.7 -        desc->a = ((LDT_VIRT_START&0xffff)<<16) | (ents*8-1);
    14.8 -        desc->b = (LDT_VIRT_START&(0xff<<24)) | 0x8200 |
    14.9 -            ((LDT_VIRT_START&0xff0000)>>16);
   14.10 +        desc->a = ((LDT_VIRT_START(p)&0xffff)<<16) | (ents*8-1);
   14.11 +        desc->b = (LDT_VIRT_START(p)&(0xff<<24)) | 0x8200 |
   14.12 +            ((LDT_VIRT_START(p)&0xff0000)>>16);
   14.13          __asm__ __volatile__ ( "lldt %%ax" : : "a" (__LDT(cpu)<<3) );
   14.14      }
   14.15  }
    15.1 --- a/xen/include/asm-x86/processor.h	Tue Nov 16 18:47:36 2004 +0000
    15.2 +++ b/xen/include/asm-x86/processor.h	Tue Nov 16 18:54:49 2004 +0000
    15.3 @@ -364,7 +364,7 @@ struct mm_struct {
    15.4       * Every domain has a L1 pagetable of its own. Per-domain mappings
    15.5       * are put in this table (eg. the current GDT is mapped here).
    15.6       */
    15.7 -    l1_pgentry_t *perdomain_pt;
    15.8 +    l1_pgentry_t *perdomain_ptes;
    15.9      pagetable_t  pagetable;
   15.10  
   15.11      /* shadow mode status and controls */
   15.12 @@ -410,8 +410,8 @@ static inline void write_ptbase(struct m
   15.13  
   15.14  #define IDLE0_MM                                                    \
   15.15  {                                                                   \
   15.16 -    perdomain_pt: 0,                                                \
   15.17 -    pagetable:   mk_pagetable(__pa(idle_pg_table))                  \
   15.18 +    perdomain_ptes: 0,                                              \
   15.19 +    pagetable:      mk_pagetable(__pa(idle_pg_table))               \
   15.20  }
   15.21  
   15.22  /* Convenient accessor for mm.gdt. */
    16.1 --- a/xen/include/xen/sched.h	Tue Nov 16 18:47:36 2004 +0000
    16.2 +++ b/xen/include/xen/sched.h	Tue Nov 16 18:54:49 2004 +0000
    16.3 @@ -108,6 +108,14 @@ struct exec_domain
    16.4  
    16.5  };
    16.6  
    16.7 +#if 01
    16.8 +#define LOCK_BIGLOCK(_d) spin_lock(&(_d)->big_lock)
    16.9 +#define UNLOCK_BIGLOCK(_d) spin_unlock(&(_d)->big_lock)
   16.10 +#else
   16.11 +#define LOCK_BIGLOCK(_d) (void)(_d)
   16.12 +#define UNLOCK_BIGLOCK(_d)
   16.13 +#endif
   16.14 +
   16.15  struct domain {
   16.16      domid_t          id;
   16.17      s_time_t         create_time;
   16.18 @@ -115,6 +123,10 @@ struct domain {
   16.19      shared_info_t   *shared_info;     /* shared data area */
   16.20      spinlock_t       time_lock;
   16.21  
   16.22 +    spinlock_t       big_lock;
   16.23 +
   16.24 +    l1_pgentry_t    *mm_perdomain_pt;
   16.25 +
   16.26      spinlock_t       page_alloc_lock; /* protects all the following fields  */
   16.27      struct list_head page_list;       /* linked list, of size tot_pages     */
   16.28      struct list_head xenpage_list;    /* linked list, of size xenheap_pages */