3 * HPET as an inmate for Jailhouse
11 * Definitions for ACPI
25 } __attribute__((packed));
37 } __attribute__((packed));
45 /* XXX Hardcode PCI device scope: path = (device, function) */
48 } __attribute__((packed));
53 SCOPE_PCI_ENDPOINT = 1,
65 /* If we include more than RMRRs here, we need to fix the DMAR
66 duplication code in zapp.c */
72 struct device_scope first_scope;
75 } __attribute__((packed));
78 struct acpi_table generic;
82 struct dmar_entry first_entry;
85 char acpi_checksum(const char *table, unsigned long count);
86 void acpi_fix_checksum(struct acpi_table *tab);
88 struct rsdp *acpi_get_rsdp(void);
89 struct acpi_table **acpi_get_table_ptr(struct acpi_table *rsdt, const char signature[4]);
91 static inline struct dmar_entry *acpi_dmar_next(struct dmar_entry *cur)
92 { return (struct dmar_entry *)((char *)cur + cur->size); }
94 static inline bool acpi_in_table(struct acpi_table *tab, const void *p)
95 { return ((unsigned int *)tab + tab->size) > (unsigned int *)p; }
97 typedef void *(*memory_alloc_t)(unsigned long len, unsigned align);
99 struct acpi_table *acpi_dup_table(struct acpi_table *rsdt, const char signature[4],
100 memory_alloc_t alloc);
102 /* ACPI code inspired by Vancouver. */
105 * @brief memory compare
106 * @details [long description]
108 * @param s1 [description]
109 * @param s2 [description]
110 * @param n [description]
112 typedef unsigned long size_t;
113 static int memcmp(const void *s1, const void *s2, size_t n)
118 while (n-- && (res == 0)) {
119 res = *(p1++) - *(p2++);
126 * Calculate the ACPI checksum of a table.
128 char acpi_checksum(const char *table, unsigned long count)
131 while (count--) res += *(table++);
135 void acpi_fix_checksum(struct acpi_table *tab)
137 tab->checksum -= acpi_checksum((const char *)tab, tab->size);
143 struct rsdp *acpi_get_rsdp(void)
146 struct rsdp *ret = 0;
148 void check(char *p) {
149 if ((memcmp(p, "RSD PTR ", 8) == 0) &&
150 (acpi_checksum(p, 20) == 0)) {
151 //ret = (char *)(((u32 *)p)[4]);
152 ret = (struct rsdp *)p;
157 void find(unsigned int * start, unsigned long len) {
159 for (cur = start; cur < start + len; cur += 16)//was 16
163 find( (unsigned int *) 0x40e, 0x400); /* BDA */
164 find( (unsigned int *) 0xe0000, 0x2000); /* BIOS read-only memory */
170 struct acpi_table **acpi_get_table_ptr(struct acpi_table *rsdt, const char signature[4])
173 for (cur = (const char*)rsdt + sizeof(struct acpi_table);
174 acpi_in_table(rsdt, cur);
175 cur += sizeof(unsigned int *)) {
176 struct acpi_table *entry = *(struct acpi_table **)cur;
177 if (acpi_checksum((const char *)entry, entry->size) != 0)
179 if (memcmp(signature, entry->signature, sizeof(signature)) == 0)
180 return (struct acpi_table **)cur;
186 /** Duplicate an ACPI table. */
187 struct acpi_table *acpi_dup_table(struct acpi_table *rsdt, const char signature[4],
188 memory_alloc_t alloc)
190 struct acpi_table **tab = acpi_get_table_ptr(rsdt, signature);
191 struct acpi_table *newtab = alloc((*tab)->size, 0x1000); /* 4K aligned */
192 memcpy(newtab, *tab, (*tab)->size);
194 acpi_fix_checksum(rsdt);
201 struct address_structure
203 u8 address_space_id; // 0 - system memory, 1 - system I/O
204 u8 register_bit_width;
205 u8 register_bit_offset;
208 } __attribute__((packed));
210 typedef struct hpet_description_table_header
212 struct acpi_table table_header;
215 u8 comparator_count : 5;
218 u8 legacy_replacement : 1;
221 struct address_structure address_st;
226 } __attribute__((packed)) acpi_hpet_tbl;
229 * This was taken from IA-PC HPET Specification
231 *----------------------------------------------------------------------------------------
232 * Offset |Register |Type
233 *----------------------------------------------------------------------------------------
234 * 000- 007h General Capabilities and ID Register Read Only
236 * 010- 017h General Configuration Register Read-Write
238 * 020- 027h General Interrupt Status Register Read/Write Clear
240 * 0F0- 0F7h Main Counter Value Register Read/Write
242 * 100- 107h Timer 0 Configuration and Capability Register Read/Write
243 * 108- 10Fh Timer 0 Comparator Value Register Read/Write
244 * 110- 117h Timer 0 FSB Interrupt Route Register Read/Write
247 *(100+20*N )- (100+20*N+7)h Timer N Configuration and Capability Register Read/Write
248 *(100+20*N+8)- (100+20*N+F)h Timer N Comparator Value Register Read/Write
249 *(100+30*N )- (100+30*N+7)h Timer N FSB Interrupt Route Register Read/Write
250 *(100+30*N+8)- (100+30*N+F)h Reserved
252 * -3FF ----for Timers 3-31
256 * HPET general capabilities register
259 #define HPET_COUNTER_CLK_PERIOD_MASK (0xffffffff00000000ULL)
260 #define HPET_COUNTER_CLK_PERIOD_SHIFT (32UL)
261 #define HPET_VENDOR_ID_MASK (0x00000000ffff0000ULL)
262 #define HPET_VENDOR_ID_SHIFT (16ULL)
263 #define HPET_LEG_RT_CAP_MASK (0x8000)
264 #define HPET_COUNTER_SIZE_MASK (0x2000)
265 #define HPET_NUM_TIM_CAP_MASK (0x1f00)
266 #define HPET_NUM_TIM_CAP_SHIFT (8ULL)
269 * HPET general configuration register
272 #define HPET_LEG_RT_CNF_MASK (2UL)
273 #define HPET_ENABLE_CNF_MASK (1UL)
275 typedef struct general_timer_registers
280 // /*8:12 - Number of timers, 13 - count_size_cap,
281 // 14 - reserved, 15 -legacy repl route hw support */
282 // u8 num_tim_cap : 5;
283 // u8 count_size_cap : 1;
284 // u8 reserved_bit : 1;
285 // u8 leg_rt_cap : 1;
291 /*0 - ENABLE_CNF, 1 - LEG_RT_CNF, 2:63 - reserved*/
294 u8 reserved_5bit : 6;
296 u64 reserved_48bit : 48;*/
298 u32 reservedforfuture;
301 //u64 int_status_register
302 /*when level-triggered mode is used
303 each bit in the vector shows if the Timer N interrupt is ACTIVE.*/;
304 u32 int_status_vector;
306 } __attribute__((packed)) gen_regs;
308 /* 028h -> 0EFh space -- (0F0h - 28 == C8) */
309 #define RESERVED_BEFORE_MAIN_VAL_REG 0x000000C8
310 typedef struct main_counter_value_register
314 } __attribute__((packed)) main_val_reg;
317 * Timer configuration register
320 #define Tn_INT_ROUTE_CAP_MASK (0xffffffff00000000ULL)
321 #define Tn_INT_ROUTE_CAP_SHIFT (32UL)
322 #define Tn_FSB_INT_DELCAP_MASK (0x8000UL)
323 #define Tn_FSB_INT_DELCAP_SHIFT (15)
324 #define Tn_FSB_EN_CNF_MASK (0x4000UL)
325 #define Tn_FSB_EN_CNF_SHIFT (14)
326 #define Tn_INT_ROUTE_CNF_MASK (0x3e00UL)
327 #define Tn_INT_ROUTE_CNF_SHIFT (9)
328 #define Tn_32MODE_CNF_MASK (0x0100UL)
329 #define Tn_VAL_SET_CNF_MASK (0x0040UL)
330 #define Tn_SIZE_CAP_MASK (0x0020UL)
331 #define Tn_PER_INT_CAP_MASK (0x0010UL)
332 #define Tn_TYPE_CNF_MASK (0x0008UL)
333 #define Tn_INT_ENB_CNF_MASK (0x0004UL)
334 #define Tn_INT_TYPE_CNF_MASK (0x0002UL)
337 * Timer FSB Interrupt Route Register
340 #define Tn_FSB_INT_ADDR_MASK (0xffffffff00000000ULL)
341 #define Tn_FSB_INT_ADDR_SHIFT (32UL)
342 #define Tn_FSB_INT_VAL_MASK (0x00000000ffffffffULL)
346 typedef struct timer_N_registers
352 u64 fsb_interrupt_route;
355 } __attribute__((packed)) timer_regs;
357 #define MAX_TIMERS_IN_BLK 32
358 #define MAX_BLK_NUM 8
359 timer_regs * timer[MAX_TIMERS_IN_BLK];
365 #include <jailhouse/hypercall.h>
366 //#include "hpet-demo.h"
368 #ifdef CONFIG_UART_OXPCIE952
369 #define UART_BASE 0xe010
371 #define UART_BASE 0x3f8
374 #define UART_LSR_THRE 0x20
375 #define UART_IDLE_LOOPS 100
377 #define APIC_TIMER_VECTOR 32
379 //-------------hpet defines-----------------------------
380 #define NANS_TO_FEMPTS(X) ((X) * 1000000ULL)
382 u64 main_counter_tick_period = 0;
383 main_val_reg * main_counter_reg;
387 static void inline enable_main_counter(void)
389 gen_reg->config_reg |= HPET_ENABLE_CNF_MASK;
392 static void inline disable_main_counter(void)
394 gen_reg->config_reg &= ~HPET_ENABLE_CNF_MASK;
397 static void set_timer_periodic(timer_regs * timer, u64 time)
399 if (! (timer->cap_conf_reg & Tn_PER_INT_CAP_MASK) ) {
400 printk("Timer %p isnt periodic capable.\n", timer );
403 if (time < main_counter_tick_period) {
404 time = main_counter_tick_period;
405 printk("Timer %p was set on minimal tick that's possible.\n", timer);
408 disable_main_counter();
409 main_counter_reg->value = 0ULL;
410 //enable int, set periodical, set value notification
411 timer->cap_conf_reg |= Tn_INT_ENB_CNF_MASK | Tn_TYPE_CNF_MASK | Tn_VAL_SET_CNF_MASK;
412 timer->comparator_val = time;
413 enable_main_counter();
416 static void set_timer_one_shot(timer_regs * timer, u64 time)
418 if (time < (u64) main_counter_tick_period) {
419 time = main_counter_tick_period;
420 printk("Timer %p was set on minimal tick that's possible.\n", timer);
423 timer->comparator_val = time + main_counter_reg->value;
424 timer->cap_conf_reg |= Tn_INT_ENB_CNF_MASK;
427 static void set_legacy_mode(void)
429 if ( !(gen_reg->capat_id_reg & HPET_LEG_RT_CAP_MASK) ) {
430 printk("Legacy replacement not implemented in HW.\n");
433 gen_reg->config_reg |= HPET_LEG_RT_CNF_MASK;
437 //------------------------------------------------------
439 static void irq_handler(void)
441 printk("\nTimer 0 says hi!\n");
444 static void init_apic(void)
446 //unsigned long apic_freq_khz;
449 int_set_handler(APIC_TIMER_VECTOR, irq_handler);
451 //apic_freq_khz = apic_timer_init(APIC_TIMER_VECTOR);
452 //printk("Calibrated APIC frequency: %lu kHz\n", apic_freq_khz);
454 //expected_time = tsc_read() + NS_PER_MSEC;
455 //apic_timer_set(NS_PER_MSEC);
460 void inmate_main(void)
462 bool allow_terminate = false;
463 bool terminate = false;
467 printk_uart_base = UART_BASE;
469 for (n = 0; n < UART_IDLE_LOOPS; n++)
470 if (!(inb(UART_BASE + UART_LSR) & UART_LSR_THRE))
472 } while (n < UART_IDLE_LOOPS);
474 comm_region->cell_state = JAILHOUSE_CELL_RUNNING_LOCKED;
476 //-------------------------------------------------------
477 //--------------HPET part--------------------------------
479 //struct rsdp *rsdp = acpi_get_rsdp();
480 //struct acpi_table *rsdt = (struct acpi_table *)((u64) rsdp->rsdt);
481 //printk("\nRSDT at %p.\n", rsdt);
483 //acpi_hpet_tbl ** acpi_table = (acpi_hpet_tbl **) acpi_get_table_ptr(rsdt, "HPET");
485 // if (acpi_table == 0) {
486 // printk("There is no HPET in ACPI tables.");
490 //gen_reg = (gen_regs *) ( (u64) (*acpi_table)->address_st.base_address);
491 gen_reg = (gen_regs *) ( (u64) 0x00000003f1ff000ULL);
493 printk("\nBase Address for HPET registers : %p\n", gen_reg);
494 u8 comparators_amount = (gen_reg->capat_id_reg & HPET_NUM_TIM_CAP_MASK) >> HPET_NUM_TIM_CAP_SHIFT;
496 main_counter_tick_period = gen_reg->clock_period;
498 main_counter_reg = (main_val_reg *)
501 + RESERVED_BEFORE_MAIN_VAL_REG
507 curr_place = ((u8 *) main_counter_reg) + sizeof(main_val_reg), n = 0;
508 n < comparators_amount;
509 curr_place += sizeof(timer_regs), ++n )
511 timer[n] = (timer_regs *) curr_place;
512 printk("\nTimer %u on: %p, ", n, timer[n]);
513 printk("Timer comparator : 0x%llx\n", timer[n]->comparator_val);
517 enable_main_counter();
519 set_timer_periodic( timer[0], NANS_TO_FEMPTS(1000000000ULL) / main_counter_tick_period );
520 set_timer_one_shot( timer[1], NANS_TO_FEMPTS(10000000000ULL) / main_counter_tick_period );
524 //-------------------------------------------------------
528 switch (comm_region->msg_to_cell) {
529 case JAILHOUSE_MSG_SHUTDOWN_REQUEST:
530 if (!allow_terminate) {
531 printk("Rejecting first shutdown request - "
533 jailhouse_send_reply_from_cell(comm_region,
534 JAILHOUSE_MSG_REQUEST_DENIED);
535 allow_terminate = true;
540 jailhouse_send_reply_from_cell(comm_region,
541 JAILHOUSE_MSG_UNKNOWN);
546 printk("Stopped APIC demo\n");
547 comm_region->cell_state = JAILHOUSE_CELL_SHUT_DOWN;