[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] merge with xen-unstable.hg staging



# HG changeset patch
# User Alex Williamson <alex.williamson@xxxxxx>
# Date 1200689388 25200
# Node ID a868bd4236e6da06dd8dad88b66ad4f55dcc4b50
# Parent  7643472d6b436a7433b98e8708979e2674fa9047
# Parent  1e6455d608bd06a3cc4ec83fd2cf5943d0dac20f
merge with xen-unstable.hg staging
---
 docs/man/xm.pod.1                         |   13 
 extras/mini-os/Makefile                   |    2 
 extras/mini-os/arch/ia64/mm.c             |    9 
 extras/mini-os/arch/x86/minios-x86_32.lds |    2 
 extras/mini-os/arch/x86/minios-x86_64.lds |    2 
 extras/mini-os/arch/x86/mm.c              |  163 +++-
 extras/mini-os/arch/x86/traps.c           |   44 +
 extras/mini-os/blkfront.c                 |  392 ++++++++++
 extras/mini-os/fs-front.c                 | 1126 ++++++++++++++++++++++++++++++
 extras/mini-os/include/blkfront.h         |   26 
 extras/mini-os/include/fs.h               |   51 +
 extras/mini-os/include/ia64/arch_mm.h     |    4 
 extras/mini-os/include/mm.h               |    5 
 extras/mini-os/include/types.h            |   10 
 extras/mini-os/include/x86/arch_mm.h      |    7 
 extras/mini-os/include/x86/traps.h        |    4 
 extras/mini-os/kernel.c                   |    7 
 tools/examples/network-nat                |    6 
 tools/fs-back/Makefile                    |   40 +
 tools/fs-back/fs-backend.c                |  346 +++++++++
 tools/fs-back/fs-backend.h                |   86 ++
 tools/fs-back/fs-ops.c                    |  658 +++++++++++++++++
 tools/fs-back/fs-xenbus.c                 |  180 ++++
 tools/ioemu/target-i386-dm/helper2.c      |   12 
 tools/python/xen/xend/image.py            |    2 
 tools/xentrace/xenctx.c                   |  104 +-
 unmodified_drivers/linux-2.6/mkbuildtree  |   59 -
 xen/arch/ia64/xen/hypercall.c             |    5 
 xen/arch/x86/hvm/vmx/vtd/dmar.c           |  223 +++--
 xen/arch/x86/hvm/vmx/vtd/dmar.h           |   31 
 xen/arch/x86/hvm/vmx/vtd/utils.c          |    9 
 xen/arch/x86/traps.c                      |    2 
 xen/arch/x86/x86_32/traps.c               |    2 
 xen/arch/x86/x86_64/traps.c               |    2 
 xen/include/asm-x86/hvm/vmx/intel-iommu.h |   93 +-
 xen/include/asm-x86/hypercall.h           |    2 
 xen/include/public/arch-ia64.h            |   15 
 xen/include/public/arch-powerpc.h         |   13 
 xen/include/public/arch-x86/xen.h         |   13 
 xen/include/public/io/fsif.h              |  181 ++++
 xen/include/public/xen.h                  |   13 
 41 files changed, 3692 insertions(+), 272 deletions(-)

diff -r 7643472d6b43 -r a868bd4236e6 docs/man/xm.pod.1
--- a/docs/man/xm.pod.1 Thu Jan 17 12:17:14 2008 -0700
+++ b/docs/man/xm.pod.1 Fri Jan 18 13:49:48 2008 -0700
@@ -254,9 +254,12 @@ domain, as it may balloon down its memor
 
 =item B<mem-set> I<domain-id> I<mem>
 
-Set the domain's used memory using the balloon driver.  Because this
-operation requires cooperation from the domain operating system, there
-is no guarantee that it will succeed.
+Set the domain's used memory using the balloon driver.
+
+Because this operation requires cooperation from the domain operating
+system, there is no guarantee that it will succeed.  This command will
+definitely not work unless the domain has the required paravirt
+driver.
 
 B<Warning:> There is no good way to know in advance how small of a
 mem-set will make a domain unstable and cause it to crash.  Be very
@@ -391,6 +394,10 @@ Attempting to set the VCPUs to a number 
 Attempting to set the VCPUs to a number larger than the initially
 configured VCPU count is an error.  Trying to set VCPUs to < 1 will be
 quietly ignored.
+
+Because this operation requires cooperation from the domain operating
+system, there is no guarantee that it will succeed.  This command will
+not work with a full virt domain.
 
 =item B<vcpu-list> [I<domain-id>]
 
diff -r 7643472d6b43 -r a868bd4236e6 extras/mini-os/Makefile
--- a/extras/mini-os/Makefile   Thu Jan 17 12:17:14 2008 -0700
+++ b/extras/mini-os/Makefile   Fri Jan 18 13:49:48 2008 -0700
@@ -53,7 +53,7 @@ include minios.mk
 # Define some default flags for linking.
 LDLIBS := 
 LDARCHLIB := -L$(TARGET_ARCH_DIR) -l$(ARCH_LIB_NAME)
-LDFLAGS_FINAL := -N -T $(TARGET_ARCH_DIR)/minios-$(TARGET_ARCH).lds
+LDFLAGS_FINAL := -T $(TARGET_ARCH_DIR)/minios-$(TARGET_ARCH).lds
 
 # Prefix for global API names. All other symbols are localised before
 # linking with EXTRA_OBJS.
diff -r 7643472d6b43 -r a868bd4236e6 extras/mini-os/arch/ia64/mm.c
--- a/extras/mini-os/arch/ia64/mm.c     Thu Jan 17 12:17:14 2008 -0700
+++ b/extras/mini-os/arch/ia64/mm.c     Fri Jan 18 13:49:48 2008 -0700
@@ -124,9 +124,14 @@ arch_init_demand_mapping_area(unsigned l
 
 /* Helper function used in gnttab.c. */
 void*
-map_frames(unsigned long* frames, unsigned long n)
+map_frames_ex(unsigned long* frames, unsigned long n, unsigned long stride,
+       unsigned long increment, unsigned long alignment, domid_t id,
+       int may_fail, unsigned long prot)
 {
-       n = n;
+        /* TODO: incomplete! */
+        ASSERT(n == 1 || (stride == 0 && increment == 1));
+        ASSERT(id == DOMID_SELF);
+        ASSERT(prot == 0);
        return (void*) __va(SWAP(frames[0]) << PAGE_SHIFT);
 }
 
diff -r 7643472d6b43 -r a868bd4236e6 extras/mini-os/arch/x86/minios-x86_32.lds
--- a/extras/mini-os/arch/x86/minios-x86_32.lds Thu Jan 17 12:17:14 2008 -0700
+++ b/extras/mini-os/arch/x86/minios-x86_32.lds Fri Jan 18 13:49:48 2008 -0700
@@ -13,6 +13,8 @@ SECTIONS
   _etext = .;                  /* End of text section */
 
   .rodata : { *(.rodata) *(.rodata.*) }
+  . = ALIGN(4096);
+  _erodata = .;
 
   .data : {                    /* Data */
        *(.data)
diff -r 7643472d6b43 -r a868bd4236e6 extras/mini-os/arch/x86/minios-x86_64.lds
--- a/extras/mini-os/arch/x86/minios-x86_64.lds Thu Jan 17 12:17:14 2008 -0700
+++ b/extras/mini-os/arch/x86/minios-x86_64.lds Fri Jan 18 13:49:48 2008 -0700
@@ -13,6 +13,8 @@ SECTIONS
   _etext = .;                  /* End of text section */
 
   .rodata : { *(.rodata) *(.rodata.*) }
+  . = ALIGN(4096);
+  _erodata = .;
 
   .data : {                    /* Data */
        *(.data)
diff -r 7643472d6b43 -r a868bd4236e6 extras/mini-os/arch/x86/mm.c
--- a/extras/mini-os/arch/x86/mm.c      Thu Jan 17 12:17:14 2008 -0700
+++ b/extras/mini-os/arch/x86/mm.c      Fri Jan 18 13:49:48 2008 -0700
@@ -40,6 +40,7 @@
 #include <types.h>
 #include <lib.h>
 #include <xmalloc.h>
+#include <xen/memory.h>
 
 #ifdef MM_DEBUG
 #define DEBUG(_f, _a...) \
@@ -49,6 +50,7 @@
 #endif
 
 unsigned long *phys_to_machine_mapping;
+unsigned long mfn_zero;
 extern char stack[];
 extern void page_walk(unsigned long virt_addr);
 
@@ -270,12 +272,73 @@ void build_pagetable(unsigned long *star
         start_address += PAGE_SIZE;
     }
 
-    if (HYPERVISOR_update_va_mapping(0, (pte_t) {}, UVMF_INVLPG))
-        printk("Unable to unmap page 0\n");
-
     *start_pfn = pt_pfn;
 }
 
+extern void shared_info;
+static void set_readonly(void *text, void *etext)
+{
+    unsigned long start_address = ((unsigned long) text + PAGE_SIZE - 1) & 
PAGE_MASK;
+    unsigned long end_address = (unsigned long) etext;
+    static mmu_update_t mmu_updates[L1_PAGETABLE_ENTRIES + 1];
+    pgentry_t *tab = (pgentry_t *)start_info.pt_base, page;
+    unsigned long mfn = pfn_to_mfn(virt_to_pfn(start_info.pt_base));
+    unsigned long offset;
+    int count = 0;
+
+    printk("setting %p-%p readonly\n", text, etext);
+
+    while (start_address + PAGE_SIZE <= end_address) {
+        tab = (pgentry_t *)start_info.pt_base;
+        mfn = pfn_to_mfn(virt_to_pfn(start_info.pt_base));
+
+#if defined(__x86_64__)
+        offset = l4_table_offset(start_address);
+        page = tab[offset];
+        mfn = pte_to_mfn(page);
+        tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT);
+#endif
+#if defined(__x86_64__) || defined(CONFIG_X86_PAE)
+        offset = l3_table_offset(start_address);
+        page = tab[offset];
+        mfn = pte_to_mfn(page);
+        tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT);
+#endif
+        offset = l2_table_offset(start_address);        
+        page = tab[offset];
+        mfn = pte_to_mfn(page);
+        tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT);
+
+        offset = l1_table_offset(start_address);
+
+       if (start_address != (unsigned long)&shared_info) {
+           mmu_updates[count].ptr = ((pgentry_t)mfn << PAGE_SHIFT) + 
sizeof(pgentry_t) * offset;
+           mmu_updates[count].val = tab[offset] & ~_PAGE_RW;
+           count++;
+       } else
+           printk("skipped %p\n", start_address);
+
+        start_address += PAGE_SIZE;
+
+        if (count == L1_PAGETABLE_ENTRIES || start_address + PAGE_SIZE > 
end_address)
+        {
+            if(HYPERVISOR_mmu_update(mmu_updates, count, NULL, DOMID_SELF) < 0)
+            {
+                printk("PTE could not be updated\n");
+                do_exit();
+            }
+            count = 0;
+        }
+    }
+
+    {
+       mmuext_op_t op = {
+           .cmd = MMUEXT_TLB_FLUSH_ALL,
+       };
+       int count;
+       HYPERVISOR_mmuext_op(&op, 1, &count, DOMID_SELF);
+    }
+}
 
 void mem_test(unsigned long *start_add, unsigned long *end_add)
 {
@@ -305,6 +368,7 @@ void mem_test(unsigned long *start_add, 
 
 static pgentry_t *demand_map_pgt;
 static void *demand_map_area_start;
+#define DEMAND_MAP_PAGES 1024
 
 void arch_init_demand_mapping_area(unsigned long max_pfn)
 {
@@ -364,20 +428,19 @@ void arch_init_demand_mapping_area(unsig
     printk("Initialised demand area.\n");
 }
 
-void *map_frames(unsigned long *f, unsigned long n)
+#define MAP_BATCH ((STACK_SIZE / 2) / sizeof(mmu_update_t))
+
+void *map_frames_ex(unsigned long *f, unsigned long n, unsigned long stride,
+       unsigned long increment, unsigned long alignment, domid_t id,
+       int may_fail, unsigned long prot)
 {
     unsigned long x;
     unsigned long y = 0;
-    mmu_update_t mmu_updates[16];
     int rc;
-
-    if (n > 16) {
-        printk("Tried to map too many (%ld) frames at once.\n", n);
-        return NULL;
-    }
+    unsigned long done = 0;
 
     /* Find a run of n contiguous frames */
-    for (x = 0; x <= 1024 - n; x += y + 1) {
+    for (x = 0; x <= DEMAND_MAP_PAGES - n; x = (x + y + 1 + alignment - 1) & 
~(alignment - 1)) {
         for (y = 0; y < n; y++)
             if (demand_map_pgt[x+y] & _PAGE_PRESENT)
                 break;
@@ -385,26 +448,68 @@ void *map_frames(unsigned long *f, unsig
             break;
     }
     if (y != n) {
-        printk("Failed to map %ld frames!\n", n);
+        printk("Failed to find %ld frames!\n", n);
         return NULL;
     }
 
     /* Found it at x.  Map it in. */
-    for (y = 0; y < n; y++) {
-        mmu_updates[y].ptr = virt_to_mach(&demand_map_pgt[x + y]);
-        mmu_updates[y].val = (f[y] << PAGE_SHIFT) | L1_PROT;
-    }
-
-    rc = HYPERVISOR_mmu_update(mmu_updates, n, NULL, DOMID_SELF);
-    if (rc < 0) {
-        printk("Map %ld failed: %d.\n", n, rc);
-        return NULL;
-    } else {
-        return (void *)(unsigned long)((unsigned long)demand_map_area_start +
-                x * PAGE_SIZE);
-    }
-}
-
+
+    while (done < n) {
+       unsigned long todo;
+
+       if (may_fail)
+           todo = 1;
+       else
+           todo = n - done;
+
+       if (todo > MAP_BATCH)
+               todo = MAP_BATCH;
+
+       {
+           mmu_update_t mmu_updates[todo];
+
+           for (y = 0; y < todo; y++) {
+               mmu_updates[y].ptr = virt_to_mach(&demand_map_pgt[x + done + 
y]);
+               mmu_updates[y].val = ((f[(done + y) * stride] + (done + y) * 
increment) << PAGE_SHIFT) | prot;
+           }
+
+           rc = HYPERVISOR_mmu_update(mmu_updates, todo, NULL, id);
+           if (rc < 0) {
+               if (may_fail)
+                   f[done * stride] |= 0xF0000000;
+               else {
+                   printk("Map %ld (%lx, ...) failed: %d.\n", todo, f[done * 
stride], rc);
+                   return NULL;
+               }
+           }
+       }
+
+       done += todo;
+    }
+    return (void *)(unsigned long)((unsigned long)demand_map_area_start +
+           x * PAGE_SIZE);
+}
+
+static void clear_bootstrap(void)
+{
+    struct xen_memory_reservation reservation;
+    xen_pfn_t mfns[] = { virt_to_mfn(&shared_info) };
+    int n = sizeof(mfns)/sizeof(*mfns);
+    pte_t nullpte = { };
+
+    /* Use page 0 as the CoW zero page */
+    memset(NULL, 0, PAGE_SIZE);
+    mfn_zero = pfn_to_mfn(0);
+    if (HYPERVISOR_update_va_mapping(0, nullpte, UVMF_INVLPG))
+       printk("Unable to unmap page 0\n");
+
+    set_xen_guest_handle(reservation.extent_start, mfns);
+    reservation.nr_extents = n;
+    reservation.extent_order = 0;
+    reservation.domid = DOMID_SELF;
+    if (HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation) != n)
+       printk("Unable to free bootstrap pages\n");
+}
 
 void arch_init_p2m(unsigned long max_pfn)
 {
@@ -455,6 +560,7 @@ void arch_init_mm(unsigned long* start_p
 
     printk("  _text:        %p\n", &_text);
     printk("  _etext:       %p\n", &_etext);
+    printk("  _erodata:     %p\n", &_erodata);
     printk("  _edata:       %p\n", &_edata);
     printk("  stack start:  %p\n", stack);
     printk("  _end:         %p\n", &_end);
@@ -468,8 +574,9 @@ void arch_init_mm(unsigned long* start_p
     printk("  max_pfn:      %lx\n", max_pfn);
 
     build_pagetable(&start_pfn, &max_pfn);
+    clear_bootstrap();
+    set_readonly(&_text, &_erodata);
 
     *start_pfn_p = start_pfn;
     *max_pfn_p = max_pfn;
 }
-
diff -r 7643472d6b43 -r a868bd4236e6 extras/mini-os/arch/x86/traps.c
--- a/extras/mini-os/arch/x86/traps.c   Thu Jan 17 12:17:14 2008 -0700
+++ b/extras/mini-os/arch/x86/traps.c   Fri Jan 18 13:49:48 2008 -0700
@@ -118,6 +118,46 @@ void page_walk(unsigned long virt_addres
 
 }
 
+static int handle_cow(unsigned long addr) {
+        pgentry_t *tab = (pgentry_t *)start_info.pt_base, page;
+       unsigned long new_page;
+       int rc;
+
+#if defined(__x86_64__)
+        page = tab[l4_table_offset(addr)];
+       if (!(page & _PAGE_PRESENT))
+           return 0;
+        tab = pte_to_virt(page);
+#endif
+#if defined(__x86_64__) || defined(CONFIG_X86_PAE)
+        page = tab[l3_table_offset(addr)];
+       if (!(page & _PAGE_PRESENT))
+           return 0;
+        tab = pte_to_virt(page);
+#endif
+        page = tab[l2_table_offset(addr)];
+       if (!(page & _PAGE_PRESENT))
+           return 0;
+        tab = pte_to_virt(page);
+        
+        page = tab[l1_table_offset(addr)];
+       if (!(page & _PAGE_PRESENT))
+           return 0;
+       /* Only support CoW for the zero page.  */
+       if (PHYS_PFN(page) != mfn_zero)
+           return 0;
+
+       new_page = alloc_pages(0);
+       memset((void*) new_page, 0, PAGE_SIZE);
+
+       rc = HYPERVISOR_update_va_mapping(addr & PAGE_MASK, 
__pte(virt_to_mach(new_page) | L1_PROT), UVMF_INVLPG);
+       if (!rc)
+               return 1;
+
+       printk("Map zero page to %lx failed: %d.\n", addr, rc);
+       return 0;
+}
+
 #define read_cr2() \
         (HYPERVISOR_shared_info->vcpu_info[smp_processor_id()].arch.cr2)
 
@@ -126,6 +166,10 @@ void do_page_fault(struct pt_regs *regs,
 void do_page_fault(struct pt_regs *regs, unsigned long error_code)
 {
     unsigned long addr = read_cr2();
+
+    if ((error_code & TRAP_PF_WRITE) && handle_cow(addr))
+       return;
+
     /* If we are already handling a page fault, and got another one
        that means we faulted in pagetable walk. Continuing here would cause
        a recursive fault */       
diff -r 7643472d6b43 -r a868bd4236e6 extras/mini-os/blkfront.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/blkfront.c Fri Jan 18 13:49:48 2008 -0700
@@ -0,0 +1,392 @@
+/* Minimal block driver for Mini-OS. 
+ * Copyright (c) 2007-2008 Samuel Thibault.
+ * Based on netfront.c.
+ */
+
+#include <os.h>
+#include <xenbus.h>
+#include <events.h>
+#include <errno.h>
+#include <xen/io/blkif.h>
+#include <gnttab.h>
+#include <xmalloc.h>
+#include <time.h>
+#include <blkfront.h>
+#include <lib.h>
+#include <fcntl.h>
+
+/* Note: we generally don't need to disable IRQs since we hardly do anything in
+ * the interrupt handler.  */
+
+/* Note: we really suppose non-preemptive threads.  */
+
+DECLARE_WAIT_QUEUE_HEAD(blkfront_queue);
+
+
+
+
+#define BLK_RING_SIZE __RING_SIZE((struct blkif_sring *)0, PAGE_SIZE)
+#define GRANT_INVALID_REF 0
+
+
+struct blk_buffer {
+    void* page;
+    grant_ref_t gref;
+};
+
+struct blkfront_dev {
+    struct blkif_front_ring ring;
+    grant_ref_t ring_ref;
+    evtchn_port_t evtchn, local_port;
+    blkif_vdev_t handle;
+
+    char *nodename;
+    char *backend;
+    unsigned sector_size;
+    unsigned sectors;
+    int mode;
+    int barrier;
+    int flush;
+};
+
+static inline int xenblk_rxidx(RING_IDX idx)
+{
+    return idx & (BLK_RING_SIZE - 1);
+}
+
+void blkfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
+{
+    wake_up(&blkfront_queue);
+}
+
+struct blkfront_dev *init_blkfront(char *nodename, uint64_t *sectors, unsigned 
*sector_size, int *mode)
+{
+    xenbus_transaction_t xbt;
+    char* err;
+    char* message=NULL;
+    struct blkif_sring *s;
+    int retry=0;
+    char* msg;
+    char* c;
+
+    struct blkfront_dev *dev;
+
+    ASSERT(!strncmp(nodename, "/local/domain/", 14));
+    nodename = strchr(nodename + 14, '/') + 1;
+
+    char path[strlen(nodename) + 1 + 10 + 1];
+
+    printk("******************* BLKFRONT for %s **********\n\n\n", nodename);
+
+    dev = malloc(sizeof(*dev));
+    dev->nodename = strdup(nodename);
+
+    s = (struct blkif_sring*) alloc_page();
+    memset(s,0,PAGE_SIZE);
+
+
+    SHARED_RING_INIT(s);
+    FRONT_RING_INIT(&dev->ring, s, PAGE_SIZE);
+
+    dev->ring_ref = gnttab_grant_access(0,virt_to_mfn(s),0);
+
+    evtchn_alloc_unbound_t op;
+    op.dom = DOMID_SELF;
+    snprintf(path, sizeof(path), "%s/backend-id", nodename);
+    op.remote_dom = xenbus_read_integer(path); 
+    HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
+    clear_evtchn(op.port);        /* Without, handler gets invoked now! */
+    dev->local_port = bind_evtchn(op.port, blkfront_handler, dev);
+    dev->evtchn=op.port;
+
+    // FIXME: proper frees on failures
+again:
+    err = xenbus_transaction_start(&xbt);
+    if (err) {
+        printk("starting transaction\n");
+    }
+
+    err = xenbus_printf(xbt, nodename, "ring-ref","%u",
+                dev->ring_ref);
+    if (err) {
+        message = "writing ring-ref";
+        goto abort_transaction;
+    }
+    err = xenbus_printf(xbt, nodename,
+                "event-channel", "%u", dev->evtchn);
+    if (err) {
+        message = "writing event-channel";
+        goto abort_transaction;
+    }
+
+    err = xenbus_printf(xbt, nodename, "state", "%u",
+            4); /* connected */
+
+
+    err = xenbus_transaction_end(xbt, 0, &retry);
+    if (retry) {
+            goto again;
+        printk("completing transaction\n");
+    }
+
+    goto done;
+
+abort_transaction:
+    xenbus_transaction_end(xbt, 1, &retry);
+    return NULL;
+
+done:
+
+    snprintf(path, sizeof(path), "%s/backend", nodename);
+    msg = xenbus_read(XBT_NIL, path, &dev->backend);
+    if (msg) {
+        printk("Error %s when reading the backend path %s\n", msg, path);
+        return NULL;
+    }
+
+    printk("backend at %s\n", dev->backend);
+
+    dev->handle = simple_strtoul(strrchr(nodename, '/')+1, NULL, 0);
+
+    {
+        char path[strlen(dev->backend) + 1 + 19 + 1];
+        snprintf(path, sizeof(path), "%s/mode", dev->backend);
+        msg = xenbus_read(XBT_NIL, path, &c);
+        if (msg) {
+            printk("Error %s when reading the mode\n", msg);
+            return NULL;
+        }
+        if (*c == 'w')
+            *mode = dev->mode = O_RDWR;
+        else
+            *mode = dev->mode = O_RDONLY;
+        free(c);
+
+        snprintf(path, sizeof(path), "%s/state", dev->backend);
+
+        xenbus_watch_path(XBT_NIL, path);
+
+        xenbus_wait_for_value(path,"4");
+
+        xenbus_unwatch_path(XBT_NIL, path);
+
+        snprintf(path, sizeof(path), "%s/sectors", dev->backend);
+        // FIXME: read_integer returns an int, so disk size limited to 1TB for 
now
+        *sectors = dev->sectors = xenbus_read_integer(path);
+
+        snprintf(path, sizeof(path), "%s/sector-size", dev->backend);
+        *sector_size = dev->sector_size = xenbus_read_integer(path);
+
+        snprintf(path, sizeof(path), "%s/feature-barrier", dev->backend);
+        dev->barrier = xenbus_read_integer(path);
+
+        snprintf(path, sizeof(path), "%s/feature-flush-cache", dev->backend);
+        dev->flush = xenbus_read_integer(path);
+    }
+
+    printk("%u sectors of %u bytes\n", dev->sectors, dev->sector_size);
+    printk("**************************\n");
+
+    return dev;
+}
+
+void shutdown_blkfront(struct blkfront_dev *dev)
+{
+    char* err;
+    char *nodename = dev->nodename;
+
+    char path[strlen(dev->backend) + 1 + 5 + 1];
+
+    blkfront_sync(dev);
+
+    printk("close blk: backend at %s\n",dev->backend);
+
+    snprintf(path, sizeof(path), "%s/state", dev->backend);
+    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */
+    xenbus_wait_for_value(path,"5");
+
+    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
+    xenbus_wait_for_value(path,"6");
+
+    unbind_evtchn(dev->local_port);
+
+    free(nodename);
+    free(dev->backend);
+    free(dev);
+}
+
+static void blkfront_wait_slot(struct blkfront_dev *dev)
+{
+    /* Wait for a slot */
+    if (RING_FULL(&dev->ring)) {
+       unsigned long flags;
+       DEFINE_WAIT(w);
+       local_irq_save(flags);
+       while (1) {
+           blkfront_aio_poll(dev);
+           if (!RING_FULL(&dev->ring))
+               break;
+           /* Really no slot, go to sleep. */
+           add_waiter(w, blkfront_queue);
+           local_irq_restore(flags);
+           schedule();
+           local_irq_save(flags);
+       }
+       remove_waiter(w);
+       local_irq_restore(flags);
+    }
+}
+
+/* Issue an aio */
+void blkfront_aio(struct blkfront_aiocb *aiocbp, int write)
+{
+    struct blkfront_dev *dev = aiocbp->aio_dev;
+    struct blkif_request *req;
+    RING_IDX i;
+    int notify;
+    int n, j;
+    uintptr_t start, end;
+
+    // Can't io at non-sector-aligned location
+    ASSERT(!(aiocbp->aio_offset & (dev->sector_size-1)));
+    // Can't io non-sector-sized amounts
+    ASSERT(!(aiocbp->aio_nbytes & (dev->sector_size-1)));
+    // Can't io non-sector-aligned buffer
+    ASSERT(!((uintptr_t) aiocbp->aio_buf & (dev->sector_size-1)));
+
+    start = (uintptr_t)aiocbp->aio_buf & PAGE_MASK;
+    end = ((uintptr_t)aiocbp->aio_buf + aiocbp->aio_nbytes + PAGE_SIZE - 1) & 
PAGE_MASK;
+    n = (end - start) / PAGE_SIZE;
+
+    /* qemu's IDE max multsect is 16 (8KB) and SCSI max DMA was set to 32KB,
+     * so max 44KB can't happen */
+    ASSERT(n <= BLKIF_MAX_SEGMENTS_PER_REQUEST);
+
+    blkfront_wait_slot(dev);
+    i = dev->ring.req_prod_pvt;
+    req = RING_GET_REQUEST(&dev->ring, i);
+
+    req->operation = write ? BLKIF_OP_WRITE : BLKIF_OP_READ;
+    req->nr_segments = n;
+    req->handle = dev->handle;
+    req->id = (uintptr_t) aiocbp;
+    req->sector_number = aiocbp->aio_offset / dev->sector_size;
+
+    for (j = 0; j < n; j++) {
+       uintptr_t data = start + j * PAGE_SIZE;
+       aiocbp->gref[j] = req->seg[j].gref =
+            gnttab_grant_access(0, virt_to_mfn(data), write);
+       req->seg[j].first_sect = 0;
+       req->seg[j].last_sect = PAGE_SIZE / dev->sector_size - 1;
+    }
+    req->seg[0].first_sect = ((uintptr_t)aiocbp->aio_buf & ~PAGE_MASK) / 
dev->sector_size;
+    req->seg[n-1].last_sect = (((uintptr_t)aiocbp->aio_buf + 
aiocbp->aio_nbytes - 1) & ~PAGE_MASK) / dev->sector_size;
+
+    dev->ring.req_prod_pvt = i + 1;
+
+    wmb();
+    RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&dev->ring, notify);
+
+    if(notify) notify_remote_via_evtchn(dev->evtchn);
+}
+
+void blkfront_aio_write(struct blkfront_aiocb *aiocbp)
+{
+    blkfront_aio(aiocbp, 1);
+}
+
+void blkfront_aio_read(struct blkfront_aiocb *aiocbp)
+{
+    blkfront_aio(aiocbp, 0);
+}
+
+int blkfront_aio_poll(struct blkfront_dev *dev)
+{
+    RING_IDX rp, cons;
+    struct blkif_response *rsp;
+
+moretodo:
+    rp = dev->ring.sring->rsp_prod;
+    rmb(); /* Ensure we see queued responses up to 'rp'. */
+    cons = dev->ring.rsp_cons;
+
+    int nr_consumed = 0;
+    while ((cons != rp))
+    {
+       rsp = RING_GET_RESPONSE(&dev->ring, cons);
+
+        switch (rsp->operation) {
+        case BLKIF_OP_READ:
+        case BLKIF_OP_WRITE:
+        {
+            struct blkfront_aiocb *aiocbp = (void*) (uintptr_t) rsp->id;
+            int n = (aiocbp->aio_nbytes + PAGE_SIZE - 1) / PAGE_SIZE, j;
+            for (j = 0; j < n; j++)
+                gnttab_end_access(aiocbp->gref[j]);
+
+            /* Nota: callback frees aiocbp itself */
+            aiocbp->aio_cb(aiocbp, rsp->status ? -EIO : 0);
+            break;
+        }
+        case BLKIF_OP_WRITE_BARRIER:
+        case BLKIF_OP_FLUSH_DISKCACHE:
+            break;
+        default:
+            printk("unrecognized block operation %d response\n", 
rsp->operation);
+            break;
+        }
+
+       nr_consumed++;
+       ++cons;
+    }
+    dev->ring.rsp_cons = cons;
+
+    int more;
+    RING_FINAL_CHECK_FOR_RESPONSES(&dev->ring, more);
+    if (more) goto moretodo;
+
+    return nr_consumed;
+}
+
+static void blkfront_push_operation(struct blkfront_dev *dev, uint8_t op)
+{
+    int i;
+    struct blkif_request *req;
+    int notify;
+
+    blkfront_wait_slot(dev);
+    i = dev->ring.req_prod_pvt;
+    req = RING_GET_REQUEST(&dev->ring, i);
+    req->operation = op;
+    dev->ring.req_prod_pvt = i + 1;
+    wmb();
+    RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&dev->ring, notify);
+    if (notify) notify_remote_via_evtchn(dev->evtchn);
+}
+
+void blkfront_sync(struct blkfront_dev *dev)
+{
+    unsigned long flags;
+
+    if (dev->barrier == 1)
+        blkfront_push_operation(dev, BLKIF_OP_WRITE_BARRIER);
+
+    if (dev->flush == 1)
+        blkfront_push_operation(dev, BLKIF_OP_FLUSH_DISKCACHE);
+
+    /* Note: This won't finish if another thread enqueues requests.  */
+    local_irq_save(flags);
+    DEFINE_WAIT(w);
+    while (1) {
+       blkfront_aio_poll(dev);
+       if (RING_FREE_REQUESTS(&dev->ring) == RING_SIZE(&dev->ring))
+           break;
+
+       add_waiter(w, blkfront_queue);
+       local_irq_restore(flags);
+       schedule();
+       local_irq_save(flags);
+    }
+    remove_waiter(w);
+    local_irq_restore(flags);
+}
diff -r 7643472d6b43 -r a868bd4236e6 extras/mini-os/fs-front.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/fs-front.c Fri Jan 18 13:49:48 2008 -0700
@@ -0,0 +1,1126 @@
+/******************************************************************************
+ * fs-front.c
+ * 
+ * Frontend driver for FS split device driver.
+ *
+ * Copyright (c) 2007, Grzegorz Milos, Sun Microsystems, Inc.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#undef NDEBUG
+#include <os.h>
+#include <list.h>
+#include <xmalloc.h>
+#include <xenbus.h>
+#include <gnttab.h>
+#include <events.h>
+#include <xen/io/fsif.h>
+#include <fs.h>
+#include <sched.h>
+
+#define preempt_disable()
+#define preempt_enable()
+#define cmpxchg(p,o,n) synch_cmpxchg(p,o,n)
+
+
+#ifdef FS_DEBUG
+#define DEBUG(_f, _a...) \
+    printk("MINI_OS(file=fs-front.c, line=%d) " _f "\n", __LINE__, ## _a)
+#else
+#define DEBUG(_f, _a...)    ((void)0)
+#endif
+
+
+struct fs_request;
+struct fs_import *fs_import;
+
+/******************************************************************************/
+/*                      RING REQUEST/RESPONSES HANDLING                       
*/
+/******************************************************************************/
+
+struct fs_request
+{
+    void *page;
+    grant_ref_t gref;
+    struct thread *thread;                 /* Thread blocked on this request */
+    struct fsif_response shadow_rsp;       /* Response copy writen by the 
+                                              interrupt handler */  
+};
+
+/* Ring operations:
+ * FSIF ring is used differently to Linux-like split devices. This stems from 
+ * the fact that no I/O request queue is present. The use of some of the macros
+ * defined in ring.h is not allowed, in particular:
+ * RING_PUSH_REQUESTS_AND_CHECK_NOTIFY cannot be used.
+ *
+ * The protocol used for FSIF ring is described below:
+ *
+ * In order to reserve a request the frontend:
+ * a) saves current frontend_ring->req_prod_pvt into a local variable
+ * b) checks that there are free request using the local req_prod_pvt
+ * c) tries to reserve the request using cmpxchg on frontend_ring->req_prod_pvt
+ *    if cmpxchg fails, it means that someone reserved the request, start from
+ *    a)
+ * 
+ * In order to commit a request to the shared ring:
+ * a) cmpxchg shared_ring->req_prod from local req_prod_pvt to req_prod_pvt+1 
+ *    Loop if unsuccessful.
+ * NOTE: Request should be commited to the shared ring as quickly as possible,
+ *       because otherwise other threads might busy loop trying to commit next
+ *       requests. It also follows that preemption should be disabled, if
+ *       possible, for the duration of the request construction.
+ */
+
+/* Number of free requests (for use on front side only). */
+#define FS_RING_FREE_REQUESTS(_r, _req_prod_pvt)                         \
+    (RING_SIZE(_r) - (_req_prod_pvt - (_r)->rsp_cons))
+
+
+
+static RING_IDX reserve_fsif_request(struct fs_import *import)
+{
+    RING_IDX idx; 
+
+    down(&import->reqs_sem);
+    preempt_disable();
+again:    
+    /* We will attempt to reserve slot idx */
+    idx = import->ring.req_prod_pvt;
+    ASSERT (FS_RING_FREE_REQUESTS(&import->ring, idx));
+    /* Attempt to reserve */
+    if(cmpxchg(&import->ring.req_prod_pvt, idx, idx+1) != idx)
+        goto again;
+
+    return idx; 
+}
+
+static void commit_fsif_request(struct fs_import *import, RING_IDX idx)
+{
+    while(cmpxchg(&import->ring.sring->req_prod, idx, idx+1) != idx)
+    {
+        printk("Failed to commit a request: req_prod=%d, idx=%d\n",
+                import->ring.sring->req_prod, idx);
+    }
+    preempt_enable();
+
+    /* NOTE: we cannot do anything clever about rsp_event, to hold off
+     * notifications, because we don't know if we are a single request (in 
which
+     * case we have to notify always), or a part of a larger request group
+     * (when, in some cases, notification isn't required) */
+    notify_remote_via_evtchn(import->local_port);
+}
+
+
+
+static inline void add_id_to_freelist(unsigned int id,unsigned short* freelist)
+{
+    unsigned int old_id, new_id;
+
+again:    
+    old_id = freelist[0];
+    /* Note: temporal inconsistency, since freelist[0] can be changed by 
someone
+     * else, but we are a sole owner of freelist[id], it's OK. */
+    freelist[id] = old_id;
+    new_id = id;
+    if(cmpxchg(&freelist[0], old_id, new_id) != old_id)
+    {
+        printk("Cmpxchg on freelist add failed.\n");
+        goto again;
+    }
+}
+
+/* always call reserve_fsif_request(import) before this, to protect from
+ * depletion. */
+static inline unsigned short get_id_from_freelist(unsigned short* freelist)
+{
+    unsigned int old_id, new_id;
+
+again:    
+    old_id = freelist[0];
+    new_id = freelist[old_id];
+    if(cmpxchg(&freelist[0], old_id, new_id) != old_id)
+    {
+        printk("Cmpxchg on freelist remove failed.\n");
+        goto again;
+    }
+    
+    return old_id;
+}
+
+/******************************************************************************/
+/*                  END OF RING REQUEST/RESPONSES HANDLING                    
*/
+/******************************************************************************/
+
+
+
+/******************************************************************************/
+/*                         INDIVIDUAL FILE OPERATIONS                         
*/
+/******************************************************************************/
+int fs_open(struct fs_import *import, char *file)
+{
+    struct fs_request *fsr;
+    unsigned short priv_req_id;
+    RING_IDX back_req_id; 
+    struct fsif_request *req;
+    int fd;
+
+    /* Prepare request for the backend */
+    back_req_id = reserve_fsif_request(import);
+    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
+
+    /* Prepare our private request structure */
+    priv_req_id = get_id_from_freelist(import->freelist);
+    DEBUG("Request id for fs_open call is: %d\n", priv_req_id);
+    fsr = &import->requests[priv_req_id];
+    fsr->thread = current;
+    sprintf(fsr->page, "%s", file);
+
+    req = RING_GET_REQUEST(&import->ring, back_req_id);
+    req->type = REQ_FILE_OPEN;
+    req->id = priv_req_id;
+    req->u.fopen.gref = fsr->gref;
+
+    /* Set blocked flag before commiting the request, thus avoiding missed
+     * response race */
+    block(current);
+    commit_fsif_request(import, back_req_id);
+    schedule();
+    
+    /* Read the response */
+    fd = (int)fsr->shadow_rsp.ret_val;
+    DEBUG("The following FD returned: %d\n", fd);
+    add_id_to_freelist(priv_req_id, import->freelist);
+
+    return fd;
+} 
+
+int fs_close(struct fs_import *import, int fd)
+{
+    struct fs_request *fsr;
+    unsigned short priv_req_id;
+    RING_IDX back_req_id; 
+    struct fsif_request *req;
+    int ret;
+
+    /* Prepare request for the backend */
+    back_req_id = reserve_fsif_request(import);
+    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
+
+    /* Prepare our private request structure */
+    priv_req_id = get_id_from_freelist(import->freelist);
+    DEBUG("Request id for fs_close call is: %d\n", priv_req_id);
+    fsr = &import->requests[priv_req_id];
+    fsr->thread = current;
+
+    req = RING_GET_REQUEST(&import->ring, back_req_id);
+    req->type = REQ_FILE_CLOSE;
+    req->id = priv_req_id;
+    req->u.fclose.fd = fd;
+
+    /* Set blocked flag before commiting the request, thus avoiding missed
+     * response race */
+    block(current);
+    commit_fsif_request(import, back_req_id);
+    schedule();
+    
+    /* Read the response */
+    ret = (int)fsr->shadow_rsp.ret_val;
+    DEBUG("Close returned: %d\n", ret);
+    add_id_to_freelist(priv_req_id, import->freelist);
+
+    return ret;
+}
+
+ssize_t fs_read(struct fs_import *import, int fd, void *buf, 
+                ssize_t len, ssize_t offset)
+{
+    struct fs_request *fsr;
+    unsigned short priv_req_id;
+    RING_IDX back_req_id; 
+    struct fsif_request *req;
+    ssize_t ret;
+
+    BUG_ON(len > PAGE_SIZE);
+
+    /* Prepare request for the backend */
+    back_req_id = reserve_fsif_request(import);
+    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
+
+    /* Prepare our private request structure */
+    priv_req_id = get_id_from_freelist(import->freelist);
+    DEBUG("Request id for fs_read call is: %d\n", priv_req_id);
+    fsr = &import->requests[priv_req_id];
+    fsr->thread = current;
+    memset(fsr->page, 0, PAGE_SIZE);
+
+    req = RING_GET_REQUEST(&import->ring, back_req_id);
+    req->type = REQ_FILE_READ;
+    req->id = priv_req_id;
+    req->u.fread.fd = fd;
+    req->u.fread.gref = fsr->gref;
+    req->u.fread.len = len;
+    req->u.fread.offset = offset;
+
+    /* Set blocked flag before commiting the request, thus avoiding missed
+     * response race */
+    block(current);
+    commit_fsif_request(import, back_req_id);
+    schedule();
+    
+    /* Read the response */
+    ret = (ssize_t)fsr->shadow_rsp.ret_val;
+    DEBUG("The following ret value returned %d\n", ret);
+    if(ret > 0)
+        memcpy(buf, fsr->page, ret);
+    add_id_to_freelist(priv_req_id, import->freelist);
+
+    return ret;
+} 
+
+ssize_t fs_write(struct fs_import *import, int fd, void *buf, 
+                 ssize_t len, ssize_t offset)
+{
+    struct fs_request *fsr;
+    unsigned short priv_req_id;
+    RING_IDX back_req_id; 
+    struct fsif_request *req;
+    ssize_t ret;
+
+    BUG_ON(len > PAGE_SIZE);
+
+    /* Prepare request for the backend */
+    back_req_id = reserve_fsif_request(import);
+    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
+
+    /* Prepare our private request structure */
+    priv_req_id = get_id_from_freelist(import->freelist);
+    DEBUG("Request id for fs_read call is: %d\n", priv_req_id);
+    fsr = &import->requests[priv_req_id];
+    fsr->thread = current;
+    memcpy(fsr->page, buf, len);
+    BUG_ON(len > PAGE_SIZE);
+    memset((char *)fsr->page + len, 0, PAGE_SIZE - len); 
+
+    req = RING_GET_REQUEST(&import->ring, back_req_id);
+    req->type = REQ_FILE_WRITE;
+    req->id = priv_req_id;
+    req->u.fwrite.fd = fd;
+    req->u.fwrite.gref = fsr->gref;
+    req->u.fwrite.len = len;
+    req->u.fwrite.offset = offset;
+
+    /* Set blocked flag before commiting the request, thus avoiding missed
+     * response race */
+    block(current);
+    commit_fsif_request(import, back_req_id);
+    schedule();
+    
+    /* Read the response */
+    ret = (ssize_t)fsr->shadow_rsp.ret_val;
+    DEBUG("The following ret value returned %d\n", ret);
+    add_id_to_freelist(priv_req_id, import->freelist);
+
+    return ret;
+} 
+
+int fs_stat(struct fs_import *import, 
+            int fd, 
+            struct fsif_stat_response *stat)
+{
+    struct fs_request *fsr;
+    unsigned short priv_req_id;
+    RING_IDX back_req_id; 
+    struct fsif_request *req;
+    int ret;
+
+    /* Prepare request for the backend */
+    back_req_id = reserve_fsif_request(import);
+    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
+
+    /* Prepare our private request structure */
+    priv_req_id = get_id_from_freelist(import->freelist);
+    DEBUG("Request id for fs_stat call is: %d\n", priv_req_id);
+    fsr = &import->requests[priv_req_id];
+    fsr->thread = current;
+    memset(fsr->page, 0, PAGE_SIZE);
+
+    req = RING_GET_REQUEST(&import->ring, back_req_id);
+    req->type = REQ_STAT;
+    req->id = priv_req_id;
+    req->u.fstat.fd   = fd;
+    req->u.fstat.gref = fsr->gref;
+
+    /* Set blocked flag before commiting the request, thus avoiding missed
+     * response race */
+    block(current);
+    commit_fsif_request(import, back_req_id);
+    schedule();
+    
+    /* Read the response */
+    ret = (int)fsr->shadow_rsp.ret_val;
+    DEBUG("Following ret from fstat: %d\n", ret);
+    memcpy(stat, fsr->page, sizeof(struct fsif_stat_response));
+    add_id_to_freelist(priv_req_id, import->freelist);
+
+    return ret;
+} 
+
+int fs_truncate(struct fs_import *import, 
+                int fd, 
+                int64_t length)
+{
+    struct fs_request *fsr;
+    unsigned short priv_req_id;
+    RING_IDX back_req_id; 
+    struct fsif_request *req;
+    int ret;
+
+    /* Prepare request for the backend */
+    back_req_id = reserve_fsif_request(import);
+    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
+
+    /* Prepare our private request structure */
+    priv_req_id = get_id_from_freelist(import->freelist);
+    DEBUG("Request id for fs_truncate call is: %d\n", priv_req_id);
+    fsr = &import->requests[priv_req_id];
+    fsr->thread = current;
+
+    req = RING_GET_REQUEST(&import->ring, back_req_id);
+    req->type = REQ_FILE_TRUNCATE;
+    req->id = priv_req_id;
+    req->u.ftruncate.fd = fd;
+    req->u.ftruncate.length = length;
+
+    /* Set blocked flag before commiting the request, thus avoiding missed
+     * response race */
+    block(current);
+    commit_fsif_request(import, back_req_id);
+    schedule();
+    
+    /* Read the response */
+    ret = (int)fsr->shadow_rsp.ret_val;
+    DEBUG("Following ret from ftruncate: %d\n", ret);
+    add_id_to_freelist(priv_req_id, import->freelist);
+
+    return ret;
+} 
+
+int fs_remove(struct fs_import *import, char *file)
+{
+    struct fs_request *fsr;
+    unsigned short priv_req_id;
+    RING_IDX back_req_id; 
+    struct fsif_request *req;
+    int ret;
+
+    /* Prepare request for the backend */
+    back_req_id = reserve_fsif_request(import);
+    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
+
+    /* Prepare our private request structure */
+    priv_req_id = get_id_from_freelist(import->freelist);
+    DEBUG("Request id for fs_open call is: %d\n", priv_req_id);
+    fsr = &import->requests[priv_req_id];
+    fsr->thread = current;
+    sprintf(fsr->page, "%s", file);
+
+    req = RING_GET_REQUEST(&import->ring, back_req_id);
+    req->type = REQ_REMOVE;
+    req->id = priv_req_id;
+    req->u.fremove.gref = fsr->gref;
+
+    /* Set blocked flag before commiting the request, thus avoiding missed
+     * response race */
+    block(current);
+    commit_fsif_request(import, back_req_id);
+    schedule();
+    
+    /* Read the response */
+    ret = (int)fsr->shadow_rsp.ret_val;
+    DEBUG("The following ret: %d\n", ret);
+    add_id_to_freelist(priv_req_id, import->freelist);
+
+    return ret;
+}
+
+
+int fs_rename(struct fs_import *import, 
+              char *old_file_name, 
+              char *new_file_name)
+{
+    struct fs_request *fsr;
+    unsigned short priv_req_id;
+    RING_IDX back_req_id; 
+    struct fsif_request *req;
+    int ret;
+    char old_header[] = "old: ";
+    char new_header[] = "new: ";
+
+    /* Prepare request for the backend */
+    back_req_id = reserve_fsif_request(import);
+    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
+
+    /* Prepare our private request structure */
+    priv_req_id = get_id_from_freelist(import->freelist);
+    DEBUG("Request id for fs_open call is: %d\n", priv_req_id);
+    fsr = &import->requests[priv_req_id];
+    fsr->thread = current;
+    sprintf(fsr->page, "%s%s%c%s%s", 
+            old_header, old_file_name, '\0', new_header, new_file_name);
+
+    req = RING_GET_REQUEST(&import->ring, back_req_id);
+    req->type = REQ_RENAME;
+    req->id = priv_req_id;
+    req->u.frename.gref = fsr->gref;
+    req->u.frename.old_name_offset = strlen(old_header);
+    req->u.frename.new_name_offset = strlen(old_header) +
+                                     strlen(old_file_name) +
+                                     strlen(new_header) +
+                                     1 /* Accouning for the additional 
+                                          end of string character */;
+
+    /* Set blocked flag before commiting the request, thus avoiding missed
+     * response race */
+    block(current);
+    commit_fsif_request(import, back_req_id);
+    schedule();
+    
+    /* Read the response */
+    ret = (int)fsr->shadow_rsp.ret_val;
+    DEBUG("The following ret: %d\n", ret);
+    add_id_to_freelist(priv_req_id, import->freelist);
+
+    return ret;
+}
+
+int fs_create(struct fs_import *import, char *name, 
+              int8_t directory, int32_t mode)
+{
+    struct fs_request *fsr;
+    unsigned short priv_req_id;
+    RING_IDX back_req_id; 
+    struct fsif_request *req;
+    int ret;
+
+    /* Prepare request for the backend */
+    back_req_id = reserve_fsif_request(import);
+    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
+
+    /* Prepare our private request structure */
+    priv_req_id = get_id_from_freelist(import->freelist);
+    DEBUG("Request id for fs_create call is: %d\n", priv_req_id);
+    fsr = &import->requests[priv_req_id];
+    fsr->thread = current;
+    sprintf(fsr->page, "%s", name);
+
+    req = RING_GET_REQUEST(&import->ring, back_req_id);
+    req->type = REQ_CREATE;
+    req->id = priv_req_id;
+    req->u.fcreate.gref = fsr->gref;
+    req->u.fcreate.directory = directory;
+    req->u.fcreate.mode = mode;
+
+    /* Set blocked flag before commiting the request, thus avoiding missed
+     * response race */
+    block(current);
+    commit_fsif_request(import, back_req_id);
+    schedule();
+    
+    /* Read the response */
+    ret = (int)fsr->shadow_rsp.ret_val;
+    DEBUG("The following ret: %d\n", ret);
+    add_id_to_freelist(priv_req_id, import->freelist);
+
+    return ret;
+} 
+
+char** fs_list(struct fs_import *import, char *name, 
+               int32_t offset, int32_t *nr_files, int *has_more)
+{
+    struct fs_request *fsr;
+    unsigned short priv_req_id;
+    RING_IDX back_req_id; 
+    struct fsif_request *req;
+    char **files, *current_file;
+    int i;
+
+    DEBUG("Different masks: NR_FILES=(%llx, %d), ERROR=(%llx, %d), 
HAS_MORE(%llx, %d)\n",
+            NR_FILES_MASK, NR_FILES_SHIFT, ERROR_MASK, ERROR_SHIFT, 
HAS_MORE_FLAG, HAS_MORE_SHIFT);
+
+    /* Prepare request for the backend */
+    back_req_id = reserve_fsif_request(import);
+    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
+
+    /* Prepare our private request structure */
+    priv_req_id = get_id_from_freelist(import->freelist);
+    DEBUG("Request id for fs_list call is: %d\n", priv_req_id);
+    fsr = &import->requests[priv_req_id];
+    fsr->thread = current;
+    sprintf(fsr->page, "%s", name);
+
+    req = RING_GET_REQUEST(&import->ring, back_req_id);
+    req->type = REQ_DIR_LIST;
+    req->id = priv_req_id;
+    req->u.flist.gref = fsr->gref;
+    req->u.flist.offset = offset;
+
+    /* Set blocked flag before commiting the request, thus avoiding missed
+     * response race */
+    block(current);
+    commit_fsif_request(import, back_req_id);
+    schedule();
+    
+    /* Read the response */
+    *nr_files = (fsr->shadow_rsp.ret_val & NR_FILES_MASK) >> NR_FILES_SHIFT;
+    files = NULL;
+    if(*nr_files <= 0) goto exit;
+    files = malloc(sizeof(char*) * (*nr_files));
+    current_file = fsr->page;
+    for(i=0; i<*nr_files; i++)
+    {
+        files[i] = strdup(current_file); 
+        current_file += strlen(current_file) + 1;
+    }
+    if(has_more != NULL)
+        *has_more = fsr->shadow_rsp.ret_val & HAS_MORE_FLAG;
+    add_id_to_freelist(priv_req_id, import->freelist);
+exit:
+    return files;
+} 
+
+int fs_chmod(struct fs_import *import, int fd, int32_t mode)
+{
+    struct fs_request *fsr;
+    unsigned short priv_req_id;
+    RING_IDX back_req_id; 
+    struct fsif_request *req;
+    int ret;
+
+    /* Prepare request for the backend */
+    back_req_id = reserve_fsif_request(import);
+    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
+
+    /* Prepare our private request structure */
+    priv_req_id = get_id_from_freelist(import->freelist);
+    DEBUG("Request id for fs_chmod call is: %d\n", priv_req_id);
+    fsr = &import->requests[priv_req_id];
+    fsr->thread = current;
+
+    req = RING_GET_REQUEST(&import->ring, back_req_id);
+    req->type = REQ_CHMOD;
+    req->id = priv_req_id;
+    req->u.fchmod.fd = fd;
+    req->u.fchmod.mode = mode;
+
+    /* Set blocked flag before commiting the request, thus avoiding missed
+     * response race */
+    block(current);
+    commit_fsif_request(import, back_req_id);
+    schedule();
+    
+    /* Read the response */
+    ret = (int)fsr->shadow_rsp.ret_val;
+    DEBUG("The following returned: %d\n", ret);
+    add_id_to_freelist(priv_req_id, import->freelist);
+
+    return ret;
+} 
+
+int64_t fs_space(struct fs_import *import, char *location)
+{
+    struct fs_request *fsr;
+    unsigned short priv_req_id;
+    RING_IDX back_req_id; 
+    struct fsif_request *req;
+    int64_t ret;
+
+    /* Prepare request for the backend */
+    back_req_id = reserve_fsif_request(import);
+    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
+
+    /* Prepare our private request structure */
+    priv_req_id = get_id_from_freelist(import->freelist);
+    DEBUG("Request id for fs_space is: %d\n", priv_req_id);
+    fsr = &import->requests[priv_req_id];
+    fsr->thread = current;
+    sprintf(fsr->page, "%s", location);
+
+    req = RING_GET_REQUEST(&import->ring, back_req_id);
+    req->type = REQ_FS_SPACE;
+    req->id = priv_req_id;
+    req->u.fspace.gref = fsr->gref;
+
+    /* Set blocked flag before commiting the request, thus avoiding missed
+     * response race */
+    block(current);
+    commit_fsif_request(import, back_req_id);
+    schedule();
+    
+    /* Read the response */
+    ret = (int64_t)fsr->shadow_rsp.ret_val;
+    DEBUG("The following returned: %lld\n", ret);
+    add_id_to_freelist(priv_req_id, import->freelist);
+
+    return ret;
+} 
+
+int fs_sync(struct fs_import *import, int fd)
+{
+    struct fs_request *fsr;
+    unsigned short priv_req_id;
+    RING_IDX back_req_id; 
+    struct fsif_request *req;
+    int ret;
+
+    /* Prepare request for the backend */
+    back_req_id = reserve_fsif_request(import);
+    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
+
+    /* Prepare our private request structure */
+    priv_req_id = get_id_from_freelist(import->freelist);
+    DEBUG("Request id for fs_sync call is: %d\n", priv_req_id);
+    fsr = &import->requests[priv_req_id];
+    fsr->thread = current;
+
+    req = RING_GET_REQUEST(&import->ring, back_req_id);
+    req->type = REQ_FILE_SYNC;
+    req->id = priv_req_id;
+    req->u.fsync.fd = fd;
+
+    /* Set blocked flag before commiting the request, thus avoiding missed
+     * response race */
+    block(current);
+    commit_fsif_request(import, back_req_id);
+    schedule();
+    
+    /* Read the response */
+    ret = (int)fsr->shadow_rsp.ret_val;
+    DEBUG("Close returned: %d\n", ret);
+    add_id_to_freelist(priv_req_id, import->freelist);
+
+    return ret;
+}
+
+
+/******************************************************************************/
+/*                       END OF INDIVIDUAL FILE OPERATIONS                    
*/
+/******************************************************************************/
+
+
+static void fsfront_handler(evtchn_port_t port, struct pt_regs *regs, void 
*data)
+{
+    struct fs_import *import = (struct fs_import*)data;
+    static int in_irq = 0;
+    RING_IDX cons, rp;
+    int more;
+
+    /* Check for non-reentrance */
+    BUG_ON(in_irq);
+    in_irq = 1;
+
+    DEBUG("Event from import [%d:%d].\n", import->dom_id, import->export_id);
+moretodo:   
+    rp = import->ring.sring->req_prod;
+    rmb(); /* Ensure we see queued responses up to 'rp'. */
+    cons = import->ring.rsp_cons;
+    while (cons != rp)
+    {
+        struct fsif_response *rsp;
+        struct fs_request *req;
+
+        rsp = RING_GET_RESPONSE(&import->ring, cons); 
+        DEBUG("Response at idx=%d to request id=%d, ret_val=%lx\n", 
+            import->ring.rsp_cons, rsp->id, rsp->ret_val);
+        req = &import->requests[rsp->id];
+        memcpy(&req->shadow_rsp, rsp, sizeof(struct fsif_response));
+        DEBUG("Waking up: %s\n", req->thread->name);
+        wake(req->thread);
+
+        cons++;
+        up(&import->reqs_sem);
+    }
+
+    import->ring.rsp_cons = rp;
+    RING_FINAL_CHECK_FOR_RESPONSES(&import->ring, more);
+    if(more) goto moretodo;
+    
+    in_irq = 0;
+}
+
+/* Small utility function to figure out our domain id */
+static domid_t get_self_id(void)
+{
+    char *dom_id;
+    domid_t ret; 
+
+    BUG_ON(xenbus_read(XBT_NIL, "domid", &dom_id));
+    sscanf(dom_id, "%d", &ret);
+
+    return ret;
+}
+
+static void alloc_request_table(struct fs_import *import)
+{
+    struct fs_request *requests;
+    int i;
+
+    BUG_ON(import->nr_entries <= 0);
+    printk("Allocating request array for import %d, nr_entries = %d.\n",
+            import->import_id, import->nr_entries);
+    requests = xmalloc_array(struct fs_request, import->nr_entries);
+    import->freelist = xmalloc_array(unsigned short, import->nr_entries);
+    memset(import->freelist, 0, sizeof(unsigned short) * import->nr_entries);
+    for(i=0; i<import->nr_entries; i++)
+    {
+       /* TODO: that's a lot of memory */
+        requests[i].page = (void *)alloc_page(); 
+        requests[i].gref = gnttab_grant_access(import->dom_id, 
+                                               virt_to_mfn(requests[i].page),
+                                               0);
+        //printk("   ===>> Page=%lx, gref=%d, mfn=%lx\n", requests[i].page, 
requests[i].gref, virt_to_mfn(requests[i].page));
+        add_id_to_freelist(i, import->freelist);
+    }
+    import->requests = requests;
+}
+
+
+/******************************************************************************/
+/*                                FS TESTS                                    
*/
+/******************************************************************************/
+
+
+void test_fs_import(void *data)
+{
+    struct fs_import *import = (struct fs_import *)data; 
+    int ret, fd, i;
+    int32_t nr_files;
+    char buffer[1024];
+    ssize_t offset;
+    char **files;
+    long ret64;
+   
+    /* Sleep for 1s and then try to open a file */
+    sleep(1000);
+    ret = fs_create(import, "mini-os-created-directory", 1, 0777);
+    printk("Directory create: %d\n", ret);
+
+    ret = fs_create(import, "mini-os-created-directory/mini-os-created-file", 
0, 0666);
+    printk("File create: %d\n", ret);
+
+    fd = fs_open(import, "mini-os-created-directory/mini-os-created-file");
+    printk("File descriptor: %d\n", fd);
+    if(fd < 0) return;
+
+    offset = 0;
+    for(i=0; i<10; i++)
+    {
+        sprintf(buffer, "Current time is: %lld\n", NOW());
+        ret = fs_write(import, fd, buffer, strlen(buffer), offset);
+        printk("Writen current time (%d)\n", ret);
+        if(ret < 0)
+            return;
+        offset += ret;
+    }
+
+    ret = fs_close(import, fd);
+    printk("Closed fd: %d, ret=%d\n", fd, ret);
+   
+    printk("Listing files in /\n");
+    files = fs_list(import, "/", 0, &nr_files, NULL); 
+    for(i=0; i<nr_files; i++)
+        printk(" files[%d] = %s\n", i, files[i]);
+
+    ret64 = fs_space(import, "/");
+    printk("Free space: %lld (=%lld Mb)\n", ret64, (ret64 >> 20));
+    
+}
+
+#if 0
+//    char *content = (char *)alloc_page();
+    int fd, ret;
+//    int read;
+    char write_string[] = "\"test data written from minios\"";
+    struct fsif_stat_response stat;
+    char **files;
+    int32_t nr_files, i;
+    int64_t ret64;
+
+
+    fd = fs_open(import, "test-export-file");
+//    read = fs_read(import, fd, content, PAGE_SIZE, 0);
+//    printk("Read: %d bytes\n", read); 
+//    content[read] = '\0';
+//    printk("Value: %s\n", content);
+    ret = fs_write(import, fd, write_string, strlen(write_string), 0);
+    printk("Ret after write: %d\n", ret);
+    ret = fs_stat(import, fd, &stat);
+    printk("Ret after stat: %d\n", ret);
+    printk(" st_mode=%o\n", stat.stat_mode);
+    printk(" st_uid =%d\n", stat.stat_uid);
+    printk(" st_gid =%d\n", stat.stat_gid);
+    printk(" st_size=%ld\n", stat.stat_size);
+    printk(" st_atime=%ld\n", stat.stat_atime);
+    printk(" st_mtime=%ld\n", stat.stat_mtime);
+    printk(" st_ctime=%ld\n", stat.stat_ctime);
+    ret = fs_truncate(import, fd, 30);
+    printk("Ret after truncate: %d\n", ret);
+    ret = fs_remove(import, "test-to-remove/test-file");
+    printk("Ret after remove: %d\n", ret);
+    ret = fs_remove(import, "test-to-remove");
+    printk("Ret after remove: %d\n", ret);
+    ret = fs_chmod(import, fd, 0700);
+    printk("Ret after chmod: %d\n", ret);
+    ret = fs_sync(import, fd);
+    printk("Ret after sync: %d\n", ret);
+    ret = fs_close(import, fd);
+    //ret = fs_rename(import, "test-export-file", "renamed-test-export-file");
+    //printk("Ret after rename: %d\n", ret);
+    ret = fs_create(import, "created-dir", 1, 0777);
+    printk("Ret after dir create: %d\n", ret);
+    ret = fs_create(import, "created-dir/created-file", 0, 0777);
+    printk("Ret after file create: %d\n", ret);
+    files = fs_list(import, "/", 15, &nr_files, NULL); 
+    for(i=0; i<nr_files; i++)
+        printk(" files[%d] = %s\n", i, files[i]);
+    ret64 = fs_space(import, "created-dir");
+    printk("Ret after space: %lld\n", ret64);
+
+#endif
+
+
+/******************************************************************************/
+/*                            END OF FS TESTS                                 
*/
+/******************************************************************************/
+
+static int init_fs_import(struct fs_import *import)
+{    
+    char *err;
+    xenbus_transaction_t xbt;
+    char nodename[1024], r_nodename[1024], token[128], *message = NULL;
+    struct fsif_sring *sring;
+    int retry = 0;
+    domid_t self_id;
+
+    printk("Initialising FS fortend to backend dom %d\n", import->dom_id);
+    /* Allocate page for the shared ring */
+    sring = (struct fsif_sring*) alloc_page();
+    memset(sring, 0, PAGE_SIZE);
+
+    /* Init the shared ring */
+    SHARED_RING_INIT(sring);
+
+    /* Init private frontend ring */
+    FRONT_RING_INIT(&import->ring, sring, PAGE_SIZE);
+    import->nr_entries = import->ring.nr_ents;
+
+    /* Allocate table of requests */
+    alloc_request_table(import);
+    init_SEMAPHORE(&import->reqs_sem, import->nr_entries);
+
+    /* Grant access to the shared ring */
+    import->gnt_ref = gnttab_grant_access(import->dom_id, virt_to_mfn(sring), 
0);
+   
+    /* Allocate event channel */ 
+    BUG_ON(evtchn_alloc_unbound(import->dom_id, 
+                                fsfront_handler, 
+                                //ANY_CPU, 
+                                import, 
+                                &import->local_port));
+
+    
+    self_id = get_self_id(); 
+    /* Write the frontend info to a node in our Xenbus */
+    sprintf(nodename, "/local/domain/%d/device/vfs/%d", 
+                        self_id, import->import_id);
+
+again:    
+    err = xenbus_transaction_start(&xbt);
+    if (err) {
+        printk("starting transaction\n");
+    }
+    
+    err = xenbus_printf(xbt, 
+                        nodename, 
+                        "ring-ref",
+                        "%u",
+                        import->gnt_ref);
+    if (err) {
+        message = "writing ring-ref";
+        goto abort_transaction;
+    }
+
+    err = xenbus_printf(xbt, 
+                        nodename,
+                        "event-channel", 
+                        "%u", 
+                        import->local_port);
+    if (err) {
+        message = "writing event-channel";
+        goto abort_transaction;
+    }
+
+    err = xenbus_printf(xbt, nodename, "state", STATE_READY, 0xdeadbeef);
+
+    
+    err = xenbus_transaction_end(xbt, 0, &retry);
+    if (retry) {
+            goto again;
+        printk("completing transaction\n");
+    }
+
+    /* Now, when our node is prepared we write request in the exporting domain
+     * */
+    printk("Our own id is %d\n", self_id);
+    sprintf(r_nodename, 
+            "/local/domain/%d/backend/vfs/exports/requests/%d/%d/frontend", 
+            import->dom_id, self_id, import->export_id);
+    BUG_ON(xenbus_write(XBT_NIL, r_nodename, nodename));
+
+    goto done;
+
+abort_transaction:
+    xenbus_transaction_end(xbt, 1, &retry);
+
+done:
+
+#define WAIT_PERIOD 10   /* Wait period in ms */    
+#define MAX_WAIT    10   /* Max number of WAIT_PERIODs */
+    import->backend = NULL;
+    sprintf(r_nodename, "%s/backend", nodename);
+   
+    for(retry = MAX_WAIT; retry > 0; retry--)
+    { 
+        xenbus_read(XBT_NIL, r_nodename, &import->backend);
+        if(import->backend)
+        {
+            printk("Backend found at %s\n", import->backend);
+            break;
+        }
+       sleep(WAIT_PERIOD);
+    }        
+    
+    if(!import->backend)
+    {
+        printk("No backend available.\n");
+        /* TODO - cleanup datastructures/xenbus */
+        return 0;
+    }
+    sprintf(r_nodename, "%s/state", import->backend);
+    sprintf(token, "fs-front-%d", import->import_id);
+    /* The token will not be unique if multiple imports are inited */
+    xenbus_watch_path(XBT_NIL, r_nodename/*, token*/);
+    xenbus_wait_for_value(/*token,*/ r_nodename, STATE_READY);
+    printk("Backend ready.\n");
+   
+    //create_thread("fs-tester", test_fs_import, import); 
+
+    return 1;
+}
+
+static void add_export(struct list_head *exports, unsigned int domid)
+{
+    char node[1024], **exports_list = NULL, *ret_msg;
+    int j = 0;
+    static int import_id = 0;
+
+    sprintf(node, "/local/domain/%d/backend/vfs/exports", domid);
+    ret_msg = xenbus_ls(XBT_NIL, node, &exports_list);
+    if (ret_msg && strcmp(ret_msg, "ENOENT"))
+        printk("couldn't read %s: %s\n", node, ret_msg);
+    while(exports_list && exports_list[j])
+    {
+        struct fs_import *import; 
+        int export_id = -1;
+        
+        sscanf(exports_list[j], "%d", &export_id);
+        if(export_id >= 0)
+        {
+            import = xmalloc(struct fs_import);
+            import->dom_id = domid;
+            import->export_id = export_id;
+            import->import_id = import_id++;
+            INIT_LIST_HEAD(&import->list);
+            list_add(&import->list, exports);
+        }
+        free(exports_list[j]);
+        j++;
+    }
+    if(exports_list)
+        free(exports_list);
+    if(ret_msg)
+        free(ret_msg);
+}
+
+#if 0
+static struct list_head* probe_exports(void)
+{
+    struct list_head *exports;
+    char **node_list = NULL, *msg = NULL;
+    int i = 0;
+
+    exports = xmalloc(struct list_head);
+    INIT_LIST_HEAD(exports);
+    
+    msg = xenbus_ls(XBT_NIL, "/local/domain", &node_list);
+    if(msg)
+    {
+        printk("Could not list VFS exports (%s).\n", msg);
+        goto exit;
+    }
+
+    while(node_list[i])
+    {
+        add_export(exports, atoi(node_list[i]));
+        free(node_list[i]);
+        i++;
+    } 
+
+exit:    
+    if(msg)
+        free(msg);
+    if(node_list)
+        free(node_list);
+    return exports;
+}
+#endif
+
+LIST_HEAD(exports);
+
+void init_fs_frontend(void)
+{
+    struct list_head *entry;
+    struct fs_import *import = NULL;
+    printk("Initing FS fronend(s).\n");
+
+    //exports = probe_exports();
+    add_export(&exports, 0);
+    list_for_each(entry, &exports)
+    {
+        import = list_entry(entry, struct fs_import, list);
+        printk("FS export [dom=%d, id=%d] found\n", 
+                import->dom_id, import->export_id);
+        init_fs_import(import);
+    }
+
+    fs_import = import;
+
+    if (!fs_import)
+       printk("No FS import\n");
+}
diff -r 7643472d6b43 -r a868bd4236e6 extras/mini-os/include/blkfront.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/blkfront.h Fri Jan 18 13:49:48 2008 -0700
@@ -0,0 +1,26 @@
+#include <wait.h>
+#include <xen/io/blkif.h>
+#include <types.h>
+struct blkfront_dev;
+struct blkfront_aiocb
+{
+    struct blkfront_dev *aio_dev;
+    uint8_t *aio_buf;
+    size_t aio_nbytes;
+    uint64_t aio_offset;
+    void *data;
+
+    grant_ref_t gref[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+
+    void (*aio_cb)(struct blkfront_aiocb *aiocb, int ret);
+};
+struct blkfront_dev *init_blkfront(char *nodename, uint64_t *sectors, unsigned 
*sector_size, int *mode);
+int blkfront_open(struct blkfront_dev *dev);
+void blkfront_aio(struct blkfront_aiocb *aiocbp, int write);
+void blkfront_aio_read(struct blkfront_aiocb *aiocbp);
+void blkfront_aio_write(struct blkfront_aiocb *aiocbp);
+int blkfront_aio_poll(struct blkfront_dev *dev);
+void blkfront_sync(struct blkfront_dev *dev);
+void shutdown_blkfront(struct blkfront_dev *dev);
+
+extern struct wait_queue_head blkfront_queue;
diff -r 7643472d6b43 -r a868bd4236e6 extras/mini-os/include/fs.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/fs.h       Fri Jan 18 13:49:48 2008 -0700
@@ -0,0 +1,51 @@
+#ifndef __FS_H__
+#define __FS_H__
+
+#include <xen/io/fsif.h>
+#include <semaphore.h>
+
+struct fs_import 
+{
+    domid_t dom_id;                 /* dom id of the exporting domain       */ 
+    u16 export_id;                  /* export id (exporting dom specific)   */
+    u16 import_id;                  /* import id (specific to this domain)  */ 
+    struct list_head list;          /* list of all imports                  */
+    unsigned int nr_entries;        /* Number of entries in rings & request
+                                       array                                */
+    struct fsif_front_ring ring;    /* frontend ring (contains shared ring) */
+    int gnt_ref;                    /* grant reference to the shared ring   */
+    evtchn_port_t local_port;       /* local event channel port             */
+    char *backend;                  /* XenBus location of the backend       */
+    struct fs_request *requests;    /* Table of requests                    */
+    unsigned short *freelist;       /* List of free request ids             */
+    struct semaphore reqs_sem;      /* Accounts requests resource           */
+};
+
+
+void init_fs_frontend(void);
+
+int fs_open(struct fs_import *import, char *file);
+int fs_close(struct fs_import *import, int fd);
+ssize_t fs_read(struct fs_import *import, int fd, void *buf, 
+                ssize_t len, ssize_t offset);
+ssize_t fs_write(struct fs_import *import, int fd, void *buf, 
+                 ssize_t len, ssize_t offset);
+int fs_stat(struct fs_import *import, 
+            int fd, 
+            struct fsif_stat_response *stat);
+int fs_truncate(struct fs_import *import, 
+                int fd, 
+                int64_t length);
+int fs_remove(struct fs_import *import, char *file);
+int fs_rename(struct fs_import *import, 
+              char *old_file_name, 
+              char *new_file_name);
+int fs_create(struct fs_import *import, char *name, 
+              int8_t directory, int32_t mode);
+char** fs_list(struct fs_import *import, char *name, 
+               int32_t offset, int32_t *nr_files, int *has_more);
+int fs_chmod(struct fs_import *import, int fd, int32_t mode);
+int64_t fs_space(struct fs_import *import, char *location);
+int fs_sync(struct fs_import *import, int fd);
+
+#endif
diff -r 7643472d6b43 -r a868bd4236e6 extras/mini-os/include/ia64/arch_mm.h
--- a/extras/mini-os/include/ia64/arch_mm.h     Thu Jan 17 12:17:14 2008 -0700
+++ b/extras/mini-os/include/ia64/arch_mm.h     Fri Jan 18 13:49:48 2008 -0700
@@ -36,4 +36,8 @@
 #define STACK_SIZE_PAGE_ORDER   1
 #define STACK_SIZE              (PAGE_SIZE * (1 << STACK_SIZE_PAGE_ORDER))
 
+#define map_frames(f, n) map_frames_ex(f, n, 1, 0, 1, DOMID_SELF, 0, 0)
+/* TODO */
+#define map_zero(n, a) map_frames_ex(NULL, n, 0, 0, a, DOMID_SELF, 0, 0)
+
 #endif /* __ARCH_MM_H__ */
diff -r 7643472d6b43 -r a868bd4236e6 extras/mini-os/include/mm.h
--- a/extras/mini-os/include/mm.h       Thu Jan 17 12:17:14 2008 -0700
+++ b/extras/mini-os/include/mm.h       Fri Jan 18 13:49:48 2008 -0700
@@ -57,6 +57,9 @@ void arch_init_mm(unsigned long* start_p
 void arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p);
 void arch_init_p2m(unsigned long max_pfn_p);
 
-void *map_frames(unsigned long *f, unsigned long n);
+/* map f[i*stride]+i*increment for i in 0..n-1, aligned on alignment pages */
+void *map_frames_ex(unsigned long *f, unsigned long n, unsigned long stride,
+       unsigned long increment, unsigned long alignment, domid_t id,
+       int may_fail, unsigned long prot);
 
 #endif /* _MM_H_ */
diff -r 7643472d6b43 -r a868bd4236e6 extras/mini-os/include/types.h
--- a/extras/mini-os/include/types.h    Thu Jan 17 12:17:14 2008 -0700
+++ b/extras/mini-os/include/types.h    Fri Jan 18 13:49:48 2008 -0700
@@ -57,6 +57,13 @@ typedef struct { unsigned long pte; } pt
 typedef struct { unsigned long pte; } pte_t;
 #endif /* __i386__ || __x86_64__ */
 
+#if !defined(CONFIG_X86_PAE)
+#define __pte(x) ((pte_t) { (x) } )
+#else
+#define __pte(x) ({ unsigned long long _x = (x);        \
+    ((pte_t) {(unsigned long)(_x), (unsigned long)(_x>>32)}); })
+#endif
+
 typedef  u8 uint8_t;
 typedef  s8 int8_t;
 typedef u16 uint16_t;
@@ -69,4 +76,7 @@ typedef s64 int64_t;
 
 #define INT_MAX         ((int)(~0U>>1))
 #define UINT_MAX            (~0U)
+
+typedef long ssize_t;
+typedef unsigned long size_t;
 #endif /* _TYPES_H_ */
diff -r 7643472d6b43 -r a868bd4236e6 extras/mini-os/include/x86/arch_mm.h
--- a/extras/mini-os/include/x86/arch_mm.h      Thu Jan 17 12:17:14 2008 -0700
+++ b/extras/mini-os/include/x86/arch_mm.h      Fri Jan 18 13:49:48 2008 -0700
@@ -144,12 +144,14 @@ typedef unsigned long pgentry_t;
 
 #if defined(__i386__)
 #define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
+#define L1_PROT_RO (_PAGE_PRESENT|_PAGE_ACCESSED)
 #define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY |_PAGE_USER)
 #if defined(CONFIG_X86_PAE)
 #define L3_PROT (_PAGE_PRESENT)
 #endif /* CONFIG_X86_PAE */
 #elif defined(__x86_64__)
 #define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_USER)
+#define L1_PROT_RO (_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_USER)
 #define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
 #define L3_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
 #define L4_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
@@ -189,7 +191,8 @@ typedef unsigned long maddr_t;
 #endif
 
 extern unsigned long *phys_to_machine_mapping;
-extern char _text, _etext, _edata, _end;
+extern char _text, _etext, _erodata, _edata, _end;
+extern unsigned long mfn_zero;
 #define pfn_to_mfn(_pfn) (phys_to_machine_mapping[(_pfn)])
 static __inline__ maddr_t phys_to_machine(paddr_t phys)
 {
@@ -223,5 +226,7 @@ static __inline__ paddr_t machine_to_phy
 #define pte_to_mfn(_pte)           (((_pte) & (PADDR_MASK&PAGE_MASK)) >> 
L1_PAGETABLE_SHIFT)
 #define pte_to_virt(_pte)          to_virt(mfn_to_pfn(pte_to_mfn(_pte)) << 
PAGE_SHIFT)
 
+#define map_frames(f, n) map_frames_ex(f, n, 1, 0, 1, DOMID_SELF, 0, L1_PROT)
+#define map_zero(n, a) map_frames_ex(&mfn_zero, n, 0, 0, a, DOMID_SELF, 0, 
L1_PROT_RO)
 
 #endif /* _ARCH_MM_H_ */
diff -r 7643472d6b43 -r a868bd4236e6 extras/mini-os/include/x86/traps.h
--- a/extras/mini-os/include/x86/traps.h        Thu Jan 17 12:17:14 2008 -0700
+++ b/extras/mini-os/include/x86/traps.h        Fri Jan 18 13:49:48 2008 -0700
@@ -70,4 +70,8 @@ struct pt_regs {
 
 void dump_regs(struct pt_regs *regs);
 
+#define TRAP_PF_PROT   0x1
+#define TRAP_PF_WRITE  0x2
+#define TRAP_PF_USER   0x4
+
 #endif /* _TRAPS_H_ */
diff -r 7643472d6b43 -r a868bd4236e6 extras/mini-os/kernel.c
--- a/extras/mini-os/kernel.c   Thu Jan 17 12:17:14 2008 -0700
+++ b/extras/mini-os/kernel.c   Fri Jan 18 13:49:48 2008 -0700
@@ -38,6 +38,7 @@
 #include <xenbus.h>
 #include <gnttab.h>
 #include <netfront.h>
+#include <fs.h>
 #include <xen/features.h>
 #include <xen/version.h>
 
@@ -85,6 +86,11 @@ static void netfront_thread(void *p)
     init_netfront(NULL, NULL, NULL);
 }
 
+static void fs_thread(void *p)
+{
+    init_fs_frontend();
+}
+
 /* This should be overridden by the application we are linked against. */
 __attribute__((weak)) int app_main(start_info_t *si)
 {
@@ -92,6 +98,7 @@ __attribute__((weak)) int app_main(start
     create_thread("xenbus_tester", xenbus_tester, si);
     create_thread("periodic_thread", periodic_thread, si);
     create_thread("netfront", netfront_thread, si);
+    create_thread("fs-frontend", fs_thread, si);
     return 0;
 }
 
diff -r 7643472d6b43 -r a868bd4236e6 tools/examples/network-nat
--- a/tools/examples/network-nat        Thu Jan 17 12:17:14 2008 -0700
+++ b/tools/examples/network-nat        Fri Jan 18 13:49:48 2008 -0700
@@ -43,9 +43,9 @@ fi
 
 function dhcp_start()
 {
-  if ! grep -q "subnet 192.0.2.0" "$dhcpd_conf_file"
+  if ! grep -q "subnet 10.0.0.0" "$dhcpd_conf_file"
   then
-    echo >>"$dhcpd_conf_file" "subnet 192.0.2.0 netmask 255.255.255.0 {}"
+    echo >>"$dhcpd_conf_file" "subnet 10.0.0.0 netmask 255.255.0.0 {}"
   fi
 
   "$dhcpd_init_file" restart
@@ -55,7 +55,7 @@ function dhcp_stop()
 function dhcp_stop()
 {
   local tmpfile=$(mktemp)
-  grep -v "subnet 192.0.2.0" "$dhcpd_conf_file" >"$tmpfile"
+  grep -v "subnet 10.0.0.0" "$dhcpd_conf_file" >"$tmpfile"
   if diff "$tmpfile" "$dhcpd_conf_file" >&/dev/null
   then
     rm "$tmpfile"
diff -r 7643472d6b43 -r a868bd4236e6 tools/fs-back/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/fs-back/Makefile    Fri Jan 18 13:49:48 2008 -0700
@@ -0,0 +1,40 @@
+XEN_ROOT = ../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+INCLUDES += -I.. -I../lib
+
+IBIN         = fs-backend 
+INST_DIR     = /usr/sbin
+
+CFLAGS   += -Werror
+CFLAGS   += -Wno-unused
+CFLAGS   += -fno-strict-aliasing
+CFLAGS   += -I $(XEN_LIBXC)
+CFLAGS   += $(INCLUDES) -I. -I../xenstore 
+CFLAGS   += -D_GNU_SOURCE
+
+# Get gcc to generate the dependencies for us.
+CFLAGS   += -Wp,-MD,.$(@F).d
+DEPS      = .*.d
+
+LIBS      := -L. -L.. -L../lib
+LIBS      += -L$(XEN_LIBXC)
+LIBS      += -lxenctrl -lpthread -lrt 
+LIBS      += -L$(XEN_XENSTORE) -lxenstore
+
+OBJS     := fs-xenbus.o fs-ops.o
+
+all: $(IBIN)
+
+fs-backend: $(OBJS) fs-backend.c
+       $(CC) $(CFLAGS) -o fs-backend $(OBJS) $(LIBS) fs-backend.c
+
+install: all
+       $(INSTALL_PROG) $(IBIN) $(DESTDIR)$(INST_DIR)
+
+clean:
+       rm -rf *.o *~ $(DEPS) xen $(IBIN) $(LIB)
+
+.PHONY: clean install
+
+-include $(DEPS)
diff -r 7643472d6b43 -r a868bd4236e6 tools/fs-back/fs-backend.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/fs-back/fs-backend.c        Fri Jan 18 13:49:48 2008 -0700
@@ -0,0 +1,346 @@
+#undef NDEBUG
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <malloc.h>
+#include <pthread.h>
+#include <xenctrl.h>
+#include <aio.h>
+#include <sys/mman.h>
+#include <sys/select.h>
+#include <xen/io/ring.h>
+#include "fs-backend.h"
+
+struct xs_handle *xsh = NULL;
+static struct fs_export *fs_exports = NULL;
+static int export_id = 0;
+static int mount_id = 0;
+
+void dispatch_response(struct mount *mount, int priv_req_id)
+{
+    int i;
+    struct fs_op *op;
+    struct fs_request *req = &mount->requests[priv_req_id];
+
+    for(i=0;;i++)
+    {
+        op = fsops[i];
+        /* We should dispatch a response before reaching the end of the array 
*/
+        assert(op != NULL);
+        if(op->type == req->req_shadow.type)
+        {
+            printf("Found op for type=%d\n", op->type);
+            /* There needs to be a response handler */
+            assert(op->response_handler != NULL);
+            op->response_handler(mount, req);
+            break;
+        }
+    }
+
+    req->active = 0;
+    add_id_to_freelist(priv_req_id, mount->freelist);
+}
+
+static void handle_aio_events(struct mount *mount)
+{
+    int fd, ret, count, i, notify;
+    evtchn_port_t port;
+    /* AIO control block for the evtchn file destriptor */
+    struct aiocb evtchn_cb;
+    const struct aiocb * cb_list[mount->nr_entries];
+    int request_ids[mount->nr_entries];
+
+    /* Prepare the AIO control block for evtchn */ 
+    fd = xc_evtchn_fd(mount->evth); 
+    bzero(&evtchn_cb, sizeof(struct aiocb));
+    evtchn_cb.aio_fildes = fd;
+    evtchn_cb.aio_nbytes = sizeof(port);
+    evtchn_cb.aio_buf = &port;
+    assert(aio_read(&evtchn_cb) == 0);
+
+wait_again:   
+    /* Create list of active AIO requests */
+    count = 0;
+    for(i=0; i<mount->nr_entries; i++)
+        if(mount->requests[i].active)
+        {
+            cb_list[count] = &mount->requests[i].aiocb;
+            request_ids[count] = i;
+            count++;
+        }
+    /* Add the event channel at the end of the list. Event channel needs to be
+     * handled last as it exits this function. */
+    cb_list[count] = &evtchn_cb;
+    request_ids[count] = -1;
+    count++;
+
+    /* Block till an AIO requset finishes, or we get an event */ 
+    while(1) {
+       int ret = aio_suspend(cb_list, count, NULL);
+       if (!ret)
+           break;
+       assert(errno == EINTR);
+    }
+    for(i=0; i<count; i++)
+        if(aio_error(cb_list[i]) != EINPROGRESS)
+        {
+            if(request_ids[i] >= 0)
+                dispatch_response(mount, request_ids[i]);
+            else
+                goto read_event_channel;
+        }
+ 
+    RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&mount->ring, notify);
+    printf("Pushed responces and notify=%d\n", notify);
+    if(notify)
+        xc_evtchn_notify(mount->evth, mount->local_evtchn);
+    
+    goto wait_again;
+
+read_event_channel:    
+    assert(aio_return(&evtchn_cb) == sizeof(evtchn_port_t)); 
+    assert(xc_evtchn_unmask(mount->evth, mount->local_evtchn) >= 0);
+}
+
+
+void allocate_request_array(struct mount *mount)
+{
+    int i, nr_entries = mount->nr_entries;
+    struct fs_request *requests;
+    unsigned short *freelist;
+    
+    requests = malloc(sizeof(struct fs_request) *nr_entries);
+    freelist = malloc(sizeof(unsigned short) * nr_entries); 
+    memset(requests, 0, sizeof(struct fs_request) * nr_entries);
+    memset(freelist, 0, sizeof(unsigned short) * nr_entries);
+    for(i=0; i< nr_entries; i++)
+    {
+        requests[i].active = 0; 
+        add_id_to_freelist(i, freelist);
+    }
+    mount->requests = requests;
+    mount->freelist = freelist;
+}
+
+
+void* handle_mount(void *data)
+{
+    int more, notify;
+    struct mount *mount = (struct mount *)data;
+    
+    printf("Starting a thread for mount: %d\n", mount->mount_id);
+    allocate_request_array(mount);
+
+    for(;;)
+    {
+        int nr_consumed=0;
+        RING_IDX cons, rp;
+        struct fsif_request *req;
+
+        handle_aio_events(mount);
+moretodo:
+        rp = mount->ring.sring->req_prod;
+        rmb(); /* Ensure we see queued requests up to 'rp'. */
+                
+        while ((cons = mount->ring.req_cons) != rp)
+        {
+            int i;
+            struct fs_op *op;
+
+            printf("Got a request at %d\n", cons);
+            req = RING_GET_REQUEST(&mount->ring, cons);
+            printf("Request type=%d\n", req->type); 
+            for(i=0;;i++)
+            {
+                op = fsops[i];
+                if(op == NULL)
+                {
+                    /* We've reached the end of the array, no appropirate
+                     * handler found. Warn, ignore and continue. */
+                    printf("WARN: Unknown request type: %d\n", req->type);
+                    mount->ring.req_cons++; 
+                    break;
+                }
+                if(op->type == req->type)
+                {
+                    /* There needs to be a dispatch handler */
+                    assert(op->dispatch_handler != NULL);
+                    op->dispatch_handler(mount, req);
+                    break;
+                }
+             }
+
+            nr_consumed++;
+        }
+        printf("Backend consumed: %d requests\n", nr_consumed);
+        RING_FINAL_CHECK_FOR_REQUESTS(&mount->ring, more);
+        if(more) goto moretodo;
+
+        RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&mount->ring, notify);
+        printf("Pushed responces and notify=%d\n", notify);
+        if(notify)
+            xc_evtchn_notify(mount->evth, mount->local_evtchn);
+    }
+ 
+    printf("Destroying thread for mount: %d\n", mount->mount_id);
+    xc_gnttab_munmap(mount->gnth, mount->ring.sring, 1);
+    xc_gnttab_close(mount->gnth);
+    xc_evtchn_unbind(mount->evth, mount->local_evtchn);
+    xc_evtchn_close(mount->evth);
+    free(mount->frontend);
+    pthread_exit(NULL);
+}
+
+static void handle_connection(int frontend_dom_id, int export_id, char 
*frontend)
+{
+    struct mount *mount;
+    struct fs_export *export;
+    int evt_port;
+    pthread_t handling_thread;
+    struct fsif_sring *sring;
+
+    printf("Handling connection from dom=%d, for export=%d\n", 
+            frontend_dom_id, export_id);
+    /* Try to find the export on the list */
+    export = fs_exports;
+    while(export)
+    {
+        if(export->export_id == export_id)
+            break;
+        export = export->next;
+    }
+    if(!export)
+    {
+        printf("Could not find the export (the id is unknown).\n");
+        return;
+    }
+
+    mount = (struct mount*)malloc(sizeof(struct mount));
+    mount->dom_id = frontend_dom_id;
+    mount->export = export;
+    mount->mount_id = mount_id++;
+    xenbus_read_mount_request(mount, frontend);
+    printf("Frontend found at: %s (gref=%d, evtchn=%d)\n", 
+            mount->frontend, mount->gref, mount->remote_evtchn);
+    xenbus_write_backend_node(mount);
+    mount->evth = -1;
+    mount->evth = xc_evtchn_open(); 
+    assert(mount->evth != -1);
+    mount->local_evtchn = -1;
+    mount->local_evtchn = xc_evtchn_bind_interdomain(mount->evth, 
+                                                     mount->dom_id, 
+                                                     mount->remote_evtchn);
+    assert(mount->local_evtchn != -1);
+    mount->gnth = -1;
+    mount->gnth = xc_gnttab_open(); 
+    assert(mount->gnth != -1);
+    sring = xc_gnttab_map_grant_ref(mount->gnth,
+                                    mount->dom_id,
+                                    mount->gref,
+                                    PROT_READ | PROT_WRITE);
+    BACK_RING_INIT(&mount->ring, sring, PAGE_SIZE);
+    mount->nr_entries = mount->ring.nr_ents; 
+    xenbus_write_backend_ready(mount);
+
+    pthread_create(&handling_thread, NULL, &handle_mount, mount);
+}
+
+static void await_connections(void)
+{
+    int fd, ret, dom_id, export_id; 
+    fd_set fds;
+    char **watch_paths;
+    unsigned int len;
+    char d;
+
+    assert(xsh != NULL);
+    fd = xenbus_get_watch_fd(); 
+    /* Infinite watch loop */
+    do {
+       FD_ZERO(&fds);
+       FD_SET(fd, &fds);
+        ret = select(fd+1, &fds, NULL, NULL, NULL);
+        assert(ret == 1);
+        watch_paths = xs_read_watch(xsh, &len);
+        assert(len == 2);
+        assert(strcmp(watch_paths[1], "conn-watch") == 0);
+        dom_id = -1;
+        export_id = -1;
+       d = 0;
+        printf("Path changed %s\n", watch_paths[0]);
+        sscanf(watch_paths[0], WATCH_NODE"/%d/%d/fronten%c", 
+                &dom_id, &export_id, &d);
+        if((dom_id >= 0) && (export_id >= 0) && d == 'd') {
+           char *frontend = xs_read(xsh, XBT_NULL, watch_paths[0], NULL);
+           if (frontend) {
+               handle_connection(dom_id, export_id, frontend);
+               xs_rm(xsh, XBT_NULL, watch_paths[0]);
+           }
+       }
+next_select:        
+        printf("Awaiting next connection.\n");
+        /* TODO - we need to figure out what to free */
+       free(watch_paths);
+    } while (1);
+}
+
+struct fs_export* create_export(char *name, char *export_path)
+{
+    struct fs_export *curr_export, **last_export;
+
+    /* Create export structure */
+    curr_export = (struct fs_export *)malloc(sizeof(struct fs_export));
+    curr_export->name = name;
+    curr_export->export_path = export_path;
+    curr_export->export_id = export_id++;
+    /* Thread it onto the list */
+    curr_export->next = NULL;
+    last_export = &fs_exports;
+    while(*last_export)
+        last_export = &((*last_export)->next);
+    *last_export = curr_export;
+
+    return curr_export;
+}
+
+
+int main(void)
+{
+    struct fs_export *export;
+
+    /* Open the connection to XenStore first */
+    xsh = xs_domain_open();
+    assert(xsh != NULL);
+    xs_rm(xsh, XBT_NULL, ROOT_NODE);
+    /* Create watch node */
+    xenbus_create_request_node();
+    
+    /* Create & register the default export */
+    export = create_export("default", "/exports");
+    xenbus_register_export(export);
+
+    await_connections();
+    /* Close the connection to XenStore when we are finished with everything */
+    xs_daemon_close(xsh);
+#if 0
+    int xc_handle;
+    char *shared_page;
+    int prot = PROT_READ | PROT_WRITE;
+  
+    xc_handle = xc_gnttab_open();
+    printf("Main fn.\n");
+
+    shared_page = xc_gnttab_map_grant_ref(xc_handle,
+                                           7,
+                                           2047,
+                                           prot);
+    
+    shared_page[20] = '\0';
+    printf("Current content of the page = %s\n", shared_page);
+    sprintf(shared_page, "%s", "Haha dirty page now! Very bad page.");
+    xc_gnttab_munmap(xc_handle, shared_page, 1);
+    xc_gnttab_close(xc_handle);
+    unrelated next line, saved for later convinience    
+    xc_evtchn_notify(mount->evth, mount->local_evtchn);
+#endif
+}
diff -r 7643472d6b43 -r a868bd4236e6 tools/fs-back/fs-backend.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/fs-back/fs-backend.h        Fri Jan 18 13:49:48 2008 -0700
@@ -0,0 +1,86 @@
+#ifndef __LIB_FS_BACKEND__
+#define __LIB_FS_BACKEND__
+
+#include <aio.h>
+#include <xs.h>
+#include <xen/grant_table.h>
+#include <xen/event_channel.h>
+#include <xen/io/ring.h>
+#include <xen/io/fsif.h>
+
+#define ROOT_NODE           "backend/vfs"
+#define EXPORTS_SUBNODE     "exports"
+#define EXPORTS_NODE        ROOT_NODE"/"EXPORTS_SUBNODE
+#define WATCH_NODE          EXPORTS_NODE"/requests"
+
+struct fs_export
+{
+    int export_id;
+    char *export_path;
+    char *name;
+    struct fs_export *next; 
+};
+
+struct fs_request
+{
+    int active;
+    void *page;                         /* Pointer to mapped grant */
+    struct fsif_request req_shadow;
+    struct aiocb aiocb; 
+};
+
+
+struct mount
+{
+    struct fs_export *export;
+    int dom_id;
+    char *frontend;
+    int mount_id;                     /* = backend id */
+    grant_ref_t gref;
+    evtchn_port_t remote_evtchn;
+    int evth;                         /* Handle to the event channel */
+    evtchn_port_t local_evtchn;
+    int gnth;
+    struct fsif_back_ring ring;
+    int nr_entries;
+    struct fs_request *requests;
+    unsigned short *freelist;
+};
+
+
+/* Handle to XenStore driver */
+extern struct xs_handle *xsh;
+
+bool xenbus_create_request_node(void);
+int xenbus_register_export(struct fs_export *export);
+int xenbus_get_watch_fd(void);
+void xenbus_read_mount_request(struct mount *mount, char *frontend);
+void xenbus_write_backend_node(struct mount *mount);
+void xenbus_write_backend_ready(struct mount *mount);
+
+/* File operations, implemented in fs-ops.c */
+struct fs_op
+{
+    int type;       /* Type of request (from fsif.h) this handlers 
+                       are responsible for */
+    void (*dispatch_handler)(struct mount *mount, struct fsif_request *req);
+    void (*response_handler)(struct mount *mount, struct fs_request *req);
+};
+
+/* This NULL terminated array of all file requests handlers */
+extern struct fs_op *fsops[];
+
+static inline void add_id_to_freelist(unsigned int id,unsigned short* freelist)
+{
+    freelist[id] = freelist[0];
+    freelist[0]  = id;
+}
+
+static inline unsigned short get_id_from_freelist(unsigned short* freelist)
+{
+    unsigned int id = freelist[0];
+    freelist[0] = freelist[id];
+    return id;
+}
+
+#endif /* __LIB_FS_BACKEND__ */
diff -r 7643472d6b43 -r a868bd4236e6 tools/fs-back/fs-ops.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/fs-back/fs-ops.c    Fri Jan 18 13:49:48 2008 -0700
@@ -0,0 +1,658 @@
+#undef NDEBUG
+#include <stdio.h>
+#include <aio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <inttypes.h>
+#include <xenctrl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/vfs.h>
+#include <sys/mount.h>
+#include <unistd.h>
+#include "fs-backend.h"
+
+/* For debugging only */
+#include <sys/time.h>
+#include <time.h>
+
+
+#define BUFFER_SIZE 1024
+
+
+unsigned short get_request(struct mount *mount, struct fsif_request *req)
+{
+    unsigned short id = get_id_from_freelist(mount->freelist); 
+
+    printf("Private Request id: %d\n", id);
+    memcpy(&mount->requests[id].req_shadow, req, sizeof(struct fsif_request));
+    mount->requests[id].active = 1;
+
+    return id;
+}
+
+
+void dispatch_file_open(struct mount *mount, struct fsif_request *req)
+{
+    char *file_name, full_path[BUFFER_SIZE];
+    int fd;
+    struct timeval tv1, tv2;
+    RING_IDX rsp_idx;
+    fsif_response_t *rsp;
+    uint16_t req_id;
+
+    printf("Dispatching file open operation (gref=%d).\n", req->u.fopen.gref);
+    /* Read the request, and open file */
+    file_name = xc_gnttab_map_grant_ref(mount->gnth,
+                                        mount->dom_id,
+                                        req->u.fopen.gref,
+                                        PROT_READ);
+   
+    req_id = req->id;
+    printf("File open issued for %s\n", file_name); 
+    assert(BUFFER_SIZE > 
+           strlen(file_name) + strlen(mount->export->export_path) + 1); 
+    sprintf(full_path, "%s/%s", mount->export->export_path, file_name);
+    assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
+    printf("Issuing open for %s\n", full_path);
+    fd = open(full_path, O_RDWR);
+    printf("Got FD: %d\n", fd);
+    /* We can advance the request consumer index, from here on, the request
+     * should not be used (it may be overrinden by a response) */
+    mount->ring.req_cons++;
+
+
+    /* Get a response from the ring */
+    rsp_idx = mount->ring.rsp_prod_pvt++;
+    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
+    rsp->id = req_id; 
+    rsp->ret_val = (uint64_t)fd;
+}
+
+void dispatch_file_close(struct mount *mount, struct fsif_request *req)
+{
+    int ret;
+    RING_IDX rsp_idx;
+    fsif_response_t *rsp;
+    uint16_t req_id;
+
+    printf("Dispatching file close operation (fd=%d).\n", req->u.fclose.fd);
+   
+    req_id = req->id;
+    ret = close(req->u.fclose.fd);
+    printf("Got ret: %d\n", ret);
+    /* We can advance the request consumer index, from here on, the request
+     * should not be used (it may be overrinden by a response) */
+    mount->ring.req_cons++;
+
+
+    /* Get a response from the ring */
+    rsp_idx = mount->ring.rsp_prod_pvt++;
+    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
+    rsp->id = req_id; 
+    rsp->ret_val = (uint64_t)ret;
+}
+void dispatch_file_read(struct mount *mount, struct fsif_request *req)
+{
+    void *buf;
+    int fd;
+    uint16_t req_id;
+    unsigned short priv_id;
+    struct fs_request *priv_req;
+
+    /* Read the request */
+    buf = xc_gnttab_map_grant_ref(mount->gnth,
+                                  mount->dom_id,
+                                  req->u.fread.gref,
+                                  PROT_WRITE);
+   
+    req_id = req->id;
+    printf("File read issued for FD=%d (len=%"PRIu64", offest=%"PRIu64")\n", 
+            req->u.fread.fd, req->u.fread.len, req->u.fread.offset); 
+   
+    priv_id = get_request(mount, req);
+    printf("Private id is: %d\n", priv_id);
+    priv_req = &mount->requests[priv_id];
+    priv_req->page = buf;
+
+    /* Dispatch AIO read request */
+    bzero(&priv_req->aiocb, sizeof(struct aiocb));
+    priv_req->aiocb.aio_fildes = req->u.fread.fd;
+    priv_req->aiocb.aio_nbytes = req->u.fread.len;
+    priv_req->aiocb.aio_offset = req->u.fread.offset;
+    priv_req->aiocb.aio_buf = buf;
+    assert(aio_read(&priv_req->aiocb) >= 0);
+
+     
+    /* We can advance the request consumer index, from here on, the request
+     * should not be used (it may be overrinden by a response) */
+    mount->ring.req_cons++;
+}
+
+void end_file_read(struct mount *mount, struct fs_request *priv_req)
+{
+    RING_IDX rsp_idx;
+    fsif_response_t *rsp;
+    uint16_t req_id;
+
+    /* Release the grant */
+    assert(xc_gnttab_munmap(mount->gnth, priv_req->page, 1) == 0);
+
+    /* Get a response from the ring */
+    rsp_idx = mount->ring.rsp_prod_pvt++;
+    req_id = priv_req->req_shadow.id; 
+    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
+    rsp->id = req_id; 
+    rsp->ret_val = (uint64_t)aio_return(&priv_req->aiocb);
+}
+
+void dispatch_file_write(struct mount *mount, struct fsif_request *req)
+{
+    void *buf;
+    int fd;
+    uint16_t req_id;
+    unsigned short priv_id;
+    struct fs_request *priv_req;
+
+    /* Read the request */
+    buf = xc_gnttab_map_grant_ref(mount->gnth,
+                                  mount->dom_id,
+                                  req->u.fwrite.gref,
+                                  PROT_READ);
+   
+    req_id = req->id;
+    printf("File write issued for FD=%d (len=%"PRIu64", offest=%"PRIu64")\n", 
+            req->u.fwrite.fd, req->u.fwrite.len, req->u.fwrite.offset); 
+   
+    priv_id = get_request(mount, req);
+    printf("Private id is: %d\n", priv_id);
+    priv_req = &mount->requests[priv_id];
+    priv_req->page = buf;
+
+    /* Dispatch AIO write request */
+    bzero(&priv_req->aiocb, sizeof(struct aiocb));
+    priv_req->aiocb.aio_fildes = req->u.fwrite.fd;
+    priv_req->aiocb.aio_nbytes = req->u.fwrite.len;
+    priv_req->aiocb.aio_offset = req->u.fwrite.offset;
+    priv_req->aiocb.aio_buf = buf;
+    assert(aio_write(&priv_req->aiocb) >= 0);
+
+     
+    /* We can advance the request consumer index, from here on, the request
+     * should not be used (it may be overrinden by a response) */
+    mount->ring.req_cons++;
+}
+
+void end_file_write(struct mount *mount, struct fs_request *priv_req)
+{
+    RING_IDX rsp_idx;
+    fsif_response_t *rsp;
+    uint16_t req_id;
+
+    /* Release the grant */
+    assert(xc_gnttab_munmap(mount->gnth, priv_req->page, 1) == 0);
+    
+    /* Get a response from the ring */
+    rsp_idx = mount->ring.rsp_prod_pvt++;
+    req_id = priv_req->req_shadow.id; 
+    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
+    rsp->id = req_id; 
+    rsp->ret_val = (uint64_t)aio_return(&priv_req->aiocb);
+}
+
+void dispatch_stat(struct mount *mount, struct fsif_request *req)
+{
+    struct fsif_stat_response *buf;
+    struct stat stat;
+    int fd, ret;
+    uint16_t req_id;
+    RING_IDX rsp_idx;
+    fsif_response_t *rsp;
+
+    /* Read the request */
+    buf = xc_gnttab_map_grant_ref(mount->gnth,
+                                  mount->dom_id,
+                                  req->u.fstat.gref,
+                                  PROT_WRITE);
+   
+    req_id = req->id;
+    fd = req->u.fstat.fd;
+    printf("File stat issued for FD=%d\n", fd); 
+   
+    /* We can advance the request consumer index, from here on, the request
+     * should not be used (it may be overrinden by a response) */
+    mount->ring.req_cons++;
+   
+    /* Stat, and create the response */ 
+    ret = fstat(fd, &stat);
+    printf("Mode=%o, uid=%d, a_time=%ld\n",
+            stat.st_mode, stat.st_uid, stat.st_atime);
+    buf->stat_mode  = stat.st_mode;
+    buf->stat_uid   = stat.st_uid;
+    buf->stat_gid   = stat.st_gid;
+#ifdef BLKGETSIZE
+    if (S_ISBLK(stat.st_mode)) {
+       int sectors;
+       if (ioctl(fd, BLKGETSIZE, &sectors)) {
+           perror("getting device size\n");
+           buf->stat_size = 0;
+       } else
+           buf->stat_size = sectors << 9;
+    } else
+#endif
+       buf->stat_size  = stat.st_size;
+    buf->stat_atime = stat.st_atime;
+    buf->stat_mtime = stat.st_mtime;
+    buf->stat_ctime = stat.st_ctime;
+
+    /* Release the grant */
+    assert(xc_gnttab_munmap(mount->gnth, buf, 1) == 0);
+    
+    /* Get a response from the ring */
+    rsp_idx = mount->ring.rsp_prod_pvt++;
+    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
+    rsp->id = req_id; 
+    rsp->ret_val = (uint64_t)ret;
+}
+
+
+void dispatch_truncate(struct mount *mount, struct fsif_request *req)
+{
+    int fd, ret;
+    uint16_t req_id;
+    RING_IDX rsp_idx;
+    fsif_response_t *rsp;
+    int64_t length;
+
+    req_id = req->id;
+    fd = req->u.ftruncate.fd;
+    length = req->u.ftruncate.length;
+    printf("File truncate issued for FD=%d, length=%"PRId64"\n", fd, length); 
+   
+    /* We can advance the request consumer index, from here on, the request
+     * should not be used (it may be overrinden by a response) */
+    mount->ring.req_cons++;
+   
+    /* Stat, and create the response */ 
+    ret = ftruncate(fd, length);
+
+    /* Get a response from the ring */
+    rsp_idx = mount->ring.rsp_prod_pvt++;
+    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
+    rsp->id = req_id; 
+    rsp->ret_val = (uint64_t)ret;
+}
+
+void dispatch_remove(struct mount *mount, struct fsif_request *req)
+{
+    char *file_name, full_path[BUFFER_SIZE];
+    int ret;
+    RING_IDX rsp_idx;
+    fsif_response_t *rsp;
+    uint16_t req_id;
+
+    printf("Dispatching remove operation (gref=%d).\n", req->u.fremove.gref);
+    /* Read the request, and open file */
+    file_name = xc_gnttab_map_grant_ref(mount->gnth,
+                                        mount->dom_id,
+                                        req->u.fremove.gref,
+                                        PROT_READ);
+   
+    req_id = req->id;
+    printf("File remove issued for %s\n", file_name); 
+    assert(BUFFER_SIZE > 
+           strlen(file_name) + strlen(mount->export->export_path) + 1); 
+    sprintf(full_path, "%s/%s", mount->export->export_path, file_name);
+    assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
+    printf("Issuing remove for %s\n", full_path);
+    ret = remove(full_path);
+    printf("Got ret: %d\n", ret);
+    /* We can advance the request consumer index, from here on, the request
+     * should not be used (it may be overrinden by a response) */
+    mount->ring.req_cons++;
+
+
+    /* Get a response from the ring */
+    rsp_idx = mount->ring.rsp_prod_pvt++;
+    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
+    rsp->id = req_id; 
+    rsp->ret_val = (uint64_t)ret;
+}
+
+
+void dispatch_rename(struct mount *mount, struct fsif_request *req)
+{
+    char *buf, *old_file_name, *new_file_name;
+    char old_full_path[BUFFER_SIZE], new_full_path[BUFFER_SIZE];
+    int ret;
+    RING_IDX rsp_idx;
+    fsif_response_t *rsp;
+    uint16_t req_id;
+
+    printf("Dispatching rename operation (gref=%d).\n", req->u.fremove.gref);
+    /* Read the request, and open file */
+    buf = xc_gnttab_map_grant_ref(mount->gnth,
+                                  mount->dom_id,
+                                  req->u.frename.gref,
+                                  PROT_READ);
+   
+    req_id = req->id;
+    old_file_name = buf + req->u.frename.old_name_offset;
+    new_file_name = buf + req->u.frename.new_name_offset;
+    printf("File rename issued for %s -> %s (buf=%s)\n", 
+            old_file_name, new_file_name, buf); 
+    assert(BUFFER_SIZE > 
+           strlen(old_file_name) + strlen(mount->export->export_path) + 1); 
+    assert(BUFFER_SIZE > 
+           strlen(new_file_name) + strlen(mount->export->export_path) + 1); 
+    sprintf(old_full_path, "%s/%s", mount->export->export_path, old_file_name);
+    sprintf(new_full_path, "%s/%s", mount->export->export_path, new_file_name);
+    assert(xc_gnttab_munmap(mount->gnth, buf, 1) == 0);
+    printf("Issuing rename for %s -> %s\n", old_full_path, new_full_path);
+    ret = rename(old_full_path, new_full_path);
+    printf("Got ret: %d\n", ret);
+    /* We can advance the request consumer index, from here on, the request
+     * should not be used (it may be overrinden by a response) */
+    mount->ring.req_cons++;
+
+
+    /* Get a response from the ring */
+    rsp_idx = mount->ring.rsp_prod_pvt++;
+    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
+    rsp->id = req_id; 
+    rsp->ret_val = (uint64_t)ret;
+}
+
+
+void dispatch_create(struct mount *mount, struct fsif_request *req)
+{
+    char *file_name, full_path[BUFFER_SIZE];
+    int ret;
+    int8_t directory;
+    int32_t mode;
+    RING_IDX rsp_idx;
+    fsif_response_t *rsp;
+    uint16_t req_id;
+
+    printf("Dispatching file create operation (gref=%d).\n", 
req->u.fcreate.gref);
+    /* Read the request, and create file/directory */
+    mode = req->u.fcreate.mode;
+    directory = req->u.fcreate.directory;
+    file_name = xc_gnttab_map_grant_ref(mount->gnth,
+                                        mount->dom_id,
+                                        req->u.fcreate.gref,
+                                        PROT_READ);
+   
+    req_id = req->id;
+    printf("File create issued for %s\n", file_name); 
+    assert(BUFFER_SIZE > 
+           strlen(file_name) + strlen(mount->export->export_path) + 1); 
+    sprintf(full_path, "%s/%s", mount->export->export_path, file_name);
+    assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
+    /* We can advance the request consumer index, from here on, the request
+     * should not be used (it may be overrinden by a response) */
+    mount->ring.req_cons++;
+
+    if(directory)
+    {
+        printf("Issuing create for directory: %s\n", full_path);
+        ret = mkdir(full_path, mode);
+    }
+    else
+    {
+        printf("Issuing create for file: %s\n", full_path);
+        ret = creat(full_path, mode); 
+    }
+    printf("Got ret %d (errno=%d)\n", ret, errno);
+
+    /* Get a response from the ring */
+    rsp_idx = mount->ring.rsp_prod_pvt++;
+    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
+    rsp->id = req_id; 
+    rsp->ret_val = (uint64_t)ret;
+}
+
+void dispatch_list(struct mount *mount, struct fsif_request *req)
+{
+    char *file_name, *buf, full_path[BUFFER_SIZE];
+    uint32_t offset, nr_files, error_code; 
+    uint64_t ret_val;
+    RING_IDX rsp_idx;
+    fsif_response_t *rsp;
+    uint16_t req_id;
+    DIR *dir;
+    struct dirent *dirent = NULL;
+
+    printf("Dispatching list operation (gref=%d).\n", req->u.flist.gref);
+    /* Read the request, and list directory */
+    offset = req->u.flist.offset;
+    buf = file_name = xc_gnttab_map_grant_ref(mount->gnth,
+                                        mount->dom_id,
+                                        req->u.flist.gref,
+                                        PROT_READ | PROT_WRITE);
+   
+    req_id = req->id;
+    printf("Dir list issued for %s\n", file_name); 
+    assert(BUFFER_SIZE > 
+           strlen(file_name) + strlen(mount->export->export_path) + 1); 
+    sprintf(full_path, "%s/%s", mount->export->export_path, file_name);
+    /* We can advance the request consumer index, from here on, the request
+     * should not be used (it may be overrinden by a response) */
+    mount->ring.req_cons++;
+
+    ret_val = 0;
+    nr_files = 0;
+    dir = opendir(full_path);
+    if(dir == NULL)
+    {
+        error_code = errno;
+        goto error_out;
+    }
+    /* Skip offset dirs */
+    dirent = readdir(dir);
+    while(offset-- > 0 && dirent != NULL)
+        dirent = readdir(dir);
+    /* If there was any error with reading the directory, errno will be set */
+    error_code = errno;
+    /* Copy file names of the remaining non-NULL dirents into buf */
+    assert(NAME_MAX < PAGE_SIZE >> 1);
+    while(dirent != NULL && 
+            (PAGE_SIZE - ((unsigned long)buf & PAGE_MASK) > NAME_MAX))
+    {
+        int curr_length = strlen(dirent->d_name) + 1;
+        
+        memcpy(buf, dirent->d_name, curr_length);
+        buf += curr_length;
+        dirent = readdir(dir);
+        error_code = errno;
+        nr_files++;
+    }
+error_out:    
+    ret_val = ((nr_files << NR_FILES_SHIFT) & NR_FILES_MASK) | 
+              ((error_code << ERROR_SHIFT) & ERROR_MASK) | 
+              (dirent != NULL ? HAS_MORE_FLAG : 0);
+    assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
+    
+    /* Get a response from the ring */
+    rsp_idx = mount->ring.rsp_prod_pvt++;
+    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
+    rsp->id = req_id; 
+    rsp->ret_val = ret_val;
+}
+
+void dispatch_chmod(struct mount *mount, struct fsif_request *req)
+{
+    int fd, ret;
+    RING_IDX rsp_idx;
+    fsif_response_t *rsp;
+    uint16_t req_id;
+    int32_t mode;
+
+    printf("Dispatching file chmod operation (fd=%d, mode=%o).\n", 
+            req->u.fchmod.fd, req->u.fchmod.mode);
+    req_id = req->id;
+    fd = req->u.fchmod.fd;
+    mode = req->u.fchmod.mode;
+    /* We can advance the request consumer index, from here on, the request
+     * should not be used (it may be overrinden by a response) */
+    mount->ring.req_cons++;
+
+    ret = fchmod(fd, mode); 
+
+    /* Get a response from the ring */
+    rsp_idx = mount->ring.rsp_prod_pvt++;
+    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
+    rsp->id = req_id; 
+    rsp->ret_val = (uint64_t)ret;
+}
+
+void dispatch_fs_space(struct mount *mount, struct fsif_request *req)
+{
+    char *file_name, full_path[BUFFER_SIZE];
+    RING_IDX rsp_idx;
+    fsif_response_t *rsp;
+    uint16_t req_id;
+    struct statfs stat;
+    int64_t ret;
+
+    printf("Dispatching fs space operation (gref=%d).\n", req->u.fspace.gref);
+    /* Read the request, and open file */
+    file_name = xc_gnttab_map_grant_ref(mount->gnth,
+                                        mount->dom_id,
+                                        req->u.fspace.gref,
+                                        PROT_READ);
+   
+    req_id = req->id;
+    printf("Fs space issued for %s\n", file_name); 
+    assert(BUFFER_SIZE > 
+           strlen(file_name) + strlen(mount->export->export_path) + 1); 
+    sprintf(full_path, "%s/%s", mount->export->export_path, file_name);
+    assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
+    printf("Issuing fs space for %s\n", full_path);
+    ret = statfs(full_path, &stat);
+    if(ret >= 0)
+        ret = stat.f_bsize * stat.f_bfree;
+
+    /* We can advance the request consumer index, from here on, the request
+     * should not be used (it may be overrinden by a response) */
+    mount->ring.req_cons++;
+
+
+    /* Get a response from the ring */
+    rsp_idx = mount->ring.rsp_prod_pvt++;
+    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
+    rsp->id = req_id; 
+    rsp->ret_val = (uint64_t)ret;
+}
+
+void dispatch_file_sync(struct mount *mount, struct fsif_request *req)
+{
+    int fd;
+    uint16_t req_id;
+    unsigned short priv_id;
+    struct fs_request *priv_req;
+
+    req_id = req->id;
+    fd = req->u.fsync.fd;
+    printf("File sync issued for FD=%d\n", fd); 
+   
+    priv_id = get_request(mount, req);
+    printf("Private id is: %d\n", priv_id);
+    priv_req = &mount->requests[priv_id];
+
+    /* Dispatch AIO read request */
+    bzero(&priv_req->aiocb, sizeof(struct aiocb));
+    priv_req->aiocb.aio_fildes = fd;
+    assert(aio_fsync(O_SYNC, &priv_req->aiocb) >= 0);
+
+     
+    /* We can advance the request consumer index, from here on, the request
+     * should not be used (it may be overrinden by a response) */
+    mount->ring.req_cons++;
+}
+
+void end_file_sync(struct mount *mount, struct fs_request *priv_req)
+{
+    RING_IDX rsp_idx;
+    fsif_response_t *rsp;
+    uint16_t req_id;
+
+    /* Get a response from the ring */
+    rsp_idx = mount->ring.rsp_prod_pvt++;
+    req_id = priv_req->req_shadow.id; 
+    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
+    rsp->id = req_id; 
+    rsp->ret_val = (uint64_t)aio_return(&priv_req->aiocb);
+}
+
+struct fs_op fopen_op     = {.type             = REQ_FILE_OPEN,
+                             .dispatch_handler = dispatch_file_open,
+                             .response_handler = NULL};
+struct fs_op fclose_op    = {.type             = REQ_FILE_CLOSE,
+                             .dispatch_handler = dispatch_file_close,
+                             .response_handler = NULL};
+struct fs_op fread_op     = {.type             = REQ_FILE_READ,
+                             .dispatch_handler = dispatch_file_read,
+                             .response_handler = end_file_read};
+struct fs_op fwrite_op    = {.type             = REQ_FILE_WRITE,
+                             .dispatch_handler = dispatch_file_write,
+                             .response_handler = end_file_write};
+struct fs_op fstat_op     = {.type             = REQ_STAT,
+                             .dispatch_handler = dispatch_stat,
+                             .response_handler = NULL};
+struct fs_op ftruncate_op = {.type             = REQ_FILE_TRUNCATE,
+                             .dispatch_handler = dispatch_truncate,
+                             .response_handler = NULL};
+struct fs_op fremove_op   = {.type             = REQ_REMOVE,
+                             .dispatch_handler = dispatch_remove,
+                             .response_handler = NULL};
+struct fs_op frename_op   = {.type             = REQ_RENAME,
+                             .dispatch_handler = dispatch_rename,
+                             .response_handler = NULL};
+struct fs_op fcreate_op   = {.type             = REQ_CREATE,
+                             .dispatch_handler = dispatch_create,
+                             .response_handler = NULL};
+struct fs_op flist_op     = {.type             = REQ_DIR_LIST,
+                             .dispatch_handler = dispatch_list,
+                             .response_handler = NULL};
+struct fs_op fchmod_op    = {.type             = REQ_CHMOD,
+                             .dispatch_handler = dispatch_chmod,
+                             .response_handler = NULL};
+struct fs_op fspace_op    = {.type             = REQ_FS_SPACE,
+                             .dispatch_handler = dispatch_fs_space,
+                             .response_handler = NULL};
+struct fs_op fsync_op     = {.type             = REQ_FILE_SYNC,
+                             .dispatch_handler = dispatch_file_sync,
+                             .response_handler = end_file_sync};
+
+
+struct fs_op *fsops[] = {&fopen_op, 
+                         &fclose_op, 
+                         &fread_op, 
+                         &fwrite_op, 
+                         &fstat_op, 
+                         &ftruncate_op, 
+                         &fremove_op, 
+                         &frename_op, 
+                         &fcreate_op, 
+                         &flist_op, 
+                         &fchmod_op, 
+                         &fspace_op, 
+                         &fsync_op, 
+                         NULL};
diff -r 7643472d6b43 -r a868bd4236e6 tools/fs-back/fs-xenbus.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/fs-back/fs-xenbus.c Fri Jan 18 13:49:48 2008 -0700
@@ -0,0 +1,180 @@
+#undef NDEBUG
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <assert.h>
+#include <xenctrl.h>
+#include <xs.h>
+#include <xen/io/fsif.h>
+#include "fs-backend.h"
+
+
+static bool xenbus_printf(struct xs_handle *xsh,
+                          xs_transaction_t xbt,
+                          char* node,
+                          char* path,
+                          char* fmt,
+                          ...)
+{
+    char fullpath[1024];
+    char val[1024];
+    va_list args;
+    
+    va_start(args, fmt);
+    sprintf(fullpath,"%s/%s", node, path);
+    vsprintf(val, fmt, args);
+    va_end(args);
+    printf("xenbus_printf (%s) <= %s.\n", fullpath, val);    
+
+    return xs_write(xsh, xbt, fullpath, val, strlen(val));
+}
+
+bool xenbus_create_request_node(void)
+{
+    bool ret;
+    struct xs_permissions perms;
+    
+    assert(xsh != NULL);
+    xs_rm(xsh, XBT_NULL, WATCH_NODE);
+    ret = xs_mkdir(xsh, XBT_NULL, WATCH_NODE); 
+    if (!ret)
+        return false;
+
+    perms.id = 0;
+    perms.perms = XS_PERM_WRITE;
+    ret = xs_set_permissions(xsh, XBT_NULL, WATCH_NODE, &perms, 1);
+
+    return ret;
+}
+
+int xenbus_register_export(struct fs_export *export)
+{
+    xs_transaction_t xst = 0;
+    char node[1024];
+    struct xs_permissions perms;
+
+    assert(xsh != NULL);
+    if(xsh == NULL)
+    {
+        printf("Could not open connection to xenbus deamon.\n");
+        goto error_exit;
+    }
+    printf("Connection to the xenbus deamon opened successfully.\n");
+
+    /* Start transaction */
+    xst = xs_transaction_start(xsh);
+    if(xst == 0)
+    {
+        printf("Could not start a transaction.\n");
+        goto error_exit;
+    }
+    printf("XS transaction is %d\n", xst); 
+ 
+    /* Create node string */
+    sprintf(node, "%s/%d", EXPORTS_NODE, export->export_id); 
+    /* Remove old export (if exists) */ 
+    xs_rm(xsh, xst, node);
+
+    if(!xenbus_printf(xsh, xst, node, "name", "%s", export->name))
+    {
+        printf("Could not write the export node.\n");
+        goto error_exit;
+    }
+
+    /* People need to be able to read our export */
+    perms.id = 0;
+    perms.perms = XS_PERM_READ;
+    if(!xs_set_permissions(xsh, xst, EXPORTS_NODE, &perms, 1))
+    {
+        printf("Could not set permissions on the export node.\n");
+        goto error_exit;
+    }
+
+    xs_transaction_end(xsh, xst, 0);
+    return 0; 
+
+error_exit:    
+    if(xst != 0)
+        xs_transaction_end(xsh, xst, 1);
+    return -1;
+}
+
+int xenbus_get_watch_fd(void)
+{
+    int res;
+    assert(xsh != NULL);
+    res = xs_watch(xsh, WATCH_NODE, "conn-watch");
+    assert(res);
+    return xs_fileno(xsh); 
+}
+
+void xenbus_read_mount_request(struct mount *mount, char *frontend)
+{
+    char node[1024];
+    char *s;
+
+    assert(xsh != NULL);
+#if 0
+    sprintf(node, WATCH_NODE"/%d/%d/frontend", 
+                           mount->dom_id, mount->export->export_id);
+    frontend = xs_read(xsh, XBT_NULL, node, NULL);
+#endif
+    mount->frontend = frontend;
+    sprintf(node, "%s/state", frontend);
+    s = xs_read(xsh, XBT_NULL, node, NULL);
+    assert(strcmp(s, STATE_READY) == 0);
+    free(s);
+    sprintf(node, "%s/ring-ref", frontend);
+    s = xs_read(xsh, XBT_NULL, node, NULL);
+    mount->gref = atoi(s);
+    free(s);
+    sprintf(node, "%s/event-channel", frontend);
+    s = xs_read(xsh, XBT_NULL, node, NULL);
+    mount->remote_evtchn = atoi(s);
+    free(s);
+}
+
+/* Small utility function to figure out our domain id */
+static int get_self_id(void)
+{
+    char *dom_id;
+    int ret; 
+                
+    assert(xsh != NULL);
+    dom_id = xs_read(xsh, XBT_NULL, "domid", NULL);
+    sscanf(dom_id, "%d", &ret); 
+    free(dom_id);
+                        
+    return ret;                                  
+} 
+
+
+void xenbus_write_backend_node(struct mount *mount)
+{
+    char node[1024], backend_node[1024];
+    int self_id;
+
+    assert(xsh != NULL);
+    self_id = get_self_id();
+    printf("Our own dom_id=%d\n", self_id);
+    sprintf(node, "%s/backend", mount->frontend);
+    sprintf(backend_node, "/local/domain/%d/"ROOT_NODE"/%d",
+                                self_id, mount->mount_id);
+    xs_write(xsh, XBT_NULL, node, backend_node, strlen(backend_node));
+
+    sprintf(node, ROOT_NODE"/%d/state", mount->mount_id);
+    xs_write(xsh, XBT_NULL, node, STATE_INITIALISED, 
strlen(STATE_INITIALISED));
+}
+
+void xenbus_write_backend_ready(struct mount *mount)
+{
+    char node[1024];
+    int self_id;
+
+    assert(xsh != NULL);
+    self_id = get_self_id();
+    sprintf(node, ROOT_NODE"/%d/state", mount->mount_id);
+    xs_write(xsh, XBT_NULL, node, STATE_READY, strlen(STATE_READY));
+}
+
diff -r 7643472d6b43 -r a868bd4236e6 tools/ioemu/target-i386-dm/helper2.c
--- a/tools/ioemu/target-i386-dm/helper2.c      Thu Jan 17 12:17:14 2008 -0700
+++ b/tools/ioemu/target-i386-dm/helper2.c      Fri Jan 18 13:49:48 2008 -0700
@@ -476,7 +476,7 @@ void cpu_ioreq_timeoffset(CPUState *env,
 {
     char b[64];
 
-    time_offset += (ulong)req->data;
+    time_offset += (unsigned long)req->data;
 
     fprintf(logfile, "Time offset set %ld, added offset %ld\n", time_offset, 
req->data);
     sprintf(b, "%ld", time_offset);
@@ -637,6 +637,7 @@ int main_loop(void)
     int evtchn_fd = xce_handle == -1 ? -1 : xc_evtchn_fd(xce_handle);
     char qemu_file[PATH_MAX];
     fd_set fds;
+    int ret = 0;
 
     buffered_io_timer = qemu_new_timer(rt_clock, handle_buffered_io,
                                       cpu_single_env);
@@ -647,9 +648,14 @@ int main_loop(void)
 
     xenstore_record_dm_state("running");
     while (1) {
-        while (!(vm_running && suspend_requested))
+        while (!((vm_running && suspend_requested) || shutdown_requested))
             /* Wait up to 10 msec. */
             main_loop_wait(10);
+
+        if (shutdown_requested) {
+            ret = EXCP_INTERRUPT;
+            break;
+        }
 
         fprintf(logfile, "device model saving state\n");
 
@@ -676,7 +682,7 @@ int main_loop(void)
         xenstore_record_dm_state("running");
     }
 
-    return 0;
+    return ret;
 }
 
 void destroy_hvm_domain(void)
diff -r 7643472d6b43 -r a868bd4236e6 tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py    Thu Jan 17 12:17:14 2008 -0700
+++ b/tools/python/xen/xend/image.py    Fri Jan 18 13:49:48 2008 -0700
@@ -321,7 +321,7 @@ class ImageHandler:
             return
         if self.pid:
             try:
-                os.kill(self.pid, signal.SIGKILL)
+                os.kill(self.pid, signal.SIGTERM)
             except OSError, exn:
                 log.exception(exn)
             try:
diff -r 7643472d6b43 -r a868bd4236e6 tools/xentrace/xenctx.c
--- a/tools/xentrace/xenctx.c   Thu Jan 17 12:17:14 2008 -0700
+++ b/tools/xentrace/xenctx.c   Fri Jan 18 13:49:48 2008 -0700
@@ -29,6 +29,7 @@ int domid = 0;
 int domid = 0;
 int frame_ptrs = 0;
 int stack_trace = 0;
+int disp_all = 0;
 
 #if defined (__i386__)
 #if defined (__OpenBSD__)
@@ -243,12 +244,23 @@ void print_flags(uint64_t flags)
 {
     int i;
 
-    printf("flags: %08" PRIx64, flags);
+    printf("\nflags: %08" PRIx64, flags);
     for (i = 21; i >= 0; i--) {
         char *s = flag_values[i][(flags >> i) & 1];
         if (s != NULL)
             printf(" %s", s);
     }
+    printf("\n");
+}
+
+void print_special(unsigned long *regs, const char *name, unsigned int mask)
+{
+    unsigned int i;
+
+    printf("\n");
+    for (i = 0; mask; mask >>= 1, ++i)
+        if (mask & 1)
+            printf("%s%u: " FMT_SIZE_T "\n", name, i, (size_t)regs[i]);
 }
 #endif
 
@@ -257,12 +269,10 @@ void print_ctx(vcpu_guest_context_t *ctx
 {
     struct cpu_user_regs *regs = &ctx1->user_regs;
 
-    printf("eip: %08x ", regs->eip);
+    printf("cs:eip: %04x:%08x ", regs->cs, regs->eip);
     print_symbol(regs->eip);
     print_flags(regs->eflags);
-    printf("\n");
-
-    printf("esp: %08x\n", regs->esp);
+    printf("ss:esp: %04x:%08x\n", regs->ss, regs->esp);
 
     printf("eax: %08x\t", regs->eax);
     printf("ebx: %08x\t", regs->ebx);
@@ -273,47 +283,59 @@ void print_ctx(vcpu_guest_context_t *ctx
     printf("edi: %08x\t", regs->edi);
     printf("ebp: %08x\n", regs->ebp);
 
-    printf(" cs: %08x\t", regs->cs);
-    printf(" ds: %08x\t", regs->ds);
-    printf(" fs: %08x\t", regs->fs);
-    printf(" gs: %08x\n", regs->gs);
-
+    printf(" ds:     %04x\t", regs->ds);
+    printf(" es:     %04x\t", regs->es);
+    printf(" fs:     %04x\t", regs->fs);
+    printf(" gs:     %04x\n", regs->gs);
+
+    if (disp_all) {
+        print_special(ctx1->ctrlreg, "cr", 0x1d);
+        print_special(ctx1->debugreg, "dr", 0xcf);
+    }
 }
 #elif defined(__x86_64__)
 void print_ctx(vcpu_guest_context_t *ctx1)
 {
     struct cpu_user_regs *regs = &ctx1->user_regs;
 
-    printf("rip: %08lx ", regs->rip);
+    printf("rip: %016lx ", regs->rip);
     print_symbol(regs->rip);
     print_flags(regs->rflags);
-    printf("\n");
-    printf("rsp: %08lx\n", regs->rsp);
-
-    printf("rax: %08lx\t", regs->rax);
-    printf("rbx: %08lx\t", regs->rbx);
-    printf("rcx: %08lx\t", regs->rcx);
-    printf("rdx: %08lx\n", regs->rdx);
-
-    printf("rsi: %08lx\t", regs->rsi);
-    printf("rdi: %08lx\t", regs->rdi);
-    printf("rbp: %08lx\n", regs->rbp);
-
-    printf(" r8: %08lx\t", regs->r8);
-    printf(" r9: %08lx\t", regs->r9);
-    printf("r10: %08lx\t", regs->r10);
-    printf("r11: %08lx\n", regs->r11);
-
-    printf("r12: %08lx\t", regs->r12);
-    printf("r13: %08lx\t", regs->r13);
-    printf("r14: %08lx\t", regs->r14);
-    printf("r15: %08lx\n", regs->r15);
-
-    printf(" cs:     %04x\t", regs->cs);
-    printf(" ds:     %04x\t", regs->ds);
-    printf(" fs:     %04x\t", regs->fs);
-    printf(" gs:     %04x\n", regs->gs);
-
+    printf("rsp: %016lx\n", regs->rsp);
+
+    printf("rax: %016lx\t", regs->rax);
+    printf("rcx: %016lx\t", regs->rcx);
+    printf("rdx: %016lx\n", regs->rdx);
+
+    printf("rbx: %016lx\t", regs->rbx);
+    printf("rsi: %016lx\t", regs->rsi);
+    printf("rdi: %016lx\n", regs->rdi);
+
+    printf("rbp: %016lx\t", regs->rbp);
+    printf(" r8: %016lx\t", regs->r8);
+    printf(" r9: %016lx\n", regs->r9);
+
+    printf("r10: %016lx\t", regs->r10);
+    printf("r11: %016lx\t", regs->r11);
+    printf("r12: %016lx\n", regs->r12);
+
+    printf("r13: %016lx\t", regs->r13);
+    printf("r14: %016lx\t", regs->r14);
+    printf("r15: %016lx\n", regs->r15);
+
+    printf(" cs: %04x\t", regs->cs);
+    printf(" ss: %04x\t", regs->ss);
+    printf(" ds: %04x\t", regs->ds);
+    printf(" es: %04x\n", regs->es);
+
+    printf(" fs: %04x @ %016lx\n", regs->fs, ctx1->fs_base);
+    printf(" gs: %04x @ %016lx/%016lx\n", regs->gs,
+           ctx1->gs_base_kernel, ctx1->gs_base_user);
+
+    if (disp_all) {
+        print_special(ctx1->ctrlreg, "cr", 0x1d);
+        print_special(ctx1->debugreg, "dr", 0xcf);
+    }
 }
 #elif defined(__ia64__)
 
@@ -742,6 +764,8 @@ void usage(void)
 #ifdef __ia64__
     printf("  -r LIST, --regs=LIST  display more registers.\n");
     printf("  -a --all          same as --regs=tlb,cr,ar,br,bk\n");
+#else
+    printf("  -a --all          display more registers\n");
 #endif
 }
 
@@ -811,6 +835,10 @@ int main(int argc, char **argv)
             disp_bank_regs = 1;
             disp_tlb = 1;
             break;
+#else
+        case 'a':
+            disp_all = 1;
+            break;
 #endif
         case 'h':
             usage();
diff -r 7643472d6b43 -r a868bd4236e6 unmodified_drivers/linux-2.6/mkbuildtree
--- a/unmodified_drivers/linux-2.6/mkbuildtree  Thu Jan 17 12:17:14 2008 -0700
+++ b/unmodified_drivers/linux-2.6/mkbuildtree  Fri Jan 18 13:49:48 2008 -0700
@@ -8,27 +8,28 @@ else
     echo "This may be overridden on the command line (i386,x86_64,ia64)."
 fi
 
-C=$PWD
+C=$(cd $(dirname $0) && pwd)
+R=${C%/*/*}
 
 if [ -n "$XEN" -a -d "$XEN" ]; then
   XEN=$(cd $XEN && pwd)
 else
-  XEN=$C/../../xen
+  XEN=$R/xen
 fi
+echo "Xen tree: $XEN"
 
 if [ -n "$XL" -a -d "$XL" ]; then
   XL=$(cd $XL && pwd)
 else
-  XL=$C/../../linux-2.6.18-xen.hg
+  XL=$R/linux-2.6.18-xen.hg
 fi
+echo "Linux tree: $XL"
 
-for d in $(find ${XL}/drivers/xen/ -maxdepth 1 -type d | sed -e 1d); do
-    if ! echo $d | egrep -q back; then
-        lndir $d $(basename $d) > /dev/null 2>&1
-    fi
-    if ! echo $d | egrep -q ball; then
-        lndir $d $(basename $d) > /dev/null 2>&1
-    fi
+cd $C
+
+for d in $(find ${XL}/drivers/xen/ -mindepth 1 -maxdepth 1 -type d); do
+    test -d $(basename $d) || continue
+    lndir $d $(basename $d) > /dev/null 2>&1
 done
 
 ln -sf ${XL}/drivers/xen/core/gnttab.c platform-pci
@@ -44,23 +45,27 @@ ln -nsf ${XEN}/include/public include/xe
 # Need to be quite careful here: we don't want the files we link in to
 # risk overriding the native Linux ones (in particular, system.h must
 # be native and not xenolinux).
-case "$uname"
-in
-"x86_64")
-    ln -sf ${XL}/include/asm-x86_64/mach-xen/asm/hypervisor.h include/asm
-    ln -sf ${XL}/include/asm-x86_64/mach-xen/asm/hypercall.h include/asm
-    ln -sf ${XL}/include/asm-x86_64/mach-xen/asm/synch_bitops.h include/asm
-    ln -sf ${XL}/include/asm-x86_64/mach-xen/asm/maddr.h include/asm
-    ln -sf ${XL}/include/asm-x86_64/mach-xen/asm/gnttab_dma.h include/asm
-    mkdir -p include/asm-i386
-    lndir -silent ${XL}/include/asm-i386 include/asm-i386
-  ;;
-i[34567]86)
-    ln -sf ${XL}/include/asm-i386/mach-xen/asm/hypervisor.h include/asm
-    ln -sf ${XL}/include/asm-i386/mach-xen/asm/hypercall.h include/asm
-    ln -sf ${XL}/include/asm-i386/mach-xen/asm/synch_bitops.h include/asm
-    ln -sf ${XL}/include/asm-i386/mach-xen/asm/maddr.h include/asm
-    ln -sf ${XL}/include/asm-i386/mach-xen/asm/gnttab_dma.h include/asm
+case "$uname" in
+i[34567]86|x86_64)
+    if [ -d ${XL}/include/asm-x86 ]; then
+        ln -sf ${XL}/include/asm-x86/mach-xen/asm/hypervisor.h include/asm
+        ln -sf ${XL}/include/asm-x86/mach-xen/asm/hypercall*.h include/asm
+        ln -sf ${XL}/include/asm-x86/mach-xen/asm/synch_bitops*.h include/asm
+        ln -sf ${XL}/include/asm-x86/mach-xen/asm/maddr*.h include/asm
+        ln -sf ${XL}/include/asm-x86/mach-xen/asm/gnttab_dma.h include/asm
+    else
+        if [ $uname = x86_64 ]; then
+            mkdir -p include/asm-i386
+            lndir -silent ${XL}/include/asm-i386 include/asm-i386
+        else
+            uname=i386
+        fi
+        ln -sf ${XL}/include/asm-$uname/mach-xen/asm/hypervisor.h include/asm
+        ln -sf ${XL}/include/asm-$uname/mach-xen/asm/hypercall.h include/asm
+        ln -sf ${XL}/include/asm-$uname/mach-xen/asm/synch_bitops.h include/asm
+        ln -sf ${XL}/include/asm-$uname/mach-xen/asm/maddr.h include/asm
+        ln -sf ${XL}/include/asm-$uname/mach-xen/asm/gnttab_dma.h include/asm
+    fi
   ;;
 "ia64")
     ln -sf ${XL}/include/asm-ia64/hypervisor.h include/asm
diff -r 7643472d6b43 -r a868bd4236e6 xen/arch/ia64/xen/hypercall.c
--- a/xen/arch/ia64/xen/hypercall.c     Thu Jan 17 12:17:14 2008 -0700
+++ b/xen/arch/ia64/xen/hypercall.c     Fri Jan 18 13:49:48 2008 -0700
@@ -33,9 +33,6 @@
 #include <xen/event.h>
 #include <xen/perfc.h>
 #include <public/arch-ia64/debug_op.h>
-
-extern long do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg);
-extern long do_callback_op(int cmd, XEN_GUEST_HANDLE(void) arg);
 
 static IA64FAULT
 xen_hypercall (struct pt_regs *regs)
@@ -457,7 +454,7 @@ static long unregister_guest_callback(st
 /* First time to add callback to xen/ia64, so let's just stick to
  * the newer callback interface.
  */
-long do_callback_op(int cmd, XEN_GUEST_HANDLE(void) arg)
+long do_callback_op(int cmd, XEN_GUEST_HANDLE(const_void) arg)
 {
     long ret;
 
diff -r 7643472d6b43 -r a868bd4236e6 xen/arch/x86/hvm/vmx/vtd/dmar.c
--- a/xen/arch/x86/hvm/vmx/vtd/dmar.c   Thu Jan 17 12:17:14 2008 -0700
+++ b/xen/arch/x86/hvm/vmx/vtd/dmar.c   Fri Jan 18 13:49:48 2008 -0700
@@ -43,7 +43,6 @@ LIST_HEAD(acpi_drhd_units);
 LIST_HEAD(acpi_drhd_units);
 LIST_HEAD(acpi_rmrr_units);
 LIST_HEAD(acpi_atsr_units);
-LIST_HEAD(acpi_ioapic_units);
 
 u8 dmar_host_address_width;
 
@@ -66,6 +65,47 @@ static int __init acpi_register_rmrr_uni
     return 0;
 }
 
+static int acpi_ioapic_device_match(
+    struct list_head *ioapic_list, unsigned int apic_id)
+{
+    struct acpi_ioapic_unit *ioapic;
+    list_for_each_entry( ioapic, ioapic_list, list ) {
+        if (ioapic->apic_id == apic_id)
+            return 1;
+    }
+    return 0;
+}
+
+struct acpi_drhd_unit * ioapic_to_drhd(unsigned int apic_id)
+{
+    struct acpi_drhd_unit *drhd;
+    list_for_each_entry( drhd, &acpi_drhd_units, list ) {
+        if ( acpi_ioapic_device_match(&drhd->ioapic_list, apic_id) ) {
+            dprintk(XENLOG_INFO VTDPREFIX,
+                    "ioapic_to_drhd: drhd->address = %lx\n",
+                    drhd->address);
+            return drhd;
+        }
+    }
+    return NULL;
+}
+
+struct iommu * ioapic_to_iommu(unsigned int apic_id)
+{
+    struct acpi_drhd_unit *drhd;
+
+    list_for_each_entry( drhd, &acpi_drhd_units, list ) {
+        if ( acpi_ioapic_device_match(&drhd->ioapic_list, apic_id) ) {
+            dprintk(XENLOG_INFO VTDPREFIX,
+                    "ioapic_to_iommu: drhd->address = %lx\n",
+                    drhd->address);
+            return drhd->iommu;
+        }
+    }
+    dprintk(XENLOG_WARNING VTDPREFIX, "returning NULL\n");
+    return NULL;
+}
+
 static int acpi_pci_device_match(struct pci_dev *devices, int cnt,
                                  struct pci_dev *dev)
 {
@@ -111,18 +151,18 @@ struct acpi_drhd_unit * acpi_find_matche
         if ( acpi_pci_device_match(drhd->devices,
                                    drhd->devices_cnt, dev) )
         {
-            gdprintk(XENLOG_INFO VTDPREFIX, 
-                     "acpi_find_matched_drhd_unit: drhd->address = %lx\n",
-                     drhd->address);
+            dprintk(XENLOG_INFO VTDPREFIX, 
+                    "acpi_find_matched_drhd_unit: drhd->address = %lx\n",
+                    drhd->address);
             return drhd;
         }
     }
 
     if ( include_all_drhd )
     {
-        gdprintk(XENLOG_INFO VTDPREFIX, 
-                 "acpi_find_matched_drhd_unit:include_all_drhd->addr = %lx\n",
-                 include_all_drhd->address);
+        dprintk(XENLOG_INFO VTDPREFIX, 
+                "acpi_find_matched_drhd_unit:include_all_drhd->addr = %lx\n",
+                include_all_drhd->address);
         return include_all_drhd;
     }
 
@@ -160,8 +200,8 @@ struct acpi_atsr_unit * acpi_find_matche
 
     if ( all_ports_atsru )
     {
-        gdprintk(XENLOG_INFO VTDPREFIX,
-                 "acpi_find_matched_atsr_unit: all_ports_atsru\n");
+        dprintk(XENLOG_INFO VTDPREFIX,
+                "acpi_find_matched_atsr_unit: all_ports_atsru\n");
         return all_ports_atsru;;
     }
 
@@ -180,9 +220,10 @@ static int scope_device_count(void *star
     while ( start < end )
     {
         scope = start;
-        if ( scope->length < MIN_SCOPE_LEN )
-        {
-            printk(KERN_WARNING PREFIX "Invalid device scope\n");
+        if ( (scope->length < MIN_SCOPE_LEN) ||
+             (scope->dev_type >= ACPI_DEV_ENTRY_COUNT) )
+        {
+            dprintk(XENLOG_WARNING VTDPREFIX, "Invalid device scope\n");
             return -EINVAL;
         }
 
@@ -199,16 +240,16 @@ static int scope_device_count(void *star
 
         if ( scope->dev_type == ACPI_DEV_ENDPOINT )
         {
-            printk(KERN_INFO PREFIX
-                   "found endpoint: bdf = %x:%x:%x\n",
-                   bus, path->dev, path->fn);
+            dprintk(XENLOG_INFO VTDPREFIX,
+                    "found endpoint: bdf = %x:%x:%x\n",
+                    bus, path->dev, path->fn);
             count++;
         }
         else if ( scope->dev_type == ACPI_DEV_P2PBRIDGE )
         {
-            printk(KERN_INFO PREFIX
-                   "found bridge: bdf = %x:%x:%x\n",
-                   bus, path->dev, path->fn);
+            dprintk(XENLOG_INFO VTDPREFIX,
+                    "found bridge: bdf = %x:%x:%x\n",
+                    bus, path->dev, path->fn);
             sec_bus = read_pci_config_byte(
                 bus, path->dev, path->fn, PCI_SECONDARY_BUS);
             sub_bus = read_pci_config_byte(
@@ -237,16 +278,16 @@ static int scope_device_count(void *star
         }
         else if ( scope->dev_type == ACPI_DEV_IOAPIC )
         {
-            printk(KERN_INFO PREFIX
-                   "found IOAPIC: bdf = %x:%x:%x\n",
-                   bus, path->dev, path->fn);
+            dprintk(XENLOG_INFO VTDPREFIX,
+                    "found IOAPIC: bdf = %x:%x:%x\n",
+                    bus, path->dev, path->fn);
             count++;
         }
         else
         {
-            printk(KERN_INFO PREFIX
-                   "found MSI HPET: bdf = %x:%x:%x\n",
-                   bus, path->dev, path->fn);
+            dprintk(XENLOG_INFO VTDPREFIX,
+                    "found MSI HPET: bdf = %x:%x:%x\n",
+                    bus, path->dev, path->fn);
             count++;
         }
 
@@ -256,8 +297,8 @@ static int scope_device_count(void *star
     return count;
 }
 
-static int __init acpi_parse_dev_scope(void *start, void *end, int *cnt,
-                                       struct pci_dev **devices)
+static int __init acpi_parse_dev_scope(
+    void *start, void *end, void *acpi_entry, int type)
 {
     struct acpi_dev_scope *scope;
     u8 bus, sub_bus, sec_bus;
@@ -268,10 +309,33 @@ static int __init acpi_parse_dev_scope(v
     u8 dev, func;
     u32 l;
 
+    int *cnt = NULL;
+    struct pci_dev **devices = NULL;
+    struct acpi_drhd_unit *dmaru = (struct acpi_drhd_unit *) acpi_entry;
+    struct acpi_rmrr_unit *rmrru = (struct acpi_rmrr_unit *) acpi_entry;
+    struct acpi_atsr_unit *atsru = (struct acpi_atsr_unit *) acpi_entry;
+
+    switch (type) {
+        case DMAR_TYPE:
+            cnt = &(dmaru->devices_cnt);
+            devices = &(dmaru->devices);
+            break;
+        case RMRR_TYPE:
+            cnt = &(rmrru->devices_cnt);
+            devices = &(rmrru->devices);
+            break;
+        case ATSR_TYPE:
+            cnt = &(atsru->devices_cnt);
+            devices = &(atsru->devices);
+            break;
+        default:
+            dprintk(XENLOG_ERR VTDPREFIX, "invalid vt-d acpi entry type\n");
+    }
+
     *cnt = scope_device_count(start, end);
     if ( *cnt == 0 )
     {
-        printk(KERN_INFO PREFIX "acpi_parse_dev_scope: no device\n");
+        dprintk(XENLOG_INFO VTDPREFIX, "acpi_parse_dev_scope: no device\n");
         return 0;
     }
 
@@ -298,18 +362,18 @@ static int __init acpi_parse_dev_scope(v
 
         if ( scope->dev_type == ACPI_DEV_ENDPOINT )
         {
-            printk(KERN_INFO PREFIX
-                   "found endpoint: bdf = %x:%x:%x\n",
-                   bus, path->dev, path->fn);
+            dprintk(XENLOG_INFO VTDPREFIX,
+                    "found endpoint: bdf = %x:%x:%x\n",
+                    bus, path->dev, path->fn);
             pdev->bus = bus;
             pdev->devfn = PCI_DEVFN(path->dev, path->fn);
             pdev++;
         }
         else if ( scope->dev_type == ACPI_DEV_P2PBRIDGE )
         {
-            printk(KERN_INFO PREFIX
-                   "found bridge: bus = %x dev = %x func = %x\n",
-                   bus, path->dev, path->fn);
+            dprintk(XENLOG_INFO VTDPREFIX,
+                    "found bridge: bus = %x dev = %x func = %x\n",
+                    bus, path->dev, path->fn);
             sec_bus = read_pci_config_byte(
                 bus, path->dev, path->fn, PCI_SECONDARY_BUS);
             sub_bus = read_pci_config_byte(
@@ -348,16 +412,15 @@ static int __init acpi_parse_dev_scope(v
             acpi_ioapic_unit->ioapic.bdf.bus = bus;
             acpi_ioapic_unit->ioapic.bdf.dev = path->dev;
             acpi_ioapic_unit->ioapic.bdf.func = path->fn;
-            list_add(&acpi_ioapic_unit->list, &acpi_ioapic_units);
-            printk(KERN_INFO PREFIX
-                   "found IOAPIC: bus = %x dev = %x func = %x\n",
-                   bus, path->dev, path->fn);
+            list_add(&acpi_ioapic_unit->list, &dmaru->ioapic_list);
+            dprintk(XENLOG_INFO VTDPREFIX,
+                    "found IOAPIC: bus = %x dev = %x func = %x\n",
+                    bus, path->dev, path->fn);
         }
         else
-            printk(KERN_INFO PREFIX
-                   "found MSI HPET: bus = %x dev = %x func = %x\n",
-                   bus, path->dev, path->fn);
-        
+            dprintk(XENLOG_INFO VTDPREFIX,
+                    "found MSI HPET: bus = %x dev = %x func = %x\n",
+                    bus, path->dev, path->fn);
         start += scope->length;
     }
 
@@ -371,6 +434,7 @@ acpi_parse_one_drhd(struct acpi_dmar_ent
     struct acpi_drhd_unit *dmaru;
     int ret = 0;
     static int include_all;
+    void *dev_scope_start, *dev_scope_end;
 
     dmaru = xmalloc(struct acpi_drhd_unit);
     if ( !dmaru )
@@ -379,21 +443,22 @@ acpi_parse_one_drhd(struct acpi_dmar_ent
 
     dmaru->address = drhd->address;
     dmaru->include_all = drhd->flags & 1; /* BIT0: INCLUDE_ALL */
-    printk(KERN_INFO PREFIX "dmaru->address = %lx\n", dmaru->address);
-
-    if ( !dmaru->include_all )
-        ret = acpi_parse_dev_scope(
-            (void *)(drhd + 1),
-            ((void *)drhd) + header->length,
-            &dmaru->devices_cnt, &dmaru->devices);
-    else
-    {
-        printk(KERN_INFO PREFIX "found INCLUDE_ALL\n");
+    INIT_LIST_HEAD(&dmaru->ioapic_list);
+    dprintk(XENLOG_INFO VTDPREFIX, "dmaru->address = %lx\n", dmaru->address);
+
+    dev_scope_start = (void *)(drhd + 1);
+    dev_scope_end   = ((void *)drhd) + header->length;
+    ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
+                               dmaru, DMAR_TYPE);
+
+    if ( dmaru->include_all )
+    {
+        dprintk(XENLOG_INFO VTDPREFIX, "found INCLUDE_ALL\n");
         /* Only allow one INCLUDE_ALL */
         if ( include_all )
         {
-            printk(KERN_WARNING PREFIX "Only one INCLUDE_ALL "
-                   "device scope is allowed\n");
+            dprintk(XENLOG_WARNING VTDPREFIX,
+                    "Only one INCLUDE_ALL device scope is allowed\n");
             ret = -EINVAL;
         }
         include_all = 1;
@@ -411,6 +476,7 @@ acpi_parse_one_rmrr(struct acpi_dmar_ent
 {
     struct acpi_table_rmrr *rmrr = (struct acpi_table_rmrr *)header;
     struct acpi_rmrr_unit *rmrru;
+    void *dev_scope_start, *dev_scope_end;
     int ret = 0;
 
     rmrru = xmalloc(struct acpi_rmrr_unit);
@@ -420,15 +486,10 @@ acpi_parse_one_rmrr(struct acpi_dmar_ent
 
     rmrru->base_address = rmrr->base_address;
     rmrru->end_address = rmrr->end_address;
-    printk(KERN_INFO PREFIX
-           "acpi_parse_one_rmrr: base=%"PRIx64" end=%"PRIx64"\n",
-           rmrr->base_address, rmrr->end_address);
-
-    ret = acpi_parse_dev_scope(
-        (void *)(rmrr + 1),
-        ((void*)rmrr) + header->length,
-        &rmrru->devices_cnt, &rmrru->devices);
-
+    dev_scope_start = (void *)(rmrr + 1);
+    dev_scope_end   = ((void *)rmrr) + header->length;
+    ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
+                               rmrru, RMRR_TYPE);
     if ( ret || (rmrru->devices_cnt == 0) )
         xfree(rmrru);
     else
@@ -443,6 +504,7 @@ acpi_parse_one_atsr(struct acpi_dmar_ent
     struct acpi_atsr_unit *atsru;
     int ret = 0;
     static int all_ports;
+    void *dev_scope_start, *dev_scope_end;
 
     atsru = xmalloc(struct acpi_atsr_unit);
     if ( !atsru )
@@ -451,18 +513,19 @@ acpi_parse_one_atsr(struct acpi_dmar_ent
 
     atsru->all_ports = atsr->flags & 1; /* BIT0: ALL_PORTS */
     if ( !atsru->all_ports )
-        ret = acpi_parse_dev_scope(
-            (void *)(atsr + 1),
-            ((void *)atsr) + header->length,
-            &atsru->devices_cnt, &atsru->devices);
-    else
-    {
-        printk(KERN_INFO PREFIX "found ALL_PORTS\n");
+    {
+        dev_scope_start = (void *)(atsr + 1);
+        dev_scope_end   = ((void *)atsr) + header->length;
+        ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
+                                   atsru, ATSR_TYPE);
+    }
+    else {
+        dprintk(XENLOG_INFO VTDPREFIX, "found ALL_PORTS\n");
         /* Only allow one ALL_PORTS */
         if ( all_ports )
         {
-            printk(KERN_WARNING PREFIX "Only one ALL_PORTS "
-                   "device scope is allowed\n");
+            dprintk(XENLOG_WARNING VTDPREFIX,
+                    "Only one ALL_PORTS device scope is allowed\n");
             ret = -EINVAL;
         }
         all_ports = 1;
@@ -488,19 +551,19 @@ static int __init acpi_parse_dmar(unsign
     dmar = (struct acpi_table_dmar *)__acpi_map_table(phys_addr, size);
     if ( !dmar )
     {
-        printk(KERN_WARNING PREFIX "Unable to map DMAR\n");
+        dprintk(XENLOG_WARNING VTDPREFIX, "Unable to map DMAR\n");
         return -ENODEV;
     }
 
     if ( !dmar->haw )
     {
-        printk(KERN_WARNING PREFIX "Zero: Invalid DMAR haw\n");
+        dprintk(XENLOG_WARNING VTDPREFIX, "Zero: Invalid DMAR haw\n");
         return -EINVAL;
     }
 
     dmar_host_address_width = dmar->haw;
-    printk(KERN_INFO PREFIX "Host address width %d\n",
-           dmar_host_address_width);
+    dprintk(XENLOG_INFO VTDPREFIX, "Host address width %d\n",
+            dmar_host_address_width);
 
     entry_header = (struct acpi_dmar_entry_header *)(dmar + 1);
     while ( ((unsigned long)entry_header) <
@@ -509,19 +572,19 @@ static int __init acpi_parse_dmar(unsign
         switch ( entry_header->type )
         {
         case ACPI_DMAR_DRHD:
-            printk(KERN_INFO PREFIX "found ACPI_DMAR_DRHD\n");
+            dprintk(XENLOG_INFO VTDPREFIX, "found ACPI_DMAR_DRHD\n");
             ret = acpi_parse_one_drhd(entry_header);
             break;
         case ACPI_DMAR_RMRR:
-            printk(KERN_INFO PREFIX "found ACPI_DMAR_RMRR\n");
+            dprintk(XENLOG_INFO VTDPREFIX, "found ACPI_DMAR_RMRR\n");
             ret = acpi_parse_one_rmrr(entry_header);
             break;
         case ACPI_DMAR_ATSR:
-            printk(KERN_INFO PREFIX "found ACPI_DMAR_ATSR\n");
+            dprintk(XENLOG_INFO VTDPREFIX, "found ACPI_DMAR_ATSR\n");
             ret = acpi_parse_one_atsr(entry_header);
             break;
         default:
-            printk(KERN_WARNING PREFIX "Unknown DMAR structure type\n");
+            dprintk(XENLOG_WARNING VTDPREFIX, "Unknown DMAR structure type\n");
             ret = -EINVAL;
             break;
         }
@@ -551,7 +614,7 @@ int acpi_dmar_init(void)
 
     if ( list_empty(&acpi_drhd_units) )
     {
-        printk(KERN_ERR PREFIX "No DMAR devices found\n");
+        dprintk(XENLOG_ERR VTDPREFIX, "No DMAR devices found\n");
         vtd_enabled = 0;
         return -ENODEV;
     }
diff -r 7643472d6b43 -r a868bd4236e6 xen/arch/x86/hvm/vmx/vtd/dmar.h
--- a/xen/arch/x86/hvm/vmx/vtd/dmar.h   Thu Jan 17 12:17:14 2008 -0700
+++ b/xen/arch/x86/hvm/vmx/vtd/dmar.h   Fri Jan 18 13:49:48 2008 -0700
@@ -26,6 +26,20 @@
 
 extern u8 dmar_host_address_width;
 
+/* This one is for interrupt remapping */
+struct acpi_ioapic_unit {
+    struct list_head list;
+    int apic_id;
+    union {
+        u16 info;
+        struct {
+            u16 func: 3,
+                dev:  5,
+                bus:  8;
+        }bdf;
+    }ioapic;
+};
+
 struct acpi_drhd_unit {
     struct list_head list;
     unsigned long    address; /* register base address of the unit */
@@ -33,6 +47,7 @@ struct acpi_drhd_unit {
     int    devices_cnt;
     u8    include_all:1;
     struct iommu *iommu;
+    struct list_head ioapic_list;
 };
 
 struct acpi_rmrr_unit {
@@ -73,19 +88,9 @@ struct acpi_drhd_unit * acpi_find_matche
 struct acpi_drhd_unit * acpi_find_matched_drhd_unit(struct pci_dev *dev);
 struct acpi_rmrr_unit * acpi_find_matched_rmrr_unit(struct pci_dev *dev);
 
-/* This one is for interrupt remapping */
-struct acpi_ioapic_unit {
-    struct list_head list;
-    int apic_id;
-    union {
-        u16 info;
-        struct {
-            u16 bus: 8,
-                dev: 5,
-                func: 3;
-        }bdf;
-    }ioapic;
-};
+#define DMAR_TYPE 1
+#define RMRR_TYPE 2
+#define ATSR_TYPE 3
 
 #define DMAR_OPERATION_TIMEOUT (HZ*60) /* 1m */
 #define time_after(a,b)         \
diff -r 7643472d6b43 -r a868bd4236e6 xen/arch/x86/hvm/vmx/vtd/utils.c
--- a/xen/arch/x86/hvm/vmx/vtd/utils.c  Thu Jan 17 12:17:14 2008 -0700
+++ b/xen/arch/x86/hvm/vmx/vtd/utils.c  Fri Jan 18 13:49:48 2008 -0700
@@ -146,12 +146,14 @@ u32 get_level_index(unsigned long gmfn, 
     return gmfn & LEVEL_MASK;
 }
 
-void print_vtd_entries(struct domain *d, int bus, int devfn,
-                       unsigned long gmfn)
+void print_vtd_entries(
+    struct domain *d, 
+    struct iommu *iommu,
+    int bus, int devfn,
+    unsigned long gmfn)
 {
     struct hvm_iommu *hd = domain_hvm_iommu(d);
     struct acpi_drhd_unit *drhd;
-    struct iommu *iommu;
     struct context_entry *ctxt_entry;
     struct root_entry *root_entry;
     struct dma_pte pte;
@@ -175,7 +177,6 @@ void print_vtd_entries(struct domain *d,
     {
         printk("---- print_vtd_entries %d ----\n", i++);
 
-        iommu = drhd->iommu;
         root_entry = iommu->root_entry;
         if ( root_entry == NULL )
         {
diff -r 7643472d6b43 -r a868bd4236e6 xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c      Thu Jan 17 12:17:14 2008 -0700
+++ b/xen/arch/x86/traps.c      Fri Jan 18 13:49:48 2008 -0700
@@ -2825,7 +2825,7 @@ long unregister_guest_nmi_callback(void)
     return 0;
 }
 
-long do_set_trap_table(XEN_GUEST_HANDLE(trap_info_t) traps)
+long do_set_trap_table(XEN_GUEST_HANDLE(const_trap_info_t) traps)
 {
     struct trap_info cur;
     struct vcpu *curr = current;
diff -r 7643472d6b43 -r a868bd4236e6 xen/arch/x86/x86_32/traps.c
--- a/xen/arch/x86/x86_32/traps.c       Thu Jan 17 12:17:14 2008 -0700
+++ b/xen/arch/x86/x86_32/traps.c       Fri Jan 18 13:49:48 2008 -0700
@@ -419,7 +419,7 @@ static long unregister_guest_callback(st
 }
 
 
-long do_callback_op(int cmd, XEN_GUEST_HANDLE(void) arg)
+long do_callback_op(int cmd, XEN_GUEST_HANDLE(const_void) arg)
 {
     long ret;
 
diff -r 7643472d6b43 -r a868bd4236e6 xen/arch/x86/x86_64/traps.c
--- a/xen/arch/x86/x86_64/traps.c       Thu Jan 17 12:17:14 2008 -0700
+++ b/xen/arch/x86/x86_64/traps.c       Fri Jan 18 13:49:48 2008 -0700
@@ -470,7 +470,7 @@ static long unregister_guest_callback(st
 }
 
 
-long do_callback_op(int cmd, XEN_GUEST_HANDLE(void) arg)
+long do_callback_op(int cmd, XEN_GUEST_HANDLE(const_void) arg)
 {
     long ret;
 
diff -r 7643472d6b43 -r a868bd4236e6 xen/include/asm-x86/hvm/vmx/intel-iommu.h
--- a/xen/include/asm-x86/hvm/vmx/intel-iommu.h Thu Jan 17 12:17:14 2008 -0700
+++ b/xen/include/asm-x86/hvm/vmx/intel-iommu.h Fri Jan 18 13:49:48 2008 -0700
@@ -127,32 +127,34 @@
 #define DMA_TLB_IVA_HINT(x) ((((u64)x) & 1) << 6)
 
 /* GCMD_REG */
-#define DMA_GCMD_TE (((u64)1) << 31)
-#define DMA_GCMD_SRTP (((u64)1) << 30)
-#define DMA_GCMD_SFL (((u64)1) << 29)
-#define DMA_GCMD_EAFL (((u64)1) << 28)
-#define DMA_GCMD_WBF (((u64)1) << 27)
-#define DMA_GCMD_QIE (((u64)1) << 26)
-#define DMA_GCMD_IRE (((u64)1) << 25)
-#define DMA_GCMD_SIRTP (((u64)1) << 24)
+#define DMA_GCMD_TE     (((u64)1) << 31)
+#define DMA_GCMD_SRTP   (((u64)1) << 30)
+#define DMA_GCMD_SFL    (((u64)1) << 29)
+#define DMA_GCMD_EAFL   (((u64)1) << 28)
+#define DMA_GCMD_WBF    (((u64)1) << 27)
+#define DMA_GCMD_QIE    (((u64)1) << 26)
+#define DMA_GCMD_IRE    (((u64)1) << 25)
+#define DMA_GCMD_SIRTP  (((u64)1) << 24)
+#define DMA_GCMD_CFI    (((u64)1) << 23)
 
 /* GSTS_REG */
-#define DMA_GSTS_TES (((u64)1) << 31)
-#define DMA_GSTS_RTPS (((u64)1) << 30)
-#define DMA_GSTS_FLS (((u64)1) << 29)
-#define DMA_GSTS_AFLS (((u64)1) << 28)
-#define DMA_GSTS_WBFS (((u64)1) << 27)
-#define DMA_GSTS_IRTPS (((u64)1) << 24)
+#define DMA_GSTS_TES    (((u64)1) << 31)
+#define DMA_GSTS_RTPS   (((u64)1) << 30)
+#define DMA_GSTS_FLS    (((u64)1) << 29)
+#define DMA_GSTS_AFLS   (((u64)1) << 28)
+#define DMA_GSTS_WBFS   (((u64)1) << 27)
 #define DMA_GSTS_QIES   (((u64)1) <<26)
 #define DMA_GSTS_IRES   (((u64)1) <<25)
+#define DMA_GSTS_SIRTPS (((u64)1) << 24)
+#define DMA_GSTS_CFIS   (((u64)1) <<23)
 
 /* PMEN_REG */
-#define DMA_PMEN_EPM   (((u32)1) << 31)
-#define DMA_PMEN_PRS   (((u32)1) << 0)
+#define DMA_PMEN_EPM    (((u32)1) << 31)
+#define DMA_PMEN_PRS    (((u32)1) << 0)
 
 /* CCMD_REG */
 #define DMA_CCMD_INVL_GRANU_OFFSET  61
-#define DMA_CCMD_ICC (((u64)1) << 63)
+#define DMA_CCMD_ICC   (((u64)1) << 63)
 #define DMA_CCMD_GLOBAL_INVL (((u64)1) << 61)
 #define DMA_CCMD_DOMAIN_INVL (((u64)2) << 61)
 #define DMA_CCMD_DEVICE_INVL (((u64)3) << 61)
@@ -171,8 +173,14 @@
 #define DMA_FECTL_IM (((u64)1) << 31)
 
 /* FSTS_REG */
-#define DMA_FSTS_PPF ((u64)2)
-#define DMA_FSTS_PFO ((u64)1)
+#define DMA_FSTS_PFO ((u64)1 << 0)
+#define DMA_FSTS_PPF ((u64)1 << 1)
+#define DMA_FSTS_AFO ((u64)1 << 2)
+#define DMA_FSTS_APF ((u64)1 << 3)
+#define DMA_FSTS_IQE ((u64)1 << 4)
+#define DMA_FSTS_ICE ((u64)1 << 5)
+#define DMA_FSTS_ITE ((u64)1 << 6)
+#define DMA_FSTS_FAULTS    DMA_FSTS_PFO | DMA_FSTS_PPF | DMA_FSTS_AFO | 
DMA_FSTS_APF | DMA_FSTS_IQE | DMA_FSTS_ICE | DMA_FSTS_ITE
 #define dma_fsts_fault_record_index(s) (((s) >> 8) & 0xff)
 
 /* FRCD_REG, 32 bits access */
@@ -266,8 +274,10 @@ struct dma_pte {
 
 /* interrupt remap entry */
 struct iremap_entry {
+  union {
+    u64 lo_val;
     struct {
-        u64 present : 1,
+        u64 p       : 1,
             fpd     : 1,
             dm      : 1,
             rh      : 1,
@@ -279,12 +289,16 @@ struct iremap_entry {
             res_2   : 8,
             dst     : 32;
     }lo;
+  };
+  union {
+    u64 hi_val;
     struct {
         u64 sid     : 16,
             sq      : 2,
             svt     : 2,
             res_1   : 44;
     }hi;
+  };
 };
 #define IREMAP_ENTRY_NR (PAGE_SIZE_4K/sizeof(struct iremap_entry))
 #define iremap_present(v) ((v).lo & 1)
@@ -386,11 +400,11 @@ struct poll_info {
 
 #define RESERVED_VAL        0
 
-#define TYPE_INVAL_CONTEXT  1
-#define TYPE_INVAL_IOTLB    2
-#define TYPE_INVAL_DEVICE_IOTLB 3
-#define TYPE_INVAL_IEC          4
-#define TYPE_INVAL_WAIT         5
+#define TYPE_INVAL_CONTEXT      0x1
+#define TYPE_INVAL_IOTLB        0x2
+#define TYPE_INVAL_DEVICE_IOTLB 0x3
+#define TYPE_INVAL_IEC          0x4
+#define TYPE_INVAL_WAIT         0x5
 
 #define NOTIFY_TYPE_POLL        1
 #define NOTIFY_TYPE_INTR        1
@@ -400,6 +414,10 @@ struct poll_info {
 
 #define IEC_GLOBAL_INVL         0
 #define IEC_INDEX_INVL          1
+#define IRTA_REG_EIME_SHIFT     11
+#define IRTA_REG_TABLE_SIZE     7    // 4k page = 256 * 16 byte entries
+                                     // 2^^(IRTA_REG_TABLE_SIZE + 1) = 256
+                                     // IRTA_REG_TABLE_SIZE = 7
 
 #define VTD_PAGE_TABLE_LEVEL_3  3
 #define VTD_PAGE_TABLE_LEVEL_4  4
@@ -414,4 +432,29 @@ extern struct list_head acpi_rmrr_units;
 extern struct list_head acpi_rmrr_units;
 extern struct list_head acpi_ioapic_units;
 
+struct qi_ctrl {
+    struct qinval_entry *qinval;         /* queue invalidation page */
+    int qinval_index;                    /* queue invalidation index */
+    spinlock_t qinval_lock;      /* lock for queue invalidation page */
+    spinlock_t qinval_poll_lock; /* lock for queue invalidation poll addr */
+    volatile u32 qinval_poll_status;     /* used by poll methord to sync */
+};
+
+struct ir_ctrl {
+    struct iremap_entry *iremap;         /* interrupt remap table */
+    int iremap_index;                    /* interrupt remap index */
+    spinlock_t iremap_lock;      /* lock for irq remappping table */
+};
+
+struct iommu_flush {
+    int (*context)(void *iommu, u16 did, u16 source_id, u8 function_mask, u64 
type, int non_present_entry_flush);
+    int (*iotlb)(void *iommu, u16 did, u64 addr, unsigned int size_order, u64 
type, int non_present_entry_flush);
+};
+
+struct intel_iommu {
+    struct qi_ctrl qi_ctrl;
+    struct ir_ctrl ir_ctrl;
+    struct iommu_flush flush; 
+};
+
 #endif
diff -r 7643472d6b43 -r a868bd4236e6 xen/include/asm-x86/hypercall.h
--- a/xen/include/asm-x86/hypercall.h   Thu Jan 17 12:17:14 2008 -0700
+++ b/xen/include/asm-x86/hypercall.h   Fri Jan 18 13:49:48 2008 -0700
@@ -34,7 +34,7 @@ do_physdev_op_compat(
 
 extern long
 do_set_trap_table(
-    XEN_GUEST_HANDLE(trap_info_t) traps);
+    XEN_GUEST_HANDLE(const_trap_info_t) traps);
 
 extern int
 do_mmu_update(
diff -r 7643472d6b43 -r a868bd4236e6 xen/include/public/arch-ia64.h
--- a/xen/include/public/arch-ia64.h    Thu Jan 17 12:17:14 2008 -0700
+++ b/xen/include/public/arch-ia64.h    Fri Jan 18 13:49:48 2008 -0700
@@ -36,7 +36,9 @@
 #endif
 
 #define __DEFINE_XEN_GUEST_HANDLE(name, type) \
-    ___DEFINE_XEN_GUEST_HANDLE(name, type)
+    ___DEFINE_XEN_GUEST_HANDLE(name, type);   \
+    ___DEFINE_XEN_GUEST_HANDLE(const_##name, const type)
+
 #define DEFINE_XEN_GUEST_HANDLE(name)   __DEFINE_XEN_GUEST_HANDLE(name, name)
 #define XEN_GUEST_HANDLE(name)          __guest_handle_ ## name
 #define XEN_GUEST_HANDLE_64(name)       XEN_GUEST_HANDLE(name)
@@ -47,18 +49,7 @@
 #endif
 
 #ifndef __ASSEMBLY__
-/* Guest handles for primitive C types. */
-__DEFINE_XEN_GUEST_HANDLE(uchar, unsigned char);
-__DEFINE_XEN_GUEST_HANDLE(uint,  unsigned int);
-__DEFINE_XEN_GUEST_HANDLE(ulong, unsigned long);
-__DEFINE_XEN_GUEST_HANDLE(u64,   unsigned long);
-DEFINE_XEN_GUEST_HANDLE(char);
-DEFINE_XEN_GUEST_HANDLE(int);
-DEFINE_XEN_GUEST_HANDLE(long);
-DEFINE_XEN_GUEST_HANDLE(void);
-
 typedef unsigned long xen_pfn_t;
-DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
 #define PRI_xen_pfn "lx"
 #endif
 
diff -r 7643472d6b43 -r a868bd4236e6 xen/include/public/arch-powerpc.h
--- a/xen/include/public/arch-powerpc.h Thu Jan 17 12:17:14 2008 -0700
+++ b/xen/include/public/arch-powerpc.h Fri Jan 18 13:49:48 2008 -0700
@@ -32,7 +32,8 @@
     } __attribute__((__aligned__(8))) __guest_handle_ ## name
 
 #define __DEFINE_XEN_GUEST_HANDLE(name, type) \
-    ___DEFINE_XEN_GUEST_HANDLE(name, type)
+    ___DEFINE_XEN_GUEST_HANDLE(name, type);   \
+    ___DEFINE_XEN_GUEST_HANDLE(const_##name, const type)
 #define DEFINE_XEN_GUEST_HANDLE(name) __DEFINE_XEN_GUEST_HANDLE(name, name)
 #define XEN_GUEST_HANDLE(name)        __guest_handle_ ## name
 #define set_xen_guest_handle(hnd, val) \
@@ -47,17 +48,7 @@
 #endif
 
 #ifndef __ASSEMBLY__
-/* Guest handles for primitive C types. */
-__DEFINE_XEN_GUEST_HANDLE(uchar, unsigned char);
-__DEFINE_XEN_GUEST_HANDLE(uint,  unsigned int);
-__DEFINE_XEN_GUEST_HANDLE(ulong, unsigned long);
-DEFINE_XEN_GUEST_HANDLE(char);
-DEFINE_XEN_GUEST_HANDLE(int);
-DEFINE_XEN_GUEST_HANDLE(long);
-DEFINE_XEN_GUEST_HANDLE(void);
-
 typedef unsigned long long xen_pfn_t;
-DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
 #define PRI_xen_pfn "llx"
 #endif
 
diff -r 7643472d6b43 -r a868bd4236e6 xen/include/public/arch-x86/xen.h
--- a/xen/include/public/arch-x86/xen.h Thu Jan 17 12:17:14 2008 -0700
+++ b/xen/include/public/arch-x86/xen.h Fri Jan 18 13:49:48 2008 -0700
@@ -37,7 +37,8 @@
 #endif
 
 #define __DEFINE_XEN_GUEST_HANDLE(name, type) \
-    ___DEFINE_XEN_GUEST_HANDLE(name, type)
+    ___DEFINE_XEN_GUEST_HANDLE(name, type);   \
+    ___DEFINE_XEN_GUEST_HANDLE(const_##name, const type)
 #define DEFINE_XEN_GUEST_HANDLE(name)   __DEFINE_XEN_GUEST_HANDLE(name, name)
 #define __XEN_GUEST_HANDLE(name)        __guest_handle_ ## name
 #define XEN_GUEST_HANDLE(name)          __XEN_GUEST_HANDLE(name)
@@ -53,17 +54,7 @@
 #endif
 
 #ifndef __ASSEMBLY__
-/* Guest handles for primitive C types. */
-__DEFINE_XEN_GUEST_HANDLE(uchar, unsigned char);
-__DEFINE_XEN_GUEST_HANDLE(uint,  unsigned int);
-__DEFINE_XEN_GUEST_HANDLE(ulong, unsigned long);
-DEFINE_XEN_GUEST_HANDLE(char);
-DEFINE_XEN_GUEST_HANDLE(int);
-DEFINE_XEN_GUEST_HANDLE(long);
-DEFINE_XEN_GUEST_HANDLE(void);
-
 typedef unsigned long xen_pfn_t;
-DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
 #define PRI_xen_pfn "lx"
 #endif
 
diff -r 7643472d6b43 -r a868bd4236e6 xen/include/public/io/fsif.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/public/io/fsif.h      Fri Jan 18 13:49:48 2008 -0700
@@ -0,0 +1,181 @@
+/******************************************************************************
+ * fsif.h
+ * 
+ * Interface to FS level split device drivers.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2007, Grzegorz Milos, Sun Microsystems, Inc.  
+ */
+
+#ifndef __XEN_PUBLIC_IO_FSIF_H__
+#define __XEN_PUBLIC_IO_FSIF_H__
+
+#include "ring.h"
+#include "../grant_table.h"
+
+#define REQ_FILE_OPEN        1
+#define REQ_FILE_CLOSE       2
+#define REQ_FILE_READ        3
+#define REQ_FILE_WRITE       4
+#define REQ_STAT             5
+#define REQ_FILE_TRUNCATE    6
+#define REQ_REMOVE           7
+#define REQ_RENAME           8
+#define REQ_CREATE           9
+#define REQ_DIR_LIST        10
+#define REQ_CHMOD           11
+#define REQ_FS_SPACE        12
+#define REQ_FILE_SYNC       13
+
+struct fsif_open_request {
+    grant_ref_t gref;
+};
+
+struct fsif_close_request {
+    uint32_t fd;
+};
+
+struct fsif_read_request {
+    uint32_t fd;
+    grant_ref_t gref;
+    uint64_t len;
+    uint64_t offset;
+};
+
+struct fsif_write_request {
+    uint32_t fd;
+    grant_ref_t gref;
+    uint64_t len;
+    uint64_t offset;
+};
+
+struct fsif_stat_request {
+    uint32_t fd;
+    grant_ref_t gref;
+};
+
+/* This structure is a copy of some fields from stat structure, writen to the
+ * granted page. */
+struct fsif_stat_response {
+    int32_t  stat_mode;
+    uint32_t stat_uid;
+    uint32_t stat_gid;
+    int32_t  pad;
+    int64_t  stat_size;
+    int64_t  stat_atime;
+    int64_t  stat_mtime;
+    int64_t  stat_ctime;
+};
+
+struct fsif_truncate_request {
+    uint32_t fd;
+    int32_t pad;
+    int64_t length;
+};
+
+struct fsif_remove_request {
+    grant_ref_t gref;
+};
+
+struct fsif_rename_request {
+    uint16_t old_name_offset;
+    uint16_t new_name_offset;
+    grant_ref_t gref;
+};
+
+struct fsif_create_request {
+    int8_t directory;
+    int8_t pad;
+    int16_t pad2;
+    int32_t mode;
+    grant_ref_t gref;
+};
+
+struct fsif_list_request {
+    uint32_t offset;
+    grant_ref_t gref;
+};
+
+#define NR_FILES_SHIFT  0
+#define NR_FILES_SIZE   16   /* 16 bits for the number of files mask */
+#define NR_FILES_MASK   (((1ULL << NR_FILES_SIZE) - 1) << NR_FILES_SHIFT)
+#define ERROR_SIZE      32   /* 32 bits for the error mask */
+#define ERROR_SHIFT     (NR_FILES_SIZE + NR_FILES_SHIFT)
+#define ERROR_MASK      (((1ULL << ERROR_SIZE) - 1) << ERROR_SHIFT)
+#define HAS_MORE_SHIFT  (ERROR_SHIFT + ERROR_SIZE)    
+#define HAS_MORE_FLAG   (1ULL << HAS_MORE_SHIFT)
+
+struct fsif_chmod_request {
+    uint32_t fd;
+    int32_t mode;
+};
+
+struct fsif_space_request {
+    grant_ref_t gref;
+};
+
+struct fsif_sync_request {
+    uint32_t fd;
+};
+
+
+/* FS operation request */
+struct fsif_request {
+    uint8_t type;                 /* Type of the request                  */
+    uint8_t pad;
+    uint16_t id;                  /* Request ID, copied to the response   */
+    uint32_t pad2;
+    union {
+        struct fsif_open_request     fopen;
+        struct fsif_close_request    fclose;
+        struct fsif_read_request     fread;
+        struct fsif_write_request    fwrite;
+        struct fsif_stat_request     fstat;
+        struct fsif_truncate_request ftruncate;
+        struct fsif_remove_request   fremove;
+        struct fsif_rename_request   frename;
+        struct fsif_create_request   fcreate;
+        struct fsif_list_request     flist;
+        struct fsif_chmod_request    fchmod;
+        struct fsif_space_request    fspace;
+        struct fsif_sync_request     fsync;
+    } u;
+};
+typedef struct fsif_request fsif_request_t;
+
+/* FS operation response */
+struct fsif_response {
+    uint16_t id;
+    uint16_t pad1;
+    uint32_t pad2;
+    uint64_t ret_val;
+};
+
+typedef struct fsif_response fsif_response_t;
+
+
+DEFINE_RING_TYPES(fsif, struct fsif_request, struct fsif_response);
+
+#define STATE_INITIALISED     "init"
+#define STATE_READY           "ready"
+
+
+
+#endif
diff -r 7643472d6b43 -r a868bd4236e6 xen/include/public/xen.h
--- a/xen/include/public/xen.h  Thu Jan 17 12:17:14 2008 -0700
+++ b/xen/include/public/xen.h  Fri Jan 18 13:49:48 2008 -0700
@@ -37,6 +37,19 @@
 #include "arch-powerpc.h"
 #else
 #error "Unsupported architecture"
+#endif
+
+#ifndef __ASSEMBLY__
+/* Guest handles for primitive C types. */
+DEFINE_XEN_GUEST_HANDLE(char);
+__DEFINE_XEN_GUEST_HANDLE(uchar, unsigned char);
+DEFINE_XEN_GUEST_HANDLE(int);
+__DEFINE_XEN_GUEST_HANDLE(uint,  unsigned int);
+DEFINE_XEN_GUEST_HANDLE(long);
+__DEFINE_XEN_GUEST_HANDLE(ulong, unsigned long);
+DEFINE_XEN_GUEST_HANDLE(void);
+
+DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
 #endif
 
 /*

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.