bitkeeper revision 1.880 (408e873bJZUD6CJ5wPeA5HUnW78lhQ)
authoriap10@labyrinth.cl.cam.ac.uk <iap10@labyrinth.cl.cam.ac.uk>
Tue, 27 Apr 2004 16:15:55 +0000 (16:15 +0000)
committeriap10@labyrinth.cl.cam.ac.uk <iap10@labyrinth.cl.cam.ac.uk>
Tue, 27 Apr 2004 16:15:55 +0000 (16:15 +0000)
Merge

1  2 
tools/xc/lib/xc_private.c
tools/xc/lib/xc_private.h
xen/common/memory.c
xen/net/dev.c
xenolinux-2.4.26-sparse/arch/xen/drivers/dom0/core.c
xenolinux-2.4.26-sparse/arch/xen/mm/ioremap.c
xenolinux-2.4.26-sparse/include/asm-xen/proc_cmd.h

Simple merge
Simple merge
Simple merge
diff --cc xen/net/dev.c
index 69ed0e399a98278d1bfb8a7c15532d6ac3d5e868,aefd3a0df14fe13b7af7d198c1c29b5a3904741c..e4e10928407dd5d60cbeb99d2a3fdd07e62a9381
@@@ -553,10 -553,13 +553,13 @@@ void deliver_packet(struct sk_buff *skb
        unsigned long *sptr = map_domain_mem( (spte_pfn<<PAGE_SHIFT) |
                        (((unsigned long)ptep)&~PAGE_MASK) );
  
 -        // avoid the fault later
 +        /* Avoid the fault later. */
        *sptr = new_pte;
        unmap_domain_mem(sptr);
+       if( p->mm.shadow_mode == SHM_logdirty )
+               mark_dirty( &p->mm, new_page-frame_table );
        put_shadow_status(&p->mm);
      }
  
index b59f3e8a841f3045362557eb5cfbf328af0697ff,0000000000000000000000000000000000000000..a94b016fb7b0eaae10b7e993335051e258487ec8
mode 100644,000000..100644
--- /dev/null
@@@ -1,104 -1,0 +1,158 @@@
-       }
 +/******************************************************************************
 + * core.c
 + * 
 + * Interface to privileged domain-0 commands.
 + * 
 + * Copyright (c) 2002-2004, K A Fraser, B Dragovic
 + */
 +
 +#include <linux/config.h>
 +#include <linux/module.h>
 +#include <linux/kernel.h>
 +#include <linux/sched.h>
 +#include <linux/slab.h>
 +#include <linux/string.h>
 +#include <linux/errno.h>
 +#include <linux/mm.h>
 +#include <linux/mman.h>
 +#include <linux/swap.h>
 +#include <linux/smp_lock.h>
 +#include <linux/swapctl.h>
 +#include <linux/iobuf.h>
 +#include <linux/highmem.h>
 +#include <linux/pagemap.h>
 +#include <linux/seq_file.h>
 +
 +#include <asm/pgalloc.h>
 +#include <asm/pgtable.h>
 +#include <asm/uaccess.h>
 +#include <asm/tlb.h>
 +#include <asm/proc_cmd.h>
 +#include <asm/hypervisor-ifs/dom0_ops.h>
 +#include <asm/xen_proc.h>
 +
 +static struct proc_dir_entry *privcmd_intf;
 +
 +static int privcmd_ioctl(struct inode *inode, struct file *file,
 +                         unsigned int cmd, unsigned long data)
 +{
 +    int ret = 0;
 +
 +    switch ( cmd )
 +    {
 +    case IOCTL_PRIVCMD_HYPERCALL:
 +    {
 +        privcmd_hypercall_t hypercall;
 +  
 +        if ( copy_from_user(&hypercall, (void *)data, sizeof(hypercall)) )
 +            return -EFAULT;
 +
 +        __asm__ __volatile__ (
 +            "pushl %%ebx; pushl %%ecx; pushl %%edx; pushl %%esi; pushl %%edi; "
 +            "movl  4(%%eax),%%ebx ;"
 +            "movl  8(%%eax),%%ecx ;"
 +            "movl 12(%%eax),%%edx ;"
 +            "movl 16(%%eax),%%esi ;"
 +            "movl 20(%%eax),%%edi ;"
 +            "movl   (%%eax),%%eax ;"
 +            TRAP_INSTR "; "
 +            "popl %%edi; popl %%esi; popl %%edx; popl %%ecx; popl %%ebx"
 +            : "=a" (ret) : "0" (&hypercall) : "memory" );
 +
 +    }
 +    break;
 +
++    case IOCTL_PRIVCMD_MMAP:
++    {
++#define PRIVCMD_MMAP_SZ 32
++      privcmd_mmap_t mmapcmd;
++      privcmd_mmap_entry_t msg[PRIVCMD_MMAP_SZ], *p;
++      int i;
++
++        if ( copy_from_user(&mmapcmd, (void *)data, sizeof(mmapcmd)) )
++            return -EFAULT;
++
++      p = mmapcmd.entry;
++
++      for (i=0; i<mmapcmd.num; i+=PRIVCMD_MMAP_SZ, p+=PRIVCMD_MMAP_SZ)
++      {
++          int j, n = ((mmapcmd.num-i)>PRIVCMD_MMAP_SZ)?
++              PRIVCMD_MMAP_SZ:(mmapcmd.num-i);
++          if ( copy_from_user(&msg, p, n*sizeof(privcmd_mmap_entry_t)) )
++              return -EFAULT;
++          
++          for (j=0;j<n;j++)
++          {
++              struct vm_area_struct *vma = 
++                  find_vma( current->mm, msg[j].va );
++
++              if (!vma)
++                  return -EINVAL;
++
++              if (msg[j].va > PAGE_OFFSET)
++                  return -EINVAL;
++
++              if (msg[j].va + (msg[j].npages<<PAGE_SHIFT) > vma->vm_end)
++                  return -EINVAL;
++
++              if (direct_remap_area_pages(vma->vm_mm, 
++                                          msg[j].va&PAGE_MASK, 
++                                          msg[j].mfn<<PAGE_SHIFT, 
++                                          msg[j].npages<<PAGE_SHIFT, 
++                                          vma->vm_page_prot))
++                  return -EINVAL;
++          }
++      }
++      ret = 0;
++    }
++    break;
++
 +    default:
 +        ret = -EINVAL;
 +      break;
-   ioctl : privcmd_ioctl
++    }
 +    return ret;
 +}
 +
++static int privcmd_mmap(struct file * file, struct vm_area_struct * vma)
++{
++printk(KERN_ALERT"privcmd_mmap\n");
++      /* DONTCOPY is essential for Xen as copy_page_range is broken. */
++      vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY;
++
++      return 0;
++}
 +
 +static struct file_operations privcmd_file_ops = {
++  ioctl : privcmd_ioctl,
++  mmap:   privcmd_mmap
 +};
 +
 +
 +static int __init init_module(void)
 +{
 +    if ( !(start_info.flags & SIF_PRIVILEGED) )
 +        return 0;
 +
 +    privcmd_intf = create_xen_proc_entry("privcmd", 0400);
 +    if ( privcmd_intf != NULL )
 +    {
 +        privcmd_intf->owner      = THIS_MODULE;
 +        privcmd_intf->nlink      = 1;
 +      privcmd_intf->proc_fops  = &privcmd_file_ops;
 +    }
 +
 +    return 0;
 +}
 +
 +
 +static void __exit cleanup_module(void)
 +{
 +    if ( privcmd_intf == NULL ) return;
 +    remove_xen_proc_entry("privcmd");
 +    privcmd_intf = NULL;
 +}
 +
 +
 +module_init(init_module);
 +module_exit(cleanup_module);
index 665357d4bcc6dfb4cab757bad06ed48664f4d460,0000000000000000000000000000000000000000..6474d4c6ed3de7ed480776a32d5512028149f9cb
mode 100644,000000..100644
--- /dev/null
@@@ -1,253 -1,0 +1,258 @@@
 +/*
 + * arch/xen/mm/ioremap.c
 + *
 + * Re-map IO memory to kernel address space so that we can access it.
 + *
 + * (C) Copyright 1995 1996 Linus Torvalds
 + *
 + * Modifications for Xenolinux (c) 2003 Keir Fraser
 + */
 +
 +#include <linux/slab.h>
 +#include <linux/mm.h>
 +#include <linux/mman.h>
 +#include <linux/vmalloc.h>
 +#include <asm/io.h>
 +#include <asm/pgalloc.h>
 +#include <asm/uaccess.h>
 +#include <asm/tlb.h>
 +#include <asm/mmu.h>
 +
 +#if defined(CONFIG_XEN_PRIVILEGED_GUEST)
 +
 +/* These hacky macros avoid phys->machine translations. */
 +#define __direct_pte(x) ((pte_t) { (x) } )
 +#define __direct_mk_pte(page_nr,pgprot) \
 +  __direct_pte(((page_nr) << PAGE_SHIFT) | pgprot_val(pgprot))
 +#define direct_mk_pte_phys(physpage, pgprot) \
 +  __direct_mk_pte((physpage) >> PAGE_SHIFT, pgprot)
 +
 +static inline void direct_remap_area_pte(pte_t *pte, 
 +                                         unsigned long address, 
 +                                         unsigned long size,
 +                                         unsigned long machine_addr, 
 +                                         pgprot_t prot,
 +                                         domid_t  domid)
 +{
 +    unsigned long end;
 +
 +    mmu_update_t *u, *v;
 +    u = v = vmalloc(3*PAGE_SIZE); /* plenty */
 +
 +    /* If not I/O mapping then specify General-Purpose Subject Domain (GPS). */
 +    if ( domid != 0 )
 +    {
 +        v[0].val  = (unsigned long)(domid<<16) & ~0xFFFFUL;
 +        v[0].ptr  = (unsigned long)(domid<< 0) & ~0xFFFFUL;
 +        v[1].val  = (unsigned long)(domid>>16) & ~0xFFFFUL;
 +        v[1].ptr  = (unsigned long)(domid>>32) & ~0xFFFFUL;
 +        v[0].ptr |= MMU_EXTENDED_COMMAND;
 +        v[0].val |= MMUEXT_SET_SUBJECTDOM_L;
 +        v[1].ptr |= MMU_EXTENDED_COMMAND;
 +        v[1].val |= MMUEXT_SET_SUBJECTDOM_H;
 +        v += 2;
 +    }
 +
 +    address &= ~PMD_MASK;
 +    end = address + size;
 +    if (end > PMD_SIZE)
 +        end = PMD_SIZE;
 +    if (address >= end)
 +        BUG();
 +    do {
++#if 0  /* thanks to new ioctl mmaping interface this is no longer a bug */
 +        if (!pte_none(*pte)) {
 +            printk("direct_remap_area_pte: page already exists\n");
 +            BUG();
 +        }
++#endif
 +        v->ptr = virt_to_machine(pte);
 +        v->val = (machine_addr & PAGE_MASK) | pgprot_val(prot) | _PAGE_IO;
 +        v++;
 +        address += PAGE_SIZE;
 +        machine_addr += PAGE_SIZE;
 +        pte++;
 +    } while (address && (address < end));
 +
 +    if ( ((v-u) != 0) && (HYPERVISOR_mmu_update(u, v-u) < 0) )
 +        printk(KERN_WARNING "Failed to ioremap %08lx->%08lx (%08lx)\n",
 +               end-size, end, machine_addr-size);
 +    vfree(u);
 +}
 +
 +static inline int direct_remap_area_pmd(struct mm_struct *mm,
 +                                        pmd_t *pmd, 
 +                                        unsigned long address, 
 +                                        unsigned long size,
 +                                        unsigned long machine_addr,
 +                                        pgprot_t prot,
 +                                        domid_t  domid)
 +{
 +    unsigned long end;
 +
 +    address &= ~PGDIR_MASK;
 +    end = address + size;
 +    if (end > PGDIR_SIZE)
 +        end = PGDIR_SIZE;
 +    machine_addr -= address;
 +    if (address >= end)
 +        BUG();
 +    do {
 +        pte_t * pte = pte_alloc(mm, pmd, address);
 +        if (!pte)
 +            return -ENOMEM;
 +        direct_remap_area_pte(pte, address, end - address, 
 +                              address + machine_addr, prot, domid);
 +        address = (address + PMD_SIZE) & PMD_MASK;
 +        pmd++;
 +    } while (address && (address < end));
 +    return 0;
 +}
 + 
 +int direct_remap_area_pages(struct mm_struct *mm,
 +                            unsigned long address, 
 +                            unsigned long machine_addr,
 +                            unsigned long size, 
 +                            pgprot_t prot,
 +                            domid_t  domid)
 +{
 +    int error = 0;
 +    pgd_t * dir;
 +    unsigned long end = address + size;
 +
++printk("direct_remap_area_pages va=%08lx ma=%08lx size=%d\n",
++       address, machine_addr, size);
++
 +    machine_addr -= address;
 +    dir = pgd_offset(mm, address);
 +    flush_cache_all();
 +    if (address >= end)
 +        BUG();
 +    spin_lock(&mm->page_table_lock);
 +    do {
 +        pmd_t *pmd = pmd_alloc(mm, dir, address);
 +        error = -ENOMEM;
 +        if (!pmd)
 +            break;
 +        error = direct_remap_area_pmd(mm, pmd, address, end - address,
 +                                      machine_addr + address, prot, domid);
 +        if (error)
 +            break;
 +        address = (address + PGDIR_SIZE) & PGDIR_MASK;
 +        dir++;
 +    } while (address && (address < end));
 +    spin_unlock(&mm->page_table_lock);
 +    flush_tlb_all();
 +    return error;
 +}
 +
 +#endif /* CONFIG_XEN_PRIVILEGED_GUEST */
 +
 +
 +/*
 + * Remap an arbitrary machine address space into the kernel virtual
 + * address space. Needed when a privileged instance of Xenolinux wants
 + * to access space outside its world directly.
 + *
 + * NOTE! We need to allow non-page-aligned mappings too: we will obviously
 + * have to convert them into an offset in a page-aligned mapping, but the
 + * caller shouldn't need to know that small detail.
 + */
 +void * __ioremap(unsigned long machine_addr, 
 +                 unsigned long size, 
 +                 unsigned long flags)
 +{
 +#if defined(CONFIG_XEN_PRIVILEGED_GUEST)
 +    void * addr;
 +    struct vm_struct * area;
 +    unsigned long offset, last_addr;
 +    pgprot_t prot;
 +
 +    /* Only privileged Xenolinux can make unchecked pagetable updates. */
 +    if ( !(start_info.flags & SIF_PRIVILEGED) )
 +        return NULL;
 +
 +    /* Don't allow wraparound or zero size */
 +    last_addr = machine_addr + size - 1;
 +    if (!size || last_addr < machine_addr)
 +        return NULL;
 +
 +    /* Mappings have to be page-aligned */
 +    offset = machine_addr & ~PAGE_MASK;
 +    machine_addr &= PAGE_MASK;
 +    size = PAGE_ALIGN(last_addr+1) - machine_addr;
 +
 +    /* Ok, go for it */
 +    area = get_vm_area(size, VM_IOREMAP);
 +    if (!area)
 +        return NULL;
 +    addr = area->addr;
 +    prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | 
 +                    _PAGE_ACCESSED | flags);
 +    if (direct_remap_area_pages(&init_mm, VMALLOC_VMADDR(addr), 
 +                                machine_addr, size, prot, 0)) {
 +        vfree(addr);
 +        return NULL;
 +    }
 +    return (void *) (offset + (char *)addr);
 +#else
 +    return NULL;
 +#endif
 +}
 +
 +void iounmap(void *addr)
 +{
 +    vfree((void *)((unsigned long)addr & PAGE_MASK));
 +}
 +
 +/* implementation of boot time ioremap for purpose of provising access
 +to the vga console for privileged domains. Unlike boot time ioremap on 
 +other architectures, ours is permanent and not reclaimed when then vmalloc
 +infrastructure is started */
 +
 +void __init *bt_ioremap(unsigned long machine_addr, unsigned long size)
 +{
 +        unsigned long offset, last_addr;
 +        unsigned int nrpages;
 +        enum fixed_addresses idx;
 +
 +        /* Don't allow wraparound or zero size */
 +        last_addr = machine_addr + size - 1;
 +        if (!size || last_addr < machine_addr)
 +                return NULL;
 +
 +        /*
 +         * Mappings have to be page-aligned
 +         */
 +        offset = machine_addr & ~PAGE_MASK;
 +        machine_addr &= PAGE_MASK;
 +        size = PAGE_ALIGN(last_addr) - machine_addr;
 +
 +        /*
 +         * Mappings have to fit in the FIX_BTMAP area.
 +         */
 +        nrpages = size >> PAGE_SHIFT;
 +        if (nrpages > NR_FIX_BTMAPS)
 +                return NULL;
 +
 +        /*
 +         * Ok, go for it..
 +         */
 +        idx = FIX_BTMAP_BEGIN;
 +        while (nrpages > 0) {
 +                __set_fixmap(idx, machine_addr, 
 +                             __pgprot(__PAGE_KERNEL|_PAGE_IO));
 +                machine_addr += PAGE_SIZE;
 +                --idx;
 +                --nrpages;
 +        }
 +
 +      flush_tlb_all();
 +
 +        return (void*) (offset + fix_to_virt(FIX_BTMAP_BEGIN));
 +}
 +
 +
 +#if 0 /* We don't support these functions. They shouldn't be required. */
 +void __init bt_iounmap(void *addr, unsigned long size) {}
 +#endif
index 4ce2930daa037e35da9ae1ac5056752d1cd1eabf,0000000000000000000000000000000000000000..205355fa9c40749ae581363e90a6cace6bef4d84
mode 100644,000000..100644
--- /dev/null
@@@ -1,28 -1,0 +1,41 @@@
 +/******************************************************************************
 + * proc_cmd.h
 + * 
 + * Interface to /proc/cmd and /proc/xen/privcmd.
 + */
 +
 +#ifndef __PROC_CMD_H__
 +#define __PROC_CMD_H__
 +
 +typedef struct privcmd_hypercall
 +{
 +    unsigned long op;
 +    unsigned long arg[5];
 +} privcmd_hypercall_t;
 +
++typedef struct privcmd_mmap_entry {
++    unsigned long va;
++    unsigned long mfn;
++    unsigned long npages;
++} privcmd_mmap_entry_t; 
++
++typedef struct privcmd_mmap {
++    int num;
++    privcmd_mmap_entry_t *entry;
++} privcmd_mmap_t; 
++
 +typedef struct privcmd_blkmsg
 +{
 +    unsigned long op;
 +    void         *buf;
 +    int           buf_size;
 +} privcmd_blkmsg_t;
 +
 +#define IOCTL_PRIVCMD_HYPERCALL        \
 +    _IOC(_IOC_NONE, 'P', 0, sizeof(privcmd_hypercall_t))
 +#define IOCTL_PRIVCMD_BLKMSG           \
 +    _IOC(_IOC_NONE, 'P', 1, sizeof(privcmd_blkmsg_t))
++#define IOCTL_PRIVCMD_MMAP             \
++    _IOC(_IOC_NONE, 'P', 2, sizeof(privcmd_mmap_t))
 +
 +#endif /* __PROC_CMD_H__ */