Forum Topic - QNX 8.0.4 x86_64 platform "Haswell" system timer delay: (10 Items)
   
QNX 8.0.4 x86_64 platform "Haswell" system timer delay  
The QNX 8.0.4 Intel BSP startup code is configured to use the LAPIC timer. HPET is disabled, and the legacy 8254 timer 
is not used. We are observing significant system time drift under this configuration. For example, the system clock 
falls behind by approximately -2.52 seconds over a 15-minute period.
We would appreciate any comments, recommended solutions, or information about known issues or limitations in the QNX 
implementation related to LAPIC timer usage.
Regards,
Janusz
Re: QNX 8.0.4 x86_64 platform "Haswell" system timer delay  
QNX 8 requires a per-processor timer. On x86 this is the LAPIC timer - there is no other choice.
This drift is indeed significant - is it a simple matter of adjusting the value of cycles per second to match this 
particular board?

--Elad
Re: QNX 8.0.4 x86_64 platform "Haswell" system timer delay  
Thank you for your comments. The target platform is an Advantech SOM‑6884 COM Express module based on an Intel® Core™
 i7 processor. Given this hardware configuration, I do not believe that any practical clock‑rate “adjustment” or 
correction is possible after the startup initialization phase. Once the system has completed early boot and the timer 
source has been selected, there appears to be no viable mechanism to compensate for the observed time drift at runtime.

Janusz
Re: QNX 8.0.4 x86_64 platform "Haswell" system timer delay  
I meant set a better value for this board in startup. See set_cycles_per_sec() in the startup library. You can specify a
 different value from the startup command line with the -f option, and also look into why calibration doesn't produce a 
value that's correct for the board.

--Elad
Re: QNX 8.0.4 x86_64 platform "Haswell" system timer delay  
The calibration is executed as part of the startup sequence, prior to kernel initialization. The code snippet below 
shows the implementation. That is part of QNX 8.0 BSP.

/**
 * Calibrate the frequency of TSC in Hz, using the default timer
 * @return	TSC cycles per second (Hz)
 */
uint64_t calibrate_tsc(unsigned long ns)
{
	unsigned long ticks;
	unsigned start_tick;
	uint64_t init_diff;
	uint64_t tick_diff;
	uint64_t start_tsc;
	uint64_t end_tsc;
	uint64_t elapsed_time_nano;
	uint64_t cycles_per_sec;
	unsigned factor;
	unsigned scale_factor;

	ticks = timer_ns2tick(ns);
	start_tick = timer_start();

	/* preparation: wait for the beginning of a tick to sync with rdtsc */
	do {
		init_diff = timer_diff(start_tick);
	} while (init_diff == 0);
	ticks += init_diff;

	/* actual benchmark */
	rdtsc_ordered(&start_tsc);
	__asm__ __volatile__ (".align 16");
	do {
		tick_diff = timer_diff(start_tick);
	} while (tick_diff < ticks);

	rdtsc_ordered(&end_tsc);

	/* calculation based on end_tsc, start_tsc and tick_diff */
	tick_diff -= init_diff;	/* init_diff is measured prior to the beginning of benchmark */

	/* Please, refer to [A Note About Using qtime::timer_rate And qtime::timer_scale]
	 * in services/system/doc/clock.txt and services/system/ker/nano_clock.c:clock_start()
	 * and jiffy_to_ns() for the detail
	 */
    if (lsp.qtime.p->timer_scale < NANO_SCALE) {
        factor = (unsigned)(NANO_SCALE - lsp.qtime.p->timer_scale);
    } else {
        factor = (unsigned)(lsp.qtime.p->timer_scale - NANO_SCALE);
    }

    scale_factor = 1;
    while (factor != 0) {
        scale_factor *= 10;
        --factor;
    }

	if (lsp.qtime.p->timer_scale < NANO_SCALE) {	/* e.g. if nano_conversion_scale is -6, it means 'timer_scale' is femto */

		elapsed_time_nano = ((tick_diff * (lsp.qtime.p->timer_period)) + (scale_factor >> 1)) / scale_factor;	/* to 
nanoseconds */
	} else {	/* e.g if nano_conversion_scale is 3, it means 'timer_scale' is micro */
		elapsed_time_nano = (tick_diff * (lsp.qtime.p->timer_period)) * scale_factor;	/* to nanoseconds */
	}

	cycles_per_sec = ((end_tsc - start_tsc) * 1000000000) / elapsed_time_nano;
	return cycles_per_sec;
}
Re: QNX 8.0.4 x86_64 platform "Haswell" system timer delay  
Yes, I am aware of what it does. What I am saying is that you can find empirically a correct value for your board and 
pass it with the -f function to startup. It would be interesting to know why that value is not what the calibration loop
 comes up with.
By the way, does it produce the same value on every boot?

--Elad
Re: QNX 8.0.4 x86_64 platform "Haswell" system timer delay  
It does not produce the same value on each boot. For example:
0x95031584 = 2,500,007,300
0x95031c8b = 2,500,009,099
0x95024de8 = 2,499,956,200
0x95031f47 = 2,500,009,799

Based on empirical observation, the value that appears to be sufficiently accurate to keep time aligned with the wall 
clock is: 2494076850.
Re: QNX 8.0.4 x86_64 platform "Haswell" system timer delay  
Can you post the output of `startup -v`  please ?
Re: QNX 8.0.4 x86_64 platform "Haswell" system timer delay  
Stephen, here you go :

non UEFI or UEFI+CSM boot
Hypervisor support disabled
Added /memory/lapic
pci_find_class() returned D31:F0
Added 1 IOAPIC from ACPI tables
Base CPU interrupt for APIC is 48
lapic_configure(cpu=0), lapic_id: 0x00000000
Intel IOAPIC config
Found 1 IOAPIC's.
configuring IOAPIC id:8
Autofill: 16 of requested 40 entries available for profile 6
Restored IOAPIC B:D:F to 0:31:0 from 240:31:0
IOAPIC 8: successfully configured 40 vectors from 0 to 39
MSI interrupt = 0x00000100
MSI vector no = 94 0x0000005e
MSI vec count = 161
CPU Family/Model: 0x00000006/0x00000045
MSR_PLATFORM_INFO: 0x000803df3011900, TSC multiplier: 25
LAPIC on CPU 0 (ID=0x00000000) selected for system clock on IRQ 0x00010000
**Checking smp_hwcoreid for cpu 0
found ACPI reset reg addr/value of 00000000000cf9/00000006
using reset reg addr/value of 00000000000cf9/00000006

Loading IFS...decompressing...done

apic_smp_start(1), CPU 0, cep->smp_hwcoreid = 0x00000000
apic_smp_start(1), CPU 1, cep->smp_hwcoreid = 0x00000002
apic_smp_start(1), CPU 2, cep->smp_hwcoreid = 0x00000001
apic_smp_start(1), CPU 3, cep->smp_hwcoreid = 0x00000003

No low memory for AP start-up; using bootloader
apstart_init(0000000000000680, 00000000004018c43) [size=0x000000b6]

**Checking smp_hwcoreid for cpu 1
lapic_configure(cpu=1), lapic_id: 0x00000002
**Checking smp_hwcoreid for cpu 2
lapic_configure(cpu=2), lapic_id: 0x00000001
**Checking smp_hwcoreid for cpu 3
lapic_configure(cpu=3), lapic_id: 0x00000003

System page at phys:00000000001c000 user:fffff808000003000 kern:fffff808000007000

Starting next program at vffff80800004609e
overriding mask for controller 2, vector_base 0
Exar's devc-xrserpcie QNX-module ver 0.2 - x86_64-bits
16 Exar ports found.
Re: QNX 8.0.4 x86_64 platform "Haswell" system timer delay  
Correction:
MSR_PLATFORM_INFO: 0x000803df3011900, TSC multiplier: 25
LAPIC on CPU 0 (ID=0x00000000) selected for system clock on IRQ 0x80010000