Provide basic Xen PM infrastructure

Basic infrastructure for Xen S3 support with a common CPU
context save/restore logic for both 32bit and 64bit.

Wakeup code is split into two parts:
    - the first locates after trampoline code, to share all the
      tricks on the latter, like relocation base and identy mapping
    - the 2nd part locates in xen code segment, to do the actual
      CPU context restore

Signed-off-by Ke Yu <ke.yu@intel.com>
Signed-off-by Kevin Tian <kevin.tian@intel.com>
This commit is contained in:
kfraser@localhost.localdomain committed 2007-07-11 15:47:14 +01:00
1 parent ffc3f3c3db
commit d8c8fef090
12 files changed
+884 -4

No files matched your search

+1
View File
@@ -1 +1,2 @@
obj-y += boot.o
obj-y += power.o suspend.o wakeup_prot.o
+258
View File
@@ -0,0 +1,258 @@
/* drivers/acpi/sleep/power.c - PM core functionality for Xen
*
* Copyrights from Linux side:
* Copyright (c) 2000-2003 Patrick Mochel
* Copyright (C) 2001-2003 Pavel Machek <pavel@suse.cz>
* Copyright (c) 2003 Open Source Development Lab
* Copyright (c) 2004 David Shaohua Li <shaohua.li@intel.com>
* Copyright (c) 2005 Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>
*
* Slimmed with Xen specific support.
*/
#include <xen/config.h>
#include <asm/io.h>
#include <asm/acpi.h>
#include <xen/acpi.h>
#include <xen/errno.h>
#include <xen/iocap.h>
#include <xen/sched.h>
#include <asm/acpi.h>
#include <asm/irq.h>
#include <asm/init.h>
#include <xen/spinlock.h>
#include <xen/sched.h>
#include <xen/domain.h>
#include <xen/console.h>
#include <public/platform.h>
#define pmprintk(_l, _f, _a...) printk(_l "<PM>" _f, ## _a )
u8 sleep_states[ACPI_S_STATE_COUNT];
DEFINE_SPINLOCK(pm_lock);
struct acpi_sleep_info {
uint16_t pm1a_cnt;
uint16_t pm1b_cnt;
uint16_t pm1a_evt;
uint16_t pm1b_evt;
uint16_t pm1a_cnt_val;
uint16_t pm1b_cnt_val;
uint32_t sleep_state;
} acpi_sinfo;
extern void do_suspend_lowlevel(void);
static char *acpi_states[ACPI_S_STATE_COUNT] =
{
[ACPI_STATE_S1] = "standby",
[ACPI_STATE_S3] = "mem",
[ACPI_STATE_S4] = "disk",
};
unsigned long acpi_video_flags;
unsigned long saved_videomode;
/* XXX: Add suspend failure recover later */
static int device_power_down(void)
{
console_suspend();
time_suspend();
i8259A_suspend();
ioapic_suspend();
lapic_suspend();
return 0;
}
static void device_power_up(void)
{
lapic_resume();
ioapic_resume();
i8259A_resume();
time_resume();
console_resume();
}
/* Main interface to do xen specific suspend/resume */
int enter_state(u32 state)
{
struct domain *d;
unsigned long flags;
int error;
if (state <= ACPI_STATE_S0 || state > ACPI_S_STATES_MAX)
return -EINVAL;
/* Sync lazy state on ths cpu */
__sync_lazy_execstate();
pmprintk(XENLOG_INFO, "Flush lazy state\n");
if (!spin_trylock(&pm_lock))
return -EBUSY;
for_each_domain(d)
if (d->domain_id != 0)
domain_pause(d);
pmprintk(XENLOG_INFO, "PM: Preparing system for %s sleep\n",
acpi_states[state]);
local_irq_save(flags);
if ((error = device_power_down()))
{
printk(XENLOG_ERR "Some devices failed to power down\n");
goto Done;
}
ACPI_FLUSH_CPU_CACHE();
switch (state)
{
case ACPI_STATE_S3:
do_suspend_lowlevel();
break;
default:
error = -EINVAL;
break;
}
pmprintk(XENLOG_INFO, "Back to C!\n");
device_power_up();
pmprintk(XENLOG_INFO, "PM: Finishing wakeup.\n");
Done:
local_irq_restore(flags);
for_each_domain(d)
if (d->domain_id!=0)
domain_unpause(d);
spin_unlock(&pm_lock);
return error;
}
/*
* Xen just requires address of pm1x_cnt, and ACPI interpreter
* is still kept in dom0. Address of xen wakeup stub will be
* returned, and then dom0 writes that address to FACS.
*/
int set_acpi_sleep_info(struct xenpf_set_acpi_sleep *info)
{
if (acpi_sinfo.pm1a_cnt)
pmprintk(XENLOG_WARNING, "Multiple setting on acpi sleep info\n");
acpi_sinfo.pm1a_cnt = info->pm1a_cnt_port;
acpi_sinfo.pm1b_cnt = info->pm1b_cnt_port;
acpi_sinfo.pm1a_evt = info->pm1a_evt_port;
acpi_sinfo.pm1b_evt = info->pm1b_evt_port;
info->xen_waking_vec = (uint64_t)bootsym_phys(wakeup_start);
pmprintk(XENLOG_INFO, "pm1a[%x],pm1b[%x],pm1a_e[%x],pm1b_e[%x]"
"wake[%"PRIx64"]",
acpi_sinfo.pm1a_cnt, acpi_sinfo.pm1b_cnt,
acpi_sinfo.pm1a_evt, acpi_sinfo.pm1b_evt,
info->xen_waking_vec);
return 0;
}
/*
* Dom0 issues this hypercall in place of writing pm1a_cnt. Xen then
* takes over the control and put the system into sleep state really.
* Also video flags and mode are passed here, in case user may use
* "acpi_sleep=***" for video resume.
*
* Guest may issue a two-phases write to PM1x_CNT, to work
* around poorly implemented hardware. It's better to keep
* this logic here. Two writes can be differentiated by
* enable bit setting.
*/
int acpi_enter_sleep(struct xenpf_enter_acpi_sleep *sleep)
{
if (!IS_PRIV(current->domain) || !acpi_sinfo.pm1a_cnt)
return -EPERM;
/* Sanity check */
if (acpi_sinfo.pm1b_cnt_val &&
((sleep->pm1a_cnt_val ^ sleep->pm1b_cnt_val) &
ACPI_BITMASK_SLEEP_ENABLE))
{
pmprintk(XENLOG_ERR, "Mismatched pm1a/pm1b setting\n");
return -EINVAL;
}
/* Write #1 */
if (!(sleep->pm1a_cnt_val & ACPI_BITMASK_SLEEP_ENABLE))
{
outw((u16)sleep->pm1a_cnt_val, acpi_sinfo.pm1a_cnt);
if (acpi_sinfo.pm1b_cnt)
outw((u16)sleep->pm1b_cnt_val, acpi_sinfo.pm1b_cnt);
return 0;
}
/* Write #2 */
acpi_sinfo.pm1a_cnt_val = sleep->pm1a_cnt_val;
acpi_sinfo.pm1b_cnt_val = sleep->pm1b_cnt_val;
acpi_sinfo.sleep_state = sleep->sleep_state;
acpi_video_flags = sleep->video_flags;
saved_videomode = sleep->video_mode;
return enter_state(acpi_sinfo.sleep_state);
}
static int acpi_get_wake_status(void)
{
uint16_t val;
/* Wake status is the 15th bit of PM1 status register. (ACPI spec 3.0) */
val = inw(acpi_sinfo.pm1a_evt) | inw(acpi_sinfo.pm1b_evt);
val &= ACPI_BITMASK_WAKE_STATUS;
val >>= ACPI_BITPOSITION_WAKE_STATUS;
return val;
}
/* System is really put into sleep state by this stub */
acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
{
ACPI_FLUSH_CPU_CACHE();
outw((u16)acpi_sinfo.pm1a_cnt_val, acpi_sinfo.pm1a_cnt);
if (acpi_sinfo.pm1b_cnt)
outw((u16)acpi_sinfo.pm1b_cnt_val, acpi_sinfo.pm1b_cnt);
/* Wait until we enter sleep state, and spin until we wake */
while (!acpi_get_wake_status());
return_ACPI_STATUS(AE_OK);
}
static int __init acpi_sleep_init(void)
{
int i = 0;
pmprintk(XENLOG_INFO, "ACPI (supports");
for (i = 0; i < ACPI_S_STATE_COUNT; i++)
{
if (i == ACPI_STATE_S3)
{
sleep_states[i] = 1;
printk(" S%d", i);
}
else
sleep_states[i] = 0;
}
printk(")\n");
return 0;
}
__initcall(acpi_sleep_init);
+85
View File
@@ -0,0 +1,85 @@
/*
* Suspend support specific for i386.
*
* Distribute under GPLv2
*
* Copyright (c) 2002 Pavel Machek <pavel@suse.cz>
* Copyright (c) 2001 Patrick Mochel <mochel@osdl.org>
*/
#include <xen/config.h>
#include <xen/acpi.h>
#include <xen/smp.h>
#include <asm/processor.h>
#include <asm/msr.h>
#include <asm/flushtlb.h>
#include <asm/hvm/hvm.h>
#include <asm/hvm/support.h>
#include <asm/i387.h>
/* Following context save/restore happens on the real context
* of current vcpu, with a lazy state sync forced earlier.
*/
#if defined(CONFIG_X86_64)
unsigned long saved_lstar, saved_cstar;
#endif
void save_rest_processor_state(void)
{
/*
* Net effect of unlazy_fpu is to set cr0.ts and thus there's no
* need to restore fpu after resume.
*/
if (!is_idle_vcpu(current))
unlazy_fpu(current);
#if defined(CONFIG_X86_64)
rdmsrl(MSR_CSTAR, saved_cstar);
rdmsrl(MSR_LSTAR, saved_lstar);
#endif
bootsym(video_flags) = acpi_video_flags;
bootsym(video_mode) = saved_videomode;
}
#define loaddebug(_v,_reg) \
__asm__ __volatile__ ("mov %0,%%db" #_reg : : "r" ((_v)->debugreg[_reg]))
void restore_rest_processor_state(void)
{
int cpu = smp_processor_id();
struct tss_struct *t = &init_tss[cpu];
struct vcpu *v = current;
/* Really scared by suffixed comment from Linux, and keep it for safe */
set_tss_desc(cpu, t); /* This just modifies memory; should not be necessary. But... This is necessary, because 386 hardware has concept of busy TSS or some similar stupidity. */
load_TR(cpu);
#if defined(CONFIG_X86_64)
/* Recover syscall MSRs */
wrmsrl(MSR_LSTAR, saved_lstar);
wrmsrl(MSR_CSTAR, saved_cstar);
wrmsr(MSR_STAR, 0, (FLAT_RING3_CS32<<16) | __HYPERVISOR_CS);
wrmsr(MSR_SYSCALL_MASK, EF_VM|EF_RF|EF_NT|EF_DF|EF_IE|EF_TF, 0U);
#else /* !defined(CONFIG_X86_64) */
if (supervisor_mode_kernel && cpu_has_sep)
wrmsr(MSR_IA32_SYSENTER_ESP, &t->esp1, 0);
#endif
/* Maybe load the debug registers. */
if ( !is_idle_vcpu(v) && unlikely(v->arch.guest_context.debugreg[7]) )
{
loaddebug(&v->arch.guest_context, 0);
loaddebug(&v->arch.guest_context, 1);
loaddebug(&v->arch.guest_context, 2);
loaddebug(&v->arch.guest_context, 3);
/* no 4 and 5 */
loaddebug(&v->arch.guest_context, 6);
loaddebug(&v->arch.guest_context, 7);
}
/* Do we start fpu really? Just set cr0.ts to monitor it */
stts();
mtrr_ap_init();
mcheck_init(&boot_cpu_data);
}
+267
View File
@@ -0,0 +1,267 @@
.text
#include <xen/config.h>
#include <xen/multiboot.h>
#include <public/xen.h>
#include <asm/asm_defns.h>
#include <asm/desc.h>
#include <asm/page.h>
#include <asm/msr.h>
#if defined(__x86_64__)
.code64
#define GREG(x) %r##x
#define SAVED_GREG(x) saved_r##x(%rip)
#define DECLARE_GREG(x) saved_r##x: .quad 0
#define SAVE_GREG(x) movq GREG(x), SAVED_GREG(x)
#define LOAD_GREG(x) movq SAVED_GREG(x), GREG(x)
#define REF(x) x(%rip)
#define RDMSR(ind, m) \
xorq %rdx, %rdx; \
mov $ind, %ecx; \
rdmsr; \
shlq $0x20, %rdx; \
orq %rax, %rdx; \
movq %rdx, m(%rip);
#define WRMSR(ind, m) \
mov $ind, %ecx; \
movq m(%rip), %rdx; \
mov %edx, %eax; \
shrq $0x20, %rdx; \
wrmsr;
#else /* !defined(__x86_64__) */
.code32
#define GREG(x) %e##x
#define SAVED_GREG(x) saved_e##x
#define DECLARE_GREG(x) saved_e##x: .long 0
#define SAVE_GREG(x) movl GREG(x), SAVED_GREG(x)
#define LOAD_GREG(x) movl SAVED_GREG(x), GREG(x)
#define REF(x) x
#endif
ENTRY(do_suspend_lowlevel)
SAVE_GREG(sp)
SAVE_GREG(ax)
SAVE_GREG(bx)
SAVE_GREG(cx)
SAVE_GREG(dx)
SAVE_GREG(bp)
SAVE_GREG(si)
SAVE_GREG(di)
#if defined(__x86_64__)
SAVE_GREG(8) # save r8...r15
SAVE_GREG(9)
SAVE_GREG(10)
SAVE_GREG(11)
SAVE_GREG(12)
SAVE_GREG(13)
SAVE_GREG(14)
SAVE_GREG(15)
pushfq;
popq SAVED_GREG(flags)
mov %cr8, GREG(ax)
mov GREG(ax), REF(saved_cr8)
RDMSR(MSR_FS_BASE, saved_fs_base)
RDMSR(MSR_GS_BASE, saved_gs_base)
RDMSR(MSR_SHADOW_GS_BASE, saved_kernel_gs_base)
#else /* !defined(__x86_64__) */
pushfl;
popl SAVED_GREG(flags)
#endif
mov %ds, REF(saved_ds)
mov %es, REF(saved_es)
mov %fs, REF(saved_fs)
mov %gs, REF(saved_gs)
mov %ss, REF(saved_ss)
sgdt REF(saved_gdt)
sidt REF(saved_idt)
sldt REF(saved_ldt)
mov %cr0, GREG(ax)
mov GREG(ax), REF(saved_cr0)
mov %cr3, GREG(ax)
mov GREG(ax), REF(saved_cr3)
call save_rest_processor_state
#if defined(__x86_64__)
mov $3, %rdi
xor %eax, %eax
#else /* !defined(__x86_64__) */
push $3
#endif
/* enter sleep state physically */
call acpi_enter_sleep_state
jmp __ret_point
.align 16
.globl __ret_point
__ret_point:
/* mmu_cr4_features contains latest cr4 setting */
mov REF(mmu_cr4_features), GREG(ax)
mov GREG(ax), %cr4
mov REF(saved_cr3), GREG(ax)
mov GREG(ax), %cr3
mov REF(saved_cr0), GREG(ax)
mov GREG(ax), %cr0
lgdt REF(saved_gdt)
lidt REF(saved_idt)
lldt REF(saved_ldt)
mov REF(saved_ss), %ss
LOAD_GREG(sp)
#if defined(__x86_64__)
mov REF(saved_cr8), %rax
mov %rax, %cr8
pushq SAVED_GREG(flags)
popfq
/* Idle vcpu doesn't need segment selectors reload, since
* those may contain stale value from other domains and
* reload may result page fault due to no matched gdt entry
*/
mov $(STACK_SIZE - 8), %rax
or %rsp, %rax
and $~7, %rax
mov (%rax), %rax
mov 0x10(%rax), %rax
cmpw $0x7fff, (%rax)
je 1f
/* These selectors are from guest, and thus need reload */
mov REF(saved_ds), %ds
mov REF(saved_es), %es
mov REF(saved_fs), %fs
/* gs load is special */
mov REF(saved_gs), %rsi
mov $3, %rdi # SEGBASE_GS_USER_SEL
call do_set_segment_base
1:
# MSR restore
WRMSR(MSR_FS_BASE, saved_fs_base)
WRMSR(MSR_GS_BASE, saved_gs_base)
WRMSR(MSR_SHADOW_GS_BASE, saved_kernel_gs_base)
#else /* !defined(__x86_64__) */
pushl SAVED_GREG(flags)
popfl
/* No reload to fs/gs, which is saved in bottom stack already */
mov REF(saved_ds), %ds
mov REF(saved_es), %es
#endif
call restore_rest_processor_state
LOAD_GREG(bp)
LOAD_GREG(ax)
LOAD_GREG(bx)
LOAD_GREG(cx)
LOAD_GREG(dx)
LOAD_GREG(si)
LOAD_GREG(di)
#if defined(__x86_64__)
LOAD_GREG(8) # save r8...r15
LOAD_GREG(9)
LOAD_GREG(10)
LOAD_GREG(11)
LOAD_GREG(12)
LOAD_GREG(13)
LOAD_GREG(14)
LOAD_GREG(15)
#endif
ret
.data
.align 16
saved_ds: .word 0
saved_es: .word 0
saved_ss: .word 0
saved_gs: .word 0
saved_fs: .word 0
.align 4
.globl saved_magic
saved_magic: .long 0x9abcdef0
.align 8
DECLARE_GREG(sp)
DECLARE_GREG(bp)
DECLARE_GREG(ax)
DECLARE_GREG(bx)
DECLARE_GREG(cx)
DECLARE_GREG(dx)
DECLARE_GREG(si)
DECLARE_GREG(di)
DECLARE_GREG(flags)
#if defined(__x86_64__)
DECLARE_GREG(8)
DECLARE_GREG(9)
DECLARE_GREG(10)
DECLARE_GREG(11)
DECLARE_GREG(12)
DECLARE_GREG(13)
DECLARE_GREG(14)
DECLARE_GREG(15)
saved_gdt: .quad 0,0
saved_idt: .quad 0,0
saved_ldt: .quad 0,0
saved_cr0: .quad 0
saved_cr3: .quad 0
saved_cr8: .quad 0
saved_gs_base: .quad 0
saved_fs_base: .quad 0
saved_kernel_gs_base: .quad 0
#else /* !defined(__x86_64__) */
saved_gdt: .long 0,0
saved_idt: .long 0,0
saved_ldt: .long 0
saved_cr0: .long 0
saved_cr3: .long 0
#endif
+2 -1
View File
@@ -1,3 +1,4 @@
obj-y += head.o
head.o: head.S $(TARGET_SUBARCH).S trampoline.S mem.S video.S cmdline.S edd.S
head.o: head.S $(TARGET_SUBARCH).S trampoline.S mem.S video.S \
cmdline.S edd.S wakeup.S
+2
View File
@@ -175,9 +175,11 @@ __start:
#include "cmdline.S"
.align 16
.globl trampoline_start, trampoline_end
trampoline_start:
#include "trampoline.S"
#include "wakeup.S"
trampoline_end:
.text
+212
View File
@@ -0,0 +1,212 @@
.code16
#undef wakesym
/* Used in real mode, to cal offset in current segment */
#define wakesym(sym) (sym - wakeup_start)
ENTRY(wakeup_start)
wakeup_code_start = .
cli
cld
# setup data segment
movw %cs, %ax
movw %ax, %ds
movw %ax, %ss # A stack required for BIOS call
movw $wakesym(wakeup_stack), %sp
pushl $0 # Kill dangerous flag early
popfl
# check magic number
movl wakesym(real_magic), %eax
cmpl $0x12345678, %eax
jne bogus_real_magic
# for acpi_sleep=s3_bios
testl $1, wakesym(video_flags)
jz 1f
lcall $0xc000, $3
movw %cs, %ax # In case messed by BIOS
movw %ax, %ds
movw %ax, %ss # Need this? How to ret if clobbered?
1: # for acpi_sleep=s3_mode
testl $2, wakesym(video_flags)
jz 1f
movl wakesym(video_mode), %eax
call mode_setw
1: # Show some progress if VGA is resumed
movw $0xb800, %ax
movw %ax, %fs
movw $0x0e00 + 'L', %fs:(0x10)
# boot trampoline is under 1M, and shift its start into
# %fs to reference symbols in that area
movl $BOOT_TRAMPOLINE, %eax
shrl $4, %eax
movl %eax, %fs
lidt %fs:bootsym(idt_48)
lgdt %fs:bootsym(gdt_48)
movw $1, %ax
lmsw %ax # Turn on CR0.PE
jmp 1f
1: ljmpl $BOOT_CS32, $bootsym_phys(wakeup_32)
/* This code uses an extended set of video mode numbers. These include:
* Aliases for standard modes
* NORMAL_VGA (-1)
* EXTENDED_VGA (-2)
* ASK_VGA (-3)
* Video modes numbered by menu position -- NOT RECOMMENDED because of lack
* of compatibility when extending the table. These are between 0x00 and 0xff.
*/
#define VIDEO_FIRST_MENU 0x0000
/* Standard BIOS video modes (BIOS number + 0x0100) */
#define VIDEO_FIRST_BIOS 0x0100
/* VESA BIOS video modes (VESA number + 0x0200) */
#define VIDEO_FIRST_VESA 0x0200
/* Video7 special modes (BIOS number + 0x0900) */
#define VIDEO_FIRST_V7 0x0900
# Setting of user mode (AX=mode ID) => CF=success
mode_setw:
movw %ax, %bx
cmpb $VIDEO_FIRST_VESA>>8, %ah
jnc check_vesaw
decb %ah
setbadw: clc
ret
check_vesaw:
subb $VIDEO_FIRST_VESA>>8, %bh
orw $0x4000, %bx # Use linear frame buffer
movw $0x4f02, %ax # VESA BIOS mode set call
int $0x10
cmpw $0x004f, %ax # AL=4f if implemented
jnz _setbadw # AH=0 if OK
stc
ret
_setbadw: jmp setbadw
bogus_real_magic:
movw $0x0e00 + 'B', %fs:(0x12)
jmp bogus_real_magic
.align 4
real_magic: .long 0x12345678
.globl video_mode, video_flags
video_mode: .long 0
video_flags: .long 0
.code32
# Now in protect mode, with paging disabled
# Add offset for any reference to xen specific symbols
wakeup_32:
mov $BOOT_DS, %eax
mov %eax, %ds
mov %eax, %ss
mov $bootsym_phys(wakeup_stack), %esp
# check saved magic again
mov $sym_phys(saved_magic), %eax
add bootsym_phys(trampoline_xen_phys_start), %eax
mov (%eax), %eax
cmp $0x9abcdef0, %eax
jne bogus_saved_magic
/* fpu init? */
/* Initialise CR4. */
#if CONFIG_PAGING_LEVELS == 2
mov $X86_CR4_PSE, %ecx
#else
mov $X86_CR4_PAE, %ecx
#endif
mov %ecx, %cr4
/* Load pagetable base register */
mov $sym_phys(idle_pg_table),%eax
add bootsym_phys(trampoline_xen_phys_start),%eax
mov %eax,%cr3
/* Will cpuid feature change after resume? */
#if CONFIG_PAGING_LEVELS != 2
/* Set up EFER (Extended Feature Enable Register). */
mov bootsym_phys(cpuid_ext_features),%edi
test $0x20100800,%edi /* SYSCALL/SYSRET, No Execute, Long Mode? */
jz .Lskip_eferw
movl $MSR_EFER,%ecx
rdmsr
#if CONFIG_PAGING_LEVELS == 4
btsl $_EFER_LME,%eax /* Long Mode */
btsl $_EFER_SCE,%eax /* SYSCALL/SYSRET */
#endif
btl $20,%edi /* No Execute? */
jnc 1f
btsl $_EFER_NX,%eax /* No Execute */
1: wrmsr
.Lskip_eferw:
#endif
wbinvd
mov $0x80050033,%eax /* hi-to-lo: PG,AM,WP,NE,ET,MP,PE */
mov %eax,%cr0
jmp 1f
1:
#if defined(__x86_64__)
/* Now in compatibility mode. Long-jump to 64-bit mode */
ljmp $BOOT_CS64, $bootsym_phys(wakeup_64)
.code64
.align 8
.word 0,0,0
lgdt_descr:
.word LAST_RESERVED_GDT_BYTE
.quad gdt_table - FIRST_RESERVED_GDT_BYTE
wakeup_64:
lgdt lgdt_descr(%rip)
mov $(__HYPERVISOR_DS64), %eax
mov %eax, %ds
# long jump to return point, with cs reload
rex64 ljmp *ret_point(%rip)
.align 8
ret_point:
.quad __ret_point
.word __HYPERVISOR_CS64
#else /* !defined(__x86_64__) */
lgdt gdt_descr
mov $(__HYPERVISOR_DS), %eax
mov %eax, %ds
ljmp $(__HYPERVISOR_CS), $__ret_point
#endif
bogus_saved_magic:
movw $0x0e00 + 'S', 0xb8014
jmp bogus_saved_magic
.align 16
wakeup_stack_begin: # Stack grows down
.fill PAGE_SIZE,1,0
wakeup_stack: # Just below end of first page in this section
ENTRY(wakeup_end)
-1
View File
@@ -184,7 +184,6 @@ static __init int broken_toshiba_keyboard(struct dmi_blacklist *d)
static __init int reset_videomode_after_s3(struct dmi_blacklist *d)
{
/* See acpi_wakeup.S */
extern long acpi_video_flags;
acpi_video_flags |= 2;
return 0;
}
+17
View File
@@ -18,6 +18,7 @@
#include <xen/console.h>
#include <xen/iocap.h>
#include <xen/guest_access.h>
#include <xen/acpi.h>
#include <asm/current.h>
#include <public/platform.h>
#include <asm/edd.h>
@@ -247,6 +248,22 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
}
break;
#if 0
case XENPF_set_acpi_sleep:
{
ret = set_acpi_sleep_info(&op->u.set_acpi_sleep);
if (!ret && copy_to_guest(u_xenpf_op, op, 1))
ret = -EFAULT;
}
break;
case XENPF_enter_acpi_sleep:
{
ret = acpi_enter_sleep(&op->u.enter_acpi_sleep);
}
break;
#endif
default:
ret = -ENOSYS;
break;
+8
View File
@@ -173,6 +173,14 @@ extern unsigned long acpi_wakeup_address;
/* early initialization routine */
extern void acpi_reserve_bootmem(void);
extern unsigned long acpi_video_flags;
extern unsigned long saved_videomode;
struct xenpf_set_acpi_sleep;
struct xenpf_enter_acpi_sleep;
extern int set_acpi_sleep_info(struct xenpf_set_acpi_sleep *info);
extern int acpi_enter_sleep(struct xenpf_enter_acpi_sleep *sleep);
extern int acpi_enter_state(u32 state);
#endif /*CONFIG_ACPI_SLEEP*/
extern u8 x86_acpiid_to_apicid[];
+5 -2
View File
@@ -25,9 +25,7 @@
#define CONFIG_X86_PM_TIMER 1
#define CONFIG_HPET_TIMER 1
#define CONFIG_X86_MCE_P4THERMAL 1
#define CONFIG_ACPI_NUMA 1
#define CONFIG_NUMA 1
#define CONFIG_ACPI_SRAT 1
#define CONFIG_DISCONTIGMEM 1
#define CONFIG_NUMA_EMU 1
@@ -36,6 +34,9 @@
#define CONFIG_ACPI 1
#define CONFIG_ACPI_BOOT 1
#define CONFIG_ACPI_SLEEP 1
#define CONFIG_ACPI_NUMA 1
#define CONFIG_ACPI_SRAT 1
#define CONFIG_VGA 1
@@ -100,6 +101,8 @@ extern char trampoline_start[], trampoline_end[];
extern char trampoline_realmode_entry[];
extern unsigned int trampoline_xen_phys_start;
extern unsigned char trampoline_cpu_started;
extern char wakeup_start[];
extern unsigned int video_mode, video_flags;
#endif
#if defined(__x86_64__)
+27
View File
@@ -153,6 +153,31 @@ struct xenpf_firmware_info {
typedef struct xenpf_firmware_info xenpf_firmware_info_t;
DEFINE_XEN_GUEST_HANDLE(xenpf_firmware_info_t);
#define XENPF_set_acpi_sleep 51
struct xenpf_set_acpi_sleep {
/* IN variables. */
uint16_t pm1a_cnt_port;
uint16_t pm1b_cnt_port;
uint16_t pm1a_evt_port;
uint16_t pm1b_evt_port;
/* OUT variables */
uint64_t xen_waking_vec; /* Tell dom0 to set FACS waking vector */
};
typedef struct xenpf_set_acpi_sleep xenpf_set_acpi_sleep_t;
DEFINE_XEN_GUEST_HANDLE(xenpf_set_acpi_sleep_t);
#define XENPF_enter_acpi_sleep 52
struct xenpf_enter_acpi_sleep {
/* IN variables */
uint16_t pm1a_cnt_val;
uint16_t pm1b_cnt_val;
uint32_t sleep_state; /* Which state to enter */
uint32_t video_flags; /* S3_bios or s3_mode */
uint32_t video_mode; /* Mode setting for s3_mode */
};
typedef struct xenpf_enter_acpi_sleep xenpf_enter_acpi_sleep_t;
DEFINE_XEN_GUEST_HANDLE(xenpf_enter_acpi_sleep_t);
struct xen_platform_op {
uint32_t cmd;
uint32_t interface_version; /* XENPF_INTERFACE_VERSION */
@@ -164,6 +189,8 @@ struct xen_platform_op {
struct xenpf_microcode_update microcode;
struct xenpf_platform_quirk platform_quirk;
struct xenpf_firmware_info firmware_info;
struct xenpf_set_acpi_sleep set_acpi_sleep;
struct xenpf_enter_acpi_sleep enter_acpi_sleep;
uint8_t pad[128];
} u;
};
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.