Changeset 454f1da in mainline
- Timestamp:
- 2007-03-26T19:35:28Z (18 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 5d7daff
- Parents:
- 4638401
- Location:
- kernel
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/sparc64/include/cpu.h
r4638401 r454f1da 40 40 #include <arch/asm.h> 41 41 42 #ifdef CONFIG_SMP 43 #include <arch/mm/cache.h> 44 #endif 45 42 46 #define MANUF_FUJITSU 0x04 43 47 #define MANUF_ULTRASPARC 0x17 /**< UltraSPARC I, UltraSPARC II */ … … 54 58 55 59 typedef struct { 56 uint32_t mid; /**< Processor ID as read from UPA_CONFIG. */ 60 uint32_t mid; /**< Processor ID as read from 61 UPA_CONFIG. */ 57 62 ver_reg_t ver; 58 63 uint32_t clock_frequency; /**< Processor frequency in Hz. */ 59 64 uint64_t next_tick_cmpr; /**< Next clock interrupt should be 60 generated when the TICK register 61 matches this value. */ 65 generated when the TICK register 66 matches this value. */ 67 #ifdef CONFIG_SMP 68 int dcache_active; 69 dcache_shootdown_msg_t dcache_messages[DCACHE_MSG_QUEUE_LEN]; 70 count_t dcache_message_count; 71 #endif 62 72 } cpu_arch_t; 63 73 -
kernel/arch/sparc64/include/interrupt.h
r4638401 r454f1da 47 47 48 48 enum { 49 IPI_TLB_SHOOTDOWN = VECTOR_TLB_SHOOTDOWN_IPI 49 IPI_TLB_SHOOTDOWN = VECTOR_TLB_SHOOTDOWN_IPI, 50 IPI_DCACHE_SHOOTDOWN 50 51 }; 51 52 -
kernel/arch/sparc64/include/mm/cache.h
r4638401 r454f1da 44 44 dcache_flush_tag(PAGE_COLOR((p)), ADDR2PFN((f))); 45 45 46 /** 47 * Enumerations to differentiate among different scopes of D-Cache 48 * invalidation. 49 */ 50 typedef enum { 51 DCACHE_INVL_INVALID, 52 DCACHE_INVL_ALL, 53 DCACHE_INVL_COLOR, 54 DCACHE_INVL_FRAME 55 } dcache_invalidate_type_t; 56 57 /** 58 * Number of messages that can be queued in the cpu_arch_t structure at a time. 59 */ 60 #define DCACHE_MSG_QUEUE_LEN 10 61 62 /** D-cache shootdown message type. */ 63 typedef struct { 64 dcache_invalidate_type_t type; 65 int color; 66 uintptr_t frame; 67 } dcache_shootdown_msg_t; 68 46 69 extern void dcache_flush(void); 47 70 extern void dcache_flush_color(int c); 48 71 extern void dcache_flush_tag(int c, pfn_t tag); 72 73 #ifdef CONFIG_SMP 74 extern void dcache_shootdown_start(dcache_invalidate_type_t type, int color, 75 uintptr_t frame); 76 extern void dcache_shootdown_finalize(void); 77 extern void dcache_shootdown_ipi_recv(void); 78 #else 79 #define dcache_shootdown_start(t, c, f) 80 #define dcache_shootdown_finalize() 81 #define dcache_shootdown_ipi_recv() 82 #endif /* CONFIG_SMP */ 49 83 50 84 #endif -
kernel/arch/sparc64/src/cpu/cpu.c
r4638401 r454f1da 52 52 CPU->arch.mid = upa_config.mid; 53 53 54 #if (defined(CONFIG_SMP) && defined(CONFIG_VIRT_IDX_DCACHE)) 55 CPU->arch.dcache_active = 1; 56 CPU->arch.dcache_message_count = 0; 57 #endif 58 54 59 /* 55 60 * Detect processor frequency. -
kernel/arch/sparc64/src/mm/cache.c
r4638401 r454f1da 32 32 /** 33 33 * @file 34 * @brief D-cache shootdown algorithm. 34 35 */ 35 36 36 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 */ -
kernel/arch/sparc64/src/mm/tlb.c
r4638401 r454f1da 483 483 484 484 for (i = 0; i < cnt; i++) { 485 itlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_PRIMARY, page + i *486 487 dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_PRIMARY, page + i *488 485 itlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_PRIMARY, 486 page + i * PAGE_SIZE); 487 dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_PRIMARY, 488 page + i * PAGE_SIZE); 489 489 } 490 490 -
kernel/arch/sparc64/src/smp/ipi.c
r4638401 r454f1da 40 40 #include <config.h> 41 41 #include <mm/tlb.h> 42 #include <arch/mm/cache.h> 42 43 #include <arch/interrupt.h> 43 44 #include <arch/trap/interrupt.h> … … 79 80 asi_u64_write(ASI_UDB_INTR_W, ASI_UDB_INTR_W_DATA_1, 0); 80 81 asi_u64_write(ASI_UDB_INTR_W, ASI_UDB_INTR_W_DATA_2, 0); 81 asi_u64_write(ASI_UDB_INTR_W, (mid <<82 INTR_VEC_DISPATCH_MID_SHIFT) | ASI_UDB_INTR_W_DISPATCH,83 82 asi_u64_write(ASI_UDB_INTR_W, 83 (mid << INTR_VEC_DISPATCH_MID_SHIFT) | 84 ASI_UDB_INTR_W_DISPATCH, 0); 84 85 85 86 membar(); … … 125 126 func = tlb_shootdown_ipi_recv; 126 127 break; 128 #if (defined(CONFIG_SMP) && (defined(CONFIG_VIRT_IDX_DCACHE))) 129 case IPI_DCACHE_SHOOTDOWN: 130 func = dcache_shootdown_ipi_recv; 131 break; 132 #endif 127 133 default: 128 134 panic("Unknown IPI (%d).\n", ipi); -
kernel/arch/sparc64/src/trap/interrupt.c
r4638401 r454f1da 45 45 #include <arch.h> 46 46 #include <mm/tlb.h> 47 #include <arch/mm/cache.h> 47 48 #include <config.h> 48 49 #include <synch/spinlock.h> … … 84 85 /* 85 86 * This is a cross-call. 86 * data0 contains address of kernel function.87 * data0 contains address of the kernel function. 87 88 * We call the function only after we verify 88 * it is on of the supported ones.89 * it is one of the supported ones. 89 90 */ 90 91 #ifdef CONFIG_SMP 91 92 if (data0 == (uintptr_t) tlb_shootdown_ipi_recv) { 92 93 tlb_shootdown_ipi_recv(); 94 #ifdef CONFIG_VIRT_IDX_DCACHE 95 } else if (data0 == (uintptr_t) dcache_shootdown_ipi_recv) { 96 dcache_shootdown_ipi_recv(); 97 #endif 93 98 } 94 99 #endif -
kernel/generic/src/mm/backend_anon.c
r4638401 r454f1da 79 79 { 80 80 uintptr_t frame; 81 bool dirty = false; 81 82 82 83 if (!as_area_check_access(area, access)) … … 95 96 mutex_lock(&area->sh_info->lock); 96 97 frame = (uintptr_t) btree_search(&area->sh_info->pagemap, 97 98 ALIGN_DOWN(addr, PAGE_SIZE) - area->base, &leaf); 98 99 if (!frame) { 99 100 bool allocate = true; … … 114 115 frame = (uintptr_t) frame_alloc(ONE_FRAME, 0); 115 116 memsetb(PA2KA(frame), FRAME_SIZE, 0); 117 dirty = true; 116 118 117 119 /* … … 144 146 frame = (uintptr_t) frame_alloc(ONE_FRAME, 0); 145 147 memsetb(PA2KA(frame), FRAME_SIZE, 0); 148 dirty = true; 146 149 } 147 150 … … 155 158 panic("Could not insert used space.\n"); 156 159 160 #ifdef CONFIG_VIRT_IDX_DCACHE 161 if (dirty && PAGE_COLOR(PA2KA(frame)) != PAGE_COLOR(addr)) { 162 /* 163 * By writing to the frame using kernel virtual address, 164 * we have created an illegal virtual alias. We now have to 165 * invalidate cachelines belonging to addr on all processors 166 * so that they will be reloaded with the new content on next 167 * read. 168 */ 169 dcache_flush_frame(addr, frame); 170 dcache_shootdown_start(DCACHE_INVL_FRAME, PAGE_COLOR(addr), frame); 171 dcache_shootdown_finalize(); 172 } 173 #endif 174 157 175 return AS_PF_OK; 158 176 } … … 169 187 { 170 188 frame_free(frame); 171 #ifdef CONFIG_VIRT_IDX_DCACHE172 dcache_flush_frame(page, frame);173 #endif174 189 } 175 190 … … 218 233 frame_reference_add(pfn); 219 234 } 220 235 221 236 } 222 237 } -
kernel/generic/src/mm/backend_elf.c
r4638401 r454f1da 82 82 uintptr_t base, frame; 83 83 index_t i; 84 bool dirty = false; 84 85 85 86 if (!as_area_check_access(area, access)) … … 148 149 memcpy((void *) PA2KA(frame), 149 150 (void *) (base + i * FRAME_SIZE), FRAME_SIZE); 150 151 dirty = true; 152 151 153 if (area->sh_info) { 152 154 frame_reference_add(ADDR2PFN(frame)); … … 169 171 frame = (uintptr_t)frame_alloc(ONE_FRAME, 0); 170 172 memsetb(PA2KA(frame), FRAME_SIZE, 0); 173 dirty = true; 171 174 172 175 if (area->sh_info) { … … 189 192 memcpy((void *) PA2KA(frame), (void *) (base + i * FRAME_SIZE), 190 193 size); 194 dirty = true; 191 195 192 196 if (area->sh_info) { … … 205 209 if (!used_space_insert(area, ALIGN_DOWN(addr, PAGE_SIZE), 1)) 206 210 panic("Could not insert used space.\n"); 211 212 #ifdef CONFIG_VIRT_IDX_DCACHE 213 if (dirty && PAGE_COLOR(PA2KA(frame)) != PAGE_COLOR(addr)) { 214 /* 215 * By writing to the frame using kernel virtual address, 216 * we have created an illegal virtual alias. We now have to 217 * invalidate cachelines belonging to addr on all processors 218 * so that they will be reloaded with the new content on next 219 * read. 220 */ 221 dcache_flush_frame(addr, frame); 222 dcache_shootdown_start(DCACHE_INVL_FRAME, PAGE_COLOR(addr), frame); 223 dcache_shootdown_finalize(); 224 } 225 #endif 207 226 208 227 return AS_PF_OK; … … 239 258 */ 240 259 frame_free(frame); 241 #ifdef CONFIG_VIRT_IDX_DCACHE242 dcache_flush_frame(page, frame);243 #endif244 260 } 245 261 } else { … … 248 264 * lower part is backed by the ELF image and the upper is 249 265 * anonymous). In any case, a frame needs to be freed. 250 */ 251 frame_free(frame); 252 #ifdef CONFIG_VIRT_IDX_DCACHE 253 dcache_flush_frame(page, frame); 254 #endif 266 */ 267 frame_free(frame); 255 268 } 256 269 }
Note:
See TracChangeset
for help on using the changeset viewer.