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