ia64/xen-unstable

changeset 16813:a868bd4236e6

merge with xen-unstable.hg staging
author Alex Williamson <alex.williamson@hp.com>
date Fri Jan 18 13:49:48 2008 -0700 (2008-01-18)
parents 7643472d6b43 1e6455d608bd
children 0ace9a451a25
files
line diff
     1.1 --- a/docs/man/xm.pod.1	Thu Jan 17 12:17:14 2008 -0700
     1.2 +++ b/docs/man/xm.pod.1	Fri Jan 18 13:49:48 2008 -0700
     1.3 @@ -254,9 +254,12 @@ domain, as it may balloon down its memor
     1.4  
     1.5  =item B<mem-set> I<domain-id> I<mem>
     1.6  
     1.7 -Set the domain's used memory using the balloon driver.  Because this
     1.8 -operation requires cooperation from the domain operating system, there
     1.9 -is no guarantee that it will succeed.
    1.10 +Set the domain's used memory using the balloon driver.
    1.11 +
    1.12 +Because this operation requires cooperation from the domain operating
    1.13 +system, there is no guarantee that it will succeed.  This command will
    1.14 +definitely not work unless the domain has the required paravirt
    1.15 +driver.
    1.16  
    1.17  B<Warning:> There is no good way to know in advance how small of a
    1.18  mem-set will make a domain unstable and cause it to crash.  Be very
    1.19 @@ -392,6 +395,10 @@ Attempting to set the VCPUs to a number 
    1.20  configured VCPU count is an error.  Trying to set VCPUs to < 1 will be
    1.21  quietly ignored.
    1.22  
    1.23 +Because this operation requires cooperation from the domain operating
    1.24 +system, there is no guarantee that it will succeed.  This command will
    1.25 +not work with a full virt domain.
    1.26 +
    1.27  =item B<vcpu-list> [I<domain-id>]
    1.28  
    1.29  Lists VCPU information for a specific domain.  If no domain is
     2.1 --- a/extras/mini-os/Makefile	Thu Jan 17 12:17:14 2008 -0700
     2.2 +++ b/extras/mini-os/Makefile	Fri Jan 18 13:49:48 2008 -0700
     2.3 @@ -53,7 +53,7 @@ include minios.mk
     2.4  # Define some default flags for linking.
     2.5  LDLIBS := 
     2.6  LDARCHLIB := -L$(TARGET_ARCH_DIR) -l$(ARCH_LIB_NAME)
     2.7 -LDFLAGS_FINAL := -N -T $(TARGET_ARCH_DIR)/minios-$(TARGET_ARCH).lds
     2.8 +LDFLAGS_FINAL := -T $(TARGET_ARCH_DIR)/minios-$(TARGET_ARCH).lds
     2.9  
    2.10  # Prefix for global API names. All other symbols are localised before
    2.11  # linking with EXTRA_OBJS.
     3.1 --- a/extras/mini-os/arch/ia64/mm.c	Thu Jan 17 12:17:14 2008 -0700
     3.2 +++ b/extras/mini-os/arch/ia64/mm.c	Fri Jan 18 13:49:48 2008 -0700
     3.3 @@ -124,9 +124,14 @@ arch_init_demand_mapping_area(unsigned l
     3.4  
     3.5  /* Helper function used in gnttab.c. */
     3.6  void*
     3.7 -map_frames(unsigned long* frames, unsigned long n)
     3.8 +map_frames_ex(unsigned long* frames, unsigned long n, unsigned long stride,
     3.9 +	unsigned long increment, unsigned long alignment, domid_t id,
    3.10 +	int may_fail, unsigned long prot)
    3.11  {
    3.12 -	n = n;
    3.13 +        /* TODO: incomplete! */
    3.14 +        ASSERT(n == 1 || (stride == 0 && increment == 1));
    3.15 +        ASSERT(id == DOMID_SELF);
    3.16 +        ASSERT(prot == 0);
    3.17  	return (void*) __va(SWAP(frames[0]) << PAGE_SHIFT);
    3.18  }
    3.19  
     4.1 --- a/extras/mini-os/arch/x86/minios-x86_32.lds	Thu Jan 17 12:17:14 2008 -0700
     4.2 +++ b/extras/mini-os/arch/x86/minios-x86_32.lds	Fri Jan 18 13:49:48 2008 -0700
     4.3 @@ -13,6 +13,8 @@ SECTIONS
     4.4    _etext = .;			/* End of text section */
     4.5  
     4.6    .rodata : { *(.rodata) *(.rodata.*) }
     4.7 +  . = ALIGN(4096);
     4.8 +  _erodata = .;
     4.9  
    4.10    .data : {			/* Data */
    4.11  	*(.data)
     5.1 --- a/extras/mini-os/arch/x86/minios-x86_64.lds	Thu Jan 17 12:17:14 2008 -0700
     5.2 +++ b/extras/mini-os/arch/x86/minios-x86_64.lds	Fri Jan 18 13:49:48 2008 -0700
     5.3 @@ -13,6 +13,8 @@ SECTIONS
     5.4    _etext = .;			/* End of text section */
     5.5  
     5.6    .rodata : { *(.rodata) *(.rodata.*) }
     5.7 +  . = ALIGN(4096);
     5.8 +  _erodata = .;
     5.9  
    5.10    .data : {			/* Data */
    5.11  	*(.data)
     6.1 --- a/extras/mini-os/arch/x86/mm.c	Thu Jan 17 12:17:14 2008 -0700
     6.2 +++ b/extras/mini-os/arch/x86/mm.c	Fri Jan 18 13:49:48 2008 -0700
     6.3 @@ -40,6 +40,7 @@
     6.4  #include <types.h>
     6.5  #include <lib.h>
     6.6  #include <xmalloc.h>
     6.7 +#include <xen/memory.h>
     6.8  
     6.9  #ifdef MM_DEBUG
    6.10  #define DEBUG(_f, _a...) \
    6.11 @@ -49,6 +50,7 @@
    6.12  #endif
    6.13  
    6.14  unsigned long *phys_to_machine_mapping;
    6.15 +unsigned long mfn_zero;
    6.16  extern char stack[];
    6.17  extern void page_walk(unsigned long virt_addr);
    6.18  
    6.19 @@ -270,12 +272,73 @@ void build_pagetable(unsigned long *star
    6.20          start_address += PAGE_SIZE;
    6.21      }
    6.22  
    6.23 -    if (HYPERVISOR_update_va_mapping(0, (pte_t) {}, UVMF_INVLPG))
    6.24 -        printk("Unable to unmap page 0\n");
    6.25 -
    6.26      *start_pfn = pt_pfn;
    6.27  }
    6.28  
    6.29 +extern void shared_info;
    6.30 +static void set_readonly(void *text, void *etext)
    6.31 +{
    6.32 +    unsigned long start_address = ((unsigned long) text + PAGE_SIZE - 1) & PAGE_MASK;
    6.33 +    unsigned long end_address = (unsigned long) etext;
    6.34 +    static mmu_update_t mmu_updates[L1_PAGETABLE_ENTRIES + 1];
    6.35 +    pgentry_t *tab = (pgentry_t *)start_info.pt_base, page;
    6.36 +    unsigned long mfn = pfn_to_mfn(virt_to_pfn(start_info.pt_base));
    6.37 +    unsigned long offset;
    6.38 +    int count = 0;
    6.39 +
    6.40 +    printk("setting %p-%p readonly\n", text, etext);
    6.41 +
    6.42 +    while (start_address + PAGE_SIZE <= end_address) {
    6.43 +        tab = (pgentry_t *)start_info.pt_base;
    6.44 +        mfn = pfn_to_mfn(virt_to_pfn(start_info.pt_base));
    6.45 +
    6.46 +#if defined(__x86_64__)
    6.47 +        offset = l4_table_offset(start_address);
    6.48 +        page = tab[offset];
    6.49 +        mfn = pte_to_mfn(page);
    6.50 +        tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT);
    6.51 +#endif
    6.52 +#if defined(__x86_64__) || defined(CONFIG_X86_PAE)
    6.53 +        offset = l3_table_offset(start_address);
    6.54 +        page = tab[offset];
    6.55 +        mfn = pte_to_mfn(page);
    6.56 +        tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT);
    6.57 +#endif
    6.58 +        offset = l2_table_offset(start_address);        
    6.59 +        page = tab[offset];
    6.60 +        mfn = pte_to_mfn(page);
    6.61 +        tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT);
    6.62 +
    6.63 +        offset = l1_table_offset(start_address);
    6.64 +
    6.65 +	if (start_address != (unsigned long)&shared_info) {
    6.66 +	    mmu_updates[count].ptr = ((pgentry_t)mfn << PAGE_SHIFT) + sizeof(pgentry_t) * offset;
    6.67 +	    mmu_updates[count].val = tab[offset] & ~_PAGE_RW;
    6.68 +	    count++;
    6.69 +	} else
    6.70 +	    printk("skipped %p\n", start_address);
    6.71 +
    6.72 +        start_address += PAGE_SIZE;
    6.73 +
    6.74 +        if (count == L1_PAGETABLE_ENTRIES || start_address + PAGE_SIZE > end_address)
    6.75 +        {
    6.76 +            if(HYPERVISOR_mmu_update(mmu_updates, count, NULL, DOMID_SELF) < 0)
    6.77 +            {
    6.78 +                printk("PTE could not be updated\n");
    6.79 +                do_exit();
    6.80 +            }
    6.81 +            count = 0;
    6.82 +        }
    6.83 +    }
    6.84 +
    6.85 +    {
    6.86 +	mmuext_op_t op = {
    6.87 +	    .cmd = MMUEXT_TLB_FLUSH_ALL,
    6.88 +	};
    6.89 +	int count;
    6.90 +	HYPERVISOR_mmuext_op(&op, 1, &count, DOMID_SELF);
    6.91 +    }
    6.92 +}
    6.93  
    6.94  void mem_test(unsigned long *start_add, unsigned long *end_add)
    6.95  {
    6.96 @@ -305,6 +368,7 @@ void mem_test(unsigned long *start_add, 
    6.97  
    6.98  static pgentry_t *demand_map_pgt;
    6.99  static void *demand_map_area_start;
   6.100 +#define DEMAND_MAP_PAGES 1024
   6.101  
   6.102  void arch_init_demand_mapping_area(unsigned long max_pfn)
   6.103  {
   6.104 @@ -364,20 +428,19 @@ void arch_init_demand_mapping_area(unsig
   6.105      printk("Initialised demand area.\n");
   6.106  }
   6.107  
   6.108 -void *map_frames(unsigned long *f, unsigned long n)
   6.109 +#define MAP_BATCH ((STACK_SIZE / 2) / sizeof(mmu_update_t))
   6.110 +
   6.111 +void *map_frames_ex(unsigned long *f, unsigned long n, unsigned long stride,
   6.112 +	unsigned long increment, unsigned long alignment, domid_t id,
   6.113 +	int may_fail, unsigned long prot)
   6.114  {
   6.115      unsigned long x;
   6.116      unsigned long y = 0;
   6.117 -    mmu_update_t mmu_updates[16];
   6.118      int rc;
   6.119 -
   6.120 -    if (n > 16) {
   6.121 -        printk("Tried to map too many (%ld) frames at once.\n", n);
   6.122 -        return NULL;
   6.123 -    }
   6.124 +    unsigned long done = 0;
   6.125  
   6.126      /* Find a run of n contiguous frames */
   6.127 -    for (x = 0; x <= 1024 - n; x += y + 1) {
   6.128 +    for (x = 0; x <= DEMAND_MAP_PAGES - n; x = (x + y + 1 + alignment - 1) & ~(alignment - 1)) {
   6.129          for (y = 0; y < n; y++)
   6.130              if (demand_map_pgt[x+y] & _PAGE_PRESENT)
   6.131                  break;
   6.132 @@ -385,26 +448,68 @@ void *map_frames(unsigned long *f, unsig
   6.133              break;
   6.134      }
   6.135      if (y != n) {
   6.136 -        printk("Failed to map %ld frames!\n", n);
   6.137 +        printk("Failed to find %ld frames!\n", n);
   6.138          return NULL;
   6.139      }
   6.140  
   6.141      /* Found it at x.  Map it in. */
   6.142 -    for (y = 0; y < n; y++) {
   6.143 -        mmu_updates[y].ptr = virt_to_mach(&demand_map_pgt[x + y]);
   6.144 -        mmu_updates[y].val = (f[y] << PAGE_SHIFT) | L1_PROT;
   6.145 -    }
   6.146  
   6.147 -    rc = HYPERVISOR_mmu_update(mmu_updates, n, NULL, DOMID_SELF);
   6.148 -    if (rc < 0) {
   6.149 -        printk("Map %ld failed: %d.\n", n, rc);
   6.150 -        return NULL;
   6.151 -    } else {
   6.152 -        return (void *)(unsigned long)((unsigned long)demand_map_area_start +
   6.153 -                x * PAGE_SIZE);
   6.154 +    while (done < n) {
   6.155 +	unsigned long todo;
   6.156 +
   6.157 +	if (may_fail)
   6.158 +	    todo = 1;
   6.159 +	else
   6.160 +	    todo = n - done;
   6.161 +
   6.162 +	if (todo > MAP_BATCH)
   6.163 +		todo = MAP_BATCH;
   6.164 +
   6.165 +	{
   6.166 +	    mmu_update_t mmu_updates[todo];
   6.167 +
   6.168 +	    for (y = 0; y < todo; y++) {
   6.169 +		mmu_updates[y].ptr = virt_to_mach(&demand_map_pgt[x + done + y]);
   6.170 +		mmu_updates[y].val = ((f[(done + y) * stride] + (done + y) * increment) << PAGE_SHIFT) | prot;
   6.171 +	    }
   6.172 +
   6.173 +	    rc = HYPERVISOR_mmu_update(mmu_updates, todo, NULL, id);
   6.174 +	    if (rc < 0) {
   6.175 +		if (may_fail)
   6.176 +		    f[done * stride] |= 0xF0000000;
   6.177 +		else {
   6.178 +		    printk("Map %ld (%lx, ...) failed: %d.\n", todo, f[done * stride], rc);
   6.179 +		    return NULL;
   6.180 +		}
   6.181 +	    }
   6.182 +	}
   6.183 +
   6.184 +	done += todo;
   6.185      }
   6.186 +    return (void *)(unsigned long)((unsigned long)demand_map_area_start +
   6.187 +	    x * PAGE_SIZE);
   6.188  }
   6.189  
   6.190 +static void clear_bootstrap(void)
   6.191 +{
   6.192 +    struct xen_memory_reservation reservation;
   6.193 +    xen_pfn_t mfns[] = { virt_to_mfn(&shared_info) };
   6.194 +    int n = sizeof(mfns)/sizeof(*mfns);
   6.195 +    pte_t nullpte = { };
   6.196 +
   6.197 +    /* Use page 0 as the CoW zero page */
   6.198 +    memset(NULL, 0, PAGE_SIZE);
   6.199 +    mfn_zero = pfn_to_mfn(0);
   6.200 +    if (HYPERVISOR_update_va_mapping(0, nullpte, UVMF_INVLPG))
   6.201 +	printk("Unable to unmap page 0\n");
   6.202 +
   6.203 +    set_xen_guest_handle(reservation.extent_start, mfns);
   6.204 +    reservation.nr_extents = n;
   6.205 +    reservation.extent_order = 0;
   6.206 +    reservation.domid = DOMID_SELF;
   6.207 +    if (HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation) != n)
   6.208 +	printk("Unable to free bootstrap pages\n");
   6.209 +}
   6.210  
   6.211  void arch_init_p2m(unsigned long max_pfn)
   6.212  {
   6.213 @@ -455,6 +560,7 @@ void arch_init_mm(unsigned long* start_p
   6.214  
   6.215      printk("  _text:        %p\n", &_text);
   6.216      printk("  _etext:       %p\n", &_etext);
   6.217 +    printk("  _erodata:     %p\n", &_erodata);
   6.218      printk("  _edata:       %p\n", &_edata);
   6.219      printk("  stack start:  %p\n", stack);
   6.220      printk("  _end:         %p\n", &_end);
   6.221 @@ -468,8 +574,9 @@ void arch_init_mm(unsigned long* start_p
   6.222      printk("  max_pfn:      %lx\n", max_pfn);
   6.223  
   6.224      build_pagetable(&start_pfn, &max_pfn);
   6.225 +    clear_bootstrap();
   6.226 +    set_readonly(&_text, &_erodata);
   6.227  
   6.228      *start_pfn_p = start_pfn;
   6.229      *max_pfn_p = max_pfn;
   6.230  }
   6.231 -
     7.1 --- a/extras/mini-os/arch/x86/traps.c	Thu Jan 17 12:17:14 2008 -0700
     7.2 +++ b/extras/mini-os/arch/x86/traps.c	Fri Jan 18 13:49:48 2008 -0700
     7.3 @@ -118,6 +118,46 @@ void page_walk(unsigned long virt_addres
     7.4  
     7.5  }
     7.6  
     7.7 +static int handle_cow(unsigned long addr) {
     7.8 +        pgentry_t *tab = (pgentry_t *)start_info.pt_base, page;
     7.9 +	unsigned long new_page;
    7.10 +	int rc;
    7.11 +
    7.12 +#if defined(__x86_64__)
    7.13 +        page = tab[l4_table_offset(addr)];
    7.14 +	if (!(page & _PAGE_PRESENT))
    7.15 +	    return 0;
    7.16 +        tab = pte_to_virt(page);
    7.17 +#endif
    7.18 +#if defined(__x86_64__) || defined(CONFIG_X86_PAE)
    7.19 +        page = tab[l3_table_offset(addr)];
    7.20 +	if (!(page & _PAGE_PRESENT))
    7.21 +	    return 0;
    7.22 +        tab = pte_to_virt(page);
    7.23 +#endif
    7.24 +        page = tab[l2_table_offset(addr)];
    7.25 +	if (!(page & _PAGE_PRESENT))
    7.26 +	    return 0;
    7.27 +        tab = pte_to_virt(page);
    7.28 +        
    7.29 +        page = tab[l1_table_offset(addr)];
    7.30 +	if (!(page & _PAGE_PRESENT))
    7.31 +	    return 0;
    7.32 +	/* Only support CoW for the zero page.  */
    7.33 +	if (PHYS_PFN(page) != mfn_zero)
    7.34 +	    return 0;
    7.35 +
    7.36 +	new_page = alloc_pages(0);
    7.37 +	memset((void*) new_page, 0, PAGE_SIZE);
    7.38 +
    7.39 +	rc = HYPERVISOR_update_va_mapping(addr & PAGE_MASK, __pte(virt_to_mach(new_page) | L1_PROT), UVMF_INVLPG);
    7.40 +	if (!rc)
    7.41 +		return 1;
    7.42 +
    7.43 +	printk("Map zero page to %lx failed: %d.\n", addr, rc);
    7.44 +	return 0;
    7.45 +}
    7.46 +
    7.47  #define read_cr2() \
    7.48          (HYPERVISOR_shared_info->vcpu_info[smp_processor_id()].arch.cr2)
    7.49  
    7.50 @@ -126,6 +166,10 @@ static int handling_pg_fault = 0;
    7.51  void do_page_fault(struct pt_regs *regs, unsigned long error_code)
    7.52  {
    7.53      unsigned long addr = read_cr2();
    7.54 +
    7.55 +    if ((error_code & TRAP_PF_WRITE) && handle_cow(addr))
    7.56 +	return;
    7.57 +
    7.58      /* If we are already handling a page fault, and got another one
    7.59         that means we faulted in pagetable walk. Continuing here would cause
    7.60         a recursive fault */       
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/extras/mini-os/blkfront.c	Fri Jan 18 13:49:48 2008 -0700
     8.3 @@ -0,0 +1,392 @@
     8.4 +/* Minimal block driver for Mini-OS. 
     8.5 + * Copyright (c) 2007-2008 Samuel Thibault.
     8.6 + * Based on netfront.c.
     8.7 + */
     8.8 +
     8.9 +#include <os.h>
    8.10 +#include <xenbus.h>
    8.11 +#include <events.h>
    8.12 +#include <errno.h>
    8.13 +#include <xen/io/blkif.h>
    8.14 +#include <gnttab.h>
    8.15 +#include <xmalloc.h>
    8.16 +#include <time.h>
    8.17 +#include <blkfront.h>
    8.18 +#include <lib.h>
    8.19 +#include <fcntl.h>
    8.20 +
    8.21 +/* Note: we generally don't need to disable IRQs since we hardly do anything in
    8.22 + * the interrupt handler.  */
    8.23 +
    8.24 +/* Note: we really suppose non-preemptive threads.  */
    8.25 +
    8.26 +DECLARE_WAIT_QUEUE_HEAD(blkfront_queue);
    8.27 +
    8.28 +
    8.29 +
    8.30 +
    8.31 +#define BLK_RING_SIZE __RING_SIZE((struct blkif_sring *)0, PAGE_SIZE)
    8.32 +#define GRANT_INVALID_REF 0
    8.33 +
    8.34 +
    8.35 +struct blk_buffer {
    8.36 +    void* page;
    8.37 +    grant_ref_t gref;
    8.38 +};
    8.39 +
    8.40 +struct blkfront_dev {
    8.41 +    struct blkif_front_ring ring;
    8.42 +    grant_ref_t ring_ref;
    8.43 +    evtchn_port_t evtchn, local_port;
    8.44 +    blkif_vdev_t handle;
    8.45 +
    8.46 +    char *nodename;
    8.47 +    char *backend;
    8.48 +    unsigned sector_size;
    8.49 +    unsigned sectors;
    8.50 +    int mode;
    8.51 +    int barrier;
    8.52 +    int flush;
    8.53 +};
    8.54 +
    8.55 +static inline int xenblk_rxidx(RING_IDX idx)
    8.56 +{
    8.57 +    return idx & (BLK_RING_SIZE - 1);
    8.58 +}
    8.59 +
    8.60 +void blkfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
    8.61 +{
    8.62 +    wake_up(&blkfront_queue);
    8.63 +}
    8.64 +
    8.65 +struct blkfront_dev *init_blkfront(char *nodename, uint64_t *sectors, unsigned *sector_size, int *mode)
    8.66 +{
    8.67 +    xenbus_transaction_t xbt;
    8.68 +    char* err;
    8.69 +    char* message=NULL;
    8.70 +    struct blkif_sring *s;
    8.71 +    int retry=0;
    8.72 +    char* msg;
    8.73 +    char* c;
    8.74 +
    8.75 +    struct blkfront_dev *dev;
    8.76 +
    8.77 +    ASSERT(!strncmp(nodename, "/local/domain/", 14));
    8.78 +    nodename = strchr(nodename + 14, '/') + 1;
    8.79 +
    8.80 +    char path[strlen(nodename) + 1 + 10 + 1];
    8.81 +
    8.82 +    printk("******************* BLKFRONT for %s **********\n\n\n", nodename);
    8.83 +
    8.84 +    dev = malloc(sizeof(*dev));
    8.85 +    dev->nodename = strdup(nodename);
    8.86 +
    8.87 +    s = (struct blkif_sring*) alloc_page();
    8.88 +    memset(s,0,PAGE_SIZE);
    8.89 +
    8.90 +
    8.91 +    SHARED_RING_INIT(s);
    8.92 +    FRONT_RING_INIT(&dev->ring, s, PAGE_SIZE);
    8.93 +
    8.94 +    dev->ring_ref = gnttab_grant_access(0,virt_to_mfn(s),0);
    8.95 +
    8.96 +    evtchn_alloc_unbound_t op;
    8.97 +    op.dom = DOMID_SELF;
    8.98 +    snprintf(path, sizeof(path), "%s/backend-id", nodename);
    8.99 +    op.remote_dom = xenbus_read_integer(path); 
   8.100 +    HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
   8.101 +    clear_evtchn(op.port);        /* Without, handler gets invoked now! */
   8.102 +    dev->local_port = bind_evtchn(op.port, blkfront_handler, dev);
   8.103 +    dev->evtchn=op.port;
   8.104 +
   8.105 +    // FIXME: proper frees on failures
   8.106 +again:
   8.107 +    err = xenbus_transaction_start(&xbt);
   8.108 +    if (err) {
   8.109 +        printk("starting transaction\n");
   8.110 +    }
   8.111 +
   8.112 +    err = xenbus_printf(xbt, nodename, "ring-ref","%u",
   8.113 +                dev->ring_ref);
   8.114 +    if (err) {
   8.115 +        message = "writing ring-ref";
   8.116 +        goto abort_transaction;
   8.117 +    }
   8.118 +    err = xenbus_printf(xbt, nodename,
   8.119 +                "event-channel", "%u", dev->evtchn);
   8.120 +    if (err) {
   8.121 +        message = "writing event-channel";
   8.122 +        goto abort_transaction;
   8.123 +    }
   8.124 +
   8.125 +    err = xenbus_printf(xbt, nodename, "state", "%u",
   8.126 +            4); /* connected */
   8.127 +
   8.128 +
   8.129 +    err = xenbus_transaction_end(xbt, 0, &retry);
   8.130 +    if (retry) {
   8.131 +            goto again;
   8.132 +        printk("completing transaction\n");
   8.133 +    }
   8.134 +
   8.135 +    goto done;
   8.136 +
   8.137 +abort_transaction:
   8.138 +    xenbus_transaction_end(xbt, 1, &retry);
   8.139 +    return NULL;
   8.140 +
   8.141 +done:
   8.142 +
   8.143 +    snprintf(path, sizeof(path), "%s/backend", nodename);
   8.144 +    msg = xenbus_read(XBT_NIL, path, &dev->backend);
   8.145 +    if (msg) {
   8.146 +        printk("Error %s when reading the backend path %s\n", msg, path);
   8.147 +        return NULL;
   8.148 +    }
   8.149 +
   8.150 +    printk("backend at %s\n", dev->backend);
   8.151 +
   8.152 +    dev->handle = simple_strtoul(strrchr(nodename, '/')+1, NULL, 0);
   8.153 +
   8.154 +    {
   8.155 +        char path[strlen(dev->backend) + 1 + 19 + 1];
   8.156 +        snprintf(path, sizeof(path), "%s/mode", dev->backend);
   8.157 +        msg = xenbus_read(XBT_NIL, path, &c);
   8.158 +        if (msg) {
   8.159 +            printk("Error %s when reading the mode\n", msg);
   8.160 +            return NULL;
   8.161 +        }
   8.162 +        if (*c == 'w')
   8.163 +            *mode = dev->mode = O_RDWR;
   8.164 +        else
   8.165 +            *mode = dev->mode = O_RDONLY;
   8.166 +        free(c);
   8.167 +
   8.168 +        snprintf(path, sizeof(path), "%s/state", dev->backend);
   8.169 +
   8.170 +        xenbus_watch_path(XBT_NIL, path);
   8.171 +
   8.172 +        xenbus_wait_for_value(path,"4");
   8.173 +
   8.174 +        xenbus_unwatch_path(XBT_NIL, path);
   8.175 +
   8.176 +        snprintf(path, sizeof(path), "%s/sectors", dev->backend);
   8.177 +        // FIXME: read_integer returns an int, so disk size limited to 1TB for now
   8.178 +        *sectors = dev->sectors = xenbus_read_integer(path);
   8.179 +
   8.180 +        snprintf(path, sizeof(path), "%s/sector-size", dev->backend);
   8.181 +        *sector_size = dev->sector_size = xenbus_read_integer(path);
   8.182 +
   8.183 +        snprintf(path, sizeof(path), "%s/feature-barrier", dev->backend);
   8.184 +        dev->barrier = xenbus_read_integer(path);
   8.185 +
   8.186 +        snprintf(path, sizeof(path), "%s/feature-flush-cache", dev->backend);
   8.187 +        dev->flush = xenbus_read_integer(path);
   8.188 +    }
   8.189 +
   8.190 +    printk("%u sectors of %u bytes\n", dev->sectors, dev->sector_size);
   8.191 +    printk("**************************\n");
   8.192 +
   8.193 +    return dev;
   8.194 +}
   8.195 +
   8.196 +void shutdown_blkfront(struct blkfront_dev *dev)
   8.197 +{
   8.198 +    char* err;
   8.199 +    char *nodename = dev->nodename;
   8.200 +
   8.201 +    char path[strlen(dev->backend) + 1 + 5 + 1];
   8.202 +
   8.203 +    blkfront_sync(dev);
   8.204 +
   8.205 +    printk("close blk: backend at %s\n",dev->backend);
   8.206 +
   8.207 +    snprintf(path, sizeof(path), "%s/state", dev->backend);
   8.208 +    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */
   8.209 +    xenbus_wait_for_value(path,"5");
   8.210 +
   8.211 +    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
   8.212 +    xenbus_wait_for_value(path,"6");
   8.213 +
   8.214 +    unbind_evtchn(dev->local_port);
   8.215 +
   8.216 +    free(nodename);
   8.217 +    free(dev->backend);
   8.218 +    free(dev);
   8.219 +}
   8.220 +
   8.221 +static void blkfront_wait_slot(struct blkfront_dev *dev)
   8.222 +{
   8.223 +    /* Wait for a slot */
   8.224 +    if (RING_FULL(&dev->ring)) {
   8.225 +	unsigned long flags;
   8.226 +	DEFINE_WAIT(w);
   8.227 +	local_irq_save(flags);
   8.228 +	while (1) {
   8.229 +	    blkfront_aio_poll(dev);
   8.230 +	    if (!RING_FULL(&dev->ring))
   8.231 +		break;
   8.232 +	    /* Really no slot, go to sleep. */
   8.233 +	    add_waiter(w, blkfront_queue);
   8.234 +	    local_irq_restore(flags);
   8.235 +	    schedule();
   8.236 +	    local_irq_save(flags);
   8.237 +	}
   8.238 +	remove_waiter(w);
   8.239 +	local_irq_restore(flags);
   8.240 +    }
   8.241 +}
   8.242 +
   8.243 +/* Issue an aio */
   8.244 +void blkfront_aio(struct blkfront_aiocb *aiocbp, int write)
   8.245 +{
   8.246 +    struct blkfront_dev *dev = aiocbp->aio_dev;
   8.247 +    struct blkif_request *req;
   8.248 +    RING_IDX i;
   8.249 +    int notify;
   8.250 +    int n, j;
   8.251 +    uintptr_t start, end;
   8.252 +
   8.253 +    // Can't io at non-sector-aligned location
   8.254 +    ASSERT(!(aiocbp->aio_offset & (dev->sector_size-1)));
   8.255 +    // Can't io non-sector-sized amounts
   8.256 +    ASSERT(!(aiocbp->aio_nbytes & (dev->sector_size-1)));
   8.257 +    // Can't io non-sector-aligned buffer
   8.258 +    ASSERT(!((uintptr_t) aiocbp->aio_buf & (dev->sector_size-1)));
   8.259 +
   8.260 +    start = (uintptr_t)aiocbp->aio_buf & PAGE_MASK;
   8.261 +    end = ((uintptr_t)aiocbp->aio_buf + aiocbp->aio_nbytes + PAGE_SIZE - 1) & PAGE_MASK;
   8.262 +    n = (end - start) / PAGE_SIZE;
   8.263 +
   8.264 +    /* qemu's IDE max multsect is 16 (8KB) and SCSI max DMA was set to 32KB,
   8.265 +     * so max 44KB can't happen */
   8.266 +    ASSERT(n <= BLKIF_MAX_SEGMENTS_PER_REQUEST);
   8.267 +
   8.268 +    blkfront_wait_slot(dev);
   8.269 +    i = dev->ring.req_prod_pvt;
   8.270 +    req = RING_GET_REQUEST(&dev->ring, i);
   8.271 +
   8.272 +    req->operation = write ? BLKIF_OP_WRITE : BLKIF_OP_READ;
   8.273 +    req->nr_segments = n;
   8.274 +    req->handle = dev->handle;
   8.275 +    req->id = (uintptr_t) aiocbp;
   8.276 +    req->sector_number = aiocbp->aio_offset / dev->sector_size;
   8.277 +
   8.278 +    for (j = 0; j < n; j++) {
   8.279 +	uintptr_t data = start + j * PAGE_SIZE;
   8.280 +	aiocbp->gref[j] = req->seg[j].gref =
   8.281 +            gnttab_grant_access(0, virt_to_mfn(data), write);
   8.282 +	req->seg[j].first_sect = 0;
   8.283 +	req->seg[j].last_sect = PAGE_SIZE / dev->sector_size - 1;
   8.284 +    }
   8.285 +    req->seg[0].first_sect = ((uintptr_t)aiocbp->aio_buf & ~PAGE_MASK) / dev->sector_size;
   8.286 +    req->seg[n-1].last_sect = (((uintptr_t)aiocbp->aio_buf + aiocbp->aio_nbytes - 1) & ~PAGE_MASK) / dev->sector_size;
   8.287 +
   8.288 +    dev->ring.req_prod_pvt = i + 1;
   8.289 +
   8.290 +    wmb();
   8.291 +    RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&dev->ring, notify);
   8.292 +
   8.293 +    if(notify) notify_remote_via_evtchn(dev->evtchn);
   8.294 +}
   8.295 +
   8.296 +void blkfront_aio_write(struct blkfront_aiocb *aiocbp)
   8.297 +{
   8.298 +    blkfront_aio(aiocbp, 1);
   8.299 +}
   8.300 +
   8.301 +void blkfront_aio_read(struct blkfront_aiocb *aiocbp)
   8.302 +{
   8.303 +    blkfront_aio(aiocbp, 0);
   8.304 +}
   8.305 +
   8.306 +int blkfront_aio_poll(struct blkfront_dev *dev)
   8.307 +{
   8.308 +    RING_IDX rp, cons;
   8.309 +    struct blkif_response *rsp;
   8.310 +
   8.311 +moretodo:
   8.312 +    rp = dev->ring.sring->rsp_prod;
   8.313 +    rmb(); /* Ensure we see queued responses up to 'rp'. */
   8.314 +    cons = dev->ring.rsp_cons;
   8.315 +
   8.316 +    int nr_consumed = 0;
   8.317 +    while ((cons != rp))
   8.318 +    {
   8.319 +	rsp = RING_GET_RESPONSE(&dev->ring, cons);
   8.320 +
   8.321 +        switch (rsp->operation) {
   8.322 +        case BLKIF_OP_READ:
   8.323 +        case BLKIF_OP_WRITE:
   8.324 +        {
   8.325 +            struct blkfront_aiocb *aiocbp = (void*) (uintptr_t) rsp->id;
   8.326 +            int n = (aiocbp->aio_nbytes + PAGE_SIZE - 1) / PAGE_SIZE, j;
   8.327 +            for (j = 0; j < n; j++)
   8.328 +                gnttab_end_access(aiocbp->gref[j]);
   8.329 +
   8.330 +            /* Nota: callback frees aiocbp itself */
   8.331 +            aiocbp->aio_cb(aiocbp, rsp->status ? -EIO : 0);
   8.332 +            break;
   8.333 +        }
   8.334 +        case BLKIF_OP_WRITE_BARRIER:
   8.335 +        case BLKIF_OP_FLUSH_DISKCACHE:
   8.336 +            break;
   8.337 +        default:
   8.338 +            printk("unrecognized block operation %d response\n", rsp->operation);
   8.339 +            break;
   8.340 +        }
   8.341 +
   8.342 +	nr_consumed++;
   8.343 +	++cons;
   8.344 +    }
   8.345 +    dev->ring.rsp_cons = cons;
   8.346 +
   8.347 +    int more;
   8.348 +    RING_FINAL_CHECK_FOR_RESPONSES(&dev->ring, more);
   8.349 +    if (more) goto moretodo;
   8.350 +
   8.351 +    return nr_consumed;
   8.352 +}
   8.353 +
   8.354 +static void blkfront_push_operation(struct blkfront_dev *dev, uint8_t op)
   8.355 +{
   8.356 +    int i;
   8.357 +    struct blkif_request *req;
   8.358 +    int notify;
   8.359 +
   8.360 +    blkfront_wait_slot(dev);
   8.361 +    i = dev->ring.req_prod_pvt;
   8.362 +    req = RING_GET_REQUEST(&dev->ring, i);
   8.363 +    req->operation = op;
   8.364 +    dev->ring.req_prod_pvt = i + 1;
   8.365 +    wmb();
   8.366 +    RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&dev->ring, notify);
   8.367 +    if (notify) notify_remote_via_evtchn(dev->evtchn);
   8.368 +}
   8.369 +
   8.370 +void blkfront_sync(struct blkfront_dev *dev)
   8.371 +{
   8.372 +    unsigned long flags;
   8.373 +
   8.374 +    if (dev->barrier == 1)
   8.375 +        blkfront_push_operation(dev, BLKIF_OP_WRITE_BARRIER);
   8.376 +
   8.377 +    if (dev->flush == 1)
   8.378 +        blkfront_push_operation(dev, BLKIF_OP_FLUSH_DISKCACHE);
   8.379 +
   8.380 +    /* Note: This won't finish if another thread enqueues requests.  */
   8.381 +    local_irq_save(flags);
   8.382 +    DEFINE_WAIT(w);
   8.383 +    while (1) {
   8.384 +	blkfront_aio_poll(dev);
   8.385 +	if (RING_FREE_REQUESTS(&dev->ring) == RING_SIZE(&dev->ring))
   8.386 +	    break;
   8.387 +
   8.388 +	add_waiter(w, blkfront_queue);
   8.389 +	local_irq_restore(flags);
   8.390 +	schedule();
   8.391 +	local_irq_save(flags);
   8.392 +    }
   8.393 +    remove_waiter(w);
   8.394 +    local_irq_restore(flags);
   8.395 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/extras/mini-os/fs-front.c	Fri Jan 18 13:49:48 2008 -0700
     9.3 @@ -0,0 +1,1126 @@
     9.4 +/******************************************************************************
     9.5 + * fs-front.c
     9.6 + * 
     9.7 + * Frontend driver for FS split device driver.
     9.8 + *
     9.9 + * Copyright (c) 2007, Grzegorz Milos, Sun Microsystems, Inc.
    9.10 + * 
    9.11 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    9.12 + * of this software and associated documentation files (the "Software"), to
    9.13 + * deal in the Software without restriction, including without limitation the
    9.14 + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
    9.15 + * sell copies of the Software, and to permit persons to whom the Software is
    9.16 + * furnished to do so, subject to the following conditions:
    9.17 + * 
    9.18 + * The above copyright notice and this permission notice shall be included in
    9.19 + * all copies or substantial portions of the Software.
    9.20 + * 
    9.21 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
    9.22 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
    9.23 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
    9.24 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
    9.25 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
    9.26 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
    9.27 + * DEALINGS IN THE SOFTWARE.
    9.28 + */
    9.29 +
    9.30 +#undef NDEBUG
    9.31 +#include <os.h>
    9.32 +#include <list.h>
    9.33 +#include <xmalloc.h>
    9.34 +#include <xenbus.h>
    9.35 +#include <gnttab.h>
    9.36 +#include <events.h>
    9.37 +#include <xen/io/fsif.h>
    9.38 +#include <fs.h>
    9.39 +#include <sched.h>
    9.40 +
    9.41 +#define preempt_disable()
    9.42 +#define preempt_enable()
    9.43 +#define cmpxchg(p,o,n) synch_cmpxchg(p,o,n)
    9.44 +
    9.45 +
    9.46 +#ifdef FS_DEBUG
    9.47 +#define DEBUG(_f, _a...) \
    9.48 +    printk("MINI_OS(file=fs-front.c, line=%d) " _f "\n", __LINE__, ## _a)
    9.49 +#else
    9.50 +#define DEBUG(_f, _a...)    ((void)0)
    9.51 +#endif
    9.52 +
    9.53 +
    9.54 +struct fs_request;
    9.55 +struct fs_import *fs_import;
    9.56 +
    9.57 +/******************************************************************************/
    9.58 +/*                      RING REQUEST/RESPONSES HANDLING                       */
    9.59 +/******************************************************************************/
    9.60 +
    9.61 +struct fs_request
    9.62 +{
    9.63 +    void *page;
    9.64 +    grant_ref_t gref;
    9.65 +    struct thread *thread;                 /* Thread blocked on this request */
    9.66 +    struct fsif_response shadow_rsp;       /* Response copy writen by the 
    9.67 +                                              interrupt handler */  
    9.68 +};
    9.69 +
    9.70 +/* Ring operations:
    9.71 + * FSIF ring is used differently to Linux-like split devices. This stems from 
    9.72 + * the fact that no I/O request queue is present. The use of some of the macros
    9.73 + * defined in ring.h is not allowed, in particular:
    9.74 + * RING_PUSH_REQUESTS_AND_CHECK_NOTIFY cannot be used.
    9.75 + *
    9.76 + * The protocol used for FSIF ring is described below:
    9.77 + *
    9.78 + * In order to reserve a request the frontend:
    9.79 + * a) saves current frontend_ring->req_prod_pvt into a local variable
    9.80 + * b) checks that there are free request using the local req_prod_pvt
    9.81 + * c) tries to reserve the request using cmpxchg on frontend_ring->req_prod_pvt
    9.82 + *    if cmpxchg fails, it means that someone reserved the request, start from
    9.83 + *    a)
    9.84 + * 
    9.85 + * In order to commit a request to the shared ring:
    9.86 + * a) cmpxchg shared_ring->req_prod from local req_prod_pvt to req_prod_pvt+1 
    9.87 + *    Loop if unsuccessful.
    9.88 + * NOTE: Request should be commited to the shared ring as quickly as possible,
    9.89 + *       because otherwise other threads might busy loop trying to commit next
    9.90 + *       requests. It also follows that preemption should be disabled, if
    9.91 + *       possible, for the duration of the request construction.
    9.92 + */
    9.93 +
    9.94 +/* Number of free requests (for use on front side only). */
    9.95 +#define FS_RING_FREE_REQUESTS(_r, _req_prod_pvt)                         \
    9.96 +    (RING_SIZE(_r) - (_req_prod_pvt - (_r)->rsp_cons))
    9.97 +
    9.98 +
    9.99 +
   9.100 +static RING_IDX reserve_fsif_request(struct fs_import *import)
   9.101 +{
   9.102 +    RING_IDX idx; 
   9.103 +
   9.104 +    down(&import->reqs_sem);
   9.105 +    preempt_disable();
   9.106 +again:    
   9.107 +    /* We will attempt to reserve slot idx */
   9.108 +    idx = import->ring.req_prod_pvt;
   9.109 +    ASSERT (FS_RING_FREE_REQUESTS(&import->ring, idx));
   9.110 +    /* Attempt to reserve */
   9.111 +    if(cmpxchg(&import->ring.req_prod_pvt, idx, idx+1) != idx)
   9.112 +        goto again;
   9.113 +
   9.114 +    return idx; 
   9.115 +}
   9.116 +
   9.117 +static void commit_fsif_request(struct fs_import *import, RING_IDX idx)
   9.118 +{
   9.119 +    while(cmpxchg(&import->ring.sring->req_prod, idx, idx+1) != idx)
   9.120 +    {
   9.121 +        printk("Failed to commit a request: req_prod=%d, idx=%d\n",
   9.122 +                import->ring.sring->req_prod, idx);
   9.123 +    }
   9.124 +    preempt_enable();
   9.125 +
   9.126 +    /* NOTE: we cannot do anything clever about rsp_event, to hold off
   9.127 +     * notifications, because we don't know if we are a single request (in which
   9.128 +     * case we have to notify always), or a part of a larger request group
   9.129 +     * (when, in some cases, notification isn't required) */
   9.130 +    notify_remote_via_evtchn(import->local_port);
   9.131 +}
   9.132 +
   9.133 +
   9.134 +
   9.135 +static inline void add_id_to_freelist(unsigned int id,unsigned short* freelist)
   9.136 +{
   9.137 +    unsigned int old_id, new_id;
   9.138 +
   9.139 +again:    
   9.140 +    old_id = freelist[0];
   9.141 +    /* Note: temporal inconsistency, since freelist[0] can be changed by someone
   9.142 +     * else, but we are a sole owner of freelist[id], it's OK. */
   9.143 +    freelist[id] = old_id;
   9.144 +    new_id = id;
   9.145 +    if(cmpxchg(&freelist[0], old_id, new_id) != old_id)
   9.146 +    {
   9.147 +        printk("Cmpxchg on freelist add failed.\n");
   9.148 +        goto again;
   9.149 +    }
   9.150 +}
   9.151 +
   9.152 +/* always call reserve_fsif_request(import) before this, to protect from
   9.153 + * depletion. */
   9.154 +static inline unsigned short get_id_from_freelist(unsigned short* freelist)
   9.155 +{
   9.156 +    unsigned int old_id, new_id;
   9.157 +
   9.158 +again:    
   9.159 +    old_id = freelist[0];
   9.160 +    new_id = freelist[old_id];
   9.161 +    if(cmpxchg(&freelist[0], old_id, new_id) != old_id)
   9.162 +    {
   9.163 +        printk("Cmpxchg on freelist remove failed.\n");
   9.164 +        goto again;
   9.165 +    }
   9.166 +    
   9.167 +    return old_id;
   9.168 +}
   9.169 +
   9.170 +/******************************************************************************/
   9.171 +/*                  END OF RING REQUEST/RESPONSES HANDLING                    */
   9.172 +/******************************************************************************/
   9.173 +
   9.174 +
   9.175 +
   9.176 +/******************************************************************************/
   9.177 +/*                         INDIVIDUAL FILE OPERATIONS                         */
   9.178 +/******************************************************************************/
   9.179 +int fs_open(struct fs_import *import, char *file)
   9.180 +{
   9.181 +    struct fs_request *fsr;
   9.182 +    unsigned short priv_req_id;
   9.183 +    RING_IDX back_req_id; 
   9.184 +    struct fsif_request *req;
   9.185 +    int fd;
   9.186 +
   9.187 +    /* Prepare request for the backend */
   9.188 +    back_req_id = reserve_fsif_request(import);
   9.189 +    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
   9.190 +
   9.191 +    /* Prepare our private request structure */
   9.192 +    priv_req_id = get_id_from_freelist(import->freelist);
   9.193 +    DEBUG("Request id for fs_open call is: %d\n", priv_req_id);
   9.194 +    fsr = &import->requests[priv_req_id];
   9.195 +    fsr->thread = current;
   9.196 +    sprintf(fsr->page, "%s", file);
   9.197 +
   9.198 +    req = RING_GET_REQUEST(&import->ring, back_req_id);
   9.199 +    req->type = REQ_FILE_OPEN;
   9.200 +    req->id = priv_req_id;
   9.201 +    req->u.fopen.gref = fsr->gref;
   9.202 +
   9.203 +    /* Set blocked flag before commiting the request, thus avoiding missed
   9.204 +     * response race */
   9.205 +    block(current);
   9.206 +    commit_fsif_request(import, back_req_id);
   9.207 +    schedule();
   9.208 +    
   9.209 +    /* Read the response */
   9.210 +    fd = (int)fsr->shadow_rsp.ret_val;
   9.211 +    DEBUG("The following FD returned: %d\n", fd);
   9.212 +    add_id_to_freelist(priv_req_id, import->freelist);
   9.213 +
   9.214 +    return fd;
   9.215 +} 
   9.216 +
   9.217 +int fs_close(struct fs_import *import, int fd)
   9.218 +{
   9.219 +    struct fs_request *fsr;
   9.220 +    unsigned short priv_req_id;
   9.221 +    RING_IDX back_req_id; 
   9.222 +    struct fsif_request *req;
   9.223 +    int ret;
   9.224 +
   9.225 +    /* Prepare request for the backend */
   9.226 +    back_req_id = reserve_fsif_request(import);
   9.227 +    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
   9.228 +
   9.229 +    /* Prepare our private request structure */
   9.230 +    priv_req_id = get_id_from_freelist(import->freelist);
   9.231 +    DEBUG("Request id for fs_close call is: %d\n", priv_req_id);
   9.232 +    fsr = &import->requests[priv_req_id];
   9.233 +    fsr->thread = current;
   9.234 +
   9.235 +    req = RING_GET_REQUEST(&import->ring, back_req_id);
   9.236 +    req->type = REQ_FILE_CLOSE;
   9.237 +    req->id = priv_req_id;
   9.238 +    req->u.fclose.fd = fd;
   9.239 +
   9.240 +    /* Set blocked flag before commiting the request, thus avoiding missed
   9.241 +     * response race */
   9.242 +    block(current);
   9.243 +    commit_fsif_request(import, back_req_id);
   9.244 +    schedule();
   9.245 +    
   9.246 +    /* Read the response */
   9.247 +    ret = (int)fsr->shadow_rsp.ret_val;
   9.248 +    DEBUG("Close returned: %d\n", ret);
   9.249 +    add_id_to_freelist(priv_req_id, import->freelist);
   9.250 +
   9.251 +    return ret;
   9.252 +}
   9.253 +
   9.254 +ssize_t fs_read(struct fs_import *import, int fd, void *buf, 
   9.255 +                ssize_t len, ssize_t offset)
   9.256 +{
   9.257 +    struct fs_request *fsr;
   9.258 +    unsigned short priv_req_id;
   9.259 +    RING_IDX back_req_id; 
   9.260 +    struct fsif_request *req;
   9.261 +    ssize_t ret;
   9.262 +
   9.263 +    BUG_ON(len > PAGE_SIZE);
   9.264 +
   9.265 +    /* Prepare request for the backend */
   9.266 +    back_req_id = reserve_fsif_request(import);
   9.267 +    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
   9.268 +
   9.269 +    /* Prepare our private request structure */
   9.270 +    priv_req_id = get_id_from_freelist(import->freelist);
   9.271 +    DEBUG("Request id for fs_read call is: %d\n", priv_req_id);
   9.272 +    fsr = &import->requests[priv_req_id];
   9.273 +    fsr->thread = current;
   9.274 +    memset(fsr->page, 0, PAGE_SIZE);
   9.275 +
   9.276 +    req = RING_GET_REQUEST(&import->ring, back_req_id);
   9.277 +    req->type = REQ_FILE_READ;
   9.278 +    req->id = priv_req_id;
   9.279 +    req->u.fread.fd = fd;
   9.280 +    req->u.fread.gref = fsr->gref;
   9.281 +    req->u.fread.len = len;
   9.282 +    req->u.fread.offset = offset;
   9.283 +
   9.284 +    /* Set blocked flag before commiting the request, thus avoiding missed
   9.285 +     * response race */
   9.286 +    block(current);
   9.287 +    commit_fsif_request(import, back_req_id);
   9.288 +    schedule();
   9.289 +    
   9.290 +    /* Read the response */
   9.291 +    ret = (ssize_t)fsr->shadow_rsp.ret_val;
   9.292 +    DEBUG("The following ret value returned %d\n", ret);
   9.293 +    if(ret > 0)
   9.294 +        memcpy(buf, fsr->page, ret);
   9.295 +    add_id_to_freelist(priv_req_id, import->freelist);
   9.296 +
   9.297 +    return ret;
   9.298 +} 
   9.299 +
   9.300 +ssize_t fs_write(struct fs_import *import, int fd, void *buf, 
   9.301 +                 ssize_t len, ssize_t offset)
   9.302 +{
   9.303 +    struct fs_request *fsr;
   9.304 +    unsigned short priv_req_id;
   9.305 +    RING_IDX back_req_id; 
   9.306 +    struct fsif_request *req;
   9.307 +    ssize_t ret;
   9.308 +
   9.309 +    BUG_ON(len > PAGE_SIZE);
   9.310 +
   9.311 +    /* Prepare request for the backend */
   9.312 +    back_req_id = reserve_fsif_request(import);
   9.313 +    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
   9.314 +
   9.315 +    /* Prepare our private request structure */
   9.316 +    priv_req_id = get_id_from_freelist(import->freelist);
   9.317 +    DEBUG("Request id for fs_read call is: %d\n", priv_req_id);
   9.318 +    fsr = &import->requests[priv_req_id];
   9.319 +    fsr->thread = current;
   9.320 +    memcpy(fsr->page, buf, len);
   9.321 +    BUG_ON(len > PAGE_SIZE);
   9.322 +    memset((char *)fsr->page + len, 0, PAGE_SIZE - len); 
   9.323 +
   9.324 +    req = RING_GET_REQUEST(&import->ring, back_req_id);
   9.325 +    req->type = REQ_FILE_WRITE;
   9.326 +    req->id = priv_req_id;
   9.327 +    req->u.fwrite.fd = fd;
   9.328 +    req->u.fwrite.gref = fsr->gref;
   9.329 +    req->u.fwrite.len = len;
   9.330 +    req->u.fwrite.offset = offset;
   9.331 +
   9.332 +    /* Set blocked flag before commiting the request, thus avoiding missed
   9.333 +     * response race */
   9.334 +    block(current);
   9.335 +    commit_fsif_request(import, back_req_id);
   9.336 +    schedule();
   9.337 +    
   9.338 +    /* Read the response */
   9.339 +    ret = (ssize_t)fsr->shadow_rsp.ret_val;
   9.340 +    DEBUG("The following ret value returned %d\n", ret);
   9.341 +    add_id_to_freelist(priv_req_id, import->freelist);
   9.342 +
   9.343 +    return ret;
   9.344 +} 
   9.345 +
   9.346 +int fs_stat(struct fs_import *import, 
   9.347 +            int fd, 
   9.348 +            struct fsif_stat_response *stat)
   9.349 +{
   9.350 +    struct fs_request *fsr;
   9.351 +    unsigned short priv_req_id;
   9.352 +    RING_IDX back_req_id; 
   9.353 +    struct fsif_request *req;
   9.354 +    int ret;
   9.355 +
   9.356 +    /* Prepare request for the backend */
   9.357 +    back_req_id = reserve_fsif_request(import);
   9.358 +    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
   9.359 +
   9.360 +    /* Prepare our private request structure */
   9.361 +    priv_req_id = get_id_from_freelist(import->freelist);
   9.362 +    DEBUG("Request id for fs_stat call is: %d\n", priv_req_id);
   9.363 +    fsr = &import->requests[priv_req_id];
   9.364 +    fsr->thread = current;
   9.365 +    memset(fsr->page, 0, PAGE_SIZE);
   9.366 +
   9.367 +    req = RING_GET_REQUEST(&import->ring, back_req_id);
   9.368 +    req->type = REQ_STAT;
   9.369 +    req->id = priv_req_id;
   9.370 +    req->u.fstat.fd   = fd;
   9.371 +    req->u.fstat.gref = fsr->gref;
   9.372 +
   9.373 +    /* Set blocked flag before commiting the request, thus avoiding missed
   9.374 +     * response race */
   9.375 +    block(current);
   9.376 +    commit_fsif_request(import, back_req_id);
   9.377 +    schedule();
   9.378 +    
   9.379 +    /* Read the response */
   9.380 +    ret = (int)fsr->shadow_rsp.ret_val;
   9.381 +    DEBUG("Following ret from fstat: %d\n", ret);
   9.382 +    memcpy(stat, fsr->page, sizeof(struct fsif_stat_response));
   9.383 +    add_id_to_freelist(priv_req_id, import->freelist);
   9.384 +
   9.385 +    return ret;
   9.386 +} 
   9.387 +
   9.388 +int fs_truncate(struct fs_import *import, 
   9.389 +                int fd, 
   9.390 +                int64_t length)
   9.391 +{
   9.392 +    struct fs_request *fsr;
   9.393 +    unsigned short priv_req_id;
   9.394 +    RING_IDX back_req_id; 
   9.395 +    struct fsif_request *req;
   9.396 +    int ret;
   9.397 +
   9.398 +    /* Prepare request for the backend */
   9.399 +    back_req_id = reserve_fsif_request(import);
   9.400 +    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
   9.401 +
   9.402 +    /* Prepare our private request structure */
   9.403 +    priv_req_id = get_id_from_freelist(import->freelist);
   9.404 +    DEBUG("Request id for fs_truncate call is: %d\n", priv_req_id);
   9.405 +    fsr = &import->requests[priv_req_id];
   9.406 +    fsr->thread = current;
   9.407 +
   9.408 +    req = RING_GET_REQUEST(&import->ring, back_req_id);
   9.409 +    req->type = REQ_FILE_TRUNCATE;
   9.410 +    req->id = priv_req_id;
   9.411 +    req->u.ftruncate.fd = fd;
   9.412 +    req->u.ftruncate.length = length;
   9.413 +
   9.414 +    /* Set blocked flag before commiting the request, thus avoiding missed
   9.415 +     * response race */
   9.416 +    block(current);
   9.417 +    commit_fsif_request(import, back_req_id);
   9.418 +    schedule();
   9.419 +    
   9.420 +    /* Read the response */
   9.421 +    ret = (int)fsr->shadow_rsp.ret_val;
   9.422 +    DEBUG("Following ret from ftruncate: %d\n", ret);
   9.423 +    add_id_to_freelist(priv_req_id, import->freelist);
   9.424 +
   9.425 +    return ret;
   9.426 +} 
   9.427 +
   9.428 +int fs_remove(struct fs_import *import, char *file)
   9.429 +{
   9.430 +    struct fs_request *fsr;
   9.431 +    unsigned short priv_req_id;
   9.432 +    RING_IDX back_req_id; 
   9.433 +    struct fsif_request *req;
   9.434 +    int ret;
   9.435 +
   9.436 +    /* Prepare request for the backend */
   9.437 +    back_req_id = reserve_fsif_request(import);
   9.438 +    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
   9.439 +
   9.440 +    /* Prepare our private request structure */
   9.441 +    priv_req_id = get_id_from_freelist(import->freelist);
   9.442 +    DEBUG("Request id for fs_open call is: %d\n", priv_req_id);
   9.443 +    fsr = &import->requests[priv_req_id];
   9.444 +    fsr->thread = current;
   9.445 +    sprintf(fsr->page, "%s", file);
   9.446 +
   9.447 +    req = RING_GET_REQUEST(&import->ring, back_req_id);
   9.448 +    req->type = REQ_REMOVE;
   9.449 +    req->id = priv_req_id;
   9.450 +    req->u.fremove.gref = fsr->gref;
   9.451 +
   9.452 +    /* Set blocked flag before commiting the request, thus avoiding missed
   9.453 +     * response race */
   9.454 +    block(current);
   9.455 +    commit_fsif_request(import, back_req_id);
   9.456 +    schedule();
   9.457 +    
   9.458 +    /* Read the response */
   9.459 +    ret = (int)fsr->shadow_rsp.ret_val;
   9.460 +    DEBUG("The following ret: %d\n", ret);
   9.461 +    add_id_to_freelist(priv_req_id, import->freelist);
   9.462 +
   9.463 +    return ret;
   9.464 +}
   9.465 +
   9.466 +
   9.467 +int fs_rename(struct fs_import *import, 
   9.468 +              char *old_file_name, 
   9.469 +              char *new_file_name)
   9.470 +{
   9.471 +    struct fs_request *fsr;
   9.472 +    unsigned short priv_req_id;
   9.473 +    RING_IDX back_req_id; 
   9.474 +    struct fsif_request *req;
   9.475 +    int ret;
   9.476 +    char old_header[] = "old: ";
   9.477 +    char new_header[] = "new: ";
   9.478 +
   9.479 +    /* Prepare request for the backend */
   9.480 +    back_req_id = reserve_fsif_request(import);
   9.481 +    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
   9.482 +
   9.483 +    /* Prepare our private request structure */
   9.484 +    priv_req_id = get_id_from_freelist(import->freelist);
   9.485 +    DEBUG("Request id for fs_open call is: %d\n", priv_req_id);
   9.486 +    fsr = &import->requests[priv_req_id];
   9.487 +    fsr->thread = current;
   9.488 +    sprintf(fsr->page, "%s%s%c%s%s", 
   9.489 +            old_header, old_file_name, '\0', new_header, new_file_name);
   9.490 +
   9.491 +    req = RING_GET_REQUEST(&import->ring, back_req_id);
   9.492 +    req->type = REQ_RENAME;
   9.493 +    req->id = priv_req_id;
   9.494 +    req->u.frename.gref = fsr->gref;
   9.495 +    req->u.frename.old_name_offset = strlen(old_header);
   9.496 +    req->u.frename.new_name_offset = strlen(old_header) +
   9.497 +                                     strlen(old_file_name) +
   9.498 +                                     strlen(new_header) +
   9.499 +                                     1 /* Accouning for the additional 
   9.500 +                                          end of string character */;
   9.501 +
   9.502 +    /* Set blocked flag before commiting the request, thus avoiding missed
   9.503 +     * response race */
   9.504 +    block(current);
   9.505 +    commit_fsif_request(import, back_req_id);
   9.506 +    schedule();
   9.507 +    
   9.508 +    /* Read the response */
   9.509 +    ret = (int)fsr->shadow_rsp.ret_val;
   9.510 +    DEBUG("The following ret: %d\n", ret);
   9.511 +    add_id_to_freelist(priv_req_id, import->freelist);
   9.512 +
   9.513 +    return ret;
   9.514 +}
   9.515 +
   9.516 +int fs_create(struct fs_import *import, char *name, 
   9.517 +              int8_t directory, int32_t mode)
   9.518 +{
   9.519 +    struct fs_request *fsr;
   9.520 +    unsigned short priv_req_id;
   9.521 +    RING_IDX back_req_id; 
   9.522 +    struct fsif_request *req;
   9.523 +    int ret;
   9.524 +
   9.525 +    /* Prepare request for the backend */
   9.526 +    back_req_id = reserve_fsif_request(import);
   9.527 +    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
   9.528 +
   9.529 +    /* Prepare our private request structure */
   9.530 +    priv_req_id = get_id_from_freelist(import->freelist);
   9.531 +    DEBUG("Request id for fs_create call is: %d\n", priv_req_id);
   9.532 +    fsr = &import->requests[priv_req_id];
   9.533 +    fsr->thread = current;
   9.534 +    sprintf(fsr->page, "%s", name);
   9.535 +
   9.536 +    req = RING_GET_REQUEST(&import->ring, back_req_id);
   9.537 +    req->type = REQ_CREATE;
   9.538 +    req->id = priv_req_id;
   9.539 +    req->u.fcreate.gref = fsr->gref;
   9.540 +    req->u.fcreate.directory = directory;
   9.541 +    req->u.fcreate.mode = mode;
   9.542 +
   9.543 +    /* Set blocked flag before commiting the request, thus avoiding missed
   9.544 +     * response race */
   9.545 +    block(current);
   9.546 +    commit_fsif_request(import, back_req_id);
   9.547 +    schedule();
   9.548 +    
   9.549 +    /* Read the response */
   9.550 +    ret = (int)fsr->shadow_rsp.ret_val;
   9.551 +    DEBUG("The following ret: %d\n", ret);
   9.552 +    add_id_to_freelist(priv_req_id, import->freelist);
   9.553 +
   9.554 +    return ret;
   9.555 +} 
   9.556 +
   9.557 +char** fs_list(struct fs_import *import, char *name, 
   9.558 +               int32_t offset, int32_t *nr_files, int *has_more)
   9.559 +{
   9.560 +    struct fs_request *fsr;
   9.561 +    unsigned short priv_req_id;
   9.562 +    RING_IDX back_req_id; 
   9.563 +    struct fsif_request *req;
   9.564 +    char **files, *current_file;
   9.565 +    int i;
   9.566 +
   9.567 +    DEBUG("Different masks: NR_FILES=(%llx, %d), ERROR=(%llx, %d), HAS_MORE(%llx, %d)\n",
   9.568 +            NR_FILES_MASK, NR_FILES_SHIFT, ERROR_MASK, ERROR_SHIFT, HAS_MORE_FLAG, HAS_MORE_SHIFT);
   9.569 +
   9.570 +    /* Prepare request for the backend */
   9.571 +    back_req_id = reserve_fsif_request(import);
   9.572 +    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
   9.573 +
   9.574 +    /* Prepare our private request structure */
   9.575 +    priv_req_id = get_id_from_freelist(import->freelist);
   9.576 +    DEBUG("Request id for fs_list call is: %d\n", priv_req_id);
   9.577 +    fsr = &import->requests[priv_req_id];
   9.578 +    fsr->thread = current;
   9.579 +    sprintf(fsr->page, "%s", name);
   9.580 +
   9.581 +    req = RING_GET_REQUEST(&import->ring, back_req_id);
   9.582 +    req->type = REQ_DIR_LIST;
   9.583 +    req->id = priv_req_id;
   9.584 +    req->u.flist.gref = fsr->gref;
   9.585 +    req->u.flist.offset = offset;
   9.586 +
   9.587 +    /* Set blocked flag before commiting the request, thus avoiding missed
   9.588 +     * response race */
   9.589 +    block(current);
   9.590 +    commit_fsif_request(import, back_req_id);
   9.591 +    schedule();
   9.592 +    
   9.593 +    /* Read the response */
   9.594 +    *nr_files = (fsr->shadow_rsp.ret_val & NR_FILES_MASK) >> NR_FILES_SHIFT;
   9.595 +    files = NULL;
   9.596 +    if(*nr_files <= 0) goto exit;
   9.597 +    files = malloc(sizeof(char*) * (*nr_files));
   9.598 +    current_file = fsr->page;
   9.599 +    for(i=0; i<*nr_files; i++)
   9.600 +    {
   9.601 +        files[i] = strdup(current_file); 
   9.602 +        current_file += strlen(current_file) + 1;
   9.603 +    }
   9.604 +    if(has_more != NULL)
   9.605 +        *has_more = fsr->shadow_rsp.ret_val & HAS_MORE_FLAG;
   9.606 +    add_id_to_freelist(priv_req_id, import->freelist);
   9.607 +exit:
   9.608 +    return files;
   9.609 +} 
   9.610 +
   9.611 +int fs_chmod(struct fs_import *import, int fd, int32_t mode)
   9.612 +{
   9.613 +    struct fs_request *fsr;
   9.614 +    unsigned short priv_req_id;
   9.615 +    RING_IDX back_req_id; 
   9.616 +    struct fsif_request *req;
   9.617 +    int ret;
   9.618 +
   9.619 +    /* Prepare request for the backend */
   9.620 +    back_req_id = reserve_fsif_request(import);
   9.621 +    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
   9.622 +
   9.623 +    /* Prepare our private request structure */
   9.624 +    priv_req_id = get_id_from_freelist(import->freelist);
   9.625 +    DEBUG("Request id for fs_chmod call is: %d\n", priv_req_id);
   9.626 +    fsr = &import->requests[priv_req_id];
   9.627 +    fsr->thread = current;
   9.628 +
   9.629 +    req = RING_GET_REQUEST(&import->ring, back_req_id);
   9.630 +    req->type = REQ_CHMOD;
   9.631 +    req->id = priv_req_id;
   9.632 +    req->u.fchmod.fd = fd;
   9.633 +    req->u.fchmod.mode = mode;
   9.634 +
   9.635 +    /* Set blocked flag before commiting the request, thus avoiding missed
   9.636 +     * response race */
   9.637 +    block(current);
   9.638 +    commit_fsif_request(import, back_req_id);
   9.639 +    schedule();
   9.640 +    
   9.641 +    /* Read the response */
   9.642 +    ret = (int)fsr->shadow_rsp.ret_val;
   9.643 +    DEBUG("The following returned: %d\n", ret);
   9.644 +    add_id_to_freelist(priv_req_id, import->freelist);
   9.645 +
   9.646 +    return ret;
   9.647 +} 
   9.648 +
   9.649 +int64_t fs_space(struct fs_import *import, char *location)
   9.650 +{
   9.651 +    struct fs_request *fsr;
   9.652 +    unsigned short priv_req_id;
   9.653 +    RING_IDX back_req_id; 
   9.654 +    struct fsif_request *req;
   9.655 +    int64_t ret;
   9.656 +
   9.657 +    /* Prepare request for the backend */
   9.658 +    back_req_id = reserve_fsif_request(import);
   9.659 +    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
   9.660 +
   9.661 +    /* Prepare our private request structure */
   9.662 +    priv_req_id = get_id_from_freelist(import->freelist);
   9.663 +    DEBUG("Request id for fs_space is: %d\n", priv_req_id);
   9.664 +    fsr = &import->requests[priv_req_id];
   9.665 +    fsr->thread = current;
   9.666 +    sprintf(fsr->page, "%s", location);
   9.667 +
   9.668 +    req = RING_GET_REQUEST(&import->ring, back_req_id);
   9.669 +    req->type = REQ_FS_SPACE;
   9.670 +    req->id = priv_req_id;
   9.671 +    req->u.fspace.gref = fsr->gref;
   9.672 +
   9.673 +    /* Set blocked flag before commiting the request, thus avoiding missed
   9.674 +     * response race */
   9.675 +    block(current);
   9.676 +    commit_fsif_request(import, back_req_id);
   9.677 +    schedule();
   9.678 +    
   9.679 +    /* Read the response */
   9.680 +    ret = (int64_t)fsr->shadow_rsp.ret_val;
   9.681 +    DEBUG("The following returned: %lld\n", ret);
   9.682 +    add_id_to_freelist(priv_req_id, import->freelist);
   9.683 +
   9.684 +    return ret;
   9.685 +} 
   9.686 +
   9.687 +int fs_sync(struct fs_import *import, int fd)
   9.688 +{
   9.689 +    struct fs_request *fsr;
   9.690 +    unsigned short priv_req_id;
   9.691 +    RING_IDX back_req_id; 
   9.692 +    struct fsif_request *req;
   9.693 +    int ret;
   9.694 +
   9.695 +    /* Prepare request for the backend */
   9.696 +    back_req_id = reserve_fsif_request(import);
   9.697 +    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
   9.698 +
   9.699 +    /* Prepare our private request structure */
   9.700 +    priv_req_id = get_id_from_freelist(import->freelist);
   9.701 +    DEBUG("Request id for fs_sync call is: %d\n", priv_req_id);
   9.702 +    fsr = &import->requests[priv_req_id];
   9.703 +    fsr->thread = current;
   9.704 +
   9.705 +    req = RING_GET_REQUEST(&import->ring, back_req_id);
   9.706 +    req->type = REQ_FILE_SYNC;
   9.707 +    req->id = priv_req_id;
   9.708 +    req->u.fsync.fd = fd;
   9.709 +
   9.710 +    /* Set blocked flag before commiting the request, thus avoiding missed
   9.711 +     * response race */
   9.712 +    block(current);
   9.713 +    commit_fsif_request(import, back_req_id);
   9.714 +    schedule();
   9.715 +    
   9.716 +    /* Read the response */
   9.717 +    ret = (int)fsr->shadow_rsp.ret_val;
   9.718 +    DEBUG("Close returned: %d\n", ret);
   9.719 +    add_id_to_freelist(priv_req_id, import->freelist);
   9.720 +
   9.721 +    return ret;
   9.722 +}
   9.723 +
   9.724 +
   9.725 +/******************************************************************************/
   9.726 +/*                       END OF INDIVIDUAL FILE OPERATIONS                    */
   9.727 +/******************************************************************************/
   9.728 +
   9.729 +
   9.730 +static void fsfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
   9.731 +{
   9.732 +    struct fs_import *import = (struct fs_import*)data;
   9.733 +    static int in_irq = 0;
   9.734 +    RING_IDX cons, rp;
   9.735 +    int more;
   9.736 +
   9.737 +    /* Check for non-reentrance */
   9.738 +    BUG_ON(in_irq);
   9.739 +    in_irq = 1;
   9.740 +
   9.741 +    DEBUG("Event from import [%d:%d].\n", import->dom_id, import->export_id);
   9.742 +moretodo:   
   9.743 +    rp = import->ring.sring->req_prod;
   9.744 +    rmb(); /* Ensure we see queued responses up to 'rp'. */
   9.745 +    cons = import->ring.rsp_cons;
   9.746 +    while (cons != rp)
   9.747 +    {
   9.748 +        struct fsif_response *rsp;
   9.749 +        struct fs_request *req;
   9.750 +
   9.751 +        rsp = RING_GET_RESPONSE(&import->ring, cons); 
   9.752 +        DEBUG("Response at idx=%d to request id=%d, ret_val=%lx\n", 
   9.753 +            import->ring.rsp_cons, rsp->id, rsp->ret_val);
   9.754 +        req = &import->requests[rsp->id];
   9.755 +        memcpy(&req->shadow_rsp, rsp, sizeof(struct fsif_response));
   9.756 +        DEBUG("Waking up: %s\n", req->thread->name);
   9.757 +        wake(req->thread);
   9.758 +
   9.759 +        cons++;
   9.760 +        up(&import->reqs_sem);
   9.761 +    }
   9.762 +
   9.763 +    import->ring.rsp_cons = rp;
   9.764 +    RING_FINAL_CHECK_FOR_RESPONSES(&import->ring, more);
   9.765 +    if(more) goto moretodo;
   9.766 +    
   9.767 +    in_irq = 0;
   9.768 +}
   9.769 +
   9.770 +/* Small utility function to figure out our domain id */
   9.771 +static domid_t get_self_id(void)
   9.772 +{
   9.773 +    char *dom_id;
   9.774 +    domid_t ret; 
   9.775 +
   9.776 +    BUG_ON(xenbus_read(XBT_NIL, "domid", &dom_id));
   9.777 +    sscanf(dom_id, "%d", &ret);
   9.778 +
   9.779 +    return ret;
   9.780 +}
   9.781 +
   9.782 +static void alloc_request_table(struct fs_import *import)
   9.783 +{
   9.784 +    struct fs_request *requests;
   9.785 +    int i;
   9.786 +
   9.787 +    BUG_ON(import->nr_entries <= 0);
   9.788 +    printk("Allocating request array for import %d, nr_entries = %d.\n",
   9.789 +            import->import_id, import->nr_entries);
   9.790 +    requests = xmalloc_array(struct fs_request, import->nr_entries);
   9.791 +    import->freelist = xmalloc_array(unsigned short, import->nr_entries);
   9.792 +    memset(import->freelist, 0, sizeof(unsigned short) * import->nr_entries);
   9.793 +    for(i=0; i<import->nr_entries; i++)
   9.794 +    {
   9.795 +	/* TODO: that's a lot of memory */
   9.796 +        requests[i].page = (void *)alloc_page(); 
   9.797 +        requests[i].gref = gnttab_grant_access(import->dom_id, 
   9.798 +                                               virt_to_mfn(requests[i].page),
   9.799 +                                               0);
   9.800 +        //printk("   ===>> Page=%lx, gref=%d, mfn=%lx\n", requests[i].page, requests[i].gref, virt_to_mfn(requests[i].page));
   9.801 +        add_id_to_freelist(i, import->freelist);
   9.802 +    }
   9.803 +    import->requests = requests;
   9.804 +}
   9.805 +
   9.806 +
   9.807 +/******************************************************************************/
   9.808 +/*                                FS TESTS                                    */
   9.809 +/******************************************************************************/
   9.810 +
   9.811 +
   9.812 +void test_fs_import(void *data)
   9.813 +{
   9.814 +    struct fs_import *import = (struct fs_import *)data; 
   9.815 +    int ret, fd, i;
   9.816 +    int32_t nr_files;
   9.817 +    char buffer[1024];
   9.818 +    ssize_t offset;
   9.819 +    char **files;
   9.820 +    long ret64;
   9.821 +   
   9.822 +    /* Sleep for 1s and then try to open a file */
   9.823 +    sleep(1000);
   9.824 +    ret = fs_create(import, "mini-os-created-directory", 1, 0777);
   9.825 +    printk("Directory create: %d\n", ret);
   9.826 +
   9.827 +    ret = fs_create(import, "mini-os-created-directory/mini-os-created-file", 0, 0666);
   9.828 +    printk("File create: %d\n", ret);
   9.829 +
   9.830 +    fd = fs_open(import, "mini-os-created-directory/mini-os-created-file");
   9.831 +    printk("File descriptor: %d\n", fd);
   9.832 +    if(fd < 0) return;
   9.833 +
   9.834 +    offset = 0;
   9.835 +    for(i=0; i<10; i++)
   9.836 +    {
   9.837 +        sprintf(buffer, "Current time is: %lld\n", NOW());
   9.838 +        ret = fs_write(import, fd, buffer, strlen(buffer), offset);
   9.839 +        printk("Writen current time (%d)\n", ret);
   9.840 +        if(ret < 0)
   9.841 +            return;
   9.842 +        offset += ret;
   9.843 +    }
   9.844 +
   9.845 +    ret = fs_close(import, fd);
   9.846 +    printk("Closed fd: %d, ret=%d\n", fd, ret);
   9.847 +   
   9.848 +    printk("Listing files in /\n");
   9.849 +    files = fs_list(import, "/", 0, &nr_files, NULL); 
   9.850 +    for(i=0; i<nr_files; i++)
   9.851 +        printk(" files[%d] = %s\n", i, files[i]);
   9.852 +
   9.853 +    ret64 = fs_space(import, "/");
   9.854 +    printk("Free space: %lld (=%lld Mb)\n", ret64, (ret64 >> 20));
   9.855 +    
   9.856 +}
   9.857 +
   9.858 +#if 0
   9.859 +//    char *content = (char *)alloc_page();
   9.860 +    int fd, ret;
   9.861 +//    int read;
   9.862 +    char write_string[] = "\"test data written from minios\"";
   9.863 +    struct fsif_stat_response stat;
   9.864 +    char **files;
   9.865 +    int32_t nr_files, i;
   9.866 +    int64_t ret64;
   9.867 +
   9.868 +
   9.869 +    fd = fs_open(import, "test-export-file");
   9.870 +//    read = fs_read(import, fd, content, PAGE_SIZE, 0);
   9.871 +//    printk("Read: %d bytes\n", read); 
   9.872 +//    content[read] = '\0';
   9.873 +//    printk("Value: %s\n", content);
   9.874 +    ret = fs_write(import, fd, write_string, strlen(write_string), 0);
   9.875 +    printk("Ret after write: %d\n", ret);
   9.876 +    ret = fs_stat(import, fd, &stat);
   9.877 +    printk("Ret after stat: %d\n", ret);
   9.878 +    printk(" st_mode=%o\n", stat.stat_mode);
   9.879 +    printk(" st_uid =%d\n", stat.stat_uid);
   9.880 +    printk(" st_gid =%d\n", stat.stat_gid);
   9.881 +    printk(" st_size=%ld\n", stat.stat_size);
   9.882 +    printk(" st_atime=%ld\n", stat.stat_atime);
   9.883 +    printk(" st_mtime=%ld\n", stat.stat_mtime);
   9.884 +    printk(" st_ctime=%ld\n", stat.stat_ctime);
   9.885 +    ret = fs_truncate(import, fd, 30);
   9.886 +    printk("Ret after truncate: %d\n", ret);
   9.887 +    ret = fs_remove(import, "test-to-remove/test-file");
   9.888 +    printk("Ret after remove: %d\n", ret);
   9.889 +    ret = fs_remove(import, "test-to-remove");
   9.890 +    printk("Ret after remove: %d\n", ret);
   9.891 +    ret = fs_chmod(import, fd, 0700);
   9.892 +    printk("Ret after chmod: %d\n", ret);
   9.893 +    ret = fs_sync(import, fd);
   9.894 +    printk("Ret after sync: %d\n", ret);
   9.895 +    ret = fs_close(import, fd);
   9.896 +    //ret = fs_rename(import, "test-export-file", "renamed-test-export-file");
   9.897 +    //printk("Ret after rename: %d\n", ret);
   9.898 +    ret = fs_create(import, "created-dir", 1, 0777);
   9.899 +    printk("Ret after dir create: %d\n", ret);
   9.900 +    ret = fs_create(import, "created-dir/created-file", 0, 0777);
   9.901 +    printk("Ret after file create: %d\n", ret);
   9.902 +    files = fs_list(import, "/", 15, &nr_files, NULL); 
   9.903 +    for(i=0; i<nr_files; i++)
   9.904 +        printk(" files[%d] = %s\n", i, files[i]);
   9.905 +    ret64 = fs_space(import, "created-dir");
   9.906 +    printk("Ret after space: %lld\n", ret64);
   9.907 +
   9.908 +#endif
   9.909 +
   9.910 +
   9.911 +/******************************************************************************/
   9.912 +/*                            END OF FS TESTS                                 */
   9.913 +/******************************************************************************/
   9.914 +
   9.915 +static int init_fs_import(struct fs_import *import)
   9.916 +{    
   9.917 +    char *err;
   9.918 +    xenbus_transaction_t xbt;
   9.919 +    char nodename[1024], r_nodename[1024], token[128], *message = NULL;
   9.920 +    struct fsif_sring *sring;
   9.921 +    int retry = 0;
   9.922 +    domid_t self_id;
   9.923 +
   9.924 +    printk("Initialising FS fortend to backend dom %d\n", import->dom_id);
   9.925 +    /* Allocate page for the shared ring */
   9.926 +    sring = (struct fsif_sring*) alloc_page();
   9.927 +    memset(sring, 0, PAGE_SIZE);
   9.928 +
   9.929 +    /* Init the shared ring */
   9.930 +    SHARED_RING_INIT(sring);
   9.931 +
   9.932 +    /* Init private frontend ring */
   9.933 +    FRONT_RING_INIT(&import->ring, sring, PAGE_SIZE);
   9.934 +    import->nr_entries = import->ring.nr_ents;
   9.935 +
   9.936 +    /* Allocate table of requests */
   9.937 +    alloc_request_table(import);
   9.938 +    init_SEMAPHORE(&import->reqs_sem, import->nr_entries);
   9.939 +
   9.940 +    /* Grant access to the shared ring */
   9.941 +    import->gnt_ref = gnttab_grant_access(import->dom_id, virt_to_mfn(sring), 0);
   9.942 +   
   9.943 +    /* Allocate event channel */ 
   9.944 +    BUG_ON(evtchn_alloc_unbound(import->dom_id, 
   9.945 +                                fsfront_handler, 
   9.946 +                                //ANY_CPU, 
   9.947 +                                import, 
   9.948 +                                &import->local_port));
   9.949 +
   9.950 +    
   9.951 +    self_id = get_self_id(); 
   9.952 +    /* Write the frontend info to a node in our Xenbus */
   9.953 +    sprintf(nodename, "/local/domain/%d/device/vfs/%d", 
   9.954 +                        self_id, import->import_id);
   9.955 +
   9.956 +again:    
   9.957 +    err = xenbus_transaction_start(&xbt);
   9.958 +    if (err) {
   9.959 +        printk("starting transaction\n");
   9.960 +    }
   9.961 +    
   9.962 +    err = xenbus_printf(xbt, 
   9.963 +                        nodename, 
   9.964 +                        "ring-ref",
   9.965 +                        "%u",
   9.966 +                        import->gnt_ref);
   9.967 +    if (err) {
   9.968 +        message = "writing ring-ref";
   9.969 +        goto abort_transaction;
   9.970 +    }
   9.971 +
   9.972 +    err = xenbus_printf(xbt, 
   9.973 +                        nodename,
   9.974 +                        "event-channel", 
   9.975 +                        "%u", 
   9.976 +                        import->local_port);
   9.977 +    if (err) {
   9.978 +        message = "writing event-channel";
   9.979 +        goto abort_transaction;
   9.980 +    }
   9.981 +
   9.982 +    err = xenbus_printf(xbt, nodename, "state", STATE_READY, 0xdeadbeef);
   9.983 +
   9.984 +    
   9.985 +    err = xenbus_transaction_end(xbt, 0, &retry);
   9.986 +    if (retry) {
   9.987 +            goto again;
   9.988 +        printk("completing transaction\n");
   9.989 +    }
   9.990 +
   9.991 +    /* Now, when our node is prepared we write request in the exporting domain
   9.992 +     * */
   9.993 +    printk("Our own id is %d\n", self_id);
   9.994 +    sprintf(r_nodename, 
   9.995 +            "/local/domain/%d/backend/vfs/exports/requests/%d/%d/frontend", 
   9.996 +            import->dom_id, self_id, import->export_id);
   9.997 +    BUG_ON(xenbus_write(XBT_NIL, r_nodename, nodename));
   9.998 +
   9.999 +    goto done;
  9.1000 +
  9.1001 +abort_transaction:
  9.1002 +    xenbus_transaction_end(xbt, 1, &retry);
  9.1003 +
  9.1004 +done:
  9.1005 +
  9.1006 +#define WAIT_PERIOD 10   /* Wait period in ms */    
  9.1007 +#define MAX_WAIT    10   /* Max number of WAIT_PERIODs */
  9.1008 +    import->backend = NULL;
  9.1009 +    sprintf(r_nodename, "%s/backend", nodename);
  9.1010 +   
  9.1011 +    for(retry = MAX_WAIT; retry > 0; retry--)
  9.1012 +    { 
  9.1013 +        xenbus_read(XBT_NIL, r_nodename, &import->backend);
  9.1014 +        if(import->backend)
  9.1015 +        {
  9.1016 +            printk("Backend found at %s\n", import->backend);
  9.1017 +            break;
  9.1018 +        }
  9.1019 +	sleep(WAIT_PERIOD);
  9.1020 +    }        
  9.1021 +    
  9.1022 +    if(!import->backend)
  9.1023 +    {
  9.1024 +        printk("No backend available.\n");
  9.1025 +        /* TODO - cleanup datastructures/xenbus */
  9.1026 +        return 0;
  9.1027 +    }
  9.1028 +    sprintf(r_nodename, "%s/state", import->backend);
  9.1029 +    sprintf(token, "fs-front-%d", import->import_id);
  9.1030 +    /* The token will not be unique if multiple imports are inited */
  9.1031 +    xenbus_watch_path(XBT_NIL, r_nodename/*, token*/);
  9.1032 +    xenbus_wait_for_value(/*token,*/ r_nodename, STATE_READY);
  9.1033 +    printk("Backend ready.\n");
  9.1034 +   
  9.1035 +    //create_thread("fs-tester", test_fs_import, import); 
  9.1036 +
  9.1037 +    return 1;
  9.1038 +}
  9.1039 +
  9.1040 +static void add_export(struct list_head *exports, unsigned int domid)
  9.1041 +{
  9.1042 +    char node[1024], **exports_list = NULL, *ret_msg;
  9.1043 +    int j = 0;
  9.1044 +    static int import_id = 0;
  9.1045 +
  9.1046 +    sprintf(node, "/local/domain/%d/backend/vfs/exports", domid);
  9.1047 +    ret_msg = xenbus_ls(XBT_NIL, node, &exports_list);
  9.1048 +    if (ret_msg && strcmp(ret_msg, "ENOENT"))
  9.1049 +        printk("couldn't read %s: %s\n", node, ret_msg);
  9.1050 +    while(exports_list && exports_list[j])
  9.1051 +    {
  9.1052 +        struct fs_import *import; 
  9.1053 +        int export_id = -1;
  9.1054 +        
  9.1055 +        sscanf(exports_list[j], "%d", &export_id);
  9.1056 +        if(export_id >= 0)
  9.1057 +        {
  9.1058 +            import = xmalloc(struct fs_import);
  9.1059 +            import->dom_id = domid;
  9.1060 +            import->export_id = export_id;
  9.1061 +            import->import_id = import_id++;
  9.1062 +            INIT_LIST_HEAD(&import->list);
  9.1063 +            list_add(&import->list, exports);
  9.1064 +        }
  9.1065 +        free(exports_list[j]);
  9.1066 +        j++;
  9.1067 +    }
  9.1068 +    if(exports_list)
  9.1069 +        free(exports_list);
  9.1070 +    if(ret_msg)
  9.1071 +        free(ret_msg);
  9.1072 +}
  9.1073 +
  9.1074 +#if 0
  9.1075 +static struct list_head* probe_exports(void)
  9.1076 +{
  9.1077 +    struct list_head *exports;
  9.1078 +    char **node_list = NULL, *msg = NULL;
  9.1079 +    int i = 0;
  9.1080 +
  9.1081 +    exports = xmalloc(struct list_head);
  9.1082 +    INIT_LIST_HEAD(exports);
  9.1083 +    
  9.1084 +    msg = xenbus_ls(XBT_NIL, "/local/domain", &node_list);
  9.1085 +    if(msg)
  9.1086 +    {
  9.1087 +        printk("Could not list VFS exports (%s).\n", msg);
  9.1088 +        goto exit;
  9.1089 +    }
  9.1090 +
  9.1091 +    while(node_list[i])
  9.1092 +    {
  9.1093 +        add_export(exports, atoi(node_list[i]));
  9.1094 +        free(node_list[i]);
  9.1095 +        i++;
  9.1096 +    } 
  9.1097 +
  9.1098 +exit:    
  9.1099 +    if(msg)
  9.1100 +        free(msg);
  9.1101 +    if(node_list)
  9.1102 +        free(node_list);
  9.1103 +    return exports;
  9.1104 +}
  9.1105 +#endif
  9.1106 +
  9.1107 +LIST_HEAD(exports);
  9.1108 +
  9.1109 +void init_fs_frontend(void)
  9.1110 +{
  9.1111 +    struct list_head *entry;
  9.1112 +    struct fs_import *import = NULL;
  9.1113 +    printk("Initing FS fronend(s).\n");
  9.1114 +
  9.1115 +    //exports = probe_exports();
  9.1116 +    add_export(&exports, 0);
  9.1117 +    list_for_each(entry, &exports)
  9.1118 +    {
  9.1119 +        import = list_entry(entry, struct fs_import, list);
  9.1120 +        printk("FS export [dom=%d, id=%d] found\n", 
  9.1121 +                import->dom_id, import->export_id);
  9.1122 +        init_fs_import(import);
  9.1123 +    }
  9.1124 +
  9.1125 +    fs_import = import;
  9.1126 +
  9.1127 +    if (!fs_import)
  9.1128 +	printk("No FS import\n");
  9.1129 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/extras/mini-os/include/blkfront.h	Fri Jan 18 13:49:48 2008 -0700
    10.3 @@ -0,0 +1,26 @@
    10.4 +#include <wait.h>
    10.5 +#include <xen/io/blkif.h>
    10.6 +#include <types.h>
    10.7 +struct blkfront_dev;
    10.8 +struct blkfront_aiocb
    10.9 +{
   10.10 +    struct blkfront_dev *aio_dev;
   10.11 +    uint8_t *aio_buf;
   10.12 +    size_t aio_nbytes;
   10.13 +    uint64_t aio_offset;
   10.14 +    void *data;
   10.15 +
   10.16 +    grant_ref_t gref[BLKIF_MAX_SEGMENTS_PER_REQUEST];
   10.17 +
   10.18 +    void (*aio_cb)(struct blkfront_aiocb *aiocb, int ret);
   10.19 +};
   10.20 +struct blkfront_dev *init_blkfront(char *nodename, uint64_t *sectors, unsigned *sector_size, int *mode);
   10.21 +int blkfront_open(struct blkfront_dev *dev);
   10.22 +void blkfront_aio(struct blkfront_aiocb *aiocbp, int write);
   10.23 +void blkfront_aio_read(struct blkfront_aiocb *aiocbp);
   10.24 +void blkfront_aio_write(struct blkfront_aiocb *aiocbp);
   10.25 +int blkfront_aio_poll(struct blkfront_dev *dev);
   10.26 +void blkfront_sync(struct blkfront_dev *dev);
   10.27 +void shutdown_blkfront(struct blkfront_dev *dev);
   10.28 +
   10.29 +extern struct wait_queue_head blkfront_queue;
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/extras/mini-os/include/fs.h	Fri Jan 18 13:49:48 2008 -0700
    11.3 @@ -0,0 +1,51 @@
    11.4 +#ifndef __FS_H__
    11.5 +#define __FS_H__
    11.6 +
    11.7 +#include <xen/io/fsif.h>
    11.8 +#include <semaphore.h>
    11.9 +
   11.10 +struct fs_import 
   11.11 +{
   11.12 +    domid_t dom_id;                 /* dom id of the exporting domain       */ 
   11.13 +    u16 export_id;                  /* export id (exporting dom specific)   */
   11.14 +    u16 import_id;                  /* import id (specific to this domain)  */ 
   11.15 +    struct list_head list;          /* list of all imports                  */
   11.16 +    unsigned int nr_entries;        /* Number of entries in rings & request
   11.17 +                                       array                                */
   11.18 +    struct fsif_front_ring ring;    /* frontend ring (contains shared ring) */
   11.19 +    int gnt_ref;                    /* grant reference to the shared ring   */
   11.20 +    evtchn_port_t local_port;       /* local event channel port             */
   11.21 +    char *backend;                  /* XenBus location of the backend       */
   11.22 +    struct fs_request *requests;    /* Table of requests                    */
   11.23 +    unsigned short *freelist;       /* List of free request ids             */
   11.24 +    struct semaphore reqs_sem;      /* Accounts requests resource           */
   11.25 +};
   11.26 +
   11.27 +
   11.28 +void init_fs_frontend(void);
   11.29 +
   11.30 +int fs_open(struct fs_import *import, char *file);
   11.31 +int fs_close(struct fs_import *import, int fd);
   11.32 +ssize_t fs_read(struct fs_import *import, int fd, void *buf, 
   11.33 +                ssize_t len, ssize_t offset);
   11.34 +ssize_t fs_write(struct fs_import *import, int fd, void *buf, 
   11.35 +                 ssize_t len, ssize_t offset);
   11.36 +int fs_stat(struct fs_import *import, 
   11.37 +            int fd, 
   11.38 +            struct fsif_stat_response *stat);
   11.39 +int fs_truncate(struct fs_import *import, 
   11.40 +                int fd, 
   11.41 +                int64_t length);
   11.42 +int fs_remove(struct fs_import *import, char *file);
   11.43 +int fs_rename(struct fs_import *import, 
   11.44 +              char *old_file_name, 
   11.45 +              char *new_file_name);
   11.46 +int fs_create(struct fs_import *import, char *name, 
   11.47 +              int8_t directory, int32_t mode);
   11.48 +char** fs_list(struct fs_import *import, char *name, 
   11.49 +               int32_t offset, int32_t *nr_files, int *has_more);
   11.50 +int fs_chmod(struct fs_import *import, int fd, int32_t mode);
   11.51 +int64_t fs_space(struct fs_import *import, char *location);
   11.52 +int fs_sync(struct fs_import *import, int fd);
   11.53 +
   11.54 +#endif
    12.1 --- a/extras/mini-os/include/ia64/arch_mm.h	Thu Jan 17 12:17:14 2008 -0700
    12.2 +++ b/extras/mini-os/include/ia64/arch_mm.h	Fri Jan 18 13:49:48 2008 -0700
    12.3 @@ -36,4 +36,8 @@
    12.4  #define STACK_SIZE_PAGE_ORDER   1
    12.5  #define STACK_SIZE              (PAGE_SIZE * (1 << STACK_SIZE_PAGE_ORDER))
    12.6  
    12.7 +#define map_frames(f, n) map_frames_ex(f, n, 1, 0, 1, DOMID_SELF, 0, 0)
    12.8 +/* TODO */
    12.9 +#define map_zero(n, a) map_frames_ex(NULL, n, 0, 0, a, DOMID_SELF, 0, 0)
   12.10 +
   12.11  #endif /* __ARCH_MM_H__ */
    13.1 --- a/extras/mini-os/include/mm.h	Thu Jan 17 12:17:14 2008 -0700
    13.2 +++ b/extras/mini-os/include/mm.h	Fri Jan 18 13:49:48 2008 -0700
    13.3 @@ -57,6 +57,9 @@ void arch_init_demand_mapping_area(unsig
    13.4  void arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p);
    13.5  void arch_init_p2m(unsigned long max_pfn_p);
    13.6  
    13.7 -void *map_frames(unsigned long *f, unsigned long n);
    13.8 +/* map f[i*stride]+i*increment for i in 0..n-1, aligned on alignment pages */
    13.9 +void *map_frames_ex(unsigned long *f, unsigned long n, unsigned long stride,
   13.10 +	unsigned long increment, unsigned long alignment, domid_t id,
   13.11 +	int may_fail, unsigned long prot);
   13.12  
   13.13  #endif /* _MM_H_ */
    14.1 --- a/extras/mini-os/include/types.h	Thu Jan 17 12:17:14 2008 -0700
    14.2 +++ b/extras/mini-os/include/types.h	Fri Jan 18 13:49:48 2008 -0700
    14.3 @@ -57,6 +57,13 @@ typedef unsigned long       uintptr_t;
    14.4  typedef struct { unsigned long pte; } pte_t;
    14.5  #endif /* __i386__ || __x86_64__ */
    14.6  
    14.7 +#if !defined(CONFIG_X86_PAE)
    14.8 +#define __pte(x) ((pte_t) { (x) } )
    14.9 +#else
   14.10 +#define __pte(x) ({ unsigned long long _x = (x);        \
   14.11 +    ((pte_t) {(unsigned long)(_x), (unsigned long)(_x>>32)}); })
   14.12 +#endif
   14.13 +
   14.14  typedef  u8 uint8_t;
   14.15  typedef  s8 int8_t;
   14.16  typedef u16 uint16_t;
   14.17 @@ -69,4 +76,7 @@ typedef s64 int64_t;
   14.18  
   14.19  #define INT_MAX         ((int)(~0U>>1))
   14.20  #define UINT_MAX            (~0U)
   14.21 +
   14.22 +typedef long ssize_t;
   14.23 +typedef unsigned long size_t;
   14.24  #endif /* _TYPES_H_ */
    15.1 --- a/extras/mini-os/include/x86/arch_mm.h	Thu Jan 17 12:17:14 2008 -0700
    15.2 +++ b/extras/mini-os/include/x86/arch_mm.h	Fri Jan 18 13:49:48 2008 -0700
    15.3 @@ -144,12 +144,14 @@ typedef unsigned long pgentry_t;
    15.4  
    15.5  #if defined(__i386__)
    15.6  #define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
    15.7 +#define L1_PROT_RO (_PAGE_PRESENT|_PAGE_ACCESSED)
    15.8  #define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY |_PAGE_USER)
    15.9  #if defined(CONFIG_X86_PAE)
   15.10  #define L3_PROT (_PAGE_PRESENT)
   15.11  #endif /* CONFIG_X86_PAE */
   15.12  #elif defined(__x86_64__)
   15.13  #define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_USER)
   15.14 +#define L1_PROT_RO (_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_USER)
   15.15  #define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
   15.16  #define L3_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
   15.17  #define L4_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
   15.18 @@ -189,7 +191,8 @@ typedef unsigned long maddr_t;
   15.19  #endif
   15.20  
   15.21  extern unsigned long *phys_to_machine_mapping;
   15.22 -extern char _text, _etext, _edata, _end;
   15.23 +extern char _text, _etext, _erodata, _edata, _end;
   15.24 +extern unsigned long mfn_zero;
   15.25  #define pfn_to_mfn(_pfn) (phys_to_machine_mapping[(_pfn)])
   15.26  static __inline__ maddr_t phys_to_machine(paddr_t phys)
   15.27  {
   15.28 @@ -223,5 +226,7 @@ static __inline__ paddr_t machine_to_phy
   15.29  #define pte_to_mfn(_pte)           (((_pte) & (PADDR_MASK&PAGE_MASK)) >> L1_PAGETABLE_SHIFT)
   15.30  #define pte_to_virt(_pte)          to_virt(mfn_to_pfn(pte_to_mfn(_pte)) << PAGE_SHIFT)
   15.31  
   15.32 +#define map_frames(f, n) map_frames_ex(f, n, 1, 0, 1, DOMID_SELF, 0, L1_PROT)
   15.33 +#define map_zero(n, a) map_frames_ex(&mfn_zero, n, 0, 0, a, DOMID_SELF, 0, L1_PROT_RO)
   15.34  
   15.35  #endif /* _ARCH_MM_H_ */
    16.1 --- a/extras/mini-os/include/x86/traps.h	Thu Jan 17 12:17:14 2008 -0700
    16.2 +++ b/extras/mini-os/include/x86/traps.h	Fri Jan 18 13:49:48 2008 -0700
    16.3 @@ -70,4 +70,8 @@ struct pt_regs {
    16.4  
    16.5  void dump_regs(struct pt_regs *regs);
    16.6  
    16.7 +#define TRAP_PF_PROT   0x1
    16.8 +#define TRAP_PF_WRITE  0x2
    16.9 +#define TRAP_PF_USER   0x4
   16.10 +
   16.11  #endif /* _TRAPS_H_ */
    17.1 --- a/extras/mini-os/kernel.c	Thu Jan 17 12:17:14 2008 -0700
    17.2 +++ b/extras/mini-os/kernel.c	Fri Jan 18 13:49:48 2008 -0700
    17.3 @@ -38,6 +38,7 @@
    17.4  #include <xenbus.h>
    17.5  #include <gnttab.h>
    17.6  #include <netfront.h>
    17.7 +#include <fs.h>
    17.8  #include <xen/features.h>
    17.9  #include <xen/version.h>
   17.10  
   17.11 @@ -85,6 +86,11 @@ static void netfront_thread(void *p)
   17.12      init_netfront(NULL, NULL, NULL);
   17.13  }
   17.14  
   17.15 +static void fs_thread(void *p)
   17.16 +{
   17.17 +    init_fs_frontend();
   17.18 +}
   17.19 +
   17.20  /* This should be overridden by the application we are linked against. */
   17.21  __attribute__((weak)) int app_main(start_info_t *si)
   17.22  {
   17.23 @@ -92,6 +98,7 @@ static void netfront_thread(void *p)
   17.24      create_thread("xenbus_tester", xenbus_tester, si);
   17.25      create_thread("periodic_thread", periodic_thread, si);
   17.26      create_thread("netfront", netfront_thread, si);
   17.27 +    create_thread("fs-frontend", fs_thread, si);
   17.28      return 0;
   17.29  }
   17.30  
    18.1 --- a/tools/examples/network-nat	Thu Jan 17 12:17:14 2008 -0700
    18.2 +++ b/tools/examples/network-nat	Fri Jan 18 13:49:48 2008 -0700
    18.3 @@ -43,9 +43,9 @@ fi
    18.4  
    18.5  function dhcp_start()
    18.6  {
    18.7 -  if ! grep -q "subnet 192.0.2.0" "$dhcpd_conf_file"
    18.8 +  if ! grep -q "subnet 10.0.0.0" "$dhcpd_conf_file"
    18.9    then
   18.10 -    echo >>"$dhcpd_conf_file" "subnet 192.0.2.0 netmask 255.255.255.0 {}"
   18.11 +    echo >>"$dhcpd_conf_file" "subnet 10.0.0.0 netmask 255.255.0.0 {}"
   18.12    fi
   18.13  
   18.14    "$dhcpd_init_file" restart
   18.15 @@ -55,7 +55,7 @@ function dhcp_start()
   18.16  function dhcp_stop()
   18.17  {
   18.18    local tmpfile=$(mktemp)
   18.19 -  grep -v "subnet 192.0.2.0" "$dhcpd_conf_file" >"$tmpfile"
   18.20 +  grep -v "subnet 10.0.0.0" "$dhcpd_conf_file" >"$tmpfile"
   18.21    if diff "$tmpfile" "$dhcpd_conf_file" >&/dev/null
   18.22    then
   18.23      rm "$tmpfile"
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/tools/fs-back/Makefile	Fri Jan 18 13:49:48 2008 -0700
    19.3 @@ -0,0 +1,40 @@
    19.4 +XEN_ROOT = ../..
    19.5 +include $(XEN_ROOT)/tools/Rules.mk
    19.6 +
    19.7 +INCLUDES += -I.. -I../lib
    19.8 +
    19.9 +IBIN         = fs-backend 
   19.10 +INST_DIR     = /usr/sbin
   19.11 +
   19.12 +CFLAGS   += -Werror
   19.13 +CFLAGS   += -Wno-unused
   19.14 +CFLAGS   += -fno-strict-aliasing
   19.15 +CFLAGS   += -I $(XEN_LIBXC)
   19.16 +CFLAGS   += $(INCLUDES) -I. -I../xenstore 
   19.17 +CFLAGS   += -D_GNU_SOURCE
   19.18 +
   19.19 +# Get gcc to generate the dependencies for us.
   19.20 +CFLAGS   += -Wp,-MD,.$(@F).d
   19.21 +DEPS      = .*.d
   19.22 +
   19.23 +LIBS      := -L. -L.. -L../lib
   19.24 +LIBS      += -L$(XEN_LIBXC)
   19.25 +LIBS      += -lxenctrl -lpthread -lrt 
   19.26 +LIBS      += -L$(XEN_XENSTORE) -lxenstore
   19.27 +
   19.28 +OBJS	  := fs-xenbus.o fs-ops.o
   19.29 +
   19.30 +all: $(IBIN)
   19.31 +
   19.32 +fs-backend: $(OBJS) fs-backend.c
   19.33 +	$(CC) $(CFLAGS) -o fs-backend $(OBJS) $(LIBS) fs-backend.c
   19.34 +
   19.35 +install: all
   19.36 +	$(INSTALL_PROG) $(IBIN) $(DESTDIR)$(INST_DIR)
   19.37 +
   19.38 +clean:
   19.39 +	rm -rf *.o *~ $(DEPS) xen $(IBIN) $(LIB)
   19.40 +
   19.41 +.PHONY: clean install
   19.42 +
   19.43 +-include $(DEPS)
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/tools/fs-back/fs-backend.c	Fri Jan 18 13:49:48 2008 -0700
    20.3 @@ -0,0 +1,346 @@
    20.4 +#undef NDEBUG
    20.5 +#include <stdio.h>
    20.6 +#include <string.h>
    20.7 +#include <assert.h>
    20.8 +#include <malloc.h>
    20.9 +#include <pthread.h>
   20.10 +#include <xenctrl.h>
   20.11 +#include <aio.h>
   20.12 +#include <sys/mman.h>
   20.13 +#include <sys/select.h>
   20.14 +#include <xen/io/ring.h>
   20.15 +#include "fs-backend.h"
   20.16 +
   20.17 +struct xs_handle *xsh = NULL;
   20.18 +static struct fs_export *fs_exports = NULL;
   20.19 +static int export_id = 0;
   20.20 +static int mount_id = 0;
   20.21 +
   20.22 +void dispatch_response(struct mount *mount, int priv_req_id)
   20.23 +{
   20.24 +    int i;
   20.25 +    struct fs_op *op;
   20.26 +    struct fs_request *req = &mount->requests[priv_req_id];
   20.27 +
   20.28 +    for(i=0;;i++)
   20.29 +    {
   20.30 +        op = fsops[i];
   20.31 +        /* We should dispatch a response before reaching the end of the array */
   20.32 +        assert(op != NULL);
   20.33 +        if(op->type == req->req_shadow.type)
   20.34 +        {
   20.35 +            printf("Found op for type=%d\n", op->type);
   20.36 +            /* There needs to be a response handler */
   20.37 +            assert(op->response_handler != NULL);
   20.38 +            op->response_handler(mount, req);
   20.39 +            break;
   20.40 +        }
   20.41 +    }
   20.42 +
   20.43 +    req->active = 0;
   20.44 +    add_id_to_freelist(priv_req_id, mount->freelist);
   20.45 +}
   20.46 +
   20.47 +static void handle_aio_events(struct mount *mount)
   20.48 +{
   20.49 +    int fd, ret, count, i, notify;
   20.50 +    evtchn_port_t port;
   20.51 +    /* AIO control block for the evtchn file destriptor */
   20.52 +    struct aiocb evtchn_cb;
   20.53 +    const struct aiocb * cb_list[mount->nr_entries];
   20.54 +    int request_ids[mount->nr_entries];
   20.55 +
   20.56 +    /* Prepare the AIO control block for evtchn */ 
   20.57 +    fd = xc_evtchn_fd(mount->evth); 
   20.58 +    bzero(&evtchn_cb, sizeof(struct aiocb));
   20.59 +    evtchn_cb.aio_fildes = fd;
   20.60 +    evtchn_cb.aio_nbytes = sizeof(port);
   20.61 +    evtchn_cb.aio_buf = &port;
   20.62 +    assert(aio_read(&evtchn_cb) == 0);
   20.63 +
   20.64 +wait_again:   
   20.65 +    /* Create list of active AIO requests */
   20.66 +    count = 0;
   20.67 +    for(i=0; i<mount->nr_entries; i++)
   20.68 +        if(mount->requests[i].active)
   20.69 +        {
   20.70 +            cb_list[count] = &mount->requests[i].aiocb;
   20.71 +            request_ids[count] = i;
   20.72 +            count++;
   20.73 +        }
   20.74 +    /* Add the event channel at the end of the list. Event channel needs to be
   20.75 +     * handled last as it exits this function. */
   20.76 +    cb_list[count] = &evtchn_cb;
   20.77 +    request_ids[count] = -1;
   20.78 +    count++;
   20.79 +
   20.80 +    /* Block till an AIO requset finishes, or we get an event */ 
   20.81 +    while(1) {
   20.82 +	int ret = aio_suspend(cb_list, count, NULL);
   20.83 +	if (!ret)
   20.84 +	    break;
   20.85 +	assert(errno == EINTR);
   20.86 +    }
   20.87 +    for(i=0; i<count; i++)
   20.88 +        if(aio_error(cb_list[i]) != EINPROGRESS)
   20.89 +        {
   20.90 +            if(request_ids[i] >= 0)
   20.91 +                dispatch_response(mount, request_ids[i]);
   20.92 +            else
   20.93 +                goto read_event_channel;
   20.94 +        }
   20.95 + 
   20.96 +    RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&mount->ring, notify);
   20.97 +    printf("Pushed responces and notify=%d\n", notify);
   20.98 +    if(notify)
   20.99 +        xc_evtchn_notify(mount->evth, mount->local_evtchn);
  20.100 +    
  20.101 +    goto wait_again;
  20.102 +
  20.103 +read_event_channel:    
  20.104 +    assert(aio_return(&evtchn_cb) == sizeof(evtchn_port_t)); 
  20.105 +    assert(xc_evtchn_unmask(mount->evth, mount->local_evtchn) >= 0);
  20.106 +}
  20.107 +
  20.108 +
  20.109 +void allocate_request_array(struct mount *mount)
  20.110 +{
  20.111 +    int i, nr_entries = mount->nr_entries;
  20.112 +    struct fs_request *requests;
  20.113 +    unsigned short *freelist;
  20.114 +    
  20.115 +    requests = malloc(sizeof(struct fs_request) *nr_entries);
  20.116 +    freelist = malloc(sizeof(unsigned short) * nr_entries); 
  20.117 +    memset(requests, 0, sizeof(struct fs_request) * nr_entries);
  20.118 +    memset(freelist, 0, sizeof(unsigned short) * nr_entries);
  20.119 +    for(i=0; i< nr_entries; i++)
  20.120 +    {
  20.121 +        requests[i].active = 0; 
  20.122 +        add_id_to_freelist(i, freelist);
  20.123 +    }
  20.124 +    mount->requests = requests;
  20.125 +    mount->freelist = freelist;
  20.126 +}
  20.127 +
  20.128 +
  20.129 +void* handle_mount(void *data)
  20.130 +{
  20.131 +    int more, notify;
  20.132 +    struct mount *mount = (struct mount *)data;
  20.133 +    
  20.134 +    printf("Starting a thread for mount: %d\n", mount->mount_id);
  20.135 +    allocate_request_array(mount);
  20.136 +
  20.137 +    for(;;)
  20.138 +    {
  20.139 +        int nr_consumed=0;
  20.140 +        RING_IDX cons, rp;
  20.141 +        struct fsif_request *req;
  20.142 +
  20.143 +        handle_aio_events(mount);
  20.144 +moretodo:
  20.145 +        rp = mount->ring.sring->req_prod;
  20.146 +        rmb(); /* Ensure we see queued requests up to 'rp'. */
  20.147 +                
  20.148 +        while ((cons = mount->ring.req_cons) != rp)
  20.149 +        {
  20.150 +            int i;
  20.151 +            struct fs_op *op;
  20.152 +
  20.153 +            printf("Got a request at %d\n", cons);
  20.154 +            req = RING_GET_REQUEST(&mount->ring, cons);
  20.155 +            printf("Request type=%d\n", req->type); 
  20.156 +            for(i=0;;i++)
  20.157 +            {
  20.158 +                op = fsops[i];
  20.159 +                if(op == NULL)
  20.160 +                {
  20.161 +                    /* We've reached the end of the array, no appropirate
  20.162 +                     * handler found. Warn, ignore and continue. */
  20.163 +                    printf("WARN: Unknown request type: %d\n", req->type);
  20.164 +                    mount->ring.req_cons++; 
  20.165 +                    break;
  20.166 +                }
  20.167 +                if(op->type == req->type)
  20.168 +                {
  20.169 +                    /* There needs to be a dispatch handler */
  20.170 +                    assert(op->dispatch_handler != NULL);
  20.171 +                    op->dispatch_handler(mount, req);
  20.172 +                    break;
  20.173 +                }
  20.174 +             }
  20.175 +
  20.176 +            nr_consumed++;
  20.177 +        }
  20.178 +        printf("Backend consumed: %d requests\n", nr_consumed);
  20.179 +        RING_FINAL_CHECK_FOR_REQUESTS(&mount->ring, more);
  20.180 +        if(more) goto moretodo;
  20.181 +
  20.182 +        RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&mount->ring, notify);
  20.183 +        printf("Pushed responces and notify=%d\n", notify);
  20.184 +        if(notify)
  20.185 +            xc_evtchn_notify(mount->evth, mount->local_evtchn);
  20.186 +    }
  20.187 + 
  20.188 +    printf("Destroying thread for mount: %d\n", mount->mount_id);
  20.189 +    xc_gnttab_munmap(mount->gnth, mount->ring.sring, 1);
  20.190 +    xc_gnttab_close(mount->gnth);
  20.191 +    xc_evtchn_unbind(mount->evth, mount->local_evtchn);
  20.192 +    xc_evtchn_close(mount->evth);
  20.193 +    free(mount->frontend);
  20.194 +    pthread_exit(NULL);
  20.195 +}
  20.196 +
  20.197 +static void handle_connection(int frontend_dom_id, int export_id, char *frontend)
  20.198 +{
  20.199 +    struct mount *mount;
  20.200 +    struct fs_export *export;
  20.201 +    int evt_port;
  20.202 +    pthread_t handling_thread;
  20.203 +    struct fsif_sring *sring;
  20.204 +
  20.205 +    printf("Handling connection from dom=%d, for export=%d\n", 
  20.206 +            frontend_dom_id, export_id);
  20.207 +    /* Try to find the export on the list */
  20.208 +    export = fs_exports;
  20.209 +    while(export)
  20.210 +    {
  20.211 +        if(export->export_id == export_id)
  20.212 +            break;
  20.213 +        export = export->next;
  20.214 +    }
  20.215 +    if(!export)
  20.216 +    {
  20.217 +        printf("Could not find the export (the id is unknown).\n");
  20.218 +        return;
  20.219 +    }
  20.220 +
  20.221 +    mount = (struct mount*)malloc(sizeof(struct mount));
  20.222 +    mount->dom_id = frontend_dom_id;
  20.223 +    mount->export = export;
  20.224 +    mount->mount_id = mount_id++;
  20.225 +    xenbus_read_mount_request(mount, frontend);
  20.226 +    printf("Frontend found at: %s (gref=%d, evtchn=%d)\n", 
  20.227 +            mount->frontend, mount->gref, mount->remote_evtchn);
  20.228 +    xenbus_write_backend_node(mount);
  20.229 +    mount->evth = -1;
  20.230 +    mount->evth = xc_evtchn_open(); 
  20.231 +    assert(mount->evth != -1);
  20.232 +    mount->local_evtchn = -1;
  20.233 +    mount->local_evtchn = xc_evtchn_bind_interdomain(mount->evth, 
  20.234 +                                                     mount->dom_id, 
  20.235 +                                                     mount->remote_evtchn);
  20.236 +    assert(mount->local_evtchn != -1);
  20.237 +    mount->gnth = -1;
  20.238 +    mount->gnth = xc_gnttab_open(); 
  20.239 +    assert(mount->gnth != -1);
  20.240 +    sring = xc_gnttab_map_grant_ref(mount->gnth,
  20.241 +                                    mount->dom_id,
  20.242 +                                    mount->gref,
  20.243 +                                    PROT_READ | PROT_WRITE);
  20.244 +    BACK_RING_INIT(&mount->ring, sring, PAGE_SIZE);
  20.245 +    mount->nr_entries = mount->ring.nr_ents; 
  20.246 +    xenbus_write_backend_ready(mount);
  20.247 +
  20.248 +    pthread_create(&handling_thread, NULL, &handle_mount, mount);
  20.249 +}
  20.250 +
  20.251 +static void await_connections(void)
  20.252 +{
  20.253 +    int fd, ret, dom_id, export_id; 
  20.254 +    fd_set fds;
  20.255 +    char **watch_paths;
  20.256 +    unsigned int len;
  20.257 +    char d;
  20.258 +
  20.259 +    assert(xsh != NULL);
  20.260 +    fd = xenbus_get_watch_fd(); 
  20.261 +    /* Infinite watch loop */
  20.262 +    do {
  20.263 +	FD_ZERO(&fds);
  20.264 +	FD_SET(fd, &fds);
  20.265 +        ret = select(fd+1, &fds, NULL, NULL, NULL);
  20.266 +        assert(ret == 1);
  20.267 +        watch_paths = xs_read_watch(xsh, &len);
  20.268 +        assert(len == 2);
  20.269 +        assert(strcmp(watch_paths[1], "conn-watch") == 0);
  20.270 +        dom_id = -1;
  20.271 +        export_id = -1;
  20.272 +	d = 0;
  20.273 +        printf("Path changed %s\n", watch_paths[0]);
  20.274 +        sscanf(watch_paths[0], WATCH_NODE"/%d/%d/fronten%c", 
  20.275 +                &dom_id, &export_id, &d);
  20.276 +        if((dom_id >= 0) && (export_id >= 0) && d == 'd') {
  20.277 +	    char *frontend = xs_read(xsh, XBT_NULL, watch_paths[0], NULL);
  20.278 +	    if (frontend) {
  20.279 +		handle_connection(dom_id, export_id, frontend);
  20.280 +		xs_rm(xsh, XBT_NULL, watch_paths[0]);
  20.281 +	    }
  20.282 +	}
  20.283 +next_select:        
  20.284 +        printf("Awaiting next connection.\n");
  20.285 +        /* TODO - we need to figure out what to free */
  20.286 +	free(watch_paths);
  20.287 +    } while (1);
  20.288 +}
  20.289 +
  20.290 +struct fs_export* create_export(char *name, char *export_path)
  20.291 +{
  20.292 +    struct fs_export *curr_export, **last_export;
  20.293 +
  20.294 +    /* Create export structure */
  20.295 +    curr_export = (struct fs_export *)malloc(sizeof(struct fs_export));
  20.296 +    curr_export->name = name;
  20.297 +    curr_export->export_path = export_path;
  20.298 +    curr_export->export_id = export_id++;
  20.299 +    /* Thread it onto the list */
  20.300 +    curr_export->next = NULL;
  20.301 +    last_export = &fs_exports;
  20.302 +    while(*last_export)
  20.303 +        last_export = &((*last_export)->next);
  20.304 +    *last_export = curr_export;
  20.305 +
  20.306 +    return curr_export;
  20.307 +}
  20.308 +
  20.309 +
  20.310 +int main(void)
  20.311 +{
  20.312 +    struct fs_export *export;
  20.313 +
  20.314 +    /* Open the connection to XenStore first */
  20.315 +    xsh = xs_domain_open();
  20.316 +    assert(xsh != NULL);
  20.317 +    xs_rm(xsh, XBT_NULL, ROOT_NODE);
  20.318 +    /* Create watch node */
  20.319 +    xenbus_create_request_node();
  20.320 +    
  20.321 +    /* Create & register the default export */
  20.322 +    export = create_export("default", "/exports");
  20.323 +    xenbus_register_export(export);
  20.324 +
  20.325 +    await_connections();
  20.326 +    /* Close the connection to XenStore when we are finished with everything */
  20.327 +    xs_daemon_close(xsh);
  20.328 +#if 0
  20.329 +    int xc_handle;
  20.330 +    char *shared_page;
  20.331 +    int prot = PROT_READ | PROT_WRITE;
  20.332 +  
  20.333 +    xc_handle = xc_gnttab_open();
  20.334 +    printf("Main fn.\n");
  20.335 +
  20.336 +    shared_page = xc_gnttab_map_grant_ref(xc_handle,
  20.337 +                                           7,
  20.338 +                                           2047,
  20.339 +                                           prot);
  20.340 +    
  20.341 +    shared_page[20] = '\0';
  20.342 +    printf("Current content of the page = %s\n", shared_page);
  20.343 +    sprintf(shared_page, "%s", "Haha dirty page now! Very bad page.");
  20.344 +    xc_gnttab_munmap(xc_handle, shared_page, 1);
  20.345 +    xc_gnttab_close(xc_handle);
  20.346 +    unrelated next line, saved for later convinience    
  20.347 +    xc_evtchn_notify(mount->evth, mount->local_evtchn);
  20.348 +#endif
  20.349 +}
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/tools/fs-back/fs-backend.h	Fri Jan 18 13:49:48 2008 -0700
    21.3 @@ -0,0 +1,86 @@
    21.4 +#ifndef __LIB_FS_BACKEND__
    21.5 +#define __LIB_FS_BACKEND__
    21.6 +
    21.7 +#include <aio.h>
    21.8 +#include <xs.h>
    21.9 +#include <xen/grant_table.h>
   21.10 +#include <xen/event_channel.h>
   21.11 +#include <xen/io/ring.h>
   21.12 +#include <xen/io/fsif.h>
   21.13 +
   21.14 +#define ROOT_NODE           "backend/vfs"
   21.15 +#define EXPORTS_SUBNODE     "exports"
   21.16 +#define EXPORTS_NODE        ROOT_NODE"/"EXPORTS_SUBNODE
   21.17 +#define WATCH_NODE          EXPORTS_NODE"/requests"
   21.18 +
   21.19 +struct fs_export
   21.20 +{
   21.21 +    int export_id;
   21.22 +    char *export_path;
   21.23 +    char *name;
   21.24 +    struct fs_export *next; 
   21.25 +};
   21.26 +
   21.27 +struct fs_request
   21.28 +{
   21.29 +    int active;
   21.30 +    void *page;                         /* Pointer to mapped grant */
   21.31 +    struct fsif_request req_shadow;
   21.32 +    struct aiocb aiocb; 
   21.33 +};
   21.34 +
   21.35 +
   21.36 +struct mount
   21.37 +{
   21.38 +    struct fs_export *export;
   21.39 +    int dom_id;
   21.40 +    char *frontend;
   21.41 +    int mount_id;                     /* = backend id */
   21.42 +    grant_ref_t gref;
   21.43 +    evtchn_port_t remote_evtchn;
   21.44 +    int evth;                         /* Handle to the event channel */
   21.45 +    evtchn_port_t local_evtchn;
   21.46 +    int gnth;
   21.47 +    struct fsif_back_ring ring;
   21.48 +    int nr_entries;
   21.49 +    struct fs_request *requests;
   21.50 +    unsigned short *freelist;
   21.51 +};
   21.52 +
   21.53 +
   21.54 +/* Handle to XenStore driver */
   21.55 +extern struct xs_handle *xsh;
   21.56 +
   21.57 +bool xenbus_create_request_node(void);
   21.58 +int xenbus_register_export(struct fs_export *export);
   21.59 +int xenbus_get_watch_fd(void);
   21.60 +void xenbus_read_mount_request(struct mount *mount, char *frontend);
   21.61 +void xenbus_write_backend_node(struct mount *mount);
   21.62 +void xenbus_write_backend_ready(struct mount *mount);
   21.63 +
   21.64 +/* File operations, implemented in fs-ops.c */
   21.65 +struct fs_op
   21.66 +{
   21.67 +    int type;       /* Type of request (from fsif.h) this handlers 
   21.68 +                       are responsible for */
   21.69 +    void (*dispatch_handler)(struct mount *mount, struct fsif_request *req);
   21.70 +    void (*response_handler)(struct mount *mount, struct fs_request *req);
   21.71 +};
   21.72 +
   21.73 +/* This NULL terminated array of all file requests handlers */
   21.74 +extern struct fs_op *fsops[];
   21.75 +
   21.76 +static inline void add_id_to_freelist(unsigned int id,unsigned short* freelist)
   21.77 +{
   21.78 +    freelist[id] = freelist[0];
   21.79 +    freelist[0]  = id;
   21.80 +}
   21.81 +
   21.82 +static inline unsigned short get_id_from_freelist(unsigned short* freelist)
   21.83 +{
   21.84 +    unsigned int id = freelist[0];
   21.85 +    freelist[0] = freelist[id];
   21.86 +    return id;
   21.87 +}
   21.88 +
   21.89 +#endif /* __LIB_FS_BACKEND__ */
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/tools/fs-back/fs-ops.c	Fri Jan 18 13:49:48 2008 -0700
    22.3 @@ -0,0 +1,658 @@
    22.4 +#undef NDEBUG
    22.5 +#include <stdio.h>
    22.6 +#include <aio.h>
    22.7 +#include <string.h>
    22.8 +#include <assert.h>
    22.9 +#include <fcntl.h>
   22.10 +#include <dirent.h>
   22.11 +#include <inttypes.h>
   22.12 +#include <xenctrl.h>
   22.13 +#include <sys/mman.h>
   22.14 +#include <sys/types.h>
   22.15 +#include <sys/stat.h>
   22.16 +#include <sys/vfs.h>
   22.17 +#include <sys/mount.h>
   22.18 +#include <unistd.h>
   22.19 +#include "fs-backend.h"
   22.20 +
   22.21 +/* For debugging only */
   22.22 +#include <sys/time.h>
   22.23 +#include <time.h>
   22.24 +
   22.25 +
   22.26 +#define BUFFER_SIZE 1024
   22.27 +
   22.28 +
   22.29 +unsigned short get_request(struct mount *mount, struct fsif_request *req)
   22.30 +{
   22.31 +    unsigned short id = get_id_from_freelist(mount->freelist); 
   22.32 +
   22.33 +    printf("Private Request id: %d\n", id);
   22.34 +    memcpy(&mount->requests[id].req_shadow, req, sizeof(struct fsif_request));
   22.35 +    mount->requests[id].active = 1;
   22.36 +
   22.37 +    return id;
   22.38 +}
   22.39 +
   22.40 +
   22.41 +void dispatch_file_open(struct mount *mount, struct fsif_request *req)
   22.42 +{
   22.43 +    char *file_name, full_path[BUFFER_SIZE];
   22.44 +    int fd;
   22.45 +    struct timeval tv1, tv2;
   22.46 +    RING_IDX rsp_idx;
   22.47 +    fsif_response_t *rsp;
   22.48 +    uint16_t req_id;
   22.49 +
   22.50 +    printf("Dispatching file open operation (gref=%d).\n", req->u.fopen.gref);
   22.51 +    /* Read the request, and open file */
   22.52 +    file_name = xc_gnttab_map_grant_ref(mount->gnth,
   22.53 +                                        mount->dom_id,
   22.54 +                                        req->u.fopen.gref,
   22.55 +                                        PROT_READ);
   22.56 +   
   22.57 +    req_id = req->id;
   22.58 +    printf("File open issued for %s\n", file_name); 
   22.59 +    assert(BUFFER_SIZE > 
   22.60 +           strlen(file_name) + strlen(mount->export->export_path) + 1); 
   22.61 +    sprintf(full_path, "%s/%s", mount->export->export_path, file_name);
   22.62 +    assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
   22.63 +    printf("Issuing open for %s\n", full_path);
   22.64 +    fd = open(full_path, O_RDWR);
   22.65 +    printf("Got FD: %d\n", fd);
   22.66 +    /* We can advance the request consumer index, from here on, the request
   22.67 +     * should not be used (it may be overrinden by a response) */
   22.68 +    mount->ring.req_cons++;
   22.69 +
   22.70 +
   22.71 +    /* Get a response from the ring */
   22.72 +    rsp_idx = mount->ring.rsp_prod_pvt++;
   22.73 +    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   22.74 +    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
   22.75 +    rsp->id = req_id; 
   22.76 +    rsp->ret_val = (uint64_t)fd;
   22.77 +}
   22.78 +
   22.79 +void dispatch_file_close(struct mount *mount, struct fsif_request *req)
   22.80 +{
   22.81 +    int ret;
   22.82 +    RING_IDX rsp_idx;
   22.83 +    fsif_response_t *rsp;
   22.84 +    uint16_t req_id;
   22.85 +
   22.86 +    printf("Dispatching file close operation (fd=%d).\n", req->u.fclose.fd);
   22.87 +   
   22.88 +    req_id = req->id;
   22.89 +    ret = close(req->u.fclose.fd);
   22.90 +    printf("Got ret: %d\n", ret);
   22.91 +    /* We can advance the request consumer index, from here on, the request
   22.92 +     * should not be used (it may be overrinden by a response) */
   22.93 +    mount->ring.req_cons++;
   22.94 +
   22.95 +
   22.96 +    /* Get a response from the ring */
   22.97 +    rsp_idx = mount->ring.rsp_prod_pvt++;
   22.98 +    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   22.99 +    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
  22.100 +    rsp->id = req_id; 
  22.101 +    rsp->ret_val = (uint64_t)ret;
  22.102 +}
  22.103 +void dispatch_file_read(struct mount *mount, struct fsif_request *req)
  22.104 +{
  22.105 +    void *buf;
  22.106 +    int fd;
  22.107 +    uint16_t req_id;
  22.108 +    unsigned short priv_id;
  22.109 +    struct fs_request *priv_req;
  22.110 +
  22.111 +    /* Read the request */
  22.112 +    buf = xc_gnttab_map_grant_ref(mount->gnth,
  22.113 +                                  mount->dom_id,
  22.114 +                                  req->u.fread.gref,
  22.115 +                                  PROT_WRITE);
  22.116 +   
  22.117 +    req_id = req->id;
  22.118 +    printf("File read issued for FD=%d (len=%"PRIu64", offest=%"PRIu64")\n", 
  22.119 +            req->u.fread.fd, req->u.fread.len, req->u.fread.offset); 
  22.120 +   
  22.121 +    priv_id = get_request(mount, req);
  22.122 +    printf("Private id is: %d\n", priv_id);
  22.123 +    priv_req = &mount->requests[priv_id];
  22.124 +    priv_req->page = buf;
  22.125 +
  22.126 +    /* Dispatch AIO read request */
  22.127 +    bzero(&priv_req->aiocb, sizeof(struct aiocb));
  22.128 +    priv_req->aiocb.aio_fildes = req->u.fread.fd;
  22.129 +    priv_req->aiocb.aio_nbytes = req->u.fread.len;
  22.130 +    priv_req->aiocb.aio_offset = req->u.fread.offset;
  22.131 +    priv_req->aiocb.aio_buf = buf;
  22.132 +    assert(aio_read(&priv_req->aiocb) >= 0);
  22.133 +
  22.134 +     
  22.135 +    /* We can advance the request consumer index, from here on, the request
  22.136 +     * should not be used (it may be overrinden by a response) */
  22.137 +    mount->ring.req_cons++;
  22.138 +}
  22.139 +
  22.140 +void end_file_read(struct mount *mount, struct fs_request *priv_req)
  22.141 +{
  22.142 +    RING_IDX rsp_idx;
  22.143 +    fsif_response_t *rsp;
  22.144 +    uint16_t req_id;
  22.145 +
  22.146 +    /* Release the grant */
  22.147 +    assert(xc_gnttab_munmap(mount->gnth, priv_req->page, 1) == 0);
  22.148 +
  22.149 +    /* Get a response from the ring */
  22.150 +    rsp_idx = mount->ring.rsp_prod_pvt++;
  22.151 +    req_id = priv_req->req_shadow.id; 
  22.152 +    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
  22.153 +    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
  22.154 +    rsp->id = req_id; 
  22.155 +    rsp->ret_val = (uint64_t)aio_return(&priv_req->aiocb);
  22.156 +}
  22.157 +
  22.158 +void dispatch_file_write(struct mount *mount, struct fsif_request *req)
  22.159 +{
  22.160 +    void *buf;
  22.161 +    int fd;
  22.162 +    uint16_t req_id;
  22.163 +    unsigned short priv_id;
  22.164 +    struct fs_request *priv_req;
  22.165 +
  22.166 +    /* Read the request */
  22.167 +    buf = xc_gnttab_map_grant_ref(mount->gnth,
  22.168 +                                  mount->dom_id,
  22.169 +                                  req->u.fwrite.gref,
  22.170 +                                  PROT_READ);
  22.171 +   
  22.172 +    req_id = req->id;
  22.173 +    printf("File write issued for FD=%d (len=%"PRIu64", offest=%"PRIu64")\n", 
  22.174 +            req->u.fwrite.fd, req->u.fwrite.len, req->u.fwrite.offset); 
  22.175 +   
  22.176 +    priv_id = get_request(mount, req);
  22.177 +    printf("Private id is: %d\n", priv_id);
  22.178 +    priv_req = &mount->requests[priv_id];
  22.179 +    priv_req->page = buf;
  22.180 +
  22.181 +    /* Dispatch AIO write request */
  22.182 +    bzero(&priv_req->aiocb, sizeof(struct aiocb));
  22.183 +    priv_req->aiocb.aio_fildes = req->u.fwrite.fd;
  22.184 +    priv_req->aiocb.aio_nbytes = req->u.fwrite.len;
  22.185 +    priv_req->aiocb.aio_offset = req->u.fwrite.offset;
  22.186 +    priv_req->aiocb.aio_buf = buf;
  22.187 +    assert(aio_write(&priv_req->aiocb) >= 0);
  22.188 +
  22.189 +     
  22.190 +    /* We can advance the request consumer index, from here on, the request
  22.191 +     * should not be used (it may be overrinden by a response) */
  22.192 +    mount->ring.req_cons++;
  22.193 +}
  22.194 +
  22.195 +void end_file_write(struct mount *mount, struct fs_request *priv_req)
  22.196 +{
  22.197 +    RING_IDX rsp_idx;
  22.198 +    fsif_response_t *rsp;
  22.199 +    uint16_t req_id;
  22.200 +
  22.201 +    /* Release the grant */
  22.202 +    assert(xc_gnttab_munmap(mount->gnth, priv_req->page, 1) == 0);
  22.203 +    
  22.204 +    /* Get a response from the ring */
  22.205 +    rsp_idx = mount->ring.rsp_prod_pvt++;
  22.206 +    req_id = priv_req->req_shadow.id; 
  22.207 +    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
  22.208 +    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
  22.209 +    rsp->id = req_id; 
  22.210 +    rsp->ret_val = (uint64_t)aio_return(&priv_req->aiocb);
  22.211 +}
  22.212 +
  22.213 +void dispatch_stat(struct mount *mount, struct fsif_request *req)
  22.214 +{
  22.215 +    struct fsif_stat_response *buf;
  22.216 +    struct stat stat;
  22.217 +    int fd, ret;
  22.218 +    uint16_t req_id;
  22.219 +    RING_IDX rsp_idx;
  22.220 +    fsif_response_t *rsp;
  22.221 +
  22.222 +    /* Read the request */
  22.223 +    buf = xc_gnttab_map_grant_ref(mount->gnth,
  22.224 +                                  mount->dom_id,
  22.225 +                                  req->u.fstat.gref,
  22.226 +                                  PROT_WRITE);
  22.227 +   
  22.228 +    req_id = req->id;
  22.229 +    fd = req->u.fstat.fd;
  22.230 +    printf("File stat issued for FD=%d\n", fd); 
  22.231 +   
  22.232 +    /* We can advance the request consumer index, from here on, the request
  22.233 +     * should not be used (it may be overrinden by a response) */
  22.234 +    mount->ring.req_cons++;
  22.235 +   
  22.236 +    /* Stat, and create the response */ 
  22.237 +    ret = fstat(fd, &stat);
  22.238 +    printf("Mode=%o, uid=%d, a_time=%ld\n",
  22.239 +            stat.st_mode, stat.st_uid, stat.st_atime);
  22.240 +    buf->stat_mode  = stat.st_mode;
  22.241 +    buf->stat_uid   = stat.st_uid;
  22.242 +    buf->stat_gid   = stat.st_gid;
  22.243 +#ifdef BLKGETSIZE
  22.244 +    if (S_ISBLK(stat.st_mode)) {
  22.245 +	int sectors;
  22.246 +	if (ioctl(fd, BLKGETSIZE, &sectors)) {
  22.247 +	    perror("getting device size\n");
  22.248 +	    buf->stat_size = 0;
  22.249 +	} else
  22.250 +	    buf->stat_size = sectors << 9;
  22.251 +    } else
  22.252 +#endif
  22.253 +	buf->stat_size  = stat.st_size;
  22.254 +    buf->stat_atime = stat.st_atime;
  22.255 +    buf->stat_mtime = stat.st_mtime;
  22.256 +    buf->stat_ctime = stat.st_ctime;
  22.257 +
  22.258 +    /* Release the grant */
  22.259 +    assert(xc_gnttab_munmap(mount->gnth, buf, 1) == 0);
  22.260 +    
  22.261 +    /* Get a response from the ring */
  22.262 +    rsp_idx = mount->ring.rsp_prod_pvt++;
  22.263 +    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
  22.264 +    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
  22.265 +    rsp->id = req_id; 
  22.266 +    rsp->ret_val = (uint64_t)ret;
  22.267 +}
  22.268 +
  22.269 +
  22.270 +void dispatch_truncate(struct mount *mount, struct fsif_request *req)
  22.271 +{
  22.272 +    int fd, ret;
  22.273 +    uint16_t req_id;
  22.274 +    RING_IDX rsp_idx;
  22.275 +    fsif_response_t *rsp;
  22.276 +    int64_t length;
  22.277 +
  22.278 +    req_id = req->id;
  22.279 +    fd = req->u.ftruncate.fd;
  22.280 +    length = req->u.ftruncate.length;
  22.281 +    printf("File truncate issued for FD=%d, length=%"PRId64"\n", fd, length); 
  22.282 +   
  22.283 +    /* We can advance the request consumer index, from here on, the request
  22.284 +     * should not be used (it may be overrinden by a response) */
  22.285 +    mount->ring.req_cons++;
  22.286 +   
  22.287 +    /* Stat, and create the response */ 
  22.288 +    ret = ftruncate(fd, length);
  22.289 +
  22.290 +    /* Get a response from the ring */
  22.291 +    rsp_idx = mount->ring.rsp_prod_pvt++;
  22.292 +    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
  22.293 +    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
  22.294 +    rsp->id = req_id; 
  22.295 +    rsp->ret_val = (uint64_t)ret;
  22.296 +}
  22.297 +
  22.298 +void dispatch_remove(struct mount *mount, struct fsif_request *req)
  22.299 +{
  22.300 +    char *file_name, full_path[BUFFER_SIZE];
  22.301 +    int ret;
  22.302 +    RING_IDX rsp_idx;
  22.303 +    fsif_response_t *rsp;
  22.304 +    uint16_t req_id;
  22.305 +
  22.306 +    printf("Dispatching remove operation (gref=%d).\n", req->u.fremove.gref);
  22.307 +    /* Read the request, and open file */
  22.308 +    file_name = xc_gnttab_map_grant_ref(mount->gnth,
  22.309 +                                        mount->dom_id,
  22.310 +                                        req->u.fremove.gref,
  22.311 +                                        PROT_READ);
  22.312 +   
  22.313 +    req_id = req->id;
  22.314 +    printf("File remove issued for %s\n", file_name); 
  22.315 +    assert(BUFFER_SIZE > 
  22.316 +           strlen(file_name) + strlen(mount->export->export_path) + 1); 
  22.317 +    sprintf(full_path, "%s/%s", mount->export->export_path, file_name);
  22.318 +    assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
  22.319 +    printf("Issuing remove for %s\n", full_path);
  22.320 +    ret = remove(full_path);
  22.321 +    printf("Got ret: %d\n", ret);
  22.322 +    /* We can advance the request consumer index, from here on, the request
  22.323 +     * should not be used (it may be overrinden by a response) */
  22.324 +    mount->ring.req_cons++;
  22.325 +
  22.326 +
  22.327 +    /* Get a response from the ring */
  22.328 +    rsp_idx = mount->ring.rsp_prod_pvt++;
  22.329 +    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
  22.330 +    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
  22.331 +    rsp->id = req_id; 
  22.332 +    rsp->ret_val = (uint64_t)ret;
  22.333 +}
  22.334 +
  22.335 +
  22.336 +void dispatch_rename(struct mount *mount, struct fsif_request *req)
  22.337 +{
  22.338 +    char *buf, *old_file_name, *new_file_name;
  22.339 +    char old_full_path[BUFFER_SIZE], new_full_path[BUFFER_SIZE];
  22.340 +    int ret;
  22.341 +    RING_IDX rsp_idx;
  22.342 +    fsif_response_t *rsp;
  22.343 +    uint16_t req_id;
  22.344 +
  22.345 +    printf("Dispatching rename operation (gref=%d).\n", req->u.fremove.gref);
  22.346 +    /* Read the request, and open file */
  22.347 +    buf = xc_gnttab_map_grant_ref(mount->gnth,
  22.348 +                                  mount->dom_id,
  22.349 +                                  req->u.frename.gref,
  22.350 +                                  PROT_READ);
  22.351 +   
  22.352 +    req_id = req->id;
  22.353 +    old_file_name = buf + req->u.frename.old_name_offset;
  22.354 +    new_file_name = buf + req->u.frename.new_name_offset;
  22.355 +    printf("File rename issued for %s -> %s (buf=%s)\n", 
  22.356 +            old_file_name, new_file_name, buf); 
  22.357 +    assert(BUFFER_SIZE > 
  22.358 +           strlen(old_file_name) + strlen(mount->export->export_path) + 1); 
  22.359 +    assert(BUFFER_SIZE > 
  22.360 +           strlen(new_file_name) + strlen(mount->export->export_path) + 1); 
  22.361 +    sprintf(old_full_path, "%s/%s", mount->export->export_path, old_file_name);
  22.362 +    sprintf(new_full_path, "%s/%s", mount->export->export_path, new_file_name);
  22.363 +    assert(xc_gnttab_munmap(mount->gnth, buf, 1) == 0);
  22.364 +    printf("Issuing rename for %s -> %s\n", old_full_path, new_full_path);
  22.365 +    ret = rename(old_full_path, new_full_path);
  22.366 +    printf("Got ret: %d\n", ret);
  22.367 +    /* We can advance the request consumer index, from here on, the request
  22.368 +     * should not be used (it may be overrinden by a response) */
  22.369 +    mount->ring.req_cons++;
  22.370 +
  22.371 +
  22.372 +    /* Get a response from the ring */
  22.373 +    rsp_idx = mount->ring.rsp_prod_pvt++;
  22.374 +    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
  22.375 +    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
  22.376 +    rsp->id = req_id; 
  22.377 +    rsp->ret_val = (uint64_t)ret;
  22.378 +}
  22.379 +
  22.380 +
  22.381 +void dispatch_create(struct mount *mount, struct fsif_request *req)
  22.382 +{
  22.383 +    char *file_name, full_path[BUFFER_SIZE];
  22.384 +    int ret;
  22.385 +    int8_t directory;
  22.386 +    int32_t mode;
  22.387 +    RING_IDX rsp_idx;
  22.388 +    fsif_response_t *rsp;
  22.389 +    uint16_t req_id;
  22.390 +
  22.391 +    printf("Dispatching file create operation (gref=%d).\n", req->u.fcreate.gref);
  22.392 +    /* Read the request, and create file/directory */
  22.393 +    mode = req->u.fcreate.mode;
  22.394 +    directory = req->u.fcreate.directory;
  22.395 +    file_name = xc_gnttab_map_grant_ref(mount->gnth,
  22.396 +                                        mount->dom_id,
  22.397 +                                        req->u.fcreate.gref,
  22.398 +                                        PROT_READ);
  22.399 +   
  22.400 +    req_id = req->id;
  22.401 +    printf("File create issued for %s\n", file_name); 
  22.402 +    assert(BUFFER_SIZE > 
  22.403 +           strlen(file_name) + strlen(mount->export->export_path) + 1); 
  22.404 +    sprintf(full_path, "%s/%s", mount->export->export_path, file_name);
  22.405 +    assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
  22.406 +    /* We can advance the request consumer index, from here on, the request
  22.407 +     * should not be used (it may be overrinden by a response) */
  22.408 +    mount->ring.req_cons++;
  22.409 +
  22.410 +    if(directory)
  22.411 +    {
  22.412 +        printf("Issuing create for directory: %s\n", full_path);
  22.413 +        ret = mkdir(full_path, mode);
  22.414 +    }
  22.415 +    else
  22.416 +    {
  22.417 +        printf("Issuing create for file: %s\n", full_path);
  22.418 +        ret = creat(full_path, mode); 
  22.419 +    }
  22.420 +    printf("Got ret %d (errno=%d)\n", ret, errno);
  22.421 +
  22.422 +    /* Get a response from the ring */
  22.423 +    rsp_idx = mount->ring.rsp_prod_pvt++;
  22.424 +    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
  22.425 +    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
  22.426 +    rsp->id = req_id; 
  22.427 +    rsp->ret_val = (uint64_t)ret;
  22.428 +}
  22.429 +
  22.430 +void dispatch_list(struct mount *mount, struct fsif_request *req)
  22.431 +{
  22.432 +    char *file_name, *buf, full_path[BUFFER_SIZE];
  22.433 +    uint32_t offset, nr_files, error_code; 
  22.434 +    uint64_t ret_val;
  22.435 +    RING_IDX rsp_idx;
  22.436 +    fsif_response_t *rsp;
  22.437 +    uint16_t req_id;
  22.438 +    DIR *dir;
  22.439 +    struct dirent *dirent = NULL;
  22.440 +
  22.441 +    printf("Dispatching list operation (gref=%d).\n", req->u.flist.gref);
  22.442 +    /* Read the request, and list directory */
  22.443 +    offset = req->u.flist.offset;
  22.444 +    buf = file_name = xc_gnttab_map_grant_ref(mount->gnth,
  22.445 +                                        mount->dom_id,
  22.446 +                                        req->u.flist.gref,
  22.447 +                                        PROT_READ | PROT_WRITE);
  22.448 +   
  22.449 +    req_id = req->id;
  22.450 +    printf("Dir list issued for %s\n", file_name); 
  22.451 +    assert(BUFFER_SIZE > 
  22.452 +           strlen(file_name) + strlen(mount->export->export_path) + 1); 
  22.453 +    sprintf(full_path, "%s/%s", mount->export->export_path, file_name);
  22.454 +    /* We can advance the request consumer index, from here on, the request
  22.455 +     * should not be used (it may be overrinden by a response) */
  22.456 +    mount->ring.req_cons++;
  22.457 +
  22.458 +    ret_val = 0;
  22.459 +    nr_files = 0;
  22.460 +    dir = opendir(full_path);
  22.461 +    if(dir == NULL)
  22.462 +    {
  22.463 +        error_code = errno;
  22.464 +        goto error_out;
  22.465 +    }
  22.466 +    /* Skip offset dirs */
  22.467 +    dirent = readdir(dir);
  22.468 +    while(offset-- > 0 && dirent != NULL)
  22.469 +        dirent = readdir(dir);
  22.470 +    /* If there was any error with reading the directory, errno will be set */
  22.471 +    error_code = errno;
  22.472 +    /* Copy file names of the remaining non-NULL dirents into buf */
  22.473 +    assert(NAME_MAX < PAGE_SIZE >> 1);
  22.474 +    while(dirent != NULL && 
  22.475 +            (PAGE_SIZE - ((unsigned long)buf & PAGE_MASK) > NAME_MAX))
  22.476 +    {
  22.477 +        int curr_length = strlen(dirent->d_name) + 1;
  22.478 +        
  22.479 +        memcpy(buf, dirent->d_name, curr_length);
  22.480 +        buf += curr_length;
  22.481 +        dirent = readdir(dir);
  22.482 +        error_code = errno;
  22.483 +        nr_files++;
  22.484 +    }
  22.485 +error_out:    
  22.486 +    ret_val = ((nr_files << NR_FILES_SHIFT) & NR_FILES_MASK) | 
  22.487 +              ((error_code << ERROR_SHIFT) & ERROR_MASK) | 
  22.488 +              (dirent != NULL ? HAS_MORE_FLAG : 0);
  22.489 +    assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
  22.490 +    
  22.491 +    /* Get a response from the ring */
  22.492 +    rsp_idx = mount->ring.rsp_prod_pvt++;
  22.493 +    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
  22.494 +    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
  22.495 +    rsp->id = req_id; 
  22.496 +    rsp->ret_val = ret_val;
  22.497 +}
  22.498 +
  22.499 +void dispatch_chmod(struct mount *mount, struct fsif_request *req)
  22.500 +{
  22.501 +    int fd, ret;
  22.502 +    RING_IDX rsp_idx;
  22.503 +    fsif_response_t *rsp;
  22.504 +    uint16_t req_id;
  22.505 +    int32_t mode;
  22.506 +
  22.507 +    printf("Dispatching file chmod operation (fd=%d, mode=%o).\n", 
  22.508 +            req->u.fchmod.fd, req->u.fchmod.mode);
  22.509 +    req_id = req->id;
  22.510 +    fd = req->u.fchmod.fd;
  22.511 +    mode = req->u.fchmod.mode;
  22.512 +    /* We can advance the request consumer index, from here on, the request
  22.513 +     * should not be used (it may be overrinden by a response) */
  22.514 +    mount->ring.req_cons++;
  22.515 +
  22.516 +    ret = fchmod(fd, mode); 
  22.517 +
  22.518 +    /* Get a response from the ring */
  22.519 +    rsp_idx = mount->ring.rsp_prod_pvt++;
  22.520 +    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
  22.521 +    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
  22.522 +    rsp->id = req_id; 
  22.523 +    rsp->ret_val = (uint64_t)ret;
  22.524 +}
  22.525 +
  22.526 +void dispatch_fs_space(struct mount *mount, struct fsif_request *req)
  22.527 +{
  22.528 +    char *file_name, full_path[BUFFER_SIZE];
  22.529 +    RING_IDX rsp_idx;
  22.530 +    fsif_response_t *rsp;
  22.531 +    uint16_t req_id;
  22.532 +    struct statfs stat;
  22.533 +    int64_t ret;
  22.534 +
  22.535 +    printf("Dispatching fs space operation (gref=%d).\n", req->u.fspace.gref);
  22.536 +    /* Read the request, and open file */
  22.537 +    file_name = xc_gnttab_map_grant_ref(mount->gnth,
  22.538 +                                        mount->dom_id,
  22.539 +                                        req->u.fspace.gref,
  22.540 +                                        PROT_READ);
  22.541 +   
  22.542 +    req_id = req->id;
  22.543 +    printf("Fs space issued for %s\n", file_name); 
  22.544 +    assert(BUFFER_SIZE > 
  22.545 +           strlen(file_name) + strlen(mount->export->export_path) + 1); 
  22.546 +    sprintf(full_path, "%s/%s", mount->export->export_path, file_name);
  22.547 +    assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
  22.548 +    printf("Issuing fs space for %s\n", full_path);
  22.549 +    ret = statfs(full_path, &stat);
  22.550 +    if(ret >= 0)
  22.551 +        ret = stat.f_bsize * stat.f_bfree;
  22.552 +
  22.553 +    /* We can advance the request consumer index, from here on, the request
  22.554 +     * should not be used (it may be overrinden by a response) */
  22.555 +    mount->ring.req_cons++;
  22.556 +
  22.557 +
  22.558 +    /* Get a response from the ring */
  22.559 +    rsp_idx = mount->ring.rsp_prod_pvt++;
  22.560 +    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
  22.561 +    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
  22.562 +    rsp->id = req_id; 
  22.563 +    rsp->ret_val = (uint64_t)ret;
  22.564 +}
  22.565 +
  22.566 +void dispatch_file_sync(struct mount *mount, struct fsif_request *req)
  22.567 +{
  22.568 +    int fd;
  22.569 +    uint16_t req_id;
  22.570 +    unsigned short priv_id;
  22.571 +    struct fs_request *priv_req;
  22.572 +
  22.573 +    req_id = req->id;
  22.574 +    fd = req->u.fsync.fd;
  22.575 +    printf("File sync issued for FD=%d\n", fd); 
  22.576 +   
  22.577 +    priv_id = get_request(mount, req);
  22.578 +    printf("Private id is: %d\n", priv_id);
  22.579 +    priv_req = &mount->requests[priv_id];
  22.580 +
  22.581 +    /* Dispatch AIO read request */
  22.582 +    bzero(&priv_req->aiocb, sizeof(struct aiocb));
  22.583 +    priv_req->aiocb.aio_fildes = fd;
  22.584 +    assert(aio_fsync(O_SYNC, &priv_req->aiocb) >= 0);
  22.585 +
  22.586 +     
  22.587 +    /* We can advance the request consumer index, from here on, the request
  22.588 +     * should not be used (it may be overrinden by a response) */
  22.589 +    mount->ring.req_cons++;
  22.590 +}
  22.591 +
  22.592 +void end_file_sync(struct mount *mount, struct fs_request *priv_req)
  22.593 +{
  22.594 +    RING_IDX rsp_idx;
  22.595 +    fsif_response_t *rsp;
  22.596 +    uint16_t req_id;
  22.597 +
  22.598 +    /* Get a response from the ring */
  22.599 +    rsp_idx = mount->ring.rsp_prod_pvt++;
  22.600 +    req_id = priv_req->req_shadow.id; 
  22.601 +    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
  22.602 +    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
  22.603 +    rsp->id = req_id; 
  22.604 +    rsp->ret_val = (uint64_t)aio_return(&priv_req->aiocb);
  22.605 +}
  22.606 +
  22.607 +struct fs_op fopen_op     = {.type             = REQ_FILE_OPEN,
  22.608 +                             .dispatch_handler = dispatch_file_open,
  22.609 +                             .response_handler = NULL};
  22.610 +struct fs_op fclose_op    = {.type             = REQ_FILE_CLOSE,
  22.611 +                             .dispatch_handler = dispatch_file_close,
  22.612 +                             .response_handler = NULL};
  22.613 +struct fs_op fread_op     = {.type             = REQ_FILE_READ,
  22.614 +                             .dispatch_handler = dispatch_file_read,
  22.615 +                             .response_handler = end_file_read};
  22.616 +struct fs_op fwrite_op    = {.type             = REQ_FILE_WRITE,
  22.617 +                             .dispatch_handler = dispatch_file_write,
  22.618 +                             .response_handler = end_file_write};
  22.619 +struct fs_op fstat_op     = {.type             = REQ_STAT,
  22.620 +                             .dispatch_handler = dispatch_stat,
  22.621 +                             .response_handler = NULL};
  22.622 +struct fs_op ftruncate_op = {.type             = REQ_FILE_TRUNCATE,
  22.623 +                             .dispatch_handler = dispatch_truncate,
  22.624 +                             .response_handler = NULL};
  22.625 +struct fs_op fremove_op   = {.type             = REQ_REMOVE,
  22.626 +                             .dispatch_handler = dispatch_remove,
  22.627 +                             .response_handler = NULL};
  22.628 +struct fs_op frename_op   = {.type             = REQ_RENAME,
  22.629 +                             .dispatch_handler = dispatch_rename,
  22.630 +                             .response_handler = NULL};
  22.631 +struct fs_op fcreate_op   = {.type             = REQ_CREATE,
  22.632 +                             .dispatch_handler = dispatch_create,
  22.633 +                             .response_handler = NULL};
  22.634 +struct fs_op flist_op     = {.type             = REQ_DIR_LIST,
  22.635 +                             .dispatch_handler = dispatch_list,
  22.636 +                             .response_handler = NULL};
  22.637 +struct fs_op fchmod_op    = {.type             = REQ_CHMOD,
  22.638 +                             .dispatch_handler = dispatch_chmod,
  22.639 +                             .response_handler = NULL};
  22.640 +struct fs_op fspace_op    = {.type             = REQ_FS_SPACE,
  22.641 +                             .dispatch_handler = dispatch_fs_space,
  22.642 +                             .response_handler = NULL};
  22.643 +struct fs_op fsync_op     = {.type             = REQ_FILE_SYNC,
  22.644 +                             .dispatch_handler = dispatch_file_sync,
  22.645 +                             .response_handler = end_file_sync};
  22.646 +
  22.647 +
  22.648 +struct fs_op *fsops[] = {&fopen_op, 
  22.649 +                         &fclose_op, 
  22.650 +                         &fread_op, 
  22.651 +                         &fwrite_op, 
  22.652 +                         &fstat_op, 
  22.653 +                         &ftruncate_op, 
  22.654 +                         &fremove_op, 
  22.655 +                         &frename_op, 
  22.656 +                         &fcreate_op, 
  22.657 +                         &flist_op, 
  22.658 +                         &fchmod_op, 
  22.659 +                         &fspace_op, 
  22.660 +                         &fsync_op, 
  22.661 +                         NULL};
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/tools/fs-back/fs-xenbus.c	Fri Jan 18 13:49:48 2008 -0700
    23.3 @@ -0,0 +1,180 @@
    23.4 +#undef NDEBUG
    23.5 +#include <stdio.h>
    23.6 +#include <stdlib.h>
    23.7 +#include <stdarg.h>
    23.8 +#include <string.h>
    23.9 +#include <assert.h>
   23.10 +#include <xenctrl.h>
   23.11 +#include <xs.h>
   23.12 +#include <xen/io/fsif.h>
   23.13 +#include "fs-backend.h"
   23.14 +
   23.15 +
   23.16 +static bool xenbus_printf(struct xs_handle *xsh,
   23.17 +                          xs_transaction_t xbt,
   23.18 +                          char* node,
   23.19 +                          char* path,
   23.20 +                          char* fmt,
   23.21 +                          ...)
   23.22 +{
   23.23 +    char fullpath[1024];
   23.24 +    char val[1024];
   23.25 +    va_list args;
   23.26 +    
   23.27 +    va_start(args, fmt);
   23.28 +    sprintf(fullpath,"%s/%s", node, path);
   23.29 +    vsprintf(val, fmt, args);
   23.30 +    va_end(args);
   23.31 +    printf("xenbus_printf (%s) <= %s.\n", fullpath, val);    
   23.32 +
   23.33 +    return xs_write(xsh, xbt, fullpath, val, strlen(val));
   23.34 +}
   23.35 +
   23.36 +bool xenbus_create_request_node(void)
   23.37 +{
   23.38 +    bool ret;
   23.39 +    struct xs_permissions perms;
   23.40 +    
   23.41 +    assert(xsh != NULL);
   23.42 +    xs_rm(xsh, XBT_NULL, WATCH_NODE);
   23.43 +    ret = xs_mkdir(xsh, XBT_NULL, WATCH_NODE); 
   23.44 +    if (!ret)
   23.45 +        return false;
   23.46 +
   23.47 +    perms.id = 0;
   23.48 +    perms.perms = XS_PERM_WRITE;
   23.49 +    ret = xs_set_permissions(xsh, XBT_NULL, WATCH_NODE, &perms, 1);
   23.50 +
   23.51 +    return ret;
   23.52 +}
   23.53 +
   23.54 +int xenbus_register_export(struct fs_export *export)
   23.55 +{
   23.56 +    xs_transaction_t xst = 0;
   23.57 +    char node[1024];
   23.58 +    struct xs_permissions perms;
   23.59 +
   23.60 +    assert(xsh != NULL);
   23.61 +    if(xsh == NULL)
   23.62 +    {
   23.63 +        printf("Could not open connection to xenbus deamon.\n");
   23.64 +        goto error_exit;
   23.65 +    }
   23.66 +    printf("Connection to the xenbus deamon opened successfully.\n");
   23.67 +
   23.68 +    /* Start transaction */
   23.69 +    xst = xs_transaction_start(xsh);
   23.70 +    if(xst == 0)
   23.71 +    {
   23.72 +        printf("Could not start a transaction.\n");
   23.73 +        goto error_exit;
   23.74 +    }
   23.75 +    printf("XS transaction is %d\n", xst); 
   23.76 + 
   23.77 +    /* Create node string */
   23.78 +    sprintf(node, "%s/%d", EXPORTS_NODE, export->export_id); 
   23.79 +    /* Remove old export (if exists) */ 
   23.80 +    xs_rm(xsh, xst, node);
   23.81 +
   23.82 +    if(!xenbus_printf(xsh, xst, node, "name", "%s", export->name))
   23.83 +    {
   23.84 +        printf("Could not write the export node.\n");
   23.85 +        goto error_exit;
   23.86 +    }
   23.87 +
   23.88 +    /* People need to be able to read our export */
   23.89 +    perms.id = 0;
   23.90 +    perms.perms = XS_PERM_READ;
   23.91 +    if(!xs_set_permissions(xsh, xst, EXPORTS_NODE, &perms, 1))
   23.92 +    {
   23.93 +        printf("Could not set permissions on the export node.\n");
   23.94 +        goto error_exit;
   23.95 +    }
   23.96 +
   23.97 +    xs_transaction_end(xsh, xst, 0);
   23.98 +    return 0; 
   23.99 +
  23.100 +error_exit:    
  23.101 +    if(xst != 0)
  23.102 +        xs_transaction_end(xsh, xst, 1);
  23.103 +    return -1;
  23.104 +}
  23.105 +
  23.106 +int xenbus_get_watch_fd(void)
  23.107 +{
  23.108 +    int res;
  23.109 +    assert(xsh != NULL);
  23.110 +    res = xs_watch(xsh, WATCH_NODE, "conn-watch");
  23.111 +    assert(res);
  23.112 +    return xs_fileno(xsh); 
  23.113 +}
  23.114 +
  23.115 +void xenbus_read_mount_request(struct mount *mount, char *frontend)
  23.116 +{
  23.117 +    char node[1024];
  23.118 +    char *s;
  23.119 +
  23.120 +    assert(xsh != NULL);
  23.121 +#if 0
  23.122 +    sprintf(node, WATCH_NODE"/%d/%d/frontend", 
  23.123 +                           mount->dom_id, mount->export->export_id);
  23.124 +    frontend = xs_read(xsh, XBT_NULL, node, NULL);
  23.125 +#endif
  23.126 +    mount->frontend = frontend;
  23.127 +    sprintf(node, "%s/state", frontend);
  23.128 +    s = xs_read(xsh, XBT_NULL, node, NULL);
  23.129 +    assert(strcmp(s, STATE_READY) == 0);
  23.130 +    free(s);
  23.131 +    sprintf(node, "%s/ring-ref", frontend);
  23.132 +    s = xs_read(xsh, XBT_NULL, node, NULL);
  23.133 +    mount->gref = atoi(s);
  23.134 +    free(s);
  23.135 +    sprintf(node, "%s/event-channel", frontend);
  23.136 +    s = xs_read(xsh, XBT_NULL, node, NULL);
  23.137 +    mount->remote_evtchn = atoi(s);
  23.138 +    free(s);
  23.139 +}
  23.140 +
  23.141 +/* Small utility function to figure out our domain id */
  23.142 +static int get_self_id(void)
  23.143 +{
  23.144 +    char *dom_id;
  23.145 +    int ret; 
  23.146 +                
  23.147 +    assert(xsh != NULL);
  23.148 +    dom_id = xs_read(xsh, XBT_NULL, "domid", NULL);
  23.149 +    sscanf(dom_id, "%d", &ret); 
  23.150 +    free(dom_id);
  23.151 +                        
  23.152 +    return ret;                                  
  23.153 +} 
  23.154 +
  23.155 +
  23.156 +void xenbus_write_backend_node(struct mount *mount)
  23.157 +{
  23.158 +    char node[1024], backend_node[1024];
  23.159 +    int self_id;
  23.160 +
  23.161 +    assert(xsh != NULL);
  23.162 +    self_id = get_self_id();
  23.163 +    printf("Our own dom_id=%d\n", self_id);
  23.164 +    sprintf(node, "%s/backend", mount->frontend);
  23.165 +    sprintf(backend_node, "/local/domain/%d/"ROOT_NODE"/%d",
  23.166 +                                self_id, mount->mount_id);
  23.167 +    xs_write(xsh, XBT_NULL, node, backend_node, strlen(backend_node));
  23.168 +
  23.169 +    sprintf(node, ROOT_NODE"/%d/state", mount->mount_id);
  23.170 +    xs_write(xsh, XBT_NULL, node, STATE_INITIALISED, strlen(STATE_INITIALISED));
  23.171 +}
  23.172 +
  23.173 +void xenbus_write_backend_ready(struct mount *mount)
  23.174 +{
  23.175 +    char node[1024];
  23.176 +    int self_id;
  23.177 +
  23.178 +    assert(xsh != NULL);
  23.179 +    self_id = get_self_id();
  23.180 +    sprintf(node, ROOT_NODE"/%d/state", mount->mount_id);
  23.181 +    xs_write(xsh, XBT_NULL, node, STATE_READY, strlen(STATE_READY));
  23.182 +}
  23.183 +
    24.1 --- a/tools/ioemu/target-i386-dm/helper2.c	Thu Jan 17 12:17:14 2008 -0700
    24.2 +++ b/tools/ioemu/target-i386-dm/helper2.c	Fri Jan 18 13:49:48 2008 -0700
    24.3 @@ -476,7 +476,7 @@ void cpu_ioreq_timeoffset(CPUState *env,
    24.4  {
    24.5      char b[64];
    24.6  
    24.7 -    time_offset += (ulong)req->data;
    24.8 +    time_offset += (unsigned long)req->data;
    24.9  
   24.10      fprintf(logfile, "Time offset set %ld, added offset %ld\n", time_offset, req->data);
   24.11      sprintf(b, "%ld", time_offset);
   24.12 @@ -637,6 +637,7 @@ int main_loop(void)
   24.13      int evtchn_fd = xce_handle == -1 ? -1 : xc_evtchn_fd(xce_handle);
   24.14      char qemu_file[PATH_MAX];
   24.15      fd_set fds;
   24.16 +    int ret = 0;
   24.17  
   24.18      buffered_io_timer = qemu_new_timer(rt_clock, handle_buffered_io,
   24.19  				       cpu_single_env);
   24.20 @@ -647,10 +648,15 @@ int main_loop(void)
   24.21  
   24.22      xenstore_record_dm_state("running");
   24.23      while (1) {
   24.24 -        while (!(vm_running && suspend_requested))
   24.25 +        while (!((vm_running && suspend_requested) || shutdown_requested))
   24.26              /* Wait up to 10 msec. */
   24.27              main_loop_wait(10);
   24.28  
   24.29 +        if (shutdown_requested) {
   24.30 +            ret = EXCP_INTERRUPT;
   24.31 +            break;
   24.32 +        }
   24.33 +
   24.34          fprintf(logfile, "device model saving state\n");
   24.35  
   24.36          /* Pull all outstanding ioreqs through the system */
   24.37 @@ -676,7 +682,7 @@ int main_loop(void)
   24.38          xenstore_record_dm_state("running");
   24.39      }
   24.40  
   24.41 -    return 0;
   24.42 +    return ret;
   24.43  }
   24.44  
   24.45  void destroy_hvm_domain(void)
    25.1 --- a/tools/python/xen/xend/image.py	Thu Jan 17 12:17:14 2008 -0700
    25.2 +++ b/tools/python/xen/xend/image.py	Fri Jan 18 13:49:48 2008 -0700
    25.3 @@ -321,7 +321,7 @@ class ImageHandler:
    25.4              return
    25.5          if self.pid:
    25.6              try:
    25.7 -                os.kill(self.pid, signal.SIGKILL)
    25.8 +                os.kill(self.pid, signal.SIGTERM)
    25.9              except OSError, exn:
   25.10                  log.exception(exn)
   25.11              try:
    26.1 --- a/tools/xentrace/xenctx.c	Thu Jan 17 12:17:14 2008 -0700
    26.2 +++ b/tools/xentrace/xenctx.c	Fri Jan 18 13:49:48 2008 -0700
    26.3 @@ -29,6 +29,7 @@ int xc_handle = 0;
    26.4  int domid = 0;
    26.5  int frame_ptrs = 0;
    26.6  int stack_trace = 0;
    26.7 +int disp_all = 0;
    26.8  
    26.9  #if defined (__i386__)
   26.10  #if defined (__OpenBSD__)
   26.11 @@ -243,12 +244,23 @@ void print_flags(uint64_t flags)
   26.12  {
   26.13      int i;
   26.14  
   26.15 -    printf("flags: %08" PRIx64, flags);
   26.16 +    printf("\nflags: %08" PRIx64, flags);
   26.17      for (i = 21; i >= 0; i--) {
   26.18          char *s = flag_values[i][(flags >> i) & 1];
   26.19          if (s != NULL)
   26.20              printf(" %s", s);
   26.21      }
   26.22 +    printf("\n");
   26.23 +}
   26.24 +
   26.25 +void print_special(unsigned long *regs, const char *name, unsigned int mask)
   26.26 +{
   26.27 +    unsigned int i;
   26.28 +
   26.29 +    printf("\n");
   26.30 +    for (i = 0; mask; mask >>= 1, ++i)
   26.31 +        if (mask & 1)
   26.32 +            printf("%s%u: " FMT_SIZE_T "\n", name, i, (size_t)regs[i]);
   26.33  }
   26.34  #endif
   26.35  
   26.36 @@ -257,12 +269,10 @@ void print_ctx(vcpu_guest_context_t *ctx
   26.37  {
   26.38      struct cpu_user_regs *regs = &ctx1->user_regs;
   26.39  
   26.40 -    printf("eip: %08x ", regs->eip);
   26.41 +    printf("cs:eip: %04x:%08x ", regs->cs, regs->eip);
   26.42      print_symbol(regs->eip);
   26.43      print_flags(regs->eflags);
   26.44 -    printf("\n");
   26.45 -
   26.46 -    printf("esp: %08x\n", regs->esp);
   26.47 +    printf("ss:esp: %04x:%08x\n", regs->ss, regs->esp);
   26.48  
   26.49      printf("eax: %08x\t", regs->eax);
   26.50      printf("ebx: %08x\t", regs->ebx);
   26.51 @@ -273,47 +283,59 @@ void print_ctx(vcpu_guest_context_t *ctx
   26.52      printf("edi: %08x\t", regs->edi);
   26.53      printf("ebp: %08x\n", regs->ebp);
   26.54  
   26.55 -    printf(" cs: %08x\t", regs->cs);
   26.56 -    printf(" ds: %08x\t", regs->ds);
   26.57 -    printf(" fs: %08x\t", regs->fs);
   26.58 -    printf(" gs: %08x\n", regs->gs);
   26.59 +    printf(" ds:     %04x\t", regs->ds);
   26.60 +    printf(" es:     %04x\t", regs->es);
   26.61 +    printf(" fs:     %04x\t", regs->fs);
   26.62 +    printf(" gs:     %04x\n", regs->gs);
   26.63  
   26.64 +    if (disp_all) {
   26.65 +        print_special(ctx1->ctrlreg, "cr", 0x1d);
   26.66 +        print_special(ctx1->debugreg, "dr", 0xcf);
   26.67 +    }
   26.68  }
   26.69  #elif defined(__x86_64__)
   26.70  void print_ctx(vcpu_guest_context_t *ctx1)
   26.71  {
   26.72      struct cpu_user_regs *regs = &ctx1->user_regs;
   26.73  
   26.74 -    printf("rip: %08lx ", regs->rip);
   26.75 +    printf("rip: %016lx ", regs->rip);
   26.76      print_symbol(regs->rip);
   26.77      print_flags(regs->rflags);
   26.78 -    printf("\n");
   26.79 -    printf("rsp: %08lx\n", regs->rsp);
   26.80 -
   26.81 -    printf("rax: %08lx\t", regs->rax);
   26.82 -    printf("rbx: %08lx\t", regs->rbx);
   26.83 -    printf("rcx: %08lx\t", regs->rcx);
   26.84 -    printf("rdx: %08lx\n", regs->rdx);
   26.85 -
   26.86 -    printf("rsi: %08lx\t", regs->rsi);
   26.87 -    printf("rdi: %08lx\t", regs->rdi);
   26.88 -    printf("rbp: %08lx\n", regs->rbp);
   26.89 +    printf("rsp: %016lx\n", regs->rsp);
   26.90  
   26.91 -    printf(" r8: %08lx\t", regs->r8);
   26.92 -    printf(" r9: %08lx\t", regs->r9);
   26.93 -    printf("r10: %08lx\t", regs->r10);
   26.94 -    printf("r11: %08lx\n", regs->r11);
   26.95 +    printf("rax: %016lx\t", regs->rax);
   26.96 +    printf("rcx: %016lx\t", regs->rcx);
   26.97 +    printf("rdx: %016lx\n", regs->rdx);
   26.98  
   26.99 -    printf("r12: %08lx\t", regs->r12);
  26.100 -    printf("r13: %08lx\t", regs->r13);
  26.101 -    printf("r14: %08lx\t", regs->r14);
  26.102 -    printf("r15: %08lx\n", regs->r15);
  26.103 +    printf("rbx: %016lx\t", regs->rbx);
  26.104 +    printf("rsi: %016lx\t", regs->rsi);
  26.105 +    printf("rdi: %016lx\n", regs->rdi);
  26.106  
  26.107 -    printf(" cs:     %04x\t", regs->cs);
  26.108 -    printf(" ds:     %04x\t", regs->ds);
  26.109 -    printf(" fs:     %04x\t", regs->fs);
  26.110 -    printf(" gs:     %04x\n", regs->gs);
  26.111 +    printf("rbp: %016lx\t", regs->rbp);
  26.112 +    printf(" r8: %016lx\t", regs->r8);
  26.113 +    printf(" r9: %016lx\n", regs->r9);
  26.114  
  26.115 +    printf("r10: %016lx\t", regs->r10);
  26.116 +    printf("r11: %016lx\t", regs->r11);
  26.117 +    printf("r12: %016lx\n", regs->r12);
  26.118 +
  26.119 +    printf("r13: %016lx\t", regs->r13);
  26.120 +    printf("r14: %016lx\t", regs->r14);
  26.121 +    printf("r15: %016lx\n", regs->r15);
  26.122 +
  26.123 +    printf(" cs: %04x\t", regs->cs);
  26.124 +    printf(" ss: %04x\t", regs->ss);
  26.125 +    printf(" ds: %04x\t", regs->ds);
  26.126 +    printf(" es: %04x\n", regs->es);
  26.127 +
  26.128 +    printf(" fs: %04x @ %016lx\n", regs->fs, ctx1->fs_base);
  26.129 +    printf(" gs: %04x @ %016lx/%016lx\n", regs->gs,
  26.130 +           ctx1->gs_base_kernel, ctx1->gs_base_user);
  26.131 +
  26.132 +    if (disp_all) {
  26.133 +        print_special(ctx1->ctrlreg, "cr", 0x1d);
  26.134 +        print_special(ctx1->debugreg, "dr", 0xcf);
  26.135 +    }
  26.136  }
  26.137  #elif defined(__ia64__)
  26.138  
  26.139 @@ -742,6 +764,8 @@ void usage(void)
  26.140  #ifdef __ia64__
  26.141      printf("  -r LIST, --regs=LIST  display more registers.\n");
  26.142      printf("  -a --all          same as --regs=tlb,cr,ar,br,bk\n");
  26.143 +#else
  26.144 +    printf("  -a --all          display more registers\n");
  26.145  #endif
  26.146  }
  26.147  
  26.148 @@ -811,6 +835,10 @@ int main(int argc, char **argv)
  26.149              disp_bank_regs = 1;
  26.150              disp_tlb = 1;
  26.151              break;
  26.152 +#else
  26.153 +        case 'a':
  26.154 +            disp_all = 1;
  26.155 +            break;
  26.156  #endif
  26.157          case 'h':
  26.158              usage();
    27.1 --- a/unmodified_drivers/linux-2.6/mkbuildtree	Thu Jan 17 12:17:14 2008 -0700
    27.2 +++ b/unmodified_drivers/linux-2.6/mkbuildtree	Fri Jan 18 13:49:48 2008 -0700
    27.3 @@ -8,27 +8,28 @@ else
    27.4      echo "This may be overridden on the command line (i386,x86_64,ia64)."
    27.5  fi
    27.6  
    27.7 -C=$PWD
    27.8 +C=$(cd $(dirname $0) && pwd)
    27.9 +R=${C%/*/*}
   27.10  
   27.11  if [ -n "$XEN" -a -d "$XEN" ]; then
   27.12    XEN=$(cd $XEN && pwd)
   27.13  else
   27.14 -  XEN=$C/../../xen
   27.15 +  XEN=$R/xen
   27.16  fi
   27.17 +echo "Xen tree: $XEN"
   27.18  
   27.19  if [ -n "$XL" -a -d "$XL" ]; then
   27.20    XL=$(cd $XL && pwd)
   27.21  else
   27.22 -  XL=$C/../../linux-2.6.18-xen.hg
   27.23 +  XL=$R/linux-2.6.18-xen.hg
   27.24  fi
   27.25 +echo "Linux tree: $XL"
   27.26  
   27.27 -for d in $(find ${XL}/drivers/xen/ -maxdepth 1 -type d | sed -e 1d); do
   27.28 -    if ! echo $d | egrep -q back; then
   27.29 -        lndir $d $(basename $d) > /dev/null 2>&1
   27.30 -    fi
   27.31 -    if ! echo $d | egrep -q ball; then
   27.32 -        lndir $d $(basename $d) > /dev/null 2>&1
   27.33 -    fi
   27.34 +cd $C
   27.35 +
   27.36 +for d in $(find ${XL}/drivers/xen/ -mindepth 1 -maxdepth 1 -type d); do
   27.37 +    test -d $(basename $d) || continue
   27.38 +    lndir $d $(basename $d) > /dev/null 2>&1
   27.39  done
   27.40  
   27.41  ln -sf ${XL}/drivers/xen/core/gnttab.c platform-pci
   27.42 @@ -44,23 +45,27 @@ ln -nsf ${XEN}/include/public include/xe
   27.43  # Need to be quite careful here: we don't want the files we link in to
   27.44  # risk overriding the native Linux ones (in particular, system.h must
   27.45  # be native and not xenolinux).
   27.46 -case "$uname"
   27.47 -in
   27.48 -"x86_64")
   27.49 -    ln -sf ${XL}/include/asm-x86_64/mach-xen/asm/hypervisor.h include/asm
   27.50 -    ln -sf ${XL}/include/asm-x86_64/mach-xen/asm/hypercall.h include/asm
   27.51 -    ln -sf ${XL}/include/asm-x86_64/mach-xen/asm/synch_bitops.h include/asm
   27.52 -    ln -sf ${XL}/include/asm-x86_64/mach-xen/asm/maddr.h include/asm
   27.53 -    ln -sf ${XL}/include/asm-x86_64/mach-xen/asm/gnttab_dma.h include/asm
   27.54 -    mkdir -p include/asm-i386
   27.55 -    lndir -silent ${XL}/include/asm-i386 include/asm-i386
   27.56 -  ;;
   27.57 -i[34567]86)
   27.58 -    ln -sf ${XL}/include/asm-i386/mach-xen/asm/hypervisor.h include/asm
   27.59 -    ln -sf ${XL}/include/asm-i386/mach-xen/asm/hypercall.h include/asm
   27.60 -    ln -sf ${XL}/include/asm-i386/mach-xen/asm/synch_bitops.h include/asm
   27.61 -    ln -sf ${XL}/include/asm-i386/mach-xen/asm/maddr.h include/asm
   27.62 -    ln -sf ${XL}/include/asm-i386/mach-xen/asm/gnttab_dma.h include/asm
   27.63 +case "$uname" in
   27.64 +i[34567]86|x86_64)
   27.65 +    if [ -d ${XL}/include/asm-x86 ]; then
   27.66 +        ln -sf ${XL}/include/asm-x86/mach-xen/asm/hypervisor.h include/asm
   27.67 +        ln -sf ${XL}/include/asm-x86/mach-xen/asm/hypercall*.h include/asm
   27.68 +        ln -sf ${XL}/include/asm-x86/mach-xen/asm/synch_bitops*.h include/asm
   27.69 +        ln -sf ${XL}/include/asm-x86/mach-xen/asm/maddr*.h include/asm
   27.70 +        ln -sf ${XL}/include/asm-x86/mach-xen/asm/gnttab_dma.h include/asm
   27.71 +    else
   27.72 +        if [ $uname = x86_64 ]; then
   27.73 +            mkdir -p include/asm-i386
   27.74 +            lndir -silent ${XL}/include/asm-i386 include/asm-i386
   27.75 +        else
   27.76 +            uname=i386
   27.77 +        fi
   27.78 +        ln -sf ${XL}/include/asm-$uname/mach-xen/asm/hypervisor.h include/asm
   27.79 +        ln -sf ${XL}/include/asm-$uname/mach-xen/asm/hypercall.h include/asm
   27.80 +        ln -sf ${XL}/include/asm-$uname/mach-xen/asm/synch_bitops.h include/asm
   27.81 +        ln -sf ${XL}/include/asm-$uname/mach-xen/asm/maddr.h include/asm
   27.82 +        ln -sf ${XL}/include/asm-$uname/mach-xen/asm/gnttab_dma.h include/asm
   27.83 +    fi
   27.84    ;;
   27.85  "ia64")
   27.86      ln -sf ${XL}/include/asm-ia64/hypervisor.h include/asm
    28.1 --- a/xen/arch/ia64/xen/hypercall.c	Thu Jan 17 12:17:14 2008 -0700
    28.2 +++ b/xen/arch/ia64/xen/hypercall.c	Fri Jan 18 13:49:48 2008 -0700
    28.3 @@ -34,9 +34,6 @@
    28.4  #include <xen/perfc.h>
    28.5  #include <public/arch-ia64/debug_op.h>
    28.6  
    28.7 -extern long do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg);
    28.8 -extern long do_callback_op(int cmd, XEN_GUEST_HANDLE(void) arg);
    28.9 -
   28.10  static IA64FAULT
   28.11  xen_hypercall (struct pt_regs *regs)
   28.12  {
   28.13 @@ -457,7 +454,7 @@ static long unregister_guest_callback(st
   28.14  /* First time to add callback to xen/ia64, so let's just stick to
   28.15   * the newer callback interface.
   28.16   */
   28.17 -long do_callback_op(int cmd, XEN_GUEST_HANDLE(void) arg)
   28.18 +long do_callback_op(int cmd, XEN_GUEST_HANDLE(const_void) arg)
   28.19  {
   28.20      long ret;
   28.21  
    29.1 --- a/xen/arch/x86/hvm/vmx/vtd/dmar.c	Thu Jan 17 12:17:14 2008 -0700
    29.2 +++ b/xen/arch/x86/hvm/vmx/vtd/dmar.c	Fri Jan 18 13:49:48 2008 -0700
    29.3 @@ -43,7 +43,6 @@ boolean_param("vtd", vtd_enabled);
    29.4  LIST_HEAD(acpi_drhd_units);
    29.5  LIST_HEAD(acpi_rmrr_units);
    29.6  LIST_HEAD(acpi_atsr_units);
    29.7 -LIST_HEAD(acpi_ioapic_units);
    29.8  
    29.9  u8 dmar_host_address_width;
   29.10  
   29.11 @@ -66,6 +65,47 @@ static int __init acpi_register_rmrr_uni
   29.12      return 0;
   29.13  }
   29.14  
   29.15 +static int acpi_ioapic_device_match(
   29.16 +    struct list_head *ioapic_list, unsigned int apic_id)
   29.17 +{
   29.18 +    struct acpi_ioapic_unit *ioapic;
   29.19 +    list_for_each_entry( ioapic, ioapic_list, list ) {
   29.20 +        if (ioapic->apic_id == apic_id)
   29.21 +            return 1;
   29.22 +    }
   29.23 +    return 0;
   29.24 +}
   29.25 +
   29.26 +struct acpi_drhd_unit * ioapic_to_drhd(unsigned int apic_id)
   29.27 +{
   29.28 +    struct acpi_drhd_unit *drhd;
   29.29 +    list_for_each_entry( drhd, &acpi_drhd_units, list ) {
   29.30 +        if ( acpi_ioapic_device_match(&drhd->ioapic_list, apic_id) ) {
   29.31 +            dprintk(XENLOG_INFO VTDPREFIX,
   29.32 +                    "ioapic_to_drhd: drhd->address = %lx\n",
   29.33 +                    drhd->address);
   29.34 +            return drhd;
   29.35 +        }
   29.36 +    }
   29.37 +    return NULL;
   29.38 +}
   29.39 +
   29.40 +struct iommu * ioapic_to_iommu(unsigned int apic_id)
   29.41 +{
   29.42 +    struct acpi_drhd_unit *drhd;
   29.43 +
   29.44 +    list_for_each_entry( drhd, &acpi_drhd_units, list ) {
   29.45 +        if ( acpi_ioapic_device_match(&drhd->ioapic_list, apic_id) ) {
   29.46 +            dprintk(XENLOG_INFO VTDPREFIX,
   29.47 +                    "ioapic_to_iommu: drhd->address = %lx\n",
   29.48 +                    drhd->address);
   29.49 +            return drhd->iommu;
   29.50 +        }
   29.51 +    }
   29.52 +    dprintk(XENLOG_WARNING VTDPREFIX, "returning NULL\n");
   29.53 +    return NULL;
   29.54 +}
   29.55 +
   29.56  static int acpi_pci_device_match(struct pci_dev *devices, int cnt,
   29.57                                   struct pci_dev *dev)
   29.58  {
   29.59 @@ -111,18 +151,18 @@ struct acpi_drhd_unit * acpi_find_matche
   29.60          if ( acpi_pci_device_match(drhd->devices,
   29.61                                     drhd->devices_cnt, dev) )
   29.62          {
   29.63 -            gdprintk(XENLOG_INFO VTDPREFIX, 
   29.64 -                     "acpi_find_matched_drhd_unit: drhd->address = %lx\n",
   29.65 -                     drhd->address);
   29.66 +            dprintk(XENLOG_INFO VTDPREFIX, 
   29.67 +                    "acpi_find_matched_drhd_unit: drhd->address = %lx\n",
   29.68 +                    drhd->address);
   29.69              return drhd;
   29.70          }
   29.71      }
   29.72  
   29.73      if ( include_all_drhd )
   29.74      {
   29.75 -        gdprintk(XENLOG_INFO VTDPREFIX, 
   29.76 -                 "acpi_find_matched_drhd_unit:include_all_drhd->addr = %lx\n",
   29.77 -                 include_all_drhd->address);
   29.78 +        dprintk(XENLOG_INFO VTDPREFIX, 
   29.79 +                "acpi_find_matched_drhd_unit:include_all_drhd->addr = %lx\n",
   29.80 +                include_all_drhd->address);
   29.81          return include_all_drhd;
   29.82      }
   29.83  
   29.84 @@ -160,8 +200,8 @@ struct acpi_atsr_unit * acpi_find_matche
   29.85  
   29.86      if ( all_ports_atsru )
   29.87      {
   29.88 -        gdprintk(XENLOG_INFO VTDPREFIX,
   29.89 -                 "acpi_find_matched_atsr_unit: all_ports_atsru\n");
   29.90 +        dprintk(XENLOG_INFO VTDPREFIX,
   29.91 +                "acpi_find_matched_atsr_unit: all_ports_atsru\n");
   29.92          return all_ports_atsru;;
   29.93      }
   29.94  
   29.95 @@ -180,9 +220,10 @@ static int scope_device_count(void *star
   29.96      while ( start < end )
   29.97      {
   29.98          scope = start;
   29.99 -        if ( scope->length < MIN_SCOPE_LEN )
  29.100 +        if ( (scope->length < MIN_SCOPE_LEN) ||
  29.101 +             (scope->dev_type >= ACPI_DEV_ENTRY_COUNT) )
  29.102          {
  29.103 -            printk(KERN_WARNING PREFIX "Invalid device scope\n");
  29.104 +            dprintk(XENLOG_WARNING VTDPREFIX, "Invalid device scope\n");
  29.105              return -EINVAL;
  29.106          }
  29.107  
  29.108 @@ -199,16 +240,16 @@ static int scope_device_count(void *star
  29.109  
  29.110          if ( scope->dev_type == ACPI_DEV_ENDPOINT )
  29.111          {
  29.112 -            printk(KERN_INFO PREFIX
  29.113 -                   "found endpoint: bdf = %x:%x:%x\n",
  29.114 -                   bus, path->dev, path->fn);
  29.115 +            dprintk(XENLOG_INFO VTDPREFIX,
  29.116 +                    "found endpoint: bdf = %x:%x:%x\n",
  29.117 +                    bus, path->dev, path->fn);
  29.118              count++;
  29.119          }
  29.120          else if ( scope->dev_type == ACPI_DEV_P2PBRIDGE )
  29.121          {
  29.122 -            printk(KERN_INFO PREFIX
  29.123 -                   "found bridge: bdf = %x:%x:%x\n",
  29.124 -                   bus, path->dev, path->fn);
  29.125 +            dprintk(XENLOG_INFO VTDPREFIX,
  29.126 +                    "found bridge: bdf = %x:%x:%x\n",
  29.127 +                    bus, path->dev, path->fn);
  29.128              sec_bus = read_pci_config_byte(
  29.129                  bus, path->dev, path->fn, PCI_SECONDARY_BUS);
  29.130              sub_bus = read_pci_config_byte(
  29.131 @@ -237,16 +278,16 @@ static int scope_device_count(void *star
  29.132          }
  29.133          else if ( scope->dev_type == ACPI_DEV_IOAPIC )
  29.134          {
  29.135 -            printk(KERN_INFO PREFIX
  29.136 -                   "found IOAPIC: bdf = %x:%x:%x\n",
  29.137 -                   bus, path->dev, path->fn);
  29.138 +            dprintk(XENLOG_INFO VTDPREFIX,
  29.139 +                    "found IOAPIC: bdf = %x:%x:%x\n",
  29.140 +                    bus, path->dev, path->fn);
  29.141              count++;
  29.142          }
  29.143          else
  29.144          {
  29.145 -            printk(KERN_INFO PREFIX
  29.146 -                   "found MSI HPET: bdf = %x:%x:%x\n",
  29.147 -                   bus, path->dev, path->fn);
  29.148 +            dprintk(XENLOG_INFO VTDPREFIX,
  29.149 +                    "found MSI HPET: bdf = %x:%x:%x\n",
  29.150 +                    bus, path->dev, path->fn);
  29.151              count++;
  29.152          }
  29.153  
  29.154 @@ -256,8 +297,8 @@ static int scope_device_count(void *star
  29.155      return count;
  29.156  }
  29.157  
  29.158 -static int __init acpi_parse_dev_scope(void *start, void *end, int *cnt,
  29.159 -                                       struct pci_dev **devices)
  29.160 +static int __init acpi_parse_dev_scope(
  29.161 +    void *start, void *end, void *acpi_entry, int type)
  29.162  {
  29.163      struct acpi_dev_scope *scope;
  29.164      u8 bus, sub_bus, sec_bus;
  29.165 @@ -268,10 +309,33 @@ static int __init acpi_parse_dev_scope(v
  29.166      u8 dev, func;
  29.167      u32 l;
  29.168  
  29.169 +    int *cnt = NULL;
  29.170 +    struct pci_dev **devices = NULL;
  29.171 +    struct acpi_drhd_unit *dmaru = (struct acpi_drhd_unit *) acpi_entry;
  29.172 +    struct acpi_rmrr_unit *rmrru = (struct acpi_rmrr_unit *) acpi_entry;
  29.173 +    struct acpi_atsr_unit *atsru = (struct acpi_atsr_unit *) acpi_entry;
  29.174 +
  29.175 +    switch (type) {
  29.176 +        case DMAR_TYPE:
  29.177 +            cnt = &(dmaru->devices_cnt);
  29.178 +            devices = &(dmaru->devices);
  29.179 +            break;
  29.180 +        case RMRR_TYPE:
  29.181 +            cnt = &(rmrru->devices_cnt);
  29.182 +            devices = &(rmrru->devices);
  29.183 +            break;
  29.184 +        case ATSR_TYPE:
  29.185 +            cnt = &(atsru->devices_cnt);
  29.186 +            devices = &(atsru->devices);
  29.187 +            break;
  29.188 +        default:
  29.189 +            dprintk(XENLOG_ERR VTDPREFIX, "invalid vt-d acpi entry type\n");
  29.190 +    }
  29.191 +
  29.192      *cnt = scope_device_count(start, end);
  29.193      if ( *cnt == 0 )
  29.194      {
  29.195 -        printk(KERN_INFO PREFIX "acpi_parse_dev_scope: no device\n");
  29.196 +        dprintk(XENLOG_INFO VTDPREFIX, "acpi_parse_dev_scope: no device\n");
  29.197          return 0;
  29.198      }
  29.199  
  29.200 @@ -298,18 +362,18 @@ static int __init acpi_parse_dev_scope(v
  29.201  
  29.202          if ( scope->dev_type == ACPI_DEV_ENDPOINT )
  29.203          {
  29.204 -            printk(KERN_INFO PREFIX
  29.205 -                   "found endpoint: bdf = %x:%x:%x\n",
  29.206 -                   bus, path->dev, path->fn);
  29.207 +            dprintk(XENLOG_INFO VTDPREFIX,
  29.208 +                    "found endpoint: bdf = %x:%x:%x\n",
  29.209 +                    bus, path->dev, path->fn);
  29.210              pdev->bus = bus;
  29.211              pdev->devfn = PCI_DEVFN(path->dev, path->fn);
  29.212              pdev++;
  29.213          }
  29.214          else if ( scope->dev_type == ACPI_DEV_P2PBRIDGE )
  29.215          {
  29.216 -            printk(KERN_INFO PREFIX
  29.217 -                   "found bridge: bus = %x dev = %x func = %x\n",
  29.218 -                   bus, path->dev, path->fn);
  29.219 +            dprintk(XENLOG_INFO VTDPREFIX,
  29.220 +                    "found bridge: bus = %x dev = %x func = %x\n",
  29.221 +                    bus, path->dev, path->fn);
  29.222              sec_bus = read_pci_config_byte(
  29.223                  bus, path->dev, path->fn, PCI_SECONDARY_BUS);
  29.224              sub_bus = read_pci_config_byte(
  29.225 @@ -348,16 +412,15 @@ static int __init acpi_parse_dev_scope(v
  29.226              acpi_ioapic_unit->ioapic.bdf.bus = bus;
  29.227              acpi_ioapic_unit->ioapic.bdf.dev = path->dev;
  29.228              acpi_ioapic_unit->ioapic.bdf.func = path->fn;
  29.229 -            list_add(&acpi_ioapic_unit->list, &acpi_ioapic_units);
  29.230 -            printk(KERN_INFO PREFIX
  29.231 -                   "found IOAPIC: bus = %x dev = %x func = %x\n",
  29.232 -                   bus, path->dev, path->fn);
  29.233 +            list_add(&acpi_ioapic_unit->list, &dmaru->ioapic_list);
  29.234 +            dprintk(XENLOG_INFO VTDPREFIX,
  29.235 +                    "found IOAPIC: bus = %x dev = %x func = %x\n",
  29.236 +                    bus, path->dev, path->fn);
  29.237          }
  29.238          else
  29.239 -            printk(KERN_INFO PREFIX
  29.240 -                   "found MSI HPET: bus = %x dev = %x func = %x\n",
  29.241 -                   bus, path->dev, path->fn);
  29.242 -        
  29.243 +            dprintk(XENLOG_INFO VTDPREFIX,
  29.244 +                    "found MSI HPET: bus = %x dev = %x func = %x\n",
  29.245 +                    bus, path->dev, path->fn);
  29.246          start += scope->length;
  29.247      }
  29.248  
  29.249 @@ -371,6 +434,7 @@ acpi_parse_one_drhd(struct acpi_dmar_ent
  29.250      struct acpi_drhd_unit *dmaru;
  29.251      int ret = 0;
  29.252      static int include_all;
  29.253 +    void *dev_scope_start, *dev_scope_end;
  29.254  
  29.255      dmaru = xmalloc(struct acpi_drhd_unit);
  29.256      if ( !dmaru )
  29.257 @@ -379,21 +443,22 @@ acpi_parse_one_drhd(struct acpi_dmar_ent
  29.258  
  29.259      dmaru->address = drhd->address;
  29.260      dmaru->include_all = drhd->flags & 1; /* BIT0: INCLUDE_ALL */
  29.261 -    printk(KERN_INFO PREFIX "dmaru->address = %lx\n", dmaru->address);
  29.262 +    INIT_LIST_HEAD(&dmaru->ioapic_list);
  29.263 +    dprintk(XENLOG_INFO VTDPREFIX, "dmaru->address = %lx\n", dmaru->address);
  29.264  
  29.265 -    if ( !dmaru->include_all )
  29.266 -        ret = acpi_parse_dev_scope(
  29.267 -            (void *)(drhd + 1),
  29.268 -            ((void *)drhd) + header->length,
  29.269 -            &dmaru->devices_cnt, &dmaru->devices);
  29.270 -    else
  29.271 +    dev_scope_start = (void *)(drhd + 1);
  29.272 +    dev_scope_end   = ((void *)drhd) + header->length;
  29.273 +    ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
  29.274 +                               dmaru, DMAR_TYPE);
  29.275 +
  29.276 +    if ( dmaru->include_all )
  29.277      {
  29.278 -        printk(KERN_INFO PREFIX "found INCLUDE_ALL\n");
  29.279 +        dprintk(XENLOG_INFO VTDPREFIX, "found INCLUDE_ALL\n");
  29.280          /* Only allow one INCLUDE_ALL */
  29.281          if ( include_all )
  29.282          {
  29.283 -            printk(KERN_WARNING PREFIX "Only one INCLUDE_ALL "
  29.284 -                   "device scope is allowed\n");
  29.285 +            dprintk(XENLOG_WARNING VTDPREFIX,
  29.286 +                    "Only one INCLUDE_ALL device scope is allowed\n");
  29.287              ret = -EINVAL;
  29.288          }
  29.289          include_all = 1;
  29.290 @@ -411,6 +476,7 @@ acpi_parse_one_rmrr(struct acpi_dmar_ent
  29.291  {
  29.292      struct acpi_table_rmrr *rmrr = (struct acpi_table_rmrr *)header;
  29.293      struct acpi_rmrr_unit *rmrru;
  29.294 +    void *dev_scope_start, *dev_scope_end;
  29.295      int ret = 0;
  29.296  
  29.297      rmrru = xmalloc(struct acpi_rmrr_unit);
  29.298 @@ -420,15 +486,10 @@ acpi_parse_one_rmrr(struct acpi_dmar_ent
  29.299  
  29.300      rmrru->base_address = rmrr->base_address;
  29.301      rmrru->end_address = rmrr->end_address;
  29.302 -    printk(KERN_INFO PREFIX
  29.303 -           "acpi_parse_one_rmrr: base=%"PRIx64" end=%"PRIx64"\n",
  29.304 -           rmrr->base_address, rmrr->end_address);
  29.305 -
  29.306 -    ret = acpi_parse_dev_scope(
  29.307 -        (void *)(rmrr + 1),
  29.308 -        ((void*)rmrr) + header->length,
  29.309 -        &rmrru->devices_cnt, &rmrru->devices);
  29.310 -
  29.311 +    dev_scope_start = (void *)(rmrr + 1);
  29.312 +    dev_scope_end   = ((void *)rmrr) + header->length;
  29.313 +    ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
  29.314 +                               rmrru, RMRR_TYPE);
  29.315      if ( ret || (rmrru->devices_cnt == 0) )
  29.316          xfree(rmrru);
  29.317      else
  29.318 @@ -443,6 +504,7 @@ acpi_parse_one_atsr(struct acpi_dmar_ent
  29.319      struct acpi_atsr_unit *atsru;
  29.320      int ret = 0;
  29.321      static int all_ports;
  29.322 +    void *dev_scope_start, *dev_scope_end;
  29.323  
  29.324      atsru = xmalloc(struct acpi_atsr_unit);
  29.325      if ( !atsru )
  29.326 @@ -451,18 +513,19 @@ acpi_parse_one_atsr(struct acpi_dmar_ent
  29.327  
  29.328      atsru->all_ports = atsr->flags & 1; /* BIT0: ALL_PORTS */
  29.329      if ( !atsru->all_ports )
  29.330 -        ret = acpi_parse_dev_scope(
  29.331 -            (void *)(atsr + 1),
  29.332 -            ((void *)atsr) + header->length,
  29.333 -            &atsru->devices_cnt, &atsru->devices);
  29.334 -    else
  29.335      {
  29.336 -        printk(KERN_INFO PREFIX "found ALL_PORTS\n");
  29.337 +        dev_scope_start = (void *)(atsr + 1);
  29.338 +        dev_scope_end   = ((void *)atsr) + header->length;
  29.339 +        ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
  29.340 +                                   atsru, ATSR_TYPE);
  29.341 +    }
  29.342 +    else {
  29.343 +        dprintk(XENLOG_INFO VTDPREFIX, "found ALL_PORTS\n");
  29.344          /* Only allow one ALL_PORTS */
  29.345          if ( all_ports )
  29.346          {
  29.347 -            printk(KERN_WARNING PREFIX "Only one ALL_PORTS "
  29.348 -                   "device scope is allowed\n");
  29.349 +            dprintk(XENLOG_WARNING VTDPREFIX,
  29.350 +                    "Only one ALL_PORTS device scope is allowed\n");
  29.351              ret = -EINVAL;
  29.352          }
  29.353          all_ports = 1;
  29.354 @@ -488,19 +551,19 @@ static int __init acpi_parse_dmar(unsign
  29.355      dmar = (struct acpi_table_dmar *)__acpi_map_table(phys_addr, size);
  29.356      if ( !dmar )
  29.357      {
  29.358 -        printk(KERN_WARNING PREFIX "Unable to map DMAR\n");
  29.359 +        dprintk(XENLOG_WARNING VTDPREFIX, "Unable to map DMAR\n");
  29.360          return -ENODEV;
  29.361      }
  29.362  
  29.363      if ( !dmar->haw )
  29.364      {
  29.365 -        printk(KERN_WARNING PREFIX "Zero: Invalid DMAR haw\n");
  29.366 +        dprintk(XENLOG_WARNING VTDPREFIX, "Zero: Invalid DMAR haw\n");
  29.367          return -EINVAL;
  29.368      }
  29.369  
  29.370      dmar_host_address_width = dmar->haw;
  29.371 -    printk(KERN_INFO PREFIX "Host address width %d\n",
  29.372 -           dmar_host_address_width);
  29.373 +    dprintk(XENLOG_INFO VTDPREFIX, "Host address width %d\n",
  29.374 +            dmar_host_address_width);
  29.375  
  29.376      entry_header = (struct acpi_dmar_entry_header *)(dmar + 1);
  29.377      while ( ((unsigned long)entry_header) <
  29.378 @@ -509,19 +572,19 @@ static int __init acpi_parse_dmar(unsign
  29.379          switch ( entry_header->type )
  29.380          {
  29.381          case ACPI_DMAR_DRHD:
  29.382 -            printk(KERN_INFO PREFIX "found ACPI_DMAR_DRHD\n");
  29.383 +            dprintk(XENLOG_INFO VTDPREFIX, "found ACPI_DMAR_DRHD\n");
  29.384              ret = acpi_parse_one_drhd(entry_header);
  29.385              break;
  29.386          case ACPI_DMAR_RMRR:
  29.387 -            printk(KERN_INFO PREFIX "found ACPI_DMAR_RMRR\n");
  29.388 +            dprintk(XENLOG_INFO VTDPREFIX, "found ACPI_DMAR_RMRR\n");
  29.389              ret = acpi_parse_one_rmrr(entry_header);
  29.390              break;
  29.391          case ACPI_DMAR_ATSR:
  29.392 -            printk(KERN_INFO PREFIX "found ACPI_DMAR_ATSR\n");
  29.393 +            dprintk(XENLOG_INFO VTDPREFIX, "found ACPI_DMAR_ATSR\n");
  29.394              ret = acpi_parse_one_atsr(entry_header);
  29.395              break;
  29.396          default:
  29.397 -            printk(KERN_WARNING PREFIX "Unknown DMAR structure type\n");
  29.398 +            dprintk(XENLOG_WARNING VTDPREFIX, "Unknown DMAR structure type\n");
  29.399              ret = -EINVAL;
  29.400              break;
  29.401          }
  29.402 @@ -551,7 +614,7 @@ int acpi_dmar_init(void)
  29.403  
  29.404      if ( list_empty(&acpi_drhd_units) )
  29.405      {
  29.406 -        printk(KERN_ERR PREFIX "No DMAR devices found\n");
  29.407 +        dprintk(XENLOG_ERR VTDPREFIX, "No DMAR devices found\n");
  29.408          vtd_enabled = 0;
  29.409          return -ENODEV;
  29.410      }
    30.1 --- a/xen/arch/x86/hvm/vmx/vtd/dmar.h	Thu Jan 17 12:17:14 2008 -0700
    30.2 +++ b/xen/arch/x86/hvm/vmx/vtd/dmar.h	Fri Jan 18 13:49:48 2008 -0700
    30.3 @@ -26,6 +26,20 @@
    30.4  
    30.5  extern u8 dmar_host_address_width;
    30.6  
    30.7 +/* This one is for interrupt remapping */
    30.8 +struct acpi_ioapic_unit {
    30.9 +    struct list_head list;
   30.10 +    int apic_id;
   30.11 +    union {
   30.12 +        u16 info;
   30.13 +        struct {
   30.14 +            u16 func: 3,
   30.15 +                dev:  5,
   30.16 +                bus:  8;
   30.17 +        }bdf;
   30.18 +    }ioapic;
   30.19 +};
   30.20 +
   30.21  struct acpi_drhd_unit {
   30.22      struct list_head list;
   30.23      unsigned long    address; /* register base address of the unit */
   30.24 @@ -33,6 +47,7 @@ struct acpi_drhd_unit {
   30.25      int    devices_cnt;
   30.26      u8    include_all:1;
   30.27      struct iommu *iommu;
   30.28 +    struct list_head ioapic_list;
   30.29  };
   30.30  
   30.31  struct acpi_rmrr_unit {
   30.32 @@ -73,19 +88,9 @@ struct acpi_atsr_unit {
   30.33  struct acpi_drhd_unit * acpi_find_matched_drhd_unit(struct pci_dev *dev);
   30.34  struct acpi_rmrr_unit * acpi_find_matched_rmrr_unit(struct pci_dev *dev);
   30.35  
   30.36 -/* This one is for interrupt remapping */
   30.37 -struct acpi_ioapic_unit {
   30.38 -    struct list_head list;
   30.39 -    int apic_id;
   30.40 -    union {
   30.41 -        u16 info;
   30.42 -        struct {
   30.43 -            u16 bus: 8,
   30.44 -                dev: 5,
   30.45 -                func: 3;
   30.46 -        }bdf;
   30.47 -    }ioapic;
   30.48 -};
   30.49 +#define DMAR_TYPE 1
   30.50 +#define RMRR_TYPE 2
   30.51 +#define ATSR_TYPE 3
   30.52  
   30.53  #define DMAR_OPERATION_TIMEOUT (HZ*60) /* 1m */
   30.54  #define time_after(a,b)         \
    31.1 --- a/xen/arch/x86/hvm/vmx/vtd/utils.c	Thu Jan 17 12:17:14 2008 -0700
    31.2 +++ b/xen/arch/x86/hvm/vmx/vtd/utils.c	Fri Jan 18 13:49:48 2008 -0700
    31.3 @@ -146,12 +146,14 @@ u32 get_level_index(unsigned long gmfn, 
    31.4      return gmfn & LEVEL_MASK;
    31.5  }
    31.6  
    31.7 -void print_vtd_entries(struct domain *d, int bus, int devfn,
    31.8 -                       unsigned long gmfn)
    31.9 +void print_vtd_entries(
   31.10 +    struct domain *d, 
   31.11 +    struct iommu *iommu,
   31.12 +    int bus, int devfn,
   31.13 +    unsigned long gmfn)
   31.14  {
   31.15      struct hvm_iommu *hd = domain_hvm_iommu(d);
   31.16      struct acpi_drhd_unit *drhd;
   31.17 -    struct iommu *iommu;
   31.18      struct context_entry *ctxt_entry;
   31.19      struct root_entry *root_entry;
   31.20      struct dma_pte pte;
   31.21 @@ -175,7 +177,6 @@ void print_vtd_entries(struct domain *d,
   31.22      {
   31.23          printk("---- print_vtd_entries %d ----\n", i++);
   31.24  
   31.25 -        iommu = drhd->iommu;
   31.26          root_entry = iommu->root_entry;
   31.27          if ( root_entry == NULL )
   31.28          {
    32.1 --- a/xen/arch/x86/traps.c	Thu Jan 17 12:17:14 2008 -0700
    32.2 +++ b/xen/arch/x86/traps.c	Fri Jan 18 13:49:48 2008 -0700
    32.3 @@ -2825,7 +2825,7 @@ long unregister_guest_nmi_callback(void)
    32.4      return 0;
    32.5  }
    32.6  
    32.7 -long do_set_trap_table(XEN_GUEST_HANDLE(trap_info_t) traps)
    32.8 +long do_set_trap_table(XEN_GUEST_HANDLE(const_trap_info_t) traps)
    32.9  {
   32.10      struct trap_info cur;
   32.11      struct vcpu *curr = current;
    33.1 --- a/xen/arch/x86/x86_32/traps.c	Thu Jan 17 12:17:14 2008 -0700
    33.2 +++ b/xen/arch/x86/x86_32/traps.c	Fri Jan 18 13:49:48 2008 -0700
    33.3 @@ -419,7 +419,7 @@ static long unregister_guest_callback(st
    33.4  }
    33.5  
    33.6  
    33.7 -long do_callback_op(int cmd, XEN_GUEST_HANDLE(void) arg)
    33.8 +long do_callback_op(int cmd, XEN_GUEST_HANDLE(const_void) arg)
    33.9  {
   33.10      long ret;
   33.11  
    34.1 --- a/xen/arch/x86/x86_64/traps.c	Thu Jan 17 12:17:14 2008 -0700
    34.2 +++ b/xen/arch/x86/x86_64/traps.c	Fri Jan 18 13:49:48 2008 -0700
    34.3 @@ -470,7 +470,7 @@ static long unregister_guest_callback(st
    34.4  }
    34.5  
    34.6  
    34.7 -long do_callback_op(int cmd, XEN_GUEST_HANDLE(void) arg)
    34.8 +long do_callback_op(int cmd, XEN_GUEST_HANDLE(const_void) arg)
    34.9  {
   34.10      long ret;
   34.11  
    35.1 --- a/xen/include/asm-x86/hvm/vmx/intel-iommu.h	Thu Jan 17 12:17:14 2008 -0700
    35.2 +++ b/xen/include/asm-x86/hvm/vmx/intel-iommu.h	Fri Jan 18 13:49:48 2008 -0700
    35.3 @@ -127,32 +127,34 @@
    35.4  #define DMA_TLB_IVA_HINT(x) ((((u64)x) & 1) << 6)
    35.5  
    35.6  /* GCMD_REG */
    35.7 -#define DMA_GCMD_TE (((u64)1) << 31)
    35.8 -#define DMA_GCMD_SRTP (((u64)1) << 30)
    35.9 -#define DMA_GCMD_SFL (((u64)1) << 29)
   35.10 -#define DMA_GCMD_EAFL (((u64)1) << 28)
   35.11 -#define DMA_GCMD_WBF (((u64)1) << 27)
   35.12 -#define DMA_GCMD_QIE (((u64)1) << 26)
   35.13 -#define DMA_GCMD_IRE (((u64)1) << 25)
   35.14 -#define DMA_GCMD_SIRTP (((u64)1) << 24)
   35.15 +#define DMA_GCMD_TE     (((u64)1) << 31)
   35.16 +#define DMA_GCMD_SRTP   (((u64)1) << 30)
   35.17 +#define DMA_GCMD_SFL    (((u64)1) << 29)
   35.18 +#define DMA_GCMD_EAFL   (((u64)1) << 28)
   35.19 +#define DMA_GCMD_WBF    (((u64)1) << 27)
   35.20 +#define DMA_GCMD_QIE    (((u64)1) << 26)
   35.21 +#define DMA_GCMD_IRE    (((u64)1) << 25)
   35.22 +#define DMA_GCMD_SIRTP  (((u64)1) << 24)
   35.23 +#define DMA_GCMD_CFI    (((u64)1) << 23)
   35.24  
   35.25  /* GSTS_REG */
   35.26 -#define DMA_GSTS_TES (((u64)1) << 31)
   35.27 -#define DMA_GSTS_RTPS (((u64)1) << 30)
   35.28 -#define DMA_GSTS_FLS (((u64)1) << 29)
   35.29 -#define DMA_GSTS_AFLS (((u64)1) << 28)
   35.30 -#define DMA_GSTS_WBFS (((u64)1) << 27)
   35.31 -#define DMA_GSTS_IRTPS (((u64)1) << 24)
   35.32 +#define DMA_GSTS_TES    (((u64)1) << 31)
   35.33 +#define DMA_GSTS_RTPS   (((u64)1) << 30)
   35.34 +#define DMA_GSTS_FLS    (((u64)1) << 29)
   35.35 +#define DMA_GSTS_AFLS   (((u64)1) << 28)
   35.36 +#define DMA_GSTS_WBFS   (((u64)1) << 27)
   35.37  #define DMA_GSTS_QIES   (((u64)1) <<26)
   35.38  #define DMA_GSTS_IRES   (((u64)1) <<25)
   35.39 +#define DMA_GSTS_SIRTPS (((u64)1) << 24)
   35.40 +#define DMA_GSTS_CFIS   (((u64)1) <<23)
   35.41  
   35.42  /* PMEN_REG */
   35.43 -#define DMA_PMEN_EPM   (((u32)1) << 31)
   35.44 -#define DMA_PMEN_PRS   (((u32)1) << 0)
   35.45 +#define DMA_PMEN_EPM    (((u32)1) << 31)
   35.46 +#define DMA_PMEN_PRS    (((u32)1) << 0)
   35.47  
   35.48  /* CCMD_REG */
   35.49  #define DMA_CCMD_INVL_GRANU_OFFSET  61
   35.50 -#define DMA_CCMD_ICC (((u64)1) << 63)
   35.51 +#define DMA_CCMD_ICC   (((u64)1) << 63)
   35.52  #define DMA_CCMD_GLOBAL_INVL (((u64)1) << 61)
   35.53  #define DMA_CCMD_DOMAIN_INVL (((u64)2) << 61)
   35.54  #define DMA_CCMD_DEVICE_INVL (((u64)3) << 61)
   35.55 @@ -171,8 +173,14 @@
   35.56  #define DMA_FECTL_IM (((u64)1) << 31)
   35.57  
   35.58  /* FSTS_REG */
   35.59 -#define DMA_FSTS_PPF ((u64)2)
   35.60 -#define DMA_FSTS_PFO ((u64)1)
   35.61 +#define DMA_FSTS_PFO ((u64)1 << 0)
   35.62 +#define DMA_FSTS_PPF ((u64)1 << 1)
   35.63 +#define DMA_FSTS_AFO ((u64)1 << 2)
   35.64 +#define DMA_FSTS_APF ((u64)1 << 3)
   35.65 +#define DMA_FSTS_IQE ((u64)1 << 4)
   35.66 +#define DMA_FSTS_ICE ((u64)1 << 5)
   35.67 +#define DMA_FSTS_ITE ((u64)1 << 6)
   35.68 +#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
   35.69  #define dma_fsts_fault_record_index(s) (((s) >> 8) & 0xff)
   35.70  
   35.71  /* FRCD_REG, 32 bits access */
   35.72 @@ -266,8 +274,10 @@ struct dma_pte {
   35.73  
   35.74  /* interrupt remap entry */
   35.75  struct iremap_entry {
   35.76 +  union {
   35.77 +    u64 lo_val;
   35.78      struct {
   35.79 -        u64 present : 1,
   35.80 +        u64 p       : 1,
   35.81              fpd     : 1,
   35.82              dm      : 1,
   35.83              rh      : 1,
   35.84 @@ -279,12 +289,16 @@ struct iremap_entry {
   35.85              res_2   : 8,
   35.86              dst     : 32;
   35.87      }lo;
   35.88 +  };
   35.89 +  union {
   35.90 +    u64 hi_val;
   35.91      struct {
   35.92          u64 sid     : 16,
   35.93              sq      : 2,
   35.94              svt     : 2,
   35.95              res_1   : 44;
   35.96      }hi;
   35.97 +  };
   35.98  };
   35.99  #define IREMAP_ENTRY_NR (PAGE_SIZE_4K/sizeof(struct iremap_entry))
  35.100  #define iremap_present(v) ((v).lo & 1)
  35.101 @@ -386,11 +400,11 @@ struct poll_info {
  35.102  
  35.103  #define RESERVED_VAL        0
  35.104  
  35.105 -#define TYPE_INVAL_CONTEXT  1
  35.106 -#define TYPE_INVAL_IOTLB    2
  35.107 -#define TYPE_INVAL_DEVICE_IOTLB 3
  35.108 -#define TYPE_INVAL_IEC          4
  35.109 -#define TYPE_INVAL_WAIT         5
  35.110 +#define TYPE_INVAL_CONTEXT      0x1
  35.111 +#define TYPE_INVAL_IOTLB        0x2
  35.112 +#define TYPE_INVAL_DEVICE_IOTLB 0x3
  35.113 +#define TYPE_INVAL_IEC          0x4
  35.114 +#define TYPE_INVAL_WAIT         0x5
  35.115  
  35.116  #define NOTIFY_TYPE_POLL        1
  35.117  #define NOTIFY_TYPE_INTR        1
  35.118 @@ -400,6 +414,10 @@ struct poll_info {
  35.119  
  35.120  #define IEC_GLOBAL_INVL         0
  35.121  #define IEC_INDEX_INVL          1
  35.122 +#define IRTA_REG_EIME_SHIFT     11
  35.123 +#define IRTA_REG_TABLE_SIZE     7    // 4k page = 256 * 16 byte entries
  35.124 +                                     // 2^^(IRTA_REG_TABLE_SIZE + 1) = 256
  35.125 +                                     // IRTA_REG_TABLE_SIZE = 7
  35.126  
  35.127  #define VTD_PAGE_TABLE_LEVEL_3  3
  35.128  #define VTD_PAGE_TABLE_LEVEL_4  4
  35.129 @@ -414,4 +432,29 @@ extern struct list_head acpi_drhd_units;
  35.130  extern struct list_head acpi_rmrr_units;
  35.131  extern struct list_head acpi_ioapic_units;
  35.132  
  35.133 +struct qi_ctrl {
  35.134 +    struct qinval_entry *qinval;         /* queue invalidation page */
  35.135 +    int qinval_index;                    /* queue invalidation index */
  35.136 +    spinlock_t qinval_lock;      /* lock for queue invalidation page */
  35.137 +    spinlock_t qinval_poll_lock; /* lock for queue invalidation poll addr */
  35.138 +    volatile u32 qinval_poll_status;     /* used by poll methord to sync */
  35.139 +};
  35.140 +
  35.141 +struct ir_ctrl {
  35.142 +    struct iremap_entry *iremap;         /* interrupt remap table */
  35.143 +    int iremap_index;                    /* interrupt remap index */
  35.144 +    spinlock_t iremap_lock;      /* lock for irq remappping table */
  35.145 +};
  35.146 +
  35.147 +struct iommu_flush {
  35.148 +    int (*context)(void *iommu, u16 did, u16 source_id, u8 function_mask, u64 type, int non_present_entry_flush);
  35.149 +    int (*iotlb)(void *iommu, u16 did, u64 addr, unsigned int size_order, u64 type, int non_present_entry_flush);
  35.150 +};
  35.151 +
  35.152 +struct intel_iommu {
  35.153 +    struct qi_ctrl qi_ctrl;
  35.154 +    struct ir_ctrl ir_ctrl;
  35.155 +    struct iommu_flush flush; 
  35.156 +};
  35.157 +
  35.158  #endif
    36.1 --- a/xen/include/asm-x86/hypercall.h	Thu Jan 17 12:17:14 2008 -0700
    36.2 +++ b/xen/include/asm-x86/hypercall.h	Fri Jan 18 13:49:48 2008 -0700
    36.3 @@ -34,7 +34,7 @@ do_physdev_op_compat(
    36.4  
    36.5  extern long
    36.6  do_set_trap_table(
    36.7 -    XEN_GUEST_HANDLE(trap_info_t) traps);
    36.8 +    XEN_GUEST_HANDLE(const_trap_info_t) traps);
    36.9  
   36.10  extern int
   36.11  do_mmu_update(
    37.1 --- a/xen/include/public/arch-ia64.h	Thu Jan 17 12:17:14 2008 -0700
    37.2 +++ b/xen/include/public/arch-ia64.h	Fri Jan 18 13:49:48 2008 -0700
    37.3 @@ -36,7 +36,9 @@
    37.4  #endif
    37.5  
    37.6  #define __DEFINE_XEN_GUEST_HANDLE(name, type) \
    37.7 -    ___DEFINE_XEN_GUEST_HANDLE(name, type)
    37.8 +    ___DEFINE_XEN_GUEST_HANDLE(name, type);   \
    37.9 +    ___DEFINE_XEN_GUEST_HANDLE(const_##name, const type)
   37.10 +
   37.11  #define DEFINE_XEN_GUEST_HANDLE(name)   __DEFINE_XEN_GUEST_HANDLE(name, name)
   37.12  #define XEN_GUEST_HANDLE(name)          __guest_handle_ ## name
   37.13  #define XEN_GUEST_HANDLE_64(name)       XEN_GUEST_HANDLE(name)
   37.14 @@ -47,18 +49,7 @@
   37.15  #endif
   37.16  
   37.17  #ifndef __ASSEMBLY__
   37.18 -/* Guest handles for primitive C types. */
   37.19 -__DEFINE_XEN_GUEST_HANDLE(uchar, unsigned char);
   37.20 -__DEFINE_XEN_GUEST_HANDLE(uint,  unsigned int);
   37.21 -__DEFINE_XEN_GUEST_HANDLE(ulong, unsigned long);
   37.22 -__DEFINE_XEN_GUEST_HANDLE(u64,   unsigned long);
   37.23 -DEFINE_XEN_GUEST_HANDLE(char);
   37.24 -DEFINE_XEN_GUEST_HANDLE(int);
   37.25 -DEFINE_XEN_GUEST_HANDLE(long);
   37.26 -DEFINE_XEN_GUEST_HANDLE(void);
   37.27 -
   37.28  typedef unsigned long xen_pfn_t;
   37.29 -DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
   37.30  #define PRI_xen_pfn "lx"
   37.31  #endif
   37.32  
    38.1 --- a/xen/include/public/arch-powerpc.h	Thu Jan 17 12:17:14 2008 -0700
    38.2 +++ b/xen/include/public/arch-powerpc.h	Fri Jan 18 13:49:48 2008 -0700
    38.3 @@ -32,7 +32,8 @@
    38.4      } __attribute__((__aligned__(8))) __guest_handle_ ## name
    38.5  
    38.6  #define __DEFINE_XEN_GUEST_HANDLE(name, type) \
    38.7 -    ___DEFINE_XEN_GUEST_HANDLE(name, type)
    38.8 +    ___DEFINE_XEN_GUEST_HANDLE(name, type);   \
    38.9 +    ___DEFINE_XEN_GUEST_HANDLE(const_##name, const type)
   38.10  #define DEFINE_XEN_GUEST_HANDLE(name) __DEFINE_XEN_GUEST_HANDLE(name, name)
   38.11  #define XEN_GUEST_HANDLE(name)        __guest_handle_ ## name
   38.12  #define set_xen_guest_handle(hnd, val) \
   38.13 @@ -47,17 +48,7 @@
   38.14  #endif
   38.15  
   38.16  #ifndef __ASSEMBLY__
   38.17 -/* Guest handles for primitive C types. */
   38.18 -__DEFINE_XEN_GUEST_HANDLE(uchar, unsigned char);
   38.19 -__DEFINE_XEN_GUEST_HANDLE(uint,  unsigned int);
   38.20 -__DEFINE_XEN_GUEST_HANDLE(ulong, unsigned long);
   38.21 -DEFINE_XEN_GUEST_HANDLE(char);
   38.22 -DEFINE_XEN_GUEST_HANDLE(int);
   38.23 -DEFINE_XEN_GUEST_HANDLE(long);
   38.24 -DEFINE_XEN_GUEST_HANDLE(void);
   38.25 -
   38.26  typedef unsigned long long xen_pfn_t;
   38.27 -DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
   38.28  #define PRI_xen_pfn "llx"
   38.29  #endif
   38.30  
    39.1 --- a/xen/include/public/arch-x86/xen.h	Thu Jan 17 12:17:14 2008 -0700
    39.2 +++ b/xen/include/public/arch-x86/xen.h	Fri Jan 18 13:49:48 2008 -0700
    39.3 @@ -37,7 +37,8 @@
    39.4  #endif
    39.5  
    39.6  #define __DEFINE_XEN_GUEST_HANDLE(name, type) \
    39.7 -    ___DEFINE_XEN_GUEST_HANDLE(name, type)
    39.8 +    ___DEFINE_XEN_GUEST_HANDLE(name, type);   \
    39.9 +    ___DEFINE_XEN_GUEST_HANDLE(const_##name, const type)
   39.10  #define DEFINE_XEN_GUEST_HANDLE(name)   __DEFINE_XEN_GUEST_HANDLE(name, name)
   39.11  #define __XEN_GUEST_HANDLE(name)        __guest_handle_ ## name
   39.12  #define XEN_GUEST_HANDLE(name)          __XEN_GUEST_HANDLE(name)
   39.13 @@ -53,17 +54,7 @@
   39.14  #endif
   39.15  
   39.16  #ifndef __ASSEMBLY__
   39.17 -/* Guest handles for primitive C types. */
   39.18 -__DEFINE_XEN_GUEST_HANDLE(uchar, unsigned char);
   39.19 -__DEFINE_XEN_GUEST_HANDLE(uint,  unsigned int);
   39.20 -__DEFINE_XEN_GUEST_HANDLE(ulong, unsigned long);
   39.21 -DEFINE_XEN_GUEST_HANDLE(char);
   39.22 -DEFINE_XEN_GUEST_HANDLE(int);
   39.23 -DEFINE_XEN_GUEST_HANDLE(long);
   39.24 -DEFINE_XEN_GUEST_HANDLE(void);
   39.25 -
   39.26  typedef unsigned long xen_pfn_t;
   39.27 -DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
   39.28  #define PRI_xen_pfn "lx"
   39.29  #endif
   39.30  
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/xen/include/public/io/fsif.h	Fri Jan 18 13:49:48 2008 -0700
    40.3 @@ -0,0 +1,181 @@
    40.4 +/******************************************************************************
    40.5 + * fsif.h
    40.6 + * 
    40.7 + * Interface to FS level split device drivers.
    40.8 + * 
    40.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   40.10 + * of this software and associated documentation files (the "Software"), to
   40.11 + * deal in the Software without restriction, including without limitation the
   40.12 + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
   40.13 + * sell copies of the Software, and to permit persons to whom the Software is
   40.14 + * furnished to do so, subject to the following conditions:
   40.15 + *
   40.16 + * The above copyright notice and this permission notice shall be included in
   40.17 + * all copies or substantial portions of the Software.
   40.18 + *
   40.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   40.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   40.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   40.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   40.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   40.24 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   40.25 + * DEALINGS IN THE SOFTWARE.
   40.26 + *
   40.27 + * Copyright (c) 2007, Grzegorz Milos, Sun Microsystems, Inc.  
   40.28 + */
   40.29 +
   40.30 +#ifndef __XEN_PUBLIC_IO_FSIF_H__
   40.31 +#define __XEN_PUBLIC_IO_FSIF_H__
   40.32 +
   40.33 +#include "ring.h"
   40.34 +#include "../grant_table.h"
   40.35 +
   40.36 +#define REQ_FILE_OPEN        1
   40.37 +#define REQ_FILE_CLOSE       2
   40.38 +#define REQ_FILE_READ        3
   40.39 +#define REQ_FILE_WRITE       4
   40.40 +#define REQ_STAT             5
   40.41 +#define REQ_FILE_TRUNCATE    6
   40.42 +#define REQ_REMOVE           7
   40.43 +#define REQ_RENAME           8
   40.44 +#define REQ_CREATE           9
   40.45 +#define REQ_DIR_LIST        10
   40.46 +#define REQ_CHMOD           11
   40.47 +#define REQ_FS_SPACE        12
   40.48 +#define REQ_FILE_SYNC       13
   40.49 +
   40.50 +struct fsif_open_request {
   40.51 +    grant_ref_t gref;
   40.52 +};
   40.53 +
   40.54 +struct fsif_close_request {
   40.55 +    uint32_t fd;
   40.56 +};
   40.57 +
   40.58 +struct fsif_read_request {
   40.59 +    uint32_t fd;
   40.60 +    grant_ref_t gref;
   40.61 +    uint64_t len;
   40.62 +    uint64_t offset;
   40.63 +};
   40.64 +
   40.65 +struct fsif_write_request {
   40.66 +    uint32_t fd;
   40.67 +    grant_ref_t gref;
   40.68 +    uint64_t len;
   40.69 +    uint64_t offset;
   40.70 +};
   40.71 +
   40.72 +struct fsif_stat_request {
   40.73 +    uint32_t fd;
   40.74 +    grant_ref_t gref;
   40.75 +};
   40.76 +
   40.77 +/* This structure is a copy of some fields from stat structure, writen to the
   40.78 + * granted page. */
   40.79 +struct fsif_stat_response {
   40.80 +    int32_t  stat_mode;
   40.81 +    uint32_t stat_uid;
   40.82 +    uint32_t stat_gid;
   40.83 +    int32_t  pad;
   40.84 +    int64_t  stat_size;
   40.85 +    int64_t  stat_atime;
   40.86 +    int64_t  stat_mtime;
   40.87 +    int64_t  stat_ctime;
   40.88 +};
   40.89 +
   40.90 +struct fsif_truncate_request {
   40.91 +    uint32_t fd;
   40.92 +    int32_t pad;
   40.93 +    int64_t length;
   40.94 +};
   40.95 +
   40.96 +struct fsif_remove_request {
   40.97 +    grant_ref_t gref;
   40.98 +};
   40.99 +
  40.100 +struct fsif_rename_request {
  40.101 +    uint16_t old_name_offset;
  40.102 +    uint16_t new_name_offset;
  40.103 +    grant_ref_t gref;
  40.104 +};
  40.105 +
  40.106 +struct fsif_create_request {
  40.107 +    int8_t directory;
  40.108 +    int8_t pad;
  40.109 +    int16_t pad2;
  40.110 +    int32_t mode;
  40.111 +    grant_ref_t gref;
  40.112 +};
  40.113 +
  40.114 +struct fsif_list_request {
  40.115 +    uint32_t offset;
  40.116 +    grant_ref_t gref;
  40.117 +};
  40.118 +
  40.119 +#define NR_FILES_SHIFT  0
  40.120 +#define NR_FILES_SIZE   16   /* 16 bits for the number of files mask */
  40.121 +#define NR_FILES_MASK   (((1ULL << NR_FILES_SIZE) - 1) << NR_FILES_SHIFT)
  40.122 +#define ERROR_SIZE      32   /* 32 bits for the error mask */
  40.123 +#define ERROR_SHIFT     (NR_FILES_SIZE + NR_FILES_SHIFT)
  40.124 +#define ERROR_MASK      (((1ULL << ERROR_SIZE) - 1) << ERROR_SHIFT)
  40.125 +#define HAS_MORE_SHIFT  (ERROR_SHIFT + ERROR_SIZE)    
  40.126 +#define HAS_MORE_FLAG   (1ULL << HAS_MORE_SHIFT)
  40.127 +
  40.128 +struct fsif_chmod_request {
  40.129 +    uint32_t fd;
  40.130 +    int32_t mode;
  40.131 +};
  40.132 +
  40.133 +struct fsif_space_request {
  40.134 +    grant_ref_t gref;
  40.135 +};
  40.136 +
  40.137 +struct fsif_sync_request {
  40.138 +    uint32_t fd;
  40.139 +};
  40.140 +
  40.141 +
  40.142 +/* FS operation request */
  40.143 +struct fsif_request {
  40.144 +    uint8_t type;                 /* Type of the request                  */
  40.145 +    uint8_t pad;
  40.146 +    uint16_t id;                  /* Request ID, copied to the response   */
  40.147 +    uint32_t pad2;
  40.148 +    union {
  40.149 +        struct fsif_open_request     fopen;
  40.150 +        struct fsif_close_request    fclose;
  40.151 +        struct fsif_read_request     fread;
  40.152 +        struct fsif_write_request    fwrite;
  40.153 +        struct fsif_stat_request     fstat;
  40.154 +        struct fsif_truncate_request ftruncate;
  40.155 +        struct fsif_remove_request   fremove;
  40.156 +        struct fsif_rename_request   frename;
  40.157 +        struct fsif_create_request   fcreate;
  40.158 +        struct fsif_list_request     flist;
  40.159 +        struct fsif_chmod_request    fchmod;
  40.160 +        struct fsif_space_request    fspace;
  40.161 +        struct fsif_sync_request     fsync;
  40.162 +    } u;
  40.163 +};
  40.164 +typedef struct fsif_request fsif_request_t;
  40.165 +
  40.166 +/* FS operation response */
  40.167 +struct fsif_response {
  40.168 +    uint16_t id;
  40.169 +    uint16_t pad1;
  40.170 +    uint32_t pad2;
  40.171 +    uint64_t ret_val;
  40.172 +};
  40.173 +
  40.174 +typedef struct fsif_response fsif_response_t;
  40.175 +
  40.176 +
  40.177 +DEFINE_RING_TYPES(fsif, struct fsif_request, struct fsif_response);
  40.178 +
  40.179 +#define STATE_INITIALISED     "init"
  40.180 +#define STATE_READY           "ready"
  40.181 +
  40.182 +
  40.183 +
  40.184 +#endif
    41.1 --- a/xen/include/public/xen.h	Thu Jan 17 12:17:14 2008 -0700
    41.2 +++ b/xen/include/public/xen.h	Fri Jan 18 13:49:48 2008 -0700
    41.3 @@ -39,6 +39,19 @@
    41.4  #error "Unsupported architecture"
    41.5  #endif
    41.6  
    41.7 +#ifndef __ASSEMBLY__
    41.8 +/* Guest handles for primitive C types. */
    41.9 +DEFINE_XEN_GUEST_HANDLE(char);
   41.10 +__DEFINE_XEN_GUEST_HANDLE(uchar, unsigned char);
   41.11 +DEFINE_XEN_GUEST_HANDLE(int);
   41.12 +__DEFINE_XEN_GUEST_HANDLE(uint,  unsigned int);
   41.13 +DEFINE_XEN_GUEST_HANDLE(long);
   41.14 +__DEFINE_XEN_GUEST_HANDLE(ulong, unsigned long);
   41.15 +DEFINE_XEN_GUEST_HANDLE(void);
   41.16 +
   41.17 +DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
   41.18 +#endif
   41.19 +
   41.20  /*
   41.21   * HYPERCALLS
   41.22   */