Skip to content

Commit

Permalink
Make sure timers don't go completely out of sync upon altering TSC vi…
Browse files Browse the repository at this point in the history
…a WRMSR
  • Loading branch information
Cacodemon345 committed Jun 18, 2024
1 parent 382b941 commit 281ad05
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 6 deletions.
13 changes: 7 additions & 6 deletions src/cpu/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include <86box/nmi.h>
#include <86box/pic.h>
#include <86box/pci.h>
#include <86box/timer.h>
#include <86box/gdbstub.h>
#include <86box/plat_fallthrough.h>
#include <86box/plat_unused.h>
Expand Down Expand Up @@ -3492,7 +3493,7 @@ cpu_WRMSR(void)
break;
/* Time Stamp Counter */
case 0x10:
tsc = EAX | ((uint64_t) EDX << 32);
timer_set_new_tsc(EAX | ((uint64_t) EDX << 32));
break;
/* Performance Monitor - Control and Event Select */
case 0x11:
Expand Down Expand Up @@ -3568,7 +3569,7 @@ cpu_WRMSR(void)
break;
/* Time Stamp Counter */
case 0x10:
tsc = EAX | ((uint64_t) EDX << 32);
timer_set_new_tsc(EAX | ((uint64_t) EDX << 32));
break;
/* PERFCTR0 - Performance Counter Register 0 - aliased to TSC */
case 0xc1:
Expand Down Expand Up @@ -3664,7 +3665,7 @@ cpu_WRMSR(void)
break;
/* Time Stamp Counter */
case 0x00000010:
tsc = EAX | ((uint64_t) EDX << 32);
timer_set_new_tsc(EAX | ((uint64_t) EDX << 32));
break;
/* Array Access Register */
case 0x00000082:
Expand Down Expand Up @@ -3834,7 +3835,7 @@ cpu_WRMSR(void)
/* Time Stamp Counter */
case 0x00000010:
case 0x80000010:
tsc = EAX | ((uint64_t) EDX << 32);
timer_set_new_tsc(EAX | ((uint64_t) EDX << 32));
break;
/* Performance Monitor - Control and Event Select */
case 0x00000011:
Expand Down Expand Up @@ -3919,7 +3920,7 @@ cpu_WRMSR(void)
msr.tr5 = EAX & 0x008f0f3b;
/* Time Stamp Counter */
case 0x10:
tsc = EAX | ((uint64_t) EDX << 32);
timer_set_new_tsc(EAX | ((uint64_t) EDX << 32));
break;
/* Performance Monitor - Control and Event Select */
case 0x11:
Expand Down Expand Up @@ -3952,7 +3953,7 @@ cpu_WRMSR(void)
break;
/* Time Stamp Counter */
case 0x10:
tsc = EAX | ((uint64_t) EDX << 32);
timer_set_new_tsc(EAX | ((uint64_t) EDX << 32));
break;
/* Unknown */
case 0x18:
Expand Down
3 changes: 3 additions & 0 deletions src/include/86box/timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,9 @@ timer_set_p(pc_timer_t *timer, void *priv)
extern void timer_stop(pc_timer_t *timer);
extern void timer_on_auto(pc_timer_t *timer, double period);

/* Change TSC, taking into account the timers. */
extern void timer_set_new_tsc(uint64_t new_tsc);

#ifdef __cplusplus
}
#endif
Expand Down
29 changes: 29 additions & 0 deletions src/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,3 +253,32 @@ timer_on_auto(pc_timer_t *timer, double period)
else
timer_stop(timer);
}

void
timer_set_new_tsc(uint64_t new_tsc)
{
pc_timer_t *timer = NULL;
uint32_t offset = 0;
/* Run timers already expired. */
#ifdef USE_DYNAREC
if (cpu_use_dynarec)
update_tsc();
#endif

if (!timer_head) {
tsc = new_tsc;
return;
}

timer = timer_head;
timer_target = new_tsc + (int32_t)(timer_get_ts_int(timer_head) - (uint32_t)tsc);

while (timer) {
int32_t offset_from_current_tsc = (int32_t)(timer_get_ts_int(timer) - (uint32_t)tsc);
timer->ts.ts32.integer = new_tsc + offset_from_current_tsc;

timer = timer->next;
}

tsc = new_tsc;
}

0 comments on commit 281ad05

Please sign in to comment.