# HG changeset patch
# User adsharma@xxxxxxxxxxxxxxxxxxxx
# Node ID 112d44270733c583e9c2506732299baceff7753a
# Parent e2025593f702880de0cd6cb1958a72b5b6250d31
# Parent b4b3f6be5226adfb127bc32fd5cca27f2ed473f7
Merge.
diff -r e2025593f702 -r 112d44270733 extras/mini-os/include/hypervisor.h
--- a/extras/mini-os/include/hypervisor.h Wed Aug 24 23:16:52 2005
+++ b/extras/mini-os/include/hypervisor.h Thu Aug 25 18:18:47 2005
@@ -80,16 +80,42 @@
static __inline__ int HYPERVISOR_mmu_update(mmu_update_t *req,
int count,
- int *success_count)
-{
- int ret;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret) : "0" (__HYPERVISOR_mmu_update),
- _a1 (req), _a2 (count), _a3 (success_count) : "memory" );
-
- return ret;
-}
+ int *success_count,
+ domid_t domid)
+{
+ int ret;
+ unsigned long ign1, ign2, ign3, ign4;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
+ : "0" (__HYPERVISOR_mmu_update), "1" (req), "2" (count),
+ "3" (success_count), "4" (domid)
+ : "memory" );
+
+ return ret;
+}
+
+
+static __inline__ int HYPERVISOR_mmuext_op(struct mmuext_op *op,
+ int count,
+ int *success_count,
+ domid_t domid)
+{
+ int ret;
+ unsigned long ign1, ign2, ign3, ign4;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
+ : "0" (__HYPERVISOR_mmuext_op), "1" (op), "2" (count),
+ "3" (success_count), "4" (domid)
+ : "memory" );
+
+ return ret;
+}
+
+
static __inline__ int HYPERVISOR_set_gdt(unsigned long *frame_list, int
entries)
{
diff -r e2025593f702 -r 112d44270733 extras/mini-os/include/mm.h
--- a/extras/mini-os/include/mm.h Wed Aug 24 23:16:52 2005
+++ b/extras/mini-os/include/mm.h Thu Aug 25 18:18:47 2005
@@ -43,13 +43,27 @@
#define PADDR_MASK ((1UL << PADDR_BITS)-1)
#define VADDR_MASK ((1UL << VADDR_BITS)-1)
-#define pte_to_mfn(_pte) (((_pte) & (PADDR_MASK&PAGE_MASK)) >> PAGE_SHIFT)
+#define pte_to_mfn(_pte) (((_pte) & (PADDR_MASK&PAGE_MASK)) >>
L1_PAGETABLE_SHIFT)
+
+#endif
+
+
+
+#ifdef __i386__
+
+#define L1_PAGETABLE_SHIFT 12
+#define L2_PAGETABLE_SHIFT 22
+
+#define L1_PAGETABLE_ENTRIES 1024
+#define L2_PAGETABLE_ENTRIES 1024
+#endif
/* Given a virtual address, get an entry offset into a page table. */
#define l1_table_offset(_a) \
(((_a) >> L1_PAGETABLE_SHIFT) & (L1_PAGETABLE_ENTRIES - 1))
#define l2_table_offset(_a) \
(((_a) >> L2_PAGETABLE_SHIFT) & (L2_PAGETABLE_ENTRIES - 1))
+#ifdef __x86_64__
#define l3_table_offset(_a) \
(((_a) >> L3_PAGETABLE_SHIFT) & (L3_PAGETABLE_ENTRIES - 1))
#define l4_table_offset(_a) \
@@ -67,13 +81,16 @@
#define _PAGE_PSE 0x080UL
#define _PAGE_GLOBAL 0x100UL
-#define PAGE_SHIFT 12
-#define PAGE_SIZE (1UL << PAGE_SHIFT)
+#define L1_PROT (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED)
+#define L2_PROT (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY |
_PAGE_USER)
+
+#define PAGE_SIZE (1UL << L1_PAGETABLE_SHIFT)
+#define PAGE_SHIFT L1_PAGETABLE_SHIFT
#define PAGE_MASK (~(PAGE_SIZE-1))
-#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
-#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
+#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> L1_PAGETABLE_SHIFT)
+#define PFN_DOWN(x) ((x) >> L1_PAGETABLE_SHIFT)
+#define PFN_PHYS(x) ((x) << L1_PAGETABLE_SHIFT)
/* to align the pointer to the (next) page boundary */
#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
@@ -83,14 +100,14 @@
#define mfn_to_pfn(_mfn) (machine_to_phys_mapping[(_mfn)])
static __inline__ unsigned long phys_to_machine(unsigned long phys)
{
- unsigned long machine = pfn_to_mfn(phys >> PAGE_SHIFT);
- machine = (machine << PAGE_SHIFT) | (phys & ~PAGE_MASK);
+ unsigned long machine = pfn_to_mfn(phys >> L1_PAGETABLE_SHIFT);
+ machine = (machine << L1_PAGETABLE_SHIFT) | (phys & ~PAGE_MASK);
return machine;
}
static __inline__ unsigned long machine_to_phys(unsigned long machine)
{
- unsigned long phys = mfn_to_pfn(machine >> PAGE_SHIFT);
- phys = (phys << PAGE_SHIFT) | (machine & ~PAGE_MASK);
+ unsigned long phys = mfn_to_pfn(machine >> L1_PAGETABLE_SHIFT);
+ phys = (phys << L1_PAGETABLE_SHIFT) | (machine & ~PAGE_MASK);
return phys;
}
@@ -105,7 +122,10 @@
#define __va to_virt
#define __pa to_phys
+#define virt_to_pfn(_virt) (PFN_DOWN(to_phys(_virt)))
+
void init_mm(void);
unsigned long alloc_pages(int order);
+int is_mfn_mapped(unsigned long mfn);
#endif /* _MM_H_ */
diff -r e2025593f702 -r 112d44270733 extras/mini-os/kernel.c
--- a/extras/mini-os/kernel.c Wed Aug 24 23:16:52 2005
+++ b/extras/mini-os/kernel.c Thu Aug 25 18:18:47 2005
@@ -133,7 +133,7 @@
for ( ; ; )
{
// HYPERVISOR_yield();
- block(1);
+ block(100);
i++;
}
}
diff -r e2025593f702 -r 112d44270733 extras/mini-os/mm.c
--- a/extras/mini-os/mm.c Wed Aug 24 23:16:52 2005
+++ b/extras/mini-os/mm.c Thu Aug 25 18:18:47 2005
@@ -5,9 +5,9 @@
*
* File: mm.c
* Author: Rolf Neugebauer (neugebar@xxxxxxxxxxxxx)
- * Changes:
+ * Changes: Grzegorz Milos
*
- * Date: Aug 2003
+ * Date: Aug 2003, chages Aug 2005
*
* Environment: Xen Minimal OS
* Description: memory management related functions
@@ -41,86 +41,18 @@
#include <types.h>
#include <lib.h>
+
+#ifdef MM_DEBUG
+#define DEBUG(_f, _a...) \
+ printk("MINI_OS(file=mm.c, line=%d) " _f "\n", __LINE__, ## _a)
+#else
+#define DEBUG(_f, _a...) ((void)0)
+#endif
+
unsigned long *phys_to_machine_mapping;
extern char *stack;
extern char _text, _etext, _edata, _end;
-static void init_page_allocator(unsigned long min, unsigned long max);
-
-void init_mm(void)
-{
-
- unsigned long start_pfn, max_pfn, max_free_pfn;
-
- unsigned long *pgd = (unsigned long *)start_info.pt_base;
-
- printk("MM: Init\n");
-
- printk(" _text: %p\n", &_text);
- printk(" _etext: %p\n", &_etext);
- printk(" _edata: %p\n", &_edata);
- printk(" stack start: %p\n", &stack);
- printk(" _end: %p\n", &_end);
-
- /* set up minimal memory infos */
- start_pfn = PFN_UP(to_phys(&_end));
- max_pfn = start_info.nr_pages;
-
- printk(" start_pfn: %lx\n", start_pfn);
- printk(" max_pfn: %lx\n", max_pfn);
-
- /*
- * we know where free tables start (start_pfn) and how many we
- * have (max_pfn).
- *
- * Currently the hypervisor stores page tables it providesin the
- * high region of the this memory range.
- *
- * next we work out how far down this goes (max_free_pfn)
- *
- * XXX this assumes the hypervisor provided page tables to be in
- * the upper region of our initial memory. I don't know if this
- * is always true.
- */
-
- max_free_pfn = PFN_DOWN(to_phys(pgd));
-#ifdef __i386__
- {
- unsigned long *pgd = (unsigned long *)start_info.pt_base;
- unsigned long pte;
- int i;
- printk(" pgd(pa(pgd)): %lx(%lx)", (u_long)pgd, to_phys(pgd));
-
- for ( i = 0; i < (HYPERVISOR_VIRT_START>>22); i++ )
- {
- unsigned long pgde = *pgd++;
- if ( !(pgde & 1) ) continue;
- pte = machine_to_phys(pgde & PAGE_MASK);
- printk(" PT(%x): %lx(%lx)", i, (u_long)to_virt(pte), pte);
- if (PFN_DOWN(pte) <= max_free_pfn)
- max_free_pfn = PFN_DOWN(pte);
- }
- }
- max_free_pfn--;
- printk(" max_free_pfn: %lx\n", max_free_pfn);
-
- /*
- * now we can initialise the page allocator
- */
- printk("MM: Initialise page allocator for %lx(%lx)-%lx(%lx)\n",
- (u_long)to_virt(PFN_PHYS(start_pfn)), PFN_PHYS(start_pfn),
- (u_long)to_virt(PFN_PHYS(max_free_pfn)), PFN_PHYS(max_free_pfn));
- init_page_allocator(PFN_PHYS(start_pfn), PFN_PHYS(max_free_pfn));
-#endif
-
-
- /* Now initialise the physical->machine mapping table. */
-
-
- printk("MM: done\n");
-
-
-}
/*********************
* ALLOCATION BITMAP
@@ -213,6 +145,59 @@
#define round_pgdown(_p) ((_p)&PAGE_MASK)
#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
+
+#ifdef MM_DEBUG
+/*
+ * Prints allocation[0/1] for @nr_pages, starting at @start
+ * address (virtual).
+ */
+static void print_allocation(void *start, int nr_pages)
+{
+ unsigned long pfn_start = virt_to_pfn(start);
+ int count;
+ for(count = 0; count < nr_pages; count++)
+ if(allocated_in_map(pfn_start + count)) printk("1");
+ else printk("0");
+
+ printk("\n");
+}
+
+/*
+ * Prints chunks (making them with letters) for @nr_pages starting
+ * at @start (virtual).
+ */
+static void print_chunks(void *start, int nr_pages)
+{
+ char chunks[1001], current='A';
+ int order, count;
+ chunk_head_t *head;
+ unsigned long pfn_start = virt_to_pfn(start);
+
+ memset(chunks, (int)'_', 1000);
+ if(nr_pages > 1000)
+ {
+ DEBUG("Can only pring 1000 pages. Increase buffer size.");
+ }
+
+ for(order=0; order < FREELIST_SIZE; order++)
+ {
+ head = free_head[order];
+ while(!FREELIST_EMPTY(head))
+ {
+ for(count = 0; count < 1<< head->level; count++)
+ {
+ if(count + virt_to_pfn(head) - pfn_start < 1000)
+ chunks[count + virt_to_pfn(head) - pfn_start] = current;
+ }
+ head = head->next;
+ current++;
+ }
+ }
+ chunks[nr_pages] = '\0';
+ printk("%s\n", chunks);
+}
+#endif
+
/*
@@ -328,3 +313,198 @@
return 0;
}
+void free_pages(void *pointer, int order)
+{
+ chunk_head_t *freed_ch, *to_merge_ch;
+ chunk_tail_t *freed_ct;
+ unsigned long mask;
+
+ /* First free the chunk */
+ map_free(virt_to_pfn(pointer), 1 << order);
+
+ /* Create free chunk */
+ freed_ch = (chunk_head_t *)pointer;
+ freed_ct = (chunk_tail_t *)((char *)pointer + (1<<(order + PAGE_SHIFT)))-1;
+
+ /* Now, possibly we can conseal chunks together */
+ while(order < FREELIST_SIZE)
+ {
+ mask = 1 << (order + PAGE_SHIFT);
+ if((unsigned long)freed_ch & mask)
+ {
+ to_merge_ch = (chunk_head_t *)((char *)freed_ch - mask);
+ if(allocated_in_map(virt_to_pfn(to_merge_ch)) ||
+ to_merge_ch->level != order)
+ break;
+
+ /* Merge with predecessor */
+ freed_ch = to_merge_ch;
+ }
+ else
+ {
+ to_merge_ch = (chunk_head_t *)((char *)freed_ch + mask);
+ if(allocated_in_map(virt_to_pfn(to_merge_ch)) ||
+ to_merge_ch->level != order)
+ break;
+
+ /* Merge with successor */
+ freed_ct = (chunk_tail_t *)((char *)to_merge_ch + mask);
+ }
+
+ /* We are commited to merging, unlink the chunk */
+ *(to_merge_ch->pprev) = to_merge_ch->next;
+ to_merge_ch->next->pprev = to_merge_ch->pprev;
+
+ order++;
+ }
+
+ /* Link the new chunk */
+ freed_ch->level = order;
+ freed_ch->next = free_head[order];
+ freed_ch->pprev = &free_head[order];
+ freed_ct->level = order;
+
+ freed_ch->next->pprev = &freed_ch->next;
+ free_head[order] = freed_ch;
+
+}
+void build_pagetable(unsigned long *start_pfn, unsigned long *max_pfn)
+{
+ unsigned long pfn_to_map, pt_frame;
+ unsigned long mach_ptd, max_mach_ptd;
+ int count;
+ unsigned long mach_pte, virt_pte;
+ unsigned long *ptd = (unsigned long *)start_info.pt_base;
+ mmu_update_t mmu_updates[L1_PAGETABLE_ENTRIES + 1];
+ struct mmuext_op pin_request;
+
+ /* Firstly work out what is the first pfn that is not yet in page tables
+ NB. Assuming that builder fills whole pt_frames (which it does at the
+ moment)
+ */
+ pfn_to_map = (start_info.nr_pt_frames - 1) * L1_PAGETABLE_ENTRIES;
+ DEBUG("start_pfn=%ld, first pfn_to_map %ld, max_pfn=%ld",
+ *start_pfn, pfn_to_map, *max_pfn);
+
+ /* Machine address of page table directory */
+ mach_ptd = phys_to_machine(to_phys(start_info.pt_base));
+ mach_ptd += sizeof(void *) *
+ l2_table_offset((unsigned long)to_virt(PFN_PHYS(pfn_to_map)));
+
+ max_mach_ptd = sizeof(void *) *
+ l2_table_offset((unsigned long)to_virt(PFN_PHYS(*max_pfn)));
+
+ /* Check that we are not trying to access Xen region */
+ if(max_mach_ptd > sizeof(void *) * l2_table_offset(HYPERVISOR_VIRT_START))
+ {
+ printk("WARNING: mini-os will not use all the memory supplied\n");
+ max_mach_ptd = sizeof(void *) * l2_table_offset(HYPERVISOR_VIRT_START);
+ *max_pfn = virt_to_pfn(HYPERVISOR_VIRT_START - PAGE_SIZE);
+ }
+ max_mach_ptd += phys_to_machine(to_phys(start_info.pt_base));
+ DEBUG("Max_mach_ptd 0x%lx", max_mach_ptd);
+
+ pt_frame = *start_pfn;
+ /* Should not happen - no empty, mapped pages */
+ if(pt_frame >= pfn_to_map)
+ {
+ printk("ERROR: Not even a single empty, mapped page\n");
+ *(int*)0=0;
+ }
+
+ while(mach_ptd < max_mach_ptd)
+ {
+ /* Correct protection needs to be set for the new page table frame */
+ virt_pte = (unsigned long)to_virt(PFN_PHYS(pt_frame));
+ mach_pte = ptd[l2_table_offset(virt_pte)] & ~(PAGE_SIZE-1);
+ mach_pte += sizeof(void *) * l1_table_offset(virt_pte);
+ DEBUG("New page table page: pfn=0x%lx, mfn=0x%lx, virt_pte=0x%lx, "
+ "mach_pte=0x%lx", pt_frame, pfn_to_mfn(pt_frame),
+ virt_pte, mach_pte);
+
+ /* Update the entry */
+ mmu_updates[0].ptr = mach_pte;
+ mmu_updates[0].val = pfn_to_mfn(pt_frame) << PAGE_SHIFT |
+ (L1_PROT & ~_PAGE_RW);
+ if(HYPERVISOR_mmu_update(mmu_updates, 1, NULL, DOMID_SELF) < 0)
+ {
+ printk("PTE for new page table page could not be updated\n");
+ *(int*)0=0;
+ }
+
+ /* Pin the page to provide correct protection */
+ pin_request.cmd = MMUEXT_PIN_L1_TABLE;
+ pin_request.mfn = pfn_to_mfn(pt_frame);
+ if(HYPERVISOR_mmuext_op(&pin_request, 1, NULL, DOMID_SELF) < 0)
+ {
+ printk("ERROR: pinning failed\n");
+ *(int*)0=0;
+ }
+
+ /* Now fill the new page table page with entries.
+ Update the page directory as well. */
+ count = 0;
+ mmu_updates[count].ptr = mach_ptd;
+ mmu_updates[count].val = pfn_to_mfn(pt_frame) << PAGE_SHIFT |
+ L2_PROT;
+ count++;
+ mach_ptd += sizeof(void *);
+ mach_pte = phys_to_machine(PFN_PHYS(pt_frame++));
+
+ for(;count <= L1_PAGETABLE_ENTRIES && pfn_to_map <= *max_pfn; count++)
+ {
+ mmu_updates[count].ptr = mach_pte;
+ mmu_updates[count].val =
+ pfn_to_mfn(pfn_to_map++) << PAGE_SHIFT | L1_PROT;
+ if(count == 1) DEBUG("mach_pte 0x%lx", mach_pte);
+ mach_pte += sizeof(void *);
+ }
+ if(HYPERVISOR_mmu_update(mmu_updates, count, NULL, DOMID_SELF) < 0)
+ {
+ printk("ERROR: mmu_update failed\n");
+ *(int*)0=0;
+ }
+ (*start_pfn)++;
+ }
+
+ *start_pfn = pt_frame;
+}
+
+void init_mm(void)
+{
+
+ unsigned long start_pfn, max_pfn;
+
+ printk("MM: Init\n");
+
+ printk(" _text: %p\n", &_text);
+ printk(" _etext: %p\n", &_etext);
+ printk(" _edata: %p\n", &_edata);
+ printk(" stack start: %p\n", &stack);
+ printk(" _end: %p\n", &_end);
+
+ /* set up minimal memory infos */
+ phys_to_machine_mapping = (unsigned long *)start_info.mfn_list;
+
+ /* First page follows page table pages and 3 more pages (store page etc) */
+ start_pfn = PFN_UP(__pa(start_info.pt_base)) + start_info.nr_pt_frames + 3;
+ max_pfn = start_info.nr_pages;
+
+ printk(" start_pfn: %lx\n", start_pfn);
+ printk(" max_pfn: %lx\n", max_pfn);
+
+
+ build_pagetable(&start_pfn, &max_pfn);
+
+#ifdef __i386__
+ /*
+ * now we can initialise the page allocator
+ */
+ printk("MM: Initialise page allocator for %lx(%lx)-%lx(%lx)\n",
+ (u_long)to_virt(PFN_PHYS(start_pfn)), PFN_PHYS(start_pfn),
+ (u_long)to_virt(PFN_PHYS(max_pfn)), PFN_PHYS(max_pfn));
+ init_page_allocator(PFN_PHYS(start_pfn), PFN_PHYS(max_pfn));
+#endif
+
+ printk("MM: done\n");
+}
diff -r e2025593f702 -r 112d44270733
linux-2.6-xen-sparse/arch/xen/i386/kernel/cpu/common.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/cpu/common.c Wed Aug 24
23:16:52 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/cpu/common.c Thu Aug 25
18:18:47 2005
@@ -19,11 +19,13 @@
#include "cpu.h"
+#ifndef CONFIG_XEN
DEFINE_PER_CPU(struct desc_struct, cpu_gdt_table[GDT_ENTRIES]);
EXPORT_PER_CPU_SYMBOL(cpu_gdt_table);
DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack);
+#endif
static int cachesize_override __initdata = -1;
static int disable_x86_fxsr __initdata = 0;
diff -r e2025593f702 -r 112d44270733
linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c Wed Aug 24
23:16:52 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c Thu Aug 25
18:18:47 2005
@@ -131,15 +131,7 @@
*/
void __init smp_alloc_memory(void)
{
-#if 1
- int cpu;
-
- for (cpu = 1; cpu < NR_CPUS; cpu++) {
- cpu_gdt_descr[cpu].address = (unsigned long)
- alloc_bootmem_low_pages(PAGE_SIZE);
- /* XXX free unused pages later */
- }
-#else
+#if 0
trampoline_base = (void *) alloc_bootmem_low_pages(PAGE_SIZE);
/*
* Has to be in very low memory so we can execute
@@ -861,8 +853,8 @@
atomic_set(&init_deasserted, 0);
#if 1
- if (cpu_gdt_descr[0].size > PAGE_SIZE)
- BUG();
+ cpu_gdt_descr[cpu].address = __get_free_page(GFP_KERNEL);
+ BUG_ON(cpu_gdt_descr[0].size > PAGE_SIZE);
cpu_gdt_descr[cpu].size = cpu_gdt_descr[0].size;
printk("GDT: copying %d bytes from %lx to %lx\n",
cpu_gdt_descr[0].size, cpu_gdt_descr[0].address,
diff -r e2025593f702 -r 112d44270733
linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c Wed Aug 24 23:16:52 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c Thu Aug 25 18:18:47 2005
@@ -871,6 +871,7 @@
}
}
+#ifndef CONFIG_XEN
fastcall void setup_x86_bogus_stack(unsigned char * stk)
{
unsigned long *switch16_ptr, *switch32_ptr;
@@ -915,6 +916,7 @@
memcpy(stack32, stack16, len);
return stack32;
}
+#endif
/*
* 'math_state_restore()' saves the current math information in the
diff -r e2025593f702 -r 112d44270733
linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c Wed Aug 24 23:16:52 2005
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c Thu Aug 25 18:18:47 2005
@@ -34,9 +34,11 @@
EXPORT_SYMBOL(gnttab_grant_foreign_access);
+EXPORT_SYMBOL(gnttab_end_foreign_access_ref);
EXPORT_SYMBOL(gnttab_end_foreign_access);
EXPORT_SYMBOL(gnttab_query_foreign_access);
EXPORT_SYMBOL(gnttab_grant_foreign_transfer);
+EXPORT_SYMBOL(gnttab_end_foreign_transfer_ref);
EXPORT_SYMBOL(gnttab_end_foreign_transfer);
EXPORT_SYMBOL(gnttab_alloc_grant_references);
EXPORT_SYMBOL(gnttab_free_grant_references);
@@ -160,7 +162,7 @@
}
void
-gnttab_end_foreign_access(grant_ref_t ref, int readonly)
+gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly)
{
u16 flags, nflags;
@@ -170,7 +172,12 @@
printk(KERN_ALERT "WARNING: g.e. still in use!\n");
}
while ( (nflags = synch_cmpxchg(&shared[ref].flags, flags, 0)) != flags );
-
+}
+
+void
+gnttab_end_foreign_access(grant_ref_t ref, int readonly)
+{
+ gnttab_end_foreign_access_ref(ref, readonly);
put_free_entry(ref);
}
@@ -201,20 +208,13 @@
}
unsigned long
-gnttab_end_foreign_transfer(grant_ref_t ref)
+gnttab_end_foreign_transfer_ref(grant_ref_t ref)
{
unsigned long frame = 0;
u16 flags;
flags = shared[ref].flags;
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
- /*
- * But can't flags == (GTF_accept_transfer | GTF_transfer_completed)
- * if gnttab_donate executes without interruption???
- */
-#else
- ASSERT(flags == (GTF_accept_transfer | GTF_transfer_committed));
-#endif
+
/*
* If a transfer is committed then wait for the frame address to appear.
* Otherwise invalidate the grant entry against future use.
@@ -224,8 +224,14 @@
while ( unlikely((frame = shared[ref].frame) == 0) )
cpu_relax();
+ return frame;
+}
+
+unsigned long
+gnttab_end_foreign_transfer(grant_ref_t ref)
+{
+ unsigned long frame = gnttab_end_foreign_transfer_ref(ref);
put_free_entry(ref);
-
return frame;
}
diff -r e2025593f702 -r 112d44270733
linux-2.6-xen-sparse/arch/xen/kernel/reboot.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Wed Aug 24 23:16:52 2005
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Thu Aug 25 18:18:47 2005
@@ -128,14 +128,6 @@
/* Hmmm... a cleaner interface to suspend/resume blkdevs would be nice. */
/* XXX SMH: yes it would :-( */
-
-#ifdef CONFIG_XEN_NETDEV_FRONTEND
- extern void netif_suspend(void);
- extern void netif_resume(void);
-#else
-#define netif_suspend() do{}while(0)
-#define netif_resume() do{}while(0)
-#endif
#ifdef CONFIG_XEN_USB_FRONTEND
extern void usbif_resume();
@@ -218,8 +210,6 @@
kmem_cache_shrink(pgd_cache);
#endif
- netif_suspend();
-
time_suspend();
#ifdef CONFIG_SMP
@@ -276,8 +266,6 @@
#endif
time_resume();
-
- netif_resume();
usbif_resume();
diff -r e2025593f702 -r 112d44270733
linux-2.6-xen-sparse/arch/xen/x86_64/kernel/early_printk.c
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/early_printk.c Wed Aug
24 23:16:52 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/early_printk.c Thu Aug
25 18:18:47 2005
@@ -5,6 +5,8 @@
#include <linux/string.h>
#include <asm/io.h>
#include <asm/processor.h>
+
+#ifndef CONFIG_XEN
/* Simple VGA output */
@@ -59,7 +61,6 @@
.index = -1,
};
-#ifndef CONFIG_XEN
/* Serial functions loosely based on a similar package from Klaus P. Gerlicher
*/
static int early_serial_base = 0x3f8; /* ttyS0 */
@@ -148,7 +149,8 @@
outb((divisor >> 8) & 0xff, early_serial_base + DLH);
outb(c & ~DLAB, early_serial_base + LCR);
}
-#else
+
+#else /* CONFIG_XEN */
static void
early_serial_write(struct console *con, const char *s, unsigned count)
@@ -167,6 +169,13 @@
static __init void early_serial_init(char *s)
{
}
+
+/*
+ * No early VGA console on Xen, as we do not have convenient ISA-space
+ * mappings. Someone should fix this for domain 0. For now, use fake serial.
+ */
+#define early_vga_console early_serial_console
+
#endif
static struct console early_serial_console = {
diff -r e2025593f702 -r 112d44270733
linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head.S
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head.S Wed Aug 24
23:16:52 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head.S Thu Aug 25
18:18:47 2005
@@ -206,11 +206,13 @@
.quad 0,0,0 /* three TLS descriptors */
.quad 0 /* unused now? __KERNEL16_CS - 16bit
PM for S3 wakeup. */
-gdt_end:
+gdt_end:
+#if 0
/* asm/segment.h:GDT_ENTRIES must match this */
/* This should be a multiple of the cache line size */
/* GDTs of other CPUs: */
.fill (GDT_SIZE * NR_CPUS) - (gdt_end - cpu_gdt_table)
+#endif
.org 0x8000
ENTRY(empty_zero_page)
diff -r e2025593f702 -r 112d44270733
linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c Wed Aug 24
23:16:52 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c Thu Aug 25
18:18:47 2005
@@ -536,48 +536,7 @@
}
#endif
-#ifdef CONFIG_XEN
-#define reserve_ebda_region() void(0)
-
-static void __init print_memory_map(char *who)
-{
- int i;
-
- for (i = 0; i < e820.nr_map; i++) {
- early_printk(" %s: %016Lx - %016Lx ", who,
- e820.map[i].addr,
- e820.map[i].addr + e820.map[i].size);
- switch (e820.map[i].type) {
- case E820_RAM: early_printk("(usable)\n");
- break;
- case E820_RESERVED:
- early_printk("(reserved)\n");
- break;
- case E820_ACPI:
- early_printk("(ACPI data)\n");
- break;
- case E820_NVS:
- early_printk("(ACPI NVS)\n");
- break;
- default: early_printk("type %u\n", e820.map[i].type);
- break;
- }
- }
-}
-
-void __init smp_alloc_memory(void)
-{
- int cpu;
-
- for (cpu = 1; cpu < NR_CPUS; cpu++) {
- cpu_gdt_descr[cpu].address = (unsigned long)
- alloc_bootmem_low_pages(PAGE_SIZE);
- /* XXX free unused pages later */
- }
-}
-
-
-#else
+#ifndef CONFIG_XEN
#define EBDA_ADDR_POINTER 0x40E
static void __init reserve_ebda_region(void)
{
@@ -628,7 +587,6 @@
VMASST_TYPE_writable_pagetables);
ARCH_SETUP
- print_memory_map(machine_specific_memory_setup());
#else
ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
drive_info = DRIVE_INFO;
@@ -743,9 +701,6 @@
initrd_start = 0;
}
}
-#endif
-#ifdef CONFIG_SMP
- smp_alloc_memory();
#endif
#else /* CONFIG_XEN */
#ifdef CONFIG_BLK_DEV_INITRD
diff -r e2025593f702 -r 112d44270733
linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup64.c
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup64.c Wed Aug 24
23:16:52 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup64.c Thu Aug 25
18:18:47 2005
@@ -286,10 +286,10 @@
memcpy(me->thread.tls_array, cpu_gdt_table[cpu], GDT_ENTRY_TLS_ENTRIES
* 8);
#else
- memcpy(me->thread.tls_array, &get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN],
+ memcpy(me->thread.tls_array, &get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN],
GDT_ENTRY_TLS_ENTRIES * 8);
- cpu_gdt_init(&cpu_gdt_descr[cpu]);
+ cpu_gdt_init(&cpu_gdt_descr[cpu]);
#endif
/*
diff -r e2025593f702 -r 112d44270733
linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c Wed Aug 24
23:16:52 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c Thu Aug 25
18:18:47 2005
@@ -739,8 +739,8 @@
atomic_set(&init_deasserted, 0);
#ifdef CONFIG_XEN
- if (cpu_gdt_descr[0].size > PAGE_SIZE)
- BUG();
+ cpu_gdt_descr[cpu].address = __get_free_page(GFP_KERNEL);
+ BUG_ON(cpu_gdt_descr[0].size > PAGE_SIZE);
cpu_gdt_descr[cpu].size = cpu_gdt_descr[0].size;
memcpy((void *)cpu_gdt_descr[cpu].address,
(void *)cpu_gdt_descr[0].address, cpu_gdt_descr[0].size);
@@ -798,6 +798,8 @@
ctxt.ctrlreg[3] = virt_to_mfn(init_level4_pgt) << PAGE_SHIFT;
boot_error = HYPERVISOR_boot_vcpu(cpu, &ctxt);
+ if (boot_error)
+ printk("boot error: %ld\n", boot_error);
if (!boot_error) {
/*
diff -r e2025593f702 -r 112d44270733
linux-2.6-xen-sparse/arch/xen/x86_64/mm/init.c
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/mm/init.c Wed Aug 24 23:16:52 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/mm/init.c Thu Aug 25 18:18:47 2005
@@ -536,70 +536,38 @@
round_up(ptes * 8, PAGE_SIZE);
}
-static void xen_copy_pt(void)
-{
- unsigned long va = __START_KERNEL_map;
- unsigned long addr, *pte_page;
+void __init xen_init_pt(void)
+{
+ unsigned long addr, *page;
int i;
- pud_t *pud; pmd_t *pmd; pte_t *pte;
- unsigned long *page = (unsigned long *) init_level4_pgt;
-
- addr = (unsigned long) page[pgd_index(va)];
+
+ for (i = 0; i < NR_CPUS; i++)
+ per_cpu(cur_pgd, i) = init_mm.pgd;
+
+ memset((void *)init_level4_pgt, 0, PAGE_SIZE);
+ memset((void *)level3_kernel_pgt, 0, PAGE_SIZE);
+ memset((void *)level2_kernel_pgt, 0, PAGE_SIZE);
+
+ /* Find the initial pte page that was built for us. */
+ page = (unsigned long *)xen_start_info.pt_base;
+ addr = page[pgd_index(__START_KERNEL_map)];
addr_to_page(addr, page);
-
- pud = (pud_t *) &page[pud_index(va)];
- addr = page[pud_index(va)];
+ addr = page[pud_index(__START_KERNEL_map)];
addr_to_page(addr, page);
- level3_kernel_pgt[pud_index(va)] =
- __pud(__pa_symbol(level2_kernel_pgt) | _KERNPG_TABLE |
_PAGE_USER);
-
- for (;;) {
- pmd = (pmd_t *) &page[pmd_index(va)];
- if (pmd_present(*pmd)) {
- level2_kernel_pgt[pmd_index(va)] = *pmd;
- /*
- * if pmd is valid, check pte.
- */
- addr = page[pmd_index(va)];
- addr_to_page(addr, pte_page);
-
- for (i = 0; i < PTRS_PER_PTE; i++) {
- pte = (pte_t *) &pte_page[pte_index(va)];
- if (pte_present(*pte))
- va += PAGE_SIZE;
- else
- break;
- }
-
- } else
- break;
- }
-
+ /* Construct mapping of initial pte page in our own directories. */
init_level4_pgt[pgd_index(__START_KERNEL_map)] =
mk_kernel_pgd(__pa_symbol(level3_kernel_pgt));
-}
-
-void __init xen_init_pt(void)
-{
- int i;
-
- for (i = 0; i < NR_CPUS; i++)
- per_cpu(cur_pgd, i) = init_mm.pgd;
-
- memcpy((void *)init_level4_pgt,
- (void *)xen_start_info.pt_base, PAGE_SIZE);
-
- memset((void *)level3_kernel_pgt, 0, PAGE_SIZE);
- memset((void *)level2_kernel_pgt, 0, PAGE_SIZE);
-
- xen_copy_pt();
+ level3_kernel_pgt[pud_index(__START_KERNEL_map)] =
+ __pud(__pa_symbol(level2_kernel_pgt) |
+ _KERNPG_TABLE | _PAGE_USER);
+ memcpy((void *)level2_kernel_pgt, page, PAGE_SIZE);
make_page_readonly(init_level4_pgt);
+ make_page_readonly(init_level4_user_pgt);
make_page_readonly(level3_kernel_pgt);
+ make_page_readonly(level3_user_pgt);
make_page_readonly(level2_kernel_pgt);
- make_page_readonly(init_level4_user_pgt);
- make_page_readonly(level3_user_pgt); /* for vsyscall stuff */
xen_pgd_pin(__pa_symbol(init_level4_pgt));
xen_pgd_pin(__pa_symbol(init_level4_user_pgt));
@@ -609,7 +577,6 @@
set_pgd((pgd_t *)(init_level4_user_pgt + 511),
mk_kernel_pgd(__pa_symbol(level3_user_pgt)));
-
}
/*
@@ -617,69 +584,58 @@
* mapping done by Xen is minimal (e.g. 8MB) and we need to extend the
* mapping for early initialization.
*/
-
-#define MIN_INIT_SIZE 0x800000
static unsigned long current_size, extended_size;
void __init extend_init_mapping(void)
{
unsigned long va = __START_KERNEL_map;
- unsigned long addr, *pte_page;
-
- unsigned long phys;
+ unsigned long phys, addr, *pte_page;
pmd_t *pmd;
pte_t *pte, new_pte;
unsigned long *page = (unsigned long *) init_level4_pgt;
int i;
- addr = (unsigned long) page[pgd_index(va)];
+ addr = page[pgd_index(va)];
addr_to_page(addr, page);
-
addr = page[pud_index(va)];
addr_to_page(addr, page);
for (;;) {
+ pmd = (pmd_t *)&page[pmd_index(va)];
+ if (!pmd_present(*pmd))
+ break;
+ addr = page[pmd_index(va)];
+ addr_to_page(addr, pte_page);
+ for (i = 0; i < PTRS_PER_PTE; i++) {
+ pte = (pte_t *) &pte_page[pte_index(va)];
+ if (!pte_present(*pte))
+ break;
+ va += PAGE_SIZE;
+ current_size += PAGE_SIZE;
+ }
+ }
+
+ while (va < __START_KERNEL_map + current_size + tables_space) {
pmd = (pmd_t *) &page[pmd_index(va)];
- if (pmd_present(*pmd)) {
- /*
- * if pmd is valid, check pte.
- */
- addr = page[pmd_index(va)];
- addr_to_page(addr, pte_page);
-
- for (i = 0; i < PTRS_PER_PTE; i++) {
- pte = (pte_t *) &pte_page[pte_index(va)];
-
- if (pte_present(*pte)) {
- va += PAGE_SIZE;
- current_size += PAGE_SIZE;
- } else
- break;
- }
-
- } else
- break;
- }
-
- for (; va < __START_KERNEL_map + current_size + tables_space; ) {
- pmd = (pmd_t *) &page[pmd_index(va)];
-
- if (pmd_none(*pmd)) {
- pte_page = (unsigned long *) alloc_static_page(&phys);
- make_page_readonly(pte_page);
- xen_pte_pin(phys);
- set_pmd(pmd, __pmd(phys | _KERNPG_TABLE | _PAGE_USER));
-
- for (i = 0; i < PTRS_PER_PTE; i++, va += PAGE_SIZE) {
- new_pte = pfn_pte((va - __START_KERNEL_map) >>
PAGE_SHIFT,
- __pgprot(_KERNPG_TABLE |
_PAGE_USER));
-
- pte = (pte_t *) &pte_page[pte_index(va)];
- xen_l1_entry_update(pte, new_pte);
- extended_size += PAGE_SIZE;
- }
- }
- }
+ if (!pmd_none(*pmd))
+ continue;
+ pte_page = (unsigned long *) alloc_static_page(&phys);
+ make_page_readonly(pte_page);
+ xen_pte_pin(phys);
+ set_pmd(pmd, __pmd(phys | _KERNPG_TABLE | _PAGE_USER));
+ for (i = 0; i < PTRS_PER_PTE; i++, va += PAGE_SIZE) {
+ new_pte = pfn_pte(
+ (va - __START_KERNEL_map) >> PAGE_SHIFT,
+ __pgprot(_KERNPG_TABLE | _PAGE_USER));
+ pte = (pte_t *)&pte_page[pte_index(va)];
+ xen_l1_entry_update(pte, new_pte);
+ extended_size += PAGE_SIZE;
+ }
+ }
+
+ /* Kill mapping of low 1MB. */
+ for (va = __START_KERNEL_map; va < (unsigned long)&_text; va +=
PAGE_SIZE)
+ HYPERVISOR_update_va_mapping(va, __pte_ma(0), 0);
}
@@ -719,10 +675,6 @@
table_end<<PAGE_SHIFT);
start_pfn = ((current_size + extended_size) >> PAGE_SHIFT);
-
- /*
- * TBD: Need to calculate at runtime
- */
__flush_tlb_all();
init_mapping_done = 1;
diff -r e2025593f702 -r 112d44270733
linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Wed Aug 24 23:16:52 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Thu Aug 25 18:18:47 2005
@@ -57,26 +57,26 @@
/* Front end tells us frame. */
static void frontend_changed(struct xenbus_watch *watch, const char *node)
{
- unsigned long sharedmfn;
+ unsigned long ring_ref;
unsigned int evtchn;
int err;
struct backend_info *be
= container_of(watch, struct backend_info, watch);
/* If other end is gone, delete ourself. */
- if (!xenbus_exists(be->frontpath, "")) {
+ if (node && !xenbus_exists(be->frontpath, "")) {
xenbus_rm(be->dev->nodename, "");
device_unregister(&be->dev->dev);
return;
}
- if (be->blkif->status == CONNECTED)
- return;
-
- err = xenbus_gather(be->frontpath, "grant-id", "%lu", &sharedmfn,
+ if (be->blkif == NULL || be->blkif->status == CONNECTED)
+ return;
+
+ err = xenbus_gather(be->frontpath, "ring-ref", "%lu", &ring_ref,
"event-channel", "%u", &evtchn, NULL);
if (err) {
xenbus_dev_error(be->dev, err,
- "reading %s/grant-id and event-channel",
+ "reading %s/ring-ref and event-channel",
be->frontpath);
return;
}
@@ -113,11 +113,10 @@
}
/* Map the shared frame, irq etc. */
- err = blkif_map(be->blkif, sharedmfn, evtchn);
- if (err) {
- xenbus_dev_error(be->dev, err,
- "mapping shared-frame %lu port %u",
- sharedmfn, evtchn);
+ err = blkif_map(be->blkif, ring_ref, evtchn);
+ if (err) {
+ xenbus_dev_error(be->dev, err, "mapping ring-ref %lu port %u",
+ ring_ref, evtchn);
goto abort;
}
@@ -139,133 +138,125 @@
{
int err;
char *p;
- char *frontend;
long int handle, pdev;
struct backend_info *be
= container_of(watch, struct backend_info, backend_watch);
struct xenbus_device *dev = be->dev;
+
+ err = xenbus_scanf(dev->nodename, "physical-device", "%li", &pdev);
+ if (XENBUS_EXIST_ERR(err))
+ return;
+ if (err < 0) {
+ xenbus_dev_error(dev, err, "reading physical-device");
+ return;
+ }
+ if (be->pdev && be->pdev != pdev) {
+ printk(KERN_WARNING
+ "changing physical-device not supported\n");
+ return;
+ }
+ be->pdev = pdev;
+
+ /* If there's a read-only node, we're read only. */
+ p = xenbus_read(dev->nodename, "read-only", NULL);
+ if (!IS_ERR(p)) {
+ be->readonly = 1;
+ kfree(p);
+ }
+
+ if (be->blkif == NULL) {
+ /* Front end dir is a number, which is used as the handle. */
+ p = strrchr(be->frontpath, '/') + 1;
+ handle = simple_strtoul(p, NULL, 0);
+
+ be->blkif = alloc_blkif(be->frontend_id);
+ if (IS_ERR(be->blkif)) {
+ err = PTR_ERR(be->blkif);
+ be->blkif = NULL;
+ xenbus_dev_error(dev, err, "creating block interface");
+ return;
+ }
+
+ err = vbd_create(be->blkif, handle, be->pdev, be->readonly);
+ if (err) {
+ xenbus_dev_error(dev, err, "creating vbd structure");
+ return;
+ }
+
+ /* Pass in NULL node to skip exist test. */
+ frontend_changed(&be->watch, NULL);
+ }
+}
+
+static int blkback_probe(struct xenbus_device *dev,
+ const struct xenbus_device_id *id)
+{
+ struct backend_info *be;
+ char *frontend;
+ int err;
+
+ be = kmalloc(sizeof(*be), GFP_KERNEL);
+ if (!be) {
+ xenbus_dev_error(dev, -ENOMEM, "allocating backend structure");
+ return -ENOMEM;
+ }
+ memset(be, 0, sizeof(*be));
frontend = NULL;
err = xenbus_gather(dev->nodename,
"frontend-id", "%li", &be->frontend_id,
"frontend", NULL, &frontend,
NULL);
- if (XENBUS_EXIST_ERR(err) ||
- strlen(frontend) == 0 || !xenbus_exists(frontend, "")) {
+ if (XENBUS_EXIST_ERR(err))
+ goto free_be;
+ if (err < 0) {
+ xenbus_dev_error(dev, err,
+ "reading %s/frontend or frontend-id",
+ dev->nodename);
+ goto free_be;
+ }
+ if (strlen(frontend) == 0 || !xenbus_exists(frontend, "")) {
/* If we can't get a frontend path and a frontend-id,
* then our bus-id is no longer valid and we need to
* destroy the backend device.
*/
- goto device_fail;
- }
- if (err < 0) {
- xenbus_dev_error(dev, err,
- "reading %s/frontend or frontend-id",
- dev->nodename);
- goto device_fail;
- }
-
- if (!be->frontpath || strcmp(frontend, be->frontpath)) {
- if (be->watch.node)
- unregister_xenbus_watch(&be->watch);
- if (be->frontpath)
- kfree(be->frontpath);
- be->frontpath = frontend;
- frontend = NULL;
- be->watch.node = be->frontpath;
- be->watch.callback = frontend_changed;
- err = register_xenbus_watch(&be->watch);
- if (err) {
- be->watch.node = NULL;
- xenbus_dev_error(dev, err,
- "adding frontend watch on %s",
- be->frontpath);
- goto device_fail;
- }
- }
-
- err = xenbus_scanf(dev->nodename, "physical-device", "%li", &pdev);
- if (XENBUS_EXIST_ERR(err))
- goto out;
- if (err < 0) {
- xenbus_dev_error(dev, err, "reading physical-device");
- goto device_fail;
- }
- if (be->pdev && be->pdev != pdev) {
- printk(KERN_WARNING
- "changing physical-device not supported\n");
- goto device_fail;
- }
- be->pdev = pdev;
-
- /* If there's a read-only node, we're read only. */
- p = xenbus_read(dev->nodename, "read-only", NULL);
- if (!IS_ERR(p)) {
- be->readonly = 1;
- kfree(p);
- }
-
- if (be->blkif == NULL) {
- /* Front end dir is a number, which is used as the handle. */
- p = strrchr(be->frontpath, '/') + 1;
- handle = simple_strtoul(p, NULL, 0);
-
- be->blkif = alloc_blkif(be->frontend_id);
- if (IS_ERR(be->blkif)) {
- err = PTR_ERR(be->blkif);
- be->blkif = NULL;
- xenbus_dev_error(dev, err, "creating block interface");
- goto device_fail;
- }
-
- err = vbd_create(be->blkif, handle, be->pdev, be->readonly);
- if (err) {
- xenbus_dev_error(dev, err, "creating vbd structure");
- goto device_fail;
- }
-
- frontend_changed(&be->watch, be->frontpath);
- }
-
- out:
- if (frontend)
- kfree(frontend);
- return;
-
- device_fail:
- device_unregister(&be->dev->dev);
- goto out;
-}
-
-static int blkback_probe(struct xenbus_device *dev,
- const struct xenbus_device_id *id)
-{
- struct backend_info *be;
- int err;
-
- be = kmalloc(sizeof(*be), GFP_KERNEL);
- if (!be) {
- xenbus_dev_error(dev, -ENOMEM, "allocating backend structure");
- return -ENOMEM;
- }
-
- memset(be, 0, sizeof(*be));
+ err = -ENOENT;
+ goto free_be;
+ }
be->dev = dev;
be->backend_watch.node = dev->nodename;
be->backend_watch.callback = backend_changed;
err = register_xenbus_watch(&be->backend_watch);
if (err) {
+ be->backend_watch.node = NULL;
xenbus_dev_error(dev, err, "adding backend watch on %s",
dev->nodename);
goto free_be;
}
+ be->frontpath = frontend;
+ be->watch.node = be->frontpath;
+ be->watch.callback = frontend_changed;
+ err = register_xenbus_watch(&be->watch);
+ if (err) {
+ be->watch.node = NULL;
+ xenbus_dev_error(dev, err,
+ "adding frontend watch on %s",
+ be->frontpath);
+ goto free_be;
+ }
+
dev->data = be;
backend_changed(&be->backend_watch, dev->nodename);
- return err;
+ return 0;
+
free_be:
+ if (be->backend_watch.node)
+ unregister_xenbus_watch(&be->backend_watch);
+ if (frontend)
+ kfree(frontend);
kfree(be);
return err;
}
diff -r e2025593f702 -r 112d44270733
linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Wed Aug 24
23:16:52 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Thu Aug 25
18:18:47 2005
@@ -1084,7 +1084,8 @@
"sector-size", "%lu", §or_size,
NULL);
if (err) {
- xenbus_dev_error(info->xbdev, err, "reading backend fields");
+ xenbus_dev_error(info->xbdev, err,
+ "reading backend fields at %s", watch->node);
return;
}
@@ -1123,12 +1124,12 @@
xenbus_dev_error(dev, err, "granting access to ring page");
return err;
}
- info->grant_id = err;
+ info->ring_ref = err;
op.u.alloc_unbound.dom = info->backend_id;
err = HYPERVISOR_event_channel_op(&op);
if (err) {
- gnttab_end_foreign_access(info->grant_id, 0);
+ gnttab_end_foreign_access(info->ring_ref, 0);
free_page((unsigned long)info->ring.sring);
info->ring.sring = 0;
xenbus_dev_error(dev, err, "allocating event channel");
@@ -1176,9 +1177,9 @@
goto destroy_blkring;
}
- err = xenbus_printf(dev->nodename, "grant-id","%u", info->grant_id);
+ err = xenbus_printf(dev->nodename, "ring-ref","%u", info->ring_ref);
if (err) {
- message = "writing grant-id";
+ message = "writing ring-ref";
goto abort_transaction;
}
err = xenbus_printf(dev->nodename,
diff -r e2025593f702 -r 112d44270733
linux-2.6-xen-sparse/drivers/xen/blkfront/block.h
--- a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h Wed Aug 24 23:16:52 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h Thu Aug 25 18:18:47 2005
@@ -112,7 +112,7 @@
int connected;
char *backend;
int backend_id;
- int grant_id;
+ int ring_ref;
blkif_front_ring_t ring;
unsigned int evtchn;
struct xlbd_major_info *mi;
diff -r e2025593f702 -r 112d44270733
linux-2.6-xen-sparse/drivers/xen/console/console.c
--- a/linux-2.6-xen-sparse/drivers/xen/console/console.c Wed Aug 24
23:16:52 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/console/console.c Thu Aug 25
18:18:47 2005
@@ -240,7 +240,11 @@
#endif
/*** Useful function for console debugging -- goes straight to Xen. ***/
+#ifdef CONFIG_XEN_PRIVILEGED_GUEST
asmlinkage int xprintk(const char *fmt, ...)
+#else
+asmlinkage int xprintk(const char *fmt, ...)
+#endif
{
va_list args;
int printk_len;
diff -r e2025593f702 -r 112d44270733
linux-2.6-xen-sparse/drivers/xen/netback/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/netback/Makefile Wed Aug 24 23:16:52 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/Makefile Thu Aug 25 18:18:47 2005
@@ -1,2 +1,2 @@
-obj-y := netback.o control.o interface.o loopback.o
+obj-y := netback.o xenbus.o interface.o loopback.o
diff -r e2025593f702 -r 112d44270733
linux-2.6-xen-sparse/drivers/xen/netback/common.h
--- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h Wed Aug 24 23:16:52 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h Thu Aug 25 18:18:47 2005
@@ -59,6 +59,7 @@
grant_ref_t rx_shmem_ref;
#endif
unsigned int evtchn;
+ unsigned int remote_evtchn;
/* The shared rings and indexes. */
netif_tx_interface_t *tx;
@@ -82,36 +83,30 @@
/* Miscellaneous private stuff. */
enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
int active;
- /*
- * DISCONNECT response is deferred until pending requests are ack'ed.
- * We therefore need to store the id from the original request.
- */
- u8 disconnect_rspid;
- struct netif_st *hash_next;
struct list_head list; /* scheduling list */
atomic_t refcnt;
struct net_device *dev;
struct net_device_stats stats;
- struct work_struct work;
+ struct work_struct free_work;
} netif_t;
-void netif_create(netif_be_create_t *create);
-void netif_destroy(netif_be_destroy_t *destroy);
-void netif_creditlimit(netif_be_creditlimit_t *creditlimit);
-void netif_connect(netif_be_connect_t *connect);
-int netif_disconnect(netif_be_disconnect_t *disconnect, u8 rsp_id);
-void netif_disconnect_complete(netif_t *netif);
-netif_t *netif_find_by_handle(domid_t domid, unsigned int handle);
+void netif_creditlimit(netif_t *netif);
+int netif_disconnect(netif_t *netif);
+
+netif_t *alloc_netif(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN]);
+void free_netif_callback(netif_t *netif);
+int netif_map(netif_t *netif, unsigned long tx_ring_ref,
+ unsigned long rx_ring_ref, unsigned int evtchn);
+
#define netif_get(_b) (atomic_inc(&(_b)->refcnt))
#define netif_put(_b) \
do { \
if ( atomic_dec_and_test(&(_b)->refcnt) ) \
- netif_disconnect_complete(_b); \
+ free_netif_callback(_b); \
} while (0)
-void netif_interface_init(void);
-void netif_ctrlif_init(void);
+void netif_xenbus_init(void);
void netif_schedule_work(netif_t *netif);
void netif_deschedule_work(netif_t *netif);
diff -r e2025593f702 -r 112d44270733
linux-2.6-xen-sparse/drivers/xen/netback/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Wed Aug 24
23:16:52 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Thu Aug 25
18:18:47 2005
@@ -9,24 +9,6 @@
#include "common.h"
#include <linux/rtnetlink.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
-#endif
-
-#define NETIF_HASHSZ 1024
-#define NETIF_HASH(_d,_h) (((int)(_d)^(int)(_h))&(NETIF_HASHSZ-1))
-
-static netif_t *netif_hash[NETIF_HASHSZ];
-
-netif_t *netif_find_by_handle(domid_t domid, unsigned int handle)
-{
- netif_t *netif = netif_hash[NETIF_HASH(domid, handle)];
- while ( (netif != NULL) &&
- ((netif->domid != domid) || (netif->handle != handle)) )
- netif = netif->hash_next;
- return netif;
-}
-
static void __netif_up(netif_t *netif)
{
struct net_device *dev = netif->dev;
@@ -51,7 +33,7 @@
static int net_open(struct net_device *dev)
{
netif_t *netif = netdev_priv(dev);
- if ( netif->status == CONNECTED )
+ if (netif->status == CONNECTED)
__netif_up(netif);
netif_start_queue(dev);
return 0;
@@ -61,92 +43,23 @@
{
netif_t *netif = netdev_priv(dev);
netif_stop_queue(dev);
- if ( netif->status == CONNECTED )
+ if (netif->status == CONNECTED)
__netif_down(netif);
return 0;
}
-static void __netif_disconnect_complete(void *arg)
-{
- netif_t *netif = (netif_t *)arg;
- ctrl_msg_t cmsg;
- netif_be_disconnect_t disc;
-#if defined(CONFIG_XEN_NETDEV_GRANT_RX) || defined(CONFIG_XEN_NETDEV_GRANT_TX)
- struct gnttab_unmap_grant_ref op;
-#endif
-
- /*
- * These can't be done in netif_disconnect() because at that point there
- * may be outstanding requests in the network stack whose asynchronous
- * responses must still be notified to the remote driver.
- */
-
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
- op.host_addr = netif->tx_shmem_vaddr;
- op.handle = netif->tx_shmem_handle;
- op.dev_bus_addr = 0;
- BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
-#endif
-
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
- op.host_addr = netif->rx_shmem_vaddr;
- op.handle = netif->rx_shmem_handle;
- op.dev_bus_addr = 0;
- BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
-#endif
-
-
- vfree(netif->tx); /* Frees netif->rx as well. */
-
- /* Construct the deferred response message. */
- cmsg.type = CMSG_NETIF_BE;
- cmsg.subtype = CMSG_NETIF_BE_DISCONNECT;
- cmsg.id = netif->disconnect_rspid;
- cmsg.length = sizeof(netif_be_disconnect_t);
- disc.domid = netif->domid;
- disc.netif_handle = netif->handle;
- disc.status = NETIF_BE_STATUS_OKAY;
- memcpy(cmsg.msg, &disc, sizeof(disc));
-
- /*
- * Make sure message is constructed /before/ status change, because
- * after the status change the 'netif' structure could be deallocated at
- * any time. Also make sure we send the response /after/ status change,
- * as otherwise a subsequent CONNECT request could spuriously fail if
- * another CPU doesn't see the status change yet.
- */
- mb();
- if ( netif->status != DISCONNECTING )
- BUG();
- netif->status = DISCONNECTED;
- mb();
-
- /* Send the successful response. */
- ctrl_if_send_response(&cmsg);
-}
-
-void netif_disconnect_complete(netif_t *netif)
-{
- INIT_WORK(&netif->work, __netif_disconnect_complete, (void *)netif);
- schedule_work(&netif->work);
-}
-
-void netif_create(netif_be_create_t *create)
-{
- int err = 0;
- domid_t domid = create->domid;
- unsigned int handle = create->netif_handle;
+netif_t *alloc_netif(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN])
+{
+ int err = 0, i;
struct net_device *dev;
- netif_t **pnetif, *netif;
- char name[IFNAMSIZ] = {};
+ netif_t *netif;
+ char name[IFNAMSIZ] = {};
snprintf(name, IFNAMSIZ - 1, "vif%u.%u", domid, handle);
dev = alloc_netdev(sizeof(netif_t), name, ether_setup);
- if ( dev == NULL )
- {
+ if (dev == NULL) {
DPRINTK("Could not create netif: out of memory\n");
- create->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
- return;
+ return NULL;
}
netif = netdev_priv(dev);
@@ -161,19 +74,6 @@
netif->credit_usec = 0UL;
init_timer(&netif->credit_timeout);
- pnetif = &netif_hash[NETIF_HASH(domid, handle)];
- while ( *pnetif != NULL )
- {
- if ( ((*pnetif)->domid == domid) && ((*pnetif)->handle == handle) )
- {
- DPRINTK("Could not create netif: already exists\n");
- create->status = NETIF_BE_STATUS_INTERFACE_EXISTS;
- free_netdev(dev);
- return;
- }
- pnetif = &(*pnetif)->hash_next;
- }
-
dev->hard_start_xmit = netif_be_start_xmit;
dev->get_stats = netif_be_get_stats;
dev->open = net_open;
@@ -183,10 +83,10 @@
/* Disable queuing. */
dev->tx_queue_len = 0;
- if ( (create->be_mac[0] == 0) && (create->be_mac[1] == 0) &&
- (create->be_mac[2] == 0) && (create->be_mac[3] == 0) &&
- (create->be_mac[4] == 0) && (create->be_mac[5] == 0) )
- {
+ for (i = 0; i < ETH_ALEN; i++)
+ if (be_mac[i] != 0)
+ break;
+ if (i == ETH_ALEN) {
/*
* Initialise a dummy MAC address. We choose the numerically largest
* non-broadcast address to prevent the address getting stolen by an
@@ -194,87 +94,200 @@
*/
memset(dev->dev_addr, 0xFF, ETH_ALEN);
dev->dev_addr[0] &= ~0x01;
- }
- else
- {
- memcpy(dev->dev_addr, create->be_mac, ETH_ALEN);
- }
-
- memcpy(netif->fe_dev_addr, create->mac, ETH_ALEN);
+ } else
+ memcpy(dev->dev_addr, be_mac, ETH_ALEN);
rtnl_lock();
err = register_netdevice(dev);
rtnl_unlock();
-
- if ( err != 0 )
- {
+ if (err) {
DPRINTK("Could not register new net device %s: err=%d\n",
dev->name, err);
- create->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
free_netdev(dev);
- return;
- }
-
- netif->hash_next = *pnetif;
- *pnetif = netif;
+ return NULL;
+ }
DPRINTK("Successfully created netif\n");
- create->status = NETIF_BE_STATUS_OKAY;
-}
-
-void netif_destroy(netif_be_destroy_t *destroy)
-{
- domid_t domid = destroy->domid;
- unsigned int handle = destroy->netif_handle;
- netif_t **pnetif, *netif;
-
- pnetif = &netif_hash[NETIF_HASH(domid, handle)];
- while ( (netif = *pnetif) != NULL )
+ return netif;
+}
+
+static int map_frontend_page(netif_t *netif, unsigned long localaddr,
+ unsigned long tx_ring_ref, unsigned long
rx_ring_ref)
+{
+#if !defined(CONFIG_XEN_NETDEV_GRANT_TX)||!defined(CONFIG_XEN_NETDEV_GRANT_RX)
+ pgprot_t prot = __pgprot(_KERNPG_TABLE);
+ int err;
+#endif
+#if defined(CONFIG_XEN_NETDEV_GRANT_TX)
{
- if ( (netif->domid == domid) && (netif->handle == handle) )
- {
- if ( netif->status != DISCONNECTED )
- goto still_connected;
- goto destroy;
+ struct gnttab_map_grant_ref op;
+
+ /* Map: Use the Grant table reference */
+ op.host_addr = localaddr;
+ op.flags = GNTMAP_host_map;
+ op.ref = tx_ring_ref;
+ op.dom = netif->domid;
+
+ BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) );
+ if (op.handle < 0) {
+ DPRINTK(" Grant table operation failure !\n");
+ return op.handle;
}
- pnetif = &netif->hash_next;
- }
-
- destroy->status = NETIF_BE_STATUS_INTERFACE_NOT_FOUND;
- return;
-
- still_connected:
- destroy->status = NETIF_BE_STATUS_INTERFACE_CONNECTED;
- return;
-
- destroy:
- *pnetif = netif->hash_next;
+
+ netif->tx_shmem_ref = tx_ring_ref;
+ netif->tx_shmem_handle = op.handle;
+ netif->tx_shmem_vaddr = localaddr;
+ }
+#else
+ err = direct_remap_area_pages(&init_mm, localaddr,
+ tx_ring_ref<<PAGE_SHIFT, PAGE_SIZE,
+ prot, netif->domid);
+ if (err)
+ return err;
+#endif
+
+#if defined(CONFIG_XEN_NETDEV_GRANT_RX)
+ {
+ struct gnttab_map_grant_ref op;
+
+ /* Map: Use the Grant table reference */
+ op.host_addr = localaddr + PAGE_SIZE;
+ op.flags = GNTMAP_host_map;
+ op.ref = rx_ring_ref;
+ op.dom = netif->domid;
+
+ BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) );
+ if (op.handle < 0) {
+ DPRINTK(" Grant table operation failure !\n");
+ return op.handle;
+ }
+
+ netif->rx_shmem_ref = rx_ring_ref;
+ netif->rx_shmem_handle = op.handle;
+ netif->rx_shmem_vaddr = localaddr + PAGE_SIZE;
+ }
+#else
+ err = direct_remap_area_pages(&init_mm, localaddr + PAGE_SIZE,
+ rx_ring_ref<<PAGE_SHIFT, PAGE_SIZE,
+ prot, netif->domid);
+ if (err)
+ return err;
+#endif
+
+ return 0;
+}
+
+static void unmap_frontend_page(netif_t *netif)
+{
+#if defined(CONFIG_XEN_NETDEV_GRANT_RX) || defined(CONFIG_XEN_NETDEV_GRANT_TX)
+ struct gnttab_unmap_grant_ref op;
+#endif
+
+#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+ op.host_addr = netif->tx_shmem_vaddr;
+ op.handle = netif->tx_shmem_handle;
+ op.dev_bus_addr = 0;
+ BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
+#endif
+
+#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+ op.host_addr = netif->rx_shmem_vaddr;
+ op.handle = netif->rx_shmem_handle;
+ op.dev_bus_addr = 0;
+ BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
+#endif
+}
+
+int netif_map(netif_t *netif, unsigned long tx_ring_ref,
+ unsigned long rx_ring_ref, unsigned int evtchn)
+{
+ struct vm_struct *vma;
+ evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain };
+ int err;
+
+ vma = get_vm_area(2*PAGE_SIZE, VM_IOREMAP);
+ if (vma == NULL)
+ return -ENOMEM;
+
+ err = map_frontend_page(netif, (unsigned long)vma->addr, tx_ring_ref,
+ rx_ring_ref);
+ if (err) {
+ vfree(vma->addr);
+ return err;
+ }
+
+ op.u.bind_interdomain.dom1 = DOMID_SELF;
+ op.u.bind_interdomain.dom2 = netif->domid;
+ op.u.bind_interdomain.port1 = 0;
+ op.u.bind_interdomain.port2 = evtchn;
+ err = HYPERVISOR_event_channel_op(&op);
+ if (err) {
+ unmap_frontend_page(netif);
+ vfree(vma->addr);
+ return err;
+ }
+
+ netif->evtchn = op.u.bind_interdomain.port1;
+ netif->remote_evtchn = evtchn;
+
+ netif->tx = (netif_tx_interface_t *)vma->addr;
+ netif->rx = (netif_rx_interface_t *)((char *)vma->addr + PAGE_SIZE);
+ netif->tx->resp_prod = netif->rx->resp_prod = 0;
+ netif_get(netif);
+ wmb(); /* Other CPUs see new state before interface is started. */
+
+ rtnl_lock();
+ netif->status = CONNECTED;
+ wmb();
+ if (netif_running(netif->dev))
+ __netif_up(netif);
+ rtnl_unlock();
+
+ return 0;
+}
+
+static void free_netif(void *arg)
+{
+ evtchn_op_t op = { .cmd = EVTCHNOP_close };
+ netif_t *netif = (netif_t *)arg;
+
+ /*
+ * These can't be done in netif_disconnect() because at that point there
+ * may be outstanding requests in the network stack whose asynchronous
+ * responses must still be notified to the remote driver.
+ */
+
+ op.u.close.port = netif->evtchn;
+ op.u.close.dom = DOMID_SELF;
+ HYPERVISOR_event_channel_op(&op);
+ op.u.close.port = netif->remote_evtchn;
+ op.u.close.dom = netif->domid;
+ HYPERVISOR_event_channel_op(&op);
+
unregister_netdev(netif->dev);
+
+ if (netif->tx) {
+ unmap_frontend_page(netif);
+ vfree(netif->tx); /* Frees netif->rx as well. */
+ }
+
free_netdev(netif->dev);
- destroy->status = NETIF_BE_STATUS_OKAY;
-}
-
-void netif_creditlimit(netif_be_creditlimit_t *creditlimit)
-{
- domid_t domid = creditlimit->domid;
- unsigned int handle = creditlimit->netif_handle;
- netif_t *netif;
-
- netif = netif_find_by_handle(domid, handle);
- if ( unlikely(netif == NULL) )
- {
- DPRINTK("netif_creditlimit attempted for non-existent netif"
- " (%u,%u)\n", creditlimit->domid, creditlimit->netif_handle);
- creditlimit->status = NETIF_BE_STATUS_INTERFACE_NOT_FOUND;
- return;
- }
-
+}
+
+void free_netif_callback(netif_t *netif)
+{
+ INIT_WORK(&netif->free_work, free_netif, (void *)netif);
+ schedule_work(&netif->free_work);
+}
+
+void netif_creditlimit(netif_t *netif)
+{
+#if 0
/* Set the credit limit (reset remaining credit to new limit). */
netif->credit_bytes = netif->remaining_credit = creditlimit->credit_bytes;
netif->credit_usec = creditlimit->period_usec;
- if ( netif->status == CONNECTED )
- {
+ if (netif->status == CONNECTED) {
/*
* Schedule work so that any packets waiting under previous credit
* limit are dealt with (acts like a replenishment point).
@@ -282,184 +295,22 @@
netif->credit_timeout.expires = jiffies;
netif_schedule_work(netif);
}
-
- creditlimit->status = NETIF_BE_STATUS_OKAY;
-}
-
-void netif_connect(netif_be_connect_t *connect)
-{
- domid_t domid = connect->domid;
- unsigned int handle = connect->netif_handle;
- unsigned int evtchn = connect->evtchn;
- unsigned long tx_shmem_frame = connect->tx_shmem_frame;
- unsigned long rx_shmem_frame = connect->rx_shmem_frame;
- struct vm_struct *vma;
-#if !defined(CONFIG_XEN_NETDEV_GRANT_TX)||!defined(CONFIG_XEN_NETDEV_GRANT_RX)
- pgprot_t prot = __pgprot(_KERNPG_TABLE);
- int error;
-#endif
- netif_t *netif;
-
- netif = netif_find_by_handle(domid, handle);
- if ( unlikely(netif == NULL) ) {
- DPRINTK("netif_connect attempted for non-existent netif (%u,%u)\n",
- connect->domid, connect->netif_handle);
- connect->status = NETIF_BE_STATUS_INTERFACE_NOT_FOUND;
- return;
- }
-
- if ( netif->status != DISCONNECTED ) {
- connect->status = NETIF_BE_STATUS_INTERFACE_CONNECTED;
- return;
- }
-
- if ( (vma = get_vm_area(2*PAGE_SIZE, VM_IOREMAP)) == NULL ) {
- connect->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
- return;
- }
-
-
-#if defined(CONFIG_XEN_NETDEV_GRANT_TX)
- {
- struct gnttab_map_grant_ref op;
- int tx_ref = connect->tx_shmem_ref;
-
- /* Map: Use the Grant table reference */
- op.host_addr = VMALLOC_VMADDR(vma->addr);
- op.flags = GNTMAP_host_map;
- op.ref = tx_ref;
- op.dom = domid;
-
- if ((HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) < 0) ||
- (op.handle < 0)) {
- DPRINTK(" Grant table operation failure !\n");
- connect->status = NETIF_BE_STATUS_MAPPING_ERROR;
- vfree(vma->addr);
- return;
- }
-
- netif->tx_shmem_ref = tx_ref;
- netif->tx_shmem_handle = op.handle;
- netif->tx_shmem_vaddr = VMALLOC_VMADDR(vma->addr);
- }
-
-
-#else
- error = direct_remap_area_pages(&init_mm,
- VMALLOC_VMADDR(vma->addr),
- tx_shmem_frame<<PAGE_SHIFT, PAGE_SIZE,
- prot, domid);
- if ( error != 0 )
- {
- if ( error == -ENOMEM )
- connect->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
- else if ( error == -EFAULT )
- connect->status = NETIF_BE_STATUS_MAPPING_ERROR;
- else
- connect->status = NETIF_BE_STATUS_ERROR;
- vfree(vma->addr);
- return;
- }
-#endif
-
-
-#if defined(CONFIG_XEN_NETDEV_GRANT_RX)
- {
- struct gnttab_map_grant_ref op;
- int rx_ref = connect->rx_shmem_ref;
-
-
- /* Map: Use the Grant table reference */
- op.host_addr = VMALLOC_VMADDR(vma->addr) + PAGE_SIZE;
- op.flags = GNTMAP_host_map;
- op.ref = rx_ref;
- op.dom = domid;
-
- if ((HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) < 0) ||
- (op.handle < 0)) {
- DPRINTK(" Grant table operation failure !\n");
- connect->status = NETIF_BE_STATUS_MAPPING_ERROR;
- vfree(vma->addr);
- return;
- }
-
- netif->rx_shmem_ref = rx_ref;
- netif->rx_shmem_handle = handle;
- netif->rx_shmem_vaddr = VMALLOC_VMADDR(vma->addr) + PAGE_SIZE;
- }
-#else
- error = direct_remap_area_pages(&init_mm,
- VMALLOC_VMADDR(vma->addr) + PAGE_SIZE,
- rx_shmem_frame<<PAGE_SHIFT, PAGE_SIZE,
- prot, domid);
- if ( error != 0 )
- {
- if ( error == -ENOMEM )
- connect->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
- else if ( error == -EFAULT )
- connect->status = NETIF_BE_STATUS_MAPPING_ERROR;
- else
- connect->status = NETIF_BE_STATUS_ERROR;
- vfree(vma->addr);
- return;
- }
-
-#endif
-
- netif->evtchn = evtchn;
- netif->tx_shmem_frame = tx_shmem_frame;
- netif->rx_shmem_frame = rx_shmem_frame;
- netif->tx =
- (netif_tx_interface_t *)vma->addr;
- netif->rx =
- (netif_rx_interface_t *)((char *)vma->addr + PAGE_SIZE);
- netif->tx->resp_prod = netif->rx->resp_prod = 0;
- netif_get(netif);
- wmb(); /* Other CPUs see new state before interface is started. */
-
- rtnl_lock();
- netif->status = CONNECTED;
- wmb();
- if ( netif_running(netif->dev) )
- __netif_up(netif);
- rtnl_unlock();
-
- connect->status = NETIF_BE_STATUS_OKAY;
-}
-
-int netif_disconnect(netif_be_disconnect_t *disconnect, u8 rsp_id)
-{
- domid_t domid = disconnect->domid;
- unsigned int handle = disconnect->netif_handle;
- netif_t *netif;
-
- netif = netif_find_by_handle(domid, handle);
- if ( unlikely(netif == NULL) )
- {
- DPRINTK("netif_disconnect attempted for non-existent netif"
- " (%u,%u)\n", disconnect->domid, disconnect->netif_handle);
- disconnect->status = NETIF_BE_STATUS_INTERFACE_NOT_FOUND;
- return 1; /* Caller will send response error message. */
- }
-
- if ( netif->status == CONNECTED )
- {
+#endif
+}
+
+int netif_disconnect(netif_t *netif)
+{
+
+ if (netif->status == CONNECTED) {
rtnl_lock();
netif->status = DISCONNECTING;
- netif->disconnect_rspid = rsp_id;
wmb();
- if ( netif_running(netif->dev) )
+ if (netif_running(netif->dev))
__netif_down(netif);
rtnl_unlock();
netif_put(netif);
return 0; /* Caller should not send response message. */
}
- disconnect->status = NETIF_BE_STATUS_OKAY;
return 1;
}
-
-void netif_interface_init(void)
-{
- memset(netif_hash, 0, sizeof(netif_hash));
-}
diff -r e2025593f702 -r 112d44270733
linux-2.6-xen-sparse/drivers/xen/netback/netback.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Wed Aug 24
23:16:52 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Thu Aug 25
18:18:47 2005
@@ -13,10 +13,6 @@
#include "common.h"
#include <asm-xen/balloon.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-#include <linux/delay.h>
-#endif
-
#if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX)
#include <asm-xen/xen-public/grant_table.h>
#include <asm-xen/gnttab.h>
@@ -153,11 +149,7 @@
static inline int is_xen_skb(struct sk_buff *skb)
{
extern kmem_cache_t *skbuff_cachep;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
kmem_cache_t *cp = (kmem_cache_t *)virt_to_page(skb->head)->lru.next;
-#else
- kmem_cache_t *cp = (kmem_cache_t *)virt_to_page(skb->head)->list.next;
-#endif
return (cp == skbuff_cachep);
}
@@ -642,11 +634,7 @@
netif->credit_timeout.expires = next_credit;
netif->credit_timeout.data = (unsigned long)netif;
netif->credit_timeout.function = tx_credit_callback;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
add_timer_on(&netif->credit_timeout, smp_processor_id());
-#else
- add_timer(&netif->credit_timeout);
-#endif
break;
}
}
@@ -966,8 +954,6 @@
net_timer.data = 0;
net_timer.function = net_alarm;
- netif_interface_init();
-
page = balloon_alloc_empty_page_range(MAX_PENDING_REQS);
BUG_ON(page == NULL);
mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
@@ -987,7 +973,7 @@
spin_lock_init(&net_schedule_list_lock);
INIT_LIST_HEAD(&net_schedule_list);
- netif_ctrlif_init();
+ netif_xenbus_init();
(void)request_irq(bind_virq_to_irq(VIRQ_DEBUG),
netif_be_dbg, SA_SHIRQ,
diff -r e2025593f702 -r 112d44270733
linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Wed Aug 24
23:16:52 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Thu Aug 25
18:18:47 2005
@@ -48,7 +48,7 @@
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm-xen/evtchn.h>
-#include <asm-xen/ctrl_if.h>
+#include <asm-xen/xenbus.h>
#include <asm-xen/xen-public/io/netif.h>
#include <asm-xen/balloon.h>
#include <asm/page.h>
@@ -112,9 +112,13 @@
#endif
#if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX)
-static domid_t rdomid = 0;
#define GRANT_INVALID_REF (0xFFFF)
#endif
+
+#define NETIF_STATE_DISCONNECTED 0
+#define NETIF_STATE_CONNECTED 1
+
+static unsigned int netif_state = NETIF_STATE_DISCONNECTED;
static void network_tx_buf_gc(struct net_device *dev);
static void network_alloc_rx_buffers(struct net_device *dev);
@@ -133,12 +137,11 @@
#define xennet_proc_delif(d) ((void)0)
#endif
-static struct list_head dev_list;
-
+#define netfront_info net_private
struct net_private
{
struct list_head list;
- struct net_device *dev;
+ struct net_device *netdev;
struct net_device_stats stats;
NETIF_RING_IDX rx_resp_cons, tx_resp_cons;
@@ -176,6 +179,14 @@
*/
struct sk_buff *tx_skbs[NETIF_TX_RING_SIZE+1];
struct sk_buff *rx_skbs[NETIF_RX_RING_SIZE+1];
+
+ struct xenbus_device *xbdev;
+ char *backend;
+ int backend_id;
+ struct xenbus_watch watch;
+ int tx_ring_ref;
+ int rx_ring_ref;
+ u8 mac[ETH_ALEN];
};
/* Access macros for acquiring freeing slots in {tx,rx}_skbs[]. */
@@ -187,20 +198,14 @@
(_list)[0] = (_list)[_id]; \
(unsigned short)_id; })
-static char *status_name[] = {
- [NETIF_INTERFACE_STATUS_CLOSED] = "closed",
- [NETIF_INTERFACE_STATUS_DISCONNECTED] = "disconnected",
- [NETIF_INTERFACE_STATUS_CONNECTED] = "connected",
- [NETIF_INTERFACE_STATUS_CHANGED] = "changed",
-};
-
+#ifdef DEBUG
static char *be_state_name[] = {
[BEST_CLOSED] = "closed",
[BEST_DISCONNECTED] = "disconnected",
[BEST_CONNECTED] = "connected",
};
-
-#define DEBUG
+#endif
+
#ifdef DEBUG
#define DPRINTK(fmt, args...) \
printk(KERN_ALERT "xen_net (%s:%d) " fmt, __FUNCTION__, __LINE__, ##args)
@@ -211,89 +216,6 @@
printk(KERN_INFO "xen_net: " fmt, ##args)
#define WPRINTK(fmt, args...) \
printk(KERN_WARNING "xen_net: " fmt, ##args)
-
-static struct net_device *find_dev_by_handle(unsigned int handle)
-{
- struct list_head *ent;
- struct net_private *np;
- list_for_each (ent, &dev_list) {
- np = list_entry(ent, struct net_private, list);
- if (np->handle == handle)
- return np->dev;
- }
- return NULL;
-}
-
-/** Network interface info. */
-struct netif_ctrl {
- /** Number of interfaces. */
- int interface_n;
- /** Number of connected interfaces. */
- int connected_n;
- /** Error code. */
- int err;
- int up;
-};
-
-static struct netif_ctrl netctrl;
-
-static void netctrl_init(void)
-{
- memset(&netctrl, 0, sizeof(netctrl));
- netctrl.up = NETIF_DRIVER_STATUS_DOWN;
-}
-
-/** Get or set a network interface error.
- */
-static int netctrl_err(int err)
-{
- if ((err < 0) && !netctrl.err)
- netctrl.err = err;
- return netctrl.err;
-}
-
-/** Test if all network interfaces are connected.
- *
- * @return 1 if all connected, 0 if not, negative error code otherwise
- */
-static int netctrl_connected(void)
-{
- int ok;
-
- if (netctrl.err)
- ok = netctrl.err;
- else if (netctrl.up == NETIF_DRIVER_STATUS_UP)
- ok = (netctrl.connected_n == netctrl.interface_n);
- else
- ok = 0;
-
- return ok;
-}
-
-/** Count the connected network interfaces.
- *
- * @return connected count
- */
-static int netctrl_connected_count(void)
-{
-
- struct list_head *ent;
- struct net_private *np;
- unsigned int connected;
-
- connected = 0;
-
- list_for_each(ent, &dev_list) {
- np = list_entry(ent, struct net_private, list);
- if (np->backend_state == BEST_CONNECTED)
- connected++;
- }
-
- netctrl.connected_n = connected;
- DPRINTK("> connected_n=%d interface_n=%d\n",
- netctrl.connected_n, netctrl.interface_n);
- return connected;
-}
/** Send a packet on a net device to encourage switches to learn the
* MAC. We send a fake ARP request.
@@ -364,7 +286,7 @@
"still in use by backend domain.\n");
goto out;
}
- gnttab_end_foreign_access(grant_tx_ref[id], GNTMAP_readonly);
+ gnttab_end_foreign_access_ref(grant_tx_ref[id], GNTMAP_readonly);
gnttab_release_grant_reference(&gref_tx_head, grant_tx_ref[id]);
grant_tx_ref[id] = GRANT_INVALID_REF;
#endif
@@ -448,7 +370,7 @@
BUG();
}
grant_rx_ref[id] = ref;
- gnttab_grant_foreign_transfer_ref(ref, rdomid,
+ gnttab_grant_foreign_transfer_ref(ref, np->backend_id,
virt_to_mfn(skb->head));
np->rx->ring[MASK_NETIF_RX_IDX(req_prod + i)].req.gref = ref;
#endif
@@ -544,7 +466,7 @@
BUG();
}
mfn = virt_to_mfn(skb->data);
- gnttab_grant_foreign_access_ref(ref, rdomid, mfn, GNTMAP_readonly);
+ gnttab_grant_foreign_access_ref(ref, np->backend_id, mfn, GNTMAP_readonly);
tx->addr = ref << PAGE_SHIFT;
grant_tx_ref[id] = ref;
#else
@@ -650,7 +572,7 @@
#ifdef CONFIG_XEN_NETDEV_GRANT_RX
ref = grant_rx_ref[rx->id];
grant_rx_ref[rx->id] = GRANT_INVALID_REF;
- mfn = gnttab_end_foreign_transfer(ref);
+ mfn = gnttab_end_foreign_transfer_ref(ref);
gnttab_release_grant_reference(&gref_rx_head, ref);
#endif
@@ -809,7 +731,7 @@
{
struct net_private *np = netdev_priv(dev);
np->user_state = UST_CLOSED;
- netif_stop_queue(np->dev);
+ netif_stop_queue(np->netdev);
return 0;
}
@@ -821,8 +743,7 @@
}
-static void network_connect(struct net_device *dev,
- netif_fe_interface_status_t *status)
+static void network_connect(struct net_device *dev)
{
struct net_private *np;
int i, requeue_idx;
@@ -890,7 +811,7 @@
*/
np->backend_state = BEST_CONNECTED;
wmb();
- notify_via_evtchn(status->evtchn);
+ notify_via_evtchn(np->evtchn);
network_tx_buf_gc(dev);
if (np->user_state == UST_OPEN)
@@ -900,148 +821,21 @@
spin_unlock_irq(&np->tx_lock);
}
-static void vif_show(struct net_private *np)
+static void show_device(struct net_private *np)
{
#ifdef DEBUG
- if (np) {
- IPRINTK("<vif handle=%u %s(%s) evtchn=%u tx=%p rx=%p>\n",
- np->handle,
- be_state_name[np->backend_state],
- np->user_state ? "open" : "closed",
- np->evtchn,
- np->tx,
- np->rx);
- } else {
- IPRINTK("<vif NULL>\n");
- }
-#endif
-}
-
-/* Send a connect message to xend to tell it to bring up the interface. */
-static void send_interface_connect(struct net_private *np)
-{
- int err;
- ctrl_msg_t cmsg = {
- .type = CMSG_NETIF_FE,
- .subtype = CMSG_NETIF_FE_INTERFACE_CONNECT,
- .length = sizeof(netif_fe_interface_connect_t),
- };
- netif_fe_interface_connect_t *msg = (void*)cmsg.msg;
-
- msg->handle = np->handle;
- msg->tx_shmem_frame = virt_to_mfn(np->tx);
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
- err = gnttab_grant_foreign_access(rdomid, msg->tx_shmem_frame, 0);
- if (err < 0) {
- printk(KERN_ALERT "#### netfront can't grant access to tx_shmem\n");
- BUG();
- }
- msg->tx_shmem_ref = err;
-#endif
-
- msg->rx_shmem_frame = virt_to_mfn(np->rx);
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
- err = gnttab_grant_foreign_access(rdomid, msg->rx_shmem_frame, 0);
- if (err < 0) {
- printk(KERN_ALERT "#### netfront can't grant access to rx_shmem\n");
- BUG();
- }
- msg->rx_shmem_ref = err;
-#endif
-
- ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
-}
-
-/* Send a driver status notification to the domain controller. */
-static int send_driver_status(int ok)
-{
- int err = 0;
- ctrl_msg_t cmsg = {
- .type = CMSG_NETIF_FE,
- .subtype = CMSG_NETIF_FE_DRIVER_STATUS,
- .length = sizeof(netif_fe_driver_status_t),
- };
- netif_fe_driver_status_t *msg = (void*)cmsg.msg;
-
- msg->status = (ok ? NETIF_DRIVER_STATUS_UP : NETIF_DRIVER_STATUS_DOWN);
- err = ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
- return err;
-}
-
-/* Stop network device and free tx/rx queues and irq.
- */
-static void vif_release(struct net_private *np)
-{
- /* Stop old i/f to prevent errors whilst we rebuild the state. */
- spin_lock_irq(&np->tx_lock);
- spin_lock(&np->rx_lock);
- netif_stop_queue(np->dev);
- /* np->backend_state = BEST_DISCONNECTED; */
- spin_unlock(&np->rx_lock);
- spin_unlock_irq(&np->tx_lock);
-
- /* Free resources. */
- if ( np->tx != NULL )
- {
- unbind_evtchn_from_irqhandler(np->evtchn, np->dev);
- free_page((unsigned long)np->tx);
- free_page((unsigned long)np->rx);
- np->evtchn = 0;
- np->tx = NULL;
- np->rx = NULL;
- }
-}
-
-/* Release vif resources and close it down completely.
- */
-static void vif_close(struct net_private *np)
-{
- WPRINTK("Unexpected netif-CLOSED message in state %s\n",
- be_state_name[np->backend_state]);
- vif_release(np);
- np->backend_state = BEST_CLOSED;
- /* todo: take dev down and free. */
- vif_show(np);
-}
-
-/* Move the vif into disconnected state.
- * Allocates tx/rx pages.
- * Sends connect message to xend.
- */
-static void vif_disconnect(struct net_private *np)
-{
- if(np->tx) free_page((unsigned long)np->tx);
- if(np->rx) free_page((unsigned long)np->rx);
- // Before this np->tx and np->rx had better be null.
- np->tx = (netif_tx_interface_t *)__get_free_page(GFP_KERNEL);
- np->rx = (netif_rx_interface_t *)__get_free_page(GFP_KERNEL);
- memset(np->tx, 0, PAGE_SIZE);
- memset(np->rx, 0, PAGE_SIZE);
- np->backend_state = BEST_DISCONNECTED;
- send_interface_connect(np);
- vif_show(np);
-}
-
-/* Begin interface recovery.
- *
- * NB. Whilst we're recovering, we turn the carrier state off. We
- * take measures to ensure that this device isn't used for
- * anything. We also stop the queue for this device. Various
- * different approaches (e.g. continuing to buffer packets) have
- * been tested but don't appear to improve the overall impact on
- * TCP connections.
- *
- * TODO: (MAW) Change the Xend<->Guest protocol so that a recovery
- * is initiated by a special "RESET" message - disconnect could
- * just mean we're not allowed to use this interface any more.
- */
-static void vif_reset(struct net_private *np)
-{
- IPRINTK("Attempting to reconnect network interface: handle=%u\n",
- np->handle);
- vif_release(np);
- vif_disconnect(np);
- vif_show(np);
+ if (np) {
+ IPRINTK("<vif handle=%u %s(%s) evtchn=%u tx=%p rx=%p>\n",
+ np->handle,
+ be_state_name[np->backend_state],
+ np->user_state ? "open" : "closed",
+ np->evtchn,
+ np->tx,
+ np->rx);
+ } else {
+ IPRINTK("<vif NULL>\n");
+ }
+#endif
}
/* Move the vif into connected state.
@@ -1049,26 +843,22 @@
* Binds the irq to the event channel.
*/
static void
-vif_connect(struct net_private *np, netif_fe_interface_status_t *status)
-{
- struct net_device *dev = np->dev;
- memcpy(dev->dev_addr, status->mac, ETH_ALEN);
- network_connect(dev, status);
- np->evtchn = status->evtchn;
-#if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX)
- rdomid = status->domid;
-#endif
- (void)bind_evtchn_to_irqhandler(
- np->evtchn, netif_int, SA_SAMPLE_RANDOM, dev->name, dev);
- netctrl_connected_count();
- (void)send_fake_arp(dev);
- vif_show(np);
+connect_device(struct net_private *np, unsigned int evtchn)
+{
+ struct net_device *dev = np->netdev;
+ memcpy(dev->dev_addr, np->mac, ETH_ALEN);
+ np->evtchn = evtchn;
+ network_connect(dev);
+ (void)bind_evtchn_to_irqhandler(
+ np->evtchn, netif_int, SA_SAMPLE_RANDOM, dev->name, dev);
+ (void)send_fake_arp(dev);
+ show_device(np);
}
static struct ethtool_ops network_ethtool_ops =
{
- .get_tx_csum = ethtool_op_get_tx_csum,
- .set_tx_csum = ethtool_op_set_tx_csum,
+ .get_tx_csum = ethtool_op_get_tx_csum,
+ .set_tx_csum = ethtool_op_set_tx_csum,
};
/** Create a network device.
@@ -1076,22 +866,24 @@
* @param val return parameter for created device
* @return 0 on success, error code otherwise
*/
-static int create_netdev(int handle, struct net_device **val)
+static int create_netdev(int handle, struct xenbus_device *dev,
+ struct net_device **val)
{
int i, err = 0;
- struct net_device *dev = NULL;
+ struct net_device *netdev = NULL;
struct net_private *np = NULL;
- if ((dev = alloc_etherdev(sizeof(struct net_private))) == NULL) {
+ if ((netdev = alloc_etherdev(sizeof(struct net_private))) == NULL) {
printk(KERN_WARNING "%s> alloc_etherdev failed.\n", __FUNCTION__);
err = -ENOMEM;
goto exit;
}
- np = netdev_priv(dev);
+ np = netdev_priv(netdev);
np->backend_state = BEST_CLOSED;
np->user_state = UST_CLOSED;
np->handle = handle;
+ np->xbdev = dev;
spin_lock_init(&np->tx_lock);
spin_lock_init(&np->rx_lock);
@@ -1115,268 +907,53 @@
#endif
}
- dev->open = network_open;
- dev->hard_start_xmit = network_start_xmit;
- dev->stop = network_close;
- dev->get_stats = network_get_stats;
- dev->poll = netif_poll;
- dev->weight = 64;
- dev->features = NETIF_F_IP_CSUM;
-
- SET_ETHTOOL_OPS(dev, &network_ethtool_ops);
-
- if ((err = register_netdev(dev)) != 0) {
+ netdev->open = network_open;
+ netdev->hard_start_xmit = network_start_xmit;
+ netdev->stop = network_close;
+ netdev->get_stats = network_get_stats;
+ netdev->poll = netif_poll;
+ netdev->weight = 64;
+ netdev->features = NETIF_F_IP_CSUM;
+
+ SET_ETHTOOL_OPS(netdev, &network_ethtool_ops);
+
+ if ((err = register_netdev(netdev)) != 0) {
printk(KERN_WARNING "%s> register_netdev err=%d\n", __FUNCTION__, err);
goto exit;
}
- if ((err = xennet_proc_addif(dev)) != 0) {
- unregister_netdev(dev);
+ if ((err = xennet_proc_addif(netdev)) != 0) {
+ unregister_netdev(netdev);
goto exit;
}
- np->dev = dev;
- list_add(&np->list, &dev_list);
+ np->netdev = netdev;
exit:
- if ((err != 0) && (dev != NULL))
- kfree(dev);
+ if ((err != 0) && (netdev != NULL))
+ kfree(netdev);
else if (val != NULL)
- *val = dev;
+ *val = netdev;
return err;
}
-/* Get the target interface for a status message.
- * Creates the interface when it makes sense.
- * The returned interface may be null when there is no error.
- *
- * @param status status message
- * @param np return parameter for interface state
- * @return 0 on success, error code otherwise
- */
-static int
-target_vif(netif_fe_interface_status_t *status, struct net_private **np)
-{
- int err = 0;
- struct net_device *dev;
-
- DPRINTK("> handle=%d\n", status->handle);
- if (status->handle < 0) {
- err = -EINVAL;
- goto exit;
- }
-
- if ((dev = find_dev_by_handle(status->handle)) != NULL)
- goto exit;
-
- if (status->status == NETIF_INTERFACE_STATUS_CLOSED)
- goto exit;
- if (status->status == NETIF_INTERFACE_STATUS_CHANGED)
- goto exit;
-
- /* It's a new interface in a good state - create it. */
- DPRINTK("> create device...\n");
- if ((err = create_netdev(status->handle, &dev)) != 0)
- goto exit;
-
- netctrl.interface_n++;
-
- exit:
- if (np != NULL)
- *np = ((dev && !err) ? netdev_priv(dev) : NULL);
- DPRINTK("< err=%d\n", err);
- return err;
-}
-
-/* Handle an interface status message. */
-static void netif_interface_status(netif_fe_interface_status_t *status)
-{
- int err = 0;
- struct net_private *np = NULL;
-
- DPRINTK("> status=%s handle=%d\n",
- status_name[status->status], status->handle);
-
- if ((err = target_vif(status, &np)) != 0) {
- WPRINTK("Invalid netif: handle=%u\n", status->handle);
- return;
- }
-
- if (np == NULL) {
- DPRINTK("> no vif\n");
- return;
- }
-
- switch (status->status) {
- case NETIF_INTERFACE_STATUS_CLOSED:
- switch (np->backend_state) {
- case BEST_CLOSED:
- case BEST_DISCONNECTED:
- case BEST_CONNECTED:
- vif_close(np);
- break;
- }
- break;
-
- case NETIF_INTERFACE_STATUS_DISCONNECTED:
- switch (np->backend_state) {
- case BEST_CLOSED:
- vif_disconnect(np);
- break;
- case BEST_DISCONNECTED:
- case BEST_CONNECTED:
- vif_reset(np);
- break;
- }
- break;
-
- case NETIF_INTERFACE_STATUS_CONNECTED:
- switch (np->backend_state) {
- case BEST_CLOSED:
- WPRINTK("Unexpected netif status %s in state %s\n",
- status_name[status->status],
- be_state_name[np->backend_state]);
- vif_disconnect(np);
- vif_connect(np, status);
- break;
- case BEST_DISCONNECTED:
- vif_connect(np, status);
- break;
- }
- break;
-
- case NETIF_INTERFACE_STATUS_CHANGED:
- /*
- * The domain controller is notifying us that a device has been
- * added or removed.
- */
- break;
-
- default:
- WPRINTK("Invalid netif status code %d\n", status->status);
- break;
- }
-
- vif_show(np);
-}
-
-/*
- * Initialize the network control interface.
- */
-static void netif_driver_status(netif_fe_driver_status_t *status)
-{
- netctrl.up = status->status;
- netctrl_connected_count();
-}
-
-/* Receive handler for control messages. */
-static void netif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
-{
-
- switch (msg->subtype) {
- case CMSG_NETIF_FE_INTERFACE_STATUS:
- netif_interface_status((netif_fe_interface_status_t *) &msg->msg[0]);
- break;
-
- case CMSG_NETIF_FE_DRIVER_STATUS:
- netif_driver_status((netif_fe_driver_status_t *) &msg->msg[0]);
- break;
-
- default:
- msg->length = 0;
- break;
- }
-
- ctrl_if_send_response(msg);
-}
-
-
-#if 1
-/* Wait for all interfaces to be connected.
- *
- * This works OK, but we'd like to use the probing mode (see below).
- */
-static int probe_interfaces(void)
-{
- int err = 0, conn = 0;
- int wait_i, wait_n = 100;
-
- DPRINTK(">\n");
-
- for (wait_i = 0; wait_i < wait_n; wait_i++) {
- DPRINTK("> wait_i=%d\n", wait_i);
- conn = netctrl_connected();
- if(conn) break;
- DPRINTK("> schedule_timeout...\n");
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(10);
- }
-
- DPRINTK("> wait finished...\n");
- if (conn <= 0) {
- err = netctrl_err(-ENETDOWN);
- WPRINTK("Failed to connect all virtual interfaces: err=%d\n", err);
- }
-
- DPRINTK("< err=%d\n", err);
-
- return err;
-}
-#else
-/* Probe for interfaces until no more are found.
- *
- * This is the mode we'd like to use, but at the moment it panics the kernel.
-*/
-static int probe_interfaces(void)
-{
- int err = 0;
- int wait_i, wait_n = 100;
- ctrl_msg_t cmsg = {
- .type = CMSG_NETIF_FE,
- .subtype = CMSG_NETIF_FE_INTERFACE_STATUS,
- .length = sizeof(netif_fe_interface_status_t),
- };
- netif_fe_interface_status_t msg = {};
- ctrl_msg_t rmsg = {};
- netif_fe_interface_status_t *reply = (void*)rmsg.msg;
- int state = TASK_UNINTERRUPTIBLE;
- u32 query = -1;
-
- DPRINTK(">\n");
-
- netctrl.interface_n = 0;
- for (wait_i = 0; wait_i < wait_n; wait_i++) {
- DPRINTK("> wait_i=%d query=%d\n", wait_i, query);
- msg.handle = query;
- memcpy(cmsg.msg, &msg, sizeof(msg));
- DPRINTK("> set_current_state...\n");
- set_current_state(state);
- DPRINTK("> rmsg=%p msg=%p, reply=%p\n", &rmsg, rmsg.msg, reply);
- DPRINTK("> sending...\n");
- err = ctrl_if_send_message_and_get_response(&cmsg, &rmsg, state);
- DPRINTK("> err=%d\n", err);
- if(err) goto exit;
- DPRINTK("> rmsg=%p msg=%p, reply=%p\n", &rmsg, rmsg.msg, reply);
- if((int)reply->handle < 0) {
- // No more interfaces.
- break;
- }
- query = -reply->handle - 2;
- DPRINTK(">netif_interface_status ...\n");
- netif_interface_status(reply);
- }
-
- exit:
- if (err) {
- err = netctrl_err(-ENETDOWN);
- WPRINTK("Connecting virtual network interfaces failed: err=%d\n", err);
- }
-
- DPRINTK("< err=%d\n", err);
- return err;
-}
-
-#endif
+static int destroy_netdev(struct net_device *netdev)
+{
+ struct net_private *np = NULL;
+
+#ifdef CONFIG_PROC_FS
+ xennet_proc_delif(netdev);
+#endif
+
+ unregister_netdev(netdev);
+
+ np = netdev_priv(netdev);
+ list_del(&np->list);
+
+ kfree(netdev);
+
+ return 0;
+}
/*
* We use this notifier to send out a fake ARP reply to reset switches and
@@ -1387,19 +964,11 @@
{
struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
struct net_device *dev = ifa->ifa_dev->dev;
- struct list_head *ent;
- struct net_private *np;
-
- if (event != NETDEV_UP)
- goto out;
-
- list_for_each (ent, &dev_list) {
- np = list_entry(ent, struct net_private, list);
- if (np->dev == dev)
- (void)send_fake_arp(dev);
- }
+
+ /* UP event and is it one of our devices? */
+ if (event == NETDEV_UP && dev->open == network_open)
+ (void)send_fake_arp(dev);
- out:
return NOTIFY_DONE;
}
@@ -1409,67 +978,310 @@
.priority = 0
};
-static int __init netif_init(void)
-{
- int err = 0;
-
- if (xen_start_info.flags & SIF_INITDOMAIN)
- return 0;
+static struct xenbus_device_id netfront_ids[] = {
+ { "vif" },
+ { "" }
+};
+
+static void watch_for_status(struct xenbus_watch *watch, const char *node)
+{
+}
+
+static int setup_device(struct xenbus_device *dev, struct netfront_info *info)
+{
+ evtchn_op_t op = { .cmd = EVTCHNOP_alloc_unbound };
+ int err;
+
#ifdef CONFIG_XEN_NETDEV_GRANT_TX
- /* A grant for every ring slot */
- if (gnttab_alloc_grant_references(NETIF_TX_RING_SIZE,
- &gref_tx_head) < 0) {
- printk(KERN_ALERT "#### netfront can't alloc tx grant refs\n");
- return 1;
- }
- printk(KERN_ALERT "Netdev frontend (TX) is using grant tables.\n");
+ info->tx_ring_ref = GRANT_INVALID_REF;
#endif
#ifdef CONFIG_XEN_NETDEV_GRANT_RX
- /* A grant for every ring slot */
- if (gnttab_alloc_grant_references(NETIF_RX_RING_SIZE,
- &gref_rx_head) < 0) {
- printk(KERN_ALERT "#### netfront can't alloc rx grant refs\n");
- return 1;
- }
- printk(KERN_ALERT "Netdev frontend (RX) is using grant tables.\n");
-#endif
-
- if ((err = xennet_proc_init()) != 0)
- return err;
-
- IPRINTK("Initialising virtual ethernet driver.\n");
- INIT_LIST_HEAD(&dev_list);
- (void)register_inetaddr_notifier(¬ifier_inetdev);
- netctrl_init();
- (void)ctrl_if_register_receiver(CMSG_NETIF_FE, netif_ctrlif_rx,
- CALLBACK_IN_BLOCKING_CONTEXT);
- send_driver_status(1);
- err = probe_interfaces();
- if (err)
- ctrl_if_unregister_receiver(CMSG_NETIF_FE, netif_ctrlif_rx);
-
- DPRINTK("< err=%d\n", err);
- return err;
-}
-
-static void netif_exit(void)
-{
+ info->rx_ring_ref = GRANT_INVALID_REF;
+#endif
+
+ info->tx = (netif_tx_interface_t *)__get_free_page(GFP_KERNEL);
+ if (info->tx == 0) {
+ err = -ENOMEM;
+ xenbus_dev_error(dev, err, "allocating tx ring page");
+ goto out;
+ }
+ info->rx = (netif_rx_interface_t *)__get_free_page(GFP_KERNEL);
+ if (info->rx == 0) {
+ err = -ENOMEM;
+ xenbus_dev_error(dev, err, "allocating rx ring page");
+ goto out;
+ }
+ memset(info->tx, 0, PAGE_SIZE);
+ memset(info->rx, 0, PAGE_SIZE);
+ info->backend_state = BEST_DISCONNECTED;
+
#ifdef CONFIG_XEN_NETDEV_GRANT_TX
- gnttab_free_grant_references(gref_tx_head);
-#endif
+ err = gnttab_grant_foreign_access(info->backend_id,
+ virt_to_mfn(info->tx), 0);
+ if (err < 0) {
+ xenbus_dev_error(dev, err, "granting access to tx ring page");
+ goto out;
+ }
+ info->tx_ring_ref = err;
+#else
+ info->tx_ring_ref = virt_to_mfn(info->tx);
+#endif
+
#ifdef CONFIG_XEN_NETDEV_GRANT_RX
- gnttab_free_grant_references(gref_rx_head);
-#endif
-}
-
-static void vif_suspend(struct net_private *np)
-{
+ err = gnttab_grant_foreign_access(info->backend_id,
+ virt_to_mfn(info->rx), 0);
+ if (err < 0) {
+ xenbus_dev_error(dev, err, "granting access to rx ring page");
+ goto out;
+ }
+ info->rx_ring_ref = err;
+#else
+ info->rx_ring_ref = virt_to_mfn(info->rx);
+#endif
+
+ op.u.alloc_unbound.dom = info->backend_id;
+ err = HYPERVISOR_event_channel_op(&op);
+ if (err) {
+ xenbus_dev_error(dev, err, "allocating event channel");
+ goto out;
+ }
+ connect_device(info, op.u.alloc_unbound.port);
+ return 0;
+
+ out:
+ if (info->tx)
+ free_page((unsigned long)info->tx);
+ info->tx = 0;
+ if (info->rx)
+ free_page((unsigned long)info->rx);
+ info->rx = 0;
+#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+ if (info->tx_ring_ref != GRANT_INVALID_REF)
+ gnttab_end_foreign_access(info->tx_ring_ref, 0);
+ info->tx_ring_ref = GRANT_INVALID_REF;
+#endif
+#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+ if (info->rx_ring_ref != GRANT_INVALID_REF)
+ gnttab_end_foreign_access(info->rx_ring_ref, 0);
+ info->rx_ring_ref = GRANT_INVALID_REF;
+#endif
+ return err;
+}
+
+static void netif_free(struct netfront_info *info)
+{
+ if (info->tx)
+ free_page((unsigned long)info->tx);
+ info->tx = 0;
+ if (info->rx)
+ free_page((unsigned long)info->rx);
+ info->rx = 0;
+#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+ if (info->tx_ring_ref != GRANT_INVALID_REF)
+ gnttab_end_foreign_access(info->tx_ring_ref, 0);
+ info->tx_ring_ref = GRANT_INVALID_REF;
+#endif
+#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+ if (info->rx_ring_ref != GRANT_INVALID_REF)
+ gnttab_end_foreign_access(info->rx_ring_ref, 0);
+ info->rx_ring_ref = GRANT_INVALID_REF;
+#endif
+ unbind_evtchn_from_irqhandler(info->evtchn, info->netdev);
+ info->evtchn = 0;
+}
+
+/* Stop network device and free tx/rx queues and irq.
+ */
+static void shutdown_device(struct net_private *np)
+{
+ /* Stop old i/f to prevent errors whilst we rebuild the state. */
+ spin_lock_irq(&np->tx_lock);
+ spin_lock(&np->rx_lock);
+ netif_stop_queue(np->netdev);
+ /* np->backend_state = BEST_DISCONNECTED; */
+ spin_unlock(&np->rx_lock);
+ spin_unlock_irq(&np->tx_lock);
+
+ /* Free resources. */
+ netif_free(np);
+}
+
+/* Common code used when first setting up, and when resuming. */
+static int talk_to_backend(struct xenbus_device *dev,
+ struct netfront_info *info)
+{
+ char *backend, *mac, *e, *s;
+ const char *message;
+ int err, i;
+
+ backend = NULL;
+ err = xenbus_gather(dev->nodename,
+ "backend-id", "%i", &info->backend_id,
+ "backend", NULL, &backend,
+ NULL);
+ if (XENBUS_EXIST_ERR(err))
+ goto out;
+ if (backend && strlen(backend) == 0) {
+ err = -ENOENT;
+ goto out;
+ }
+ if (err < 0) {
+ xenbus_dev_error(dev, err, "reading %s/backend or backend-id",
+ dev->nodename);
+ goto out;
+ }
+
+ mac = xenbus_read(dev->nodename, "mac", NULL);
+ if (IS_ERR(mac)) {
+ err = PTR_ERR(mac);
+ xenbus_dev_error(dev, err, "reading %s/mac",
+ dev->nodename);
+ goto out;
+ }
+ s = mac;
+ for (i = 0; i < ETH_ALEN; i++) {
+ info->mac[i] = simple_strtoul(s, &e, 16);
+ if (s == e || (e[0] != ':' && e[0] != 0)) {
+ kfree(mac);
+ err = -ENOENT;
+ xenbus_dev_error(dev, err, "parsing %s/mac",
+ dev->nodename);
+ goto out;
+ }
+ s = &e[1];
+ }
+ kfree(mac);
+
+ /* Create shared ring, alloc event channel. */
+ err = setup_device(dev, info);
+ if (err) {
+ xenbus_dev_error(dev, err, "setting up ring");
+ goto out;
+ }
+
+ err = xenbus_transaction_start(dev->nodename);
+ if (err) {
+ xenbus_dev_error(dev, err, "starting transaction");
+ goto destroy_ring;
+ }
+
+ err = xenbus_printf(dev->nodename, "tx-ring-ref","%u",
+ info->tx_ring_ref);
+ if (err) {
+ message = "writing tx ring-ref";
+ goto abort_transaction;
+ }
+ err = xenbus_printf(dev->nodename, "rx-ring-ref","%u",
+ info->rx_ring_ref);
+ if (err) {
+ message = "writing rx ring-ref";
+ goto abort_transaction;
+ }
+ err = xenbus_printf(dev->nodename,
+ "event-channel", "%u", info->evtchn);
+ if (err) {
+ message = "writing event-channel";
+ goto abort_transaction;
+ }
+
+ info->backend = backend;
+ backend = NULL;
+
+ info->watch.node = info->backend;
+ info->watch.callback = watch_for_status;
+ err = register_xenbus_watch(&info->watch);
+ if (err) {
+ message = "registering watch on backend";
+ goto abort_transaction;
+ }
+
+ err = xenbus_transaction_end(0);
+ if (err) {
+ xenbus_dev_error(dev, err, "completing transaction");
+ goto destroy_ring;
+ }
+
+ netif_state = NETIF_STATE_CONNECTED;
+
+ out:
+ if (backend)
+ kfree(backend);
+ return err;
+
+ abort_transaction:
+ xenbus_transaction_end(1);
+ /* Have to do this *outside* transaction. */
+ xenbus_dev_error(dev, err, "%s", message);
+ destroy_ring:
+ shutdown_device(info);
+ goto out;
+}
+
+/* Setup supplies the backend dir, virtual device.
+
+ We place an event channel and shared frame entries.
+ We watch backend to wait if it's ok. */
+static int netfront_probe(struct xenbus_device *dev,
+ const struct xenbus_device_id *id)
+{
+ int err;
+ struct net_device *netdev;
+ struct netfront_info *info;
+ unsigned int handle;
+
+ err = xenbus_scanf(dev->nodename, "handle", "%u", &handle);
+ if (XENBUS_EXIST_ERR(err))
+ return err;
+ if (err < 0) {
+ xenbus_dev_error(dev, err, "reading handle");
+ return err;
+ }
+
+ err = create_netdev(handle, dev, &netdev);
+ if (err) {
+ xenbus_dev_error(dev, err, "creating netdev");
+ return err;
+ }
+
+ info = netdev_priv(netdev);
+ err = talk_to_backend(dev, info);
+ if (err) {
+ destroy_netdev(netdev);
+ return err;
+ }
+
+ /* Call once in case entries already there. */
+ watch_for_status(&info->watch, info->watch.node);
+
+ return 0;
+}
+
+static int netfront_remove(struct xenbus_device *dev)
+{
+ struct netfront_info *info = dev->data;
+
+ if (info->backend)
+ unregister_xenbus_watch(&info->watch);
+
+ netif_free(info);
+
+ kfree(info->backend);
+ kfree(info);
+
+ return 0;
+}
+
+static int netfront_suspend(struct xenbus_device *dev)
+{
+ struct net_private *np = dev->data;
/* Avoid having tx/rx stuff happen until we're ready. */
- unbind_evtchn_from_irqhandler(np->evtchn, np->dev);
-}
-
-static void vif_resume(struct net_private *np)
-{
+ unbind_evtchn_from_irqhandler(np->evtchn, np->netdev);
+ return 0;
+}
+
+static int netfront_resume(struct xenbus_device *dev)
+{
+ struct net_private *np = dev->data;
/*
* Connect regardless of whether IFF_UP flag set.
* Stop bad things from happening until we're back up.
@@ -1478,29 +1290,96 @@
memset(np->tx, 0, PAGE_SIZE);
memset(np->rx, 0, PAGE_SIZE);
- send_interface_connect(np);
-}
-
-void netif_suspend(void)
-{
- struct list_head *ent;
- struct net_private *np;
-
- list_for_each (ent, &dev_list) {
- np = list_entry(ent, struct net_private, list);
- vif_suspend(np);
- }
-}
-
-void netif_resume(void)
-{
- struct list_head *ent;
- struct net_private *np;
-
- list_for_each (ent, &dev_list) {
- np = list_entry(ent, struct net_private, list);
- vif_resume(np);
- }
+ // send_interface_connect(np);
+ return 0;
+}
+
+static struct xenbus_driver netfront = {
+ .name = "vif",
+ .owner = THIS_MODULE,
+ .ids = netfront_ids,
+ .probe = netfront_probe,
+ .remove = netfront_remove,
+ .resume = netfront_resume,
+ .suspend = netfront_suspend,
+};
+
+static void __init init_net_xenbus(void)
+{
+ xenbus_register_device(&netfront);
+}
+
+static int wait_for_netif(void)
+{
+ int err = 0;
+ int i;
+
+ /*
+ * We should figure out how many and which devices we need to
+ * proceed and only wait for those. For now, continue once the
+ * first device is around.
+ */
+ for ( i=0; netif_state != NETIF_STATE_CONNECTED && (i < 10*HZ); i++ )
+ {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
+ }
+
+ if (netif_state != NETIF_STATE_CONNECTED) {
+ WPRINTK("Timeout connecting to device!\n");
+ err = -ENOSYS;
+ }
+ return err;
+}
+
+static int __init netif_init(void)
+{
+ int err = 0;
+
+ if (xen_start_info.flags & SIF_INITDOMAIN)
+ return 0;
+
+#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+ /* A grant for every ring slot */
+ if (gnttab_alloc_grant_references(NETIF_TX_RING_SIZE,
+ &gref_tx_head) < 0) {
+ printk(KERN_ALERT "#### netfront can't alloc tx grant refs\n");
+ return 1;
+ }
+ printk(KERN_ALERT "Netdev frontend (TX) is using grant tables.\n");
+#endif
+#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+ /* A grant for every ring slot */
+ if (gnttab_alloc_grant_references(NETIF_RX_RING_SIZE,
+ &gref_rx_head) < 0) {
+ printk(KERN_ALERT "#### netfront can't alloc rx grant refs\n");
+ return 1;
+ }
+ printk(KERN_ALERT "Netdev frontend (RX) is using grant tables.\n");
+#endif
+
+ if ((err = xennet_proc_init()) != 0)
+ return err;
+
+ IPRINTK("Initialising virtual ethernet driver.\n");
+
+ (void)register_inetaddr_notifier(¬ifier_inetdev);
+
+ init_net_xenbus();
+
+ wait_for_netif();
+
+ return err;
+}
+
+static void netif_exit(void)
+{
+#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+ gnttab_free_grant_references(gref_tx_head);
+#endif
+#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+ gnttab_free_grant_references(gref_rx_head);
+#endif
}
#ifdef CONFIG_PROC_FS
diff -r e2025593f702 -r 112d44270733
linux-2.6-xen-sparse/include/asm-xen/asm-i386/page.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/page.h Wed Aug 24
23:16:52 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/page.h Thu Aug 25
18:18:47 2005
@@ -65,8 +65,26 @@
extern unsigned int *phys_to_machine_mapping;
#define pfn_to_mfn(pfn) \
((unsigned long)phys_to_machine_mapping[(unsigned int)(pfn)] & 0x7FFFFFFFUL)
-#define mfn_to_pfn(mfn) \
-((unsigned long)machine_to_phys_mapping[(unsigned int)(mfn)])
+static inline unsigned long mfn_to_pfn(unsigned long mfn)
+{
+ unsigned int pfn;
+
+ /*
+ * The array access can fail (e.g., device space beyond end of RAM).
+ * In such cases it doesn't matter what we return (we return garbage),
+ * but we must handle the fault without crashing!
+ */
+ asm (
+ "1: movl %1,%0\n"
+ "2:\n"
+ ".section __ex_table,\"a\"\n"
+ " .align 4\n"
+ " .long 1b,2b\n"
+ ".previous"
+ : "=r" (pfn) : "m" (machine_to_phys_mapping[mfn]) );
+
+ return (unsigned long)pfn;
+}
/* Definitions for machine and pseudophysical addresses. */
#ifdef CONFIG_X86_PAE
diff -r e2025593f702 -r 112d44270733
linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/page.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/page.h Wed Aug 24
23:16:52 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/page.h Thu Aug 25
18:18:47 2005
@@ -67,8 +67,26 @@
extern u32 *phys_to_machine_mapping;
#define pfn_to_mfn(pfn) \
((unsigned long)phys_to_machine_mapping[(unsigned int)(pfn)] & 0x7FFFFFFFUL)
-#define mfn_to_pfn(mfn) \
-((unsigned long)machine_to_phys_mapping[(unsigned int)(mfn)])
+static inline unsigned long mfn_to_pfn(unsigned long mfn)
+{
+ unsigned int pfn;
+
+ /*
+ * The array access can fail (e.g., device space beyond end of RAM).
+ * In such cases it doesn't matter what we return (we return garbage),
+ * but we must handle the fault without crashing!
+ */
+ asm (
+ "1: movl %1,%k0\n"
+ "2:\n"
+ ".section __ex_table,\"a\"\n"
+ " .align 8\n"
+ " .quad 1b,2b\n"
+ ".previous"
+ : "=r" (pfn) : "m" (machine_to_phys_mapping[mfn]) );
+
+ return (unsigned long)pfn;
+}
/* Definitions for machine and pseudophysical addresses. */
typedef unsigned long paddr_t;
diff -r e2025593f702 -r 112d44270733
linux-2.6-xen-sparse/include/asm-xen/gnttab.h
--- a/linux-2.6-xen-sparse/include/asm-xen/gnttab.h Wed Aug 24 23:16:52 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/gnttab.h Thu Aug 25 18:18:47 2005
@@ -30,10 +30,12 @@
int gnttab_grant_foreign_access(domid_t domid, unsigned long frame,
int readonly);
+void gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly);
void gnttab_end_foreign_access(grant_ref_t ref, int readonly);
int gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn);
+unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref);
unsigned long gnttab_end_foreign_transfer(grant_ref_t ref);
int gnttab_query_foreign_access(grant_ref_t ref);
diff -r e2025593f702 -r 112d44270733 tools/blktap/blktaplib.h
--- a/tools/blktap/blktaplib.h Wed Aug 24 23:16:52 2005
+++ b/tools/blktap/blktaplib.h Thu Aug 25 18:18:47 2005
@@ -7,7 +7,7 @@
#ifndef __BLKTAPLIB_H__
#define __BLKTAPLIB_H__
-#include <xc.h>
+#include <xenctrl.h>
#include <sys/user.h>
#include <xen/xen.h>
#include <xen/io/blkif.h>
diff -r e2025593f702 -r 112d44270733 tools/blktap/parallax/block-async.h
--- a/tools/blktap/parallax/block-async.h Wed Aug 24 23:16:52 2005
+++ b/tools/blktap/parallax/block-async.h Thu Aug 25 18:18:47 2005
@@ -7,7 +7,7 @@
#define _BLOCKASYNC_H_
#include <assert.h>
-#include <xc.h>
+#include <xenctrl.h>
#include "vdi.h"
struct io_ret
diff -r e2025593f702 -r 112d44270733 tools/blktap/parallax/blockstore.h
--- a/tools/blktap/parallax/blockstore.h Wed Aug 24 23:16:52 2005
+++ b/tools/blktap/parallax/blockstore.h Thu Aug 25 18:18:47 2005
@@ -10,7 +10,7 @@
#define __BLOCKSTORE_H__
#include <netinet/in.h>
-#include <xc.h>
+#include <xenctrl.h>
#define BLOCK_SIZE 4096
#define BLOCK_SHIFT 12
diff -r e2025593f702 -r 112d44270733 tools/console/Makefile
--- a/tools/console/Makefile Wed Aug 24 23:16:52 2005
+++ b/tools/console/Makefile Thu Aug 25 18:18:47 2005
@@ -26,11 +26,11 @@
xenconsoled: $(patsubst %.c,%.o,$(wildcard daemon/*.c))
$(CC) $(CFLAGS) $^ -o $@ -L$(XEN_LIBXC) -L$(XEN_XENSTORE) \
- -lxc -lxenstore
+ -lxenctrl -lxenstore
xenconsole: $(patsubst %.c,%.o,$(wildcard client/*.c))
$(CC) $(CFLAGS) $^ -o $@ -L$(XEN_LIBXC) -L$(XEN_XENSTORE) \
- -lxc -lxenstore
+ -lxenctrl -lxenstore
install: $(BIN)
$(INSTALL_DIR) -p $(DESTDIR)/$(DAEMON_INSTALL_DIR)
d |