mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
bitkeeper revision 1.802.1.1 (405853fcN7rcf_nAOUv8-8C-udNDkw)
vnetif.c, Makefile: new file Many files: Relaid out xenolinux drivers. More x86_64 stuff. domain_page.c: Rename: xen/common/domain_page.c -> xen/arch/i386/domain_page.c vbd.c: Rename: xenolinux-2.4.25-sparse/arch/xeno/drivers/block/xl_vbd.c -> xenolinux-2.4.25-sparse/arch/xeno/drivers/block/vbd.c block.h: Rename: xenolinux-2.4.25-sparse/arch/xeno/drivers/block/xl_block.h -> xenolinux-2.4.25-sparse/arch/xeno/drivers/block/block.h block.c: Rename: xenolinux-2.4.25-sparse/arch/xeno/drivers/block/xl_block.c -> xenolinux-2.4.25-sparse/arch/xeno/drivers/block/block.c core.c: Rename: xenolinux-2.4.25-sparse/arch/xeno/drivers/dom0/dom0_core.c -> xenolinux-2.4.25-sparse/arch/xeno/drivers/dom0/core.c evtchn.c: Rename: xenolinux-2.4.25-sparse/arch/xeno/drivers/evtchn/xl_evtchn.c -> xenolinux-2.4.25-sparse/arch/xeno/drivers/evtchn/evtchn.c
This commit is contained in:
1 parent
211e124bd8
commit
672c8342f6
47 files changed
+995
-375
No files matched your search
@@ -117,6 +117,7 @@
|
||||
3ddb79bcsjinG9k1KcvbVBuas1R2dA xen/arch/i386/apic.c
|
||||
3ddb79bcSC_LvnmFlX-T5iTgaR0SKg xen/arch/i386/boot/boot.S
|
||||
3ddb79bcUrk2EIaM5VsT6wUudH1kkg xen/arch/i386/delay.c
|
||||
3e32af9aRnYGl4GMOaDKp7JdfhOGhg xen/arch/i386/domain_page.c
|
||||
3ddb79bcecupHj56ZbTa3B0FxDowMg xen/arch/i386/entry.S
|
||||
3ddb79bcY5zW7KhvI9gvfuPi3ZumEg xen/arch/i386/extable.c
|
||||
3fe443fdDDb0Sw6NQBCk4GQapayfTA xen/arch/i386/flushtlb.c
|
||||
@@ -154,7 +155,6 @@
|
||||
3ddb79bdLX_P6iB7ILiblRLWvebapg xen/common/dom0_ops.c
|
||||
3e6377e4i0c9GtKN65e99OtRbw3AZw xen/common/dom_mem_ops.c
|
||||
3ddb79bdYO5D8Av12NHqPeSviav7cg xen/common/domain.c
|
||||
3e32af9aRnYGl4GMOaDKp7JdfhOGhg xen/common/domain_page.c
|
||||
3ddb79bdeyutmaXEfpQvvxj7eQ0fCw xen/common/event.c
|
||||
3fba5b96H0khoxNiKbjdi0inpXV-Pw xen/common/event_channel.c
|
||||
3ddb79bd9drcFPVxd4w2GPOIjLlXpA xen/common/kernel.c
|
||||
@@ -600,18 +600,20 @@
|
||||
3e6377f5xwPfYZkPHPrDbEq1PRN7uQ xenolinux-2.4.25-sparse/arch/xeno/drivers/balloon/Makefile
|
||||
3e6377f8Me8IqtvEhb70XFgOvqQH7A xenolinux-2.4.25-sparse/arch/xeno/drivers/balloon/balloon.c
|
||||
3e5a4e65iHEuC5sjFhj42XALYbLVRw xenolinux-2.4.25-sparse/arch/xeno/drivers/block/Makefile
|
||||
3e5a4e65pP5spJErBW69pJxSSdK9RA xenolinux-2.4.25-sparse/arch/xeno/drivers/block/xl_block.c
|
||||
3e67f822FOPwqHiaRKbrskgWgoNL5g xenolinux-2.4.25-sparse/arch/xeno/drivers/block/xl_block.h
|
||||
3e676eb5RXnHzSHgA1BvM0B1aIm4qg xenolinux-2.4.25-sparse/arch/xeno/drivers/block/xl_vbd.c
|
||||
3e5a4e65pP5spJErBW69pJxSSdK9RA xenolinux-2.4.25-sparse/arch/xeno/drivers/block/block.c
|
||||
3e67f822FOPwqHiaRKbrskgWgoNL5g xenolinux-2.4.25-sparse/arch/xeno/drivers/block/block.h
|
||||
3e676eb5RXnHzSHgA1BvM0B1aIm4qg xenolinux-2.4.25-sparse/arch/xeno/drivers/block/vbd.c
|
||||
3e5a4e65G3e2s0ghPMgiJ-gBTUJ0uQ xenolinux-2.4.25-sparse/arch/xeno/drivers/console/Makefile
|
||||
3e5a4e651TH-SXHoufurnWjgl5bfOA xenolinux-2.4.25-sparse/arch/xeno/drivers/console/console.c
|
||||
3e5a4e656nfFISThfbyXQOA6HN6YHw xenolinux-2.4.25-sparse/arch/xeno/drivers/dom0/Makefile
|
||||
3e5a4e65BXtftInNHUC2PjDfPhdZZA xenolinux-2.4.25-sparse/arch/xeno/drivers/dom0/dom0_core.c
|
||||
3e5a4e65BXtftInNHUC2PjDfPhdZZA xenolinux-2.4.25-sparse/arch/xeno/drivers/dom0/core.c
|
||||
3e5a4e65gfn_ltB8ujHMVFApnTTNRQ xenolinux-2.4.25-sparse/arch/xeno/drivers/dom0/vfr.c
|
||||
40420a6ebRqDjufoN1WSJvolEW2Wjw xenolinux-2.4.25-sparse/arch/xeno/drivers/evtchn/Makefile
|
||||
40420a73Wou6JlsZDiu6YwjYomsm7A xenolinux-2.4.25-sparse/arch/xeno/drivers/evtchn/xl_evtchn.c
|
||||
40420a73Wou6JlsZDiu6YwjYomsm7A xenolinux-2.4.25-sparse/arch/xeno/drivers/evtchn/evtchn.c
|
||||
3e5a4e65gZBRBB6RsSVg1c9iahigAw xenolinux-2.4.25-sparse/arch/xeno/drivers/network/Makefile
|
||||
3e5a4e65ZxKrbFetVB84JhrTyZ1YuQ xenolinux-2.4.25-sparse/arch/xeno/drivers/network/network.c
|
||||
405853f2wg7JXZJNltspMwOZJklxgw xenolinux-2.4.25-sparse/arch/xeno/drivers/vnetif/Makefile
|
||||
405853f6nbeazrNyEWNHBuoSg2PiPA xenolinux-2.4.25-sparse/arch/xeno/drivers/vnetif/vnetif.c
|
||||
3e5a4e65lWzkiPXsZdzPt2RNnJGG1g xenolinux-2.4.25-sparse/arch/xeno/kernel/Makefile
|
||||
3e5a4e65_hqfuxtGG8IUy6wRM86Ecg xenolinux-2.4.25-sparse/arch/xeno/kernel/entry.S
|
||||
3e5a4e65Hy_1iUvMTPsNqGNXd9uFpg xenolinux-2.4.25-sparse/arch/xeno/kernel/head.S
|
||||
|
||||
@@ -378,32 +378,32 @@ int xc_linux_build(int xc_handle,
|
||||
|
||||
/*
|
||||
* Initial register values:
|
||||
* DS,ES,FS,GS = FLAT_RING1_DS
|
||||
* CS:EIP = FLAT_RING1_CS:start_pc
|
||||
* SS:ESP = FLAT_RING1_DS:start_stack
|
||||
* DS,ES,FS,GS = FLAT_GUESTOS_DS
|
||||
* CS:EIP = FLAT_GUESTOS_CS:start_pc
|
||||
* SS:ESP = FLAT_GUESTOS_DS:start_stack
|
||||
* ESI = start_info
|
||||
* [EAX,EBX,ECX,EDX,EDI,EBP are zero]
|
||||
* EFLAGS = IF | 2 (bit 1 is reserved and should always be 1)
|
||||
*/
|
||||
ctxt->i386_ctxt.ds = FLAT_RING1_DS;
|
||||
ctxt->i386_ctxt.es = FLAT_RING1_DS;
|
||||
ctxt->i386_ctxt.fs = FLAT_RING1_DS;
|
||||
ctxt->i386_ctxt.gs = FLAT_RING1_DS;
|
||||
ctxt->i386_ctxt.ss = FLAT_RING1_DS;
|
||||
ctxt->i386_ctxt.cs = FLAT_RING1_CS;
|
||||
ctxt->i386_ctxt.eip = load_addr;
|
||||
ctxt->i386_ctxt.esp = virt_startinfo_addr;
|
||||
ctxt->i386_ctxt.esi = virt_startinfo_addr;
|
||||
ctxt->i386_ctxt.eflags = (1<<9) | (1<<2);
|
||||
ctxt->cpu_ctxt.ds = FLAT_GUESTOS_DS;
|
||||
ctxt->cpu_ctxt.es = FLAT_GUESTOS_DS;
|
||||
ctxt->cpu_ctxt.fs = FLAT_GUESTOS_DS;
|
||||
ctxt->cpu_ctxt.gs = FLAT_GUESTOS_DS;
|
||||
ctxt->cpu_ctxt.ss = FLAT_GUESTOS_DS;
|
||||
ctxt->cpu_ctxt.cs = FLAT_GUESTOS_CS;
|
||||
ctxt->cpu_ctxt.eip = load_addr;
|
||||
ctxt->cpu_ctxt.esp = virt_startinfo_addr;
|
||||
ctxt->cpu_ctxt.esi = virt_startinfo_addr;
|
||||
ctxt->cpu_ctxt.eflags = (1<<9) | (1<<2);
|
||||
|
||||
/* FPU is set up to default initial state. */
|
||||
memset(ctxt->i387_ctxt, 0, sizeof(ctxt->i387_ctxt));
|
||||
memset(ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt));
|
||||
|
||||
/* Virtual IDT is empty at start-of-day. */
|
||||
for ( i = 0; i < 256; i++ )
|
||||
{
|
||||
ctxt->trap_ctxt[i].vector = i;
|
||||
ctxt->trap_ctxt[i].cs = FLAT_RING1_CS;
|
||||
ctxt->trap_ctxt[i].cs = FLAT_GUESTOS_CS;
|
||||
}
|
||||
ctxt->fast_trap_idx = 0;
|
||||
|
||||
@@ -414,16 +414,16 @@ int xc_linux_build(int xc_handle,
|
||||
ctxt->gdt_ents = 0;
|
||||
|
||||
/* Ring 1 stack is the initial stack. */
|
||||
ctxt->ring1_ss = FLAT_RING1_DS;
|
||||
ctxt->ring1_esp = virt_startinfo_addr;
|
||||
ctxt->guestos_ss = FLAT_GUESTOS_DS;
|
||||
ctxt->guestos_esp = virt_startinfo_addr;
|
||||
|
||||
/* No debugging. */
|
||||
memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg));
|
||||
|
||||
/* No callback handlers. */
|
||||
ctxt->event_callback_cs = FLAT_RING1_CS;
|
||||
ctxt->event_callback_cs = FLAT_GUESTOS_CS;
|
||||
ctxt->event_callback_eip = 0;
|
||||
ctxt->failsafe_callback_cs = FLAT_RING1_CS;
|
||||
ctxt->failsafe_callback_cs = FLAT_GUESTOS_CS;
|
||||
ctxt->failsafe_callback_eip = 0;
|
||||
|
||||
launch_op.u.builddomain.domain = (domid_t)domid;
|
||||
|
||||
@@ -313,13 +313,13 @@ int xc_linux_restore(int xc_handle,
|
||||
verbose_printf("\b\b\b\b100%%\nMemory reloaded.\n");
|
||||
|
||||
/* Uncanonicalise the suspend-record frame number and poke resume rec. */
|
||||
pfn = ctxt.i386_ctxt.esi;
|
||||
pfn = ctxt.cpu_ctxt.esi;
|
||||
if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) )
|
||||
{
|
||||
ERROR("Suspend record frame number is bad");
|
||||
goto out;
|
||||
}
|
||||
ctxt.i386_ctxt.esi = mfn = pfn_to_mfn_table[pfn];
|
||||
ctxt.cpu_ctxt.esi = mfn = pfn_to_mfn_table[pfn];
|
||||
p_srec = map_pfn_writeable(pm_handle, mfn);
|
||||
p_srec->resume_info.nr_pages = nr_pfns;
|
||||
p_srec->resume_info.shared_info = shared_info_frame << PAGE_SHIFT;
|
||||
@@ -370,13 +370,13 @@ int xc_linux_restore(int xc_handle,
|
||||
|
||||
/*
|
||||
* Safety checking of saved context:
|
||||
* 1. i386_ctxt is fine, as Xen checks that on context switch.
|
||||
* 2. i387_ctxt is fine, as it can't hurt Xen.
|
||||
* 1. cpu_ctxt is fine, as Xen checks that on context switch.
|
||||
* 2. fpu_ctxt is fine, as it can't hurt Xen.
|
||||
* 3. trap_ctxt needs the code selectors checked.
|
||||
* 4. fast_trap_idx is checked by Xen.
|
||||
* 5. ldt base must be page-aligned, no more than 8192 ents, ...
|
||||
* 6. gdt already done, and further checking is done by Xen.
|
||||
* 7. check that ring1_ss is safe.
|
||||
* 7. check that guestos_ss is safe.
|
||||
* 8. pt_base is already done.
|
||||
* 9. debugregs are checked by Xen.
|
||||
* 10. callback code selectors need checking.
|
||||
@@ -385,14 +385,14 @@ int xc_linux_restore(int xc_handle,
|
||||
{
|
||||
ctxt.trap_ctxt[i].vector = i;
|
||||
if ( (ctxt.trap_ctxt[i].cs & 3) == 0 )
|
||||
ctxt.trap_ctxt[i].cs = FLAT_RING1_CS;
|
||||
ctxt.trap_ctxt[i].cs = FLAT_GUESTOS_CS;
|
||||
}
|
||||
if ( (ctxt.ring1_ss & 3) == 0 )
|
||||
ctxt.ring1_ss = FLAT_RING1_DS;
|
||||
if ( (ctxt.guestos_ss & 3) == 0 )
|
||||
ctxt.guestos_ss = FLAT_GUESTOS_DS;
|
||||
if ( (ctxt.event_callback_cs & 3) == 0 )
|
||||
ctxt.event_callback_cs = FLAT_RING1_CS;
|
||||
ctxt.event_callback_cs = FLAT_GUESTOS_CS;
|
||||
if ( (ctxt.failsafe_callback_cs & 3) == 0 )
|
||||
ctxt.failsafe_callback_cs = FLAT_RING1_CS;
|
||||
ctxt.failsafe_callback_cs = FLAT_GUESTOS_CS;
|
||||
if ( ((ctxt.ldt_base & (PAGE_SIZE - 1)) != 0) ||
|
||||
(ctxt.ldt_ents > 8192) ||
|
||||
(ctxt.ldt_base > HYPERVISOR_VIRT_START) ||
|
||||
|
||||
@@ -182,14 +182,14 @@ int xc_linux_save(int xc_handle,
|
||||
goto out;
|
||||
|
||||
/* Is the suspend-record MFN actually valid for this domain? */
|
||||
if ( !check_pfn_ownership(xc_handle, ctxt.i386_ctxt.esi, domid) )
|
||||
if ( !check_pfn_ownership(xc_handle, ctxt.cpu_ctxt.esi, domid) )
|
||||
{
|
||||
ERROR("Invalid state record pointer");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* If the suspend-record MFN is okay then grab a copy of it to @srec. */
|
||||
p_srec = map_pfn_readonly(pm_handle, ctxt.i386_ctxt.esi);
|
||||
p_srec = map_pfn_readonly(pm_handle, ctxt.cpu_ctxt.esi);
|
||||
memcpy(&srec, p_srec, sizeof(srec));
|
||||
unmap_pfn(pm_handle, p_srec);
|
||||
|
||||
@@ -272,7 +272,7 @@ int xc_linux_save(int xc_handle,
|
||||
}
|
||||
|
||||
/* Canonicalise the suspend-record frame number. */
|
||||
if ( !translate_mfn_to_pfn(&ctxt.i386_ctxt.esi) )
|
||||
if ( !translate_mfn_to_pfn(&ctxt.cpu_ctxt.esi) )
|
||||
{
|
||||
ERROR("State record is not in range of pseudophys map");
|
||||
goto out;
|
||||
|
||||
@@ -273,32 +273,32 @@ int xc_netbsd_build(int xc_handle,
|
||||
|
||||
/*
|
||||
* Initial register values:
|
||||
* DS,ES,FS,GS = FLAT_RING1_DS
|
||||
* CS:EIP = FLAT_RING1_CS:start_pc
|
||||
* SS:ESP = FLAT_RING1_DS:start_stack
|
||||
* DS,ES,FS,GS = FLAT_GUESTOS_DS
|
||||
* CS:EIP = FLAT_GUESTOS_CS:start_pc
|
||||
* SS:ESP = FLAT_GUESTOS_DS:start_stack
|
||||
* ESI = start_info
|
||||
* [EAX,EBX,ECX,EDX,EDI,EBP are zero]
|
||||
* EFLAGS = IF | 2 (bit 1 is reserved and should always be 1)
|
||||
*/
|
||||
ctxt->i386_ctxt.ds = FLAT_RING1_DS;
|
||||
ctxt->i386_ctxt.es = FLAT_RING1_DS;
|
||||
ctxt->i386_ctxt.fs = FLAT_RING1_DS;
|
||||
ctxt->i386_ctxt.gs = FLAT_RING1_DS;
|
||||
ctxt->i386_ctxt.ss = FLAT_RING1_DS;
|
||||
ctxt->i386_ctxt.cs = FLAT_RING1_CS;
|
||||
ctxt->i386_ctxt.eip = load_addr;
|
||||
ctxt->i386_ctxt.esp = virt_startinfo_addr;
|
||||
ctxt->i386_ctxt.esi = virt_startinfo_addr;
|
||||
ctxt->i386_ctxt.eflags = (1<<9) | (1<<2);
|
||||
ctxt->cpu_ctxt.ds = FLAT_GUESTOS_DS;
|
||||
ctxt->cpu_ctxt.es = FLAT_GUESTOS_DS;
|
||||
ctxt->cpu_ctxt.fs = FLAT_GUESTOS_DS;
|
||||
ctxt->cpu_ctxt.gs = FLAT_GUESTOS_DS;
|
||||
ctxt->cpu_ctxt.ss = FLAT_GUESTOS_DS;
|
||||
ctxt->cpu_ctxt.cs = FLAT_GUESTOS_CS;
|
||||
ctxt->cpu_ctxt.eip = load_addr;
|
||||
ctxt->cpu_ctxt.esp = virt_startinfo_addr;
|
||||
ctxt->cpu_ctxt.esi = virt_startinfo_addr;
|
||||
ctxt->cpu_ctxt.eflags = (1<<9) | (1<<2);
|
||||
|
||||
/* FPU is set up to default initial state. */
|
||||
memset(ctxt->i387_ctxt, 0, sizeof(ctxt->i387_ctxt));
|
||||
memset(ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt));
|
||||
|
||||
/* Virtual IDT is empty at start-of-day. */
|
||||
for ( i = 0; i < 256; i++ )
|
||||
{
|
||||
ctxt->trap_ctxt[i].vector = i;
|
||||
ctxt->trap_ctxt[i].cs = FLAT_RING1_CS;
|
||||
ctxt->trap_ctxt[i].cs = FLAT_GUESTOS_CS;
|
||||
}
|
||||
ctxt->fast_trap_idx = 0;
|
||||
|
||||
@@ -309,16 +309,16 @@ int xc_netbsd_build(int xc_handle,
|
||||
ctxt->gdt_ents = 0;
|
||||
|
||||
/* Ring 1 stack is the initial stack. */
|
||||
ctxt->ring1_ss = FLAT_RING1_DS;
|
||||
ctxt->ring1_esp = virt_startinfo_addr;
|
||||
ctxt->guestos_ss = FLAT_GUESTOS_DS;
|
||||
ctxt->guestos_esp = virt_startinfo_addr;
|
||||
|
||||
/* No debugging. */
|
||||
memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg));
|
||||
|
||||
/* No callback handlers. */
|
||||
ctxt->event_callback_cs = FLAT_RING1_CS;
|
||||
ctxt->event_callback_cs = FLAT_GUESTOS_CS;
|
||||
ctxt->event_callback_eip = 0;
|
||||
ctxt->failsafe_callback_cs = FLAT_RING1_CS;
|
||||
ctxt->failsafe_callback_cs = FLAT_GUESTOS_CS;
|
||||
ctxt->failsafe_callback_eip = 0;
|
||||
|
||||
launch_op.u.builddomain.domain = (domid_t)domid;
|
||||
|
||||
File renamed without changes.
+2
-2
@@ -131,8 +131,8 @@ long do_stack_switch(unsigned long ss, unsigned long esp)
|
||||
if ( (ss & 3) == 0 )
|
||||
return -EPERM;
|
||||
|
||||
current->thread.ss1 = ss;
|
||||
current->thread.esp1 = esp;
|
||||
current->thread.guestos_ss = ss;
|
||||
current->thread.guestos_sp = esp;
|
||||
t->ss1 = ss;
|
||||
t->esp1 = esp;
|
||||
|
||||
|
||||
@@ -264,8 +264,8 @@ void switch_to(struct task_struct *prev_p, struct task_struct *next_p)
|
||||
SET_FAST_TRAP(&next_p->thread);
|
||||
|
||||
/* Switch the guest OS ring-1 stack. */
|
||||
tss->esp1 = next->esp1;
|
||||
tss->ss1 = next->ss1;
|
||||
tss->esp1 = next->guestos_sp;
|
||||
tss->ss1 = next->guestos_ss;
|
||||
|
||||
/* Maybe switch the debug registers. */
|
||||
if ( next->debugreg[7] )
|
||||
|
||||
+12
-4
@@ -290,23 +290,25 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
|
||||
{
|
||||
rmb(); /* Ensure that we see saved register state. */
|
||||
op->u.getdomaininfo.ctxt.flags = 0;
|
||||
memcpy(&op->u.getdomaininfo.ctxt.i386_ctxt,
|
||||
memcpy(&op->u.getdomaininfo.ctxt.cpu_ctxt,
|
||||
&p->shared_info->execution_context,
|
||||
sizeof(p->shared_info->execution_context));
|
||||
if ( test_bit(PF_DONEFPUINIT, &p->flags) )
|
||||
op->u.getdomaininfo.ctxt.flags |= ECF_I387_VALID;
|
||||
memcpy(&op->u.getdomaininfo.ctxt.i387_ctxt,
|
||||
memcpy(&op->u.getdomaininfo.ctxt.fpu_ctxt,
|
||||
&p->thread.i387,
|
||||
sizeof(p->thread.i387));
|
||||
memcpy(&op->u.getdomaininfo.ctxt.trap_ctxt,
|
||||
p->thread.traps,
|
||||
sizeof(p->thread.traps));
|
||||
#ifdef ARCH_HAS_FAST_TRAP
|
||||
if ( (p->thread.fast_trap_desc.a == 0) &&
|
||||
(p->thread.fast_trap_desc.b == 0) )
|
||||
op->u.getdomaininfo.ctxt.fast_trap_idx = 0;
|
||||
else
|
||||
op->u.getdomaininfo.ctxt.fast_trap_idx =
|
||||
p->thread.fast_trap_idx;
|
||||
#endif
|
||||
op->u.getdomaininfo.ctxt.ldt_base = p->mm.ldt_base;
|
||||
op->u.getdomaininfo.ctxt.ldt_ents = p->mm.ldt_ents;
|
||||
op->u.getdomaininfo.ctxt.gdt_ents = 0;
|
||||
@@ -318,8 +320,8 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
|
||||
op->u.getdomaininfo.ctxt.gdt_ents =
|
||||
(GET_GDT_ENTRIES(p) + 1) >> 3;
|
||||
}
|
||||
op->u.getdomaininfo.ctxt.ring1_ss = p->thread.ss1;
|
||||
op->u.getdomaininfo.ctxt.ring1_esp = p->thread.esp1;
|
||||
op->u.getdomaininfo.ctxt.guestos_ss = p->thread.guestos_ss;
|
||||
op->u.getdomaininfo.ctxt.guestos_esp = p->thread.guestos_sp;
|
||||
op->u.getdomaininfo.ctxt.pt_base =
|
||||
pagetable_val(p->mm.pagetable);
|
||||
memcpy(op->u.getdomaininfo.ctxt.debugreg,
|
||||
@@ -371,6 +373,12 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
|
||||
case PGT_l2_page_table:
|
||||
op->u.getpageframeinfo.type = L2TAB;
|
||||
break;
|
||||
case PGT_l3_page_table:
|
||||
op->u.getpageframeinfo.type = L3TAB;
|
||||
break;
|
||||
case PGT_l4_page_table:
|
||||
op->u.getpageframeinfo.type = L4TAB;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+34
-25
@@ -19,13 +19,16 @@
|
||||
#include <xeno/vbd.h>
|
||||
#include <asm/i387.h>
|
||||
|
||||
/*
|
||||
* NB. No ring-3 access in initial guestOS pagetables. Note that we allow
|
||||
* ring-3 privileges in the page directories, so that the guestOS may later
|
||||
* decide to share a 4MB region with applications.
|
||||
*/
|
||||
#if !defined(CONFIG_X86_64BITMODE)
|
||||
/* No ring-3 access in initial page tables. */
|
||||
#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
|
||||
#else
|
||||
/* Allow ring-3 access in long mode as guest cannot use ring 1. */
|
||||
#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_USER)
|
||||
#endif
|
||||
#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
|
||||
#define L3_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
|
||||
#define L4_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
|
||||
|
||||
/* Both these structures are protected by the tasklist_lock. */
|
||||
rwlock_t tasklist_lock __cacheline_aligned = RW_LOCK_UNLOCKED;
|
||||
@@ -426,20 +429,20 @@ void free_all_dom_mem(struct task_struct *p)
|
||||
put_page(page);
|
||||
|
||||
/*
|
||||
* Forcibly invalidate L2 tables at this point to break circular
|
||||
* Forcibly invalidate base page tables at this point to break circular
|
||||
* 'linear page table' references. This is okay because MMU structures
|
||||
* are not shared across domains and this domain is now dead. Thus L2
|
||||
* are not shared across domains and this domain is now dead. Thus base
|
||||
* tables are not in use so a non-zero count means circular reference.
|
||||
*/
|
||||
y = page->type_and_flags;
|
||||
do {
|
||||
x = y;
|
||||
if ( likely((x & (PGT_type_mask|PGT_validated)) !=
|
||||
(PGT_l2_page_table|PGT_validated)) )
|
||||
(PGT_base_page_table|PGT_validated)) )
|
||||
break;
|
||||
y = cmpxchg(&page->type_and_flags, x, x & ~PGT_validated);
|
||||
if ( likely(y == x) )
|
||||
free_page_type(page, PGT_l2_page_table);
|
||||
free_page_type(page, PGT_base_page_table);
|
||||
}
|
||||
while ( unlikely(y != x) );
|
||||
|
||||
@@ -504,7 +507,7 @@ void release_task(struct task_struct *p)
|
||||
*/
|
||||
int final_setup_guestos(struct task_struct *p, dom0_builddomain_t *builddomain)
|
||||
{
|
||||
unsigned long phys_l2tab;
|
||||
unsigned long phys_basetab;
|
||||
int i;
|
||||
|
||||
if ( test_bit(PF_CONSTRUCTED, &p->flags) )
|
||||
@@ -514,16 +517,18 @@ int final_setup_guestos(struct task_struct *p, dom0_builddomain_t *builddomain)
|
||||
if ( builddomain->ctxt.flags & ECF_I387_VALID )
|
||||
set_bit(PF_DONEFPUINIT, &p->flags);
|
||||
memcpy(&p->shared_info->execution_context,
|
||||
&builddomain->ctxt.i386_ctxt,
|
||||
&builddomain->ctxt.cpu_ctxt,
|
||||
sizeof(p->shared_info->execution_context));
|
||||
memcpy(&p->thread.i387,
|
||||
&builddomain->ctxt.i387_ctxt,
|
||||
&builddomain->ctxt.fpu_ctxt,
|
||||
sizeof(p->thread.i387));
|
||||
memcpy(p->thread.traps,
|
||||
&builddomain->ctxt.trap_ctxt,
|
||||
sizeof(p->thread.traps));
|
||||
#ifdef ARCH_HAS_FAST_TRAP
|
||||
SET_DEFAULT_FAST_TRAP(&p->thread);
|
||||
(void)set_fast_trap(p, builddomain->ctxt.fast_trap_idx);
|
||||
#endif
|
||||
p->mm.ldt_base = builddomain->ctxt.ldt_base;
|
||||
p->mm.ldt_ents = builddomain->ctxt.ldt_ents;
|
||||
SET_GDT_ENTRIES(p, DEFAULT_GDT_ENTRIES);
|
||||
@@ -532,8 +537,8 @@ int final_setup_guestos(struct task_struct *p, dom0_builddomain_t *builddomain)
|
||||
(void)set_gdt(p,
|
||||
builddomain->ctxt.gdt_frames,
|
||||
builddomain->ctxt.gdt_ents);
|
||||
p->thread.ss1 = builddomain->ctxt.ring1_ss;
|
||||
p->thread.esp1 = builddomain->ctxt.ring1_esp;
|
||||
p->thread.guestos_ss = builddomain->ctxt.guestos_ss;
|
||||
p->thread.guestos_sp = builddomain->ctxt.guestos_esp;
|
||||
for ( i = 0; i < 8; i++ )
|
||||
(void)set_debugreg(p, i, builddomain->ctxt.debugreg[i]);
|
||||
p->event_selector = builddomain->ctxt.event_callback_cs;
|
||||
@@ -541,10 +546,10 @@ int final_setup_guestos(struct task_struct *p, dom0_builddomain_t *builddomain)
|
||||
p->failsafe_selector = builddomain->ctxt.failsafe_callback_cs;
|
||||
p->failsafe_address = builddomain->ctxt.failsafe_callback_eip;
|
||||
|
||||
phys_l2tab = builddomain->ctxt.pt_base;
|
||||
p->mm.pagetable = mk_pagetable(phys_l2tab);
|
||||
get_page_and_type(&frame_table[phys_l2tab>>PAGE_SHIFT], p,
|
||||
PGT_l2_page_table);
|
||||
phys_basetab = builddomain->ctxt.pt_base;
|
||||
p->mm.pagetable = mk_pagetable(phys_basetab);
|
||||
get_page_and_type(&frame_table[phys_basetab>>PAGE_SHIFT], p,
|
||||
PGT_base_page_table);
|
||||
|
||||
/* Set up the shared info structure. */
|
||||
update_dom_time(p->shared_info);
|
||||
@@ -620,6 +625,7 @@ int setup_guestos(struct task_struct *p, dom0_createdomain_t *params,
|
||||
if ( strncmp(data_start, "XenoGues", 8) )
|
||||
{
|
||||
printk("DOM%llu: Invalid guest OS image\n", dom);
|
||||
unmap_domain_mem(data_start);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -628,12 +634,14 @@ int setup_guestos(struct task_struct *p, dom0_createdomain_t *params,
|
||||
{
|
||||
printk("DOM%llu: Guest OS load address not page-aligned (%08lx)\n",
|
||||
dom, virt_load_address);
|
||||
unmap_domain_mem(data_start);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( alloc_new_dom_mem(p, params->memory_kb) )
|
||||
{
|
||||
printk("DOM%llu: Not enough memory --- reduce dom0_mem ??\n", dom);
|
||||
unmap_domain_mem(data_start);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@@ -650,6 +658,7 @@ int setup_guestos(struct task_struct *p, dom0_createdomain_t *params,
|
||||
dom, data_len>>20,
|
||||
(params->memory_kb)>>11,
|
||||
(params->memory_kb)>>10);
|
||||
unmap_domain_mem(data_start);
|
||||
free_all_dom_mem(p);
|
||||
return -1;
|
||||
}
|
||||
@@ -664,11 +673,11 @@ int setup_guestos(struct task_struct *p, dom0_createdomain_t *params,
|
||||
* We're basically forcing default RPLs to 1, so that our "what privilege
|
||||
* level are we returning to?" logic works.
|
||||
*/
|
||||
p->failsafe_selector = FLAT_RING1_CS;
|
||||
p->event_selector = FLAT_RING1_CS;
|
||||
p->thread.ss1 = FLAT_RING1_DS;
|
||||
p->failsafe_selector = FLAT_GUESTOS_CS;
|
||||
p->event_selector = FLAT_GUESTOS_CS;
|
||||
p->thread.guestos_ss = FLAT_GUESTOS_DS;
|
||||
for ( i = 0; i < 256; i++ )
|
||||
p->thread.traps[i].cs = FLAT_RING1_CS;
|
||||
p->thread.traps[i].cs = FLAT_GUESTOS_CS;
|
||||
|
||||
/*
|
||||
* WARNING: The new domain must have its 'processor' field
|
||||
@@ -770,11 +779,11 @@ int setup_guestos(struct task_struct *p, dom0_createdomain_t *params,
|
||||
src++;
|
||||
if ( (((unsigned long)src) & (PAGE_SIZE-1)) == 0 )
|
||||
{
|
||||
unmap_domain_mem( vsrc-1 );
|
||||
vsrc = map_domain_mem( (unsigned long)src );
|
||||
unmap_domain_mem(vsrc-1);
|
||||
vsrc = map_domain_mem((unsigned long)src);
|
||||
}
|
||||
}
|
||||
unmap_domain_mem( vsrc );
|
||||
unmap_domain_mem(vsrc);
|
||||
|
||||
/* Set up start info area. */
|
||||
memset(virt_startinfo_address, 0, sizeof(*virt_startinfo_address));
|
||||
|
||||
+10
-4
@@ -190,16 +190,22 @@ void cmain(unsigned long magic, multiboot_info_t *mbi)
|
||||
for ( ; ; ) ;
|
||||
}
|
||||
|
||||
max_page = (mbi->mem_upper+1024) >> (PAGE_SHIFT - 10);
|
||||
|
||||
/* The array of pfn_info structures must fit into the reserved area. */
|
||||
if ( sizeof(struct pfn_info) > 24 )
|
||||
if ( (sizeof(struct pfn_info) * max_page) >
|
||||
(FRAMETABLE_VIRT_END - FRAMETABLE_VIRT_START) )
|
||||
{
|
||||
printk("'struct pfn_info' too large to fit in Xen address space!\n");
|
||||
for ( ; ; ) ;
|
||||
unsigned long new_max =
|
||||
(FRAMETABLE_VIRT_END - FRAMETABLE_VIRT_START) /
|
||||
sizeof(struct pfn_info);
|
||||
printk("Truncating available memory to %lu/%luMB\n",
|
||||
new_max >> (20 - PAGE_SHIFT), max_page >> (20 - PAGE_SHIFT));
|
||||
max_page = new_max;
|
||||
}
|
||||
|
||||
set_current(&idle0_task);
|
||||
|
||||
max_page = (mbi->mem_upper+1024) >> (PAGE_SHIFT - 10);
|
||||
init_frametable(max_page);
|
||||
printk("Initialised all memory on a %luMB machine\n",
|
||||
max_page >> (20-PAGE_SHIFT));
|
||||
|
||||
+16
-136
@@ -2,125 +2,6 @@
|
||||
#include <xeno/ctype.h>
|
||||
#include <xeno/lib.h>
|
||||
|
||||
#if 0 // jws - now in string.c, string.h, asm/string.h
|
||||
int memcmp(const void * cs,const void * ct,size_t count)
|
||||
{
|
||||
const unsigned char *su1, *su2;
|
||||
signed char res = 0;
|
||||
|
||||
for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
|
||||
if ((res = *su1 - *su2) != 0)
|
||||
break;
|
||||
return res;
|
||||
}
|
||||
|
||||
void * memcpy(void * dest,const void *src,size_t count)
|
||||
{
|
||||
char *tmp = (char *) dest, *s = (char *) src;
|
||||
|
||||
while (count--)
|
||||
*tmp++ = *s++;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
int strncmp(const char * cs,const char * ct,size_t count)
|
||||
{
|
||||
register signed char __res = 0;
|
||||
|
||||
while (count) {
|
||||
if ((__res = *cs - *ct++) != 0 || !*cs++)
|
||||
break;
|
||||
count--;
|
||||
}
|
||||
|
||||
return __res;
|
||||
}
|
||||
|
||||
int strcmp(const char * cs,const char * ct)
|
||||
{
|
||||
register signed char __res;
|
||||
|
||||
while (1) {
|
||||
if ((__res = *cs - *ct++) != 0 || !*cs++)
|
||||
break;
|
||||
}
|
||||
|
||||
return __res;
|
||||
}
|
||||
|
||||
char * strcpy(char * dest,const char *src)
|
||||
{
|
||||
char *tmp = dest;
|
||||
|
||||
while ((*dest++ = *src++) != '\0')
|
||||
/* nothing */;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
char * strncpy(char * dest,const char *src,size_t count)
|
||||
{
|
||||
char *tmp = dest;
|
||||
|
||||
while (count-- && (*dest++ = *src++) != '\0')
|
||||
/* nothing */;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void * memset(void * s,int c,size_t count)
|
||||
{
|
||||
char *xs = (char *) s;
|
||||
|
||||
while (count--)
|
||||
*xs++ = c;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
size_t strnlen(const char * s, size_t count)
|
||||
{
|
||||
const char *sc;
|
||||
|
||||
for (sc = s; count-- && *sc != '\0'; ++sc)
|
||||
/* nothing */;
|
||||
return sc - s;
|
||||
}
|
||||
|
||||
size_t strlen(const char * s)
|
||||
{
|
||||
const char *sc;
|
||||
|
||||
for (sc = s; *sc != '\0'; ++sc)
|
||||
/* nothing */;
|
||||
return sc - s;
|
||||
}
|
||||
|
||||
char * strchr(const char * s, int c)
|
||||
{
|
||||
for(; *s != (char) c; ++s)
|
||||
if (*s == '\0')
|
||||
return NULL;
|
||||
return (char *) s;
|
||||
}
|
||||
|
||||
char * strstr(const char * s1,const char * s2)
|
||||
{
|
||||
int l1, l2;
|
||||
|
||||
l2 = strlen(s2);
|
||||
if (!l2)
|
||||
return (char *) s1;
|
||||
l1 = strlen(s1);
|
||||
while (l1 >= l2) {
|
||||
l1--;
|
||||
if (!memcmp(s1,s2,l2))
|
||||
return (char *) s1;
|
||||
s1++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* for inc/ctype.h */
|
||||
unsigned char _ctype[] = {
|
||||
@@ -213,6 +94,7 @@ unsigned char *quad_to_str(unsigned long q, unsigned char *s)
|
||||
|
||||
#include <asm/types.h>
|
||||
|
||||
#if BITS_PER_LONG == 32
|
||||
|
||||
/*
|
||||
* Depending on the desired operation, we view a `long long' (aka quad_t) in
|
||||
@@ -526,7 +408,7 @@ __udivdi3(a, b)
|
||||
return (__qdivrem(a, b, (u64 *)0));
|
||||
}
|
||||
|
||||
|
||||
#endif /* BITS_PER_LONG == 32 */
|
||||
|
||||
|
||||
/* HASH/RANDOMISATION FUNCTION
|
||||
@@ -535,8 +417,6 @@ __udivdi3(a, b)
|
||||
* See http://burlteburtle.net/bob/hash/evahash.html
|
||||
*/
|
||||
|
||||
typedef unsigned long ub4;
|
||||
|
||||
#define mix(a,b,c) \
|
||||
do { \
|
||||
a -= b; a -= c; a ^= (c>>13); \
|
||||
@@ -550,9 +430,9 @@ typedef unsigned long ub4;
|
||||
c -= a; c -= b; c = (c ^ (b>>15)) & 0xffffffff; \
|
||||
} while ( 0 )
|
||||
|
||||
unsigned long hash(unsigned char *k, unsigned long len)
|
||||
u32 hash(unsigned char *k, unsigned long len)
|
||||
{
|
||||
unsigned long a, b, c, l;
|
||||
u32 a, b, c, l;
|
||||
|
||||
l = len;
|
||||
a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
|
||||
@@ -560,9 +440,9 @@ unsigned long hash(unsigned char *k, unsigned long len)
|
||||
|
||||
while ( l >= 12 )
|
||||
{
|
||||
a += (k[0] + ((ub4)k[1]<<8) + ((ub4)k[2]<<16) + ((ub4)k[3]<<24));
|
||||
b += (k[4] + ((ub4)k[5]<<8) + ((ub4)k[6]<<16) + ((ub4)k[7]<<24));
|
||||
c += (k[8] + ((ub4)k[9]<<8) + ((ub4)k[10]<<16) + ((ub4)k[11]<<24));
|
||||
a += (k[0] + ((u32)k[1]<<8) + ((u32)k[2]<<16) + ((u32)k[3]<<24));
|
||||
b += (k[4] + ((u32)k[5]<<8) + ((u32)k[6]<<16) + ((u32)k[7]<<24));
|
||||
c += (k[8] + ((u32)k[9]<<8) + ((u32)k[10]<<16) + ((u32)k[11]<<24));
|
||||
mix(a,b,c);
|
||||
k += 12; l -= 12;
|
||||
}
|
||||
@@ -570,17 +450,17 @@ unsigned long hash(unsigned char *k, unsigned long len)
|
||||
c += len;
|
||||
switch ( l )
|
||||
{
|
||||
case 11: c+=((ub4)k[10]<<24);
|
||||
case 10: c+=((ub4)k[9]<<16);
|
||||
case 9 : c+=((ub4)k[8]<<8);
|
||||
case 11: c+=((u32)k[10]<<24);
|
||||
case 10: c+=((u32)k[9]<<16);
|
||||
case 9 : c+=((u32)k[8]<<8);
|
||||
/* the first byte of c is reserved for the length */
|
||||
case 8 : b+=((ub4)k[7]<<24);
|
||||
case 7 : b+=((ub4)k[6]<<16);
|
||||
case 6 : b+=((ub4)k[5]<<8);
|
||||
case 8 : b+=((u32)k[7]<<24);
|
||||
case 7 : b+=((u32)k[6]<<16);
|
||||
case 6 : b+=((u32)k[5]<<8);
|
||||
case 5 : b+=k[4];
|
||||
case 4 : a+=((ub4)k[3]<<24);
|
||||
case 3 : a+=((ub4)k[2]<<16);
|
||||
case 2 : a+=((ub4)k[1]<<8);
|
||||
case 4 : a+=((u32)k[3]<<24);
|
||||
case 3 : a+=((u32)k[2]<<16);
|
||||
case 2 : a+=((u32)k[1]<<8);
|
||||
case 1 : a+=k[0];
|
||||
/* case 0: nothing left to add */
|
||||
}
|
||||
|
||||
@@ -118,6 +118,8 @@
|
||||
SYMBOL_NAME_LABEL(name)
|
||||
#endif
|
||||
|
||||
#define PGT_base_page_table PGT_l2_page_table
|
||||
|
||||
#define barrier() __asm__ __volatile__("": : :"memory")
|
||||
|
||||
#define __HYPERVISOR_CS 0x0808
|
||||
|
||||
@@ -354,7 +354,7 @@ struct tss_struct {
|
||||
};
|
||||
|
||||
struct thread_struct {
|
||||
unsigned long esp1, ss1;
|
||||
unsigned long guestos_sp, guestos_ss;
|
||||
/* Hardware debugging registers */
|
||||
unsigned long debugreg[8]; /* %%db0-7 debug registers */
|
||||
/* floating point info */
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
typedef unsigned short umode_t;
|
||||
|
||||
typedef unsigned int size_t;
|
||||
|
||||
/*
|
||||
* __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
|
||||
* header files exported to user space
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef __ARCH_I386_ATOMIC__
|
||||
#define __ARCH_I386_ATOMIC__
|
||||
#ifndef __ARCH_X86_64_ATOMIC__
|
||||
#define __ARCH_X86_64_ATOMIC__
|
||||
|
||||
#include <xeno/config.h>
|
||||
|
||||
@@ -202,4 +202,4 @@ __asm__ __volatile__(LOCK "orl %0,%1" \
|
||||
#define smp_mb__before_atomic_inc() barrier()
|
||||
#define smp_mb__after_atomic_inc() barrier()
|
||||
|
||||
#endif
|
||||
#endif /* __ARCH_X86_64_ATOMIC__ */
|
||||
+193
-52
@@ -2,12 +2,14 @@
|
||||
* config.h
|
||||
*
|
||||
* A Linux-style configuration list.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __XENO_X86_64_CONFIG_H__
|
||||
#define __XENO_X86_64_CONFIG_H__
|
||||
|
||||
#define CONFIG_X86 1
|
||||
#define CONFIG_X86 1
|
||||
#define CONFIG_X86_64BITMODE 1
|
||||
|
||||
#define CONFIG_SMP 1
|
||||
#define CONFIG_X86_LOCAL_APIC 1
|
||||
@@ -53,63 +55,200 @@
|
||||
#define __cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES)))
|
||||
#define ____cacheline_aligned __cacheline_aligned
|
||||
|
||||
/*
|
||||
* Virtual addresses beyond this are not modifiable by guest OSes. The
|
||||
* machine->physical mapping table starts at this address, read-only.
|
||||
*/
|
||||
#define HYPERVISOR_VIRT_START (0xFFFF800000000000ULL)
|
||||
|
||||
/*
|
||||
* Xen exists in the highest 2GB of address space for RIP-relative
|
||||
* addressing
|
||||
*/
|
||||
#define XEN_VIRT_START (0xFFFFFFFF80000000ULL)
|
||||
|
||||
/*
|
||||
* First 4MB are mapped read-only for all. It's for the machine->physical
|
||||
* mapping table (MPT table). The following are virtual addresses.
|
||||
*/
|
||||
#define READONLY_MPT_VIRT_START (HYPERVISOR_VIRT_START)
|
||||
#define READONLY_MPT_VIRT_END (READONLY_MPT_VIRT_START + (4*1024*1024))
|
||||
/*
|
||||
* Next 16MB is fixed monitor space, which is part of a 44MB direct-mapped
|
||||
* memory region. The following are machine addresses.
|
||||
*/
|
||||
#define MAX_MONITOR_ADDRESS (16*1024*1024)
|
||||
#define MAX_DMA_ADDRESS (16*1024*1024)
|
||||
#define MAX_DIRECTMAP_ADDRESS (44*1024*1024)
|
||||
/* And the virtual addresses for the direct-map region... */
|
||||
#define DIRECTMAP_VIRT_START (READONLY_MPT_VIRT_END)
|
||||
#define DIRECTMAP_VIRT_END (DIRECTMAP_VIRT_START + MAX_DIRECTMAP_ADDRESS)
|
||||
#define MONITOR_VIRT_START (DIRECTMAP_VIRT_START)
|
||||
#define MONITOR_VIRT_END (MONITOR_VIRT_START + MAX_MONITOR_ADDRESS)
|
||||
#define RDWR_MPT_VIRT_START (MONITOR_VIRT_END)
|
||||
#define RDWR_MPT_VIRT_END (RDWR_MPT_VIRT_START + (4*1024*1024))
|
||||
#define FRAMETABLE_VIRT_START (RDWR_MPT_VIRT_END)
|
||||
#define FRAMETABLE_VIRT_END (DIRECTMAP_VIRT_END)
|
||||
/* Next 4MB of virtual address space is used as a linear p.t. mapping. */
|
||||
#define LINEAR_PT_VIRT_START (DIRECTMAP_VIRT_END)
|
||||
#define LINEAR_PT_VIRT_END (LINEAR_PT_VIRT_START + (4*1024*1024))
|
||||
/* Next 4MB of virtual address space used for per-domain mappings (eg. GDT). */
|
||||
#define PERDOMAIN_VIRT_START (LINEAR_PT_VIRT_END)
|
||||
#define PERDOMAIN_VIRT_END (PERDOMAIN_VIRT_START + (4*1024*1024))
|
||||
#define GDT_VIRT_START (PERDOMAIN_VIRT_START)
|
||||
#define GDT_VIRT_END (GDT_VIRT_START + (64*1024))
|
||||
#define LDT_VIRT_START (GDT_VIRT_END)
|
||||
#define LDT_VIRT_END (LDT_VIRT_START + (64*1024))
|
||||
/* Penultimate 4MB of virtual address space used for domain page mappings. */
|
||||
#define MAPCACHE_VIRT_START (PERDOMAIN_VIRT_END)
|
||||
#define MAPCACHE_VIRT_END (MAPCACHE_VIRT_START + (4*1024*1024))
|
||||
/* Final 4MB of virtual address space used for ioremap(). */
|
||||
#define IOREMAP_VIRT_START (MAPCACHE_VIRT_END)
|
||||
#define IOREMAP_VIRT_END (IOREMAP_VIRT_START + (4*1024*1024))
|
||||
#define PHYSICAL_ADDRESS_BITS 52
|
||||
#define MAX_PHYSICAL_ADDRESS (1 << PHYSICAL_ADDRESS_BITS)
|
||||
#define VIRTUAL_ADDRESS_BITS 48
|
||||
#define XEN_PAGE_SIZE 4096
|
||||
|
||||
#define PTE_SIZE 8
|
||||
#define TOTAL_PTES (512ULL * 512 * 512 * 512)
|
||||
|
||||
/* next PML4 from an _END address */
|
||||
#define PML4_BITS 39
|
||||
#define PML4_SPACE (1ULL << PML4_BITS)
|
||||
|
||||
/*
|
||||
* Amount of slack domain memory to leave in system, in megabytes.
|
||||
* Memory layout
|
||||
*
|
||||
* 0x0000000000000000 - 0x00007fffffffffff Guest & user apps (128TB)
|
||||
* (Only for 32-bit guests)
|
||||
* 0x00000000fc000000 - 0x00000000fc3fffff Machine/Physical 32-bit shadow (4MB)
|
||||
* 0x00000000fc400000 - 0x00000000feffffff IO remap for 32-bit guests (44MB)
|
||||
* 0x00000000ff000000 - 0x00000000ff3fffff 32-bit PTE shadow (4MB)
|
||||
*
|
||||
* 0xffff800000000000 - 0xffff807fffffffff Linear page table (512GB)
|
||||
* 0xffff808000000000 - 0xffff80ffffffffff Reserved for shadow page table (512GB)
|
||||
*
|
||||
* 0xffff810000000000 - 0xffff82ffffffffff Xen PML4 slots
|
||||
* 0xffff810000000000 - 0xffff81003fffffff Xen hypervisor virtual space (1GB)
|
||||
* 0xffff810040000000 - 0xffff81807fffffff Per-domain mappings (1GB)
|
||||
* 0xffff810080000000 - 0xffff81387fffffff R/O physical map (224GB)
|
||||
* 0xffff813880000000 - 0xffff81707fffffff R/W physical map (224GB)
|
||||
* 0xffff817080000000 - 0xffff82c07fffffff Frame table (1344GB)
|
||||
* 0xffff82c080000000 - 0xffff82c0bfffffff I/O remap space (1GB)
|
||||
* 0xffff82c0c0000000 - 0xffff82ffffffffff (253GB)
|
||||
*
|
||||
* 0xffff830000000000 - 0xffff87ffffffffff RESERVED (5TB)
|
||||
*
|
||||
* 0xffff880000000000 - ... Physical 1:1 direct mapping (112TB max)
|
||||
* 0xffff880000000000 - 0xffff880001000000 Low memory DMA region (16M)
|
||||
*
|
||||
* 0xfffff80000000000 - 0xffffffffffffffff Reserved for guest (8TB)
|
||||
*
|
||||
* The requirement that we have a 1:1 map of physical memory limits
|
||||
* the maximum memory size we can support. With only 48 virtual address
|
||||
* bits, and the assumption that guests will run users in positive address
|
||||
* space, a contiguous 1:1 map can only live in the negative address space.
|
||||
* Since we don't want to bump guests out of the very top of memory and
|
||||
* force relocation, we can't use this entire space, and Xen has several
|
||||
* heavy mapping that require PML4 slices. Just to be safe, we reserve
|
||||
* 16 PML4s each for Xen and the guest. 224 PML4s give us 112 terabytes
|
||||
* of addressable memory. Any high device physical addresses beyond this
|
||||
* region can be mapped into the IO remap space or some of the reserved
|
||||
* 6TB region.
|
||||
*
|
||||
* 112 TB is just 16 TB shy of the maximum physical memory supported
|
||||
* on Linux 2.6.0, and should be enough for anybody.
|
||||
*
|
||||
* There are some additional constraints in the memory layout that require
|
||||
* several changes from the i386 architecture.
|
||||
*
|
||||
* ACPI data and ACPI non-volatile storage must be placed in some region
|
||||
* of memory below the 4GB mark. Depending on the BIOS and system, we
|
||||
* may have this located as low as 1GB. This means allocating large
|
||||
* chunks of physically contiguous memory from the direct mapping may not
|
||||
* be possible.
|
||||
*
|
||||
* The full frame table for 112TB of physical memory currently occupies
|
||||
* 1344GB space. This clearly can not be allocated in physically contiguous
|
||||
* space, so it must be moved to a virtual address.
|
||||
*
|
||||
* Both copies of the machine->physical table must also be relocated.
|
||||
* (112 TB / 4k) * 8 bytes means that each copy of the physical map requires
|
||||
* 224GB of space, thus it also must move to VM space.
|
||||
*
|
||||
* The physical pages used to allocate the page tables for the direct 1:1
|
||||
* map may occupy (112TB / 2M) * 8 bytes = 448MB. This is almost guaranteed
|
||||
* to fit in contiguous physical memory, but these pages used to be allocated
|
||||
* in the Xen monitor address space. This means the Xen address space must
|
||||
* accomodate up to ~500 MB, which means it also must move out of the
|
||||
* direct mapped region.
|
||||
*
|
||||
* Since both copies of the MPT, the frame table, and Xen now exist in
|
||||
* purely virtual space, we have the added advantage of being able to
|
||||
* map them to local pages on NUMA machines, or use NUMA aware memory
|
||||
* allocation within Xen itself.
|
||||
*
|
||||
* Additionally, the 1:1 page table now exists contiguously in virtual
|
||||
* space, but may be mapped to physically separated pages, allowing
|
||||
* each node to contain the page tables for its own local memory. Setting
|
||||
* up this mapping presents a bit of a chicken-egg problem, but is possible
|
||||
* as a future enhancement.
|
||||
*
|
||||
* Zachary Amsden (zamsden@cisco.com)
|
||||
*
|
||||
*/
|
||||
|
||||
/* Guest and user space */
|
||||
#define NSPACE_VIRT_START 0
|
||||
#define NSPACE_VIRT_END (1ULL << (VIRTUAL_ADDRESS_BITS - 1))
|
||||
|
||||
/* Priviledged space */
|
||||
#define ESPACE_VIRT_END 0
|
||||
#define ESPACE_VIRT_START (ESPACE_VIRT_END-(1ULL << (VIRTUAL_ADDRESS_BITS-1)))
|
||||
|
||||
/* reservations in e-space */
|
||||
#define GUEST_RESERVED_PML4S 16
|
||||
#define XEN_RESERVED_PML4S 16
|
||||
|
||||
#define MAX_MEMORY_SIZE ((1ULL << (VIRTUAL_ADDRESS_BITS-1)) \
|
||||
-((GUEST_RESERVED_PML4S + XEN_RESERVED_PML4S) * PML4_SPACE))
|
||||
#define MAX_MEMORY_FRAMES (MAX_MEMORY_SIZE / XEN_PAGE_SIZE)
|
||||
|
||||
/*
|
||||
* Virtual addresses beyond this are not modifiable by guest OSes.
|
||||
*/
|
||||
#define HYPERVISOR_VIRT_START ESPACE_VIRT_START
|
||||
#define HYPERVISOR_VIRT_END (ESPACE_VIRT_END-(GUEST_RESERVED_PML4S * PML4_SPACE))
|
||||
|
||||
/* First 512GB of virtual address space is used as a linear p.t. mapping. */
|
||||
#define LINEAR_PT_VIRT_START (HYPERVISOR_VIRT_START)
|
||||
#define LINEAR_PT_VIRT_END (LINEAR_PT_VIRT_START + (PTE_SIZE * TOTAL_PTES))
|
||||
|
||||
/* Reserve some space for a shadow PT mapping */
|
||||
#define SHADOW_PT_VIRT_START (LINEAR_PT_VIRT_END)
|
||||
#define SHADOW_PT_VIRT_END (SHADOW_PT_VIRT_START + (PTE_SIZE * TOTAL_PTES))
|
||||
|
||||
/* Xen exists in the first 1GB of the next PML4 space */
|
||||
#define MAX_MONITOR_ADDRESS (1 * 1024 * 1024 * 1024)
|
||||
#define MONITOR_VIRT_START (SHADOW_PT_VIRT_END)
|
||||
#define MONITOR_VIRT_END (MONITOR_VIRT_START + MAX_MONITOR_ADDRESS)
|
||||
|
||||
/* Next 1GB of virtual address space used for per-domain mappings (eg. GDT). */
|
||||
#define PERDOMAIN_VIRT_START (MONITOR_VIRT_END)
|
||||
#define PERDOMAIN_VIRT_END (PERDOMAIN_VIRT_START + (512 * 512 * 4096))
|
||||
#define GDT_VIRT_START (PERDOMAIN_VIRT_START)
|
||||
#define GDT_VIRT_END (GDT_VIRT_START + (128*1024))
|
||||
#define LDT_VIRT_START (GDT_VIRT_END)
|
||||
#define LDT_VIRT_END (LDT_VIRT_START + (128*1024))
|
||||
|
||||
/*
|
||||
* First set of MPTs are mapped read-only for all. It's for the machine->physical
|
||||
* mapping table (MPT table). The following are virtual addresses.
|
||||
*/
|
||||
#define READONLY_MPT_VIRT_START (PERDOMAIN_VIRT_END)
|
||||
#define READONLY_MPT_VIRT_END (READONLY_MPT_VIRT_START + (PTE_SIZE * MAX_MEMORY_FRAMES))
|
||||
|
||||
/* R/W machine->physical table */
|
||||
#define RDWR_MPT_VIRT_START (READONLY_MPT_VIRT_END)
|
||||
#define RDWR_MPT_VIRT_END (RDWR_MPT_VIRT_START + (PTE_SIZE * MAX_MEMORY_FRAMES))
|
||||
|
||||
/* Frame table */
|
||||
#define FRAMETABLE_ENTRY_SIZE (48)
|
||||
#define FRAMETABLE_VIRT_START (RDWR_MPT_VIRT_END)
|
||||
#define FRAMETABLE_VIRT_END (FRAMETABLE_VIRT_START + (FRAMETABLE_ENTRY_SIZE * MAX_MEMORY_FRAMES))
|
||||
|
||||
/* Next 1GB of virtual address space used for ioremap(). */
|
||||
#define IOREMAP_VIRT_START (FRAMETABLE_VIRT_END)
|
||||
#define IOREMAP_VIRT_END (IOREMAP_VIRT_START + (512 * 512 * 4096))
|
||||
|
||||
/* And the virtual addresses for the direct-map region... */
|
||||
#define DIRECTMAP_VIRT_START (ESPACE_VIRT_START + (XEN_RESERVED_PML4S * PML4_SPACE))
|
||||
#define DIRECTMAP_VIRT_END (DIRECTMAP_VIRT_START + MAX_DIRECTMAP_ADDRESS)
|
||||
|
||||
/*
|
||||
* Next is the direct-mapped memory region. The following are machine addresses.
|
||||
*/
|
||||
#define MAX_DMA_ADDRESS (16*1024*1024)
|
||||
#define MAX_DIRECTMAP_ADDRESS MAX_MEMORY_SIZE
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Amount of slack domain memory to leave in system, in kilobytes.
|
||||
* Prevents a hard out-of-memory crunch for thinsg like network receive.
|
||||
*/
|
||||
#define SLACK_DOMAIN_MEM_KILOBYTES 2048
|
||||
|
||||
|
||||
/*
|
||||
* These will probably change in the future..
|
||||
* locations for 32-bit guest compatibility mappings
|
||||
*/
|
||||
|
||||
/* 4M of 32-bit machine-physical shadow in low 4G of VM space */
|
||||
#define SHADOW_MPT32_VIRT_START (0xfc000000)
|
||||
#define SHADOW_MPT32_VIRT_END (SHADOW_MPT32_VIRT_START + (4 * 1024 * 1024))
|
||||
|
||||
/* 44M of I/O remap for 32-bit drivers */
|
||||
#define IOREMAP_LOW_VIRT_START (SHADOW_MPT32_VIRT_END)
|
||||
#define IOREMAP_LOW_VIRT_END (IOREMAP_LOW_VIRT_START + (44 * 1024 * 1024))
|
||||
|
||||
/* 4M of 32-bit page table */
|
||||
#define SHADOW_PT32_VIRT_START (IOREMAP_LOW_VIRT_END)
|
||||
#define SHADOW_PT32_VIRT_END (SHADOW_PT32_VIRT_START + (4 * 1024 * 1024))
|
||||
|
||||
|
||||
/* Linkage for x86 */
|
||||
#define FASTCALL(x) x __attribute__((regparm(3)))
|
||||
#define asmlinkage __attribute__((regparm(0)))
|
||||
@@ -127,6 +266,8 @@
|
||||
SYMBOL_NAME_LABEL(name)
|
||||
#endif
|
||||
|
||||
#define PGT_base_page_table PGT_l4_page_table
|
||||
|
||||
#define barrier() __asm__ __volatile__("": : :"memory")
|
||||
|
||||
/*
|
||||
|
||||
@@ -26,7 +26,7 @@ static inline void set_current(struct task_struct *p)
|
||||
static inline execution_context_t *get_execution_context(void)
|
||||
{
|
||||
execution_context_t *execution_context;
|
||||
__asm__( "andq %%rsp,%0; addl %2,%0"
|
||||
__asm__( "andq %%rsp,%0; addq %2,%0"
|
||||
: "=r" (execution_context)
|
||||
: "0" (~(STACK_SIZE-1)), "i" (STACK_SIZE-STACK_RESERVED) );
|
||||
return execution_context;
|
||||
@@ -42,7 +42,7 @@ static inline unsigned long get_stack_top(void)
|
||||
|
||||
#define schedule_tail(_p) \
|
||||
__asm__ __volatile__ ( \
|
||||
"andq %%rsp,%0; addq %2,%0; movl %0,%%rsp; jmp *%1" \
|
||||
"andq %%rsp,%0; addq %2,%0; movq %0,%%rsp; jmp *%1" \
|
||||
: : "r" (~(STACK_SIZE-1)), \
|
||||
"r" (unlikely(is_idle_task((_p))) ? \
|
||||
continue_cpu_idle_loop : \
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#define __FIRST_PER_CPU_ENTRY (FIRST_RESERVED_GDT_ENTRY + 8)
|
||||
|
||||
#define __CPU_DESC_INDEX(x,field) \
|
||||
((x) * sizeof(struct per_cpu_gdt) + offsetof(struct per_cpu_gdt, field) + (FIRST_PER_CPU_ENTRY*8))
|
||||
((x) * sizeof(struct per_cpu_gdt) + offsetof(struct per_cpu_gdt, field) + (__FIRST_PER_CPU_ENTRY*8))
|
||||
#define __LDT(n) (((n)<<1) + __FIRST_LDT_ENTRY)
|
||||
|
||||
#define load_TR(cpu) asm volatile("ltr %w0"::"r" (__CPU_DESC_INDEX(cpu, tss)));
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define _ASM_IO_H
|
||||
|
||||
#include <xeno/config.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
/*
|
||||
* This file contains the definitions for the x86 IO instructions
|
||||
@@ -139,9 +140,12 @@ extern inline void * phys_to_virt(unsigned long address)
|
||||
#ifdef CONFIG_DISCONTIGMEM
|
||||
#include <asm/mmzone.h>
|
||||
#else
|
||||
#define page_to_phys(page) (((page) - frame_table) << PAGE_SHIFT)
|
||||
#define page_to_phys(page) (((page) - frame_table) << PAGE_SHIFT)
|
||||
#endif
|
||||
|
||||
#define page_to_pfn(page) ((unsigned long)((_page) - frame_table))
|
||||
#define page_to_virt(page) (phys_to_virt(page_to_phys(_page)))
|
||||
|
||||
extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
|
||||
|
||||
extern inline void * ioremap (unsigned long offset, unsigned long size)
|
||||
|
||||
@@ -9,7 +9,7 @@ static inline void load_LDT(struct task_struct *p)
|
||||
|
||||
if ( (ents = p->mm.ldt_ents) == 0 )
|
||||
{
|
||||
__asm__ __volatile__ ( "lldt %%rax" : : "a" (0) );
|
||||
__asm__ __volatile__ ( "lldt %w0" : : "r" (0) );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -17,17 +17,17 @@ static inline void load_LDT(struct task_struct *p)
|
||||
struct ldttss_desc *desc;
|
||||
|
||||
cpu = smp_processor_id();
|
||||
desc = (struct desc_struct *)((char *)GET_GDT_ADDRESS(p) + __CPU_DESC_INDEX(cpu, ldt));
|
||||
desc = (struct ldttss_desc *)((char *)GET_GDT_ADDRESS(p) + __CPU_DESC_INDEX(cpu, ldt));
|
||||
desc->limit0 = ents*8-1;
|
||||
desc->base0 = LDT_VIRT_START&0xffff;
|
||||
desc->base1 = (LDT_VIRT_START&0xff0000)>>16;
|
||||
desc->type = DESC_LDT;
|
||||
desc->dpl = 0;
|
||||
desc->p = 1;
|
||||
desc->limit = 0;
|
||||
desc->limit1 = 0;
|
||||
desc->zero0 = 0;
|
||||
desc->g = 0;
|
||||
desc->base2 = (LDT_VIRST_START&0xff000000)>>24;
|
||||
desc->base2 = (LDT_VIRT_START&0xff000000)>>24;
|
||||
desc->base3 = LDT_VIRT_START>>32;
|
||||
desc->zero1 = 0;
|
||||
__load_LDT(cpu);
|
||||
|
||||
@@ -265,7 +265,6 @@ struct bug_frame {
|
||||
#ifndef CONFIG_DISCONTIGMEM
|
||||
#define virt_to_page(kaddr) (frame_table + (__pa(kaddr) >> PAGE_SHIFT))
|
||||
#define pfn_to_page(pfn) (frame_table + (pfn))
|
||||
#define page_to_pfn(page) ((page) - frame_table)
|
||||
#define page_address(_p) (__va(((_p) - frame_table) << PAGE_SHIFT))
|
||||
#define VALID_PAGE(page) (((page) - frame_table) < max_mapnr)
|
||||
#endif
|
||||
|
||||
@@ -27,10 +27,8 @@ int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq);
|
||||
#include <xeno/types.h>
|
||||
#include <xeno/slab.h>
|
||||
#include <asm/scatterlist.h>
|
||||
/*#include <xeno/string.h>*/
|
||||
#include <asm/io.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/mmzone.h>
|
||||
|
||||
struct pci_dev;
|
||||
extern int force_mmu;
|
||||
@@ -96,14 +94,16 @@ static inline void pci_dma_sync_single(struct pci_dev *hwdev,
|
||||
dma_addr_t dma_handle,
|
||||
size_t size, int direction)
|
||||
{
|
||||
BUG_ON(direction == PCI_DMA_NONE);
|
||||
if (direction == PCI_DMA_NONE)
|
||||
out_of_line_bug();
|
||||
}
|
||||
|
||||
static inline void pci_dma_sync_sg(struct pci_dev *hwdev,
|
||||
struct scatterlist *sg,
|
||||
int nelems, int direction)
|
||||
{
|
||||
BUG_ON(direction == PCI_DMA_NONE);
|
||||
if (direction == PCI_DMA_NONE)
|
||||
out_of_line_bug();
|
||||
}
|
||||
|
||||
/* The PCI address space does equal the physical memory
|
||||
@@ -162,6 +162,19 @@ static inline dma_addr_t pci_map_page(struct pci_dev *hwdev, struct pfn_info *pa
|
||||
|
||||
#define BAD_DMA_ADDRESS (-1UL)
|
||||
|
||||
|
||||
/* Unmap a set of streaming mode DMA translations.
|
||||
* Again, cpu read rules concerning calls here are the same as for
|
||||
* pci_unmap_single() above.
|
||||
*/
|
||||
static inline void pci_unmap_sg(struct pci_dev *dev, struct scatterlist *sg,
|
||||
int nents, int dir)
|
||||
{
|
||||
if (dir == PCI_DMA_NONE)
|
||||
out_of_line_bug();
|
||||
}
|
||||
|
||||
|
||||
/* Map a set of buffers described by scatterlist in streaming
|
||||
* mode for DMA. This is the scather-gather version of the
|
||||
* above pci_map_single interface. Here the scatter gather list
|
||||
@@ -181,18 +194,20 @@ static inline int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
|
||||
int nents, int direction)
|
||||
{
|
||||
int i;
|
||||
|
||||
BUG_ON(direction == PCI_DMA_NONE);
|
||||
|
||||
|
||||
if (direction == PCI_DMA_NONE)
|
||||
out_of_line_bug();
|
||||
|
||||
/*
|
||||
* temporary 2.4 hack
|
||||
*/
|
||||
for (i = 0; i < nents; i++ ) {
|
||||
struct scatterlist *s = &sg[i];
|
||||
void *addr = s->address;
|
||||
if (addr)
|
||||
BUG_ON(s->page || s->offset);
|
||||
else if (s->page)
|
||||
if (addr) {
|
||||
if (s->page || s->offset)
|
||||
out_of_line_bug();
|
||||
} else if (s->page)
|
||||
addr = page_address(s->page) + s->offset;
|
||||
#if 0
|
||||
/* Invalid check, since address==0 is valid. */
|
||||
@@ -209,17 +224,6 @@ static inline int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
|
||||
pci_unmap_sg(hwdev, sg, i, direction);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unmap a set of streaming mode DMA translations.
|
||||
* Again, cpu read rules concerning calls here are the same as for
|
||||
* pci_unmap_single() above.
|
||||
*/
|
||||
static inline void pci_unmap_sg(struct pci_dev *dev, struct scatterlist *sg,
|
||||
int nents, int dir)
|
||||
{
|
||||
if (direction == PCI_DMA_NONE)
|
||||
out_of_line_bug();
|
||||
}
|
||||
|
||||
|
||||
/* Make physical memory consistent for a single
|
||||
@@ -259,11 +263,6 @@ static inline void pci_dma_sync_sg(struct pci_dev *hwdev,
|
||||
|
||||
#endif
|
||||
|
||||
extern int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
|
||||
int nents, int direction);
|
||||
extern void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
|
||||
int nents, int direction);
|
||||
|
||||
#define pci_unmap_page pci_unmap_single
|
||||
|
||||
/* Return whether the given PCI device DMA address mask can
|
||||
@@ -297,6 +296,7 @@ pci_dac_page_to_dma(struct pci_dev *pdev, struct pfn_info *page, unsigned long o
|
||||
static __inline__ struct pfn_info *
|
||||
pci_dac_dma_to_page(struct pci_dev *pdev, dma64_addr_t dma_addr)
|
||||
{
|
||||
unsigned long poff = (dma_addr >> PAGE_SHIFT);
|
||||
return frame_table + poff;
|
||||
}
|
||||
|
||||
|
||||
@@ -340,7 +340,8 @@ struct tss_struct {
|
||||
} __attribute__((packed)) ____cacheline_aligned;
|
||||
|
||||
struct thread_struct {
|
||||
unsigned long rsp0;
|
||||
unsigned long guestos_sp;
|
||||
unsigned long guestos_ss;
|
||||
unsigned long rip;
|
||||
unsigned long rsp;
|
||||
unsigned long userrsp; /* Copy from PDA */
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
typedef unsigned short umode_t;
|
||||
|
||||
typedef unsigned long size_t;
|
||||
|
||||
/*
|
||||
* __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
|
||||
* header files exported to user space
|
||||
|
||||
@@ -103,11 +103,11 @@ extern void __get_user_8(void);
|
||||
({ long __val_gu; \
|
||||
int __ret_gu=1; \
|
||||
switch(sizeof (*(ptr))) { \
|
||||
case 1: _ret_gu=copy_from_user(&__val_gu,ptr,1);break; \
|
||||
case 2: _ret_gu=copy_from_user(&__val_gu,ptr,2);break; \
|
||||
case 4: _ret_gu=copy_from_user(&__val_gu,ptr,4);break; \
|
||||
case 8: _ret_gu=copy_from_user(&__val_gu,ptr,8);break; \
|
||||
default: _ret_gu=copy_from_user(&__val_gu,ptr,sizeof(*(ptr)));break;\
|
||||
+ case 1: __ret_gu=copy_from_user(&__val_gu,ptr,1);break; \
|
||||
+ case 2: __ret_gu=copy_from_user(&__val_gu,ptr,2);break; \
|
||||
+ case 4: __ret_gu=copy_from_user(&__val_gu,ptr,4);break; \
|
||||
+ case 8: __ret_gu=copy_from_user(&__val_gu,ptr,8);break; \
|
||||
+ default: __ret_gu=copy_from_user(&__val_gu,ptr,sizeof(*(ptr)));break;\
|
||||
/*case 1: __get_user_x(1,__ret_gu,__val_gu,ptr); break;*/ \
|
||||
/*case 2: __get_user_x(2,__ret_gu,__val_gu,ptr); break;*/ \
|
||||
/*case 4: __get_user_x(4,__ret_gu,__val_gu,ptr); break;*/ \
|
||||
|
||||
@@ -35,6 +35,11 @@
|
||||
#define FLAT_RING3_CS 0x082b /* GDT index 261 */
|
||||
#define FLAT_RING3_DS 0x0833 /* GDT index 262 */
|
||||
|
||||
#define FLAT_GUESTOS_CS FLAT_RING1_CS
|
||||
#define FLAT_GUESTOS_DS FLAT_RING1_DS
|
||||
#define FLAT_USER_CS FLAT_RING3_CS
|
||||
#define FLAT_USER_DS FLAT_RING3_DS
|
||||
|
||||
/* And the trap vector is... */
|
||||
#define TRAP_INSTR "int $0x82"
|
||||
|
||||
@@ -99,13 +104,13 @@ typedef struct full_execution_context_st
|
||||
{
|
||||
#define ECF_I387_VALID (1<<0)
|
||||
unsigned long flags;
|
||||
execution_context_t i386_ctxt; /* User-level CPU registers */
|
||||
char i387_ctxt[256]; /* User-level FPU registers */
|
||||
execution_context_t cpu_ctxt; /* User-level CPU registers */
|
||||
char fpu_ctxt[256]; /* User-level FPU registers */
|
||||
trap_info_t trap_ctxt[256]; /* Virtual IDT */
|
||||
unsigned int fast_trap_idx; /* "Fast trap" vector offset */
|
||||
unsigned long ldt_base, ldt_ents; /* LDT (linear address, # ents) */
|
||||
unsigned long gdt_frames[16], gdt_ents; /* GDT (machine frames, # ents) */
|
||||
unsigned long ring1_ss, ring1_esp; /* Virtual TSS (only SS1/ESP1) */
|
||||
unsigned long guestos_ss, guestos_esp; /* Virtual TSS (only SS1/ESP1) */
|
||||
unsigned long pt_base; /* CR3 (pagetable base) */
|
||||
unsigned long debugreg[8]; /* DB0-DB7 (debug registers) */
|
||||
unsigned long event_callback_cs; /* CS:EIP of event callback */
|
||||
@@ -114,6 +119,8 @@ typedef struct full_execution_context_st
|
||||
unsigned long failsafe_callback_eip;
|
||||
} full_execution_context_t;
|
||||
|
||||
#define ARCH_HAS_FAST_TRAP
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -35,13 +35,20 @@
|
||||
#define FLAT_RING3_CS64 0x082b /* GDT index 261 */
|
||||
#define FLAT_RING3_DS 0x0833 /* GDT index 262 */
|
||||
|
||||
#define FLAT_GUESTOS_DS FLAT_RING3_DS
|
||||
#define FLAT_GUESTOS_CS FLAT_RING3_CS64
|
||||
#define FLAT_GUESTOS_CS32 FLAT_RING3_CS32
|
||||
|
||||
#define FLAT_USER_DS FLAT_RING3_DS
|
||||
#define FLAT_USER_CS FLAT_RING3_CS64
|
||||
#define FLAT_USER_CS32 FLAT_RING3_CS32
|
||||
|
||||
/* And the trap vector is... */
|
||||
#define TRAP_INSTR "syscall"
|
||||
|
||||
|
||||
#ifndef machine_to_phys_mapping
|
||||
#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
|
||||
#define machine_to_phys_mapping ((unsigned long *)0xffff810000000000ULL)
|
||||
#endif
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
@@ -98,13 +105,12 @@ typedef struct full_execution_context_st
|
||||
{
|
||||
#define ECF_I387_VALID (1<<0)
|
||||
unsigned long flags;
|
||||
execution_context_t x86_64_ctxt; /* User-level CPU registers */
|
||||
char i387_ctxt[512]; /* User-level FPU registers */
|
||||
execution_context_t cpu_ctxt; /* User-level CPU registers */
|
||||
char fpu_ctxt[512]; /* User-level FPU registers */
|
||||
trap_info_t trap_ctxt[256]; /* Virtual IDT */
|
||||
unsigned int fast_trap_idx; /* "Fast trap" vector offset */
|
||||
unsigned long ldt_base, ldt_ents; /* LDT (linear address, # ents) */
|
||||
unsigned long gdt_frames[16], gdt_ents; /* GDT (machine frames, # ents) */
|
||||
unsigned long ring1_ss, ring1_esp; /* Virtual TSS (only SS1/ESP1) */
|
||||
unsigned long guestos_ss, guestos_esp; /* Virtual TSS (only SS1/ESP1) */
|
||||
unsigned long pt_base; /* CR3 (pagetable base) */
|
||||
unsigned long debugreg[8]; /* DB0-DB7 (debug registers) */
|
||||
unsigned long event_callback_cs; /* CS:EIP of event callback */
|
||||
|
||||
@@ -116,10 +116,11 @@ typedef struct dom0_getdomaininfo_st
|
||||
typedef struct dom0_getpageframeinfo_st
|
||||
{
|
||||
/* IN variables. */
|
||||
unsigned long pfn; /* Machine page frame number to query. */
|
||||
unsigned long pfn; /* Machine page frame number to query. */
|
||||
domid_t domain; /* To which domain does the frame belong? */
|
||||
/* OUT variables. */
|
||||
enum { NONE, L1TAB, L2TAB } type; /* Is the page PINNED to a type? */
|
||||
/* Is the page PINNED to a type? */
|
||||
enum { NONE, L1TAB, L2TAB, L3TAB, L4TAB } type;
|
||||
} dom0_getpageframeinfo_t;
|
||||
|
||||
#define DOM0_IOPL 14
|
||||
|
||||
@@ -51,6 +51,6 @@ unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base);
|
||||
long long simple_strtoll(const char *cp,char **endp,unsigned int base);
|
||||
|
||||
/* Produce a 32-bit hash from a key string 'k' of length 'len' bytes. */
|
||||
unsigned long hash(unsigned char *k, unsigned long len);
|
||||
u32 hash(unsigned char *k, unsigned long len);
|
||||
|
||||
#endif /* __LIB_H__ */
|
||||
@@ -14,8 +14,6 @@
|
||||
#define LONG_MIN (-LONG_MAX - 1)
|
||||
#define ULONG_MAX (~0UL)
|
||||
|
||||
typedef unsigned int size_t;
|
||||
|
||||
/* bsd */
|
||||
typedef unsigned char u_char;
|
||||
typedef unsigned short u_short;
|
||||
|
||||
+1
-1
@@ -627,7 +627,7 @@ static void net_rx_action(struct softirq_action *h)
|
||||
* for ethernet header, plus any other alignment padding added by the
|
||||
* driver.
|
||||
*/
|
||||
offset = (int)skb->data & ~PAGE_MASK;
|
||||
offset = (int)(long)skb->data & ~PAGE_MASK;
|
||||
skb->head = (u8 *)map_domain_mem(((skb->pf - frame_table) <<
|
||||
PAGE_SHIFT));
|
||||
skb->data = skb->nh.raw = skb->head + offset;
|
||||
|
||||
@@ -51,20 +51,21 @@ HEAD := arch/xeno/kernel/head.o arch/xeno/kernel/init_task.o
|
||||
SUBDIRS += arch/xeno/kernel arch/xeno/mm arch/xeno/lib
|
||||
SUBDIRS += arch/xeno/drivers/console arch/xeno/drivers/network
|
||||
SUBDIRS += arch/xeno/drivers/evtchn arch/xeno/drivers/block
|
||||
SUBDIRS += arch/xeno/drivers/balloon
|
||||
SUBDIRS += arch/xeno/drivers/balloon arch/xeno/drivers/vnetif
|
||||
ifdef CONFIG_XENO_PRIV
|
||||
SUBDIRS += arch/xeno/drivers/dom0
|
||||
endif
|
||||
|
||||
CORE_FILES += arch/xeno/kernel/kernel.o arch/xeno/mm/mm.o
|
||||
CORE_FILES += arch/xeno/drivers/evtchn/evtchn.o
|
||||
CORE_FILES += arch/xeno/drivers/console/con.o
|
||||
CORE_FILES += arch/xeno/drivers/block/blk.o
|
||||
CORE_FILES += arch/xeno/drivers/network/net.o
|
||||
CORE_FILES += arch/xeno/drivers/evtchn/drv.o
|
||||
CORE_FILES += arch/xeno/drivers/console/drv.o
|
||||
CORE_FILES += arch/xeno/drivers/block/drv.o
|
||||
CORE_FILES += arch/xeno/drivers/network/drv.o
|
||||
CORE_FILES += arch/xeno/drivers/vnetif/drv.o
|
||||
ifdef CONFIG_XENO_PRIV
|
||||
CORE_FILES += arch/xeno/drivers/dom0/dom0.o
|
||||
CORE_FILES += arch/xeno/drivers/dom0/drv.o
|
||||
endif
|
||||
CORE_FILES += arch/xeno/drivers/balloon/balloon_driver.o
|
||||
CORE_FILES += arch/xeno/drivers/balloon/drv.o
|
||||
LIBS := $(TOPDIR)/arch/xeno/lib/lib.a $(LIBS) $(TOPDIR)/arch/xeno/lib/lib.a
|
||||
|
||||
arch/xeno/kernel: dummy
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
O_TARGET := balloon_driver.o
|
||||
O_TARGET := drv.o
|
||||
obj-y := balloon.o
|
||||
include $(TOPDIR)/Rules.make
|
||||
@@ -1,3 +1,3 @@
|
||||
O_TARGET := blk.o
|
||||
obj-y := xl_block.o xl_vbd.o
|
||||
O_TARGET := drv.o
|
||||
obj-y := block.o vbd.o
|
||||
include $(TOPDIR)/Rules.make
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/******************************************************************************
|
||||
* xl_block.c
|
||||
* block.c
|
||||
*
|
||||
* Xenolinux virtual block-device driver.
|
||||
*
|
||||
@@ -7,7 +7,7 @@
|
||||
* Modifications by Mark A. Williamson are (c) Intel Research Cambridge
|
||||
*/
|
||||
|
||||
#include "xl_block.h"
|
||||
#include "block.h"
|
||||
#include <linux/blk.h>
|
||||
#include <linux/cdrom.h>
|
||||
#include <linux/tqueue.h>
|
||||
@@ -219,11 +219,11 @@ int xenolinux_block_ioctl(struct inode *inode, struct file *filep,
|
||||
return 0;
|
||||
|
||||
case SCSI_IOCTL_GET_BUS_NUMBER:
|
||||
DPRINTK("FIXME: SCSI_IOCTL_GET_BUS_NUMBER ioctl in xl_block");
|
||||
DPRINTK("FIXME: SCSI_IOCTL_GET_BUS_NUMBER ioctl in Xen blkdev");
|
||||
return -ENOSYS;
|
||||
|
||||
default:
|
||||
printk(KERN_ALERT "ioctl %08x not supported by xl_block\n", command);
|
||||
printk(KERN_ALERT "ioctl %08x not supported by Xen blkdev\n", command);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
+4
-4
@@ -1,11 +1,11 @@
|
||||
/******************************************************************************
|
||||
* xl_block.h
|
||||
* block.h
|
||||
*
|
||||
* Shared definitions between all levels of XenoLinux Virtual block devices.
|
||||
*/
|
||||
|
||||
#ifndef __XL_BLOCK_H__
|
||||
#define __XL_BLOCK_H__
|
||||
#ifndef __XENO_DRIVERS_BLOCK_H__
|
||||
#define __XENO_DRIVERS_BLOCK_H__
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
@@ -79,4 +79,4 @@ static inline xl_disk_t *xldev_to_xldisk(kdev_t xldev)
|
||||
extern int xlvbd_init(void);
|
||||
extern void xlvbd_cleanup(void);
|
||||
|
||||
#endif /* __XL_BLOCK_H__ */
|
||||
#endif /* __XENO_DRIVERS_BLOCK_H__ */
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/******************************************************************************
|
||||
* xl_vbd.c
|
||||
* vbd.c
|
||||
*
|
||||
* Xenolinux virtual block-device driver (xvd).
|
||||
*
|
||||
@@ -7,7 +7,7 @@
|
||||
* Modifications by Mark A. Williamson are (c) Intel Research Cambridge
|
||||
*/
|
||||
|
||||
#include "xl_block.h"
|
||||
#include "block.h"
|
||||
#include <linux/blk.h>
|
||||
|
||||
/*
|
||||
@@ -1,3 +1,3 @@
|
||||
O_TARGET := con.o
|
||||
O_TARGET := drv.o
|
||||
obj-$(CONFIG_XEN_CONSOLE) := console.o
|
||||
include $(TOPDIR)/Rules.make
|
||||
@@ -1,3 +1,3 @@
|
||||
O_TARGET := dom0.o
|
||||
obj-y := dom0_core.o vfr.o
|
||||
O_TARGET := drv.o
|
||||
obj-y := core.o vfr.o
|
||||
include $(TOPDIR)/Rules.make
|
||||
+2
-6
@@ -1,9 +1,9 @@
|
||||
/******************************************************************************
|
||||
* dom0_core.c
|
||||
* core.c
|
||||
*
|
||||
* Interface to privileged domain-0 commands.
|
||||
*
|
||||
* Copyright (c) 2002-2003, K A Fraser, B Dragovic
|
||||
* Copyright (c) 2002-2004, K A Fraser, B Dragovic
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
@@ -31,11 +31,8 @@
|
||||
#include <asm/hypervisor-ifs/dom0_ops.h>
|
||||
#include <asm/xeno_proc.h>
|
||||
|
||||
#include "../block/xl_block.h"
|
||||
|
||||
static struct proc_dir_entry *privcmd_intf;
|
||||
|
||||
|
||||
static int privcmd_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long data)
|
||||
{
|
||||
@@ -83,7 +80,6 @@ static int __init init_module(void)
|
||||
if ( !(start_info.flags & SIF_PRIVILEGED) )
|
||||
return 0;
|
||||
|
||||
/* xeno control interface */
|
||||
privcmd_intf = create_xeno_proc_entry("privcmd", 0400);
|
||||
if ( privcmd_intf != NULL )
|
||||
{
|
||||
@@ -1,3 +1,3 @@
|
||||
O_TARGET := evtchn.o
|
||||
obj-y := xl_evtchn.o
|
||||
O_TARGET := drv.o
|
||||
obj-y := evtchn.o
|
||||
include $(TOPDIR)/Rules.make
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/******************************************************************************
|
||||
* xl_evtchn.c
|
||||
* evtchn.c
|
||||
*
|
||||
* Xenolinux driver for receiving and demuxing event-channel signals.
|
||||
*
|
||||
@@ -1,3 +1,3 @@
|
||||
O_TARGET := net.o
|
||||
O_TARGET := drv.o
|
||||
obj-y := network.o
|
||||
include $(TOPDIR)/Rules.make
|
||||
@@ -415,7 +415,7 @@ static void network_interrupt(int irq, void *unused, struct pt_regs *ptregs)
|
||||
}
|
||||
|
||||
|
||||
int network_close(struct net_device *dev)
|
||||
static int network_close(struct net_device *dev)
|
||||
{
|
||||
struct net_private *np = dev->priv;
|
||||
netop_t netop;
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
O_TARGET := drv.o
|
||||
obj-y := vnetif.o
|
||||
include $(TOPDIR)/Rules.make
|
||||
@@ -0,0 +1,552 @@
|
||||
/******************************************************************************
|
||||
* vnetif.c
|
||||
*
|
||||
* Virtual network driver for XenoLinux.
|
||||
*
|
||||
* Copyright (c) 2002-2004, K A Fraser
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/inetdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <net/sock.h>
|
||||
#include <net/pkt_sched.h>
|
||||
|
||||
#define RX_BUF_SIZE ((PAGE_SIZE/2)+1) /* Fool the slab allocator :-) */
|
||||
|
||||
static void network_interrupt(int irq, void *dev_id, struct pt_regs *ptregs);
|
||||
static void network_tx_buf_gc(struct net_device *dev);
|
||||
static void network_alloc_rx_buffers(struct net_device *dev);
|
||||
static void cleanup_module(void);
|
||||
|
||||
static struct list_head dev_list;
|
||||
|
||||
struct net_private
|
||||
{
|
||||
struct list_head list;
|
||||
struct net_device *dev;
|
||||
|
||||
struct net_device_stats stats;
|
||||
NET_RING_IDX rx_resp_cons, tx_resp_cons;
|
||||
unsigned int net_ring_fixmap_idx, tx_full;
|
||||
net_ring_t *net_ring;
|
||||
net_idx_t *net_idx;
|
||||
spinlock_t tx_lock;
|
||||
unsigned int idx; /* Domain-specific index of this VIF. */
|
||||
|
||||
unsigned int rx_bufs_to_notify;
|
||||
|
||||
#define STATE_ACTIVE 0
|
||||
#define STATE_SUSPENDED 1
|
||||
#define STATE_CLOSED 2
|
||||
unsigned int state;
|
||||
|
||||
/*
|
||||
* {tx,rx}_skbs store outstanding skbuffs. The first entry in each
|
||||
* array is an index into a chain of free entries.
|
||||
*/
|
||||
struct sk_buff *tx_skbs[TX_RING_SIZE+1];
|
||||
struct sk_buff *rx_skbs[RX_RING_SIZE+1];
|
||||
};
|
||||
|
||||
/* Access macros for acquiring freeing slots in {tx,rx}_skbs[]. */
|
||||
#define ADD_ID_TO_FREELIST(_list, _id) \
|
||||
(_list)[(_id)] = (_list)[0]; \
|
||||
(_list)[0] = (void *)(unsigned long)(_id);
|
||||
#define GET_ID_FROM_FREELIST(_list) \
|
||||
({ unsigned long _id = (unsigned long)(_list)[0]; \
|
||||
(_list)[0] = (_list)[_id]; \
|
||||
(unsigned short)_id; })
|
||||
|
||||
|
||||
static void _dbg_network_int(struct net_device *dev)
|
||||
{
|
||||
struct net_private *np = dev->priv;
|
||||
|
||||
if ( np->state == STATE_CLOSED )
|
||||
return;
|
||||
|
||||
printk(KERN_ALERT "net: tx_full=%d, tx_resp_cons=0x%08x,"
|
||||
" tx_req_prod=0x%08x\nnet: tx_resp_prod=0x%08x,"
|
||||
" tx_event=0x%08x, state=%d\n",
|
||||
np->tx_full, np->tx_resp_cons,
|
||||
np->net_idx->tx_req_prod, np->net_idx->tx_resp_prod,
|
||||
np->net_idx->tx_event,
|
||||
test_bit(__LINK_STATE_XOFF, &dev->state));
|
||||
printk(KERN_ALERT "net: rx_resp_cons=0x%08x,"
|
||||
" rx_req_prod=0x%08x\nnet: rx_resp_prod=0x%08x, rx_event=0x%08x\n",
|
||||
np->rx_resp_cons, np->net_idx->rx_req_prod,
|
||||
np->net_idx->rx_resp_prod, np->net_idx->rx_event);
|
||||
}
|
||||
|
||||
|
||||
static void dbg_network_int(int irq, void *unused, struct pt_regs *ptregs)
|
||||
{
|
||||
struct list_head *ent;
|
||||
struct net_private *np;
|
||||
list_for_each ( ent, &dev_list )
|
||||
{
|
||||
np = list_entry(ent, struct net_private, list);
|
||||
_dbg_network_int(np->dev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int network_open(struct net_device *dev)
|
||||
{
|
||||
struct net_private *np = dev->priv;
|
||||
netop_t netop;
|
||||
int i, ret;
|
||||
|
||||
netop.cmd = NETOP_RESET_RINGS;
|
||||
netop.vif = np->idx;
|
||||
if ( (ret = HYPERVISOR_net_io_op(&netop)) != 0 )
|
||||
{
|
||||
printk(KERN_ALERT "Possible net trouble: couldn't reset ring idxs\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
netop.cmd = NETOP_GET_VIF_INFO;
|
||||
netop.vif = np->idx;
|
||||
if ( (ret = HYPERVISOR_net_io_op(&netop)) != 0 )
|
||||
{
|
||||
printk(KERN_ALERT "Couldn't get info for vif %d\n", np->idx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
memcpy(dev->dev_addr, netop.u.get_vif_info.vmac, ETH_ALEN);
|
||||
|
||||
set_fixmap(FIX_NETRING0_BASE + np->net_ring_fixmap_idx,
|
||||
netop.u.get_vif_info.ring_mfn << PAGE_SHIFT);
|
||||
np->net_ring = (net_ring_t *)fix_to_virt(
|
||||
FIX_NETRING0_BASE + np->net_ring_fixmap_idx);
|
||||
np->net_idx = &HYPERVISOR_shared_info->net_idx[np->idx];
|
||||
|
||||
np->rx_bufs_to_notify = 0;
|
||||
np->rx_resp_cons = np->tx_resp_cons = np->tx_full = 0;
|
||||
memset(&np->stats, 0, sizeof(np->stats));
|
||||
spin_lock_init(&np->tx_lock);
|
||||
memset(np->net_ring, 0, sizeof(*np->net_ring));
|
||||
memset(np->net_idx, 0, sizeof(*np->net_idx));
|
||||
|
||||
/* Initialise {tx,rx}_skbs to be a free chain containing every entry. */
|
||||
for ( i = 0; i <= TX_RING_SIZE; i++ )
|
||||
np->tx_skbs[i] = (void *)(i+1);
|
||||
for ( i = 0; i <= RX_RING_SIZE; i++ )
|
||||
np->rx_skbs[i] = (void *)(i+1);
|
||||
|
||||
wmb();
|
||||
np->state = STATE_ACTIVE;
|
||||
|
||||
network_alloc_rx_buffers(dev);
|
||||
|
||||
netif_start_queue(dev);
|
||||
|
||||
MOD_INC_USE_COUNT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void network_tx_buf_gc(struct net_device *dev)
|
||||
{
|
||||
NET_RING_IDX i, prod;
|
||||
unsigned short id;
|
||||
struct net_private *np = dev->priv;
|
||||
struct sk_buff *skb;
|
||||
tx_entry_t *tx_ring = np->net_ring->tx_ring;
|
||||
|
||||
do {
|
||||
prod = np->net_idx->tx_resp_prod;
|
||||
|
||||
for ( i = np->tx_resp_cons; i != prod; i++ )
|
||||
{
|
||||
id = tx_ring[MASK_NET_TX_IDX(i)].resp.id;
|
||||
skb = np->tx_skbs[id];
|
||||
ADD_ID_TO_FREELIST(np->tx_skbs, id);
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
np->tx_resp_cons = prod;
|
||||
|
||||
/*
|
||||
* Set a new event, then check for race with update of tx_cons. Note
|
||||
* that it is essential to schedule a callback, no matter how few
|
||||
* buffers are pending. Even if there is space in the transmit ring,
|
||||
* higher layers may be blocked because too much data is outstanding:
|
||||
* in such cases notification from Xen is likely to be the only kick
|
||||
* that we'll get.
|
||||
*/
|
||||
np->net_idx->tx_event =
|
||||
prod + ((np->net_idx->tx_req_prod - prod) >> 1) + 1;
|
||||
mb();
|
||||
}
|
||||
while ( prod != np->net_idx->tx_resp_prod );
|
||||
|
||||
if ( np->tx_full && ((np->net_idx->tx_req_prod - prod) < TX_RING_SIZE) )
|
||||
{
|
||||
np->tx_full = 0;
|
||||
if ( np->state == STATE_ACTIVE )
|
||||
netif_wake_queue(dev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline pte_t *get_ppte(void *addr)
|
||||
{
|
||||
pgd_t *pgd; pmd_t *pmd; pte_t *pte;
|
||||
pgd = pgd_offset_k( (unsigned long)addr);
|
||||
pmd = pmd_offset(pgd, (unsigned long)addr);
|
||||
pte = pte_offset(pmd, (unsigned long)addr);
|
||||
return pte;
|
||||
}
|
||||
|
||||
|
||||
static void network_alloc_rx_buffers(struct net_device *dev)
|
||||
{
|
||||
unsigned short id;
|
||||
struct net_private *np = dev->priv;
|
||||
struct sk_buff *skb;
|
||||
netop_t netop;
|
||||
NET_RING_IDX i = np->net_idx->rx_req_prod;
|
||||
|
||||
if ( unlikely((i - np->rx_resp_cons) == RX_RING_SIZE) ||
|
||||
unlikely(np->state != STATE_ACTIVE) )
|
||||
return;
|
||||
|
||||
do {
|
||||
skb = dev_alloc_skb(RX_BUF_SIZE);
|
||||
if ( unlikely(skb == NULL) )
|
||||
break;
|
||||
|
||||
skb->dev = dev;
|
||||
|
||||
if ( unlikely(((unsigned long)skb->head & (PAGE_SIZE-1)) != 0) )
|
||||
panic("alloc_skb needs to provide us page-aligned buffers.");
|
||||
|
||||
id = GET_ID_FROM_FREELIST(np->rx_skbs);
|
||||
np->rx_skbs[id] = skb;
|
||||
|
||||
np->net_ring->rx_ring[MASK_NET_RX_IDX(i)].req.id = id;
|
||||
np->net_ring->rx_ring[MASK_NET_RX_IDX(i)].req.addr =
|
||||
virt_to_machine(get_ppte(skb->head));
|
||||
|
||||
np->rx_bufs_to_notify++;
|
||||
}
|
||||
while ( (++i - np->rx_resp_cons) != RX_RING_SIZE );
|
||||
|
||||
/*
|
||||
* We may have allocated buffers which have entries outstanding in the page
|
||||
* update queue -- make sure we flush those first!
|
||||
*/
|
||||
flush_page_update_queue();
|
||||
|
||||
np->net_idx->rx_req_prod = i;
|
||||
np->net_idx->rx_event = np->rx_resp_cons + 1;
|
||||
|
||||
/* Batch Xen notifications. */
|
||||
if ( np->rx_bufs_to_notify > (RX_RING_SIZE/4) )
|
||||
{
|
||||
netop.cmd = NETOP_PUSH_BUFFERS;
|
||||
netop.vif = np->idx;
|
||||
(void)HYPERVISOR_net_io_op(&netop);
|
||||
np->rx_bufs_to_notify = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
unsigned short id;
|
||||
struct net_private *np = (struct net_private *)dev->priv;
|
||||
tx_req_entry_t *tx;
|
||||
netop_t netop;
|
||||
NET_RING_IDX i;
|
||||
|
||||
if ( unlikely(np->tx_full) )
|
||||
{
|
||||
printk(KERN_ALERT "%s: full queue wasn't stopped!\n", dev->name);
|
||||
netif_stop_queue(dev);
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
if ( unlikely((((unsigned long)skb->data & ~PAGE_MASK) + skb->len) >=
|
||||
PAGE_SIZE) )
|
||||
{
|
||||
struct sk_buff *new_skb = dev_alloc_skb(RX_BUF_SIZE);
|
||||
if ( unlikely(new_skb == NULL) )
|
||||
return 1;
|
||||
skb_put(new_skb, skb->len);
|
||||
memcpy(new_skb->data, skb->data, skb->len);
|
||||
dev_kfree_skb(skb);
|
||||
skb = new_skb;
|
||||
}
|
||||
|
||||
spin_lock_irq(&np->tx_lock);
|
||||
|
||||
i = np->net_idx->tx_req_prod;
|
||||
|
||||
id = GET_ID_FROM_FREELIST(np->tx_skbs);
|
||||
np->tx_skbs[id] = skb;
|
||||
|
||||
tx = &np->net_ring->tx_ring[MASK_NET_TX_IDX(i)].req;
|
||||
|
||||
tx->id = id;
|
||||
tx->addr = phys_to_machine(virt_to_phys(skb->data));
|
||||
tx->size = skb->len;
|
||||
|
||||
wmb();
|
||||
np->net_idx->tx_req_prod = i + 1;
|
||||
|
||||
network_tx_buf_gc(dev);
|
||||
|
||||
if ( (i - np->tx_resp_cons) == (TX_RING_SIZE - 1) )
|
||||
{
|
||||
np->tx_full = 1;
|
||||
netif_stop_queue(dev);
|
||||
}
|
||||
|
||||
spin_unlock_irq(&np->tx_lock);
|
||||
|
||||
np->stats.tx_bytes += skb->len;
|
||||
np->stats.tx_packets++;
|
||||
|
||||
/* Only notify Xen if there are no outstanding responses. */
|
||||
mb();
|
||||
if ( np->net_idx->tx_resp_prod == i )
|
||||
{
|
||||
netop.cmd = NETOP_PUSH_BUFFERS;
|
||||
netop.vif = np->idx;
|
||||
(void)HYPERVISOR_net_io_op(&netop);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static inline void _network_interrupt(struct net_device *dev)
|
||||
{
|
||||
struct net_private *np = dev->priv;
|
||||
unsigned long flags;
|
||||
struct sk_buff *skb;
|
||||
rx_resp_entry_t *rx;
|
||||
NET_RING_IDX i;
|
||||
|
||||
if ( unlikely(np->state == STATE_CLOSED) )
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&np->tx_lock, flags);
|
||||
network_tx_buf_gc(dev);
|
||||
spin_unlock_irqrestore(&np->tx_lock, flags);
|
||||
|
||||
again:
|
||||
for ( i = np->rx_resp_cons; i != np->net_idx->rx_resp_prod; i++ )
|
||||
{
|
||||
rx = &np->net_ring->rx_ring[MASK_NET_RX_IDX(i)].resp;
|
||||
|
||||
skb = np->rx_skbs[rx->id];
|
||||
ADD_ID_TO_FREELIST(np->rx_skbs, rx->id);
|
||||
|
||||
if ( unlikely(rx->status != RING_STATUS_OK) )
|
||||
{
|
||||
/* Gate this error. We get a (valid) slew of them on suspend. */
|
||||
if ( np->state == STATE_ACTIVE )
|
||||
printk(KERN_ALERT "bad buffer on RX ring!(%d)\n", rx->status);
|
||||
dev_kfree_skb_any(skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up shinfo -- from alloc_skb This was particularily nasty: the
|
||||
* shared info is hidden at the back of the data area (presumably so it
|
||||
* can be shared), but on page flip it gets very spunked.
|
||||
*/
|
||||
atomic_set(&(skb_shinfo(skb)->dataref), 1);
|
||||
skb_shinfo(skb)->nr_frags = 0;
|
||||
skb_shinfo(skb)->frag_list = NULL;
|
||||
|
||||
phys_to_machine_mapping[virt_to_phys(skb->head) >> PAGE_SHIFT] =
|
||||
(*(unsigned long *)get_ppte(skb->head)) >> PAGE_SHIFT;
|
||||
|
||||
skb->data = skb->tail = skb->head + rx->offset;
|
||||
skb_put(skb, rx->size);
|
||||
skb->protocol = eth_type_trans(skb, dev);
|
||||
|
||||
np->stats.rx_packets++;
|
||||
|
||||
np->stats.rx_bytes += rx->size;
|
||||
netif_rx(skb);
|
||||
dev->last_rx = jiffies;
|
||||
}
|
||||
|
||||
np->rx_resp_cons = i;
|
||||
|
||||
network_alloc_rx_buffers(dev);
|
||||
|
||||
/* Deal with hypervisor racing our resetting of rx_event. */
|
||||
mb();
|
||||
if ( np->net_idx->rx_resp_prod != i )
|
||||
goto again;
|
||||
}
|
||||
|
||||
|
||||
static void network_interrupt(int irq, void *unused, struct pt_regs *ptregs)
|
||||
{
|
||||
struct list_head *ent;
|
||||
struct net_private *np;
|
||||
list_for_each ( ent, &dev_list )
|
||||
{
|
||||
np = list_entry(ent, struct net_private, list);
|
||||
_network_interrupt(np->dev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int network_close(struct net_device *dev)
|
||||
{
|
||||
struct net_private *np = dev->priv;
|
||||
netop_t netop;
|
||||
|
||||
np->state = STATE_SUSPENDED;
|
||||
wmb();
|
||||
|
||||
netif_stop_queue(np->dev);
|
||||
|
||||
netop.cmd = NETOP_FLUSH_BUFFERS;
|
||||
netop.vif = np->idx;
|
||||
(void)HYPERVISOR_net_io_op(&netop);
|
||||
|
||||
while ( (np->rx_resp_cons != np->net_idx->rx_req_prod) ||
|
||||
(np->tx_resp_cons != np->net_idx->tx_req_prod) )
|
||||
{
|
||||
barrier();
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule_timeout(1);
|
||||
}
|
||||
|
||||
wmb();
|
||||
np->state = STATE_CLOSED;
|
||||
wmb();
|
||||
|
||||
/* Now no longer safe to take interrupts for this device. */
|
||||
clear_fixmap(FIX_NETRING0_BASE + np->net_ring_fixmap_idx);
|
||||
|
||||
MOD_DEC_USE_COUNT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct net_device_stats *network_get_stats(struct net_device *dev)
|
||||
{
|
||||
struct net_private *np = (struct net_private *)dev->priv;
|
||||
return &np->stats;
|
||||
}
|
||||
|
||||
|
||||
static int __init init_module(void)
|
||||
{
|
||||
#if 0
|
||||
int i, fixmap_idx=-1, err;
|
||||
struct net_device *dev;
|
||||
struct net_private *np;
|
||||
netop_t netop;
|
||||
|
||||
INIT_LIST_HEAD(&dev_list);
|
||||
|
||||
err = request_irq(HYPEREVENT_IRQ(_EVENT_NET), network_interrupt,
|
||||
SA_SAMPLE_RANDOM, "network", NULL);
|
||||
if ( err )
|
||||
{
|
||||
printk(KERN_WARNING "Could not allocate network interrupt\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
err = request_irq(HYPEREVENT_IRQ(_EVENT_DEBUG), dbg_network_int,
|
||||
SA_SHIRQ, "net_dbg", &dbg_network_int);
|
||||
if ( err )
|
||||
printk(KERN_WARNING "Non-fatal error -- no debug interrupt\n");
|
||||
|
||||
for ( i = 0; i < MAX_DOMAIN_VIFS; i++ )
|
||||
{
|
||||
/* If the VIF is invalid then the query hypercall will fail. */
|
||||
netop.cmd = NETOP_GET_VIF_INFO;
|
||||
netop.vif = i;
|
||||
if ( HYPERVISOR_net_io_op(&netop) != 0 )
|
||||
continue;
|
||||
|
||||
/* We actually only support up to 4 vifs right now. */
|
||||
if ( ++fixmap_idx == 4 )
|
||||
break;
|
||||
|
||||
dev = alloc_etherdev(sizeof(struct net_private));
|
||||
if ( dev == NULL )
|
||||
{
|
||||
err = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
np = dev->priv;
|
||||
np->state = STATE_CLOSED;
|
||||
np->net_ring_fixmap_idx = fixmap_idx;
|
||||
np->idx = i;
|
||||
|
||||
SET_MODULE_OWNER(dev);
|
||||
dev->open = network_open;
|
||||
dev->hard_start_xmit = network_start_xmit;
|
||||
dev->stop = network_close;
|
||||
dev->get_stats = network_get_stats;
|
||||
|
||||
memcpy(dev->dev_addr, netop.u.get_vif_info.vmac, ETH_ALEN);
|
||||
|
||||
if ( (err = register_netdev(dev)) != 0 )
|
||||
{
|
||||
kfree(dev);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
np->dev = dev;
|
||||
list_add(&np->list, &dev_list);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
cleanup_module();
|
||||
return err;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void cleanup_module(void)
|
||||
{
|
||||
struct net_private *np;
|
||||
struct net_device *dev;
|
||||
|
||||
while ( !list_empty(&dev_list) )
|
||||
{
|
||||
np = list_entry(dev_list.next, struct net_private, list);
|
||||
list_del(&np->list);
|
||||
dev = np->dev;
|
||||
unregister_netdev(dev);
|
||||
kfree(dev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module_init(init_module);
|
||||
module_exit(cleanup_module);
|
||||