|
18 | 18 | #include <arch/x86.h> |
19 | 19 | #include <arch/x86/feature.h> |
20 | 20 | #include <kernel/spinlock.h> |
21 | | -#include "platform_p.h" |
| 21 | +#include <platform/time.h> |
22 | 22 | #include <platform/pc.h> |
23 | 23 | #include <kernel/vm.h> |
24 | 24 |
|
| 25 | +#include "platform_p.h" |
| 26 | + |
25 | 27 | #define LOCAL_TRACE 1 |
26 | 28 |
|
27 | 29 | static bool lapic_present = false; |
@@ -69,6 +71,19 @@ enum lapic_regs { |
69 | 71 | LAPIC_EXT_LVT0 = 0x500, |
70 | 72 | }; |
71 | 73 |
|
| 74 | +enum lapic_interrupts { |
| 75 | + LAPIC_INT_TIMER = 0xf8, |
| 76 | + LAPIC_INT_GENERIC, |
| 77 | + LAPIC_INT_RESCHEDULE, |
| 78 | +}; |
| 79 | + |
| 80 | +enum lapic_timer_mode { |
| 81 | + LAPIC_TIMER_MODE_ONESHOT = 0, |
| 82 | + LAPIC_TIMER_MODE_PERIODIC = 1, |
| 83 | + LAPIC_TIMER_MODE_TSC_DEADLINE = 2, |
| 84 | +}; |
| 85 | + |
| 86 | + |
72 | 87 | static uint32_t lapic_read(enum lapic_regs reg) { |
73 | 88 | LTRACEF("reg %#x\n", reg); |
74 | 89 | DEBUG_ASSERT(reg != LAPIC_ICRLO && reg != LAPIC_ICRHI); |
@@ -101,6 +116,29 @@ static void lapic_write_icr(uint32_t low, uint32_t apic_id) { |
101 | 116 | } |
102 | 117 | } |
103 | 118 |
|
| 119 | +void lapic_set_oneshot_timer(uint32_t tick) { |
| 120 | + LTRACEF("tick %u\n", tick); |
| 121 | + |
| 122 | + // set the initial count, which should trigger the timer |
| 123 | + lapic_write(LAPIC_TICR, tick); |
| 124 | +} |
| 125 | + |
| 126 | +void lapic_cancel_oneshot_timer(void) { |
| 127 | + LTRACE; |
| 128 | + |
| 129 | + // set the counter to 0 which disables it |
| 130 | + lapic_write(LAPIC_TICR, 0); |
| 131 | +} |
| 132 | + |
| 133 | +enum handler_return lapic_timer_handler(void *arg) { |
| 134 | + //PANIC_UNIMPLEMENTED; |
| 135 | + |
| 136 | +// return timer_tick(NULL, current_time()); |
| 137 | + |
| 138 | + lapic_set_oneshot_timer(100000000); |
| 139 | + |
| 140 | + return INT_NO_RESCHEDULE; |
| 141 | +} |
104 | 142 |
|
105 | 143 | void lapic_init(void) { |
106 | 144 | // discover the presence of the local apic and map it |
@@ -156,6 +194,17 @@ void lapic_init_postvm(uint level) { |
156 | 194 | if (eas) { |
157 | 195 | dprintf(INFO, "X86: local apic EAS features %#x\n", lapic_read(LAPIC_EXT_FEATURES)); |
158 | 196 | } |
| 197 | + |
| 198 | + lapic_cancel_oneshot_timer(); |
| 199 | + |
| 200 | + // configure the local timer and make sure it is not set to fire |
| 201 | + uint32_t val = (LAPIC_TIMER_MODE_ONESHOT << 17) | LAPIC_INT_TIMER; |
| 202 | + lapic_write(LAPIC_TIMER, val); |
| 203 | + |
| 204 | + // register the local apic interrupts |
| 205 | + register_int_handler_msi(LAPIC_INT_TIMER, &lapic_timer_handler, NULL, false); |
| 206 | + |
| 207 | + lapic_set_oneshot_timer(1000000); |
159 | 208 | } |
160 | 209 |
|
161 | 210 | LK_INIT_HOOK(lapic, lapic_init_postvm, LK_INIT_LEVEL_VM); |
|
0 commit comments