VOGONS


First post, by superfury

User metadata
Rank l33t++
Rank
l33t++

On osdev, it says that it has some weird stuff related to register write ordering(LVT vs initial counter vs divide configuration)?

Anyone knows how the APIC timer counter actually functions? Windows NT 4.0 seems to reject it (not enable the timer) when implemented as osdev describes it?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 2 of 5, by superfury

User metadata
Rank l33t++
Rank
l33t++

Both Windows NT 4.0 and Linux seem to make the timer count from it's maximum value. But after that it (at least according to the Linux on-screen debugging information) invalidates the timer for use and uses the PIT instead (disabling the APIC timer IVT entry).
Both timers run according to the very same clock.

AFAIK the interrupt functions properly, I even see it firing on Linux, but linux doesn't count it as properly fired it seems like?
Current (A)PIC emulation and IRQ handling: https://bitbucket.org/superfury/unipcemu/src/ … /hardware/pic.c
Look at updateAPIC() for the handling of the APIC timer itself (not the I/O to the timer registers), LVTTimerRegister in the remainder of the file for it's read/write operations (write sets the needstermination bit 8 and 10 to be handled after the write by the CPU).
In needstermination, bit 4 is set when the intial count register is written, bit 5 is set when the divide configuration register is written.
Look at LAPIC_handletermination() for the handling of those bits after they're set in the needstermination bitflags (which clears those bits after they're handled).

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 3 of 5, by superfury

User metadata
Rank l33t++
Rank
l33t++

This is what I get right now on Debian Jessie:

1552-UniPCemu_APIC_diagnostics.png
Filename
1552-UniPCemu_APIC_diagnostics.png
File size
14.42 KiB
Views
848 views
File comment
APIC result on Debian Jessie booting in Expert mode
File license
Fair use/fair dealing exception

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 4 of 5, by x64lover

User metadata
Rank Newbie
Rank
Newbie

It looks to me like the APIC timer is not firing in tandem with the PIC timer. Yes, the frequency of the APIC timer can be different than the PIC, but it needs to be synchronized because Linux uses the PIT for calibration . It can't be "1 apic decrement for the 10th pit raise, then 15th, than 17th, than 27th". It can be like "1 apic decrement for every 10th, 20th, 30th pit raise". It should also be synchronized with the CMOS clock, as Win NT uses that for calibration of the APIC.

I could be wrong and I certainly could do more looking into it but https://github.com/rofl0r/uniPCemu/blob/56f4a … emucore.c#L1403 shows the APIC timer handler is in a different place than the PIT and CMOS. I don't know your codebase very well, but I would first look into keeping the interrupt portion of the APIC at the same place while moving the timer portion to the 14mhz loop.

Reply 5 of 5, by superfury

User metadata
Rank l33t++
Rank
l33t++
x64lover wrote on 2022-06-11, 15:59:

It looks to me like the APIC timer is not firing in tandem with the PIC timer. Yes, the frequency of the APIC timer can be different than the PIC, but it needs to be synchronized because Linux uses the PIT for calibration . It can't be "1 apic decrement for the 10th pit raise, then 15th, than 17th, than 27th". It can be like "1 apic decrement for every 10th, 20th, 30th pit raise". It should also be synchronized with the CMOS clock, as Win NT uses that for calibration of the APIC.

I could be wrong and I certainly could do more looking into it but https://github.com/rofl0r/uniPCemu/blob/56f4a … emucore.c#L1403 shows the APIC timer handler is in a different place than the PIT and CMOS. I don't know your codebase very well, but I would first look into keeping the interrupt portion of the APIC at the same place while moving the timer portion to the 14mhz loop.

They are in fact running at the same method of timing.
The CPU itself ticks it's clocks first(the CPU loop for all emulated cores).
Then it ticks all other timing by 1 CPU timespan(1 cycle time).
The cycle time(in nanoseconds) is determined by 2 factors. If the CPU is in IPS mode(instructions per second), it drives timing a clock if any CPU has finished an instruction(otherwise, it's not ticking anything else). Otherwise (in cycle-accurate mode), it drives 1 cycle always(causing the hardware to tick 1 clock cycle time instead within any instruction).
The base timing (time in ns or 0ns) in both cases is the nanoseconds stored into effectiveinstructiontime.
The TSC timing and APIC timing are seperated because they don't just tick at the 14.31818MHz intervals, but instead at a way higher rate(up to 333MHz).
But the ticking should be in sync with the 14MHz ticking, as it's a division of the very same clock(just dividing the 333MHz signal way further down using the same timings).
Both are a simple add-divide-and-remainder like done with the TSC(divide by tick period to obtain the amount of ticks passed, substract using the multiplying of calculated ticks to obtain the remainder for future cycles to be calculated).
In fact, the ticking of the TSC is handled exactly the same as the 14MHz signal, APIC clocks ticked, as well as all hardware ticking from the 14MHz source in general(they all use either the 14MHz clocks ticked directly or the 14MHz clock cycle time in nanoseconds to update their own cycles at their own speed(like for instance the VGA 28MHz clock or Sound Blaster 1MHz clock, Game Blaster 8MHz clock etc.).
They all use the same method of divide-and-remainder to calculate cycles to tick and then perform the ticking of their own hardware by parsing that amount of cycles. Or they can use the 14MHz signal directly(like the EGA).

Since they're all still based on the base timing provided by the CPU cores together, they all run in sync.
The reason why the APIC/TSC aren't inside the 14MHz clock part is because they're way too fast(333>14.31818). It wouldn't tick properly if updated only if a 14MHz clock ticked(causing inaccuracies by skipping clocks and parsing multiple clocks at once when the APIC is updated faster than 14.31818MHz by the CPU, which isn't needed with the current scheme).
The 14MHz devices don't suffer from that because they're natural 14MHz devices.
And the only other faster than 14MHz device is the video card, which is outside the loop as well for that reason.
Also, the location of ticking the APIC/TSC now is more optimized for speed (cached variables that are used), especially for single ticks(although 333MHz in my used 3MIPS situatuation doesn't parse single APIC clocks because of 333ns for each cycle or instruction(depending on the configured CPU cycle mode)). It would need to run at 333MIPS for that to happen(333000 cycles, currently 3000 cycles). Although afaik no real physical CPU in existence can pull that off at this point in time (3MIPS at ~20% realtime already takes 100% of a core on my i7-4790K CPU).

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io