xref: /kvm-unit-tests/x86/s3.c (revision e526bc786e9878c3880ae4b09b01a4572756e492)
1c1bc863aSGleb Natapov #include "libcflat.h"
2670b1f54SNikos Nikoleris #include "acpi.h"
347546cc7SPaolo Bonzini #include "asm/io.h"
4c1bc863aSGleb Natapov 
5798b0d95SPaolo Bonzini #define RTC_SECONDS_ALARM       1
6798b0d95SPaolo Bonzini #define RTC_MINUTES_ALARM       3
7798b0d95SPaolo Bonzini #define RTC_HOURS_ALARM         5
8798b0d95SPaolo Bonzini #define RTC_ALARM_DONT_CARE     0xC0
9798b0d95SPaolo Bonzini 
10798b0d95SPaolo Bonzini #define RTC_REG_A               10
11798b0d95SPaolo Bonzini #define RTC_REG_B               11
12798b0d95SPaolo Bonzini #define RTC_REG_C               12
13798b0d95SPaolo Bonzini 
14798b0d95SPaolo Bonzini #define REG_A_UIP               0x80
15798b0d95SPaolo Bonzini #define REG_B_AIE               0x20
16798b0d95SPaolo Bonzini 
rtc_in(u8 reg)17798b0d95SPaolo Bonzini static inline int rtc_in(u8 reg)
18798b0d95SPaolo Bonzini {
1947546cc7SPaolo Bonzini     outb(reg, 0x70);
2047546cc7SPaolo Bonzini     return inb(0x71);
21798b0d95SPaolo Bonzini }
22798b0d95SPaolo Bonzini 
rtc_out(u8 reg,u8 val)23798b0d95SPaolo Bonzini static inline void rtc_out(u8 reg, u8 val)
24798b0d95SPaolo Bonzini {
2547546cc7SPaolo Bonzini     outb(reg, 0x70);
2647546cc7SPaolo Bonzini     outb(val, 0x71);
27798b0d95SPaolo Bonzini }
28798b0d95SPaolo Bonzini 
29c1bc863aSGleb Natapov extern char resume_start, resume_end;
30c1bc863aSGleb Natapov 
main(int argc,char ** argv)31c1bc863aSGleb Natapov int main(int argc, char **argv)
32c1bc863aSGleb Natapov {
3310cda508SNikos Nikoleris 	struct acpi_table_facs_rev1 *facs = find_acpi_table_addr(FACS_SIGNATURE);
34*64cd0cc1SNikos Nikoleris 	struct acpi_table_fadt *fadt = find_acpi_table_addr(FACP_SIGNATURE);
35c1bc863aSGleb Natapov 	char *addr, *resume_vec = (void*)0x1000;
36c1bc863aSGleb Natapov 
3710cda508SNikos Nikoleris 	assert(facs);
3810cda508SNikos Nikoleris 	facs->firmware_waking_vector = (u32)(ulong)resume_vec;
39c1bc863aSGleb Natapov 
4010cda508SNikos Nikoleris 	printf("FACS is at %p\n", facs);
4110cda508SNikos Nikoleris 	printf("resume vector addr is %p\n", &facs->firmware_waking_vector);
42c1bc863aSGleb Natapov 	for (addr = &resume_start; addr < &resume_end; addr++)
43c1bc863aSGleb Natapov 		*resume_vec++ = *addr;
44b006d7ebSAndrew Jones 	printf("copy resume code from %p\n", &resume_start);
45798b0d95SPaolo Bonzini 
46d26193a0SRoman Bolshakov 	printf("PM1a event registers at %" PRIx32 "\n", fadt->pm1a_evt_blk);
4747546cc7SPaolo Bonzini 	outw(0x400, fadt->pm1a_evt_blk + 2);
4847546cc7SPaolo Bonzini 
49798b0d95SPaolo Bonzini 	/* Setup RTC alarm to wake up on the next second.  */
50798b0d95SPaolo Bonzini 	while ((rtc_in(RTC_REG_A) & REG_A_UIP) == 0);
51798b0d95SPaolo Bonzini 	while ((rtc_in(RTC_REG_A) & REG_A_UIP) != 0);
52798b0d95SPaolo Bonzini 	rtc_in(RTC_REG_C);
53798b0d95SPaolo Bonzini 	rtc_out(RTC_SECONDS_ALARM, RTC_ALARM_DONT_CARE);
54798b0d95SPaolo Bonzini 	rtc_out(RTC_MINUTES_ALARM, RTC_ALARM_DONT_CARE);
55798b0d95SPaolo Bonzini 	rtc_out(RTC_HOURS_ALARM, RTC_ALARM_DONT_CARE);
56798b0d95SPaolo Bonzini 	rtc_out(RTC_REG_B, rtc_in(RTC_REG_B) | REG_B_AIE);
57798b0d95SPaolo Bonzini 
58c1bc863aSGleb Natapov 	*(volatile int*)0 = 0;
59a5d12b9fSPaolo Bonzini 	asm volatile("outw %0, %1" :: "a"((short)0x2400), "d"((short)fadt->pm1a_cnt_blk):"memory");
60c1bc863aSGleb Natapov 	while(1)
61c1bc863aSGleb Natapov 		*(volatile int*)0 = 1;
62c1bc863aSGleb Natapov 
63c1bc863aSGleb Natapov 	return 0;
64c1bc863aSGleb Natapov }
65c1bc863aSGleb Natapov 
66c1bc863aSGleb Natapov asm (
67c1bc863aSGleb Natapov         ".global resume_start\n"
68c1bc863aSGleb Natapov 	".global resume_end\n"
69c1bc863aSGleb Natapov 	".code16\n"
70c1bc863aSGleb Natapov 	"resume_start:\n"
71c1bc863aSGleb Natapov 	"mov 0x0, %eax\n"
72c1bc863aSGleb Natapov 	"mov $0xf4, %dx\n"
73c1bc863aSGleb Natapov 	"out %eax, %dx\n"
74c1bc863aSGleb Natapov 	"1: hlt\n"
75c1bc863aSGleb Natapov 	"jmp 1b\n"
76c1bc863aSGleb Natapov 	"resume_end:\n"
77c1bc863aSGleb Natapov #ifdef __i386__
78c1bc863aSGleb Natapov 	".code32\n"
79c1bc863aSGleb Natapov #else
80c1bc863aSGleb Natapov 	".code64\n"
81c1bc863aSGleb Natapov #endif
82c1bc863aSGleb Natapov     );
83