Changeset 00b38a3 in mainline


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.

Location:
kernel
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/sparc64/include/interrupt.h

    ra9ac978 r00b38a3  
    4646#define IVT_FIRST       1
    4747
    48 #define VECTOR_TLB_SHOOTDOWN_IPI        0       /* TODO */
     48#define VECTOR_TLB_SHOOTDOWN_IPI        0
     49#define IPI_TLB_SHOOTDOWN               VECTOR_TLB_SHOOTDOWN_IPI
    4950
    5051struct istate {
  • kernel/arch/sparc64/include/trap/interrupt.h

    ra9ac978 r00b38a3  
    5151#define ASI_UDB_INTR_W_DATA_1   0x50
    5252#define ASI_UDB_INTR_W_DATA_2   0x60
     53#define ASI_UDB_INTR_W_DISPATCH 0x70
    5354
    5455/* VA's used with ASI_UDB_INTR_R register. */
     
    5657#define ASI_UDB_INTR_R_DATA_1   0x50
    5758#define ASI_UDB_INTR_R_DATA_2   0x60
     59
     60/* Shifts in the Interrupt Vector Dispatch virtual address. */
     61#define INTR_VEC_DISPATCH_MID_SHIFT     14
     62
     63/* Bits in the Interrupt Dispatch Status register. */
     64#define INTR_DISPATCH_STATUS_NACK       0x2
     65#define INTR_DISPATCH_STATUS_BUSY       0x1
    5866
    5967#define TT_INTERRUPT_LEVEL_1                    0x41
  • 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
  • kernel/arch/sparc64/src/trap/interrupt.c

    ra9ac978 r00b38a3  
    4646#include <print.h>
    4747#include <genarch/kbd/z8530.h>
     48#include <arch.h>
     49#include <mm/tlb.h>
     50#include <config.h>
    4851
    4952/** Register Interrupt Level Handler.
     
    98101
    99102#endif
     103        default:
     104                if (data0 > config.base) {
     105                        /*
     106                         * This is a cross-call.
     107                         * data0 contains address of kernel function.
     108                         * We call the function only after we verify
     109                         * it is on of the supported ones.
     110                         */
     111#ifdef CONFIG_SMP
     112                        if (data0 == (uintptr_t) tlb_shootdown_ipi_recv) {
     113                                tlb_shootdown_ipi_recv();
     114                                break;
     115                        }
     116#endif
     117                }
     118                       
     119                printf("cpu%d: spurious interrupt (intrcv=%#llx, data0=%#llx)\n", CPU->id, intrcv, data0);
     120                break;
    100121        }
    101122
  • kernel/generic/src/mm/tlb.c

    ra9ac978 r00b38a3  
    162162
    163163                switch (type) {
    164                     case TLB_INVL_ALL:
     164                case TLB_INVL_ALL:
    165165                        tlb_invalidate_all();
    166166                        break;
    167                     case TLB_INVL_ASID:
     167                case TLB_INVL_ASID:
    168168                        tlb_invalidate_asid(asid);
    169169                        break;
    170                     case TLB_INVL_PAGES:
     170                case TLB_INVL_PAGES:
    171171                        ASSERT(count);
    172172                        tlb_invalidate_pages(asid, page, count);
    173173                        break;
    174                     default:
     174                default:
    175175                        panic("unknown type (%d)\n", type);
    176176                        break;
Note: See TracChangeset for help on using the changeset viewer.