WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

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

To: "Keir Fraser" <Keir.Fraser@xxxxxxxxxxxx>, "Ian Pratt" <m+Ian.Pratt@xxxxxxxxxxxx>, <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH 1/12] Add suspend/resume to devices owned by Xen
From: "Tian, Kevin" <kevin.tian@xxxxxxxxx>
Date: Wed, 14 Feb 2007 17:11:45 +0800
Cc: "Yu, Ke" <ke.yu@xxxxxxxxx>
Delivery-date: Wed, 14 Feb 2007 01:11:20 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
Thread-index: AcdQGCYZHnKtQUGSSc+vnYGEOHQArg==
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 870e21af3d3e xen/arch/x86/apic.c
--- a/xen/arch/x86/apic.c       Fri Feb 09 11:29:21 2007 +0800
+++ b/xen/arch/x86/apic.c       Fri Feb 09 14:16:11 2007 +0800
@@ -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 870e21af3d3e xen/arch/x86/i8259.c
--- a/xen/arch/x86/i8259.c      Fri Feb 09 11:29:21 2007 +0800
+++ b/xen/arch/x86/i8259.c      Fri Feb 09 14:16:11 2007 +0800
@@ -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 870e21af3d3e xen/arch/x86/io_apic.c
--- a/xen/arch/x86/io_apic.c    Fri Feb 09 11:29:21 2007 +0800
+++ b/xen/arch/x86/io_apic.c    Fri Feb 09 14:16:11 2007 +0800
@@ -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 870e21af3d3e xen/arch/x86/time.c
--- a/xen/arch/x86/time.c       Fri Feb 09 11:29:21 2007 +0800
+++ b/xen/arch/x86/time.c       Tue Feb 13 11:18:36 2007 +0800
@@ -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");
 }
 
 
@@ -726,6 +806,7 @@ void do_settime(unsigned long secs, unsi
     read_unlock(&domlist_lock);
 }
 
+static int on_resume;
 static void local_time_calibration(void *unused)
 {
     struct cpu_time *t = &this_cpu(cpu_time);
@@ -870,7 +951,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;
@@ -879,6 +961,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). */
@@ -924,6 +1011,54 @@ 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();
+    update_vcpu_system_time(current);
+    return 0;
 }
 
 /*
diff -r 870e21af3d3e xen/drivers/char/console.c
--- a/xen/drivers/char/console.c        Fri Feb 09 11:29:21 2007 +0800
+++ b/xen/drivers/char/console.c        Fri Feb 09 14:28:16 2007 +0800
@@ -889,6 +889,26 @@ void __bug(char *file, int line)
     for ( ; ; ) ;
 }
 
+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 870e21af3d3e xen/drivers/char/serial.c
--- a/xen/drivers/char/serial.c Fri Feb 09 11:29:21 2007 +0800
+++ b/xen/drivers/char/serial.c Fri Feb 09 14:16:11 2007 +0800
@@ -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 870e21af3d3e xen/include/asm-x86/apic.h
--- a/xen/include/asm-x86/apic.h        Fri Feb 09 11:29:21 2007 +0800
+++ b/xen/include/asm-x86/apic.h        Fri Feb 09 14:20:45 2007 +0800
@@ -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 870e21af3d3e xen/include/asm-x86/io_apic.h
--- a/xen/include/asm-x86/io_apic.h     Fri Feb 09 11:29:21 2007 +0800
+++ b/xen/include/asm-x86/io_apic.h     Fri Feb 09 14:21:56 2007 +0800
@@ -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 870e21af3d3e xen/include/asm-x86/irq.h
--- a/xen/include/asm-x86/irq.h Fri Feb 09 11:29:21 2007 +0800
+++ b/xen/include/asm-x86/irq.h Tue Feb 13 11:18:16 2007 +0800
@@ -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 870e21af3d3e xen/include/asm-x86/time.h
--- a/xen/include/asm-x86/time.h        Fri Feb 09 11:29:21 2007 +0800
+++ b/xen/include/asm-x86/time.h        Fri Feb 09 14:23:47 2007 +0800
@@ -16,4 +16,6 @@ static inline cycles_t get_cycles(void)
     return c;
 }
 
+extern int time_suspend(void);
+extern int time_resume(void);
 #endif /* __X86_TIME_H__ */
diff -r 870e21af3d3e xen/include/xen/console.h
--- a/xen/include/xen/console.h Fri Feb 09 11:29:21 2007 +0800
+++ b/xen/include/xen/console.h Fri Feb 09 14:28:38 2007 +0800
@@ -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 870e21af3d3e xen/include/xen/serial.h
--- a/xen/include/xen/serial.h  Fri Feb 09 11:29:21 2007 +0800
+++ b/xen/include/xen/serial.h  Fri Feb 09 14:16:11 2007 +0800
@@ -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 870e21af3d3e xen/include/xen/time.h
--- a/xen/include/xen/time.h    Fri Feb 09 11:29:21 2007 +0800
+++ b/xen/include/xen/time.h    Tue Feb 13 11:18:53 2007 +0800
@@ -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
<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH 1/12] Add suspend/resume to devices owned by Xen, Tian, Kevin <=