Changeset 00b38a3 in mainline for kernel/arch/sparc64/src/smp/ipi.c
- Timestamp:
- 2006-09-28T15:48:31Z (18 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- c23baab
- Parents:
- a9ac978
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/sparc64/src/smp/ipi.c
ra9ac978 r00b38a3 34 34 35 35 #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> 36 47 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 */ 58 static 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 */ 37 113 void ipi_broadcast_arch(int ipi) 38 114 { 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 } 40 141 } 41 142
Note:
See TracChangeset
for help on using the changeset viewer.