1.. _system-timer-hld:
2
3System Timer Virtualization
4###########################
5
6ACRN supports RTC (Real-time clock), HPET (High Precision Event Timer),
7and PIT (Programmable interval timer) devices for the VM system timer.
8Different timer devices support different resolutions. The HPET device can
9support higher resolutions than RTC and PIT.
10
11System timer virtualization architecture
12
13|image0|
14
15-  In the User VM, vRTC, vHPET, and vPIT are used by the clock event module and the clock
16   source module in the kernel space.
17
18-  In the Service VM, the Device Model creates all vRTC, vHPET, and vPIT devices
19   in the initialization phase. The Device Model uses timer\_create and
20   timerfd\_create interfaces to set up native timers for the trigger timeout
21   mechanism.
22
23System Timer Initialization
24===========================
25
26The Device Model initializes vRTC, vHEPT, and vPIT devices automatically when
27it starts the booting initialization. The initialization
28flow goes from vrtc\_init to vpit\_init and ends with vhept\_init. See
29the code snippets below.::
30
31	static int
32	vm_init_vdevs(struct vmctx ctx)*
33	{
34		int ret;
35		...
36
37		ret = vrtc_init(ctx);
38		if (ret < 0)
39			goto vrtc_fail;
40
41		ret = vpit_init(ctx);
42		if (ret < 0)
43			goto vpit_fail;
44
45		ret = vhpet_init(ctx);
46		if (ret < 0)
47			goto vhpet_fail;
48		...
49	}
50
51PIT Emulation
52=============
53
54The ACRN emulated Intel 8253 Programmable Interval Timer includes a chip
55that has three
56independent 16-bit down counters that can be read on the fly. There are
57three mode registers and three countdown registers. The countdown
58registers are addressed directly, via the first three I/O ports.The
59three mode registers are accessed via the fourth I/O port, with two bits
60in the mode byte indicating the register.
61
62I/O ports definition::
63
64	#define IO_TIMER1_PORT 0x40 /* 8253 Timer #1 */
65	#define NMISC_PORT 0x61
66	#define TIMER_REG_CNTR0 0 /* timer 0 counter port */
67	#define TIMER_REG_CNTR1 1 /* timer 1 counter port */
68	#define TIMER_REG_CNTR2 2 /* timer 2 counter port */
69	#define TIMER_REG_MODE 3 /* timer mode port */
70
71	/*
72	 * The outputs of the three timers are connected as follows:
73	 *
74	 * timer 0 -> irq 0
75	 * timer 1 -> dma chan 0 (for dram refresh)
76	 * timer 2 -> speaker (via keyboard controller)
77	 *
78	 * Timer 0 is used to call hard clock.
79	 * Timer 2 is used to generate console beeps.
80	 */
81	#define TIMER_CNTR0 (IO_TIMER1_PORT + TIMER_REG_CNTR0)
82	#define TIMER_CNTR1 (IO_TIMER1_PORT + TIMER_REG_CNTR1)
83	#define TIMER_CNTR2 (IO_TIMER1_PORT + TIMER_REG_CNTR2)
84	#define TIMER_MODE (IO_TIMER1_PORT + TIMER_REG_MODE)
85
86RTC Emulation
87=============
88
89ACRN supports RTC (real-time clock) that can only be accessed through
90I/O ports (0x70 and 0x71).
91
920x70 is used to access CMOS address register and 0x71 is used to access
93CMOS data register; the user needs to set the CMOS address register and then
94the read/write CMOS data register for CMOS accessing.
95
96The RTC ACPI description as below::
97
98	#define IO_RTC 0x070 /* RTC */
99
100	static void
101	rtc_dsdt(void)
102	{
103		dsdt_line("");
104		dsdt_line("Device (RTC)");
105		dsdt_line("{");
106		dsdt_line(" Name (\_HID, EisaId (\\"PNP0B00\\"))");
107		dsdt_line(" Name (\_CRS, ResourceTemplate ()");
108		dsdt_line(" {");
109		dsdt_indent(2);
110		dsdt_fixed_ioport(IO_RTC, 2);
111		dsdt_fixed_irq(8);
112		dsdt_unindent(2);
113		dsdt_line(" })");
114		dsdt_line("}");
115	}
116
117HPET Emulation
118==============
119
120ACRN supports HPET (High Precision Event Timer) which is a higher resolution
121timer than RTC and PIT. Its frequency is 16.7Mhz and uses MMIO to
122access HPET device; the base address is 0xfed00000 and size is 1024
123bytes. Access to the HPET should be 4 or 8 bytes wide.::
124
125	#define HPET_FREQ (16777216) /* 16.7 (2^24) Mhz */
126	#define VHPET_BASE (0xfed00000)
127	#define VHPET_SIZE (1024)
128
129HPET registers definition::
130
131	/* General registers */
132	#define HPET_CAPABILITIES 0x0 /* General capabilities and ID register */
133	#define HPET_CAP_VENDOR_ID 0xffff0000
134	#define HPET_CAP_LEG_RT 0x00008000
135	#define HPET_CAP_COUNT_SIZE 0x00002000 /* 1 = 64-bit, 0 = 32-bit */
136	#define HPET_CAP_NUM_TIM 0x00001f00
137	#define HPET_CAP_REV_ID 0x000000ff
138	#define HPET_PERIOD 0x4 /* Period (1/hz) of timer */
139	#define HPET_CONFIG 0x10 /* General configuration register */
140	#define HPET_CNF_LEG_RT 0x00000002
141	#define HPET_CNF_ENABLE 0x00000001
142	#define HPET_ISR 0x20 /* General interrupt status register */
143	#define HPET_MAIN_COUNTER 0xf0 /* Main counter register */
144
145	/* Timer registers */
146	#define HPET_TIMER_CAP_CNF(x) ((x) * 0x20 + 0x100)
147	#define HPET_TCAP_INT_ROUTE 0xffffffff00000000
148	#define HPET_TCAP_FSB_INT_DEL 0x00008000
149	#define HPET_TCNF_FSB_EN 0x00004000
150	#define HPET_TCNF_INT_ROUTE 0x00003e00
151	#define HPET_TCNF_32MODE 0x00000100
152	#define HPET_TCNF_VAL_SET 0x00000040
153	#define HPET_TCAP_SIZE 0x00000020 /* 1 = 64-bit, 0 = 32-bit */
154	#define HPET_TCAP_PER_INT 0x00000010 /* Supports periodic interrupts */
155	#define HPET_TCNF_TYPE 0x00000008 /* 1 = periodic, 0 = one-shot */
156	#define HPET_TCNF_INT_ENB 0x00000004
157	#define HPET_TCNF_INT_TYPE 0x00000002 /* 1 = level triggered, 0 = edge */
158	#define HPET_TIMER_COMPARATOR(x) ((x) * 0x20 + 0x108)
159	#define HPET_TIMER_FSB_VAL(x) ((x) * 0x20 + 0x110)
160	#define HPET_TIMER_FSB_ADDR(x) ((x) * 0x20 + 0x114)
161
162ACPI device description::
163
164	static int
165	basl\_fwrite\_hpet(FILE \*fp, struct vmctx \*ctx)
166	{
167		EFPRINTF(fp, "/\*\\n");
168		EFPRINTF(fp, " \* dm HPET template\\n");
169		EFPRINTF(fp, " \*/\\n");
170		EFPRINTF(fp, "[0004]\\t\\tSignature : \\"HPET\\"\\n");
171		EFPRINTF(fp, "[0004]\\t\\tTable Length : 00000000\\n");
172		EFPRINTF(fp, "[0001]\\t\\tRevision : 01\\n");
173		EFPRINTF(fp, "[0001]\\t\\tChecksum : 00\\n");
174		EFPRINTF(fp, "[0006]\\t\\tOem ID : \\"DM \\"\\n");
175		EFPRINTF(fp, "[0008]\\t\\tOem Table ID : \\"DMHPET \\"\\n");
176		EFPRINTF(fp, "[0004]\\t\\tOem Revision : 00000001\\n");
177
178		/* iasl will fill in the compiler ID/revision fields */
179		EFPRINTF(fp, "[0004]\\t\\tAsl Compiler ID : \\"xxxx\\"\\n");
180		EFPRINTF(fp, "[0004]\\t\\tAsl Compiler Revision : 00000000\\n");
181		EFPRINTF(fp, "\\n");
182		EFPRINTF(fp, "[0004]\\t\\tTimer Block ID : %08X\\n", (uint32\_t)vhpet_capabilities());*
183		EFPRINTF(fp, "[0012]\\t\\tTimer Block Register : [Generic Address Structure]\\n");
184		EFPRINTF(fp, "[0001]\\t\\tSpace ID : 00 [SystemMemory]\\n");*
185		EFPRINTF(fp, "[0001]\\t\\tBit Width : 00\\n");*
186		EFPRINTF(fp, "[0001]\\t\\tBit Offset : 00\\n");*
187		EFPRINTF(fp, "[0001]\\t\\tEncoded Access Width : 00 [Undefined/Legacy]\\n");
188		EFPRINTF(fp, "[0008]\\t\\tAddress : %016X\\n", VHPET_BASE);
189		EFPRINTF(fp, "\\n");
190		EFPRINTF(fp, "[0001]\\t\\tHPET Number : 00\\n");
191		EFPRINTF(fp, "[0002]\\t\\tMinimum Clock Ticks : 0000\\n");
192		EFPRINTF(fp, "[0004]\\t\\tFlags (decoded below) : 00000001\\n");
193		EFPRINTF(fp, "\\t\\t\\t4K Page Protect : 1\\n");
194		EFPRINTF(fp, "\\t\\t\\t64K Page Protect : 0\\n");
195		EFPRINTF(fp, "\\n");
196		EFFLUSH(fp);
197		return 0;
198	}
199
200.. |image0| image:: ./images/hld-dm-timer-image1.png
201   :width: 8.00000in
202   :height: 4.63887in
203