baponkar
baponkar

Reputation: 456

Why does`LAPIC_SVR`, `LAPIC_TDCR`, `LAPIC_TICR`, `LAPIC_TCCR`, address value is zero even after write?

I am trying to enable periodic APIC Timer in x86 architecture based 64 bit OS.

void apic_timer_init(uint32_t frequency) {

    disable_interrupts();

    // Ensure APIC is enabled (set Spurious Interrupt Vector Register)
    printf("\nLAPIC_SVR before enable: %x\n", mmio_read(LAPIC_BASE + LAPIC_SVR));
    mmio_write((LAPIC_BASE + LAPIC_SVR), mmio_read(LAPIC_BASE + LAPIC_SVR) | 0x100);
    printf("LAPIC_SVR after enable: %x\n", mmio_read(LAPIC_BASE + LAPIC_SVR));

    // Set timer divide configuration (Divide by 16)
    mmio_write((LAPIC_BASE + LAPIC_TDCR), 0x3);
    printf("LAPIC_TDCR: %x\n", mmio_read(LAPIC_BASE + LAPIC_TDCR));

    // Set initial count for calibration (large value)
    mmio_write((LAPIC_BASE + LAPIC_TICR), 0xFFFFFFFF);
    printf("LAPIC_TICR after set: %x\n", mmio_read(LAPIC_BASE + LAPIC_TICR));

    // Wait a bit (using PIT or another timer for calibration)
    for (volatile int i = 0; i < 1000000; i++);

    // Measure elapsed ticks (TSC or another timer)
    uint32_t elapsed = 0xFFFFFFFF - mmio_read(LAPIC_BASE + LAPIC_TCCR);
    printf("Elapsed ticks: %x\n", elapsed);
    
    // Calculate the required APIC timer count for the desired frequency
    uint32_t ticks_per_ms = elapsed / 10; // Assuming 10ms elapsed
    uint32_t initial_count = ticks_per_ms * (1000 / frequency);
    
    // Set the APIC Timer to periodic mode
    mmio_write((LAPIC_BASE + LAPIC_TIMER), TIMER_VECTOR | 0x20000);
    printf("LAPIC_TIMER: %x\n", mmio_read(LAPIC_BASE + LAPIC_TIMER));

    printf("LAPIC_TCCR before start: %x\n", mmio_read(LAPIC_BASE + LAPIC_TCCR));
    mmio_write((LAPIC_BASE + LAPIC_TICR), initial_count);  // Periodic mode, vector 0x20
    printf("LAPIC_TCCR after start: %x\n", mmio_read(LAPIC_BASE + LAPIC_TCCR));

    // install apic timer interrupt handler apic_timerHandler
    interrupt_install_handler(TIMER_VECTOR, &apic_timerHandler); 

    apic_remap_timer(initial_count);

    enable_interrupts();

    printf("APIC Timer initialized for periodic mode.\n");
}

The above function is showing LAPIC_SVR, LAPIC_TDCR, LAPIC_TICR, LAPIC_TCCR value is 0 before and after mmio_write. I am sure APIC is available and enabled as APIC keyboard is working. The LAPIC_BASE value is 0xFEE00000.

I am also using below functions

// Write to a memory-mapped I/O address
void mmio_write(uint32_t address, uint32_t value) {
    *((volatile uint32_t*)address) = value;
}

// Read from a memory-mapped I/O address
uint64_t mmio_read(uint32_t address) {
    return *((volatile uint64_t*)address);
}

Full code

What is the reason LAPIC_SVR, LAPIC_TDCR, LAPIC_TICR, LAPIC_TCCR register's values are not updating?

Upvotes: 0

Views: 21

Answers (0)

Related Questions