[PATCH 1/4] xen interface for HVM S3
- add two sub hypercalls under HVMOP hypercall:
HVMOP_s3_suspend/HVM_s3_resume
- HVMOP_s3_suspend will reset all HVM vcpus; meanwhile, power off all
the HVM virtual device in hypervisor, e.g, pic, apic, RTC and HPET
- HVMOP_s3_resume will set BSP eip to VMXASSIST base, so that HVM will
start from rombios post entry (ffff:0000); meanwhile, power on the HVM
virtual device.
Signed-off-by: Tian Kevin <kevin.tian@xxxxxxxxx>
Signed-off-by: Yu Ke <ke.yu@xxxxxxxxx>
diff -r 305e28c0ef9b xen/arch/x86/hvm/hpet.c
--- a/xen/arch/x86/hvm/hpet.c Wed May 09 22:50:26 2007 +0100
+++ b/xen/arch/x86/hvm/hpet.c Tue May 15 14:36:02 2007 -0400
@@ -455,3 +455,17 @@ void hpet_deinit(struct domain *d)
kill_timer(&h->timers[i]);
}
+void hpet_poweroff(struct domain *d)
+{
+ HPETState *hp = &d->arch.hvm_domain.pl_time.vhpet;
+ int i;
+
+ for ( i = 0; i < HPET_TIMER_NUM; i++)
+ stop_timer(&hp->timers[i]);
+}
+
+void hpet_poweron(struct domain *d)
+{
+ /* Let's do a fresh init */
+ hpet_init(d->vcpu[0]);
+}
diff -r 305e28c0ef9b xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c Wed May 09 22:50:26 2007 +0100
+++ b/xen/arch/x86/hvm/hvm.c Tue May 15 14:36:02 2007 -0400
@@ -992,6 +992,107 @@ static int hvmop_set_pci_link_route(
rc = 0;
hvm_set_pci_link_route(d, op.link, op.isa_irq);
+
+ out:
+ rcu_unlock_domain(d);
+ return rc;
+}
+
+static int hvmop_s3_suspend(struct domain *d)
+{
+ struct vcpu *v;
+
+ if (d->arch.hvm_domain.acpi_sleep_state != 0){
+ printk("Error: HVM domain not working, so skip sleeping\n");
+ return -1;
+ }
+
+ /* Cancel any pending callback like timer */
+ pit_poweroff(d);
+ rtc_poweroff(d);
+ pmtimer_poweroff(d);
+ hpet_poweroff(d);
+
+ for_each_vcpu ( d, v )
+ hvm_vcpu_reset(v);
+
+ d->arch.hvm_domain.acpi_sleep_state = 3; /* ACPI S3 */
+
+ return 0;
+}
+
+static int hvmop_s3_resume(struct domain *d)
+{
+ int rc;
+ struct vcpu *v;
+ struct vcpu_guest_context ctxt;
+ struct cpu_user_regs *regs;
+
+ if (d->arch.hvm_domain.acpi_sleep_state != 3){
+ printk("Error: HVM domain not in S3 sleep state, so skip
resuming\n");
+ rc = -1;
+ goto out;
+ }
+
+ /* setup BSP */
+ memset (&ctxt, 0, sizeof(ctxt));
+ rc = boot_vcpu(d, 0, &ctxt);
+ if (rc != 0) {
+ gdprintk(XENLOG_ERR, "boot vcpu 0 failed\n" );
+ goto out;
+ }
+
+ v = d->vcpu[0];
+ regs = &v->arch.hvm_vcpu.io_op.io_context;
+ regs->eip = VMXASSIST_BASE;
+ regs->edx = 0;
+
+ pit_poweron(d);
+ rtc_poweron(d);
+ pmtimer_poweron(d);
+ hpet_poweron(d);
+
+ if ( test_and_clear_bit(_VPF_down, &v->pause_flags) )
+ vcpu_wake(v);
+
+ d->arch.hvm_domain.acpi_sleep_state = 0; /* ACPI S0 */
+
+out:
+ return rc;
+}
+
+static int hvmop_s3(
+ XEN_GUEST_HANDLE(xen_hvm_s3_t) uop)
+{
+ struct xen_hvm_s3 op;
+ struct domain *d;
+ int rc;
+
+ if ( copy_from_guest(&op, uop, 1) )
+ return -EFAULT;
+
+ if ( !IS_PRIV(current->domain) )
+ return -EPERM;
+
+ d = rcu_lock_domain_by_id(op.domid);
+ if ( d == NULL )
+ return -ESRCH;
+
+ rc = -EINVAL;
+ if ( !is_hvm_domain(d) )
+ goto out;
+
+ switch (op.op){
+ case HVMOP_S3_suspend:
+ rc = hvmop_s3_suspend(d);
+ break;
+ case HVMOP_S3_resume:
+ rc = hvmop_s3_resume(d);
+ break;
+ default:
+ printk("invalid HVM S3 op %x\n", op.op);
+ goto out;
+ }
out:
rcu_unlock_domain(d);
@@ -1090,6 +1191,11 @@ long do_hvm_op(unsigned long op, XEN_GUE
rc = hvmop_set_pci_link_route(
guest_handle_cast(arg, xen_hvm_set_pci_link_route_t));
break;
+
+ case HVMOP_S3:
+ rc = hvmop_s3(
+ guest_handle_cast(arg, xen_hvm_s3_t));
+ break;
default:
{
diff -r 305e28c0ef9b xen/arch/x86/hvm/i8254.c
--- a/xen/arch/x86/hvm/i8254.c Wed May 09 22:50:26 2007 +0100
+++ b/xen/arch/x86/hvm/i8254.c Tue May 15 14:36:02 2007 -0400
@@ -462,6 +462,16 @@ static void pit_reset(void *opaque)
}
}
+
+void pit_poweroff(struct domain *d)
+{
+ pit_reset(&d->arch.hvm_domain.pl_time.vpit);
+}
+
+void pit_poweron(struct domain *d)
+{
+}
+
void pit_init(struct vcpu *v, unsigned long cpu_khz)
{
PITState *pit = &v->domain->arch.hvm_domain.pl_time.vpit;
diff -r 305e28c0ef9b xen/arch/x86/hvm/pmtimer.c
--- a/xen/arch/x86/hvm/pmtimer.c Wed May 09 22:50:26 2007 +0100
+++ b/xen/arch/x86/hvm/pmtimer.c Tue May 15 14:46:21 2007 -0400
@@ -254,3 +254,16 @@ void pmtimer_deinit(struct domain *d)
PMTState *s = &d->arch.hvm_domain.pl_time.vpmt;
kill_timer(&s->timer);
}
+
+/* Null for now, since no timer is required */
+void pmtimer_poweroff(struct domain *d)
+{
+}
+
+void pmtimer_poweron(struct domain *d)
+{
+ PMTState *s = &d->arch.hvm_domain.pl_time.vpmt;
+
+ /* Reset the count */
+ s->pm.tmr_val= 0;
+}
diff -r 305e28c0ef9b xen/arch/x86/hvm/rtc.c
--- a/xen/arch/x86/hvm/rtc.c Wed May 09 22:50:26 2007 +0100
+++ b/xen/arch/x86/hvm/rtc.c Tue May 15 14:36:02 2007 -0400
@@ -466,7 +466,30 @@ void rtc_deinit(struct domain *d)
{
RTCState *s = &d->arch.hvm_domain.pl_time.vrtc;
+ destroy_periodic_time(&s->pt);
kill_timer(&s->pt.timer);
kill_timer(&s->second_timer);
kill_timer(&s->second_timer2);
}
+
+/* RTC doesn't power off in native, but let's cancel its timers here */
+void rtc_poweroff(struct domain *d)
+{
+ RTCState *s = &d->arch.hvm_domain.pl_time.vrtc;
+
+ destroy_periodic_time(&s->pt);
+ stop_timer(&s->second_timer);
+ stop_timer(&s->second_timer2);
+}
+
+/* Restart counting process by catching up latest time */
+void rtc_poweron(struct domain *d)
+{
+ RTCState *s = &d->arch.hvm_domain.pl_time.vrtc;
+
+ s->current_tm = gmtime(get_localtime(d));
+ rtc_copy_date(s);
+ s->next_second_time = NOW() + 1000000000ULL;
+ set_timer(&s->second_timer2, s->next_second_time);
+}
+
diff -r 305e28c0ef9b xen/arch/x86/hvm/vlapic.c
--- a/xen/arch/x86/hvm/vlapic.c Wed May 09 22:50:26 2007 +0100
+++ b/xen/arch/x86/hvm/vlapic.c Tue May 15 14:36:02 2007 -0400
@@ -960,3 +960,9 @@ int is_lvtt_enabled(struct vcpu *v)
return 1;
}
+
+void vlapic_poweroff(struct vlapic *s)
+{
+ destroy_periodic_time(&s->pt);
+}
+
diff -r 305e28c0ef9b xen/arch/x86/hvm/vpt.c
--- a/xen/arch/x86/hvm/vpt.c Wed May 09 22:50:26 2007 +0100
+++ b/xen/arch/x86/hvm/vpt.c Tue May 15 14:36:02 2007 -0400
@@ -120,7 +120,7 @@ void pt_update_irq(struct vcpu *v)
{
vlapic_set_irq(vcpu_vlapic(v), irq, 0);
}
- else if ( irq >= 0 )
+ else if ( irq>=0 && irq<=15 )
{
hvm_isa_irq_deassert(v->domain, irq);
hvm_isa_irq_assert(v->domain, irq);
diff -r 305e28c0ef9b xen/include/asm-x86/hvm/domain.h
--- a/xen/include/asm-x86/hvm/domain.h Wed May 09 22:50:26 2007 +0100
+++ b/xen/include/asm-x86/hvm/domain.h Tue May 15 14:36:02 2007 -0400
@@ -54,6 +54,8 @@ struct hvm_domain {
int pbuf_idx;
spinlock_t pbuf_lock;
+ int acpi_sleep_state; /* 0~5: ACPI S0~S5*/
+
uint64_t params[HVM_NR_PARAMS];
};
diff -r 305e28c0ef9b xen/include/asm-x86/hvm/vlapic.h
--- a/xen/include/asm-x86/hvm/vlapic.h Wed May 09 22:50:26 2007 +0100
+++ b/xen/include/asm-x86/hvm/vlapic.h Tue May 15 14:36:02 2007 -0400
@@ -80,6 +80,8 @@ void vlapic_destroy(struct vcpu *v);
void vlapic_reset(struct vlapic *vlapic);
+void vlapic_poweroff(struct vlapic *s);
+
void vlapic_msr_set(struct vlapic *vlapic, uint64_t value);
int vlapic_accept_pic_intr(struct vcpu *v);
diff -r 305e28c0ef9b xen/include/asm-x86/hvm/vpt.h
--- a/xen/include/asm-x86/hvm/vpt.h Wed May 09 22:50:26 2007 +0100
+++ b/xen/include/asm-x86/hvm/vpt.h Tue May 15 14:36:02 2007 -0400
@@ -125,6 +125,8 @@ void destroy_periodic_time(struct period
void destroy_periodic_time(struct periodic_time *pt);
int pv_pit_handler(int port, int data, int write);
+void pit_poweroff(struct domain *d);
+void pit_poweron(struct domain *d);
void pit_init(struct vcpu *v, unsigned long cpu_khz);
void pit_stop_channel0_irq(PITState * pit);
void pit_migrate_timers(struct vcpu *v);
@@ -132,12 +134,18 @@ void rtc_init(struct vcpu *v, int base);
void rtc_init(struct vcpu *v, int base);
void rtc_migrate_timers(struct vcpu *v);
void rtc_deinit(struct domain *d);
+void rtc_poweroff(struct domain *d);
+void rtc_poweron(struct domain *d);
int is_rtc_periodic_irq(void *opaque);
void pmtimer_init(struct vcpu *v);
void pmtimer_deinit(struct domain *d);
+void pmtimer_poweroff(struct domain *d);
+void pmtimer_poweron(struct domain *d);
void hpet_migrate_timers(struct vcpu *v);
void hpet_init(struct vcpu *v);
void hpet_deinit(struct domain *d);
+void hpet_poweroff(struct domain *d);
+void hpet_poweron(struct domain *d);
#endif /* __ASM_X86_HVM_VPT_H__ */
diff -r 305e28c0ef9b xen/include/public/hvm/hvm_op.h
--- a/xen/include/public/hvm/hvm_op.h Wed May 09 22:50:26 2007 +0100
+++ b/xen/include/public/hvm/hvm_op.h Tue May 15 14:36:02 2007 -0400
@@ -70,4 +70,19 @@ typedef struct xen_hvm_set_pci_link_rout
typedef struct xen_hvm_set_pci_link_route xen_hvm_set_pci_link_route_t;
DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_pci_link_route_t);
+#define HVMOP_S3 5
+typedef enum {
+ HVMOP_S3_suspend = 1,
+ HVMOP_S3_resume =2
+} HVMOP_S3_t;
+
+struct xen_hvm_s3 {
+ /* Domain to do s3 */
+ domid_t domid;
+ /* S3 suspend or resume */
+ HVMOP_S3_t op;
+};
+typedef struct xen_hvm_s3 xen_hvm_s3_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_s3_t);
+
#endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
xen.patch
Description: xen.patch
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|