Hi,

Looking at the working implementations of IPIs I came
across these inconsistencies:


1) APIC: waiting for completion
-------------------------------
APIC has a bit that indicates if an IPI is in progress.
Should we not wait for the dispatch of the previous IPI
to complete before we send another one? Note that I don't
know if l_apic[ICRlo].delivs is CPU local (so a simple
while(l_apic[ICRlo].delivs == DELIVS_PENDING){} would
suffice) or global for the system (then we'd need a lock).
IPIs are sent via l_apic_broadcast_custom_ipi in
arch/ia32/src/smp/apic.c:

int l_apic_broadcast_custom_ipi(uint8_t vector)
{
        icr_t icr;
        
        // Wait here for icr.delivs != DELIVS_PENDING ?
        
        icr.lo = l_apic[ICRlo];
        icr.delmod = DELMOD_FIXED;
        icr.destmod = DESTMOD_LOGIC;
        icr.level = LEVEL_ASSERT;
        icr.shorthand = SHORTHAND_ALL_EXCL;
        icr.trigger_mode = TRIGMOD_LEVEL;
        icr.vector = vector;
        
        l_apic[ICRlo] = icr.lo;
        
        icr.lo = l_apic[ICRlo];
        if (icr.delivs == DELIVS_PENDING) {
#ifdef CONFIG_DEBUG
                printf("IPI is pending.\n");
#endif
        }
        
        return apic_poll_errors();
}

2) sparc64/sun4U: while-loop cond
---------------------------------
arch/sparc64/src/smp/sun4u/ipi.c sends IPIs via cross_call().
It has a suspicious while loop end condition. I don't
know enough to decide if it is a bug or not.

static void cross_call(int mid, void (* func)(void))
{
        uint64_t status;
        bool done;

        /* snip */
        
        do {
                // snip
                if (!done) {
                        /*
                         * Prevent deadlock.
                         */                     
                        (void) interrupts_enable();
                        delay(20 + (tick_read() & 0xff));
                        (void) interrupts_disable();
                }

        } while (done); // <-- instead of "while (!done)" ?!
        
        preemption_enable();
}


3) sparc64/sun4v: cpu->arch.id vs cpu->id
-----------------------------------------
In arch/sparc64/src/smp/sun4v/ipi.c, ipi_broadcast_arch()
seems to be mixing cpu->arch.id with cpu->id as if they
were the same (even if they are guaranteed to match, it
is just not obvious from the code):

void ipi_broadcast_arch(int ipi)
{
        void (* func)(void);
        /* snip */
        unsigned int i;
        unsigned idx = 0;
        for (i = 0; i < config.cpu_active; i++) {
                if (&cpus[i] == CPU) {
                        continue;
                }

                // Was this supposed to be CPU->arch.id and
                // cpus[i].arch.id ??
                ipi_cpu_list[CPU->id][idx] = (uint16_t) cpus[i].id;
                idx++;
        }

        ipi_brodcast_to(func, ipi_cpu_list[CPU->arch.id], idx);
}


Thanks to anyone with the proper knowledge for checking
these inconsistencies.

Adam

_______________________________________________
HelenOS-devel mailing list
[email protected]
http://lists.modry.cz/cgi-bin/listinfo/helenos-devel

Reply via email to