mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
Merge.
This commit is contained in:
commit
4ef0b38ac3
99 files changed
+2096
-1845
No files matched your search
@@ -80,17 +80,43 @@ static __inline__ int HYPERVISOR_set_trap_table(trap_info_t *table)
|
||||
|
||||
static __inline__ int HYPERVISOR_mmu_update(mmu_update_t *req,
|
||||
int count,
|
||||
int *success_count)
|
||||
int *success_count,
|
||||
domid_t domid)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign1, ign2, ign3, ign4;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_mmu_update),
|
||||
_a1 (req), _a2 (count), _a3 (success_count) : "memory" );
|
||||
: "=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)
|
||||
{
|
||||
int ret;
|
||||
|
||||
+30
-10
@@ -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 @@ extern unsigned long *phys_to_machine_mapping;
|
||||
#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 @@ static __inline__ unsigned long machine_to_phys(unsigned long machine)
|
||||
#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_ */
|
||||
@@ -133,7 +133,7 @@ void start_kernel(start_info_t *si)
|
||||
for ( ; ; )
|
||||
{
|
||||
// HYPERVISOR_yield();
|
||||
block(1);
|
||||
block(100);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
+258
-78
@@ -5,9 +5,9 @@
|
||||
*
|
||||
* File: mm.c
|
||||
* Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
|
||||
* 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
|
||||
@@ -214,6 +146,59 @@ static chunk_head_t free_tail[FREELIST_SIZE];
|
||||
#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
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Initialise allocator, placing addresses [@min,@max] in free pool.
|
||||
@@ -328,3 +313,198 @@ unsigned long alloc_pages(int order)
|
||||
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");
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -131,15 +131,7 @@ static void map_cpu_to_logical_apicid(void);
|
||||
*/
|
||||
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 @@ static int __init do_boot_cpu(int apicid)
|
||||
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,
|
||||
|
||||
@@ -871,6 +871,7 @@ fastcall void do_simd_coprocessor_error(struct pt_regs * regs,
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_XEN
|
||||
fastcall void setup_x86_bogus_stack(unsigned char * stk)
|
||||
{
|
||||
unsigned long *switch16_ptr, *switch32_ptr;
|
||||
@@ -915,6 +916,7 @@ fastcall unsigned char * fixup_x86_bogus_stack(unsigned short sp)
|
||||
memcpy(stack32, stack16, len);
|
||||
return stack32;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 'math_state_restore()' saves the current math information in the
|
||||
|
||||
@@ -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 @@ gnttab_query_foreign_access(grant_ref_t ref)
|
||||
}
|
||||
|
||||
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 @@ gnttab_end_foreign_access(grant_ref_t ref, int readonly)
|
||||
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 @@ gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid,
|
||||
}
|
||||
|
||||
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 @@ gnttab_end_foreign_transfer(grant_ref_t ref)
|
||||
while ( unlikely((frame = shared[ref].frame) == 0) )
|
||||
cpu_relax();
|
||||
|
||||
put_free_entry(ref);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -129,14 +129,6 @@ static int __do_suspend(void *ignore)
|
||||
/* 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();
|
||||
#else
|
||||
@@ -218,8 +210,6 @@ static int __do_suspend(void *ignore)
|
||||
kmem_cache_shrink(pgd_cache);
|
||||
#endif
|
||||
|
||||
netif_suspend();
|
||||
|
||||
time_suspend();
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
@@ -277,8 +267,6 @@ static int __do_suspend(void *ignore)
|
||||
|
||||
time_resume();
|
||||
|
||||
netif_resume();
|
||||
|
||||
usbif_resume();
|
||||
|
||||
for_each_cpu_mask(i, prev_present_cpus) {
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include <asm/io.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
#ifndef CONFIG_XEN
|
||||
|
||||
/* Simple VGA output */
|
||||
|
||||
#ifdef __i386__
|
||||
@@ -59,7 +61,6 @@ static struct console early_vga_console = {
|
||||
.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 @@ static __init void early_serial_init(char *s)
|
||||
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 @@ early_serial_write(struct console *con, const char *s, unsigned count)
|
||||
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 = {
|
||||
|
||||
@@ -206,11 +206,13 @@ ENTRY(cpu_gdt_table)
|
||||
.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)
|
||||
|
||||
@@ -536,48 +536,7 @@ static inline void copy_edd(void)
|
||||
}
|
||||
#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 @@ void __init setup_arch(char **cmdline_p)
|
||||
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;
|
||||
@@ -744,9 +702,6 @@ void __init setup_arch(char **cmdline_p)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_SMP
|
||||
smp_alloc_memory();
|
||||
#endif
|
||||
#else /* CONFIG_XEN */
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
if (LOADER_TYPE && INITRD_START) {
|
||||
|
||||
@@ -286,10 +286,10 @@ void __init cpu_init (void)
|
||||
|
||||
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
|
||||
|
||||
/*
|
||||
|
||||
@@ -739,8 +739,8 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid)
|
||||
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 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid)
|
||||
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) {
|
||||
/*
|
||||
|
||||
@@ -536,70 +536,38 @@ static void __init find_early_table_space(unsigned long end)
|
||||
round_up(ptes * 8, PAGE_SIZE);
|
||||
}
|
||||
|
||||
static void xen_copy_pt(void)
|
||||
{
|
||||
unsigned long va = __START_KERNEL_map;
|
||||
unsigned long addr, *pte_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)];
|
||||
addr_to_page(addr, page);
|
||||
|
||||
pud = (pud_t *) &page[pud_index(va)];
|
||||
addr = page[pud_index(va)];
|
||||
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;
|
||||
}
|
||||
|
||||
init_level4_pgt[pgd_index(__START_KERNEL_map)] =
|
||||
mk_kernel_pgd(__pa_symbol(level3_kernel_pgt));
|
||||
}
|
||||
|
||||
void __init xen_init_pt(void)
|
||||
{
|
||||
unsigned long addr, *page;
|
||||
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 *)init_level4_pgt, 0, PAGE_SIZE);
|
||||
memset((void *)level3_kernel_pgt, 0, PAGE_SIZE);
|
||||
memset((void *)level2_kernel_pgt, 0, PAGE_SIZE);
|
||||
|
||||
xen_copy_pt();
|
||||
/* 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);
|
||||
addr = page[pud_index(__START_KERNEL_map)];
|
||||
addr_to_page(addr, page);
|
||||
|
||||
/* 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));
|
||||
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(level3_kernel_pgt);
|
||||
make_page_readonly(level2_kernel_pgt);
|
||||
make_page_readonly(init_level4_user_pgt);
|
||||
make_page_readonly(level3_user_pgt); /* for vsyscall stuff */
|
||||
make_page_readonly(level3_kernel_pgt);
|
||||
make_page_readonly(level3_user_pgt);
|
||||
make_page_readonly(level2_kernel_pgt);
|
||||
|
||||
xen_pgd_pin(__pa_symbol(init_level4_pgt));
|
||||
xen_pgd_pin(__pa_symbol(init_level4_user_pgt));
|
||||
@@ -609,7 +577,6 @@ void __init xen_init_pt(void)
|
||||
|
||||
set_pgd((pgd_t *)(init_level4_user_pgt + 511),
|
||||
mk_kernel_pgd(__pa_symbol(level3_user_pgt)));
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -617,69 +584,58 @@ void __init xen_init_pt(void)
|
||||
* 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)) {
|
||||
/*
|
||||
* 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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
for (; va < __START_KERNEL_map + current_size + tables_space; ) {
|
||||
while (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);
|
||||
}
|
||||
|
||||
|
||||
@@ -720,10 +676,6 @@ void __init init_memory_mapping(unsigned long start, unsigned long end)
|
||||
|
||||
start_pfn = ((current_size + extended_size) >> PAGE_SHIFT);
|
||||
|
||||
/*
|
||||
* TBD: Need to calculate at runtime
|
||||
*/
|
||||
|
||||
__flush_tlb_all();
|
||||
init_mapping_done = 1;
|
||||
}
|
||||
|
||||
@@ -57,26 +57,26 @@ static int blkback_remove(struct xenbus_device *dev)
|
||||
/* 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)
|
||||
if (be->blkif == NULL || be->blkif->status == CONNECTED)
|
||||
return;
|
||||
|
||||
err = xenbus_gather(be->frontpath, "grant-id", "%lu", &sharedmfn,
|
||||
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 @@ static void frontend_changed(struct xenbus_watch *watch, const char *node)
|
||||
}
|
||||
|
||||
/* Map the shared frame, irq etc. */
|
||||
err = blkif_map(be->blkif, sharedmfn, evtchn);
|
||||
err = blkif_map(be->blkif, ring_ref, evtchn);
|
||||
if (err) {
|
||||
xenbus_dev_error(be->dev, err,
|
||||
"mapping shared-frame %lu port %u",
|
||||
sharedmfn, evtchn);
|
||||
xenbus_dev_error(be->dev, err, "mapping ring-ref %lu port %u",
|
||||
ring_ref, evtchn);
|
||||
goto abort;
|
||||
}
|
||||
|
||||
@@ -139,62 +138,22 @@ static void backend_changed(struct xenbus_watch *watch, const char *node)
|
||||
{
|
||||
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;
|
||||
|
||||
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 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;
|
||||
return;
|
||||
if (err < 0) {
|
||||
xenbus_dev_error(dev, err, "reading physical-device");
|
||||
goto device_fail;
|
||||
return;
|
||||
}
|
||||
if (be->pdev && be->pdev != pdev) {
|
||||
printk(KERN_WARNING
|
||||
"changing physical-device not supported\n");
|
||||
goto device_fail;
|
||||
return;
|
||||
}
|
||||
be->pdev = pdev;
|
||||
|
||||
@@ -215,32 +174,25 @@ static void backend_changed(struct xenbus_watch *watch, const char *node)
|
||||
err = PTR_ERR(be->blkif);
|
||||
be->blkif = NULL;
|
||||
xenbus_dev_error(dev, err, "creating block interface");
|
||||
goto device_fail;
|
||||
return;
|
||||
}
|
||||
|
||||
err = vbd_create(be->blkif, handle, be->pdev, be->readonly);
|
||||
if (err) {
|
||||
xenbus_dev_error(dev, err, "creating vbd structure");
|
||||
goto device_fail;
|
||||
return;
|
||||
}
|
||||
|
||||
frontend_changed(&be->watch, be->frontpath);
|
||||
/* Pass in NULL node to skip exist test. */
|
||||
frontend_changed(&be->watch, NULL);
|
||||
}
|
||||
|
||||
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;
|
||||
char *frontend;
|
||||
int err;
|
||||
|
||||
be = kmalloc(sizeof(*be), GFP_KERNEL);
|
||||
@@ -248,24 +200,63 @@ static int blkback_probe(struct xenbus_device *dev,
|
||||
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))
|
||||
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.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1084,7 +1084,8 @@ static void watch_for_status(struct xenbus_watch *watch, const char *node)
|
||||
"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 @@ static int setup_blkring(struct xenbus_device *dev, struct blkfront_info *info)
|
||||
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 @@ static int talk_to_backend(struct xenbus_device *dev,
|
||||
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,
|
||||
|
||||
@@ -112,7 +112,7 @@ struct blkfront_info
|
||||
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;
|
||||
|
||||
@@ -240,7 +240,11 @@ console_initcall(xen_console_init);
|
||||
#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;
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
|
||||
obj-y := netback.o control.o interface.o loopback.o
|
||||
obj-y := netback.o xenbus.o interface.o loopback.o
|
||||
@@ -59,6 +59,7 @@ typedef struct netif_st {
|
||||
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 @@ typedef struct netif_st {
|
||||
/* 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);
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
/******************************************************************************
|
||||
* arch/xen/drivers/netif/backend/control.c
|
||||
*
|
||||
* Routines for interfacing with the control plane.
|
||||
*
|
||||
* Copyright (c) 2004, Keir Fraser
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
static void netif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
|
||||
{
|
||||
DPRINTK("Received netif backend message, subtype=%d\n", msg->subtype);
|
||||
|
||||
switch ( msg->subtype )
|
||||
{
|
||||
case CMSG_NETIF_BE_CREATE:
|
||||
netif_create((netif_be_create_t *)&msg->msg[0]);
|
||||
break;
|
||||
case CMSG_NETIF_BE_DESTROY:
|
||||
netif_destroy((netif_be_destroy_t *)&msg->msg[0]);
|
||||
break;
|
||||
case CMSG_NETIF_BE_CREDITLIMIT:
|
||||
netif_creditlimit((netif_be_creditlimit_t *)&msg->msg[0]);
|
||||
break;
|
||||
case CMSG_NETIF_BE_CONNECT:
|
||||
netif_connect((netif_be_connect_t *)&msg->msg[0]);
|
||||
break;
|
||||
case CMSG_NETIF_BE_DISCONNECT:
|
||||
if ( !netif_disconnect((netif_be_disconnect_t *)&msg->msg[0],msg->id) )
|
||||
return; /* Sending the response is deferred until later. */
|
||||
break;
|
||||
default:
|
||||
DPRINTK("Parse error while reading message subtype %d, len %d\n",
|
||||
msg->subtype, msg->length);
|
||||
msg->length = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
ctrl_if_send_response(msg);
|
||||
}
|
||||
|
||||
void netif_ctrlif_init(void)
|
||||
{
|
||||
ctrl_msg_t cmsg;
|
||||
netif_be_driver_status_t st;
|
||||
|
||||
(void)ctrl_if_register_receiver(CMSG_NETIF_BE, netif_ctrlif_rx,
|
||||
CALLBACK_IN_BLOCKING_CONTEXT);
|
||||
|
||||
/* Send a driver-UP notification to the domain controller. */
|
||||
cmsg.type = CMSG_NETIF_BE;
|
||||
cmsg.subtype = CMSG_NETIF_BE_DRIVER_STATUS;
|
||||
cmsg.length = sizeof(netif_be_driver_status_t);
|
||||
st.status = NETIF_DRIVER_STATUS_UP;
|
||||
memcpy(cmsg.msg, &st, sizeof(st));
|
||||
ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
|
||||
}
|
||||
@@ -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 void __netif_down(netif_t *netif)
|
||||
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 @@ static int net_close(struct net_device *dev)
|
||||
{
|
||||
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 *alloc_netif(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN])
|
||||
{
|
||||
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;
|
||||
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 @@ void netif_create(netif_be_create_t *create)
|
||||
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 @@ void netif_create(netif_be_create_t *create)
|
||||
/* 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,225 +94,144 @@ void netif_create(netif_be_create_t *create)
|
||||
*/
|
||||
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;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
netif->hash_next = *pnetif;
|
||||
*pnetif = netif;
|
||||
|
||||
DPRINTK("Successfully created netif\n");
|
||||
create->status = NETIF_BE_STATUS_OKAY;
|
||||
return netif;
|
||||
}
|
||||
|
||||
void netif_destroy(netif_be_destroy_t *destroy)
|
||||
static int map_frontend_page(netif_t *netif, unsigned long localaddr,
|
||||
unsigned long tx_ring_ref, unsigned long rx_ring_ref)
|
||||
{
|
||||
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 )
|
||||
{
|
||||
if ( (netif->domid == domid) && (netif->handle == handle) )
|
||||
{
|
||||
if ( netif->status != DISCONNECTED )
|
||||
goto still_connected;
|
||||
goto destroy;
|
||||
}
|
||||
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;
|
||||
unregister_netdev(netif->dev);
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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 )
|
||||
{
|
||||
/*
|
||||
* Schedule work so that any packets waiting under previous credit
|
||||
* limit are dealt with (acts like a replenishment point).
|
||||
*/
|
||||
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;
|
||||
int err;
|
||||
#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.host_addr = localaddr;
|
||||
op.flags = GNTMAP_host_map;
|
||||
op.ref = tx_ref;
|
||||
op.dom = domid;
|
||||
op.ref = tx_ring_ref;
|
||||
op.dom = netif->domid;
|
||||
|
||||
if ((HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) < 0) ||
|
||||
(op.handle < 0)) {
|
||||
BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) );
|
||||
if (op.handle < 0) {
|
||||
DPRINTK(" Grant table operation failure !\n");
|
||||
connect->status = NETIF_BE_STATUS_MAPPING_ERROR;
|
||||
vfree(vma->addr);
|
||||
return;
|
||||
return op.handle;
|
||||
}
|
||||
|
||||
netif->tx_shmem_ref = tx_ref;
|
||||
netif->tx_shmem_ref = tx_ring_ref;
|
||||
netif->tx_shmem_handle = op.handle;
|
||||
netif->tx_shmem_vaddr = VMALLOC_VMADDR(vma->addr);
|
||||
netif->tx_shmem_vaddr = localaddr;
|
||||
}
|
||||
|
||||
|
||||
#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;
|
||||
}
|
||||
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;
|
||||
int rx_ref = connect->rx_shmem_ref;
|
||||
|
||||
|
||||
/* Map: Use the Grant table reference */
|
||||
op.host_addr = VMALLOC_VMADDR(vma->addr) + PAGE_SIZE;
|
||||
op.host_addr = localaddr + PAGE_SIZE;
|
||||
op.flags = GNTMAP_host_map;
|
||||
op.ref = rx_ref;
|
||||
op.dom = domid;
|
||||
op.ref = rx_ring_ref;
|
||||
op.dom = netif->domid;
|
||||
|
||||
if ((HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) < 0) ||
|
||||
(op.handle < 0)) {
|
||||
BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) );
|
||||
if (op.handle < 0) {
|
||||
DPRINTK(" Grant table operation failure !\n");
|
||||
connect->status = NETIF_BE_STATUS_MAPPING_ERROR;
|
||||
vfree(vma->addr);
|
||||
return;
|
||||
return op.handle;
|
||||
}
|
||||
|
||||
netif->rx_shmem_ref = rx_ref;
|
||||
netif->rx_shmem_handle = handle;
|
||||
netif->rx_shmem_vaddr = VMALLOC_VMADDR(vma->addr) + PAGE_SIZE;
|
||||
netif->rx_shmem_ref = rx_ring_ref;
|
||||
netif->rx_shmem_handle = op.handle;
|
||||
netif->rx_shmem_vaddr = localaddr + 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;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
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);
|
||||
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. */
|
||||
@@ -420,46 +239,78 @@ void netif_connect(netif_be_connect_t *connect)
|
||||
rtnl_lock();
|
||||
netif->status = CONNECTED;
|
||||
wmb();
|
||||
if ( netif_running(netif->dev) )
|
||||
if (netif_running(netif->dev))
|
||||
__netif_up(netif);
|
||||
rtnl_unlock();
|
||||
|
||||
connect->status = NETIF_BE_STATUS_OKAY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int netif_disconnect(netif_be_disconnect_t *disconnect, u8 rsp_id)
|
||||
static void free_netif(void *arg)
|
||||
{
|
||||
domid_t domid = disconnect->domid;
|
||||
unsigned int handle = disconnect->netif_handle;
|
||||
netif_t *netif;
|
||||
evtchn_op_t op = { .cmd = EVTCHNOP_close };
|
||||
netif_t *netif = (netif_t *)arg;
|
||||
|
||||
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. */
|
||||
/*
|
||||
* 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. */
|
||||
}
|
||||
|
||||
if ( netif->status == CONNECTED )
|
||||
{
|
||||
free_netdev(netif->dev);
|
||||
}
|
||||
|
||||
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) {
|
||||
/*
|
||||
* Schedule work so that any packets waiting under previous credit
|
||||
* limit are dealt with (acts like a replenishment point).
|
||||
*/
|
||||
netif->credit_timeout.expires = jiffies;
|
||||
netif_schedule_work(netif);
|
||||
}
|
||||
#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));
|
||||
}
|
||||
@@ -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 void maybe_schedule_tx_action(void)
|
||||
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 @@ static void net_tx_action(unsigned long unused)
|
||||
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 @@ static int __init netback_init(void)
|
||||
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 @@ static int __init netback_init(void)
|
||||
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,
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
/* Xenbus code for netif backend
|
||||
Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <linux/module.h>
|
||||
#include <asm-xen/xenbus.h>
|
||||
#include "common.h"
|
||||
|
||||
struct backend_info
|
||||
{
|
||||
struct xenbus_device *dev;
|
||||
|
||||
/* our communications channel */
|
||||
netif_t *netif;
|
||||
|
||||
long int frontend_id;
|
||||
#if 0
|
||||
long int pdev;
|
||||
long int readonly;
|
||||
#endif
|
||||
|
||||
/* watch back end for changes */
|
||||
struct xenbus_watch backend_watch;
|
||||
|
||||
/* watch front end for changes */
|
||||
struct xenbus_watch watch;
|
||||
char *frontpath;
|
||||
};
|
||||
|
||||
static int netback_remove(struct xenbus_device *dev)
|
||||
{
|
||||
struct backend_info *be = dev->data;
|
||||
|
||||
if (be->watch.node)
|
||||
unregister_xenbus_watch(&be->watch);
|
||||
unregister_xenbus_watch(&be->backend_watch);
|
||||
if (be->netif)
|
||||
netif_disconnect(be->netif);
|
||||
if (be->frontpath)
|
||||
kfree(be->frontpath);
|
||||
kfree(be);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Front end tells us frame. */
|
||||
static void frontend_changed(struct xenbus_watch *watch, const char *node)
|
||||
{
|
||||
unsigned long tx_ring_ref, rx_ring_ref;
|
||||
unsigned int evtchn;
|
||||
int err;
|
||||
struct backend_info *be
|
||||
= container_of(watch, struct backend_info, watch);
|
||||
char *mac, *e, *s;
|
||||
int i;
|
||||
|
||||
/* If other end is gone, delete ourself. */
|
||||
if (node && !xenbus_exists(be->frontpath, "")) {
|
||||
xenbus_rm(be->dev->nodename, "");
|
||||
device_unregister(&be->dev->dev);
|
||||
return;
|
||||
}
|
||||
if (be->netif == NULL || be->netif->status == CONNECTED)
|
||||
return;
|
||||
|
||||
mac = xenbus_read(be->frontpath, "mac", NULL);
|
||||
if (IS_ERR(mac)) {
|
||||
err = PTR_ERR(mac);
|
||||
xenbus_dev_error(be->dev, err, "reading %s/mac",
|
||||
be->dev->nodename);
|
||||
return;
|
||||
}
|
||||
s = mac;
|
||||
for (i = 0; i < ETH_ALEN; i++) {
|
||||
be->netif->fe_dev_addr[i] = simple_strtoul(s, &e, 16);
|
||||
if (s == e || (e[0] != ':' && e[0] != 0)) {
|
||||
kfree(mac);
|
||||
err = -ENOENT;
|
||||
xenbus_dev_error(be->dev, err, "parsing %s/mac",
|
||||
be->dev->nodename);
|
||||
return;
|
||||
}
|
||||
s = &e[1];
|
||||
}
|
||||
kfree(mac);
|
||||
|
||||
err = xenbus_gather(be->frontpath, "tx-ring-ref", "%lu", &tx_ring_ref,
|
||||
"rx-ring-ref", "%lu", &rx_ring_ref,
|
||||
"event-channel", "%u", &evtchn, NULL);
|
||||
if (err) {
|
||||
xenbus_dev_error(be->dev, err,
|
||||
"reading %s/ring-ref and event-channel",
|
||||
be->frontpath);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Map the shared frame, irq etc. */
|
||||
err = netif_map(be->netif, tx_ring_ref, rx_ring_ref, evtchn);
|
||||
if (err) {
|
||||
xenbus_dev_error(be->dev, err,
|
||||
"mapping shared-frames %lu/%lu port %u",
|
||||
tx_ring_ref, rx_ring_ref, evtchn);
|
||||
return;
|
||||
}
|
||||
|
||||
xenbus_dev_ok(be->dev);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Setup supplies physical device.
|
||||
We provide event channel and device details to front end.
|
||||
Frontend supplies shared frame and event channel.
|
||||
*/
|
||||
static void backend_changed(struct xenbus_watch *watch, const char *node)
|
||||
{
|
||||
int err;
|
||||
long int handle;
|
||||
struct backend_info *be
|
||||
= container_of(watch, struct backend_info, backend_watch);
|
||||
struct xenbus_device *dev = be->dev;
|
||||
u8 be_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
err = xenbus_scanf(dev->nodename, "handle", "%li", &handle);
|
||||
if (XENBUS_EXIST_ERR(err))
|
||||
return;
|
||||
if (err < 0) {
|
||||
xenbus_dev_error(dev, err, "reading handle");
|
||||
return;
|
||||
}
|
||||
|
||||
if (be->netif == NULL) {
|
||||
be->netif = alloc_netif(be->frontend_id, handle, be_mac);
|
||||
if (IS_ERR(be->netif)) {
|
||||
err = PTR_ERR(be->netif);
|
||||
be->netif = NULL;
|
||||
xenbus_dev_error(dev, err, "creating interface");
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
err = vbd_create(be->netif, handle, be->pdev, be->readonly);
|
||||
if (err) {
|
||||
xenbus_dev_error(dev, err, "creating vbd structure");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Pass in NULL node to skip exist test. */
|
||||
frontend_changed(&be->watch, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static int netback_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))
|
||||
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.
|
||||
*/
|
||||
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 0;
|
||||
|
||||
free_be:
|
||||
if (be->backend_watch.node)
|
||||
unregister_xenbus_watch(&be->backend_watch);
|
||||
if (frontend)
|
||||
kfree(frontend);
|
||||
kfree(be);
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct xenbus_device_id netback_ids[] = {
|
||||
{ "vif" },
|
||||
{ "" }
|
||||
};
|
||||
|
||||
static struct xenbus_driver netback = {
|
||||
.name = "vif",
|
||||
.owner = THIS_MODULE,
|
||||
.ids = netback_ids,
|
||||
.probe = netback_probe,
|
||||
.remove = netback_remove,
|
||||
};
|
||||
|
||||
void netif_xenbus_init(void)
|
||||
{
|
||||
xenbus_register_backend(&netback);
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -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
|
||||
|
||||
@@ -67,8 +67,26 @@ void copy_page(void *, void *);
|
||||
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;
|
||||
|
||||
@@ -30,10 +30,12 @@ struct gnttab_free_callback {
|
||||
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);
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
--- linux-2.6.12/net/bridge/br_if.c 2005-06-17 14:48:29.000000000 -0500
|
||||
+++ linux-2.6.12-xen0-smp/net/bridge/br_if.c 2005-08-18 15:17:27.302615846 -0500
|
||||
@@ -382,7 +382,7 @@
|
||||
{
|
||||
struct net_bridge_port *p = dev->br_port;
|
||||
|
||||
- if (!p || p->br != br)
|
||||
+ if (!p || p->br != br || p->state == BR_STATE_DISABLED)
|
||||
return -EINVAL;
|
||||
|
||||
br_sysfs_removeif(p);
|
||||
@@ -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>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#define _BLOCKASYNC_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include <xc.h>
|
||||
#include <xenctrl.h>
|
||||
#include "vdi.h"
|
||||
|
||||
struct io_ret
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -26,11 +26,11 @@ clean:
|
||||
|
||||
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)
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
#include <errno.h>
|
||||
#include <pty.h>
|
||||
|
||||
#include "xc.h"
|
||||
#include "xenctrl.h"
|
||||
#include "xs.h"
|
||||
|
||||
#define ESCAPE_CHARACTER 0x1d
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "utils.h"
|
||||
#include "io.h"
|
||||
|
||||
#include "xc.h"
|
||||
#include "xenctrl.h"
|
||||
#include "xs.h"
|
||||
#include "xen/io/domain_controller.h"
|
||||
#include "xcs_proto.h"
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "xc.h"
|
||||
#include "xenctrl.h"
|
||||
#include "xen/io/domain_controller.h"
|
||||
#include "xcs_proto.h"
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#include <sys/un.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "xc.h"
|
||||
#include "xenctrl.h"
|
||||
#include "xen/io/domain_controller.h"
|
||||
#include "xcs_proto.h"
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <xc.h>
|
||||
#include <xenctrl.h>
|
||||
#define TRACE_ENTER /* printf("enter %s\n", __FUNCTION__) */
|
||||
long (*myptrace)(enum __ptrace_request, pid_t, long, long);
|
||||
int (*myxcwait)(int domain, int *status, int options) ;
|
||||
|
||||
@@ -20,7 +20,7 @@ CFLAGS += $(INCLUDES) -I. -I$(XEN_ROOT)/tools/libxc
|
||||
CFLAGS += -Wp,-MD,.$(@F).d
|
||||
DEPS = .*.d
|
||||
|
||||
LDFLAGS += -L$(XEN_ROOT)/tools/libxc -lxc
|
||||
LDFLAGS += -L$(XEN_ROOT)/tools/libxc -lxenctrl
|
||||
|
||||
LIB_OBJS := $(patsubst %.c,%.o,$(SRCS))
|
||||
PIC_OBJS := $(patsubst %.c,%.opic,$(SRCS))
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
#include <xc.h>
|
||||
#include <xenctrl.h>
|
||||
#include "list.h"
|
||||
|
||||
#if defined(__i386__)
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#ifndef _XENDEBUG_H_DEFINED
|
||||
#define _XENDEBUG_H_DEFINED
|
||||
|
||||
#include <xc.h>
|
||||
#include <xenctrl.h>
|
||||
|
||||
int xendebug_attach(int xc_handle,
|
||||
u32 domid,
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* PDB's OCaml interface library for debugging domains
|
||||
*/
|
||||
|
||||
#include <xc.h>
|
||||
#include <xenctrl.h>
|
||||
#include <xendebug.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* PDB's OCaml interface library for event channels
|
||||
*/
|
||||
|
||||
#include <xc.h>
|
||||
#include <xenctrl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include <caml/memory.h>
|
||||
#include <caml/mlvalues.h>
|
||||
|
||||
#include <xc.h>
|
||||
#include <xenctrl.h>
|
||||
#include <xen/xen.h>
|
||||
#include <xen/io/domain_controller.h>
|
||||
#include <xen/linux/privcmd.h>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* PDB's OCaml interface library for debugging domains
|
||||
*/
|
||||
|
||||
#include <xc.h>
|
||||
#include <xenctrl.h>
|
||||
#include <xendebug.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
#include <xc.h>
|
||||
#include <xenctrl.h>
|
||||
|
||||
#include <xen/xen.h>
|
||||
#include <xen/io/domain_controller.h>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* PDB interface library for accessing Xen
|
||||
*/
|
||||
|
||||
#include <xc.h>
|
||||
#include <xenctrl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
+13
-1
@@ -24,10 +24,14 @@ XEN_SCRIPTS += block-enbd
|
||||
XEN_BOOT_DIR = /usr/lib/xen/boot
|
||||
XEN_BOOT = mem-map.sxp
|
||||
|
||||
XEN_HOTPLUG_DIR = /etc/hotplug.d/xen-backend
|
||||
XEN_HOTPLUG_SCRIPTS = backend.hotplug
|
||||
|
||||
all:
|
||||
build:
|
||||
|
||||
install: all install-initd install-configs install-scripts install-boot
|
||||
install: all install-initd install-configs install-scripts install-boot \
|
||||
install-hotplug
|
||||
|
||||
install-initd:
|
||||
[ -d $(DESTDIR)/etc/init.d ] || $(INSTALL_DIR) $(DESTDIR)/etc/init.d
|
||||
@@ -60,4 +64,12 @@ install-boot:
|
||||
$(INSTALL_PROG) $$i $(DESTDIR)$(XEN_BOOT_DIR); \
|
||||
done
|
||||
|
||||
install-hotplug:
|
||||
[ -d $(DESTDIR)$(XEN_HOTPLUG_DIR) ] || \
|
||||
$(INSTALL_DIR) $(DESTDIR)$(XEN_HOTPLUG_DIR)
|
||||
for i in $(XEN_HOTPLUG_SCRIPTS); \
|
||||
do [ -a $(DESTDIR)$(XEN_HOTPLUG_DIR)/$$i ] || \
|
||||
$(INSTALL_PROG) $$i $(DESTDIR)$(XEN_HOTPLUG_DIR); \
|
||||
done
|
||||
|
||||
clean:
|
||||
@@ -9,9 +9,20 @@ If you write a useful script and would like to share it, please do
|
||||
send it (preferably with a little summary to go in this file) to
|
||||
<xen-devel@lists.sourceforge.net> so we can add it to this directory.
|
||||
|
||||
block-enbd - binds/unbinds network block devices
|
||||
block-file - binds/unbinds file to loopback device
|
||||
mem-map.sxp - memory map xend configuration file.
|
||||
network - default network setup script called by xend at startup.
|
||||
network-route - default xen network start/stop script.
|
||||
network-nat - default xen network start/stop script when using NAT.
|
||||
vif-bridge - default virtual network interface setup script.
|
||||
vif-route - default xen virtual network start/stop script
|
||||
vif-nat - configures vif in routed-nat mode.
|
||||
xend-config.sxp - default xend configuration file.
|
||||
xmexample1 - example configuration script for 'xm create'.
|
||||
xmexample2 - a more complex configuration script for 'xm create'.
|
||||
xmexample3 - an advanced configuration script for 'xm create'
|
||||
that utilizes the vmid.
|
||||
xmexample.vmx - a configuration script for creating a vmx domain with
|
||||
'xm create'.
|
||||
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
#! /bin/sh
|
||||
|
||||
#DEVPATH=/devices/xen-backend/vif-1-0
|
||||
#ACTION=add
|
||||
|
||||
PATH=/etc/xen/scripts:$PATH
|
||||
|
||||
DEV=$(basename "$DEVPATH")
|
||||
case "$ACTION" in
|
||||
add)
|
||||
case "$DEV" in
|
||||
vif-*)
|
||||
vif=$(echo "$DEV" | sed 's/-\([0-9]*\)-\([0-9]*\)/\1.\2/')
|
||||
vif-bridge up domain=unknown vif="$vif" mac=fe:ff:ff:ff:ff:ff bridge=xen-br0 >/dev/null 2>&1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
remove)
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -74,8 +74,10 @@ if [ "${bridge}" == "null" ] ; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Add/remove vif to/from bridge.
|
||||
brctl ${brcmd} ${bridge} ${vif}
|
||||
# Add vif to bridge. vifs are auto-removed from bridge.
|
||||
if [ "${brcmd}" == "addif" ] ; then
|
||||
brctl ${brcmd} ${bridge} ${vif}
|
||||
fi
|
||||
ifconfig ${vif} $OP
|
||||
|
||||
if [ ${ip} ] ; then
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#ifndef _ACPI_2_0_H_
|
||||
#define _ACPI_2_0_H_
|
||||
|
||||
#include "xc.h" // for u8, u16, u32, u64 definition
|
||||
#include "xenctrl.h" // for u8, u16, u32, u64 definition
|
||||
|
||||
#pragma pack (1)
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "vl.h"
|
||||
#include "xc.h"
|
||||
#include "xenctrl.h"
|
||||
#include <io/ioreq.h>
|
||||
|
||||
//#define DEBUG_PIT
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "vl.h"
|
||||
#include "xc.h"
|
||||
#include "xenctrl.h"
|
||||
#include <io/ioreq.h>
|
||||
|
||||
/* debug PIC */
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#ifndef __IOAPIC_H
|
||||
#define __IOAPIC_H
|
||||
|
||||
#include "xc.h"
|
||||
#include "xenctrl.h"
|
||||
#include <io/ioreq.h>
|
||||
#include <io/vmx_vlapic.h>
|
||||
|
||||
|
||||
@@ -188,7 +188,7 @@ endif
|
||||
#########################################################
|
||||
|
||||
DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DAPIC_SUPPORT
|
||||
LIBS+=-lm -L../../libxc -lxc
|
||||
LIBS+=-lm -L../../libxc -lxenctrl
|
||||
ifndef CONFIG_USER_ONLY
|
||||
LIBS+=-lz
|
||||
endif
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "xc.h"
|
||||
#include "xenctrl.h"
|
||||
#include <io/ioreq.h>
|
||||
|
||||
#include "cpu.h"
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@
|
||||
#endif
|
||||
#endif /* CONFIG_SDL */
|
||||
|
||||
#include "xc.h"
|
||||
#include "xenctrl.h"
|
||||
#include "exec-all.h"
|
||||
|
||||
//#define DO_TB_FLUSH
|
||||
|
||||
+61
-33
@@ -12,28 +12,32 @@ CC = gcc
|
||||
XEN_ROOT = ../..
|
||||
include $(XEN_ROOT)/tools/Rules.mk
|
||||
|
||||
SRCS :=
|
||||
SRCS += xc_sedf.c
|
||||
SRCS += xc_bvtsched.c
|
||||
SRCS += xc_core.c
|
||||
SRCS += xc_domain.c
|
||||
SRCS += xc_evtchn.c
|
||||
SRCS += xc_gnttab.c
|
||||
SRCS += xc_load_bin.c
|
||||
SRCS += xc_load_elf.c
|
||||
SRCS += xc_linux_build.c
|
||||
SRCS += xc_misc.c
|
||||
SRCS += xc_physdev.c
|
||||
SRCS += xc_private.c
|
||||
SRCS :=
|
||||
BUILD_SRCS :=
|
||||
SRCS += xc_bvtsched.c
|
||||
SRCS += xc_core.c
|
||||
SRCS += xc_domain.c
|
||||
SRCS += xc_evtchn.c
|
||||
SRCS += xc_gnttab.c
|
||||
SRCS += xc_misc.c
|
||||
SRCS += xc_physdev.c
|
||||
SRCS += xc_private.c
|
||||
SRCS += xc_sedf.c
|
||||
|
||||
ifeq ($(XEN_TARGET_ARCH),ia64)
|
||||
SRCS += xc_ia64_stubs.c
|
||||
BUILD_SRCS += xc_ia64_stubs.c
|
||||
else
|
||||
SRCS += xc_load_aout9.c
|
||||
SRCS += xc_linux_restore.c
|
||||
SRCS += xc_linux_save.c
|
||||
SRCS += xc_vmx_build.c
|
||||
SRCS += xc_ptrace.c
|
||||
SRCS += xc_ptrace_core.c
|
||||
SRCS += xc_ptrace.c
|
||||
SRCS += xc_ptrace_core.c
|
||||
|
||||
BUILD_SRCS := xc_load_aout9.c
|
||||
BUILD_SRCS += xc_load_bin.c
|
||||
BUILD_SRCS += xc_load_elf.c
|
||||
BUILD_SRCS += xc_linux_build.c
|
||||
BUILD_SRCS += xc_linux_restore.c
|
||||
BUILD_SRCS += xc_linux_save.c
|
||||
BUILD_SRCS += xc_vmx_build.c
|
||||
BUILD_SRCS += xg_private.c
|
||||
endif
|
||||
|
||||
CFLAGS += -Wall
|
||||
@@ -43,13 +47,20 @@ CFLAGS += -fno-strict-aliasing
|
||||
CFLAGS += $(INCLUDES) -I.
|
||||
# Get gcc to generate the dependencies for us.
|
||||
CFLAGS += -Wp,-MD,.$(@F).d
|
||||
LDFLAGS += -L.
|
||||
DEPS = .*.d
|
||||
|
||||
LIB_OBJS := $(patsubst %.c,%.o,$(SRCS))
|
||||
PIC_OBJS := $(patsubst %.c,%.opic,$(SRCS))
|
||||
|
||||
LIB := libxc.a libxc-pic.a
|
||||
LIB += libxc.so libxc.so.$(MAJOR) libxc.so.$(MAJOR).$(MINOR)
|
||||
LIB_BUILD_OBJS := $(patsubst %.c,%.o,$(BUILD_SRCS))
|
||||
PIC_BUILD_OBJS := $(patsubst %.c,%.opic,$(BUILD_SRCS))
|
||||
|
||||
LIB := libxenctrl.a
|
||||
LIB += libxenctrl.so libxenctrl.so.$(MAJOR) libxenctrl.so.$(MAJOR).$(MINOR)
|
||||
|
||||
LIB += libxenguest.a
|
||||
LIB += libxenguest.so libxenguest.so.$(MAJOR) libxenguest.so.$(MAJOR).$(MINOR)
|
||||
|
||||
all: build
|
||||
build: check-for-zlib mk-symlinks
|
||||
@@ -77,11 +88,16 @@ mk-symlinks:
|
||||
install: build
|
||||
[ -d $(DESTDIR)/usr/$(LIBDIR) ] || $(INSTALL_DIR) $(DESTDIR)/usr/$(LIBDIR)
|
||||
[ -d $(DESTDIR)/usr/include ] || $(INSTALL_DIR) $(DESTDIR)/usr/include
|
||||
$(INSTALL_PROG) libxc.so.$(MAJOR).$(MINOR) $(DESTDIR)/usr/$(LIBDIR)
|
||||
$(INSTALL_DATA) libxc.a $(DESTDIR)/usr/$(LIBDIR)
|
||||
ln -sf libxc.so.$(MAJOR).$(MINOR) $(DESTDIR)/usr/$(LIBDIR)/libxc.so.$(MAJOR)
|
||||
ln -sf libxc.so.$(MAJOR) $(DESTDIR)/usr/$(LIBDIR)/libxc.so
|
||||
$(INSTALL_DATA) xc.h $(DESTDIR)/usr/include
|
||||
$(INSTALL_PROG) libxenctrl.so.$(MAJOR).$(MINOR) $(DESTDIR)/usr/$(LIBDIR)
|
||||
$(INSTALL_DATA) libxenctrl.a $(DESTDIR)/usr/$(LIBDIR)
|
||||
ln -sf libxenctrl.so.$(MAJOR).$(MINOR) $(DESTDIR)/usr/$(LIBDIR)/libxenctrl.so.$(MAJOR)
|
||||
ln -sf libxenctrl.so.$(MAJOR) $(DESTDIR)/usr/$(LIBDIR)/libxenctrl.so
|
||||
$(INSTALL_DATA) xenctrl.h $(DESTDIR)/usr/include
|
||||
|
||||
$(INSTALL_PROG) libxenguest.so.$(MAJOR).$(MINOR) $(DESTDIR)/usr/$(LIBDIR)
|
||||
$(INSTALL_DATA) libxenguest.a $(DESTDIR)/usr/$(LIBDIR)
|
||||
ln -sf libxenguest.so.$(MAJOR).$(MINOR) $(DESTDIR)/usr/$(LIBDIR)/libxenguest.so.$(MAJOR)
|
||||
ln -sf libxenguest.so.$(MAJOR) $(DESTDIR)/usr/$(LIBDIR)/libxenguest.so
|
||||
|
||||
.PHONY: TAGS clean rpm install all
|
||||
|
||||
@@ -100,18 +116,30 @@ rpm: build
|
||||
mv staging/i386/*.rpm .
|
||||
rm -rf staging
|
||||
|
||||
libxc.a: $(LIB_OBJS)
|
||||
# libxenctrl
|
||||
|
||||
libxenctrl.a: $(LIB_OBJS)
|
||||
$(AR) rc $@ $^
|
||||
|
||||
libxc-pic.a: $(PIC_OBJS)
|
||||
libxenctrl.so: libxenctrl.so.$(MAJOR)
|
||||
ln -sf $< $@
|
||||
libxenctrl.so.$(MAJOR): libxenctrl.so.$(MAJOR).$(MINOR)
|
||||
ln -sf $< $@
|
||||
|
||||
libxenctrl.so.$(MAJOR).$(MINOR): $(PIC_OBJS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-soname -Wl,libxenctrl.so.$(MAJOR) -shared -o $@ $^
|
||||
|
||||
# libxenguest
|
||||
|
||||
libxenguest.a: $(LIB_BUILD_OBJS)
|
||||
$(AR) rc $@ $^
|
||||
|
||||
libxc.so: libxc.so.$(MAJOR)
|
||||
libxenguest.so: libxenguest.so.$(MAJOR)
|
||||
ln -sf $< $@
|
||||
libxc.so.$(MAJOR): libxc.so.$(MAJOR).$(MINOR)
|
||||
libxenguest.so.$(MAJOR): libxenguest.so.$(MAJOR).$(MINOR)
|
||||
ln -sf $< $@
|
||||
|
||||
libxc.so.$(MAJOR).$(MINOR): $(PIC_OBJS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-soname -Wl,libxc.so.$(MAJOR) -shared -o $@ $^ -lz
|
||||
libxenguest.so.$(MAJOR).$(MINOR): $(PIC_BUILD_OBJS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-soname -Wl,libxenguest.so.$(MAJOR) -shared -o $@ $^ -lz -lxenctrl
|
||||
|
||||
-include $(DEPS)
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "xc_private.h"
|
||||
#include "xg_private.h"
|
||||
#define ELFSIZE 32
|
||||
#include "xc_elf.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -266,7 +266,7 @@ int xc_domain_memory_increase_reservation(int xc_handle,
|
||||
int err;
|
||||
unsigned int npages = mem_kb / (PAGE_SIZE/1024);
|
||||
|
||||
err = do_dom_mem_op(xc_handle, MEMOP_increase_reservation, NULL,
|
||||
err = xc_dom_mem_op(xc_handle, MEMOP_increase_reservation, NULL,
|
||||
npages, 0, domid);
|
||||
if (err == npages)
|
||||
return 0;
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
* xc_linux_build.c
|
||||
*/
|
||||
|
||||
#include "xc_private.h"
|
||||
#include "xg_private.h"
|
||||
#include <xenctrl.h>
|
||||
|
||||
#if defined(__i386__)
|
||||
#define ELFSIZE 32
|
||||
@@ -340,7 +341,7 @@ static int setup_guest(int xc_handle,
|
||||
unsigned long count, i;
|
||||
start_info_t *start_info;
|
||||
shared_info_t *shared_info;
|
||||
mmu_t *mmu = NULL;
|
||||
xc_mmu_t *mmu = NULL;
|
||||
int rc;
|
||||
|
||||
unsigned long nr_pt_pages;
|
||||
@@ -490,7 +491,7 @@ static int setup_guest(int xc_handle,
|
||||
}
|
||||
}
|
||||
|
||||
if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL )
|
||||
if ( (mmu = xc_init_mmu_updates(xc_handle, dom)) == NULL )
|
||||
goto error_out;
|
||||
|
||||
/* setup page tables */
|
||||
@@ -520,9 +521,9 @@ static int setup_guest(int xc_handle,
|
||||
page_array[physmap_pfn++]);
|
||||
for ( count = 0; count < nr_pages; count++ )
|
||||
{
|
||||
if ( add_mmu_update(xc_handle, mmu,
|
||||
(page_array[count] << PAGE_SHIFT) |
|
||||
MMU_MACHPHYS_UPDATE, count) )
|
||||
if ( xc_add_mmu_update(xc_handle, mmu,
|
||||
(page_array[count] << PAGE_SHIFT) |
|
||||
MMU_MACHPHYS_UPDATE, count) )
|
||||
{
|
||||
munmap(physmap, PAGE_SIZE);
|
||||
goto error_out;
|
||||
@@ -602,7 +603,7 @@ static int setup_guest(int xc_handle,
|
||||
munmap(shared_info, PAGE_SIZE);
|
||||
|
||||
/* Send the page update requests down to the hypervisor. */
|
||||
if ( finish_mmu_updates(xc_handle, mmu) )
|
||||
if ( xc_finish_mmu_updates(xc_handle, mmu) )
|
||||
goto error_out;
|
||||
|
||||
free(mmu);
|
||||
@@ -676,7 +677,7 @@ int xc_linux_build(int xc_handle,
|
||||
|
||||
op.cmd = DOM0_GETDOMAININFO;
|
||||
op.u.getdomaininfo.domain = (domid_t)domid;
|
||||
if ( (do_dom0_op(xc_handle, &op) < 0) ||
|
||||
if ( (xc_dom0_op(xc_handle, &op) < 0) ||
|
||||
((u16)op.u.getdomaininfo.domain != domid) )
|
||||
{
|
||||
PERROR("Could not get info on domain");
|
||||
@@ -793,7 +794,7 @@ int xc_linux_build(int xc_handle,
|
||||
launch_op.u.setdomaininfo.ctxt = ctxt;
|
||||
|
||||
launch_op.cmd = DOM0_SETDOMAININFO;
|
||||
rc = do_dom0_op(xc_handle, &launch_op);
|
||||
rc = xc_dom0_op(xc_handle, &launch_op);
|
||||
|
||||
return rc;
|
||||
|
||||
|
||||
@@ -6,7 +6,12 @@
|
||||
* Copyright (c) 2003, K A Fraser.
|
||||
*/
|
||||
|
||||
#include "xc_private.h"
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "xg_private.h"
|
||||
#include <xenctrl.h>
|
||||
|
||||
#include <xen/linux/suspend.h>
|
||||
|
||||
#define MAX_BATCH_SIZE 1024
|
||||
@@ -89,7 +94,7 @@ int xc_linux_restore(int xc_handle, int io_fd, u32 dom, unsigned long nr_pfns,
|
||||
|
||||
char *region_base;
|
||||
|
||||
mmu_t *mmu = NULL;
|
||||
xc_mmu_t *mmu = NULL;
|
||||
|
||||
/* used by debug verify code */
|
||||
unsigned long buf[PAGE_SIZE/sizeof(unsigned long)];
|
||||
@@ -132,7 +137,7 @@ int xc_linux_restore(int xc_handle, int io_fd, u32 dom, unsigned long nr_pfns,
|
||||
/* Get the domain's shared-info frame. */
|
||||
op.cmd = DOM0_GETDOMAININFO;
|
||||
op.u.getdomaininfo.domain = (domid_t)dom;
|
||||
if (do_dom0_op(xc_handle, &op) < 0) {
|
||||
if (xc_dom0_op(xc_handle, &op) < 0) {
|
||||
ERR("Could not get information on new domain");
|
||||
goto out;
|
||||
}
|
||||
@@ -158,7 +163,7 @@ int xc_linux_restore(int xc_handle, int io_fd, u32 dom, unsigned long nr_pfns,
|
||||
goto out;
|
||||
}
|
||||
|
||||
mmu = init_mmu_updates(xc_handle, dom);
|
||||
mmu = xc_init_mmu_updates(xc_handle, dom);
|
||||
if (mmu == NULL) {
|
||||
ERR("Could not initialise for MMU updates");
|
||||
goto out;
|
||||
@@ -355,8 +360,9 @@ int xc_linux_restore(int xc_handle, int io_fd, u32 dom, unsigned long nr_pfns,
|
||||
}
|
||||
}
|
||||
|
||||
if ( add_mmu_update(xc_handle, mmu,
|
||||
(mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, pfn) )
|
||||
if ( xc_add_mmu_update(xc_handle, mmu,
|
||||
(mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE,
|
||||
pfn) )
|
||||
{
|
||||
printf("machpys mfn=%ld pfn=%ld\n",mfn,pfn);
|
||||
goto out;
|
||||
@@ -370,7 +376,7 @@ int xc_linux_restore(int xc_handle, int io_fd, u32 dom, unsigned long nr_pfns,
|
||||
|
||||
DPRINTF("Received all pages\n");
|
||||
|
||||
if ( finish_mmu_updates(xc_handle, mmu) )
|
||||
if ( xc_finish_mmu_updates(xc_handle, mmu) )
|
||||
goto out;
|
||||
|
||||
/*
|
||||
@@ -388,14 +394,14 @@ int xc_linux_restore(int xc_handle, int io_fd, u32 dom, unsigned long nr_pfns,
|
||||
pin[nr_pins].mfn = pfn_to_mfn_table[i];
|
||||
if ( ++nr_pins == MAX_PIN_BATCH )
|
||||
{
|
||||
if ( do_mmuext_op(xc_handle, pin, nr_pins, dom) < 0 )
|
||||
if ( xc_mmuext_op(xc_handle, pin, nr_pins, dom) < 0 )
|
||||
goto out;
|
||||
nr_pins = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ( (nr_pins != 0) &&
|
||||
(do_mmuext_op(xc_handle, pin, nr_pins, dom) < 0) )
|
||||
(xc_mmuext_op(xc_handle, pin, nr_pins, dom) < 0) )
|
||||
goto out;
|
||||
|
||||
DPRINTF("\b\b\b\b100%%\n");
|
||||
@@ -435,7 +441,7 @@ int xc_linux_restore(int xc_handle, int io_fd, u32 dom, unsigned long nr_pfns,
|
||||
|
||||
if ( count > 0 )
|
||||
{
|
||||
if ( (rc = do_dom_mem_op( xc_handle,
|
||||
if ( (rc = xc_dom_mem_op( xc_handle,
|
||||
MEMOP_decrease_reservation,
|
||||
pfntab, count, 0, dom )) <0 )
|
||||
{
|
||||
@@ -586,7 +592,7 @@ int xc_linux_restore(int xc_handle, int io_fd, u32 dom, unsigned long nr_pfns,
|
||||
op.u.setdomaininfo.domain = (domid_t)dom;
|
||||
op.u.setdomaininfo.vcpu = 0;
|
||||
op.u.setdomaininfo.ctxt = &ctxt;
|
||||
rc = do_dom0_op(xc_handle, &op);
|
||||
rc = xc_dom0_op(xc_handle, &op);
|
||||
|
||||
if ( rc != 0 )
|
||||
{
|
||||
@@ -597,7 +603,7 @@ int xc_linux_restore(int xc_handle, int io_fd, u32 dom, unsigned long nr_pfns,
|
||||
DPRINTF("Domain ready to be unpaused\n");
|
||||
op.cmd = DOM0_UNPAUSEDOMAIN;
|
||||
op.u.unpausedomain.domain = (domid_t)dom;
|
||||
rc = do_dom0_op(xc_handle, &op);
|
||||
rc = xc_dom0_op(xc_handle, &op);
|
||||
if (rc == 0) {
|
||||
/* Success: print the domain id. */
|
||||
DPRINTF("DOM=%u\n", dom);
|
||||
|
||||
@@ -7,11 +7,15 @@
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include "xc_private.h"
|
||||
|
||||
#include "xg_private.h"
|
||||
|
||||
#include <xen/linux/suspend.h>
|
||||
#include <xen/io/domain_controller.h>
|
||||
#include <time.h>
|
||||
|
||||
#define BATCH_SIZE 1024 /* 1024 pages (4MB) at a time */
|
||||
|
||||
@@ -772,7 +776,7 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ( get_pfn_type_batch(xc_handle, dom, batch, pfn_type) ){
|
||||
if ( xc_get_pfn_type_batch(xc_handle, dom, batch, pfn_type) ){
|
||||
ERR("get_pfn_type_batch failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
#include "xc_private.h"
|
||||
#include "xg_private.h"
|
||||
#include "xc_aout9.h"
|
||||
|
||||
#if defined(__i386__)
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
* Free Software Foundation, Inc.
|
||||
*/
|
||||
|
||||
#include "xc_private.h"
|
||||
#include "xg_private.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* xc_elf_load.c
|
||||
*/
|
||||
|
||||
#include "xc_private.h"
|
||||
#include "xg_private.h"
|
||||
|
||||
#if defined(__i386__)
|
||||
#define ELFSIZE 32
|
||||
|
||||
+73
-81
@@ -64,8 +64,8 @@ void *xc_map_foreign_range(int xc_handle, u32 dom,
|
||||
/*******************/
|
||||
|
||||
/* NB: arr must be mlock'ed */
|
||||
int get_pfn_type_batch(int xc_handle,
|
||||
u32 dom, int num, unsigned long *arr)
|
||||
int xc_get_pfn_type_batch(int xc_handle,
|
||||
u32 dom, int num, unsigned long *arr)
|
||||
{
|
||||
dom0_op_t op;
|
||||
op.cmd = DOM0_GETPAGEFRAMEINFO2;
|
||||
@@ -92,25 +92,40 @@ unsigned int get_pfn_type(int xc_handle,
|
||||
return op.u.getpageframeinfo.type;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************/
|
||||
|
||||
int pin_table(
|
||||
int xc_handle, unsigned int type, unsigned long mfn, domid_t dom)
|
||||
int xc_mmuext_op(
|
||||
int xc_handle,
|
||||
struct mmuext_op *op,
|
||||
unsigned int nr_ops,
|
||||
domid_t dom)
|
||||
{
|
||||
struct mmuext_op op;
|
||||
privcmd_hypercall_t hypercall;
|
||||
long ret = -EINVAL;
|
||||
|
||||
op.cmd = type;
|
||||
op.mfn = mfn;
|
||||
hypercall.op = __HYPERVISOR_mmuext_op;
|
||||
hypercall.arg[0] = (unsigned long)op;
|
||||
hypercall.arg[1] = (unsigned long)nr_ops;
|
||||
hypercall.arg[2] = (unsigned long)0;
|
||||
hypercall.arg[3] = (unsigned long)dom;
|
||||
|
||||
if ( do_mmuext_op(xc_handle, &op, 1, dom) < 0 )
|
||||
return 1;
|
||||
if ( mlock(op, nr_ops*sizeof(*op)) != 0 )
|
||||
{
|
||||
PERROR("Could not lock memory for Xen hypercall");
|
||||
goto out1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
|
||||
{
|
||||
fprintf(stderr, "Dom_mem operation failed (rc=%ld errno=%d)-- need to"
|
||||
" rebuild the user-space tool set?\n",ret,errno);
|
||||
}
|
||||
|
||||
static int flush_mmu_updates(int xc_handle, mmu_t *mmu)
|
||||
safe_munlock(op, nr_ops*sizeof(*op));
|
||||
|
||||
out1:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int flush_mmu_updates(int xc_handle, xc_mmu_t *mmu)
|
||||
{
|
||||
int err = 0;
|
||||
privcmd_hypercall_t hypercall;
|
||||
@@ -145,9 +160,9 @@ static int flush_mmu_updates(int xc_handle, mmu_t *mmu)
|
||||
return err;
|
||||
}
|
||||
|
||||
mmu_t *init_mmu_updates(int xc_handle, domid_t dom)
|
||||
xc_mmu_t *xc_init_mmu_updates(int xc_handle, domid_t dom)
|
||||
{
|
||||
mmu_t *mmu = malloc(sizeof(mmu_t));
|
||||
xc_mmu_t *mmu = malloc(sizeof(xc_mmu_t));
|
||||
if ( mmu == NULL )
|
||||
return mmu;
|
||||
mmu->idx = 0;
|
||||
@@ -155,8 +170,8 @@ mmu_t *init_mmu_updates(int xc_handle, domid_t dom)
|
||||
return mmu;
|
||||
}
|
||||
|
||||
int add_mmu_update(int xc_handle, mmu_t *mmu,
|
||||
unsigned long ptr, unsigned long val)
|
||||
int xc_add_mmu_update(int xc_handle, xc_mmu_t *mmu,
|
||||
unsigned long ptr, unsigned long val)
|
||||
{
|
||||
mmu->updates[mmu->idx].ptr = ptr;
|
||||
mmu->updates[mmu->idx].val = val;
|
||||
@@ -167,11 +182,48 @@ int add_mmu_update(int xc_handle, mmu_t *mmu,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int finish_mmu_updates(int xc_handle, mmu_t *mmu)
|
||||
int xc_finish_mmu_updates(int xc_handle, xc_mmu_t *mmu)
|
||||
{
|
||||
return flush_mmu_updates(xc_handle, mmu);
|
||||
}
|
||||
|
||||
int xc_dom_mem_op(int xc_handle,
|
||||
unsigned int memop,
|
||||
unsigned int *extent_list,
|
||||
unsigned int nr_extents,
|
||||
unsigned int extent_order,
|
||||
domid_t domid)
|
||||
{
|
||||
privcmd_hypercall_t hypercall;
|
||||
long ret = -EINVAL;
|
||||
|
||||
hypercall.op = __HYPERVISOR_dom_mem_op;
|
||||
hypercall.arg[0] = (unsigned long)memop;
|
||||
hypercall.arg[1] = (unsigned long)extent_list;
|
||||
hypercall.arg[2] = (unsigned long)nr_extents;
|
||||
hypercall.arg[3] = (unsigned long)extent_order;
|
||||
hypercall.arg[4] = (unsigned long)domid;
|
||||
|
||||
if ( (extent_list != NULL) &&
|
||||
(mlock(extent_list, nr_extents*sizeof(unsigned long)) != 0) )
|
||||
{
|
||||
PERROR("Could not lock memory for Xen hypercall");
|
||||
goto out1;
|
||||
}
|
||||
|
||||
if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
|
||||
{
|
||||
fprintf(stderr, "Dom_mem operation failed (rc=%ld errno=%d)-- need to"
|
||||
" rebuild the user-space tool set?\n",ret,errno);
|
||||
}
|
||||
|
||||
if ( extent_list != NULL )
|
||||
safe_munlock(extent_list, nr_extents*sizeof(unsigned long));
|
||||
|
||||
out1:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
long long xc_domain_get_cpu_usage( int xc_handle, domid_t domid, int vcpu )
|
||||
{
|
||||
@@ -190,19 +242,6 @@ long long xc_domain_get_cpu_usage( int xc_handle, domid_t domid, int vcpu )
|
||||
}
|
||||
|
||||
|
||||
/* This is shared between save and restore, and may generally be useful. */
|
||||
unsigned long csum_page (void * page)
|
||||
{
|
||||
int i;
|
||||
unsigned long *p = page;
|
||||
unsigned long long sum=0;
|
||||
|
||||
for ( i = 0; i < (PAGE_SIZE/sizeof(unsigned long)); i++ )
|
||||
sum += p[i];
|
||||
|
||||
return sum ^ (sum>>32);
|
||||
}
|
||||
|
||||
unsigned long xc_get_m2p_start_mfn ( int xc_handle )
|
||||
{
|
||||
unsigned long mfn;
|
||||
@@ -332,53 +371,6 @@ unsigned long xc_get_filesz(int fd)
|
||||
return sz;
|
||||
}
|
||||
|
||||
char *xc_read_kernel_image(const char *filename, unsigned long *size)
|
||||
{
|
||||
int kernel_fd = -1;
|
||||
gzFile kernel_gfd = NULL;
|
||||
char *image = NULL;
|
||||
unsigned int bytes;
|
||||
|
||||
if ( (kernel_fd = open(filename, O_RDONLY)) < 0 )
|
||||
{
|
||||
PERROR("Could not open kernel image");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ( (*size = xc_get_filesz(kernel_fd)) == 0 )
|
||||
{
|
||||
PERROR("Could not read kernel image");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ( (kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL )
|
||||
{
|
||||
PERROR("Could not allocate decompression state for state file");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ( (image = malloc(*size)) == NULL )
|
||||
{
|
||||
PERROR("Could not allocate memory for kernel image");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ( (bytes = gzread(kernel_gfd, image, *size)) != *size )
|
||||
{
|
||||
PERROR("Error reading kernel image, could not"
|
||||
" read the whole image (%d != %ld).", bytes, *size);
|
||||
free(image);
|
||||
image = NULL;
|
||||
}
|
||||
|
||||
out:
|
||||
if ( kernel_gfd != NULL )
|
||||
gzclose(kernel_gfd);
|
||||
else if ( kernel_fd >= 0 )
|
||||
close(kernel_fd);
|
||||
return image;
|
||||
}
|
||||
|
||||
void xc_map_memcpy(unsigned long dst, char *src, unsigned long size,
|
||||
int xch, u32 dom, unsigned long *parray,
|
||||
unsigned long vstart)
|
||||
|
||||
+4
-227
@@ -1,124 +1,26 @@
|
||||
|
||||
#ifndef __XC_PRIVATE_H__
|
||||
#define __XC_PRIVATE_H__
|
||||
#ifndef XC_PRIVATE_H
|
||||
#define XC_PRIVATE_H
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "xc.h"
|
||||
#include "xenctrl.h"
|
||||
|
||||
#include <xen/linux/privcmd.h>
|
||||
|
||||
#define _PAGE_PRESENT 0x001
|
||||
#define _PAGE_RW 0x002
|
||||
#define _PAGE_USER 0x004
|
||||
#define _PAGE_PWT 0x008
|
||||
#define _PAGE_PCD 0x010
|
||||
#define _PAGE_ACCESSED 0x020
|
||||
#define _PAGE_DIRTY 0x040
|
||||
#define _PAGE_PAT 0x080
|
||||
#define _PAGE_PSE 0x080
|
||||
#define _PAGE_GLOBAL 0x100
|
||||
|
||||
#if defined(__i386__)
|
||||
#define L1_PAGETABLE_SHIFT 12
|
||||
#define L2_PAGETABLE_SHIFT 22
|
||||
#define L1_PAGETABLE_SHIFT_PAE 12
|
||||
#define L2_PAGETABLE_SHIFT_PAE 21
|
||||
#define L3_PAGETABLE_SHIFT_PAE 30
|
||||
#elif defined(__x86_64__)
|
||||
#define L1_PAGETABLE_SHIFT 12
|
||||
#define L2_PAGETABLE_SHIFT 21
|
||||
#define L3_PAGETABLE_SHIFT 30
|
||||
#define L4_PAGETABLE_SHIFT 39
|
||||
#endif
|
||||
|
||||
#if defined(__i386__)
|
||||
#define ENTRIES_PER_L1_PAGETABLE 1024
|
||||
#define ENTRIES_PER_L2_PAGETABLE 1024
|
||||
#define L1_PAGETABLE_ENTRIES_PAE 512
|
||||
#define L2_PAGETABLE_ENTRIES_PAE 512
|
||||
#define L3_PAGETABLE_ENTRIES_PAE 4
|
||||
#elif defined(__x86_64__)
|
||||
#define L1_PAGETABLE_ENTRIES 512
|
||||
#define L2_PAGETABLE_ENTRIES 512
|
||||
#define L3_PAGETABLE_ENTRIES 512
|
||||
#define L4_PAGETABLE_ENTRIES 512
|
||||
#endif
|
||||
|
||||
#define PAGE_SHIFT XC_PAGE_SHIFT
|
||||
#define PAGE_SIZE (1UL << PAGE_SHIFT)
|
||||
#define PAGE_MASK (~(PAGE_SIZE-1))
|
||||
|
||||
typedef u32 l1_pgentry_32_t;
|
||||
typedef u32 l2_pgentry_32_t;
|
||||
typedef u64 l1_pgentry_64_t;
|
||||
typedef u64 l2_pgentry_64_t;
|
||||
typedef u64 l3_pgentry_64_t;
|
||||
typedef unsigned long l1_pgentry_t;
|
||||
typedef unsigned long l2_pgentry_t;
|
||||
#if defined(__x86_64__)
|
||||
typedef unsigned long l3_pgentry_t;
|
||||
typedef unsigned long l4_pgentry_t;
|
||||
#endif
|
||||
|
||||
#if defined(__i386__)
|
||||
#define l1_table_offset(_a) \
|
||||
(((_a) >> L1_PAGETABLE_SHIFT) & (ENTRIES_PER_L1_PAGETABLE - 1))
|
||||
#define l2_table_offset(_a) \
|
||||
((_a) >> L2_PAGETABLE_SHIFT)
|
||||
#define l1_table_offset_pae(_a) \
|
||||
(((_a) >> L1_PAGETABLE_SHIFT_PAE) & (L1_PAGETABLE_ENTRIES_PAE - 1))
|
||||
#define l2_table_offset_pae(_a) \
|
||||
(((_a) >> L2_PAGETABLE_SHIFT_PAE) & (L2_PAGETABLE_ENTRIES_PAE - 1))
|
||||
#define l3_table_offset_pae(_a) \
|
||||
(((_a) >> L3_PAGETABLE_SHIFT_PAE) & (L3_PAGETABLE_ENTRIES_PAE - 1))
|
||||
#elif defined(__x86_64__)
|
||||
#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))
|
||||
#define l3_table_offset(_a) \
|
||||
(((_a) >> L3_PAGETABLE_SHIFT) & (L3_PAGETABLE_ENTRIES - 1))
|
||||
#define l4_table_offset(_a) \
|
||||
(((_a) >> L4_PAGETABLE_SHIFT) & (L4_PAGETABLE_ENTRIES - 1))
|
||||
#endif
|
||||
|
||||
struct domain_setup_info
|
||||
{
|
||||
unsigned long v_start;
|
||||
unsigned long v_end;
|
||||
unsigned long v_kernstart;
|
||||
unsigned long v_kernend;
|
||||
unsigned long v_kernentry;
|
||||
|
||||
unsigned int load_symtab;
|
||||
unsigned int pae_kernel;
|
||||
unsigned long symtab_addr;
|
||||
unsigned long symtab_len;
|
||||
};
|
||||
|
||||
typedef int (*parseimagefunc)(char *image, unsigned long image_size,
|
||||
struct domain_setup_info *dsi);
|
||||
typedef int (*loadimagefunc)(char *image, unsigned long image_size, int xch,
|
||||
u32 dom, unsigned long *parray,
|
||||
struct domain_setup_info *dsi);
|
||||
|
||||
struct load_funcs
|
||||
{
|
||||
parseimagefunc parseimage;
|
||||
loadimagefunc loadimage;
|
||||
};
|
||||
|
||||
#define ERROR(_m, _a...) \
|
||||
do { \
|
||||
int __saved_errno = errno; \
|
||||
@@ -186,97 +88,6 @@ static inline int do_dom0_op(int xc_handle, dom0_op_t *op)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int do_dom_mem_op(int xc_handle,
|
||||
unsigned int memop,
|
||||
unsigned int *extent_list,
|
||||
unsigned int nr_extents,
|
||||
unsigned int extent_order,
|
||||
domid_t domid)
|
||||
{
|
||||
privcmd_hypercall_t hypercall;
|
||||
long ret = -EINVAL;
|
||||
|
||||
hypercall.op = __HYPERVISOR_dom_mem_op;
|
||||
hypercall.arg[0] = (unsigned long)memop;
|
||||
hypercall.arg[1] = (unsigned long)extent_list;
|
||||
hypercall.arg[2] = (unsigned long)nr_extents;
|
||||
hypercall.arg[3] = (unsigned long)extent_order;
|
||||
hypercall.arg[4] = (unsigned long)domid;
|
||||
|
||||
if ( (extent_list != NULL) &&
|
||||
(mlock(extent_list, nr_extents*sizeof(unsigned long)) != 0) )
|
||||
{
|
||||
PERROR("Could not lock memory for Xen hypercall");
|
||||
goto out1;
|
||||
}
|
||||
|
||||
if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
|
||||
{
|
||||
fprintf(stderr, "Dom_mem operation failed (rc=%ld errno=%d)-- need to"
|
||||
" rebuild the user-space tool set?\n",ret,errno);
|
||||
}
|
||||
|
||||
if ( extent_list != NULL )
|
||||
safe_munlock(extent_list, nr_extents*sizeof(unsigned long));
|
||||
|
||||
out1:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int do_mmuext_op(
|
||||
int xc_handle,
|
||||
struct mmuext_op *op,
|
||||
unsigned int nr_ops,
|
||||
domid_t dom)
|
||||
{
|
||||
privcmd_hypercall_t hypercall;
|
||||
long ret = -EINVAL;
|
||||
|
||||
hypercall.op = __HYPERVISOR_mmuext_op;
|
||||
hypercall.arg[0] = (unsigned long)op;
|
||||
hypercall.arg[1] = (unsigned long)nr_ops;
|
||||
hypercall.arg[2] = (unsigned long)0;
|
||||
hypercall.arg[3] = (unsigned long)dom;
|
||||
|
||||
if ( mlock(op, nr_ops*sizeof(*op)) != 0 )
|
||||
{
|
||||
PERROR("Could not lock memory for Xen hypercall");
|
||||
goto out1;
|
||||
}
|
||||
|
||||
if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
|
||||
{
|
||||
fprintf(stderr, "Dom_mem operation failed (rc=%ld errno=%d)-- need to"
|
||||
" rebuild the user-space tool set?\n",ret,errno);
|
||||
}
|
||||
|
||||
safe_munlock(op, nr_ops*sizeof(*op));
|
||||
|
||||
out1:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* PFN mapping.
|
||||
*/
|
||||
int get_pfn_type_batch(int xc_handle, u32 dom, int num, unsigned long *arr);
|
||||
unsigned long csum_page (void * page);
|
||||
|
||||
/*
|
||||
* MMU updates.
|
||||
*/
|
||||
#define MAX_MMU_UPDATES 1024
|
||||
typedef struct {
|
||||
mmu_update_t updates[MAX_MMU_UPDATES];
|
||||
int idx;
|
||||
domid_t subject;
|
||||
} mmu_t;
|
||||
mmu_t *init_mmu_updates(int xc_handle, domid_t dom);
|
||||
int add_mmu_update(int xc_handle, mmu_t *mmu,
|
||||
unsigned long ptr, unsigned long val);
|
||||
int finish_mmu_updates(int xc_handle, mmu_t *mmu);
|
||||
|
||||
|
||||
/*
|
||||
* ioctl-based mfn mapping interface
|
||||
@@ -296,38 +107,4 @@ typedef struct privcmd_mmap {
|
||||
} privcmd_mmap_t;
|
||||
*/
|
||||
|
||||
#define mfn_mapper_queue_size 128
|
||||
|
||||
typedef struct mfn_mapper {
|
||||
int xc_handle;
|
||||
int size;
|
||||
int prot;
|
||||
int error;
|
||||
int max_queue_size;
|
||||
void * addr;
|
||||
privcmd_mmap_t ioctl;
|
||||
|
||||
} mfn_mapper_t;
|
||||
|
||||
unsigned long xc_get_m2p_start_mfn (int xc_handle);
|
||||
|
||||
int xc_copy_to_domain_page(int xc_handle, u32 domid,
|
||||
unsigned long dst_pfn, void *src_page);
|
||||
|
||||
unsigned long xc_get_filesz(int fd);
|
||||
|
||||
char *xc_read_kernel_image(const char *filename, unsigned long *size);
|
||||
|
||||
void xc_map_memcpy(unsigned long dst, char *src, unsigned long size,
|
||||
int xch, u32 dom, unsigned long *parray,
|
||||
unsigned long vstart);
|
||||
|
||||
int pin_table(int xc_handle, unsigned int type, unsigned long mfn,
|
||||
domid_t dom);
|
||||
|
||||
/* image loading */
|
||||
int probe_elf(char *image, unsigned long image_size, struct load_funcs *funcs);
|
||||
int probe_bin(char *image, unsigned long image_size, struct load_funcs *funcs);
|
||||
int probe_aout9(char *image, unsigned long image_size, struct load_funcs *funcs);
|
||||
|
||||
#endif /* __XC_PRIVATE_H__ */
|
||||
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include "xc_private.h"
|
||||
#include "xg_private.h"
|
||||
#define ELFSIZE 32
|
||||
#include "xc_elf.h"
|
||||
#include <stdlib.h>
|
||||
@@ -243,7 +243,7 @@ static int setup_guest(int xc_handle,
|
||||
shared_info_t *shared_info;
|
||||
struct linux_boot_params * boot_paramsp;
|
||||
__u16 * boot_gdtp;
|
||||
mmu_t *mmu = NULL;
|
||||
xc_mmu_t *mmu = NULL;
|
||||
int rc;
|
||||
|
||||
unsigned long nr_pt_pages;
|
||||
@@ -358,7 +358,7 @@ static int setup_guest(int xc_handle,
|
||||
}
|
||||
}
|
||||
|
||||
if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL )
|
||||
if ( (mmu = xc_init_mmu_updates(xc_handle, dom)) == NULL )
|
||||
goto error_out;
|
||||
|
||||
#ifdef __i386__
|
||||
@@ -459,9 +459,9 @@ static int setup_guest(int xc_handle,
|
||||
/* Write the machine->phys table entries. */
|
||||
for ( count = 0; count < nr_pages; count++ )
|
||||
{
|
||||
if ( add_mmu_update(xc_handle, mmu,
|
||||
(page_array[count] << PAGE_SHIFT) |
|
||||
MMU_MACHPHYS_UPDATE, count) )
|
||||
if ( xc_add_mmu_update(xc_handle, mmu,
|
||||
(page_array[count] << PAGE_SHIFT) |
|
||||
MMU_MACHPHYS_UPDATE, count) )
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
@@ -587,7 +587,7 @@ static int setup_guest(int xc_handle,
|
||||
#endif
|
||||
|
||||
/* Send the page update requests down to the hypervisor. */
|
||||
if ( finish_mmu_updates(xc_handle, mmu) )
|
||||
if ( xc_finish_mmu_updates(xc_handle, mmu) )
|
||||
goto error_out;
|
||||
|
||||
free(mmu);
|
||||
@@ -708,7 +708,7 @@ int xc_vmx_build(int xc_handle,
|
||||
|
||||
op.cmd = DOM0_GETDOMAININFO;
|
||||
op.u.getdomaininfo.domain = (domid_t)domid;
|
||||
if ( (do_dom0_op(xc_handle, &op) < 0) ||
|
||||
if ( (xc_dom0_op(xc_handle, &op) < 0) ||
|
||||
((u16)op.u.getdomaininfo.domain != domid) )
|
||||
{
|
||||
PERROR("Could not get info on domain");
|
||||
@@ -789,7 +789,7 @@ int xc_vmx_build(int xc_handle,
|
||||
launch_op.u.setdomaininfo.ctxt = ctxt;
|
||||
|
||||
launch_op.cmd = DOM0_SETDOMAININFO;
|
||||
rc = do_dom0_op(xc_handle, &launch_op);
|
||||
rc = xc_dom0_op(xc_handle, &launch_op);
|
||||
|
||||
return rc;
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/******************************************************************************
|
||||
* xc.h
|
||||
* xenctrl.h
|
||||
*
|
||||
* A library for low-level access to the Xen control interfaces.
|
||||
*
|
||||
* Copyright (c) 2003-2004, K A Fraser.
|
||||
*/
|
||||
|
||||
#ifndef __XC_H__
|
||||
#define __XC_H__
|
||||
#ifndef XENCTRL_H
|
||||
#define XENCTRL_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -254,63 +254,6 @@ int xc_shadow_control(int xc_handle,
|
||||
unsigned long pages,
|
||||
xc_shadow_control_stats_t *stats);
|
||||
|
||||
|
||||
#define XCFLAGS_VERBOSE 1
|
||||
#define XCFLAGS_LIVE 2
|
||||
#define XCFLAGS_DEBUG 4
|
||||
#define XCFLAGS_CONFIGURE 8
|
||||
|
||||
struct XcIOContext;
|
||||
|
||||
/**
|
||||
* This function will save a domain running Linux.
|
||||
*
|
||||
* @parm xc_handle a handle to an open hypervisor interface
|
||||
* @parm fd the file descriptor to save a domain to
|
||||
* @parm dom the id of the domain
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int xc_linux_save(int xc_handle, int fd, u32 dom);
|
||||
|
||||
/**
|
||||
* This function will restore a saved domain running Linux.
|
||||
*
|
||||
* @parm xc_handle a handle to an open hypervisor interface
|
||||
* @parm fd the file descriptor to restore a domain from
|
||||
* @parm dom the id of the domain
|
||||
* @parm nr_pfns the number of pages
|
||||
* @parm store_evtchn the store event channel for this domain to use
|
||||
* @parm store_mfn returned with the mfn of the store page
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int xc_linux_restore(int xc_handle, int io_fd, u32 dom, unsigned long nr_pfns,
|
||||
unsigned int store_evtchn, unsigned long *store_mfn);
|
||||
|
||||
int xc_linux_build(int xc_handle,
|
||||
u32 domid,
|
||||
const char *image_name,
|
||||
const char *ramdisk_name,
|
||||
const char *cmdline,
|
||||
unsigned int control_evtchn,
|
||||
unsigned long flags,
|
||||
unsigned int vcpus,
|
||||
unsigned int store_evtchn,
|
||||
unsigned long *store_mfn);
|
||||
|
||||
struct mem_map;
|
||||
int xc_vmx_build(int xc_handle,
|
||||
u32 domid,
|
||||
int memsize,
|
||||
const char *image_name,
|
||||
struct mem_map *memmap,
|
||||
const char *ramdisk_name,
|
||||
const char *cmdline,
|
||||
unsigned int control_evtchn,
|
||||
unsigned long flags,
|
||||
unsigned int vcpus,
|
||||
unsigned int store_evtchn,
|
||||
unsigned long *store_mfn);
|
||||
|
||||
int xc_bvtsched_global_set(int xc_handle,
|
||||
unsigned long ctx_allow);
|
||||
|
||||
@@ -484,6 +427,16 @@ int xc_get_pfn_list(int xc_handle, u32 domid, unsigned long *pfn_buf,
|
||||
int xc_ia64_get_pfn_list(int xc_handle, u32 domid, unsigned long *pfn_buf,
|
||||
unsigned int start_page, unsigned int nr_pages);
|
||||
|
||||
int xc_mmuext_op(int xc_handle, struct mmuext_op *op, unsigned int nr_ops,
|
||||
domid_t dom);
|
||||
|
||||
int xc_dom_mem_op(int xc_handle, unsigned int memop, unsigned int *extent_list,
|
||||
unsigned int nr_extents, unsigned int extent_order,
|
||||
domid_t domid);
|
||||
|
||||
int xc_get_pfn_type_batch(int xc_handle, u32 dom, int num, unsigned long *arr);
|
||||
|
||||
|
||||
/*\
|
||||
* GRANT TABLE FUNCTIONS
|
||||
\*/
|
||||
@@ -555,4 +508,19 @@ int xc_dom0_op(int xc_handle, dom0_op_t *op);
|
||||
*/
|
||||
long xc_init_store(int xc_handle, int remote_port);
|
||||
|
||||
#endif /* __XC_H__ */
|
||||
/*
|
||||
* MMU updates.
|
||||
*/
|
||||
#define MAX_MMU_UPDATES 1024
|
||||
struct xc_mmu {
|
||||
mmu_update_t updates[MAX_MMU_UPDATES];
|
||||
int idx;
|
||||
domid_t subject;
|
||||
};
|
||||
typedef struct xc_mmu xc_mmu_t;
|
||||
xc_mmu_t *xc_init_mmu_updates(int xc_handle, domid_t dom);
|
||||
int xc_add_mmu_update(int xc_handle, xc_mmu_t *mmu,
|
||||
unsigned long ptr, unsigned long val);
|
||||
int xc_finish_mmu_updates(int xc_handle, xc_mmu_t *mmu);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,66 @@
|
||||
/******************************************************************************
|
||||
* xenguest.h
|
||||
*
|
||||
* A library for guest domain management in Xen.
|
||||
*
|
||||
* Copyright (c) 2003-2004, K A Fraser.
|
||||
*/
|
||||
|
||||
#ifndef XENBUILD_H
|
||||
#define XENBUILD_H
|
||||
|
||||
#define XCFLAGS_VERBOSE 1
|
||||
#define XCFLAGS_LIVE 2
|
||||
#define XCFLAGS_DEBUG 4
|
||||
#define XCFLAGS_CONFIGURE 8
|
||||
|
||||
/**
|
||||
* This function will save a domain running Linux.
|
||||
*
|
||||
* @parm xc_handle a handle to an open hypervisor interface
|
||||
* @parm fd the file descriptor to save a domain to
|
||||
* @parm dom the id of the domain
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int xc_linux_save(int xc_handle, int fd, uint32_t dom);
|
||||
|
||||
/**
|
||||
* This function will restore a saved domain running Linux.
|
||||
*
|
||||
* @parm xc_handle a handle to an open hypervisor interface
|
||||
* @parm fd the file descriptor to restore a domain from
|
||||
* @parm dom the id of the domain
|
||||
* @parm nr_pfns the number of pages
|
||||
* @parm store_evtchn the store event channel for this domain to use
|
||||
* @parm store_mfn returned with the mfn of the store page
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int xc_linux_restore(int xc_handle, int io_fd, uint32_t dom, unsigned long nr_pfns,
|
||||
unsigned int store_evtchn, unsigned long *store_mfn);
|
||||
|
||||
int xc_linux_build(int xc_handle,
|
||||
uint32_t domid,
|
||||
const char *image_name,
|
||||
const char *ramdisk_name,
|
||||
const char *cmdline,
|
||||
unsigned int control_evtchn,
|
||||
unsigned long flags,
|
||||
unsigned int vcpus,
|
||||
unsigned int store_evtchn,
|
||||
unsigned long *store_mfn);
|
||||
|
||||
struct mem_map;
|
||||
int xc_vmx_build(int xc_handle,
|
||||
uint32_t domid,
|
||||
int memsize,
|
||||
const char *image_name,
|
||||
struct mem_map *memmap,
|
||||
const char *ramdisk_name,
|
||||
const char *cmdline,
|
||||
unsigned int control_evtchn,
|
||||
unsigned long flags,
|
||||
unsigned int vcpus,
|
||||
unsigned int store_evtchn,
|
||||
unsigned long *store_mfn);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,86 @@
|
||||
/******************************************************************************
|
||||
* xg_private.c
|
||||
*
|
||||
* Helper functions for the rest of the library.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#include "xg_private.h"
|
||||
|
||||
char *xc_read_kernel_image(const char *filename, unsigned long *size)
|
||||
{
|
||||
int kernel_fd = -1;
|
||||
gzFile kernel_gfd = NULL;
|
||||
char *image = NULL;
|
||||
unsigned int bytes;
|
||||
|
||||
if ( (kernel_fd = open(filename, O_RDONLY)) < 0 )
|
||||
{
|
||||
PERROR("Could not open kernel image");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ( (*size = xc_get_filesz(kernel_fd)) == 0 )
|
||||
{
|
||||
PERROR("Could not read kernel image");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ( (kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL )
|
||||
{
|
||||
PERROR("Could not allocate decompression state for state file");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ( (image = malloc(*size)) == NULL )
|
||||
{
|
||||
PERROR("Could not allocate memory for kernel image");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ( (bytes = gzread(kernel_gfd, image, *size)) != *size )
|
||||
{
|
||||
PERROR("Error reading kernel image, could not"
|
||||
" read the whole image (%d != %ld).", bytes, *size);
|
||||
free(image);
|
||||
image = NULL;
|
||||
}
|
||||
|
||||
out:
|
||||
if ( kernel_gfd != NULL )
|
||||
gzclose(kernel_gfd);
|
||||
else if ( kernel_fd >= 0 )
|
||||
close(kernel_fd);
|
||||
return image;
|
||||
}
|
||||
|
||||
/*******************/
|
||||
|
||||
int pin_table(
|
||||
int xc_handle, unsigned int type, unsigned long mfn, domid_t dom)
|
||||
{
|
||||
struct mmuext_op op;
|
||||
|
||||
op.cmd = type;
|
||||
op.mfn = mfn;
|
||||
|
||||
if ( xc_mmuext_op(xc_handle, &op, 1, dom) < 0 )
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is shared between save and restore, and may generally be useful. */
|
||||
unsigned long csum_page (void * page)
|
||||
{
|
||||
int i;
|
||||
unsigned long *p = page;
|
||||
unsigned long long sum=0;
|
||||
|
||||
for ( i = 0; i < (PAGE_SIZE/sizeof(unsigned long)); i++ )
|
||||
sum += p[i];
|
||||
|
||||
return sum ^ (sum>>32);
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
#ifndef XG_PRIVATE_H
|
||||
#define XG_PRIVATE_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "xenctrl.h"
|
||||
|
||||
#include <xen/linux/privcmd.h>
|
||||
|
||||
char *xc_read_kernel_image(const char *filename, unsigned long *size);
|
||||
unsigned long csum_page (void * page);
|
||||
|
||||
#define _PAGE_PRESENT 0x001
|
||||
#define _PAGE_RW 0x002
|
||||
#define _PAGE_USER 0x004
|
||||
#define _PAGE_PWT 0x008
|
||||
#define _PAGE_PCD 0x010
|
||||
#define _PAGE_ACCESSED 0x020
|
||||
#define _PAGE_DIRTY 0x040
|
||||
#define _PAGE_PAT 0x080
|
||||
#define _PAGE_PSE 0x080
|
||||
#define _PAGE_GLOBAL 0x100
|
||||
|
||||
#if defined(__i386__)
|
||||
#define L1_PAGETABLE_SHIFT 12
|
||||
#define L2_PAGETABLE_SHIFT 22
|
||||
#define L1_PAGETABLE_SHIFT_PAE 12
|
||||
#define L2_PAGETABLE_SHIFT_PAE 21
|
||||
#define L3_PAGETABLE_SHIFT_PAE 30
|
||||
#elif defined(__x86_64__)
|
||||
#define L1_PAGETABLE_SHIFT 12
|
||||
#define L2_PAGETABLE_SHIFT 21
|
||||
#define L3_PAGETABLE_SHIFT 30
|
||||
#define L4_PAGETABLE_SHIFT 39
|
||||
#endif
|
||||
|
||||
#if defined(__i386__)
|
||||
#define ENTRIES_PER_L1_PAGETABLE 1024
|
||||
#define ENTRIES_PER_L2_PAGETABLE 1024
|
||||
#define L1_PAGETABLE_ENTRIES_PAE 512
|
||||
#define L2_PAGETABLE_ENTRIES_PAE 512
|
||||
#define L3_PAGETABLE_ENTRIES_PAE 4
|
||||
#elif defined(__x86_64__)
|
||||
#define L1_PAGETABLE_ENTRIES 512
|
||||
#define L2_PAGETABLE_ENTRIES 512
|
||||
#define L3_PAGETABLE_ENTRIES 512
|
||||
#define L4_PAGETABLE_ENTRIES 512
|
||||
#endif
|
||||
|
||||
#define PAGE_SHIFT XC_PAGE_SHIFT
|
||||
#define PAGE_SIZE (1UL << PAGE_SHIFT)
|
||||
#define PAGE_MASK (~(PAGE_SIZE-1))
|
||||
|
||||
typedef u32 l1_pgentry_32_t;
|
||||
typedef u32 l2_pgentry_32_t;
|
||||
typedef u64 l1_pgentry_64_t;
|
||||
typedef u64 l2_pgentry_64_t;
|
||||
typedef u64 l3_pgentry_64_t;
|
||||
typedef unsigned long l1_pgentry_t;
|
||||
typedef unsigned long l2_pgentry_t;
|
||||
#if defined(__x86_64__)
|
||||
typedef unsigned long l3_pgentry_t;
|
||||
typedef unsigned long l4_pgentry_t;
|
||||
#endif
|
||||
|
||||
#if defined(__i386__)
|
||||
#define l1_table_offset(_a) \
|
||||
(((_a) >> L1_PAGETABLE_SHIFT) & (ENTRIES_PER_L1_PAGETABLE - 1))
|
||||
#define l2_table_offset(_a) \
|
||||
((_a) >> L2_PAGETABLE_SHIFT)
|
||||
#define l1_table_offset_pae(_a) \
|
||||
(((_a) >> L1_PAGETABLE_SHIFT_PAE) & (L1_PAGETABLE_ENTRIES_PAE - 1))
|
||||
#define l2_table_offset_pae(_a) \
|
||||
(((_a) >> L2_PAGETABLE_SHIFT_PAE) & (L2_PAGETABLE_ENTRIES_PAE - 1))
|
||||
#define l3_table_offset_pae(_a) \
|
||||
(((_a) >> L3_PAGETABLE_SHIFT_PAE) & (L3_PAGETABLE_ENTRIES_PAE - 1))
|
||||
#elif defined(__x86_64__)
|
||||
#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))
|
||||
#define l3_table_offset(_a) \
|
||||
(((_a) >> L3_PAGETABLE_SHIFT) & (L3_PAGETABLE_ENTRIES - 1))
|
||||
#define l4_table_offset(_a) \
|
||||
(((_a) >> L4_PAGETABLE_SHIFT) & (L4_PAGETABLE_ENTRIES - 1))
|
||||
#endif
|
||||
|
||||
#define ERROR(_m, _a...) \
|
||||
do { \
|
||||
int __saved_errno = errno; \
|
||||
fprintf(stderr, "ERROR: " _m "\n" , ## _a ); \
|
||||
errno = __saved_errno; \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define PERROR(_m, _a...) \
|
||||
do { \
|
||||
int __saved_errno = errno; \
|
||||
fprintf(stderr, "ERROR: " _m " (%d = %s)\n" , ## _a , \
|
||||
__saved_errno, strerror(__saved_errno)); \
|
||||
errno = __saved_errno; \
|
||||
} while (0)
|
||||
|
||||
|
||||
struct domain_setup_info
|
||||
{
|
||||
unsigned long v_start;
|
||||
unsigned long v_end;
|
||||
unsigned long v_kernstart;
|
||||
unsigned long v_kernend;
|
||||
unsigned long v_kernentry;
|
||||
|
||||
unsigned int load_symtab;
|
||||
unsigned int pae_kernel;
|
||||
unsigned long symtab_addr;
|
||||
unsigned long symtab_len;
|
||||
};
|
||||
|
||||
typedef int (*parseimagefunc)(char *image, unsigned long image_size,
|
||||
struct domain_setup_info *dsi);
|
||||
typedef int (*loadimagefunc)(char *image, unsigned long image_size, int xch,
|
||||
u32 dom, unsigned long *parray,
|
||||
struct domain_setup_info *dsi);
|
||||
|
||||
struct load_funcs
|
||||
{
|
||||
parseimagefunc parseimage;
|
||||
loadimagefunc loadimage;
|
||||
};
|
||||
|
||||
#define mfn_mapper_queue_size 128
|
||||
|
||||
typedef struct mfn_mapper {
|
||||
int xc_handle;
|
||||
int size;
|
||||
int prot;
|
||||
int error;
|
||||
int max_queue_size;
|
||||
void * addr;
|
||||
privcmd_mmap_t ioctl;
|
||||
|
||||
} mfn_mapper_t;
|
||||
|
||||
unsigned long xc_get_m2p_start_mfn (int xc_handle);
|
||||
|
||||
int xc_copy_to_domain_page(int xc_handle, u32 domid,
|
||||
unsigned long dst_pfn, void *src_page);
|
||||
|
||||
unsigned long xc_get_filesz(int fd);
|
||||
|
||||
void xc_map_memcpy(unsigned long dst, char *src, unsigned long size,
|
||||
int xch, u32 dom, unsigned long *parray,
|
||||
unsigned long vstart);
|
||||
|
||||
int pin_table(int xc_handle, unsigned int type, unsigned long mfn,
|
||||
domid_t dom);
|
||||
|
||||
/* image loading */
|
||||
int probe_elf(char *image, unsigned long image_size, struct load_funcs *funcs);
|
||||
int probe_bin(char *image, unsigned long image_size, struct load_funcs *funcs);
|
||||
int probe_aout9(char *image, unsigned long image_size, struct load_funcs *funcs);
|
||||
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -50,4 +50,4 @@ clean:
|
||||
$(CC) -c $(CFLAGS) -o $@ $<
|
||||
|
||||
$(TARGETS): %: %.o Makefile
|
||||
$(CC) $(CFLAGS) -o $@ $< -L$(XEN_LIBXC) -lxc
|
||||
$(CC) $(CFLAGS) -o $@ $< -L$(XEN_LIBXC) -lxenctrl
|
||||
@@ -37,7 +37,7 @@ clean:
|
||||
$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
cpuperf-xen: cpuperf.c $(HDRS) Makefile
|
||||
$(CC) $(CFLAGS) -I $(XEN_LIBXC) -L$(XEN_LIBXC) -lxc -DXENO -o $@ $<
|
||||
$(CC) $(CFLAGS) -I $(XEN_LIBXC) -L$(XEN_LIBXC) -lxenctrl -DXENO -o $@ $<
|
||||
|
||||
cpuperf-perfcntr: cpuperf.c $(HDRS) Makefile
|
||||
$(CC) $(CFLAGS) -DPERFCNTR -o $@ $<
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <xc.h>
|
||||
#include <xenctrl.h>
|
||||
|
||||
static int xc_handle;
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <xc.h>
|
||||
#include <xenctrl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <xc.h>
|
||||
#include <xenctrl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
@@ -17,7 +17,7 @@ library_dirs = [ XEN_ROOT + "/tools/libxc",
|
||||
XEN_ROOT + "/tools/xenstore",
|
||||
]
|
||||
|
||||
libraries = [ "xc", "xenstore-pic" ]
|
||||
libraries = [ "xenctrl", "xenguest", "xenstore" ]
|
||||
|
||||
xc = Extension("xc",
|
||||
extra_compile_args = extra_compile_args,
|
||||
@@ -41,7 +41,7 @@ xs = Extension("xs",
|
||||
sources = [ "xen/lowlevel/xs/xs.c" ])
|
||||
|
||||
setup(name = 'xen',
|
||||
version = '2.0',
|
||||
version = '3.0',
|
||||
description = 'Xen',
|
||||
packages = ['xen',
|
||||
'xen.lowlevel',
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
*/
|
||||
|
||||
#include <Python.h>
|
||||
#include <xc.h>
|
||||
#include <xenctrl.h>
|
||||
#include <xenguest.h>
|
||||
#include <zlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <xc.h>
|
||||
#include <xenctrl.h>
|
||||
|
||||
#include <xen/xen.h>
|
||||
#include <xen/io/domain_controller.h>
|
||||
|
||||
@@ -265,6 +265,8 @@ class XendDomainInfo:
|
||||
self.info = None
|
||||
self.blkif_backend = False
|
||||
self.netif_backend = False
|
||||
self.netif_idx = 0
|
||||
|
||||
#todo: state: running, suspended
|
||||
self.state = STATE_VM_OK
|
||||
self.state_updated = threading.Condition()
|
||||
@@ -400,8 +402,7 @@ class XendDomainInfo:
|
||||
db['virtual-device'] = "%i" % devnum
|
||||
#db['backend'] = sxp.child_value(devconfig, 'backend', '0')
|
||||
db['backend'] = backdb.getPath()
|
||||
db['backend-id'] = "%i" % int(sxp.child_value(devconfig,
|
||||
'backend', '0'))
|
||||
db['backend-id'] = "%i" % backdom.id
|
||||
|
||||
backdb['frontend'] = db.getPath()
|
||||
(type, params) = string.split(sxp.child_value(devconfig, 'uname'), ':', 1)
|
||||
@@ -417,6 +418,37 @@ class XendDomainInfo:
|
||||
db.saveDB(save=True)
|
||||
|
||||
return
|
||||
|
||||
if type == 'vif':
|
||||
backdom = domain_exists(sxp.child_value(devconfig, 'backend', '0'))
|
||||
|
||||
log.error(devconfig)
|
||||
|
||||
devnum = self.netif_idx
|
||||
self.netif_idx += 1
|
||||
|
||||
# create backend db
|
||||
backdb = backdom.db.addChild("/backend/%s/%s/%d" %
|
||||
(type, self.uuid, devnum))
|
||||
|
||||
# create frontend db
|
||||
db = self.db.addChild("/device/%s/%d" % (type, devnum))
|
||||
|
||||
backdb['frontend'] = db.getPath()
|
||||
backdb['frontend-id'] = "%i" % self.id
|
||||
backdb['handle'] = "%i" % devnum
|
||||
backdb.saveDB(save=True)
|
||||
|
||||
db['backend'] = backdb.getPath()
|
||||
db['backend-id'] = "%i" % backdom.id
|
||||
db['handle'] = "%i" % devnum
|
||||
log.error(sxp.child_value(devconfig, 'mac'))
|
||||
db['mac'] = sxp.child_value(devconfig, 'mac')
|
||||
|
||||
db.saveDB(save=True)
|
||||
|
||||
return
|
||||
|
||||
ctrl = self.findDeviceController(type)
|
||||
return ctrl.createDevice(devconfig, recreate=self.recreate,
|
||||
change=change)
|
||||
@@ -718,6 +750,11 @@ class XendDomainInfo:
|
||||
devdb['node'].getData())
|
||||
typedb[dev].delete()
|
||||
typedb.saveDB(save=True)
|
||||
if type == 'vif':
|
||||
typedb = ddb.addChild(type)
|
||||
for dev in typedb.keys():
|
||||
typedb[dev].delete()
|
||||
typedb.saveDB(save=True)
|
||||
|
||||
def show(self):
|
||||
"""Print virtual machine info.
|
||||
|
||||
@@ -665,8 +665,10 @@ def main(argv=sys.argv):
|
||||
err("Most commands need root access. Please try again as root")
|
||||
sys.exit(1)
|
||||
except XendError, ex:
|
||||
if args[0] == "bogus":
|
||||
args.remove("bogus")
|
||||
if len(args) > 0:
|
||||
handle_xend_error(argv[1], args[1], ex)
|
||||
handle_xend_error(argv[1], args[0], ex)
|
||||
else:
|
||||
print "Unexpected error:", sys.exc_info()[0]
|
||||
print
|
||||
|
||||
+2
-2
@@ -34,10 +34,10 @@ clean:
|
||||
|
||||
xcsdump: xcsdump.c dump.c
|
||||
$(CC) $(CFLAGS) -o xcsdump xcsdump.c -L$(XEN_LIBXC) \
|
||||
ctrl_interface.c evtchn.c dump.c -lxc
|
||||
ctrl_interface.c evtchn.c dump.c -lxenctrl
|
||||
|
||||
$(BIN): $(OBJS)
|
||||
$(CC) $(CFLAGS) $^ -o $@ -L$(XEN_LIBXC) -lxc
|
||||
$(CC) $(CFLAGS) $^ -o $@ -L$(XEN_LIBXC) -lxenctrl
|
||||
|
||||
$(OBJS): $(HDRS)
|
||||
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@
|
||||
#define XENCTLD_ERROR_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <xc.h>
|
||||
#include <xenctrl.h>
|
||||
#include <xen/io/domain_controller.h>
|
||||
|
||||
void dump_msg(const control_msg_t *msg, uint64_t flags);
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
#define __XCS_H__
|
||||
|
||||
#include <pthread.h>
|
||||
#include <xc.h>
|
||||
#include <xenctrl.h>
|
||||
#include <xen/xen.h>
|
||||
#include <xen/io/domain_controller.h>
|
||||
#include <xen/linux/privcmd.h>
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <ctype.h>
|
||||
#include <xc.h>
|
||||
#include <xenctrl.h>
|
||||
#include <xen/xen.h>
|
||||
#include <xen/io/domain_controller.h>
|
||||
#include <getopt.h>
|
||||
|
||||
@@ -30,7 +30,7 @@ PROG_DEP = .*.d
|
||||
|
||||
PROGRAMS = xc_restore xc_save
|
||||
|
||||
LDLIBS = -L$(XEN_LIBXC) -lxc
|
||||
LDLIBS = -L$(XEN_LIBXC) -lxenguest -lxenctrl
|
||||
|
||||
.PHONY: all
|
||||
all: build
|
||||
|
||||
@@ -7,11 +7,12 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <err.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <xc.h>
|
||||
#include <xenguest.h>
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
|
||||
@@ -7,11 +7,12 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <err.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <xc.h>
|
||||
#include <xenguest.h>
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
|
||||
@@ -32,7 +32,7 @@ xen:
|
||||
ln -sf $(XEN_ROOT)/xen/include/public $@
|
||||
|
||||
xenstored: xenstored_core.o xenstored_watch.o xenstored_domain.o xenstored_transaction.o xs_lib.o talloc.o utils.o
|
||||
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -lxc -o $@
|
||||
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -lxenctrl -o $@
|
||||
|
||||
xenstored_test: xenstored_core_test.o xenstored_watch_test.o xenstored_domain_test.o xenstored_transaction_test.o xs_lib.o talloc_test.o fake_libxc.o utils.o
|
||||
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
|
||||
@@ -109,7 +109,7 @@ stresstest: xs_stress xenstored_test
|
||||
export $(TESTENV); PID=`./xenstored_test --output-pid --trace-file=/tmp/trace`; ./xs_stress 5000; ret=$$?; kill $$PID; exit $$ret
|
||||
|
||||
xs_dom0_test: xs_dom0_test.o utils.o
|
||||
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -lxc -o $@
|
||||
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -lxenctrl -o $@
|
||||
|
||||
TAGS:
|
||||
etags `find . -name '*.[ch]'`
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include "xs.h"
|
||||
#include "utils.h"
|
||||
#include <xc.h>
|
||||
#include <xenctrl.h>
|
||||
#include <xen/linux/privcmd.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <limits.h>
|
||||
#include <xc.h>
|
||||
#include <xenctrl.h>
|
||||
|
||||
/* Bitmask of permissions. */
|
||||
enum xs_perm_type {
|
||||
|
||||
@@ -36,4 +36,4 @@ clean:
|
||||
$(RM) *.a *.so *.o *.rpm $(BIN)
|
||||
|
||||
%: %.c $(HDRS) Makefile
|
||||
$(CC) $(CFLAGS) -o $@ $< -L$(XEN_LIBXC) -lxc
|
||||
$(CC) $(CFLAGS) -o $@ $< -L$(XEN_LIBXC) -lxenctrl
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <argp.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "xc.h"
|
||||
#include "xenctrl.h"
|
||||
|
||||
#ifdef __i386__
|
||||
void print_ctx(vcpu_guest_context_t *ctx1)
|
||||
|
||||
@@ -93,15 +93,10 @@ void __init paging_init(void)
|
||||
|
||||
/*
|
||||
* Allocate and map the machine-to-phys table and create read-only mapping
|
||||
* of MPT for guest-OS use. Without PAE we'll end up with one 4MB page,
|
||||
* with PAE we'll allocate 2MB pages depending on the amount of memory
|
||||
* installed, but at least 4MB to cover 4GB address space. This is needed
|
||||
* to make PCI I/O memory address lookups work in guests.
|
||||
* of MPT for guest-OS use.
|
||||
*/
|
||||
mpt_size = (max_page * 4) + (1UL << L2_PAGETABLE_SHIFT) - 1UL;
|
||||
mpt_size &= ~((1UL << L2_PAGETABLE_SHIFT) - 1UL);
|
||||
if ( mpt_size < (4 << 20) )
|
||||
mpt_size = 4 << 20;
|
||||
for ( i = 0; i < (mpt_size >> L2_PAGETABLE_SHIFT); i++ )
|
||||
{
|
||||
if ( (pg = alloc_domheap_pages(NULL, PAGETABLE_ORDER, 0)) == NULL )
|
||||
|
||||
@@ -74,7 +74,7 @@ l2_pgentry_t *virt_to_xen_l2e(unsigned long v)
|
||||
|
||||
void __init paging_init(void)
|
||||
{
|
||||
unsigned long i;
|
||||
unsigned long i, mpt_size;
|
||||
l3_pgentry_t *l3_ro_mpt;
|
||||
l2_pgentry_t *l2_ro_mpt;
|
||||
struct pfn_info *pg;
|
||||
@@ -98,16 +98,17 @@ void __init paging_init(void)
|
||||
* Allocate and map the machine-to-phys table.
|
||||
* This also ensures L3 is present for fixmaps.
|
||||
*/
|
||||
for ( i = 0; i < max_page; i += ((1UL << L2_PAGETABLE_SHIFT) / 8) )
|
||||
mpt_size = (max_page * 4) + (1UL << L2_PAGETABLE_SHIFT) - 1UL;
|
||||
mpt_size &= ~((1UL << L2_PAGETABLE_SHIFT) - 1UL);
|
||||
for ( i = 0; i < (mpt_size >> L2_PAGETABLE_SHIFT); i++ )
|
||||
{
|
||||
pg = alloc_domheap_pages(NULL, PAGETABLE_ORDER, 0);
|
||||
if ( pg == NULL )
|
||||
if ( (pg = alloc_domheap_pages(NULL, PAGETABLE_ORDER, 0)) == NULL )
|
||||
panic("Not enough memory for m2p table\n");
|
||||
map_pages_to_xen(
|
||||
RDWR_MPT_VIRT_START + i*8, page_to_pfn(pg),
|
||||
RDWR_MPT_VIRT_START + (i << L2_PAGETABLE_SHIFT), page_to_pfn(pg),
|
||||
1UL << PAGETABLE_ORDER,
|
||||
PAGE_HYPERVISOR);
|
||||
memset((void *)(RDWR_MPT_VIRT_START + i*8), 0x55,
|
||||
memset((void *)(RDWR_MPT_VIRT_START + (i << L2_PAGETABLE_SHIFT)), 0x55,
|
||||
1UL << L2_PAGETABLE_SHIFT);
|
||||
*l2_ro_mpt++ = l2e_from_page(
|
||||
pg, _PAGE_GLOBAL|_PAGE_PSE|_PAGE_USER|_PAGE_PRESENT);
|
||||
|
||||