[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 1/12] Add suspend/resume to devices owned by Xen


  • To: <xen-devel@xxxxxxxxxxxxxxxxxxx>
  • From: "Tian, Kevin" <kevin.tian@xxxxxxxxx>
  • Date: Tue, 15 May 2007 22:14:40 +0800
  • Delivery-date: Tue, 15 May 2007 07:13:13 -0700
  • List-id: Xen developer discussion <xen-devel.lists.xensource.com>
  • Thread-index: AceW+19nrz3vWNtATFekqBOc/y2imQ==
  • Thread-topic: [PATCH 1/12] Add suspend/resume to devices owned by Xen

Add suspend/resume to devices owned by Xen.

Signed-off-by Ke Yu <ke.yu@xxxxxxxxx>
Signed-off-by Kevin Tian <kevin.tian@xxxxxxxxx>

diff -r 3ef0510e44d0 xen/arch/x86/apic.c
--- a/xen/arch/x86/apic.c       Tue May 08 10:21:23 2007 +0100
+++ b/xen/arch/x86/apic.c       Mon May 14 15:05:28 2007 -0400
@@ -579,6 +579,95 @@ void __devinit setup_local_APIC(void)
     apic_pm_activate();
 }
 
+static struct {
+    int active;
+    /* r/w apic fields */
+    unsigned int apic_id;
+    unsigned int apic_taskpri;
+    unsigned int apic_ldr;
+    unsigned int apic_dfr;
+    unsigned int apic_spiv;
+    unsigned int apic_lvtt;
+    unsigned int apic_lvtpc;
+    unsigned int apic_lvt0;
+    unsigned int apic_lvt1;
+    unsigned int apic_lvterr;
+    unsigned int apic_tmict;
+    unsigned int apic_tdcr;
+    unsigned int apic_thmr;
+} apic_pm_state;
+
+int lapic_suspend(void)
+{
+    unsigned long flags;
+
+    if (!apic_pm_state.active)
+        return 0;
+
+    apic_pm_state.apic_id = apic_read(APIC_ID);
+    apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI);
+    apic_pm_state.apic_ldr = apic_read(APIC_LDR);
+    apic_pm_state.apic_dfr = apic_read(APIC_DFR);
+    apic_pm_state.apic_spiv = apic_read(APIC_SPIV);
+    apic_pm_state.apic_lvtt = apic_read(APIC_LVTT);
+    apic_pm_state.apic_lvtpc = apic_read(APIC_LVTPC);
+    apic_pm_state.apic_lvt0 = apic_read(APIC_LVT0);
+    apic_pm_state.apic_lvt1 = apic_read(APIC_LVT1);
+    apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR);
+    apic_pm_state.apic_tmict = apic_read(APIC_TMICT);
+    apic_pm_state.apic_tdcr = apic_read(APIC_TDCR);
+    apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR);
+    
+    local_irq_save(flags);
+    disable_local_APIC();
+    local_irq_restore(flags);
+    return 0;
+}
+
+int lapic_resume(void)
+{
+    unsigned int l, h;
+    unsigned long flags;
+
+    if (!apic_pm_state.active)
+        return 0;
+
+    local_irq_save(flags);
+
+    /*
+     * Make sure the APICBASE points to the right address
+     *
+     * FIXME! This will be wrong if we ever support suspend on
+     * SMP! We'll need to do this as part of the CPU restore!
+     */
+    rdmsr(MSR_IA32_APICBASE, l, h);
+    l &= ~MSR_IA32_APICBASE_BASE;
+    l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr;
+    wrmsr(MSR_IA32_APICBASE, l, h);
+
+    apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED);
+    apic_write(APIC_ID, apic_pm_state.apic_id);
+    apic_write(APIC_DFR, apic_pm_state.apic_dfr);
+    apic_write(APIC_LDR, apic_pm_state.apic_ldr);
+    apic_write(APIC_TASKPRI, apic_pm_state.apic_taskpri);
+    apic_write(APIC_SPIV, apic_pm_state.apic_spiv);
+    apic_write(APIC_LVT0, apic_pm_state.apic_lvt0);
+    apic_write(APIC_LVT1, apic_pm_state.apic_lvt1);
+    apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr);
+    apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc);
+    apic_write(APIC_LVTT, apic_pm_state.apic_lvtt);
+    apic_write(APIC_TDCR, apic_pm_state.apic_tdcr);
+    apic_write(APIC_TMICT, apic_pm_state.apic_tmict);
+    apic_write(APIC_ESR, 0);
+    apic_read(APIC_ESR);
+    apic_write(APIC_LVTERR, apic_pm_state.apic_lvterr);
+    apic_write(APIC_ESR, 0);
+    apic_read(APIC_ESR);
+    local_irq_restore(flags);
+    return 0;
+}
+
+
 /*
  * If Linux enabled the LAPIC against the BIOS default
  * disable it down before re-entering the BIOS on shutdown.
@@ -602,7 +691,10 @@ void lapic_shutdown(void)
     local_irq_restore(flags);
 }
 
-static void apic_pm_activate(void) { }
+static void apic_pm_activate(void)
+{
+    apic_pm_state.active = 1;
+}
 
 /*
  * Detect and enable local APICs on non-SMP boards.
diff -r 3ef0510e44d0 xen/arch/x86/i8259.c
--- a/xen/arch/x86/i8259.c      Tue May 08 10:21:23 2007 +0100
+++ b/xen/arch/x86/i8259.c      Mon May 14 15:05:28 2007 -0400
@@ -306,6 +306,36 @@ static void mask_and_ack_8259A_vector(un
     }
 }
 
+static char irq_trigger[2];
+/**
+ * ELCR registers (0x4d0, 0x4d1) control edge/level of IRQ
+ */
+static void restore_ELCR(char *trigger)
+{
+    outb(trigger[0], 0x4d0);
+    outb(trigger[1], 0x4d1);
+}
+
+static void save_ELCR(char *trigger)
+{
+    /* IRQ 0,1,2,8,13 are marked as reserved */
+    trigger[0] = inb(0x4d0) & 0xF8;
+    trigger[1] = inb(0x4d1) & 0xDE;
+}
+
+int i8259A_resume(void)
+{
+    init_8259A(0);
+    restore_ELCR(irq_trigger);
+    return 0;
+}
+
+int i8259A_suspend(void)
+{
+    save_ELCR(irq_trigger);
+    return 0;
+}
+
 void __init init_8259A(int auto_eoi)
 {
     unsigned long flags;
diff -r 3ef0510e44d0 xen/arch/x86/io_apic.c
--- a/xen/arch/x86/io_apic.c    Tue May 08 10:21:23 2007 +0100
+++ b/xen/arch/x86/io_apic.c    Mon May 14 15:09:20 2007 -0400
@@ -1793,6 +1793,78 @@ void __init setup_IO_APIC(void)
     register_keyhandler('z', print_IO_APIC_keyhandler, "print ioapic
info");
 }
 
+struct IO_APIC_route_entry *ioapic_pm_state=NULL;
+
+void ioapic_pm_state_alloc(void)
+{
+    int i, nr_entry=0;
+
+    if (ioapic_pm_state!=NULL) 
+        return;
+    
+    for (i=0; i<nr_ioapics; i++)
+        nr_entry += nr_ioapic_registers[i];
+    ioapic_pm_state = _xmalloc( sizeof(struct
IO_APIC_route_entry)*nr_entry,
+                                sizeof(struct IO_APIC_route_entry));
+}
+
+int ioapic_suspend(void)
+{
+    struct IO_APIC_route_entry *entry;
+    unsigned long flags;
+    int apic,i;
+
+    ioapic_pm_state_alloc();
+
+    if (ioapic_pm_state == NULL){
+        printk("can not suspend ioapic due to lack of memory\n");
+        return 1;
+    }
+
+    entry = ioapic_pm_state;
+    spin_lock_irqsave(&ioapic_lock, flags);
+    for (apic = 0; apic < nr_ioapics; apic++) {
+        for (i = 0; i < nr_ioapic_registers[apic]; i ++, entry ++ ) {
+            *(((int *)entry) + 1) = io_apic_read(apic, 0x11 + 2 * i);
+            *(((int *)entry) + 0) = io_apic_read(apic, 0x10 + 2 * i);
+        }
+    }
+    spin_unlock_irqrestore(&ioapic_lock, flags);
+
+    return 0;
+}
+
+int ioapic_resume(void)
+{
+    struct IO_APIC_route_entry *entry;
+    unsigned long flags;
+    union IO_APIC_reg_00 reg_00;
+    int i,apic;
+    
+    if (ioapic_pm_state == NULL){
+        printk("can not resume ioapic due to lack of memory\n");
+        return 1;
+    }
+    
+    entry = ioapic_pm_state;
+
+    spin_lock_irqsave(&ioapic_lock, flags);
+    for (apic = 0; apic < nr_ioapics; apic++){
+        reg_00.raw = io_apic_read(apic, 0);
+        if (reg_00.bits.ID != mp_ioapics[apic].mpc_apicid) {
+            reg_00.bits.ID = mp_ioapics[apic].mpc_apicid;
+            io_apic_write(apic, 0, reg_00.raw);
+        }
+        for (i = 0; i < nr_ioapic_registers[apic]; i ++, entry ++ ) {
+            io_apic_write(apic, 0x11+2*i, *(((int *)entry)+1));
+            io_apic_write(apic, 0x10+2*i, *(((int *)entry)+0));
+        }
+    }
+    spin_unlock_irqrestore(&ioapic_lock, flags);
+
+    return 0;
+}
+
 /*
------------------------------------------------------------------------
--
                           ACPI-based IOAPIC Configuration
 
------------------------------------------------------------------------
-- */
diff -r 3ef0510e44d0 xen/arch/x86/time.c
--- a/xen/arch/x86/time.c       Tue May 08 10:21:23 2007 +0100
+++ b/xen/arch/x86/time.c       Mon May 14 15:05:28 2007 -0400
@@ -60,6 +60,16 @@ struct cpu_time {
 
 static DEFINE_PER_CPU(struct cpu_time, cpu_time);
 
+struct plt_timer_ops {
+    char* name;
+    int   (*init)(void);
+    u64   (*read_count)(void);
+    void  (*suspend)(void);
+    void  (*resume)(void);
+};
+
+struct plt_timer_ops *cur_timer;
+
 /*
  * Protected by platform_timer_lock, which must be acquired with
interrupts
  * disabled because pit_overflow() is called from PIT ch0 interrupt
context.
@@ -68,7 +78,6 @@ static u64 platform_timer_stamp;
 static u64 platform_timer_stamp;
 static struct time_scale platform_timer_scale;
 static DEFINE_SPINLOCK(platform_timer_lock);
-static u64 (*read_platform_count)(void);
 
 /*
  * Folding 16-bit PIT into 64-bit software counter is a really critical
@@ -299,12 +308,13 @@ static void pit_overflow(void)
 static void pit_overflow(void)
 {
     u16 counter;
-
-    spin_lock_irq(&platform_timer_lock);
+    unsigned long flags;
+
+    spin_lock_irqsave(&platform_timer_lock, flags);
     counter = pit_read_counter();
     pit_counter64 += (u16)(pit_stamp - counter);
     pit_stamp = counter;
-    spin_unlock_irq(&platform_timer_lock);
+    spin_unlock_irqrestore(&platform_timer_lock, flags);
 }
 
 static u64 read_pit_count(void)
@@ -312,17 +322,33 @@ static u64 read_pit_count(void)
     return pit_counter64 + (u16)(pit_stamp - pit_read_counter());
 }
 
-static void init_pit(void)
-{
-    read_platform_count = read_pit_count;
-
+static int init_pit(void)
+{
     pit_overflow();
     platform_timer_stamp = pit_counter64;
     set_time_scale(&platform_timer_scale, CLOCK_TICK_RATE);
 
     printk("Platform timer is %s PIT\n", freq_string(CLOCK_TICK_RATE));
     using_pit = 1;
-}
+    return 1;
+}
+
+static void resume_pit(void)
+{
+    unsigned long flags;
+
+    spin_lock_irqsave(&platform_timer_lock, flags);
+    platform_timer_stamp = pit_counter64;
+    pit_stamp = pit_read_counter();
+    spin_unlock_irqrestore(&platform_timer_lock, flags);
+}
+
+static struct plt_timer_ops timer_pit = {
+    .name = "PIT",
+    .init = init_pit,
+    .read_count = read_pit_count,
+    .resume = resume_pit,
+};
 
 /************************************************************
  * PLATFORM TIMER 2: HIGH PRECISION EVENT TIMER (HPET)
@@ -336,12 +362,13 @@ static void hpet_overflow(void *unused)
 static void hpet_overflow(void *unused)
 {
     u32 counter;
-
-    spin_lock_irq(&platform_timer_lock);
+    unsigned long flags;
+
+    spin_lock_irqsave(&platform_timer_lock, flags);
     counter = hpet_read32(HPET_COUNTER);
     hpet_counter64 += (u32)(counter - hpet_stamp);
     hpet_stamp = counter;
-    spin_unlock_irq(&platform_timer_lock);
+    spin_unlock_irqrestore(&platform_timer_lock, flags);
 
     set_timer(&hpet_overflow_timer, NOW() + hpet_overflow_period);
 }
@@ -401,8 +428,6 @@ static int init_hpet(void)
     cfg |= HPET_CFG_ENABLE;
     hpet_write32(cfg, HPET_CFG);
 
-    read_platform_count = read_hpet_count;
-
     hpet_rate = 1000000000000000ULL; /* 10^15 */
     (void)do_div(hpet_rate, hpet_period);
     set_time_scale(&platform_timer_scale, hpet_rate);
@@ -427,6 +452,23 @@ static int init_hpet(void)
 
     return 1;
 }
+
+static void resume_hpet(void)
+{
+    unsigned long flags;
+
+    spin_lock_irqsave(&platform_timer_lock, flags);
+    platform_timer_stamp = hpet_counter64;
+    hpet_stamp = hpet_read32(HPET_COUNTER);
+    spin_unlock_irqrestore(&platform_timer_lock, flags);
+}
+
+static struct plt_timer_ops timer_hpet = {
+    .name = "HPET",
+    .init = init_hpet,
+    .read_count = read_hpet_count,
+    .resume = resume_hpet,
+};
 
 /************************************************************
  * PLATFORM TIMER 3: IBM 'CYCLONE' TIMER
@@ -454,12 +496,13 @@ static void cyclone_overflow(void *unuse
 static void cyclone_overflow(void *unused)
 {
     u32 counter;
-
-    spin_lock_irq(&platform_timer_lock);
+    unsigned long flags;
+
+    spin_lock_irqsave(&platform_timer_lock, flags);
     counter = *cyclone_timer;
     cyclone_counter64 += (u32)(counter - cyclone_stamp);
     cyclone_stamp = counter;
-    spin_unlock_irq(&platform_timer_lock);
+    spin_unlock_irqrestore(&platform_timer_lock, flags);
 
     set_timer(&cyclone_overflow_timer, NOW() + MILLISECS(20000));
 }
@@ -497,8 +540,6 @@ static int init_cyclone(void)
     *(map_cyclone_reg(base + CYCLONE_MPCS_OFFSET)) = 1;
     cyclone_timer = map_cyclone_reg(base + CYCLONE_MPMC_OFFSET);
 
-    read_platform_count = read_cyclone_count;
-
     init_timer(&cyclone_overflow_timer, cyclone_overflow, NULL, 0);
     cyclone_overflow(NULL);
     platform_timer_stamp = cyclone_counter64;
@@ -510,6 +551,23 @@ static int init_cyclone(void)
     return 1;
 }
 
+static void resume_cyclone(void)
+{
+    unsigned long flags;
+
+    spin_lock_irqsave(&platform_timer_lock, flags);
+    platform_timer_stamp = cyclone_counter64;
+    cyclone_stamp = *cyclone_timer;
+    spin_unlock_irqrestore(&platform_timer_lock, flags);
+}
+
+static struct plt_timer_ops timer_cyclone = {
+    .name = "CYCLONE",
+    .init = init_cyclone,
+    .read_count = read_cyclone_count,
+    .resume = resume_cyclone,
+};
+
 /************************************************************
  * GENERIC PLATFORM TIMER INFRASTRUCTURE
  */
@@ -525,11 +583,12 @@ static s_time_t read_platform_stime(void
 {
     u64 counter;
     s_time_t stime;
-
-    spin_lock_irq(&platform_timer_lock);
-    counter = read_platform_count();
+    unsigned long flags;
+
+    spin_lock_irqsave(&platform_timer_lock, flags);
+    counter = cur_timer->read_count();
     stime   = __read_platform_stime(counter);
-    spin_unlock_irq(&platform_timer_lock);
+    spin_unlock_irqrestore(&platform_timer_lock, flags);
 
     return stime;
 }
@@ -538,19 +597,40 @@ static void platform_time_calibration(vo
 {
     u64 counter;
     s_time_t stamp;
-
-    spin_lock_irq(&platform_timer_lock);
-    counter = read_platform_count();
+    unsigned long flags;
+
+    spin_lock_irqsave(&platform_timer_lock, flags);
+    counter = cur_timer->read_count();
     stamp   = __read_platform_stime(counter);
     stime_platform_stamp = stamp;
     platform_timer_stamp = counter;
-    spin_unlock_irq(&platform_timer_lock);
-}
+    spin_unlock_irqrestore(&platform_timer_lock, flags);
+}
+
+struct plt_timer_ops *timers[] = {
+    &timer_cyclone,
+    &timer_hpet,
+    &timer_pit,
+    NULL,
+};
 
 static void init_platform_timer(void)
 {
-    if ( !init_cyclone() && !init_hpet() )
-        init_pit();
+    int i = 0;
+
+    while(timers[i])
+    {
+        if (timers[i]->init && timers[i]->init())
+        {
+            cur_timer = timers[i];
+            break;
+        }
+
+        i++;
+    }
+
+    if (!cur_timer)
+        panic("Failed to find a usable platform timer source!!!\n");
 }
 
 
@@ -725,6 +805,7 @@ void do_settime(unsigned long secs, unsi
     rcu_read_unlock(&domlist_read_lock);
 }
 
+static int on_resume;
 static void local_time_calibration(void *unused)
 {
     struct cpu_time *t = &this_cpu(cpu_time);
@@ -872,7 +953,8 @@ void init_percpu_time(void)
 
     local_irq_save(flags);
     rdtscll(t->local_tsc_stamp);
-    now = (smp_processor_id() == 0) ? 0 : read_platform_stime();
+    now = ((smp_processor_id() == 0) && !on_resume) ?
+                      0 : read_platform_stime();
     local_irq_restore(flags);
 
     t->stime_master_stamp = now;
@@ -881,6 +963,11 @@ void init_percpu_time(void)
     init_timer(&t->calibration_timer, local_time_calibration,
                NULL, smp_processor_id());
     set_timer(&t->calibration_timer, NOW() + EPOCH);
+}
+
+void destroy_percpu_time(void)
+{
+    kill_timer(&this_cpu(cpu_time).calibration_timer);
 }
 
 /* Late init function (after all CPUs are booted). */
@@ -926,6 +1013,56 @@ unsigned long get_localtime(struct domai
 {
     return wc_sec + (wc_nsec + NOW()) / 1000000000ULL 
         + d->time_offset_seconds;
+}
+
+/* timer suspend/resume */
+static u64 sleep_start;
+int time_suspend(void)
+{
+    sleep_start = get_cmos_time();
+
+    /* Better to cancel calibration timer for accuracy */
+    destroy_percpu_time();
+
+    if (cur_timer->suspend)
+        cur_timer->suspend();
+    return 0;
+}
+
+int time_resume(void)
+{
+    u64 sleep_diff;
+    u64 now;
+
+    on_resume = 1;
+
+     /* Set the clock to HZ Hz */
+#define CLOCK_TICK_RATE 1193180 /* crystal freq (Hz) */
+#define LATCH (((CLOCK_TICK_RATE)+(HZ/2))/HZ)
+    outb_p(0x34, PIT_MODE);        /* binary, mode 2, LSB/MSB, ch 0 */
+    outb_p(LATCH & 0xff, PIT_CH0); /* LSB */
+    outb(LATCH >> 8, PIT_CH0);     /* MSB */
+
+    /* Set the Gate high, disable speaker */
+    outb((inb(0x61) & ~0x02) | 0x01, 0x61);
+    outb(0xb0, PIT_MODE);
+    outb(CALIBRATE_LATCH & 0xff, PIT_CH2);
+    outb(CALIBRATE_LATCH >> 8, PIT_CH2);
+
+    now = get_cmos_time();
+    sleep_diff = now - sleep_start;    
+    wc_sec = now;
+    jiffies += sleep_diff * HZ;
+    
+    stime_platform_stamp += SECONDS(sleep_diff);
+    if (cur_timer->resume)
+        cur_timer->resume();
+
+    init_percpu_time();
+    /* Resume may happen on an idle vcpu */
+    if (!is_idle_vcpu(current))
+        update_vcpu_system_time(current);
+    return 0;
 }
 
 /*
diff -r 3ef0510e44d0 xen/drivers/char/console.c
--- a/xen/drivers/char/console.c        Tue May 08 10:21:23 2007 +0100
+++ b/xen/drivers/char/console.c        Mon May 14 15:05:28 2007 -0400
@@ -914,6 +914,26 @@ void __warn(char *file, int line)
     dump_execution_state();
 }
 
+static void dummy_steal_fn(const char *str)
+{
+    return;
+}
+
+int console_suspend(void)
+{
+    console_steal(sercon_handle, dummy_steal_fn);
+    serial_suspend();
+    return 0;
+}
+
+int console_resume(void)
+{
+    serial_init_preirq();
+    serial_init_postirq();
+    console_giveback(1);
+    return 0;
+}
+
 /*
  * Local variables:
  * mode: C
diff -r 3ef0510e44d0 xen/drivers/char/serial.c
--- a/xen/drivers/char/serial.c Tue May 08 10:21:23 2007 +0100
+++ b/xen/drivers/char/serial.c Mon May 14 15:05:28 2007 -0400
@@ -381,6 +381,17 @@ int serial_irq(int idx)
     return -1;
 }
 
+void serial_suspend(void)
+{
+    int i, irq;
+    for (i = 0; i < 2; i++)
+    {
+        irq = serial_irq(i);
+        if (irq >= 0)
+            free_irq(irq);
+    }
+}
+
 void serial_register_uart(int idx, struct uart_driver *driver, void
*uart)
 {
     /* Store UART-specific info. */
diff -r 3ef0510e44d0 xen/include/asm-x86/apic.h
--- a/xen/include/asm-x86/apic.h        Tue May 08 10:21:23 2007 +0100
+++ b/xen/include/asm-x86/apic.h        Mon May 14 15:05:28 2007 -0400
@@ -108,6 +108,8 @@ extern int APIC_init_uniprocessor (void)
 extern int APIC_init_uniprocessor (void);
 extern void disable_APIC_timer(void);
 extern void enable_APIC_timer(void);
+extern int lapic_suspend(void);
+extern int lapic_resume(void);
 
 extern int check_nmi_watchdog (void);
 extern void enable_NMI_through_LVT0 (void * dummy);
@@ -123,6 +125,8 @@ extern unsigned int nmi_watchdog;
 
 #else /* !CONFIG_X86_LOCAL_APIC */
 static inline void lapic_shutdown(void) { }
+static inline int lapic_suspend(void) {return 0;}
+static inline int lapic_resume(void) {return 0;}
 
 #endif /* !CONFIG_X86_LOCAL_APIC */
 
diff -r 3ef0510e44d0 xen/include/asm-x86/io_apic.h
--- a/xen/include/asm-x86/io_apic.h     Tue May 08 10:21:23 2007 +0100
+++ b/xen/include/asm-x86/io_apic.h     Mon May 14 15:05:28 2007 -0400
@@ -169,9 +169,13 @@ extern int timer_uses_ioapic_pin_0;
 #endif /*CONFIG_ACPI_BOOT*/
 
 extern int (*ioapic_renumber_irq)(int ioapic, int irq);
+extern int ioapic_suspend(void);
+extern int ioapic_resume(void);
 
 #else  /* !CONFIG_X86_IO_APIC */
 #define io_apic_assign_pci_irqs 0
+static inline int ioapic_suspend(void) {return 0};
+static inline int ioapic_resume(void) {return 0};
 #endif
 
 extern int assign_irq_vector(int irq);
diff -r 3ef0510e44d0 xen/include/asm-x86/irq.h
--- a/xen/include/asm-x86/irq.h Tue May 08 10:21:23 2007 +0100
+++ b/xen/include/asm-x86/irq.h Mon May 14 15:05:28 2007 -0400
@@ -35,6 +35,8 @@ void enable_8259A_irq(unsigned int irq);
 void enable_8259A_irq(unsigned int irq);
 int i8259A_irq_pending(unsigned int irq);
 void init_8259A(int aeoi);
+int i8259A_suspend(void);
+int i8259A_resume(void);
 
 void setup_IO_APIC(void);
 void disable_IO_APIC(void);
diff -r 3ef0510e44d0 xen/include/asm-x86/time.h
--- a/xen/include/asm-x86/time.h        Tue May 08 10:21:23 2007 +0100
+++ b/xen/include/asm-x86/time.h        Mon May 14 15:05:28 2007 -0400
@@ -21,4 +21,6 @@ mktime (unsigned int year, unsigned int 
         unsigned int day, unsigned int hour,
         unsigned int min, unsigned int sec);
 
+extern int time_suspend(void);
+extern int time_resume(void);
 #endif /* __X86_TIME_H__ */
diff -r 3ef0510e44d0 xen/include/xen/console.h
--- a/xen/include/xen/console.h Tue May 08 10:21:23 2007 +0100
+++ b/xen/include/xen/console.h Mon May 14 15:05:28 2007 -0400
@@ -38,4 +38,7 @@ int console_steal(int handle, void (*fn)
 /* Give back stolen console. Takes the identifier returned by
console_steal. */
 void console_giveback(int id);
 
+int console_suspend(void);
+
+int console_resume(void);
 #endif /* __CONSOLE_H__ */
diff -r 3ef0510e44d0 xen/include/xen/serial.h
--- a/xen/include/xen/serial.h  Tue May 08 10:21:23 2007 +0100
+++ b/xen/include/xen/serial.h  Mon May 14 15:05:28 2007 -0400
@@ -104,6 +104,7 @@ int serial_tx_space(int handle);
 /* Return irq number for specified serial port (identified by index).
*/
 int serial_irq(int idx);
 
+void serial_suspend(void);
 /*
  * Initialisation and helper functions for uart drivers.
  */
diff -r 3ef0510e44d0 xen/include/xen/time.h
--- a/xen/include/xen/time.h    Tue May 08 10:21:23 2007 +0100
+++ b/xen/include/xen/time.h    Mon May 14 15:05:28 2007 -0400
@@ -32,6 +32,7 @@
 
 extern int init_xen_time(void);
 extern void init_percpu_time(void);
+extern void destroy_percpu_time(void);
 
 extern unsigned long cpu_khz;

Attachment: xen_add_device_suspend_resume.patch
Description: xen_add_device_suspend_resume.patch

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.