# HG changeset patch
# User Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
# Node ID 5c0c59eb5f73e7862590a8adca52bc74171bf2d5
# Parent 760669a37a3a04dd629823cf41a6bc8ee662e224
# Parent 0f9ec4b29f3a25cffcd90e03113f3790e644a3ac
[ppc-code-merge] merge with linux-2.6.tip-xen.hg
---
arch/ia64/xen/drivers/Makefile | 22 --
arch/ia64/xen/drivers/coreMakefile | 20 -
arch/ia64/xen/drivers/evtchn_ia64.c | 261 -------------------------
arch/ia64/xen/xenconsole.c | 19 -
arch/i386/kernel/head-xen.S | 2
arch/i386/kernel/process-xen.c | 14 -
arch/i386/kernel/time-xen.c | 20 +
arch/i386/kernel/vm86.c | 4
arch/i386/mm/init-xen.c | 14 -
arch/ia64/Kconfig | 36 ++-
arch/ia64/kernel/iosapic.c | 11 -
arch/ia64/kernel/irq_ia64.c | 197 ++++++++++++++++++-
arch/ia64/kernel/setup.c | 21 +-
arch/ia64/xen/Makefile | 2
arch/ia64/xen/drivers/xenia64_init.c | 1
arch/ia64/xen/hypervisor.c | 285 ++++++++++++++++++++-------
arch/ia64/xen/xenivt.S | 45 +++-
arch/powerpc/Kconfig | 5
arch/x86_64/kernel/process-xen.c | 15 -
arch/x86_64/kernel/setup-xen.c | 23 --
arch/x86_64/kernel/smp-xen.c | 2
arch/x86_64/mm/init-xen.c | 43 +++-
drivers/xen/Kconfig | 15 -
drivers/xen/Makefile | 2
drivers/xen/balloon/balloon.c | 6
drivers/xen/blkfront/blkfront.c | 21 +-
drivers/xen/blkfront/block.h | 1
drivers/xen/blkfront/vbd.c | 1
drivers/xen/core/Makefile | 6
drivers/xen/core/cpu_hotplug.c | 2
drivers/xen/core/smpboot.c | 20 +
drivers/xen/netback/loopback.c | 2
drivers/xen/netback/netback.c | 288 ++++++++++++++++++++++------
drivers/xen/netback/xenbus.c | 26 ++
drivers/xen/netfront/netfront.c | 173 +++++++++++++---
drivers/xen/privcmd/privcmd.c | 12 -
include/asm-i386/mach-xen/asm/dma-mapping.h | 2
include/asm-i386/mach-xen/asm/hypercall.h | 7
include/asm-i386/mach-xen/asm/system.h | 10
include/asm-i386/mach-xen/setup_arch_post.h | 7
include/asm-ia64/hw_irq.h | 8
include/asm-ia64/hypercall.h | 40 ++-
include/asm-ia64/hypervisor.h | 4
include/asm-ia64/irq.h | 31 +++
include/asm-ia64/xen/privop.h | 32 +--
include/asm-x86_64/mach-xen/asm/hypercall.h | 7
include/asm-x86_64/mach-xen/asm/system.h | 4
include/xen/cpu_hotplug.h | 6
include/xen/interface/arch-ia64.h | 9
include/xen/interface/arch-x86_32.h | 27 ++
include/xen/interface/arch-x86_64.h | 24 +-
include/xen/interface/callback.h | 15 +
include/xen/interface/grant_table.h | 2
include/xen/interface/io/netif.h | 4
include/xen/interface/io/ring.h | 16 +
include/xen/interface/memory.h | 10
include/xen/interface/sched_ctl.h | 2
include/xen/interface/xen.h | 22 +-
58 files changed, 1243 insertions(+), 683 deletions(-)
diff -r 760669a37a3a -r 5c0c59eb5f73 arch/i386/kernel/head-xen.S
--- a/arch/i386/kernel/head-xen.S Wed Jun 07 19:53:53 2006 -0400
+++ b/arch/i386/kernel/head-xen.S Thu Jun 08 15:10:05 2006 -0400
@@ -173,7 +173,7 @@ ENTRY(cpu_gdt_table)
.ascii "|pae_pgdir_above_4gb"
.ascii "|supervisor_mode_kernel"
#ifdef CONFIG_X86_PAE
- .ascii ",PAE=yes"
+ .ascii ",PAE=yes[extended-cr3]"
#else
.ascii ",PAE=no"
#endif
diff -r 760669a37a3a -r 5c0c59eb5f73 arch/i386/kernel/process-xen.c
--- a/arch/i386/kernel/process-xen.c Wed Jun 07 19:53:53 2006 -0400
+++ b/arch/i386/kernel/process-xen.c Thu Jun 08 15:10:05 2006 -0400
@@ -54,6 +54,7 @@
#include <xen/interface/physdev.h>
#include <xen/interface/vcpu.h>
+#include <xen/cpu_hotplug.h>
#include <linux/err.h>
@@ -100,8 +101,6 @@ EXPORT_SYMBOL(enable_hlt);
EXPORT_SYMBOL(enable_hlt);
/* XXX XEN doesn't use default_idle(), poll_idle(). Use xen_idle() instead. */
-extern void stop_hz_timer(void);
-extern void start_hz_timer(void);
void xen_idle(void)
{
local_irq_disable();
@@ -111,10 +110,7 @@ void xen_idle(void)
else {
clear_thread_flag(TIF_POLLING_NRFLAG);
smp_mb__after_clear_bit();
- stop_hz_timer();
- /* Blocking includes an implicit local_irq_enable(). */
- HYPERVISOR_block();
- start_hz_timer();
+ safe_halt();
set_thread_flag(TIF_POLLING_NRFLAG);
}
}
@@ -131,11 +127,7 @@ static inline void play_dead(void)
cpu_clear(smp_processor_id(), cpu_initialized);
preempt_enable_no_resched();
HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL);
- /* Same as drivers/xen/core/smpboot.c:cpu_bringup(). */
- cpu_init();
- touch_softlockup_watchdog();
- preempt_disable();
- local_irq_enable();
+ cpu_bringup();
}
#else
static inline void play_dead(void)
diff -r 760669a37a3a -r 5c0c59eb5f73 arch/i386/kernel/time-xen.c
--- a/arch/i386/kernel/time-xen.c Wed Jun 07 19:53:53 2006 -0400
+++ b/arch/i386/kernel/time-xen.c Thu Jun 08 15:10:05 2006 -0400
@@ -973,7 +973,7 @@ EXPORT_SYMBOL(jiffies_to_st);
* stop_hz_timer / start_hz_timer - enter/exit 'tickless mode' on an idle cpu
* These functions are based on implementations from arch/s390/kernel/time.c
*/
-void stop_hz_timer(void)
+static void stop_hz_timer(void)
{
unsigned int cpu = smp_processor_id();
unsigned long j;
@@ -993,10 +993,26 @@ void stop_hz_timer(void)
BUG_ON(HYPERVISOR_set_timer_op(jiffies_to_st(j)) != 0);
}
-void start_hz_timer(void)
+static void start_hz_timer(void)
{
cpu_clear(smp_processor_id(), nohz_cpu_mask);
}
+
+void safe_halt(void)
+{
+ stop_hz_timer();
+ /* Blocking includes an implicit local_irq_enable(). */
+ HYPERVISOR_block();
+ start_hz_timer();
+}
+EXPORT_SYMBOL(safe_halt);
+
+void halt(void)
+{
+ if (irqs_disabled())
+ HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL);
+}
+EXPORT_SYMBOL(halt);
/* No locking required. We are only CPU running, and interrupts are off. */
void time_resume(void)
diff -r 760669a37a3a -r 5c0c59eb5f73 arch/i386/kernel/vm86.c
--- a/arch/i386/kernel/vm86.c Wed Jun 07 19:53:53 2006 -0400
+++ b/arch/i386/kernel/vm86.c Thu Jun 08 15:10:05 2006 -0400
@@ -132,7 +132,9 @@ struct pt_regs * fastcall save_v86_state
current->thread.sysenter_cs = __KERNEL_CS;
load_esp0(tss, ¤t->thread);
current->thread.saved_esp0 = 0;
+#ifndef CONFIG_X86_NO_TSS
put_cpu();
+#endif
loadsegment(fs, current->thread.saved_fs);
loadsegment(gs, current->thread.saved_gs);
@@ -310,7 +312,9 @@ static void do_sys_vm86(struct kernel_vm
if (cpu_has_sep)
tsk->thread.sysenter_cs = 0;
load_esp0(tss, &tsk->thread);
+#ifndef CONFIG_X86_NO_TSS
put_cpu();
+#endif
tsk->thread.screen_bitmap = info->screen_bitmap;
if (info->flags & VM86_SCREEN_BITMAP)
diff -r 760669a37a3a -r 5c0c59eb5f73 arch/i386/mm/init-xen.c
--- a/arch/i386/mm/init-xen.c Wed Jun 07 19:53:53 2006 -0400
+++ b/arch/i386/mm/init-xen.c Thu Jun 08 15:10:05 2006 -0400
@@ -558,15 +558,11 @@ void __init paging_init(void)
kmap_init();
- if (!xen_feature(XENFEAT_auto_translated_physmap) ||
- xen_start_info->shared_info >= xen_start_info->nr_pages) {
- /* Switch to the real shared_info page, and clear the
- * dummy page. */
- set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
- HYPERVISOR_shared_info =
- (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
- memset(empty_zero_page, 0, sizeof(empty_zero_page));
- }
+ /* Switch to the real shared_info page, and clear the
+ * dummy page. */
+ set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
+ HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
+ memset(empty_zero_page, 0, sizeof(empty_zero_page));
/* Setup mapping of lower 1st MB */
for (i = 0; i < NR_FIX_ISAMAPS; i++)
diff -r 760669a37a3a -r 5c0c59eb5f73 arch/ia64/Kconfig
--- a/arch/ia64/Kconfig Wed Jun 07 19:53:53 2006 -0400
+++ b/arch/ia64/Kconfig Thu Jun 08 15:10:05 2006 -0400
@@ -81,7 +81,7 @@ config XEN_IA64_DOM0_VP
config XEN_IA64_DOM0_NON_VP
bool
- depends on !(XEN && XEN_IA64_DOM0_VP)
+ depends on XEN && !XEN_IA64_DOM0_VP
default y
help
dom0 P=M model
@@ -535,15 +535,39 @@ source "security/Kconfig"
source "crypto/Kconfig"
+#
# override default values of drivers/xen/Kconfig
-if !XEN_IA64_DOM0_VP
+#
+if XEN
+config XEN_UTIL
+ default n if XEN_IA64_DOM0_VP
+
config HAVE_ARCH_ALLOC_SKB
- bool
- default n
+ default n if !XEN_IA64_DOM0_VP
config HAVE_ARCH_DEV_ALLOC_SKB
- bool
- default n
+ default n if !XEN_IA64_DOM0_VP
+
+config XEN_BALLOON
+ default n if !XEN_IA64_DOM0_VP
+
+config XEN_SKBUFF
+ default n if !XEN_IA64_DOM0_VP
+
+config XEN_NETDEV_BACKEND
+ default n if !XEN_IA64_DOM0_VP
+
+config XEN_NETDEV_FRONTEND
+ default n if !XEN_IA64_DOM0_VP
+
+config XEN_DEVMEM
+ default n
+
+config XEN_REBOOT
+ default n
+
+config XEN_SMPBOOT
+ default n
endif
source "drivers/xen/Kconfig"
diff -r 760669a37a3a -r 5c0c59eb5f73 arch/ia64/kernel/iosapic.c
--- a/arch/ia64/kernel/iosapic.c Wed Jun 07 19:53:53 2006 -0400
+++ b/arch/ia64/kernel/iosapic.c Thu Jun 08 15:10:05 2006 -0400
@@ -191,7 +191,7 @@ static inline void xen_iosapic_write(cha
static inline unsigned int iosapic_read(char __iomem *iosapic, unsigned int
reg)
{
- if (!running_on_xen) {
+ if (!is_running_on_xen()) {
writel(reg, iosapic + IOSAPIC_REG_SELECT);
return readl(iosapic + IOSAPIC_WINDOW);
} else
@@ -200,7 +200,7 @@ static inline unsigned int iosapic_read(
static inline void iosapic_write(char __iomem *iosapic, unsigned int reg, u32
val)
{
- if (!running_on_xen) {
+ if (!is_running_on_xen()) {
writel(reg, iosapic + IOSAPIC_REG_SELECT);
writel(val, iosapic + IOSAPIC_WINDOW);
} else
@@ -712,6 +712,11 @@ register_intr (unsigned int gsi, int vec
iosapic_intr_info[vector].polarity = polarity;
iosapic_intr_info[vector].dmode = delivery;
iosapic_intr_info[vector].trigger = trigger;
+
+#ifdef CONFIG_XEN
+ if (is_running_on_xen())
+ return 0;
+#endif
if (trigger == IOSAPIC_EDGE)
irq_type = &irq_type_iosapic_edge;
@@ -1076,7 +1081,7 @@ iosapic_system_init (int system_pcat_com
pcat_compat = system_pcat_compat;
#ifdef CONFIG_XEN
- if (running_on_xen)
+ if (is_running_on_xen())
return;
#endif
if (pcat_compat) {
diff -r 760669a37a3a -r 5c0c59eb5f73 arch/ia64/kernel/irq_ia64.c
--- a/arch/ia64/kernel/irq_ia64.c Wed Jun 07 19:53:53 2006 -0400
+++ b/arch/ia64/kernel/irq_ia64.c Thu Jun 08 15:10:05 2006 -0400
@@ -68,7 +68,7 @@ assign_irq_vector (int irq)
int pos, vector;
#ifdef CONFIG_XEN
extern int xen_assign_irq_vector(int);
- if (running_on_xen)
+ if (is_running_on_xen())
return xen_assign_irq_vector(irq);
#endif /* CONFIG_XEN */
again:
@@ -229,6 +229,151 @@ static struct irqaction ipi_irqaction =
};
#endif
+#ifdef CONFIG_XEN
+#include <xen/evtchn.h>
+#include <xen/interface/callback.h>
+
+static char timer_name[NR_CPUS][15];
+static char ipi_name[NR_CPUS][15];
+static char resched_name[NR_CPUS][15];
+
+struct saved_irq {
+ unsigned int irq;
+ struct irqaction *action;
+};
+/* 16 should be far optimistic value, since only several percpu irqs
+ * are registered early.
+ */
+#define MAX_LATE_IRQ 16
+static struct saved_irq saved_percpu_irqs[MAX_LATE_IRQ];
+static unsigned short late_irq_cnt = 0;
+static unsigned short saved_irq_cnt = 0;
+static int xen_slab_ready = 0;
+
+/* Dummy stub. Though we may check RESCHEDULE_VECTOR before __do_IRQ,
+ * it ends up to issue several memory accesses upon percpu data and
+ * thus adds unnecessary traffic to other paths.
+ */
+static irqreturn_t
+handle_reschedule(int irq, void *dev_id, struct pt_regs *regs)
+{
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction resched_irqaction = {
+ .handler = handle_reschedule,
+ .flags = SA_INTERRUPT,
+ .name = "RESCHED"
+};
+
+/*
+ * This is xen version percpu irq registration, which needs bind
+ * to xen specific evtchn sub-system. One trick here is that xen
+ * evtchn binding interface depends on kmalloc because related
+ * port needs to be freed at device/cpu down. So we cache the
+ * registration on BSP before slab is ready and then deal them
+ * at later point. For rest instances happening after slab ready,
+ * we hook them to xen evtchn immediately.
+ *
+ * FIXME: MCA is not supported by far, and thus "nomca" boot param is
+ * required.
+ */
+void
+xen_register_percpu_irq (unsigned int irq, struct irqaction *action, int save)
+{
+ char name[15];
+ unsigned int cpu = smp_processor_id();
+ int ret = 0;
+
+ if (xen_slab_ready) {
+ switch (irq) {
+ case IA64_TIMER_VECTOR:
+ sprintf(timer_name[cpu], "%s%d", action->name, cpu);
+ ret = bind_virq_to_irqhandler(VIRQ_ITC, cpu,
+ action->handler, action->flags,
+ timer_name[cpu], action->dev_id);
+ printk(KERN_INFO "register VIRQ_ITC (%s) to xen irq
(%d)\n", name, ret);
+ break;
+ case IA64_IPI_RESCHEDULE:
+ sprintf(resched_name[cpu], "%s%d", action->name, cpu);
+ ret = bind_ipi_to_irqhandler(RESCHEDULE_VECTOR, cpu,
+ action->handler, action->flags,
+ resched_name[cpu], action->dev_id);
+ printk(KERN_INFO "register RESCHEDULE_VECTOR (%s) to
xen irq (%d)\n", name, ret);
+ break;
+ case IA64_IPI_VECTOR:
+ sprintf(ipi_name[cpu], "%s%d", action->name, cpu);
+ ret = bind_ipi_to_irqhandler(IPI_VECTOR, cpu,
+ action->handler, action->flags,
+ ipi_name[cpu], action->dev_id);
+ printk(KERN_INFO "register IPI_VECTOR (%s) to xen irq
(%d)\n", name, ret);
+ break;
+ default:
+ printk(KERN_WARNING "Percpu irq %d is unsupported by
xen!\n", irq);
+ break;
+ }
+ BUG_ON(ret < 0);
+ }
+
+ /* For BSP, we cache registered percpu irqs, and then re-walk
+ * them when initializing APs
+ */
+ if (!cpu && save) {
+ BUG_ON(saved_irq_cnt == MAX_LATE_IRQ);
+ saved_percpu_irqs[saved_irq_cnt].irq = irq;
+ saved_percpu_irqs[saved_irq_cnt].action = action;
+ saved_irq_cnt++;
+ if (!xen_slab_ready)
+ late_irq_cnt++;
+ }
+}
+
+static void
+xen_bind_early_percpu_irq (void)
+{
+ int i;
+
+ xen_slab_ready = 1;
+ /* There's no race when accessing this cached array, since only
+ * BSP will face with such step shortly
+ */
+ for (i = 0; i < late_irq_cnt; i++)
+ xen_register_percpu_irq(saved_percpu_irqs[i].irq,
+ saved_percpu_irqs[i].action, 0);
+}
+
+/* FIXME: There's no obvious point to check whether slab is ready. So
+ * a hack is used here by utilizing a late time hook.
+ */
+extern void (*late_time_init)(void);
+extern char xen_event_callback;
+extern void xen_init_IRQ(void);
+
+DECLARE_PER_CPU(int, ipi_to_irq[NR_IPIS]);
+void xen_smp_intr_init(void)
+{
+#ifdef CONFIG_SMP
+ unsigned int cpu = smp_processor_id();
+ unsigned int i = 0;
+ struct callback_register event = {
+ .type = CALLBACKTYPE_event,
+ .address = (unsigned long)&xen_event_callback,
+ };
+
+ if (!cpu)
+ return;
+
+ /* This should be piggyback when setup vcpu guest context */
+ BUG_ON(HYPERVISOR_callback_op(CALLBACKOP_register, &event));
+
+ for (i = 0; i < saved_irq_cnt; i++)
+ xen_register_percpu_irq(saved_percpu_irqs[i].irq,
+ saved_percpu_irqs[i].action, 0);
+#endif /* CONFIG_SMP */
+}
+#endif /* CONFIG_XEN */
+
void
register_percpu_irq (ia64_vector vec, struct irqaction *action)
{
@@ -237,6 +382,10 @@ register_percpu_irq (ia64_vector vec, st
for (irq = 0; irq < NR_IRQS; ++irq)
if (irq_to_vector(irq) == vec) {
+#ifdef CONFIG_XEN
+ if (is_running_on_xen())
+ return xen_register_percpu_irq(vec, action, 1);
+#endif
desc = irq_descp(irq);
desc->status |= IRQ_PER_CPU;
desc->handler = &irq_type_ia64_lsapic;
@@ -248,6 +397,21 @@ void __init
void __init
init_IRQ (void)
{
+#ifdef CONFIG_XEN
+ /* Maybe put into platform_irq_init later */
+ if (is_running_on_xen()) {
+ struct callback_register event = {
+ .type = CALLBACKTYPE_event,
+ .address = (unsigned long)&xen_event_callback,
+ };
+ xen_init_IRQ();
+ BUG_ON(HYPERVISOR_callback_op(CALLBACKOP_register, &event));
+ late_time_init = xen_bind_early_percpu_irq;
+#ifdef CONFIG_SMP
+ register_percpu_irq(IA64_IPI_RESCHEDULE, &resched_irqaction);
+#endif /* CONFIG_SMP */
+ }
+#endif /* CONFIG_XEN */
register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL);
#ifdef CONFIG_SMP
register_percpu_irq(IA64_IPI_VECTOR, &ipi_irqaction);
@@ -266,10 +430,33 @@ ia64_send_ipi (int cpu, int vector, int
unsigned long phys_cpu_id;
#ifdef CONFIG_XEN
- if (running_on_xen) {
- extern void xen_send_ipi (int cpu, int vec);
- xen_send_ipi (cpu, vector);
- return;
+ if (is_running_on_xen()) {
+ int irq = -1;
+
+ /* TODO: we need to call vcpu_up here */
+ if (unlikely(vector == ap_wakeup_vector)) {
+ extern void xen_send_ipi (int cpu, int vec);
+ xen_send_ipi (cpu, vector);
+ //vcpu_prepare_and_up(cpu);
+ return;
+ }
+
+ switch(vector) {
+ case IA64_IPI_VECTOR:
+ irq = per_cpu(ipi_to_irq, cpu)[IPI_VECTOR];
+ break;
+ case IA64_IPI_RESCHEDULE:
+ irq = per_cpu(ipi_to_irq, cpu)[RESCHEDULE_VECTOR];
+ break;
+ default:
+ printk(KERN_WARNING"Unsupported IPI type 0x%x\n",
vector);
+ irq = 0;
+ break;
+ }
+
+ BUG_ON(irq < 0);
+ notify_remote_via_irq(irq);
+ return;
}
#endif /* CONFIG_XEN */
diff -r 760669a37a3a -r 5c0c59eb5f73 arch/ia64/kernel/setup.c
--- a/arch/ia64/kernel/setup.c Wed Jun 07 19:53:53 2006 -0400
+++ b/arch/ia64/kernel/setup.c Thu Jun 08 15:10:05 2006 -0400
@@ -248,7 +248,7 @@ reserve_memory (void)
n++;
#ifdef CONFIG_XEN
- if (running_on_xen) {
+ if (is_running_on_xen()) {
rsvd_region[n].start = (unsigned
long)__va((HYPERVISOR_shared_info->arch.start_info_pfn << PAGE_SHIFT));
rsvd_region[n].end = rsvd_region[n].start + PAGE_SIZE;
n++;
@@ -347,8 +347,14 @@ early_console_setup (char *cmdline)
int earlycons = 0;
#ifdef CONFIG_XEN
- if (!early_xen_console_setup(cmdline))
+#ifndef CONFIG_IA64_HP_SIM
+ if (is_running_on_xen()) {
+ extern struct console hpsim_cons;
+ hpsim_cons.flags |= CON_BOOT;
+ register_console(&hpsim_cons);
earlycons++;
+ }
+#endif
#endif
#ifdef CONFIG_SERIAL_SGI_L1_CONSOLE
{
@@ -419,7 +425,7 @@ setup_arch (char **cmdline_p)
{
unw_init();
#ifdef CONFIG_XEN
- if (running_on_xen)
+ if (is_running_on_xen())
setup_xen_features();
#endif
@@ -500,7 +506,7 @@ setup_arch (char **cmdline_p)
# endif
}
#ifdef CONFIG_XEN
- if (running_on_xen) {
+ if (is_running_on_xen()) {
extern shared_info_t *HYPERVISOR_shared_info;
extern int xen_init (void);
@@ -911,6 +917,13 @@ cpu_init (void)
/* size of physical stacked register partition plus 8 bytes: */
__get_cpu_var(ia64_phys_stacked_size_p8) = num_phys_stacked*8 + 8;
platform_cpu_init();
+#ifdef CONFIG_XEN
+ /* Need to be moved into platform_cpu_init later */
+ if (is_running_on_xen()) {
+ extern void xen_smp_intr_init(void);
+ xen_smp_intr_init();
+ }
+#endif
pm_idle = default_idle;
}
diff -r 760669a37a3a -r 5c0c59eb5f73 arch/ia64/xen/Makefile
--- a/arch/ia64/xen/Makefile Wed Jun 07 19:53:53 2006 -0400
+++ b/arch/ia64/xen/Makefile Thu Jun 08 15:10:05 2006 -0400
@@ -2,7 +2,7 @@
# Makefile for Xen components
#
-obj-y := hypercall.o xenivt.o xenentry.o xensetup.o xenpal.o xenhpski.o
xenconsole.o
+obj-y := hypercall.o xenivt.o xenentry.o xensetup.o xenpal.o xenhpski.o
obj-$(CONFIG_XEN_IA64_DOM0_VP) += hypervisor.o pci-dma-xen.o util.o
pci-dma-xen-$(CONFIG_XEN_IA64_DOM0_VP) := ../../i386/kernel/pci-dma-xen.o
diff -r 760669a37a3a -r 5c0c59eb5f73 arch/ia64/xen/drivers/xenia64_init.c
--- a/arch/ia64/xen/drivers/xenia64_init.c Wed Jun 07 19:53:53 2006 -0400
+++ b/arch/ia64/xen/drivers/xenia64_init.c Thu Jun 08 15:10:05 2006 -0400
@@ -33,7 +33,6 @@ int xen_init(void)
s->arch.start_info_pfn, xen_start_info->nr_pages,
xen_start_info->flags);
- evtchn_init();
initialized = 1;
return 0;
}
diff -r 760669a37a3a -r 5c0c59eb5f73 arch/ia64/xen/hypervisor.c
--- a/arch/ia64/xen/hypervisor.c Wed Jun 07 19:53:53 2006 -0400
+++ b/arch/ia64/xen/hypervisor.c Thu Jun 08 15:10:05 2006 -0400
@@ -314,12 +314,6 @@ gnttab_map_grant_ref_pre(struct gnttab_m
uint32_t flags;
flags = uop->flags;
- if (flags & GNTMAP_readonly) {
-#if 0
- xprintd("GNTMAP_readonly is not supported yet\n");
-#endif
- flags &= ~GNTMAP_readonly;
- }
if (flags & GNTMAP_host_map) {
if (flags & GNTMAP_application_map) {
@@ -360,52 +354,179 @@ struct address_space xen_ia64_foreign_du
///////////////////////////////////////////////////////////////////////////
// foreign mapping
+#include <linux/efi.h>
+#include <asm/meminit.h> // for IA64_GRANULE_SIZE, GRANULEROUND{UP,DOWN}()
+
+static unsigned long privcmd_resource_min = 0;
+// Xen/ia64 currently can handle pseudo physical address bits up to
+// (PAGE_SHIFT * 3)
+static unsigned long privcmd_resource_max = GRANULEROUNDDOWN((1UL <<
(PAGE_SHIFT * 3)) - 1);
+static unsigned long privcmd_resource_align = IA64_GRANULE_SIZE;
+
+static unsigned long
+md_end_addr(const efi_memory_desc_t *md)
+{
+ return md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
+}
+
+#define XEN_IA64_PRIVCMD_LEAST_GAP_SIZE (1024 * 1024 * 1024UL)
+static int
+xen_ia64_privcmd_check_size(unsigned long start, unsigned long end)
+{
+ return (start < end &&
+ (end - start) > XEN_IA64_PRIVCMD_LEAST_GAP_SIZE);
+}
+
+static int __init
+xen_ia64_privcmd_init(void)
+{
+ void *efi_map_start, *efi_map_end, *p;
+ u64 efi_desc_size;
+ efi_memory_desc_t *md;
+ unsigned long tmp_min;
+ unsigned long tmp_max;
+ unsigned long gap_size;
+ unsigned long prev_end;
+
+ if (!is_running_on_xen())
+ return -1;
+
+ efi_map_start = __va(ia64_boot_param->efi_memmap);
+ efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
+ efi_desc_size = ia64_boot_param->efi_memdesc_size;
+
+ // at first check the used highest address
+ for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+ // nothing
+ }
+ md = p - efi_desc_size;
+ privcmd_resource_min = GRANULEROUNDUP(md_end_addr(md));
+ if (xen_ia64_privcmd_check_size(privcmd_resource_min,
+ privcmd_resource_max)) {
+ goto out;
+ }
+
+ // the used highest address is too large. try to find the largest gap.
+ tmp_min = privcmd_resource_max;
+ tmp_max = 0;
+ gap_size = 0;
+ prev_end = 0;
+ for (p = efi_map_start;
+ p < efi_map_end - efi_desc_size;
+ p += efi_desc_size) {
+ unsigned long end;
+ efi_memory_desc_t* next;
+ unsigned long next_start;
+
+ md = p;
+ end = md_end_addr(md);
+ if (end > privcmd_resource_max) {
+ break;
+ }
+ if (end < prev_end) {
+ // work around.
+ // Xen may pass incompletely sorted memory
+ // descriptors like
+ // [x, x + length]
+ // [x, x]
+ // this order should be reversed.
+ continue;
+ }
+ next = p + efi_desc_size;
+ next_start = next->phys_addr;
+ if (next_start > privcmd_resource_max) {
+ next_start = privcmd_resource_max;
+ }
+ if (end < next_start && gap_size < (next_start - end)) {
+ tmp_min = end;
+ tmp_max = next_start;
+ gap_size = tmp_max - tmp_min;
+ }
+ prev_end = end;
+ }
+
+ privcmd_resource_min = GRANULEROUNDUP(tmp_min);
+ if (xen_ia64_privcmd_check_size(privcmd_resource_min, tmp_max)) {
+ privcmd_resource_max = tmp_max;
+ goto out;
+ }
+
+ privcmd_resource_min = tmp_min;
+ privcmd_resource_max = tmp_max;
+ if (!xen_ia64_privcmd_check_size(privcmd_resource_min,
+ privcmd_resource_max)) {
+ // Any large enough gap isn't found.
+ // go ahead anyway with the warning hoping that large region
+ // won't be requested.
+ printk(KERN_WARNING "xen privcmd: large enough region for
privcmd mmap is not found.\n");
+ }
+
+out:
+ printk(KERN_INFO "xen privcmd uses pseudo physical addr range [0x%lx,
0x%lx] (%ldMB)\n",
+ privcmd_resource_min, privcmd_resource_max,
+ (privcmd_resource_max - privcmd_resource_min) >> 20);
+ BUG_ON(privcmd_resource_min >= privcmd_resource_max);
+ return 0;
+}
+late_initcall(xen_ia64_privcmd_init);
struct xen_ia64_privcmd_entry {
atomic_t map_count;
- struct page* page;
+#define INVALID_GPFN (~0UL)
+ unsigned long gpfn;
+};
+
+struct xen_ia64_privcmd_range {
+ atomic_t ref_count;
+ unsigned long pgoff; // in PAGE_SIZE
+ struct resource* res;
+
+ unsigned long num_entries;
+ struct xen_ia64_privcmd_entry entries[0];
+};
+
+struct xen_ia64_privcmd_vma {
+ struct xen_ia64_privcmd_range* range;
+
+ unsigned long num_entries;
+ struct xen_ia64_privcmd_entry* entries;
};
static void
xen_ia64_privcmd_init_entry(struct xen_ia64_privcmd_entry* entry)
{
atomic_set(&entry->map_count, 0);
- entry->page = NULL;
-}
-
-//TODO alloc_page() to allocate pseudo physical address space is
-// waste of memory.
-// When vti domain is created, qemu maps all of vti domain pages which
-// reaches to several hundred megabytes at least.
-// remove alloc_page().
+ entry->gpfn = INVALID_GPFN;
+}
+
static int
xen_ia64_privcmd_entry_mmap(struct vm_area_struct* vma,
unsigned long addr,
- struct xen_ia64_privcmd_entry* entry,
+ struct xen_ia64_privcmd_range* privcmd_range,
+ int i,
unsigned long mfn,
pgprot_t prot,
domid_t domid)
{
int error = 0;
- struct page* page;
+ struct xen_ia64_privcmd_entry* entry = &privcmd_range->entries[i];
unsigned long gpfn;
+ unsigned long flags;
BUG_ON((addr & ~PAGE_MASK) != 0);
BUG_ON(mfn == INVALID_MFN);
- if (entry->page != NULL) {
+ if (entry->gpfn != INVALID_GPFN) {
error = -EBUSY;
goto out;
}
- page = alloc_page(GFP_KERNEL);
- if (page == NULL) {
- error = -ENOMEM;
- goto out;
- }
- gpfn = page_to_pfn(page);
-
- error = HYPERVISOR_add_physmap(gpfn, mfn, 0/* prot:XXX */,
- domid);
+ gpfn = (privcmd_range->res->start >> PAGE_SHIFT) + i;
+
+ flags = ASSIGN_writable;
+ if (pgprot_val(prot) == PROT_READ) {
+ flags = ASSIGN_readonly;
+ }
+ error = HYPERVISOR_add_physmap(gpfn, mfn, flags, domid);
if (error != 0) {
goto out;
}
@@ -413,15 +534,13 @@ xen_ia64_privcmd_entry_mmap(struct vm_ar
prot = vma->vm_page_prot;
error = remap_pfn_range(vma, addr, gpfn, 1 << PAGE_SHIFT, prot);
if (error != 0) {
- (void)HYPERVISOR_zap_physmap(gpfn, 0);
- error = HYPERVISOR_populate_physmap(gpfn, 0, 0);
+ error = HYPERVISOR_zap_physmap(gpfn, 0);
if (error) {
BUG();//XXX
}
- __free_page(page);
} else {
atomic_inc(&entry->map_count);
- entry->page = page;
+ entry->gpfn = gpfn;
}
out:
@@ -429,30 +548,28 @@ out:
}
static void
-xen_ia64_privcmd_entry_munmap(struct xen_ia64_privcmd_entry* entry)
-{
- struct page* page = entry->page;
- unsigned long gpfn = page_to_pfn(page);
+xen_ia64_privcmd_entry_munmap(struct xen_ia64_privcmd_range* privcmd_range,
+ int i)
+{
+ struct xen_ia64_privcmd_entry* entry = &privcmd_range->entries[i];
+ unsigned long gpfn = entry->gpfn;
+ //gpfn = (privcmd_range->res->start >> PAGE_SHIFT) +
+ // (vma->vm_pgoff - privcmd_range->pgoff);
int error;
error = HYPERVISOR_zap_physmap(gpfn, 0);
if (error) {
BUG();//XXX
}
-
- error = HYPERVISOR_populate_physmap(gpfn, 0, 0);
- if (error) {
- BUG();//XXX
- }
-
- entry->page = NULL;
- __free_page(page);
+ entry->gpfn = INVALID_GPFN;
}
static int
-xen_ia64_privcmd_entry_open(struct xen_ia64_privcmd_entry* entry)
-{
- if (entry->page != NULL) {
+xen_ia64_privcmd_entry_open(struct xen_ia64_privcmd_range* privcmd_range,
+ int i)
+{
+ struct xen_ia64_privcmd_entry* entry = &privcmd_range->entries[i];
+ if (entry->gpfn != INVALID_GPFN) {
atomic_inc(&entry->map_count);
} else {
BUG_ON(atomic_read(&entry->map_count) != 0);
@@ -460,27 +577,15 @@ xen_ia64_privcmd_entry_open(struct xen_i
}
static int
-xen_ia64_privcmd_entry_close(struct xen_ia64_privcmd_entry* entry)
-{
- if (entry->page != NULL && atomic_dec_and_test(&entry->map_count)) {
- xen_ia64_privcmd_entry_munmap(entry);
- }
-}
-
-struct xen_ia64_privcmd_range {
- atomic_t ref_count;
- unsigned long pgoff; // in PAGE_SIZE
-
- unsigned long num_entries;
- struct xen_ia64_privcmd_entry entries[0];
-};
-
-struct xen_ia64_privcmd_vma {
- struct xen_ia64_privcmd_range* range;
-
- unsigned long num_entries;
- struct xen_ia64_privcmd_entry* entries;
-};
+xen_ia64_privcmd_entry_close(struct xen_ia64_privcmd_range* privcmd_range,
+ int i)
+{
+ struct xen_ia64_privcmd_entry* entry = &privcmd_range->entries[i];
+ if (entry->gpfn != INVALID_GPFN &&
+ atomic_dec_and_test(&entry->map_count)) {
+ xen_ia64_privcmd_entry_munmap(privcmd_range, i);
+ }
+}
static void xen_ia64_privcmd_vma_open(struct vm_area_struct* vma);
static void xen_ia64_privcmd_vma_close(struct vm_area_struct* vma);
@@ -507,7 +612,7 @@ __xen_ia64_privcmd_vma_open(struct vm_ar
privcmd_vma->entries = &privcmd_range->entries[entry_offset];
vma->vm_private_data = privcmd_vma;
for (i = 0; i < privcmd_vma->num_entries; i++) {
- xen_ia64_privcmd_entry_open(&privcmd_vma->entries[i]);
+ xen_ia64_privcmd_entry_open(privcmd_range, entry_offset + i);
}
vma->vm_private_data = privcmd_vma;
@@ -533,10 +638,11 @@ xen_ia64_privcmd_vma_close(struct vm_are
struct xen_ia64_privcmd_vma* privcmd_vma =
(struct xen_ia64_privcmd_vma*)vma->vm_private_data;
struct xen_ia64_privcmd_range* privcmd_range = privcmd_vma->range;
+ unsigned long entry_offset = vma->vm_pgoff - privcmd_range->pgoff;
unsigned long i;
for (i = 0; i < privcmd_vma->num_entries; i++) {
- xen_ia64_privcmd_entry_close(&privcmd_vma->entries[i]);
+ xen_ia64_privcmd_entry_close(privcmd_range, entry_offset + i);
}
vma->vm_private_data = NULL;
kfree(privcmd_vma);
@@ -547,9 +653,11 @@ xen_ia64_privcmd_vma_close(struct vm_are
struct xen_ia64_privcmd_entry* entry =
&privcmd_range->entries[i];
BUG_ON(atomic_read(&entry->map_count) != 0);
- BUG_ON(entry->page != NULL);
+ BUG_ON(entry->gpfn != INVALID_GPFN);
}
#endif
+ release_resource(privcmd_range->res);
+ kfree(privcmd_range->res);
vfree(privcmd_range);
}
}
@@ -557,13 +665,18 @@ int
int
privcmd_mmap(struct file * file, struct vm_area_struct * vma)
{
- unsigned long num_entries = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
- struct xen_ia64_privcmd_range* privcmd_range;
- struct xen_ia64_privcmd_vma* privcmd_vma;
+ int error;
+ unsigned long size = vma->vm_end - vma->vm_start;
+ unsigned long num_entries = size >> PAGE_SHIFT;
+ struct xen_ia64_privcmd_range* privcmd_range = NULL;
+ struct xen_ia64_privcmd_vma* privcmd_vma = NULL;
+ struct resource* res = NULL;
unsigned long i;
- BUG_ON(!running_on_xen);
+ BUG_ON(!is_running_on_xen());
BUG_ON(file->private_data != NULL);
+
+ error = -ENOMEM;
privcmd_range =
vmalloc(sizeof(*privcmd_range) +
sizeof(privcmd_range->entries[0]) * num_entries);
@@ -574,6 +687,18 @@ privcmd_mmap(struct file * file, struct
if (privcmd_vma == NULL) {
goto out_enomem1;
}
+ res = kzalloc(sizeof(*res), GFP_KERNEL);
+ if (res == NULL) {
+ goto out_enomem1;
+ }
+ res->name = "Xen privcmd mmap";
+ error = allocate_resource(&iomem_resource, res, size,
+ privcmd_resource_min, privcmd_resource_max,
+ privcmd_resource_align, NULL, NULL);
+ if (error) {
+ goto out_enomem1;
+ }
+ privcmd_range->res = res;
/* DONTCOPY is essential for Xen as copy_page_range is broken. */
vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY | VM_PFNMAP;
@@ -589,10 +714,11 @@ privcmd_mmap(struct file * file, struct
return 0;
out_enomem1:
+ kfree(res);
kfree(privcmd_vma);
out_enomem0:
vfree(privcmd_range);
- return -ENOMEM;
+ return error;
}
int
@@ -605,10 +731,13 @@ direct_remap_pfn_range(struct vm_area_st
{
struct xen_ia64_privcmd_vma* privcmd_vma =
(struct xen_ia64_privcmd_vma*)vma->vm_private_data;
+ struct xen_ia64_privcmd_range* privcmd_range = privcmd_vma->range;
+ unsigned long entry_offset = vma->vm_pgoff - privcmd_range->pgoff;
+
unsigned long i;
unsigned long offset;
int error = 0;
- BUG_ON(!running_on_xen);
+ BUG_ON(!is_running_on_xen());
#if 0
if (prot != vm->vm_page_prot) {
@@ -618,9 +747,7 @@ direct_remap_pfn_range(struct vm_area_st
i = (address - vma->vm_start) >> PAGE_SHIFT;
for (offset = 0; offset < size; offset += PAGE_SIZE) {
- struct xen_ia64_privcmd_entry* entry =
- &privcmd_vma->entries[i];
- error = xen_ia64_privcmd_entry_mmap(vma, (address + offset) &
PAGE_MASK, entry, mfn, prot, domid);
+ error = xen_ia64_privcmd_entry_mmap(vma, (address + offset) &
PAGE_MASK, privcmd_range, entry_offset + i, mfn, prot, domid);
if (error != 0) {
break;
}
diff -r 760669a37a3a -r 5c0c59eb5f73 arch/ia64/xen/xenivt.S
--- a/arch/ia64/xen/xenivt.S Wed Jun 07 19:53:53 2006 -0400
+++ b/arch/ia64/xen/xenivt.S Thu Jun 08 15:10:05 2006 -0400
@@ -206,9 +206,9 @@ ENTRY(vhpt_miss)
mov r24=r8
mov r8=r18
;;
-(p10) XEN_HYPER_ITC_D
- ;;
-(p11) XEN_HYPER_ITC_I
+(p10) XEN_HYPER_ITC_I
+ ;;
+(p11) XEN_HYPER_ITC_D
;;
mov r8=r24
;;
@@ -799,7 +799,16 @@ 1: ld8 r18=[r17]
;;
(p6) cmp.eq p6,p7=r26,r18 // Only compare if page is
present
;;
+#ifdef CONFIG_XEN
+(p6) mov r18=r8
+(p6) mov r8=r25
+ ;;
+(p6) XEN_HYPER_ITC_D
+ ;;
+(p6) mov r8=r18
+#else
(p6) itc.d r25 // install updated PTE
+#endif
;;
/*
* Tell the assemblers dependency-violation checker that the above
"itc" instructions
@@ -2038,6 +2047,7 @@ GLOBAL_ENTRY(xen_bsw1)
ld8 r28=[r30],16; ld8 r29=[r31],16;;
ld8 r30=[r30]; ld8 r31=[r31];;
br.ret.sptk.many b0
+END(xen_bsw1)
#endif
.org ia64_ivt+0x7f00
@@ -2130,5 +2140,32 @@ non_ia32_syscall:
mov rp=r15
br.ret.sptk.many rp
END(dispatch_to_ia32_handler)
-
#endif /* CONFIG_IA32_SUPPORT */
+
+#ifdef CONFIG_XEN
+ .section .text,"ax"
+GLOBAL_ENTRY(xen_event_callback)
+ mov r31=pr // prepare to save predicates
+ ;;
+ SAVE_MIN_WITH_COVER // uses r31; defines r2 and r3
+ ;;
+ movl r3=XSI_PSR_IC
+ mov r14=1
+ ;;
+ st4 [r3]=r14
+ ;;
+ adds r3=8,r2 // set up second base pointer for SAVE_REST
+ srlz.i // ensure everybody knows psr.ic is back on
+ ;;
+ SAVE_REST
+ ;;
+ alloc r14=ar.pfs,0,0,1,0 // must be first in an insn group
+ add out0=16,sp // pass pointer to pt_regs as first arg
+ ;;
+ srlz.d // make sure we see the effect of cr.ivr
+ movl r14=ia64_leave_kernel
+ ;;
+ mov rp=r14
+ br.call.sptk.many b6=evtchn_do_upcall
+END(xen_event_callback)
+#endif
diff -r 760669a37a3a -r 5c0c59eb5f73 arch/powerpc/Kconfig
--- a/arch/powerpc/Kconfig Wed Jun 07 19:53:53 2006 -0400
+++ b/arch/powerpc/Kconfig Thu Jun 08 15:10:05 2006 -0400
@@ -400,9 +400,14 @@ config PPC_XEN
config PPC_XEN
bool "Enable Xen compatible kernel"
depends PPC_MULTIPLATFORM && PPC64 && PPC_MAPLE && PPC_PSERIES && SMP
+ select XEN
select XEN_PRIVILEGED_GUEST
select XEN_UNPRIVILEGED_GUEST
select XEN_XENCOMM
+ reverse XEN_BALLOON
+ reverse XEN_REBOOT
+ reverse XEN_SMPBOOT
+
help
This option will compile a kernel compatible with Xen hypervisor
diff -r 760669a37a3a -r 5c0c59eb5f73 arch/x86_64/kernel/process-xen.c
--- a/arch/x86_64/kernel/process-xen.c Wed Jun 07 19:53:53 2006 -0400
+++ b/arch/x86_64/kernel/process-xen.c Thu Jun 08 15:10:05 2006 -0400
@@ -60,6 +60,8 @@
#include <asm/ia32.h>
#include <asm/idle.h>
+#include <xen/cpu_hotplug.h>
+
asmlinkage extern void ret_from_fork(void);
unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED;
@@ -111,8 +113,6 @@ void exit_idle(void)
}
/* XXX XEN doesn't use default_idle(), poll_idle(). Use xen_idle() instead. */
-extern void stop_hz_timer(void);
-extern void start_hz_timer(void);
void xen_idle(void)
{
local_irq_disable();
@@ -122,10 +122,7 @@ void xen_idle(void)
else {
clear_thread_flag(TIF_POLLING_NRFLAG);
smp_mb__after_clear_bit();
- stop_hz_timer();
- /* Blocking includes an implicit local_irq_enable(). */
- HYPERVISOR_block();
- start_hz_timer();
+ safe_halt();
set_thread_flag(TIF_POLLING_NRFLAG);
}
}
@@ -138,11 +135,7 @@ static inline void play_dead(void)
cpu_clear(smp_processor_id(), cpu_initialized);
preempt_enable_no_resched();
HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL);
- /* Same as drivers/xen/core/smpboot.c:cpu_bringup(). */
- cpu_init();
- touch_softlockup_watchdog();
- preempt_disable();
- local_irq_enable();
+ cpu_bringup();
}
#else
static inline void play_dead(void)
diff -r 760669a37a3a -r 5c0c59eb5f73 arch/x86_64/kernel/setup-xen.c
--- a/arch/x86_64/kernel/setup-xen.c Wed Jun 07 19:53:53 2006 -0400
+++ b/arch/x86_64/kernel/setup-xen.c Thu Jun 08 15:10:05 2006 -0400
@@ -693,13 +693,6 @@ void __init setup_arch(char **cmdline_p)
setup_xen_features();
- if (xen_feature(XENFEAT_auto_translated_physmap) &&
- xen_start_info->shared_info < xen_start_info->nr_pages) {
- HYPERVISOR_shared_info =
- (shared_info_t *)__va(xen_start_info->shared_info);
- memset(empty_zero_page, 0, sizeof(empty_zero_page));
- }
-
HYPERVISOR_vm_assist(VMASST_CMD_enable,
VMASST_TYPE_writable_pagetables);
@@ -860,14 +853,6 @@ void __init setup_arch(char **cmdline_p)
#ifdef CONFIG_XEN
{
int i, j, k, fpp;
- unsigned long va;
-
- /* 'Initial mapping' of initrd must be destroyed. */
- for (va = xen_start_info->mod_start;
- va < (xen_start_info->mod_start+xen_start_info->mod_len);
- va += PAGE_SIZE) {
- HYPERVISOR_update_va_mapping(va, __pte_ma(0), 0);
- }
if (!xen_feature(XENFEAT_auto_translated_physmap)) {
/* Make sure we have a large enough P->M table. */
@@ -882,14 +867,6 @@ void __init setup_arch(char **cmdline_p)
__pa(xen_start_info->mfn_list),
PFN_PHYS(PFN_UP(xen_start_info->nr_pages *
sizeof(unsigned long))));
-
- /* Destroyed 'initial mapping' of old p2m table. */
- for (va = xen_start_info->mfn_list;
- va < (xen_start_info->mfn_list +
- (xen_start_info->nr_pages*sizeof(unsigned
long)));
- va += PAGE_SIZE) {
- HYPERVISOR_update_va_mapping(va, __pte_ma(0),
0);
- }
/*
* Initialise the list of the frames that specify the
diff -r 760669a37a3a -r 5c0c59eb5f73 arch/x86_64/kernel/smp-xen.c
--- a/arch/x86_64/kernel/smp-xen.c Wed Jun 07 19:53:53 2006 -0400
+++ b/arch/x86_64/kernel/smp-xen.c Thu Jun 08 15:10:05 2006 -0400
@@ -488,7 +488,7 @@ static void smp_really_stop_cpu(void *du
{
smp_stop_cpu();
for (;;)
- asm("hlt");
+ halt();
}
void smp_send_stop(void)
diff -r 760669a37a3a -r 5c0c59eb5f73 arch/x86_64/mm/init-xen.c
--- a/arch/x86_64/mm/init-xen.c Wed Jun 07 19:53:53 2006 -0400
+++ b/arch/x86_64/mm/init-xen.c Thu Jun 08 15:10:05 2006 -0400
@@ -710,7 +710,34 @@ void __meminit init_memory_mapping(unsig
set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys));
}
- BUG_ON(!after_bootmem && start_pfn != table_end);
+ if (!after_bootmem) {
+ BUG_ON(start_pfn != table_end);
+
+ /* Re-vector virtual addresses pointing into the initial
+ mapping to the just-established permanent ones. */
+ xen_start_info = __va(__pa(xen_start_info));
+ xen_start_info->pt_base = (unsigned long)
+ __va(__pa(xen_start_info->pt_base));
+ if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+ phys_to_machine_mapping =
+ __va(__pa(xen_start_info->mfn_list));
+ xen_start_info->mfn_list = (unsigned long)
+ phys_to_machine_mapping;
+ }
+ if (xen_start_info->mod_start)
+ xen_start_info->mod_start = (unsigned long)
+ __va(__pa(xen_start_info->mod_start));
+
+ /* Destroy the Xen-created mappings beyond the kernel image as
+ * well as the temporary mappings created above. Prevents
+ * overlap with modules area (if init mapping is very big).
+ */
+ start = PAGE_ALIGN((unsigned long)_end);
+ end = __START_KERNEL_map + (table_end << PAGE_SHIFT);
+ for (; start < end; start += PAGE_SIZE)
+ WARN_ON(HYPERVISOR_update_va_mapping(
+ start, __pte_ma(0), 0));
+ }
__flush_tlb_all();
}
@@ -796,15 +823,11 @@ void __init paging_init(void)
free_area_init_node(0, NODE_DATA(0), zones,
__pa(PAGE_OFFSET) >> PAGE_SHIFT, holes);
- if (!xen_feature(XENFEAT_auto_translated_physmap) ||
- xen_start_info->shared_info >= xen_start_info->nr_pages) {
- /* Switch to the real shared_info page, and clear the
- * dummy page. */
- set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
- HYPERVISOR_shared_info =
- (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
- memset(empty_zero_page, 0, sizeof(empty_zero_page));
- }
+ /* Switch to the real shared_info page, and clear the
+ * dummy page. */
+ set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
+ HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
+ memset(empty_zero_page, 0, sizeof(empty_zero_page));
init_mm.context.pinned = 1;
diff -r 760669a37a3a -r 5c0c59eb5f73 drivers/xen/Kconfig
--- a/drivers/xen/Kconfig Wed Jun 07 19:53:53 2006 -0400
+++ b/drivers/xen/Kconfig Thu Jun 08 15:10:05 2006 -0400
@@ -6,7 +6,7 @@ mainmenu "Xen Configuration"
config XEN
bool
- default y if X86_XEN || X86_64_XEN || PPC_XEN
+ default y if X86_XEN || X86_64_XEN
help
This is the Linux Xen port.
@@ -234,24 +234,27 @@ config XEN_UTIL
config XEN_BALLOON
bool
- default y if ! PPC_XEN
+ default y
+
+config XEN_DEVMEM
+ bool
+ default y
config XEN_SKBUFF
bool
+ default y
depends on NET
- default y
config XEN_REBOOT
bool
- default y if ! PPC_XEN
+ default y
config XEN_SMPBOOT
bool
+ default y
depends on SMP
- default y if ! PPC_XEN
config XEN_XENCOMM
bool
default n
-
endif
diff -r 760669a37a3a -r 5c0c59eb5f73 drivers/xen/Makefile
--- a/drivers/xen/Makefile Wed Jun 07 19:53:53 2006 -0400
+++ b/drivers/xen/Makefile Thu Jun 08 15:10:05 2006 -0400
@@ -1,5 +1,4 @@ obj-y += core/
obj-y += core/
-obj-y += char/
obj-y += console/
obj-y += evtchn/
obj-y += privcmd/
@@ -7,6 +6,7 @@ obj-y += xenbus/
obj-$(CONFIG_XEN_UTIL) += util.o
obj-$(CONFIG_XEN_BALLOON) += balloon/
+obj-$(CONFIG_XEN_DEVMEM) += char/
obj-$(CONFIG_XEN_BLKDEV_BACKEND) += blkback/
obj-$(CONFIG_XEN_NETDEV_BACKEND) += netback/
obj-$(CONFIG_XEN_TPMDEV_BACKEND) += tpmback/
diff -r 760669a37a3a -r 5c0c59eb5f73 drivers/xen/balloon/balloon.c
--- a/drivers/xen/balloon/balloon.c Wed Jun 07 19:53:53 2006 -0400
+++ b/drivers/xen/balloon/balloon.c Thu Jun 08 15:10:05 2006 -0400
@@ -360,12 +360,6 @@ static void balloon_process(void *unused
/* Resets the Xen limit, sets new target, and kicks off processing. */
static void set_new_target(unsigned long target)
{
- unsigned long min_target;
-
- /* Do not allow target to reduce below 2% of maximum memory size. */
- min_target = max_pfn / 50;
- target = max(target, min_target);
-
/* No need for lock. Not read-modify-write updates. */
hard_limit = ~0UL;
target_pages = target;
diff -r 760669a37a3a -r 5c0c59eb5f73 drivers/xen/blkfront/blkfront.c
--- a/drivers/xen/blkfront/blkfront.c Wed Jun 07 19:53:53 2006 -0400
+++ b/drivers/xen/blkfront/blkfront.c Thu Jun 08 15:10:05 2006 -0400
@@ -452,10 +452,6 @@ int blkif_ioctl(struct inode *inode, str
command, (long)argument, inode->i_rdev);
switch (command) {
- case HDIO_GETGEO:
- /* return ENOSYS to use defaults */
- return -ENOSYS;
-
case CDROMMULTISESSION:
DPRINTK("FIXME: support multisession CDs later\n");
for (i = 0; i < sizeof(struct cdrom_multisession); i++)
@@ -469,6 +465,23 @@ int blkif_ioctl(struct inode *inode, str
return -EINVAL; /* same return as native Linux */
}
+ return 0;
+}
+
+
+int blkif_getgeo(struct block_device *bd, struct hd_geometry *hg)
+{
+ /* We don't have real geometry info, but let's at least return
+ values consistent with the size of the device */
+ sector_t nsect = get_capacity(bd->bd_disk);
+ sector_t cylinders = nsect;
+
+ hg->heads = 0xff;
+ hg->sectors = 0x3f;
+ sector_div(cylinders, hg->heads * hg->sectors);
+ hg->cylinders = cylinders;
+ if ((sector_t)(hg->cylinders + 1) * hg->heads * hg->sectors < nsect)
+ hg->cylinders = 0xffff;
return 0;
}
diff -r 760669a37a3a -r 5c0c59eb5f73 drivers/xen/blkfront/block.h
--- a/drivers/xen/blkfront/block.h Wed Jun 07 19:53:53 2006 -0400
+++ b/drivers/xen/blkfront/block.h Thu Jun 08 15:10:05 2006 -0400
@@ -140,6 +140,7 @@ extern int blkif_release(struct inode *i
extern int blkif_release(struct inode *inode, struct file *filep);
extern int blkif_ioctl(struct inode *inode, struct file *filep,
unsigned command, unsigned long argument);
+extern int blkif_getgeo(struct block_device *, struct hd_geometry *);
extern int blkif_check(dev_t dev);
extern int blkif_revalidate(dev_t dev);
extern void do_blkif_request (request_queue_t *rq);
diff -r 760669a37a3a -r 5c0c59eb5f73 drivers/xen/blkfront/vbd.c
--- a/drivers/xen/blkfront/vbd.c Wed Jun 07 19:53:53 2006 -0400
+++ b/drivers/xen/blkfront/vbd.c Thu Jun 08 15:10:05 2006 -0400
@@ -91,6 +91,7 @@ static struct block_device_operations xl
.open = blkif_open,
.release = blkif_release,
.ioctl = blkif_ioctl,
+ .getgeo = blkif_getgeo
};
DEFINE_SPINLOCK(blkif_io_lock);
diff -r 760669a37a3a -r 5c0c59eb5f73 drivers/xen/core/Makefile
--- a/drivers/xen/core/Makefile Wed Jun 07 19:53:53 2006 -0400
+++ b/drivers/xen/core/Makefile Thu Jun 08 15:10:05 2006 -0400
@@ -1,15 +1,17 @@
+#
+# Makefile for the linux kernel.
+#
#
# Makefile for the linux kernel.
#
obj-y := evtchn.o gnttab.o features.o
-
obj-$(CONFIG_PROC_FS) += xen_proc.o
obj-$(CONFIG_SYSFS) += hypervisor_sysfs.o
obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o
obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o
+obj-$(CONFIG_IA64) += xenia64_init.o
obj-$(CONFIG_XEN_SKBUFF) += skbuff.o
obj-$(CONFIG_XEN_REBOOT) += reboot.o
obj-$(CONFIG_XEN_SMPBOOT) += smpboot.o
-obj-$(CONFIG_XEN_XENCOMM) += xencomm.o
diff -r 760669a37a3a -r 5c0c59eb5f73 drivers/xen/core/cpu_hotplug.c
--- a/drivers/xen/core/cpu_hotplug.c Wed Jun 07 19:53:53 2006 -0400
+++ b/drivers/xen/core/cpu_hotplug.c Thu Jun 08 15:10:05 2006 -0400
@@ -160,7 +160,7 @@ void smp_resume(void)
vcpu_hotplug(cpu);
}
-int cpu_up_is_allowed(unsigned int cpu)
+int cpu_up_check(unsigned int cpu)
{
int rc = 0;
diff -r 760669a37a3a -r 5c0c59eb5f73 drivers/xen/core/smpboot.c
--- a/drivers/xen/core/smpboot.c Wed Jun 07 19:53:53 2006 -0400
+++ b/drivers/xen/core/smpboot.c Thu Jun 08 15:10:05 2006 -0400
@@ -87,9 +87,8 @@ void __init prefill_possible_map(void)
for (i = 0; i < NR_CPUS; i++) {
rc = HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL);
- if (rc == -ENOENT)
- break;
- cpu_set(i, cpu_possible_map);
+ if (rc >= 0)
+ cpu_set(i, cpu_possible_map);
}
}
@@ -148,12 +147,17 @@ static void xen_smp_intr_exit(unsigned i
}
#endif
-static void cpu_bringup(void)
+void cpu_bringup(void)
{
cpu_init();
touch_softlockup_watchdog();
preempt_disable();
local_irq_enable();
+}
+
+static void cpu_bringup_and_idle(void)
+{
+ cpu_bringup();
cpu_idle();
}
@@ -178,7 +182,7 @@ void cpu_initialize_context(unsigned int
ctxt.user_regs.fs = 0;
ctxt.user_regs.gs = 0;
ctxt.user_regs.ss = __KERNEL_DS;
- ctxt.user_regs.eip = (unsigned long)cpu_bringup;
+ ctxt.user_regs.eip = (unsigned long)cpu_bringup_and_idle;
ctxt.user_regs.eflags = X86_EFLAGS_IF | 0x1000; /* IOPL_RING1 */
memset(&ctxt.fpu_ctxt, 0, sizeof(ctxt.fpu_ctxt));
@@ -202,7 +206,7 @@ void cpu_initialize_context(unsigned int
ctxt.failsafe_callback_cs = __KERNEL_CS;
ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback;
- ctxt.ctrlreg[3] = virt_to_mfn(swapper_pg_dir) << PAGE_SHIFT;
+ ctxt.ctrlreg[3] = xen_pfn_to_cr3(virt_to_mfn(swapper_pg_dir));
#else /* __x86_64__ */
ctxt.user_regs.cs = __KERNEL_CS;
ctxt.user_regs.esp = idle->thread.rsp0 - sizeof(struct pt_regs);
@@ -214,7 +218,7 @@ void cpu_initialize_context(unsigned int
ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback;
ctxt.syscall_callback_eip = (unsigned long)system_call;
- ctxt.ctrlreg[3] = virt_to_mfn(init_level4_pgt) << PAGE_SHIFT;
+ ctxt.ctrlreg[3] = xen_pfn_to_cr3(virt_to_mfn(init_level4_pgt));
ctxt.gs_base_kernel = (unsigned long)(cpu_pda(cpu));
#endif
@@ -395,7 +399,7 @@ int __devinit __cpu_up(unsigned int cpu)
{
int rc;
- rc = cpu_up_is_allowed(cpu);
+ rc = cpu_up_check(cpu);
if (rc)
return rc;
diff -r 760669a37a3a -r 5c0c59eb5f73 drivers/xen/netback/loopback.c
--- a/drivers/xen/netback/loopback.c Wed Jun 07 19:53:53 2006 -0400
+++ b/drivers/xen/netback/loopback.c Thu Jun 08 15:10:05 2006 -0400
@@ -146,11 +146,13 @@ static void loopback_construct(struct ne
dev->hard_start_xmit = loopback_start_xmit;
dev->get_stats = loopback_get_stats;
dev->set_multicast_list = loopback_set_multicast_list;
+ dev->change_mtu = NULL; /* allow arbitrary mtu */
dev->tx_queue_len = 0;
dev->features = (NETIF_F_HIGHDMA |
NETIF_F_LLTX |
+ NETIF_F_SG |
NETIF_F_IP_CSUM);
SET_ETHTOOL_OPS(dev, &network_ethtool_ops);
diff -r 760669a37a3a -r 5c0c59eb5f73 drivers/xen/netback/netback.c
--- a/drivers/xen/netback/netback.c Wed Jun 07 19:53:53 2006 -0400
+++ b/drivers/xen/netback/netback.c Thu Jun 08 15:10:05 2006 -0400
@@ -458,6 +458,9 @@ inline static void net_tx_action_dealloc
dc = dealloc_cons;
dp = dealloc_prod;
+ /* Ensure we see all indexes enqueued by netif_idx_release(). */
+ smp_rmb();
+
/*
* Free up any grants we have finished using
*/
@@ -487,6 +490,177 @@ inline static void net_tx_action_dealloc
}
}
+static void netbk_tx_err(netif_t *netif, RING_IDX end)
+{
+ RING_IDX cons = netif->tx.req_cons;
+
+ do {
+ netif_tx_request_t *txp = RING_GET_REQUEST(&netif->tx, cons);
+ make_tx_response(netif, txp->id, NETIF_RSP_ERROR);
+ } while (++cons < end);
+ netif->tx.req_cons = cons;
+ netif_schedule_work(netif);
+ netif_put(netif);
+}
+
+static int netbk_count_requests(netif_t *netif, netif_tx_request_t *txp,
+ int work_to_do)
+{
+ netif_tx_request_t *first = txp;
+ RING_IDX cons = netif->tx.req_cons;
+ int frags = 1;
+
+ while (txp->flags & NETTXF_more_data) {
+ if (frags >= work_to_do) {
+ DPRINTK("Need more frags\n");
+ return -frags;
+ }
+
+ txp = RING_GET_REQUEST(&netif->tx, cons + frags);
+ if (txp->size > first->size) {
+ DPRINTK("Frags galore\n");
+ return -frags;
+ }
+
+ first->size -= txp->size;
+ frags++;
+
+ if (unlikely((txp->offset + txp->size) > PAGE_SIZE)) {
+ DPRINTK("txp->offset: %x, size: %u\n",
+ txp->offset, txp->size);
+ return -frags;
+ }
+ }
+
+ return frags;
+}
+
+static gnttab_map_grant_ref_t *netbk_get_requests(netif_t *netif,
+ struct sk_buff *skb,
+ gnttab_map_grant_ref_t *mop)
+{
+ struct skb_shared_info *shinfo = skb_shinfo(skb);
+ skb_frag_t *frags = shinfo->frags;
+ netif_tx_request_t *txp;
+ unsigned long pending_idx = *((u16 *)skb->data);
+ RING_IDX cons = netif->tx.req_cons + 1;
+ int i, start;
+
+ /* Skip first skb fragment if it is on same page as header fragment. */
+ start = ((unsigned long)shinfo->frags[0].page == pending_idx);
+
+ for (i = start; i < shinfo->nr_frags; i++) {
+ txp = RING_GET_REQUEST(&netif->tx, cons++);
+ pending_idx = pending_ring[MASK_PEND_IDX(pending_cons++)];
+
+ gnttab_set_map_op(mop++, MMAP_VADDR(pending_idx),
+ GNTMAP_host_map | GNTMAP_readonly,
+ txp->gref, netif->domid);
+
+ memcpy(&pending_tx_info[pending_idx].req, txp, sizeof(*txp));
+ netif_get(netif);
+ pending_tx_info[pending_idx].netif = netif;
+ frags[i].page = (void *)pending_idx;
+ }
+
+ return mop;
+}
+
+static int netbk_tx_check_mop(struct sk_buff *skb,
+ gnttab_map_grant_ref_t **mopp)
+{
+ gnttab_map_grant_ref_t *mop = *mopp;
+ int pending_idx = *((u16 *)skb->data);
+ netif_t *netif = pending_tx_info[pending_idx].netif;
+ netif_tx_request_t *txp;
+ struct skb_shared_info *shinfo = skb_shinfo(skb);
+ int nr_frags = shinfo->nr_frags;
+ int i, err, start;
+
+ /* Check status of header. */
+ err = mop->status;
+ if (unlikely(err)) {
+ txp = &pending_tx_info[pending_idx].req;
+ make_tx_response(netif, txp->id, NETIF_RSP_ERROR);
+ pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
+ netif_put(netif);
+ } else {
+ set_phys_to_machine(
+ __pa(MMAP_VADDR(pending_idx)) >> PAGE_SHIFT,
+ FOREIGN_FRAME(mop->dev_bus_addr >> PAGE_SHIFT));
+ grant_tx_handle[pending_idx] = mop->handle;
+ }
+
+ /* Skip first skb fragment if it is on same page as header fragment. */
+ start = ((unsigned long)shinfo->frags[0].page == pending_idx);
+
+ for (i = start; i < nr_frags; i++) {
+ int j, newerr;
+
+ pending_idx = (unsigned long)shinfo->frags[i].page;
+
+ /* Check error status: if okay then remember grant handle. */
+ newerr = (++mop)->status;
+ if (likely(!newerr)) {
+ set_phys_to_machine(
+ __pa(MMAP_VADDR(pending_idx))>>PAGE_SHIFT,
+ FOREIGN_FRAME(mop->dev_bus_addr>>PAGE_SHIFT));
+ grant_tx_handle[pending_idx] = mop->handle;
+ /* Had a previous error? Invalidate this fragment. */
+ if (unlikely(err))
+ netif_idx_release(pending_idx);
+ continue;
+ }
+
+ /* Error on this fragment: respond to client with an error. */
+ txp = &pending_tx_info[pending_idx].req;
+ make_tx_response(netif, txp->id, NETIF_RSP_ERROR);
+ pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
+ netif_put(netif);
+
+ /* Not the first error? Preceding frags already invalidated. */
+ if (err)
+ continue;
+
+ /* First error: invalidate header and preceding fragments. */
+ pending_idx = *((u16 *)skb->data);
+ netif_idx_release(pending_idx);
+ for (j = start; j < i; j++) {
+ pending_idx = (unsigned long)shinfo->frags[i].page;
+ netif_idx_release(pending_idx);
+ }
+
+ /* Remember the error: invalidate all subsequent fragments. */
+ err = newerr;
+ }
+
+ *mopp = mop + 1;
+ return err;
+}
+
+static void netbk_fill_frags(struct sk_buff *skb)
+{
+ struct skb_shared_info *shinfo = skb_shinfo(skb);
+ int nr_frags = shinfo->nr_frags;
+ int i;
+
+ for (i = 0; i < nr_frags; i++) {
+ skb_frag_t *frag = shinfo->frags + i;
+ netif_tx_request_t *txp;
+ unsigned long pending_idx;
+
+ pending_idx = (unsigned long)frag->page;
+ txp = &pending_tx_info[pending_idx].req;
+ frag->page = virt_to_page(MMAP_VADDR(pending_idx));
+ frag->size = txp->size;
+ frag->page_offset = txp->offset;
+
+ skb->len += txp->size;
+ skb->data_len += txp->size;
+ skb->truesize += txp->size;
+ }
+}
+
/* Called after netfront has transmitted */
static void net_tx_action(unsigned long unused)
{
@@ -504,7 +678,7 @@ static void net_tx_action(unsigned long
net_tx_action_dealloc();
mop = tx_map_ops;
- while ((NR_PENDING_REQS < MAX_PENDING_REQS) &&
+ while (((NR_PENDING_REQS + MAX_SKB_FRAGS) < MAX_PENDING_REQS) &&
!list_empty(&net_schedule_list)) {
/* Get a netif from the list with work to do. */
ent = net_schedule_list.next;
@@ -552,38 +726,44 @@ static void net_tx_action(unsigned long
}
netif->remaining_credit -= txreq.size;
- netif->tx.req_cons++;
-
- netif_schedule_work(netif);
-
- if (unlikely(txreq.size < ETH_HLEN) ||
- unlikely(txreq.size > ETH_FRAME_LEN)) {
+ ret = netbk_count_requests(netif, &txreq, work_to_do);
+ if (unlikely(ret < 0)) {
+ netbk_tx_err(netif, i - ret);
+ continue;
+ }
+ i += ret;
+
+ if (unlikely(ret > MAX_SKB_FRAGS + 1)) {
+ DPRINTK("Too many frags\n");
+ netbk_tx_err(netif, i);
+ continue;
+ }
+
+ if (unlikely(txreq.size < ETH_HLEN)) {
DPRINTK("Bad packet size: %d\n", txreq.size);
- make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
- netif_put(netif);
+ netbk_tx_err(netif, i);
continue;
}
/* No crossing a page as the payload mustn't fragment. */
- if (unlikely((txreq.offset + txreq.size) >= PAGE_SIZE)) {
+ if (unlikely((txreq.offset + txreq.size) > PAGE_SIZE)) {
DPRINTK("txreq.offset: %x, size: %u, end: %lu\n",
txreq.offset, txreq.size,
(txreq.offset &~PAGE_MASK) + txreq.size);
- make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
- netif_put(netif);
+ netbk_tx_err(netif, i);
continue;
}
pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
- data_len = (txreq.size > PKT_PROT_LEN) ?
+ data_len = (txreq.size > PKT_PROT_LEN &&
+ ret < MAX_SKB_FRAGS + 1) ?
PKT_PROT_LEN : txreq.size;
skb = alloc_skb(data_len+16, GFP_ATOMIC);
if (unlikely(skb == NULL)) {
DPRINTK("Can't allocate a skb in start_xmit.\n");
- make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
- netif_put(netif);
+ netbk_tx_err(netif, i);
break;
}
@@ -600,9 +780,23 @@ static void net_tx_action(unsigned long
pending_tx_info[pending_idx].netif = netif;
*((u16 *)skb->data) = pending_idx;
+ __skb_put(skb, data_len);
+
+ skb_shinfo(skb)->nr_frags = ret - 1;
+ if (data_len < txreq.size) {
+ skb_shinfo(skb)->nr_frags++;
+ skb_shinfo(skb)->frags[0].page =
+ (void *)(unsigned long)pending_idx;
+ }
+
__skb_queue_tail(&tx_queue, skb);
pending_cons++;
+
+ mop = netbk_get_requests(netif, skb, mop);
+
+ netif->tx.req_cons = i;
+ netif_schedule_work(netif);
if ((mop - tx_map_ops) >= ARRAY_SIZE(tx_map_ops))
break;
@@ -617,75 +811,56 @@ static void net_tx_action(unsigned long
mop = tx_map_ops;
while ((skb = __skb_dequeue(&tx_queue)) != NULL) {
+ netif_tx_request_t *txp;
+
pending_idx = *((u16 *)skb->data);
netif = pending_tx_info[pending_idx].netif;
- memcpy(&txreq, &pending_tx_info[pending_idx].req,
- sizeof(txreq));
+ txp = &pending_tx_info[pending_idx].req;
/* Check the remap error code. */
- if (unlikely(mop->status)) {
+ if (unlikely(netbk_tx_check_mop(skb, &mop))) {
printk(KERN_ALERT "#### netback grant fails\n");
- make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
- netif_put(netif);
+ skb_shinfo(skb)->nr_frags = 0;
kfree_skb(skb);
- mop++;
- pending_ring[MASK_PEND_IDX(pending_prod++)] =
- pending_idx;
continue;
}
- set_phys_to_machine(
- __pa(MMAP_VADDR(pending_idx)) >> PAGE_SHIFT,
- FOREIGN_FRAME(mop->dev_bus_addr >> PAGE_SHIFT));
- grant_tx_handle[pending_idx] = mop->handle;
-
- data_len = (txreq.size > PKT_PROT_LEN) ?
- PKT_PROT_LEN : txreq.size;
-
- __skb_put(skb, data_len);
+
+ data_len = skb->len;
memcpy(skb->data,
- (void *)(MMAP_VADDR(pending_idx)|txreq.offset),
+ (void *)(MMAP_VADDR(pending_idx)|txp->offset),
data_len);
- if (data_len < txreq.size) {
+ if (data_len < txp->size) {
/* Append the packet payload as a fragment. */
- skb_shinfo(skb)->frags[0].page =
- virt_to_page(MMAP_VADDR(pending_idx));
- skb_shinfo(skb)->frags[0].size =
- txreq.size - data_len;
- skb_shinfo(skb)->frags[0].page_offset =
- txreq.offset + data_len;
- skb_shinfo(skb)->nr_frags = 1;
+ txp->offset += data_len;
+ txp->size -= data_len;
} else {
/* Schedule a response immediately. */
netif_idx_release(pending_idx);
}
-
- skb->data_len = txreq.size - data_len;
- skb->len += skb->data_len;
- skb->truesize += skb->data_len;
-
- skb->dev = netif->dev;
- skb->protocol = eth_type_trans(skb, skb->dev);
/*
* Old frontends do not assert data_validated but we
* can infer it from csum_blank so test both flags.
*/
- if (txreq.flags & (NETTXF_data_validated|NETTXF_csum_blank)) {
+ if (txp->flags & (NETTXF_data_validated|NETTXF_csum_blank)) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
skb->proto_data_valid = 1;
} else {
skb->ip_summed = CHECKSUM_NONE;
skb->proto_data_valid = 0;
}
- skb->proto_csum_blank = !!(txreq.flags & NETTXF_csum_blank);
-
- netif->stats.rx_bytes += txreq.size;
+ skb->proto_csum_blank = !!(txp->flags & NETTXF_csum_blank);
+
+ netbk_fill_frags(skb);
+
+ skb->dev = netif->dev;
+ skb->protocol = eth_type_trans(skb, skb->dev);
+
+ netif->stats.rx_bytes += skb->len;
netif->stats.rx_packets++;
netif_rx(skb);
netif->dev->last_rx = jiffies;
-
- mop++;
}
}
@@ -695,7 +870,10 @@ static void netif_idx_release(u16 pendin
unsigned long flags;
spin_lock_irqsave(&_lock, flags);
- dealloc_ring[MASK_PEND_IDX(dealloc_prod++)] = pending_idx;
+ dealloc_ring[MASK_PEND_IDX(dealloc_prod)] = pending_idx;
+ /* Sync with net_tx_action_dealloc: insert idx /then/ incr producer. */
+ smp_wmb();
+ dealloc_prod++;
spin_unlock_irqrestore(&_lock, flags);
tasklet_schedule(&net_tx_tasklet);
diff -r 760669a37a3a -r 5c0c59eb5f73 drivers/xen/netback/xenbus.c
--- a/drivers/xen/netback/xenbus.c Wed Jun 07 19:53:53 2006 -0400
+++ b/drivers/xen/netback/xenbus.c Thu Jun 08 15:10:05 2006 -0400
@@ -69,6 +69,8 @@ static int netback_probe(struct xenbus_d
static int netback_probe(struct xenbus_device *dev,
const struct xenbus_device_id *id)
{
+ const char *message;
+ xenbus_transaction_t xbt;
int err;
struct backend_info *be = kzalloc(sizeof(struct backend_info),
GFP_KERNEL);
@@ -86,6 +88,27 @@ static int netback_probe(struct xenbus_d
if (err)
goto fail;
+ do {
+ err = xenbus_transaction_start(&xbt);
+ if (err) {
+ xenbus_dev_fatal(dev, err, "starting transaction");
+ goto fail;
+ }
+
+ err = xenbus_printf(xbt, dev->nodename, "feature-sg", "%d", 1);
+ if (err) {
+ message = "writing feature-sg";
+ goto abort_transaction;
+ }
+
+ err = xenbus_transaction_end(xbt, 0);
+ } while (err == -EAGAIN);
+
+ if (err) {
+ xenbus_dev_fatal(dev, err, "completing transaction");
+ goto fail;
+ }
+
err = xenbus_switch_state(dev, XenbusStateInitWait);
if (err) {
goto fail;
@@ -93,6 +116,9 @@ static int netback_probe(struct xenbus_d
return 0;
+abort_transaction:
+ xenbus_transaction_end(xbt, 1);
+ xenbus_dev_fatal(dev, err, "%s", message);
fail:
DPRINTK("failed");
netback_remove(dev);
diff -r 760669a37a3a -r 5c0c59eb5f73 drivers/xen/netfront/netfront.c
--- a/drivers/xen/netfront/netfront.c Wed Jun 07 19:53:53 2006 -0400
+++ b/drivers/xen/netfront/netfront.c Thu Jun 08 15:10:05 2006 -0400
@@ -45,6 +45,7 @@
#include <linux/bitops.h>
#include <linux/ethtool.h>
#include <linux/in.h>
+#include <linux/if_ether.h>
#include <net/sock.h>
#include <net/pkt_sched.h>
#include <net/arp.h>
@@ -173,6 +174,11 @@ static void xennet_sysfs_delif(struct ne
#define xennet_sysfs_delif(dev) do { } while(0)
#endif
+static inline int xennet_can_sg(struct net_device *dev)
+{
+ return dev->features & NETIF_F_SG;
+}
+
/**
* Entry point to this code when a new device is created. Allocate the basic
* structures and the ring buffers for communication with the backend, and
@@ -307,8 +313,6 @@ again:
goto destroy_ring;
}
- xenbus_switch_state(dev, XenbusStateConnected);
-
return 0;
abort_transaction:
@@ -370,12 +374,9 @@ static int setup_device(struct xenbus_de
goto fail;
memcpy(netdev->dev_addr, info->mac, ETH_ALEN);
- network_connect(netdev);
info->irq = bind_evtchn_to_irqhandler(
info->evtchn, netif_int, SA_SAMPLE_RANDOM, netdev->name,
netdev);
- (void)send_fake_arp(netdev);
- show_device(info);
return 0;
@@ -391,15 +392,24 @@ static void backend_changed(struct xenbu
static void backend_changed(struct xenbus_device *dev,
enum xenbus_state backend_state)
{
+ struct netfront_info *np = dev->data;
+ struct net_device *netdev = np->netdev;
+
DPRINTK("\n");
switch (backend_state) {
case XenbusStateInitialising:
- case XenbusStateInitWait:
case XenbusStateInitialised:
case XenbusStateConnected:
case XenbusStateUnknown:
case XenbusStateClosed:
+ break;
+
+ case XenbusStateInitWait:
+ network_connect(netdev);
+ xenbus_switch_state(dev, XenbusStateConnected);
+ (void)send_fake_arp(netdev);
+ show_device(np);
break;
case XenbusStateClosing:
@@ -452,13 +462,17 @@ static int network_open(struct net_devic
return 0;
}
+static inline int netfront_tx_slot_available(struct netfront_info *np)
+{
+ return RING_FREE_REQUESTS(&np->tx) >= MAX_SKB_FRAGS + 1;
+}
+
static inline void network_maybe_wake_tx(struct net_device *dev)
{
struct netfront_info *np = netdev_priv(dev);
if (unlikely(netif_queue_stopped(dev)) &&
- !RING_FULL(&np->tx) &&
- !gnttab_empty_grant_references(&np->gref_tx_head) &&
+ netfront_tx_slot_available(np) &&
likely(netif_running(dev)))
netif_wake_queue(dev);
}
@@ -485,7 +499,7 @@ static void network_tx_buf_gc(struct net
printk(KERN_ALERT "network_tx_buf_gc: warning "
"-- grant still in use by backend "
"domain.\n");
- break; /* bail immediately */
+ BUG();
}
gnttab_end_foreign_access_ref(
np->grant_tx_ref[id], GNTMAP_readonly);
@@ -638,36 +652,95 @@ static void network_alloc_rx_buffers(str
RING_PUSH_REQUESTS(&np->rx);
}
+static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev,
+ struct netif_tx_request *tx)
+{
+ struct netfront_info *np = netdev_priv(dev);
+ char *data = skb->data;
+ unsigned long mfn;
+ RING_IDX prod = np->tx.req_prod_pvt;
+ int frags = skb_shinfo(skb)->nr_frags;
+ unsigned int offset = offset_in_page(data);
+ unsigned int len = skb_headlen(skb);
+ unsigned int id;
+ grant_ref_t ref;
+ int i;
+
+ while (len > PAGE_SIZE - offset) {
+ tx->size = PAGE_SIZE - offset;
+ tx->flags |= NETTXF_more_data;
+ len -= tx->size;
+ data += tx->size;
+ offset = 0;
+
+ id = get_id_from_freelist(np->tx_skbs);
+ np->tx_skbs[id] = skb_get(skb);
+ tx = RING_GET_REQUEST(&np->tx, prod++);
+ tx->id = id;
+ ref = gnttab_claim_grant_reference(&np->gref_tx_head);
+ BUG_ON((signed short)ref < 0);
+
+ mfn = virt_to_mfn(data);
+ gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id,
+ mfn, GNTMAP_readonly);
+
+ tx->gref = np->grant_tx_ref[id] = ref;
+ tx->offset = offset;
+ tx->size = len;
+ tx->flags = 0;
+ }
+
+ for (i = 0; i < frags; i++) {
+ skb_frag_t *frag = skb_shinfo(skb)->frags + i;
+
+ tx->flags |= NETTXF_more_data;
+
+ id = get_id_from_freelist(np->tx_skbs);
+ np->tx_skbs[id] = skb_get(skb);
+ tx = RING_GET_REQUEST(&np->tx, prod++);
+ tx->id = id;
+ ref = gnttab_claim_grant_reference(&np->gref_tx_head);
+ BUG_ON((signed short)ref < 0);
+
+ mfn = pfn_to_mfn(page_to_pfn(frag->page));
+ gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id,
+ mfn, GNTMAP_readonly);
+
+ tx->gref = np->grant_tx_ref[id] = ref;
+ tx->offset = frag->page_offset;
+ tx->size = frag->size;
+ tx->flags = 0;
+ }
+
+ np->tx.req_prod_pvt = prod;
+}
static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
unsigned short id;
struct netfront_info *np = netdev_priv(dev);
struct netif_tx_request *tx;
+ char *data = skb->data;
RING_IDX i;
grant_ref_t ref;
unsigned long mfn;
int notify;
-
- if (unlikely((((unsigned long)skb->data & ~PAGE_MASK) + skb->len) >=
- PAGE_SIZE)) {
- struct sk_buff *nskb;
- nskb = __dev_alloc_skb(skb->len, GFP_ATOMIC|__GFP_NOWARN);
- if (unlikely(nskb == NULL))
- goto drop;
- skb_put(nskb, skb->len);
- memcpy(nskb->data, skb->data, skb->len);
- /* Copy only the header fields we use in this driver. */
- nskb->dev = skb->dev;
- nskb->ip_summed = skb->ip_summed;
- nskb->proto_data_valid = skb->proto_data_valid;
- dev_kfree_skb(skb);
- skb = nskb;
+ int frags = skb_shinfo(skb)->nr_frags;
+ unsigned int offset = offset_in_page(data);
+ unsigned int len = skb_headlen(skb);
+
+ frags += (offset + len + PAGE_SIZE - 1) / PAGE_SIZE;
+ if (unlikely(frags > MAX_SKB_FRAGS + 1)) {
+ printk(KERN_ALERT "xennet: skb rides the rocket: %d frags\n",
+ frags);
+ dump_stack();
+ goto drop;
}
spin_lock_irq(&np->tx_lock);
- if (unlikely(!netif_carrier_ok(dev))) {
+ if (unlikely(!netif_carrier_ok(dev) ||
+ (frags > 1 && !xennet_can_sg(dev)))) {
spin_unlock_irq(&np->tx_lock);
goto drop;
}
@@ -682,12 +755,12 @@ static int network_start_xmit(struct sk_
tx->id = id;
ref = gnttab_claim_grant_reference(&np->gref_tx_head);
BUG_ON((signed short)ref < 0);
- mfn = virt_to_mfn(skb->data);
+ mfn = virt_to_mfn(data);
gnttab_grant_foreign_access_ref(
ref, np->xbdev->otherend_id, mfn, GNTMAP_readonly);
tx->gref = np->grant_tx_ref[id] = ref;
- tx->offset = (unsigned long)skb->data & ~PAGE_MASK;
- tx->size = skb->len;
+ tx->offset = offset;
+ tx->size = len;
tx->flags = 0;
if (skb->ip_summed == CHECKSUM_HW) /* local packet? */
@@ -696,14 +769,17 @@ static int network_start_xmit(struct sk_
tx->flags |= NETTXF_data_validated;
np->tx.req_prod_pvt = i + 1;
+
+ xennet_make_frags(skb, dev, tx);
+ tx->size = skb->len;
+
RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->tx, notify);
if (notify)
notify_remote_via_irq(np->irq);
network_tx_buf_gc(dev);
- if (RING_FULL(&np->tx) ||
- gnttab_empty_grant_references(&np->gref_tx_head))
+ if (!netfront_tx_slot_available(np))
netif_stop_queue(dev);
spin_unlock_irq(&np->tx_lock);
@@ -963,12 +1039,46 @@ static struct net_device_stats *network_
return &np->stats;
}
+static int xennet_change_mtu(struct net_device *dev, int mtu)
+{
+ int max = xennet_can_sg(dev) ? 65535 - ETH_HLEN : ETH_DATA_LEN;
+
+ if (mtu > max)
+ return -EINVAL;
+ dev->mtu = mtu;
+ return 0;
+}
+
+static int xennet_set_sg(struct net_device *dev, u32 data)
+{
+ if (data) {
+ struct netfront_info *np = netdev_priv(dev);
+ int val;
+
+ if (xenbus_scanf(XBT_NULL, np->xbdev->otherend, "feature-sg",
+ "%d", &val) < 0)
+ val = 0;
+ if (!val)
+ return -ENOSYS;
+ } else if (dev->mtu > ETH_DATA_LEN)
+ dev->mtu = ETH_DATA_LEN;
+
+ return ethtool_op_set_sg(dev, data);
+}
+
+static void xennet_set_features(struct net_device *dev)
+{
+ xennet_set_sg(dev, 1);
+}
+
static void network_connect(struct net_device *dev)
{
struct netfront_info *np;
int i, requeue_idx;
struct netif_tx_request *tx;
struct sk_buff *skb;
+
+ xennet_set_features(dev);
np = netdev_priv(dev);
spin_lock_irq(&np->tx_lock);
@@ -1081,6 +1191,8 @@ static struct ethtool_ops network_ethtoo
{
.get_tx_csum = ethtool_op_get_tx_csum,
.set_tx_csum = ethtool_op_set_tx_csum,
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = xennet_set_sg,
};
#ifdef CONFIG_SYSFS
@@ -1297,6 +1409,7 @@ static struct net_device * __devinit cre
netdev->poll = netif_poll;
netdev->set_multicast_list = network_set_multicast_list;
netdev->uninit = netif_uninit;
+ netdev->change_mtu = xennet_change_mtu;
netdev->weight = 64;
netdev->features = NETIF_F_IP_CSUM;
diff -r 760669a37a3a -r 5c0c59eb5f73 drivers/xen/privcmd/privcmd.c
--- a/drivers/xen/privcmd/privcmd.c Wed Jun 07 19:53:53 2006 -0400
+++ b/drivers/xen/privcmd/privcmd.c Thu Jun 08 15:10:05 2006 -0400
@@ -63,11 +63,11 @@ static int privcmd_ioctl(struct inode *i
__asm__ __volatile__ (
"pushl %%ebx; pushl %%ecx; pushl %%edx; "
"pushl %%esi; pushl %%edi; "
- "movl 4(%%eax),%%ebx ;"
- "movl 8(%%eax),%%ecx ;"
- "movl 12(%%eax),%%edx ;"
- "movl 16(%%eax),%%esi ;"
- "movl 20(%%eax),%%edi ;"
+ "movl 8(%%eax),%%ebx ;"
+ "movl 16(%%eax),%%ecx ;"
+ "movl 24(%%eax),%%edx ;"
+ "movl 32(%%eax),%%esi ;"
+ "movl 40(%%eax),%%edi ;"
"movl (%%eax),%%eax ;"
"shll $5,%%eax ;"
"addl $hypercall_page,%%eax ;"
@@ -214,7 +214,7 @@ static int privcmd_ioctl(struct inode *i
batch_err:
printk("batch_err ret=%d vma=%p addr=%lx "
"num=%d arr=%p %lx-%lx\n",
- ret, vma, m.addr, m.num, m.arr,
+ ret, vma, (unsigned long)m.addr, m.num, m.arr,
vma ? vma->vm_start : 0, vma ? vma->vm_end : 0);
break;
}
diff -r 760669a37a3a -r 5c0c59eb5f73 include/asm-i386/mach-xen/asm/dma-mapping.h
--- a/include/asm-i386/mach-xen/asm/dma-mapping.h Wed Jun 07 19:53:53
2006 -0400
+++ b/include/asm-i386/mach-xen/asm/dma-mapping.h Thu Jun 08 15:10:05
2006 -0400
@@ -128,8 +128,6 @@ dma_get_cache_alignment(void)
* maximum possible, to be safe */
return (1 << INTERNODE_CACHE_SHIFT);
}
-#else
-extern int dma_get_cache_alignment(void);
#endif
#define dma_is_consistent(d) (1)
diff -r 760669a37a3a -r 5c0c59eb5f73 include/asm-i386/mach-xen/asm/hypercall.h
--- a/include/asm-i386/mach-xen/asm/hypercall.h Wed Jun 07 19:53:53 2006 -0400
+++ b/include/asm-i386/mach-xen/asm/hypercall.h Thu Jun 08 15:10:05 2006 -0400
@@ -260,6 +260,13 @@ HYPERVISOR_event_channel_op(
}
static inline int
+HYPERVISOR_acm_op(
+ int cmd, void *arg)
+{
+ return _hypercall2(int, acm_op, cmd, arg);
+}
+
+static inline int
HYPERVISOR_xen_version(
int cmd, void *arg)
{
diff -r 760669a37a3a -r 5c0c59eb5f73 include/asm-i386/mach-xen/asm/system.h
--- a/include/asm-i386/mach-xen/asm/system.h Wed Jun 07 19:53:53 2006 -0400
+++ b/include/asm-i386/mach-xen/asm/system.h Thu Jun 08 15:10:05 2006 -0400
@@ -115,10 +115,12 @@ __asm__ __volatile__ ("movw %%dx,%1\n\t"
__asm__ ( \
"movl %%cr3,%0\n\t" \
:"=r" (__dummy)); \
- machine_to_phys(__dummy); \
+ __dummy = xen_cr3_to_pfn(__dummy); \
+ mfn_to_pfn(__dummy) << PAGE_SHIFT; \
})
#define write_cr3(x) ({ \
- maddr_t __dummy = phys_to_machine(x); \
+ unsigned int __dummy = pfn_to_mfn((x) >> PAGE_SHIFT); \
+ __dummy = xen_pfn_to_cr3(__dummy); \
__asm__ __volatile__("movl %0,%%cr3": :"r" (__dummy)); \
})
@@ -519,8 +521,8 @@ do {
\
preempt_enable_no_resched(); \
} while (0)
-#define safe_halt() ((void)0)
-#define halt() ((void)0)
+void safe_halt(void);
+void halt(void);
#define __save_and_cli(x) \
do { \
diff -r 760669a37a3a -r 5c0c59eb5f73 include/asm-i386/mach-xen/setup_arch_post.h
--- a/include/asm-i386/mach-xen/setup_arch_post.h Wed Jun 07 19:53:53
2006 -0400
+++ b/include/asm-i386/mach-xen/setup_arch_post.h Thu Jun 08 15:10:05
2006 -0400
@@ -61,13 +61,6 @@ static void __init machine_specific_arch
.address = { __KERNEL_CS, (unsigned long)nmi },
};
- if (xen_feature(XENFEAT_auto_translated_physmap) &&
- xen_start_info->shared_info < xen_start_info->nr_pages) {
- HYPERVISOR_shared_info =
- (shared_info_t *)__va(xen_start_info->shared_info);
- memset(empty_zero_page, 0, sizeof(empty_zero_page));
- }
-
ret = HYPERVISOR_callback_op(CALLBACKOP_register, &event);
if (ret == 0)
ret = HYPERVISOR_callback_op(CALLBACKOP_register, &failsafe);
diff -r 760669a37a3a -r 5c0c59eb5f73 include/asm-ia64/hw_irq.h
--- a/include/asm-ia64/hw_irq.h Wed Jun 07 19:53:53 2006 -0400
+++ b/include/asm-ia64/hw_irq.h Thu Jun 08 15:10:05 2006 -0400
@@ -15,7 +15,11 @@
#include <asm/ptrace.h>
#include <asm/smp.h>
+#ifndef CONFIG_XEN
typedef u8 ia64_vector;
+#else
+typedef u16 ia64_vector;
+#endif
/*
* 0 special
@@ -86,11 +90,15 @@ extern void ia64_send_ipi (int cpu, int
extern void ia64_send_ipi (int cpu, int vector, int delivery_mode, int
redirect);
extern void register_percpu_irq (ia64_vector vec, struct irqaction *action);
+#ifndef CONFIG_XEN
static inline void
hw_resend_irq (struct hw_interrupt_type *h, unsigned int vector)
{
platform_send_ipi(smp_processor_id(), vector, IA64_IPI_DM_INT, 0);
}
+#else
+extern void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i);
+#endif /* CONFIG_XEN */
/*
* Default implementations for the irq-descriptor API:
diff -r 760669a37a3a -r 5c0c59eb5f73 include/asm-ia64/hypercall.h
--- a/include/asm-ia64/hypercall.h Wed Jun 07 19:53:53 2006 -0400
+++ b/include/asm-ia64/hypercall.h Thu Jun 08 15:10:05 2006 -0400
@@ -247,6 +247,13 @@ HYPERVISOR_event_channel_op(
}
static inline int
+HYPERVISOR_acm_op(
+ unsigned int cmd, void *arg)
+{
+ return _hypercall2(int, acm_op, cmd, arg);
+}
+
+static inline int
HYPERVISOR_xen_version(
int cmd, void *arg)
{
@@ -313,9 +320,20 @@ HYPERVISOR_suspend(
return rc;
}
+static inline int
+HYPERVISOR_callback_op(
+ int cmd, void *arg)
+{
+ return _hypercall2(int, callback_op, cmd, arg);
+}
+
extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs);
static inline void exit_idle(void) {}
-#define do_IRQ(irq, regs) __do_IRQ((irq), (regs))
+#define do_IRQ(irq, regs) ({ \
+ irq_enter(); \
+ __do_IRQ((irq), (regs)); \
+ irq_exit(); \
+})
#ifdef CONFIG_XEN_IA64_DOM0_VP
#include <linux/err.h>
@@ -418,12 +436,14 @@ HYPERVISOR_ioremap(unsigned long ioaddr,
HYPERVISOR_ioremap(unsigned long ioaddr, unsigned long size)
{
unsigned long ret = ioaddr;
- if (running_on_xen) {
+ if (is_running_on_xen()) {
ret = __HYPERVISOR_ioremap(ioaddr, size);
- if (unlikely(IS_ERR_VALUE(ret)))
+ if (unlikely(ret == -ENOSYS))
panic("hypercall %s failed with %ld. "
"Please check Xen and Linux config mismatch\n",
__func__, -ret);
+ else if (unlikely(IS_ERR_VALUE(ret)))
+ ret = ioaddr;
}
return ret;
}
@@ -439,7 +459,7 @@ HYPERVISOR_phystomach(unsigned long gpfn
HYPERVISOR_phystomach(unsigned long gpfn)
{
unsigned long ret = gpfn;
- if (running_on_xen) {
+ if (is_running_on_xen()) {
ret = __HYPERVISOR_phystomach(gpfn);
}
return ret;
@@ -456,7 +476,7 @@ HYPERVISOR_machtophys(unsigned long mfn)
HYPERVISOR_machtophys(unsigned long mfn)
{
unsigned long ret = mfn;
- if (running_on_xen) {
+ if (is_running_on_xen()) {
ret = __HYPERVISOR_machtophys(mfn);
}
return ret;
@@ -473,7 +493,7 @@ HYPERVISOR_zap_physmap(unsigned long gpf
HYPERVISOR_zap_physmap(unsigned long gpfn, unsigned int extent_order)
{
unsigned long ret = 0;
- if (running_on_xen) {
+ if (is_running_on_xen()) {
ret = __HYPERVISOR_zap_physmap(gpfn, extent_order);
}
return ret;
@@ -481,7 +501,7 @@ HYPERVISOR_zap_physmap(unsigned long gpf
static inline unsigned long
__HYPERVISOR_add_physmap(unsigned long gpfn, unsigned long mfn,
- unsigned int flags, domid_t domid)
+ unsigned long flags, domid_t domid)
{
return _hypercall_imm4(unsigned long, ia64_dom0vp_op,
IA64_DOM0VP_add_physmap, gpfn, mfn, flags,
@@ -490,11 +510,11 @@ __HYPERVISOR_add_physmap(unsigned long g
static inline unsigned long
HYPERVISOR_add_physmap(unsigned long gpfn, unsigned long mfn,
- unsigned int flags, domid_t domid)
+ unsigned long flags, domid_t domid)
{
unsigned long ret = 0;
- BUG_ON(!running_on_xen);//XXX
- if (running_on_xen) {
+ BUG_ON(!is_running_on_xen());//XXX
+ if (is_running_on_xen()) {
ret = __HYPERVISOR_add_physmap(gpfn, mfn, flags, domid);
}
return ret;
diff -r 760669a37a3a -r 5c0c59eb5f73 include/asm-ia64/hypervisor.h
--- a/include/asm-ia64/hypervisor.h Wed Jun 07 19:53:53 2006 -0400
+++ b/include/asm-ia64/hypervisor.h Thu Jun 08 15:10:05 2006 -0400
@@ -46,14 +46,12 @@
#include <asm/hypercall.h>
#include <asm/ptrace.h>
#include <asm/page.h>
-#include <asm/xen/privop.h> // for running_on_xen
+#include <asm/xen/privop.h> // for is_running_on_xen()
extern shared_info_t *HYPERVISOR_shared_info;
extern start_info_t *xen_start_info;
void force_evtchn_callback(void);
-
-#define is_running_on_xen() running_on_xen
/* Turn jiffies into Xen system time. XXX Implement me. */
#define jiffies_to_st(j) 0
diff -r 760669a37a3a -r 5c0c59eb5f73 include/asm-ia64/irq.h
--- a/include/asm-ia64/irq.h Wed Jun 07 19:53:53 2006 -0400
+++ b/include/asm-ia64/irq.h Thu Jun 08 15:10:05 2006 -0400
@@ -11,8 +11,39 @@
* 02/29/00 D.Mosberger moved most things into hw_irq.h
*/
+#ifndef CONFIG_XEN
#define NR_IRQS 256
#define NR_IRQ_VECTORS NR_IRQS
+#else
+/*
+ * The flat IRQ space is divided into two regions:
+ * 1. A one-to-one mapping of real physical IRQs. This space is only used
+ * if we have physical device-access privilege. This region is at the
+ * start of the IRQ space so that existing device drivers do not need
+ * to be modified to translate physical IRQ numbers into our IRQ space.
+ * 3. A dynamic mapping of inter-domain and Xen-sourced virtual IRQs. These
+ * are bound using the provided bind/unbind functions.
+ */
+
+#define PIRQ_BASE 0
+#define NR_PIRQS 256
+
+#define DYNIRQ_BASE (PIRQ_BASE + NR_PIRQS)
+#define NR_DYNIRQS 256
+
+#define NR_IRQS (NR_PIRQS + NR_DYNIRQS)
+#define NR_IRQ_VECTORS NR_IRQS
+
+#define pirq_to_irq(_x) ((_x) + PIRQ_BASE)
+#define irq_to_pirq(_x) ((_x) - PIRQ_BASE)
+
+#define dynirq_to_irq(_x) ((_x) + DYNIRQ_BASE)
+#define irq_to_dynirq(_x) ((_x) - DYNIRQ_BASE)
+
+#define RESCHEDULE_VECTOR 0
+#define IPI_VECTOR 1
+#define NR_IPIS 2
+#endif /* CONFIG_XEN */
/*
* IRQ line status macro IRQ_PER_CPU is used
diff -r 760669a37a3a -r 5c0c59eb5f73 include/asm-ia64/xen/privop.h
--- a/include/asm-ia64/xen/privop.h Wed Jun 07 19:53:53 2006 -0400
+++ b/include/asm-ia64/xen/privop.h Thu Jun 08 15:10:05 2006 -0400
@@ -43,6 +43,7 @@
#ifndef __ASSEMBLY__
extern int running_on_xen;
+#define is_running_on_xen() running_on_xen
#define XEN_HYPER_SSM_I asm("break %0" : : "i"
(HYPERPRIVOP_SSM_I))
#define XEN_HYPER_GET_IVR asm("break %0" : : "i"
(HYPERPRIVOP_GET_IVR))
@@ -122,7 +123,7 @@ extern void xen_set_eflag(unsigned long)
#define xen_ia64_intrin_local_irq_restore(x) \
{ \
- if (running_on_xen) { \
+ if (is_running_on_xen()) {
\
if ((x) & IA64_PSR_I) { xen_ssm_i(); } \
else { xen_rsm_i(); } \
} \
@@ -131,7 +132,7 @@ extern void xen_set_eflag(unsigned long)
#define xen_get_psr_i()
\
( \
- (running_on_xen) ? \
+ (is_running_on_xen()) ? \
(xen_get_virtual_psr_i() ? IA64_PSR_I : 0) \
: __ia64_get_psr_i() \
)
@@ -139,7 +140,7 @@ extern void xen_set_eflag(unsigned long)
#define xen_ia64_ssm(mask) \
{ \
if ((mask)==IA64_PSR_I) { \
- if (running_on_xen) { xen_ssm_i(); } \
+ if (is_running_on_xen()) { xen_ssm_i(); }
\
else { __ia64_ssm(mask); } \
} \
else { __ia64_ssm(mask); } \
@@ -148,7 +149,7 @@ extern void xen_set_eflag(unsigned long)
#define xen_ia64_rsm(mask) \
{ \
if ((mask)==IA64_PSR_I) { \
- if (running_on_xen) { xen_rsm_i(); } \
+ if (is_running_on_xen()) { xen_rsm_i(); }
\
else { __ia64_rsm(mask); } \
} \
else { __ia64_rsm(mask); } \
@@ -167,10 +168,11 @@ extern void xen_set_rr(unsigned long ind
extern void xen_set_rr(unsigned long index, unsigned long val);
extern unsigned long xen_get_rr(unsigned long index);
extern void xen_set_kr(unsigned long index, unsigned long val);
-
-/* Note: It may look wrong to test for running_on_xen in each case.
+extern void xen_ptcga(unsigned long addr, unsigned long size);
+
+/* Note: It may look wrong to test for is_running_on_xen() in each case.
* However regnum is always a constant so, as written, the compiler
- * eliminates the switch statement, whereas running_on_xen must be
+ * eliminates the switch statement, whereas is_running_on_xen() must be
* tested dynamically. */
#define xen_ia64_getreg(regnum)
\
({ \
@@ -178,17 +180,17 @@ extern void xen_set_kr(unsigned long ind
\
switch(regnum) { \
case _IA64_REG_CR_IVR: \
- ia64_intri_res = (running_on_xen) ? \
+ ia64_intri_res = (is_running_on_xen()) ?
\
xen_get_ivr() : \
__ia64_getreg(regnum); \
break; \
case _IA64_REG_CR_TPR: \
- ia64_intri_res = (running_on_xen) ? \
+ ia64_intri_res = (is_running_on_xen()) ?
\
xen_get_tpr() : \
__ia64_getreg(regnum); \
break; \
case _IA64_REG_AR_EFLAG: \
- ia64_intri_res = (running_on_xen) ? \
+ ia64_intri_res = (is_running_on_xen()) ?
\
xen_get_eflag() : \
__ia64_getreg(regnum); \
break; \
@@ -203,27 +205,27 @@ extern void xen_set_kr(unsigned long ind
({ \
switch(regnum) { \
case _IA64_REG_AR_KR0 ... _IA64_REG_AR_KR7: \
- (running_on_xen) ? \
+ (is_running_on_xen()) ? \
xen_set_kr((regnum-_IA64_REG_AR_KR0), val) : \
__ia64_setreg(regnum,val); \
break; \
case _IA64_REG_CR_ITM: \
- (running_on_xen) ? \
+ (is_running_on_xen()) ? \
xen_set_itm(val) : \
__ia64_setreg(regnum,val); \
break; \
case _IA64_REG_CR_TPR: \
- (running_on_xen) ? \
+ (is_running_on_xen()) ? \
xen_set_tpr(val) : \
__ia64_setreg(regnum,val); \
break; \
case _IA64_REG_CR_EOI: \
- (running_on_xen) ? \
+ (is_running_on_xen()) ? \
xen_eoi() : \
__ia64_setreg(regnum,val); \
break; \
case _IA64_REG_AR_EFLAG: \
- (running_on_xen) ? \
+ (is_running_on_xen()) ? \
xen_set_eflag(val) : \
__ia64_setreg(regnum,val); \
break; \
diff -r 760669a37a3a -r 5c0c59eb5f73 include/asm-x86_64/mach-xen/asm/hypercall.h
--- a/include/asm-x86_64/mach-xen/asm/hypercall.h Wed Jun 07 19:53:53
2006 -0400
+++ b/include/asm-x86_64/mach-xen/asm/hypercall.h Thu Jun 08 15:10:05
2006 -0400
@@ -258,6 +258,13 @@ HYPERVISOR_event_channel_op(
}
static inline int
+HYPERVISOR_acm_op(
+ int cmd, void *arg)
+{
+ return _hypercall2(int, acm_op, cmd, arg);
+}
+
+static inline int
HYPERVISOR_xen_version(
int cmd, void *arg)
{
diff -r 760669a37a3a -r 5c0c59eb5f73 include/asm-x86_64/mach-xen/asm/system.h
--- a/include/asm-x86_64/mach-xen/asm/system.h Wed Jun 07 19:53:53 2006 -0400
+++ b/include/asm-x86_64/mach-xen/asm/system.h Thu Jun 08 15:10:05 2006 -0400
@@ -418,8 +418,8 @@ do {
\
preempt_enable_no_resched(); \
___x; })
-#define safe_halt() ((void)0)
-#define halt() ((void)0)
+void safe_halt(void);
+void halt(void);
void cpu_idle_wait(void);
diff -r 760669a37a3a -r 5c0c59eb5f73 include/xen/cpu_hotplug.h
--- a/include/xen/cpu_hotplug.h Wed Jun 07 19:53:53 2006 -0400
+++ b/include/xen/cpu_hotplug.h Thu Jun 08 15:10:05 2006 -0400
@@ -13,14 +13,16 @@ void cpu_initialize_context(unsigned int
#define cpu_initialize_context(cpu) ((void)0)
#endif
-int cpu_up_is_allowed(unsigned int cpu);
+int cpu_up_check(unsigned int cpu);
void init_xenbus_allowed_cpumask(void);
int smp_suspend(void);
void smp_resume(void);
+void cpu_bringup(void);
+
#else /* !defined(CONFIG_HOTPLUG_CPU) */
-#define cpu_up_is_allowed(cpu) (1)
+#define cpu_up_check(cpu) (0)
#define init_xenbus_allowed_cpumask() ((void)0)
static inline int smp_suspend(void)
diff -r 760669a37a3a -r 5c0c59eb5f73 include/xen/interface/arch-ia64.h
--- a/include/xen/interface/arch-ia64.h Wed Jun 07 19:53:53 2006 -0400
+++ b/include/xen/interface/arch-ia64.h Thu Jun 08 15:10:05 2006 -0400
@@ -26,6 +26,9 @@ DEFINE_XEN_GUEST_HANDLE(int);
DEFINE_XEN_GUEST_HANDLE(int);
DEFINE_XEN_GUEST_HANDLE(long);
DEFINE_XEN_GUEST_HANDLE(void);
+
+typedef unsigned long xen_pfn_t;
+DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
#endif
/* Arch specific VIRQs definition */
@@ -320,6 +323,8 @@ struct arch_initrd_info {
};
typedef struct arch_initrd_info arch_initrd_info_t;
+typedef unsigned long xen_callback_t;
+
#define IA64_COMMAND_LINE_SIZE 512
struct vcpu_guest_context {
#define VGCF_FPU_VALID (1<<0)
@@ -367,6 +372,10 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_conte
#define IA64_DOM0VP_add_physmap 18 // assigne machine page frane
// to dom0's pseudo physical
// address space.
+// flags for page assignement to pseudo physical address space
+#define _ASSIGN_readonly 0
+#define ASSIGN_readonly (1UL << _ASSIGN_readonly)
+#define ASSIGN_writable (0UL << _ASSIGN_readonly) // dummy flag
#endif /* !__ASSEMBLY__ */
diff -r 760669a37a3a -r 5c0c59eb5f73 include/xen/interface/arch-x86_32.h
--- a/include/xen/interface/arch-x86_32.h Wed Jun 07 19:53:53 2006 -0400
+++ b/include/xen/interface/arch-x86_32.h Thu Jun 08 15:10:05 2006 -0400
@@ -28,6 +28,9 @@ DEFINE_XEN_GUEST_HANDLE(int);
DEFINE_XEN_GUEST_HANDLE(int);
DEFINE_XEN_GUEST_HANDLE(long);
DEFINE_XEN_GUEST_HANDLE(void);
+
+typedef unsigned long xen_pfn_t;
+DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
#endif
/*
@@ -138,9 +141,17 @@ struct vcpu_guest_context {
struct vcpu_guest_context {
/* FPU registers come first so they can be aligned for FXSAVE/FXRSTOR. */
struct { char x[512]; } fpu_ctxt; /* User-level FPU registers */
-#define VGCF_I387_VALID (1<<0)
-#define VGCF_HVM_GUEST (1<<1)
-#define VGCF_IN_KERNEL (1<<2)
+#define VGCF_I387_VALID (1<<0)
+#define VGCF_HVM_GUEST (1<<1)
+#define VGCF_IN_KERNEL (1<<2)
+#define _VGCF_i387_valid 0
+#define VGCF_i387_valid (1<<_VGCF_i387_valid)
+#define _VGCF_hvm_guest 1
+#define VGCF_hvm_guest (1<<_VGCF_hvm_guest)
+#define _VGCF_in_kernel 2
+#define VGCF_in_kernel (1<<_VGCF_in_kernel)
+#define _VGCF_failsafe_disables_events 3
+#define VGCF_failsafe_disables_events (1<<_VGCF_failsafe_disables_events)
unsigned long flags; /* VGCF_* flags */
struct cpu_user_regs user_regs; /* User-level CPU registers */
struct trap_info trap_ctxt[256]; /* Virtual IDT */
@@ -158,10 +169,18 @@ typedef struct vcpu_guest_context vcpu_g
typedef struct vcpu_guest_context vcpu_guest_context_t;
DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
+/*
+ * Page-directory addresses above 4GB do not fit into architectural %cr3.
+ * When accessing %cr3, or equivalent field in vcpu_guest_context, guests
+ * must use the following accessor macros to pack/unpack valid MFNs.
+ */
+#define xen_pfn_to_cr3(pfn) (((unsigned)(pfn) << 12) | ((unsigned)(pfn) >> 20))
+#define xen_cr3_to_pfn(cr3) (((unsigned)(cr3) >> 12) | ((unsigned)(cr3) << 20))
+
struct arch_shared_info {
unsigned long max_pfn; /* max pfn that appears in table */
/* Frame containing list of mfns containing list of mfns containing p2m. */
- unsigned long pfn_to_mfn_frame_list_list;
+ xen_pfn_t pfn_to_mfn_frame_list_list;
unsigned long nmi_reason;
};
typedef struct arch_shared_info arch_shared_info_t;
diff -r 760669a37a3a -r 5c0c59eb5f73 include/xen/interface/arch-x86_64.h
--- a/include/xen/interface/arch-x86_64.h Wed Jun 07 19:53:53 2006 -0400
+++ b/include/xen/interface/arch-x86_64.h Thu Jun 08 15:10:05 2006 -0400
@@ -28,6 +28,9 @@ DEFINE_XEN_GUEST_HANDLE(int);
DEFINE_XEN_GUEST_HANDLE(int);
DEFINE_XEN_GUEST_HANDLE(long);
DEFINE_XEN_GUEST_HANDLE(void);
+
+typedef unsigned long xen_pfn_t;
+DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
#endif
/*
@@ -211,9 +214,19 @@ struct vcpu_guest_context {
struct vcpu_guest_context {
/* FPU registers come first so they can be aligned for FXSAVE/FXRSTOR. */
struct { char x[512]; } fpu_ctxt; /* User-level FPU registers */
-#define VGCF_I387_VALID (1<<0)
-#define VGCF_HVM_GUEST (1<<1)
-#define VGCF_IN_KERNEL (1<<2)
+#define VGCF_I387_VALID (1<<0)
+#define VGCF_HVM_GUEST (1<<1)
+#define VGCF_IN_KERNEL (1<<2)
+#define _VGCF_i387_valid 0
+#define VGCF_i387_valid (1<<_VGCF_i387_valid)
+#define _VGCF_hvm_guest 1
+#define VGCF_hvm_guest (1<<_VGCF_hvm_guest)
+#define _VGCF_in_kernel 2
+#define VGCF_in_kernel (1<<_VGCF_in_kernel)
+#define _VGCF_failsafe_disables_events 3
+#define VGCF_failsafe_disables_events (1<<_VGCF_failsafe_disables_events)
+#define _VGCF_syscall_disables_events 4
+#define VGCF_syscall_disables_events (1<<_VGCF_syscall_disables_events)
unsigned long flags; /* VGCF_* flags */
struct cpu_user_regs user_regs; /* User-level CPU registers */
struct trap_info trap_ctxt[256]; /* Virtual IDT */
@@ -234,10 +247,13 @@ typedef struct vcpu_guest_context vcpu_g
typedef struct vcpu_guest_context vcpu_guest_context_t;
DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
+#define xen_pfn_to_cr3(pfn) ((unsigned long)(pfn) << 12)
+#define xen_cr3_to_pfn(cr3) ((unsigned long)(cr3) >> 12)
+
struct arch_shared_info {
unsigned long max_pfn; /* max pfn that appears in table */
/* Frame containing list of mfns containing list of mfns containing p2m. */
- unsigned long pfn_to_mfn_frame_list_list;
+ xen_pfn_t pfn_to_mfn_frame_list_list;
unsigned long nmi_reason;
};
typedef struct arch_shared_info arch_shared_info_t;
diff -r 760669a37a3a -r 5c0c59eb5f73 include/xen/interface/callback.h
--- a/include/xen/interface/callback.h Wed Jun 07 19:53:53 2006 -0400
+++ b/include/xen/interface/callback.h Thu Jun 08 15:10:05 2006 -0400
@@ -29,12 +29,20 @@
#define CALLBACKTYPE_nmi 4
/*
+ * Disable event deliver during callback? This flag is ignored for event and
+ * NMI callbacks: event delivery is unconditionally disabled.
+ */
+#define _CALLBACKF_mask_events 0
+#define CALLBACKF_mask_events (1U << _CALLBACKF_mask_events)
+
+/*
* Register a callback.
*/
#define CALLBACKOP_register 0
struct callback_register {
- int type;
- xen_callback_t address;
+ uint16_t type;
+ uint16_t flags;
+ xen_callback_t address;
};
typedef struct callback_register callback_register_t;
DEFINE_XEN_GUEST_HANDLE(callback_register_t);
@@ -47,7 +55,8 @@ DEFINE_XEN_GUEST_HANDLE(callback_registe
*/
#define CALLBACKOP_unregister 1
struct callback_unregister {
- int type;
+ uint16_t type;
+ uint16_t _unused;
};
typedef struct callback_unregister callback_unregister_t;
DEFINE_XEN_GUEST_HANDLE(callback_unregister_t);
diff -r 760669a37a3a -r 5c0c59eb5f73 include/xen/interface/grant_table.h
--- a/include/xen/interface/grant_table.h Wed Jun 07 19:53:53 2006 -0400
+++ b/include/xen/interface/grant_table.h Thu Jun 08 15:10:05 2006 -0400
@@ -244,7 +244,7 @@ DEFINE_XEN_GUEST_HANDLE(gnttab_dump_tabl
#define GNTTABOP_transfer 4
struct gnttab_transfer {
/* IN parameters. */
- unsigned long mfn;
+ xen_pfn_t mfn;
domid_t domid;
grant_ref_t ref;
/* OUT parameters. */
diff -r 760669a37a3a -r 5c0c59eb5f73 include/xen/interface/io/netif.h
--- a/include/xen/interface/io/netif.h Wed Jun 07 19:53:53 2006 -0400
+++ b/include/xen/interface/io/netif.h Thu Jun 08 15:10:05 2006 -0400
@@ -26,6 +26,10 @@
/* Packet data has been validated against protocol checksum. */
#define _NETTXF_data_validated (1)
#define NETTXF_data_validated (1U<<_NETTXF_data_validated)
+
+/* Packet continues in the request. */
+#define _NETTXF_more_data (2)
+#define NETTXF_more_data (1U<<_NETTXF_more_data)
struct netif_tx_request {
grant_ref_t gref; /* Reference to buffer page */
diff -r 760669a37a3a -r 5c0c59eb5f73 include/xen/interface/io/ring.h
--- a/include/xen/interface/io/ring.h Wed Jun 07 19:53:53 2006 -0400
+++ b/include/xen/interface/io/ring.h Thu Jun 08 15:10:05 2006 -0400
@@ -151,19 +151,27 @@ typedef struct __name##_back_ring __name
#define RING_SIZE(_r) \
((_r)->nr_ents)
+/* Number of free requests (for use on front side only). */
+#define RING_FREE_REQUESTS(_r) \
+ (RING_SIZE(_r) - ((_r)->req_prod_pvt - (_r)->rsp_cons))
+
/* Test if there is an empty slot available on the front ring.
* (This is only meaningful from the front. )
*/
#define RING_FULL(_r) \
- (((_r)->req_prod_pvt - (_r)->rsp_cons) == RING_SIZE(_r))
+ (RING_FREE_REQUESTS(_r) == 0)
/* Test if there are outstanding messages to be processed on a ring. */
#define RING_HAS_UNCONSUMED_RESPONSES(_r) \
- ((_r)->rsp_cons != (_r)->sring->rsp_prod)
+ ((_r)->sring->rsp_prod - (_r)->rsp_cons)
#define RING_HAS_UNCONSUMED_REQUESTS(_r) \
- (((_r)->req_cons != (_r)->sring->req_prod) && \
- (((_r)->req_cons - (_r)->rsp_prod_pvt) != RING_SIZE(_r)))
+ ({ \
+ unsigned int req = (_r)->sring->req_prod - (_r)->req_cons; \
+ unsigned int rsp = RING_SIZE(_r) - \
+ ((_r)->req_cons - (_r)->rsp_prod_pvt); \
+ req < rsp ? req : rsp; \
+ })
/* Direct access to individual ring elements, by index. */
#define RING_GET_REQUEST(_r, _idx) \
diff -r 760669a37a3a -r 5c0c59eb5f73 include/xen/interface/memory.h
--- a/include/xen/interface/memory.h Wed Jun 07 19:53:53 2006 -0400
+++ b/include/xen/interface/memory.h Thu Jun 08 15:10:05 2006 -0400
@@ -29,7 +29,7 @@ struct xen_memory_reservation {
* OUT: GMFN bases of extents that were allocated
* (NB. This command also updates the mach_to_phys translation table)
*/
- XEN_GUEST_HANDLE(ulong) extent_start;
+ XEN_GUEST_HANDLE(xen_pfn_t) extent_start;
/* Number of extents, and size/alignment of each (2^extent_order pages). */
unsigned long nr_extents;
@@ -87,7 +87,7 @@ struct xen_machphys_mfn_list {
* any large discontiguities in the machine address space, 2MB gaps in
* the machphys table will be represented by an MFN base of zero.
*/
- XEN_GUEST_HANDLE(ulong) extent_start;
+ XEN_GUEST_HANDLE(xen_pfn_t) extent_start;
/*
* Number of extents written to the above array. This will be smaller
@@ -117,7 +117,7 @@ struct xen_add_to_physmap {
unsigned long idx;
/* GPFN where the source mapping page should appear. */
- unsigned long gpfn;
+ xen_pfn_t gpfn;
};
typedef struct xen_add_to_physmap xen_add_to_physmap_t;
DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_t);
@@ -135,13 +135,13 @@ struct xen_translate_gpfn_list {
unsigned long nr_gpfns;
/* List of GPFNs to translate. */
- XEN_GUEST_HANDLE(ulong) gpfn_list;
+ XEN_GUEST_HANDLE(xen_pfn_t) gpfn_list;
/*
* Output list to contain MFN translations. May be the same as the input
* list (in which case each input GPFN is overwritten with the output MFN).
*/
- XEN_GUEST_HANDLE(ulong) mfn_list;
+ XEN_GUEST_HANDLE(xen_pfn_t) mfn_list;
};
typedef struct xen_translate_gpfn_list xen_translate_gpfn_list_t;
DEFINE_XEN_GUEST_HANDLE(xen_translate_gpfn_list_t);
diff -r 760669a37a3a -r 5c0c59eb5f73 include/xen/interface/sched_ctl.h
--- a/include/xen/interface/sched_ctl.h Wed Jun 07 19:53:53 2006 -0400
+++ b/include/xen/interface/sched_ctl.h Thu Jun 08 15:10:05 2006 -0400
@@ -49,7 +49,7 @@ struct sched_adjdom_cmd {
uint32_t extratime;
uint32_t weight;
} sedf;
- struct csched_domain {
+ struct sched_credit_adjdom {
uint16_t weight;
uint16_t cap;
} credit;
diff -r 760669a37a3a -r 5c0c59eb5f73 include/xen/interface/xen.h
--- a/include/xen/interface/xen.h Wed Jun 07 19:53:53 2006 -0400
+++ b/include/xen/interface/xen.h Thu Jun 08 15:10:05 2006 -0400
@@ -199,7 +199,7 @@ struct mmuext_op {
unsigned int cmd;
union {
/* [UN]PIN_TABLE, NEW_BASEPTR, NEW_USER_BASEPTR */
- unsigned long mfn;
+ xen_pfn_t mfn;
/* INVLPG_LOCAL, INVLPG_ALL, SET_LDT */
unsigned long linear_addr;
} arg1;
@@ -236,10 +236,24 @@ DEFINE_XEN_GUEST_HANDLE(mmuext_op_t);
*/
#define VMASST_CMD_enable 0
#define VMASST_CMD_disable 1
+
+/* x86/32 guests: simulate full 4GB segment limits. */
#define VMASST_TYPE_4gb_segments 0
+
+/* x86/32 guests: trap (vector 15) whenever above vmassist is used. */
#define VMASST_TYPE_4gb_segments_notify 1
+
+/*
+ * x86 guests: support writes to bottom-level PTEs.
+ * NB1. Page-directory entries cannot be written.
+ * NB2. Guest must continue to remove all writable mappings of PTEs.
+ */
#define VMASST_TYPE_writable_pagetables 2
-#define MAX_VMASST_TYPE 2
+
+/* x86/PAE guests: support PDPTs above 4GB. */
+#define VMASST_TYPE_pae_extended_cr3 3
+
+#define MAX_VMASST_TYPE 3
#ifndef __ASSEMBLY__
@@ -449,9 +463,9 @@ struct start_info {
unsigned long nr_pages; /* Total pages allocated to this domain. */
unsigned long shared_info; /* MACHINE address of shared info struct. */
uint32_t flags; /* SIF_xxx flags. */
- unsigned long store_mfn; /* MACHINE page number of shared page. */
+ xen_pfn_t store_mfn; /* MACHINE page number of shared page. */
uint32_t store_evtchn; /* Event channel for store communication. */
- unsigned long console_mfn; /* MACHINE address of console page. */
+ xen_pfn_t console_mfn; /* MACHINE page number of console page. */
uint32_t console_evtchn; /* Event channel for console messages. */
/* THE FOLLOWING ARE ONLY FILLED IN ON INITIAL BOOT (NOT RESUME). */
unsigned long pt_base; /* VIRTUAL address of page directory. */
diff -r 760669a37a3a -r 5c0c59eb5f73 arch/ia64/xen/drivers/Makefile
--- a/arch/ia64/xen/drivers/Makefile Wed Jun 07 19:53:53 2006 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-
-ifneq ($(CONFIG_XEN_IA64_DOM0_VP),y)
-obj-y += util.o
-endif
-
-obj-y += core/
-#obj-y += char/
-obj-y += console/
-obj-y += evtchn/
-obj-$(CONFIG_XEN_IA64_DOM0_VP) += balloon/
-obj-y += privcmd/
-obj-y += xenbus/
-
-obj-$(CONFIG_XEN_BLKDEV_BACKEND) += blkback/
-obj-$(CONFIG_XEN_NETDEV_BACKEND) += netback/
-obj-$(CONFIG_XEN_TPMDEV_BACKEND) += tpmback/
-obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += blkfront/
-obj-$(CONFIG_XEN_NETDEV_FRONTEND) += netfront/
-obj-$(CONFIG_XEN_BLKDEV_TAP) += blktap/
-obj-$(CONFIG_XEN_TPMDEV_FRONTEND) += tpmfront/
-obj-$(CONFIG_XEN_PCIDEV_BACKEND) += pciback/
-obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += pcifront/
diff -r 760669a37a3a -r 5c0c59eb5f73 arch/ia64/xen/drivers/coreMakefile
--- a/arch/ia64/xen/drivers/coreMakefile Wed Jun 07 19:53:53 2006 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-obj-y := gnttab.o features.o
-obj-$(CONFIG_PROC_FS) += xen_proc.o
-
-ifeq ($(ARCH),ia64)
-obj-y += evtchn_ia64.o
-obj-y += xenia64_init.o
-ifeq ($(CONFIG_XEN_IA64_DOM0_VP),y)
-obj-$(CONFIG_NET) += skbuff.o
-endif
-else
-obj-y += reboot.o evtchn.o fixup.o
-obj-$(CONFIG_SMP) += smp.o # setup_profiling_timer def'd in ia64
-obj-$(CONFIG_NET) += skbuff.o # until networking is up on ia64
-endif
-obj-$(CONFIG_SYSFS) += hypervisor_sysfs.o
-obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o
diff -r 760669a37a3a -r 5c0c59eb5f73 arch/ia64/xen/drivers/evtchn_ia64.c
--- a/arch/ia64/xen/drivers/evtchn_ia64.c Wed Jun 07 19:53:53 2006 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,261 +0,0 @@
-/* NOTE: This file split off from evtchn.c because there was
- some discussion that the mechanism is sufficiently different.
- It may be possible to merge it back in the future... djm */
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <asm/hw_irq.h>
-#include <xen/evtchn.h>
-
-#define MAX_EVTCHN 1024
-
-/* Xen will never allocate port zero for any purpose. */
-#define VALID_EVTCHN(_chn) (((_chn) != 0) && ((_chn) < MAX_EVTCHN))
-
-/* Binding types. Hey, only IRQT_VIRQ and IRQT_EVTCHN are supported now
- * for XEN/IA64 - ktian1
- */
-enum { IRQT_UNBOUND, IRQT_PIRQ, IRQT_VIRQ, IRQT_IPI, IRQT_EVTCHN };
-
-/* Constructor for packed IRQ information. */
-#define mk_irq_info(type, index, evtchn) \
- (((u32)(type) << 24) | ((u32)(index) << 16) | (u32)(evtchn))
-/* Convenient shorthand for packed representation of an unbound IRQ. */
-#define IRQ_UNBOUND mk_irq_info(IRQT_UNBOUND, 0, 0)
-/* Accessor macros for packed IRQ information. */
-#define evtchn_from_irq(irq) ((u16)(irq_info[irq]))
-#define index_from_irq(irq) ((u8)(irq_info[irq] >> 16))
-#define type_from_irq(irq) ((u8)(irq_info[irq] >> 24))
-
-/* Packed IRQ information: binding type, sub-type index, and event channel. */
-static u32 irq_info[NR_IRQS];
-
-/* One note for XEN/IA64 is that we have all event channels bound to one
- * physical irq vector. So we always mean evtchn vector identical to 'irq'
- * vector in this context. - ktian1
- */
-static struct {
- irqreturn_t (*handler)(int, void *, struct pt_regs *);
- void *dev_id;
- char opened; /* Whether allocated */
-} evtchns[MAX_EVTCHN];
-
-/*
- * This lock protects updates to the following mapping and reference-count
- * arrays. The lock does not need to be acquired to read the mapping tables.
- */
-static spinlock_t irq_mapping_update_lock;
-
-void mask_evtchn(int port)
-{
- shared_info_t *s = HYPERVISOR_shared_info;
- synch_set_bit(port, &s->evtchn_mask[0]);
-}
-EXPORT_SYMBOL(mask_evtchn);
-
-void unmask_evtchn(int port)
-{
- shared_info_t *s = HYPERVISOR_shared_info;
- unsigned int cpu = smp_processor_id();
- vcpu_info_t *vcpu_info = &s->vcpu_info[cpu];
-
-#if 0 // FIXME: diverged from x86 evtchn.c
- /* Slow path (hypercall) if this is a non-local port. */
- if (unlikely(cpu != cpu_from_evtchn(port))) {
- struct evtchn_unmask op = { .port = port };
- (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &op);
- return;
- }
-#endif
-
- synch_clear_bit(port, &s->evtchn_mask[0]);
-
- /*
- * The following is basically the equivalent of 'hw_resend_irq'. Just
- * like a real IO-APIC we 'lose the interrupt edge' if the channel is
- * masked.
- */
- if (synch_test_bit(port, &s->evtchn_pending[0]) &&
- !synch_test_and_set_bit(port / BITS_PER_LONG,
- &vcpu_info->evtchn_pending_sel)) {
- vcpu_info->evtchn_upcall_pending = 1;
- if (!vcpu_info->evtchn_upcall_mask)
- force_evtchn_callback();
- }
-}
-EXPORT_SYMBOL(unmask_evtchn);
-
-
-#define unbound_irq(e) (VALID_EVTCHN(e) && (!evtchns[(e)].opened))
-int bind_virq_to_irqhandler(
- unsigned int virq,
- unsigned int cpu,
- irqreturn_t (*handler)(int, void *, struct pt_regs *),
- unsigned long irqflags,
- const char *devname,
- void *dev_id)
-{
- struct evtchn_bind_virq bind_virq;
- int evtchn;
-
- spin_lock(&irq_mapping_update_lock);
-
- bind_virq.virq = virq;
- bind_virq.vcpu = cpu;
- if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &bind_virq) != 0)
- BUG();
- evtchn = bind_virq.port;
-
- if (!unbound_irq(evtchn)) {
- evtchn = -EINVAL;
- goto out;
- }
-
- evtchns[evtchn].handler = handler;
- evtchns[evtchn].dev_id = dev_id;
- evtchns[evtchn].opened = 1;
- irq_info[evtchn] = mk_irq_info(IRQT_VIRQ, virq, evtchn);
-
- unmask_evtchn(evtchn);
-out:
- spin_unlock(&irq_mapping_update_lock);
- return evtchn;
-}
-
-int bind_evtchn_to_irqhandler(unsigned int evtchn,
- irqreturn_t (*handler)(int, void *, struct pt_regs *),
- unsigned long irqflags, const char * devname, void *dev_id)
-{
- spin_lock(&irq_mapping_update_lock);
-
- if (!unbound_irq(evtchn)) {
- evtchn = -EINVAL;
- goto out;
- }
-
- evtchns[evtchn].handler = handler;
- evtchns[evtchn].dev_id = dev_id;
- evtchns[evtchn].opened = 1;
- irq_info[evtchn] = mk_irq_info(IRQT_EVTCHN, 0, evtchn);
-
- unmask_evtchn(evtchn);
-out:
- spin_unlock(&irq_mapping_update_lock);
- return evtchn;
-}
-
-int bind_ipi_to_irqhandler(
- unsigned int ipi,
- unsigned int cpu,
- irqreturn_t (*handler)(int, void *, struct pt_regs *),
- unsigned long irqflags,
- const char *devname,
- void *dev_id)
-{
- printk("%s is called which has not been supported now...?\n",
__FUNCTION__);
- while(1);
-}
-
-void unbind_from_irqhandler(unsigned int irq, void *dev_id)
-{
- struct evtchn_close close;
- int evtchn = evtchn_from_irq(irq);
-
- spin_lock(&irq_mapping_update_lock);
-
- if (unbound_irq(irq))
- goto out;
-
- close.port = evtchn;
- if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
- BUG();
-
- switch (type_from_irq(irq)) {
- case IRQT_VIRQ:
- /* Add smp stuff later... */
- break;
- case IRQT_IPI:
- /* Add smp stuff later... */
- break;
- default:
- break;
- }
-
- mask_evtchn(evtchn);
- evtchns[evtchn].handler = NULL;
- evtchns[evtchn].opened = 0;
-
-out:
- spin_unlock(&irq_mapping_update_lock);
-}
-
-void notify_remote_via_irq(int irq)
-{
- int evtchn = evtchn_from_irq(irq);
-
- if (!unbound_irq(evtchn))
- notify_remote_via_evtchn(evtchn);
-}
-
-irqreturn_t evtchn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- unsigned long l1, l2;
- unsigned int l1i, l2i, port;
- irqreturn_t (*handler)(int, void *, struct pt_regs *);
- shared_info_t *s = HYPERVISOR_shared_info;
- vcpu_info_t *vcpu_info = &s->vcpu_info[smp_processor_id()];
-
- vcpu_info->evtchn_upcall_mask = 1;
- vcpu_info->evtchn_upcall_pending = 0;
-
- /* NB. No need for a barrier here -- XCHG is a barrier on x86. */
- l1 = xchg(&vcpu_info->evtchn_pending_sel, 0);
- while ( l1 != 0 )
- {
- l1i = __ffs(l1);
- l1 &= ~(1UL << l1i);
-
- while ( (l2 = s->evtchn_pending[l1i] & ~s->evtchn_mask[l1i]) != 0 )
- {
- l2i = __ffs(l2);
- l2 &= ~(1UL << l2i);
-
- port = (l1i * BITS_PER_LONG) + l2i;
- if ( (handler = evtchns[port].handler) != NULL )
- {
- clear_evtchn(port);
- handler(port, evtchns[port].dev_id, regs);
- }
- else
- {
- evtchn_device_upcall(port);
- }
- }
- }
- vcpu_info->evtchn_upcall_mask = 0;
- return IRQ_HANDLED;
-}
-
-void force_evtchn_callback(void)
-{
- //(void)HYPERVISOR_xen_version(0, NULL);
-}
-
-static struct irqaction evtchn_irqaction = {
- .handler = evtchn_interrupt,
- .flags = SA_INTERRUPT,
- .name = "xen-event-channel"
-};
-
-static int evtchn_irq = 0xe9;
-void __init evtchn_init(void)
-{
- shared_info_t *s = HYPERVISOR_shared_info;
-
- register_percpu_irq(evtchn_irq, &evtchn_irqaction);
-
- s->arch.evtchn_vector = evtchn_irq;
- printk("xen-event-channel using irq %d\n", evtchn_irq);
-
- spin_lock_init(&irq_mapping_update_lock);
- memset(evtchns, 0, sizeof(evtchns));
-}
diff -r 760669a37a3a -r 5c0c59eb5f73 arch/ia64/xen/xenconsole.c
--- a/arch/ia64/xen/xenconsole.c Wed Jun 07 19:53:53 2006 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-#include <linux/config.h>
-#include <linux/console.h>
-
-int
-early_xen_console_setup (char *cmdline)
-{
-#ifdef CONFIG_XEN
-#ifndef CONFIG_IA64_HP_SIM
- extern int running_on_xen;
- if (running_on_xen) {
- extern struct console hpsim_cons;
- hpsim_cons.flags |= CON_BOOT;
- register_console(&hpsim_cons);
- return 0;
- }
-#endif
-#endif
- return -1;
-}
_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ppc-devel
|