Rev 2071 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2071 | Rev 2134 | ||
---|---|---|---|
Line 29... | Line 29... | ||
29 | /** @addtogroup sparc64mm |
29 | /** @addtogroup sparc64mm |
30 | * @{ |
30 | * @{ |
31 | */ |
31 | */ |
32 | /** |
32 | /** |
33 | * @file |
33 | * @file |
- | 34 | * @brief D-cache shootdown algorithm. |
|
34 | */ |
35 | */ |
35 | 36 | ||
36 | #include <arch/mm/cache.h> |
37 | #include <arch/mm/cache.h> |
37 | 38 | ||
- | 39 | #ifdef CONFIG_SMP |
|
- | 40 | #ifdef CONFIG_VIRT_IDX_DCACHE |
|
- | 41 | ||
- | 42 | #include <smp/ipi.h> |
|
- | 43 | #include <arch/interrupt.h> |
|
- | 44 | #include <synch/spinlock.h> |
|
- | 45 | #include <arch.h> |
|
- | 46 | #include <debug.h> |
|
- | 47 | ||
- | 48 | /** |
|
- | 49 | * This spinlock is used by the processors to synchronize during the D-cache |
|
- | 50 | * shootdown. |
|
- | 51 | */ |
|
- | 52 | SPINLOCK_INITIALIZE(dcachelock); |
|
- | 53 | ||
- | 54 | /** Initialize the D-cache shootdown sequence. |
|
- | 55 | * |
|
- | 56 | * Start the shootdown sequence by sending out an IPI and wait until all |
|
- | 57 | * processors spin on the dcachelock spinlock. |
|
- | 58 | * |
|
- | 59 | * @param type Scope of the D-cache shootdown. |
|
- | 60 | * @param color Color to be invalidated; applicable only for DCACHE_INVL_COLOR |
|
- | 61 | * and DCACHE_INVL_FRAME invalidation types. |
|
- | 62 | * @param frame Frame to be invalidated; applicable only for DCACHE_INVL_FRAME |
|
- | 63 | * invalidation types. |
|
- | 64 | */ |
|
- | 65 | void dcache_shootdown_start(dcache_invalidate_type_t type, int color, |
|
- | 66 | uintptr_t frame) |
|
- | 67 | { |
|
- | 68 | int i; |
|
- | 69 | ||
- | 70 | CPU->arch.dcache_active = 0; |
|
- | 71 | spinlock_lock(&dcachelock); |
|
- | 72 | ||
- | 73 | for (i = 0; i < config.cpu_count; i++) { |
|
- | 74 | cpu_t *cpu; |
|
- | 75 | ||
- | 76 | if (i == CPU->id) |
|
- | 77 | continue; |
|
- | 78 | ||
- | 79 | cpu = &cpus[i]; |
|
- | 80 | spinlock_lock(&cpu->lock); |
|
- | 81 | if (cpu->arch.dcache_message_count == |
|
- | 82 | DCACHE_MSG_QUEUE_LEN) { |
|
- | 83 | /* |
|
- | 84 | * The queue is full, flush the cache entirely. |
|
- | 85 | */ |
|
- | 86 | cpu->arch.dcache_message_count = 1; |
|
- | 87 | cpu->arch.dcache_messages[0].type = DCACHE_INVL_ALL; |
|
- | 88 | cpu->arch.dcache_messages[0].color = 0; /* ignored */ |
|
- | 89 | cpu->arch.dcache_messages[0].frame = 0; /* ignored */ |
|
- | 90 | } else { |
|
- | 91 | index_t idx = cpu->arch.dcache_message_count++; |
|
- | 92 | cpu->arch.dcache_messages[idx].type = type; |
|
- | 93 | cpu->arch.dcache_messages[idx].color = color; |
|
- | 94 | cpu->arch.dcache_messages[idx].frame = frame; |
|
- | 95 | } |
|
- | 96 | spinlock_unlock(&cpu->lock); |
|
- | 97 | } |
|
- | 98 | ||
- | 99 | ipi_broadcast(IPI_DCACHE_SHOOTDOWN); |
|
- | 100 | ||
- | 101 | busy_wait: |
|
- | 102 | for (i = 0; i < config.cpu_count; i++) |
|
- | 103 | if (cpus[i].arch.dcache_active) |
|
- | 104 | goto busy_wait; |
|
- | 105 | } |
|
- | 106 | ||
- | 107 | /** Finish the D-cache shootdown sequence. */ |
|
- | 108 | void dcache_shootdown_finalize(void) |
|
- | 109 | { |
|
- | 110 | spinlock_unlock(&dcachelock); |
|
- | 111 | CPU->arch.dcache_active = 1; |
|
- | 112 | } |
|
- | 113 | ||
- | 114 | /** Process the D-cache shootdown IPI. */ |
|
- | 115 | void dcache_shootdown_ipi_recv(void) |
|
- | 116 | { |
|
- | 117 | int i; |
|
- | 118 | ||
- | 119 | ASSERT(CPU); |
|
- | 120 | ||
- | 121 | CPU->arch.dcache_active = 0; |
|
- | 122 | spinlock_lock(&dcachelock); |
|
- | 123 | spinlock_unlock(&dcachelock); |
|
- | 124 | ||
- | 125 | spinlock_lock(&CPU->lock); |
|
- | 126 | ASSERT(CPU->arch.dcache_message_count < DCACHE_MSG_QUEUE_LEN); |
|
- | 127 | for (i = 0; i < CPU->arch.dcache_message_count; i++) { |
|
- | 128 | switch (CPU->arch.dcache_messages[i].type) { |
|
- | 129 | case DCACHE_INVL_ALL: |
|
- | 130 | dcache_flush(); |
|
- | 131 | goto flushed; |
|
- | 132 | break; |
|
- | 133 | case DCACHE_INVL_COLOR: |
|
- | 134 | dcache_flush_color(CPU->arch.dcache_messages[i].color); |
|
- | 135 | break; |
|
- | 136 | case DCACHE_INVL_FRAME: |
|
- | 137 | dcache_flush_frame(CPU->arch.dcache_messages[i].color, |
|
- | 138 | CPU->arch.dcache_messages[i].frame); |
|
- | 139 | break; |
|
- | 140 | default: |
|
- | 141 | panic("unknown type (%d)\n", |
|
- | 142 | CPU->arch.dcache_messages[i].type); |
|
- | 143 | } |
|
- | 144 | } |
|
- | 145 | flushed: |
|
- | 146 | CPU->arch.dcache_message_count = 0; |
|
- | 147 | spinlock_unlock(&CPU->lock); |
|
- | 148 | ||
- | 149 | CPU->arch.dcache_active = 1; |
|
- | 150 | } |
|
- | 151 | ||
- | 152 | #endif /* CONFIG_VIRT_IDX_DCACHE */ |
|
- | 153 | #endif /* CONFIG_SMP */ |
|
- | 154 | ||
38 | /** @} |
155 | /** @} |
39 | */ |
156 | */ |
40 | 157 |