Changeset 00b38a3 in mainline for kernel/arch/sparc64/src/smp/ipi.c


Ignore:
Timestamp:
2006-09-28T15:48:31Z (18 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
c23baab
Parents:
a9ac978
Message:

IPI/cross-call support for sparc64.
SMP on sparc64 is now fully supported.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/sparc64/src/smp/ipi.c

    ra9ac978 r00b38a3  
    3434
    3535#include <smp/ipi.h>
     36#include <cpu.h>
     37#include <arch/cpu.h>
     38#include <arch/asm.h>
     39#include <config.h>
     40#include <mm/tlb.h>
     41#include <arch/interrupt.h>
     42#include <arch/trap/interrupt.h>
     43#include <arch/barrier.h>
     44#include <preemption.h>
     45#include <time/delay.h>
     46#include <panic.h>
    3647
     48/** Invoke function on another processor.
     49 *
     50 * Currently, only functions without arguments are supported.
     51 * Supporting more arguments in the future should be no big deal.
     52 *
     53 * Interrupts must be disabled prior to this call.
     54 *
     55 * @param mid MID of the target processor.
     56 * @param func Function to be invoked.
     57 */
     58static void cross_call(int mid, void (* func)(void))
     59{
     60        uint64_t status;
     61        bool done;
     62
     63        /*
     64         * This functin might enable interrupts for a while.
     65         * In order to prevent migration to another processor,
     66         * we explicitly disable preemption.
     67         */
     68       
     69        preemption_disable();
     70       
     71        status = asi_u64_read(ASI_INTR_DISPATCH_STATUS, 0);
     72        if (status & INTR_DISPATCH_STATUS_BUSY)
     73                panic("Interrupt Dispatch Status busy bit set\n");
     74       
     75        do {
     76                asi_u64_write(ASI_UDB_INTR_W, ASI_UDB_INTR_W_DATA_0, (uintptr_t) func);
     77                asi_u64_write(ASI_UDB_INTR_W, ASI_UDB_INTR_W_DATA_1, 0);
     78                asi_u64_write(ASI_UDB_INTR_W, ASI_UDB_INTR_W_DATA_2, 0);
     79                asi_u64_write(ASI_UDB_INTR_W, (mid << INTR_VEC_DISPATCH_MID_SHIFT) | ASI_UDB_INTR_W_DISPATCH, 0);
     80       
     81                membar();
     82               
     83                do {
     84                        status = asi_u64_read(ASI_INTR_DISPATCH_STATUS, 0);
     85                } while (status & INTR_DISPATCH_STATUS_BUSY);
     86               
     87                done = !(status & INTR_DISPATCH_STATUS_NACK);
     88                if (!done) {
     89                        /*
     90                         * Prevent deadlock.
     91                         */                     
     92                        (void) interrupts_enable();
     93                        delay(20 + (tick_read() & 0xff));
     94                        (void) interrupts_disable();
     95                }
     96        } while (done);
     97       
     98        preemption_enable();
     99}
     100
     101/*
     102 * Deliver IPI to all processors except the current one.
     103 *
     104 * The sparc64 architecture does not support any group addressing
     105 * which is found, for instance, on ia32 and amd64. Therefore we
     106 * need to simulate the broadcast by sending the message to
     107 * all target processors step by step.
     108 *
     109 * We assume that interrupts are disabled.
     110 *
     111 * @param ipi IPI number.
     112 */
    37113void ipi_broadcast_arch(int ipi)
    38114{
    39         /* TODO */
     115        int i;
     116       
     117        void (* func)(void);
     118       
     119        switch (ipi) {
     120        case IPI_TLB_SHOOTDOWN:
     121                func = tlb_shootdown_ipi_recv;
     122                break;
     123        default:
     124                panic("Unknown IPI (%d).\n", ipi);
     125                break;
     126        }
     127       
     128        /*
     129         * As long as we don't support hot-plugging
     130         * or hot-unplugging of CPUs, we can walk
     131         * the cpus array and read processor's MID
     132         * without locking.
     133         */
     134       
     135        for (i = 0; i < config.cpu_active; i++) {
     136                if (&cpus[i] == CPU)
     137                        continue;               /* skip the current CPU */
     138
     139                cross_call(cpus[i].arch.mid, func);
     140        }
    40141}
    41142
Note: See TracChangeset for help on using the changeset viewer.