Changeset 965dc18 in mainline for kernel/arch/sparc64/src
- Timestamp:
- 2008-12-05T19:59:03Z (17 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 49093a4
- Parents:
- 0258e67
- Location:
- kernel/arch/sparc64/src
- Files:
-
- 1 added
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/sparc64/src/console.c
r0258e67 r965dc18 39 39 #include <arch/drivers/kbd.h> 40 40 41 #include <arch/drivers/sgcn.h> 42 41 43 #ifdef CONFIG_Z8530 42 44 #include <genarch/kbd/z8530.h> … … 55 57 #include <arch.h> 56 58 #include <panic.h> 59 #include <func.h> 57 60 #include <print.h> 58 61 59 62 #define KEYBOARD_POLL_PAUSE 50000 /* 50ms */ 60 63 61 /** Initialize kernel console to use framebuffer and keyboard directly. */ 62 void standalone_sparc64_console_init(void) 64 /** 65 * Initialize kernel console to use framebuffer and keyboard directly. 66 * Called on UltraSPARC machines with standard keyboard and framebuffer. 67 * 68 * @param aliases the "/aliases" OBP node 69 */ 70 static void standard_console_init(ofw_tree_node_t *aliases) 63 71 { 64 72 stdin = NULL; 65 73 66 ofw_tree_node_t *aliases;67 74 ofw_tree_property_t *prop; 68 75 ofw_tree_node_t *screen; 69 76 ofw_tree_node_t *keyboard; 70 71 aliases = ofw_tree_lookup("/aliases");72 if (!aliases)73 panic("Can't find /aliases.\n");74 77 75 78 prop = ofw_tree_getprop(aliases, "screen"); … … 96 99 } 97 100 101 /** Initilize I/O on the Serengeti machine. */ 102 static void serengeti_init(void) 103 { 104 sgcn_init(); 105 } 106 107 /** 108 * Initialize input/output. Auto-detects the type of machine 109 * and calls the appropriate I/O init routine. 110 */ 111 void standalone_sparc64_console_init(void) 112 { 113 ofw_tree_node_t *aliases; 114 ofw_tree_property_t *prop; 115 116 aliases = ofw_tree_lookup("/aliases"); 117 if (!aliases) 118 panic("Can't find /aliases.\n"); 119 120 /* "def-cn" = "default console" */ 121 prop = ofw_tree_getprop(aliases, "def-cn"); 122 123 if ((!prop) || (!prop->value) || (strcmp(prop->value, "/sgcn") != 0)) { 124 standard_console_init(aliases); 125 } else { 126 serengeti_init(); 127 } 128 } 129 130 98 131 /** Kernel thread for polling keyboard. 99 132 * … … 130 163 #endif 131 164 #endif 165 #ifdef CONFIG_SGCN 166 if (kbd_type == KBD_SGCN) 167 sgcn_poll(); 168 #endif 132 169 thread_usleep(KEYBOARD_POLL_PAUSE); 133 170 } … … 150 187 break; 151 188 #endif 189 #ifdef CONFIG_SGCN 190 case KBD_SGCN: 191 sgcn_grab(); 192 break; 193 #endif 152 194 default: 153 195 break; … … 171 213 break; 172 214 #endif 215 #ifdef CONFIG_SGCN 216 case KBD_SGCN: 217 sgcn_release(); 218 break; 219 #endif 173 220 default: 174 221 break; -
kernel/arch/sparc64/src/cpu/cpu.c
r0258e67 r965dc18 33 33 */ 34 34 35 #include <arch/cpu_family.h> 35 36 #include <cpu.h> 36 37 #include <arch.h> … … 38 39 #include <arch/drivers/tick.h> 39 40 #include <print.h> 41 #include <arch/cpu_node.h> 42 43 /** 44 * Finds out the clock frequency of the current CPU. 45 * 46 * @param node node representing the current CPU in the OFW tree 47 * @return clock frequency if "node" is the current CPU and no error 48 * occurs, -1 if "node" is not the current CPU or on error 49 */ 50 static int find_cpu_frequency(ofw_tree_node_t *node) 51 { 52 ofw_tree_property_t *prop; 53 uint32_t mid; 54 55 /* 'upa-portid' for US, 'portid' for US-III, 'cpuid' for US-IV */ 56 prop = ofw_tree_getprop(node, "upa-portid"); 57 if ((!prop) || (!prop->value)) 58 prop = ofw_tree_getprop(node, "portid"); 59 if ((!prop) || (!prop->value)) 60 prop = ofw_tree_getprop(node, "cpuid"); 61 62 if (prop && prop->value) { 63 mid = *((uint32_t *) prop->value); 64 if (mid == CPU->arch.mid) { 65 prop = ofw_tree_getprop(node, "clock-frequency"); 66 if (prop && prop->value) { 67 return *((uint32_t *) prop->value); 68 } 69 } 70 } 71 72 return -1; 73 } 40 74 41 75 /** Perform sparc64 specific initialization of the processor structure for the … … 45 79 { 46 80 ofw_tree_node_t *node; 47 uint32_t mid;48 81 uint32_t clock_frequency = 0; 49 upa_config_t upa_config;50 82 51 upa_config.value = upa_config_read(); 52 CPU->arch.mid = upa_config.mid; 83 CPU->arch.mid = read_mid(); 53 84 54 85 /* 55 86 * Detect processor frequency. 56 87 */ 57 node = ofw_tree_find_child_by_device_type(ofw_tree_lookup("/"), "cpu"); 58 while (node) { 59 ofw_tree_property_t *prop; 88 if (is_us() || is_us_iii()) { 89 node = ofw_tree_find_child_by_device_type(cpus_parent(), "cpu"); 90 while (node) { 91 int f = find_cpu_frequency(node); 92 if (f != -1) 93 clock_frequency = (uint32_t) f; 94 node = ofw_tree_find_peer_by_device_type(node, "cpu"); 95 } 96 } else if (is_us_iv()) { 97 node = ofw_tree_find_child(cpus_parent(), "cmp"); 98 while (node) { 99 int f; 100 f = find_cpu_frequency( 101 ofw_tree_find_child(node, "cpu@0")); 102 if (f != -1) 103 clock_frequency = (uint32_t) f; 104 f = find_cpu_frequency( 105 ofw_tree_find_child(node, "cpu@1")); 106 if (f != -1) 107 clock_frequency = (uint32_t) f; 108 node = ofw_tree_find_peer_by_name(node, "cmp"); 109 } 110 } 60 111 61 prop = ofw_tree_getprop(node, "upa-portid");62 if (prop && prop->value) {63 mid = *((uint32_t *) prop->value);64 if (mid == CPU->arch.mid) {65 prop = ofw_tree_getprop(node,66 "clock-frequency");67 if (prop && prop->value)68 clock_frequency = *((uint32_t *)69 prop->value);70 }71 }72 node = ofw_tree_find_peer_by_device_type(node, "cpu");73 }74 75 112 CPU->arch.clock_frequency = clock_frequency; 76 113 tick_init(); … … 125 162 impl = "UltraSPARC III"; 126 163 break; 164 case IMPL_ULTRASPARCIII_PLUS: 165 impl = "UltraSPARC III+"; 166 break; 167 case IMPL_ULTRASPARCIII_I: 168 impl = "UltraSPARC IIIi"; 169 break; 170 case IMPL_ULTRASPARCIV: 171 impl = "UltraSPARC IV"; 172 break; 127 173 case IMPL_ULTRASPARCIV_PLUS: 128 174 impl = "UltraSPARC IV+"; -
kernel/arch/sparc64/src/ddi/ddi.c
r0258e67 r965dc18 42 42 * 43 43 * @param task Task. 44 * @param ioaddr Starti gnI/O space address.44 * @param ioaddr Starting I/O space address. 45 45 * @param size Size of the enabled I/O range. 46 46 * -
kernel/arch/sparc64/src/drivers/scr.c
r0258e67 r965dc18 56 56 { 57 57 ofw_tree_property_t *prop; 58 ofw_pci_reg_t *pci_reg; 59 ofw_pci_reg_t pci_abs_reg; 60 ofw_upa_reg_t *upa_reg; 61 ofw_sbus_reg_t *sbus_reg; 58 62 const char *name; 59 63 … … 62 66 if (strcmp(name, "SUNW,m64B") == 0) 63 67 scr_type = SCR_ATYFB; 68 else if (strcmp(name, "SUNW,XVR-100") == 0) 69 scr_type = SCR_XVR; 64 70 else if (strcmp(name, "SUNW,ffb") == 0) 65 71 scr_type = SCR_FFB; … … 68 74 69 75 if (scr_type == SCR_UNKNOWN) { 70 printf("Unknown keyboarddevice.\n");76 printf("Unknown screen device.\n"); 71 77 return; 72 78 } … … 107 113 } 108 114 109 ofw_pci_reg_t *fb_reg = &((ofw_pci_reg_t *) prop->value)[1]; 110 ofw_pci_reg_t abs_reg; 111 112 if (!ofw_pci_reg_absolutize(node, fb_reg, &abs_reg)) { 115 pci_reg = &((ofw_pci_reg_t *) prop->value)[1]; 116 117 if (!ofw_pci_reg_absolutize(node, pci_reg, &pci_abs_reg)) { 113 118 printf("Failed to absolutize fb register.\n"); 114 119 return; 115 120 } 116 121 117 if (!ofw_pci_apply_ranges(node->parent, &abs_reg , &fb_addr)) { 122 if (!ofw_pci_apply_ranges(node->parent, &pci_abs_reg, 123 &fb_addr)) { 118 124 printf("Failed to determine screen address.\n"); 119 125 return; … … 143 149 144 150 break; 151 case SCR_XVR: 152 if (prop->size / sizeof(ofw_pci_reg_t) < 2) { 153 printf("Too few screen registers.\n"); 154 return; 155 } 156 157 pci_reg = &((ofw_pci_reg_t *) prop->value)[1]; 158 159 if (!ofw_pci_reg_absolutize(node, pci_reg, &pci_abs_reg)) { 160 printf("Failed to absolutize fb register.\n"); 161 return; 162 } 163 164 if (!ofw_pci_apply_ranges(node->parent, &pci_abs_reg, 165 &fb_addr)) { 166 printf("Failed to determine screen address.\n"); 167 return; 168 } 169 170 switch (fb_depth) { 171 case 8: 172 fb_scanline = fb_linebytes * (fb_depth >> 3); 173 visual = VISUAL_SB1500_PALETTE; 174 break; 175 case 16: 176 fb_scanline = fb_linebytes * (fb_depth >> 3); 177 visual = VISUAL_RGB_5_6_5; 178 break; 179 case 24: 180 fb_scanline = fb_linebytes * 4; 181 visual = VISUAL_RGB_8_8_8_0; 182 break; 183 case 32: 184 fb_scanline = fb_linebytes * (fb_depth >> 3); 185 visual = VISUAL_RGB_0_8_8_8; 186 break; 187 default: 188 printf("Unsupported bits per pixel.\n"); 189 return; 190 } 191 192 break; 145 193 case SCR_FFB: 146 194 fb_scanline = 8192; 147 195 visual = VISUAL_BGR_0_8_8_8; 148 196 149 ofw_upa_reg_t *reg = &((ofw_upa_reg_t *) prop->value)[FFB_REG_24BPP];150 if (!ofw_upa_apply_ranges(node->parent, reg, &fb_addr)) {197 upa_reg = &((ofw_upa_reg_t *) prop->value)[FFB_REG_24BPP]; 198 if (!ofw_upa_apply_ranges(node->parent, upa_reg, &fb_addr)) { 151 199 printf("Failed to determine screen address.\n"); 152 200 return; … … 165 213 } 166 214 167 ofw_sbus_reg_t *cg6_reg = &((ofw_sbus_reg_t *) prop->value)[0];168 if (!ofw_sbus_apply_ranges(node->parent, cg6_reg, &fb_addr)) {215 sbus_reg = &((ofw_sbus_reg_t *) prop->value)[0]; 216 if (!ofw_sbus_apply_ranges(node->parent, sbus_reg, &fb_addr)) { 169 217 printf("Failed to determine screen address.\n"); 170 218 return; … … 176 224 } 177 225 178 fb_init(fb_addr, fb_width, fb_height, fb_scanline, visual); 226 fb_properties_t props = { 227 .addr = fb_addr, 228 .offset = 0, 229 .x = fb_width, 230 .y = fb_height, 231 .scan = fb_scanline, 232 .visual = visual, 233 }; 234 fb_init(&props); 179 235 } 180 236 -
kernel/arch/sparc64/src/drivers/tick.c
r0258e67 r965dc18 46 46 #define TICK_RESTART_TIME 50 /* Worst case estimate. */ 47 47 48 /** Initialize tick interrupt. */48 /** Initialize tick and stick interrupt. */ 49 49 void tick_init(void) 50 50 { 51 /* initialize TICK interrupt */ 51 52 tick_compare_reg_t compare; 52 53 53 54 interrupt_register(14, "tick_int", tick_interrupt); 54 55 compare.int_dis = false; … … 57 58 tick_compare_write(compare.value); 58 59 tick_write(0); 60 61 #if defined (US3) 62 /* disable STICK interrupts and clear any pending ones */ 63 tick_compare_reg_t stick_compare; 64 softint_reg_t clear; 65 66 stick_compare.value = stick_compare_read(); 67 stick_compare.int_dis = true; 68 stick_compare.tick_cmpr = 0; 69 stick_compare_write(stick_compare.value); 70 71 clear.value = 0; 72 clear.stick_int = 1; 73 clear_softint_write(clear.value); 74 #endif 59 75 } 60 76 … … 68 84 softint_reg_t softint, clear; 69 85 uint64_t drift; 70 86 71 87 softint.value = softint_read(); 72 88 -
kernel/arch/sparc64/src/mm/as.c
r0258e67 r965dc18 165 165 tsb_base.base = ((uintptr_t) as->arch.dtsb) >> MMU_PAGE_WIDTH; 166 166 dtsb_base_write(tsb_base.value); 167 168 #if defined (US3) 169 /* 170 * Clear the extension registers. 171 * In HelenOS, primary and secondary context registers contain 172 * equal values and kernel misses (context 0, ie. the nucleus context) 173 * are excluded from the TSB miss handler, so it makes no sense 174 * to have separate TSBs for primary, secondary and nucleus contexts. 175 * Clearing the extension registers will ensure that the value of the 176 * TSB Base register will be used as an address of TSB, making the code 177 * compatible with the US port. 178 */ 179 itsb_primary_extension_write(0); 180 itsb_nucleus_extension_write(0); 181 dtsb_primary_extension_write(0); 182 dtsb_secondary_extension_write(0); 183 dtsb_nucleus_extension_write(0); 184 #endif 167 185 #endif 168 186 } -
kernel/arch/sparc64/src/mm/cache.S
r0258e67 r965dc18 48 48 ! beware SF Erratum #51, do not put the MEMBAR here 49 49 nop 50 51 /** Flush only D-cache lines of one virtual color.52 *53 * @param o0 Virtual color to be flushed.54 */55 .global dcache_flush_color56 dcache_flush_color:57 mov (DCACHE_SIZE / DCACHE_LINE_SIZE) / 2, %g158 set DCACHE_SIZE / 2, %g259 sllx %g2, %o0, %g260 sub %g2, DCACHE_LINE_SIZE, %g261 0: stxa %g0, [%g2] ASI_DCACHE_TAG62 membar #Sync63 subcc %g1, 1, %g164 bnz,pt %xcc, 0b65 sub %g2, DCACHE_LINE_SIZE, %g266 retl67 nop68 69 /** Flush only D-cache lines of one virtual color and one tag.70 *71 * @param o0 Virtual color to lookup the tag.72 * @param o1 Tag of the cachelines to be flushed.73 */74 .global dcache_flush_tag75 dcache_flush_tag:76 mov (DCACHE_SIZE / DCACHE_LINE_SIZE) / 2, %g177 set DCACHE_SIZE / 2, %g278 sllx %g2, %o0, %g279 sub %g2, DCACHE_LINE_SIZE, %g280 0: ldxa [%g2] ASI_DCACHE_TAG, %g381 srlx %g3, DCACHE_TAG_SHIFT, %g382 cmp %g3, %o183 bnz 1f84 nop85 stxa %g0, [%g2] ASI_DCACHE_TAG86 membar #Sync87 1: subcc %g1, 1, %g188 bnz,pt %xcc, 0b89 sub %g2, DCACHE_LINE_SIZE, %g290 retl91 nop -
kernel/arch/sparc64/src/mm/page.c
r0258e67 r965dc18 53 53 uintptr_t phys_page; 54 54 int pagesize_code; 55 } bsp_locked_dtlb_entry[DTLB_ ENTRY_COUNT];55 } bsp_locked_dtlb_entry[DTLB_MAX_LOCKED_ENTRIES]; 56 56 57 57 /** Number of entries in bsp_locked_dtlb_entry array. */ … … 167 167 /** @} 168 168 */ 169 -
kernel/arch/sparc64/src/mm/tlb.c
r0258e67 r965dc18 55 55 #endif 56 56 57 static void dtlb_pte_copy(pte_t *t, index_t index, bool ro); 58 static void itlb_pte_copy(pte_t *t, index_t index); 59 static void do_fast_instruction_access_mmu_miss_fault(istate_t *istate, 60 const char *str); 61 static void do_fast_data_access_mmu_miss_fault(istate_t *istate, 62 tlb_tag_access_reg_t tag, const char *str); 63 static void do_fast_data_access_protection_fault(istate_t *istate, 64 tlb_tag_access_reg_t tag, const char *str); 57 static void dtlb_pte_copy(pte_t *, index_t, bool); 58 static void itlb_pte_copy(pte_t *, index_t); 59 static void do_fast_instruction_access_mmu_miss_fault(istate_t *, const char *); 60 static void do_fast_data_access_mmu_miss_fault(istate_t *, tlb_tag_access_reg_t, 61 const char *); 62 static void do_fast_data_access_protection_fault(istate_t *, 63 tlb_tag_access_reg_t, const char *); 65 64 66 65 char *context_encoding[] = { … … 87 86 /** Insert privileged mapping into DMMU TLB. 88 87 * 89 * @param page 90 * @param frame 91 * @param pagesize 92 * @param locked 93 * @param cacheable 88 * @param page Virtual page address. 89 * @param frame Physical frame address. 90 * @param pagesize Page size. 91 * @param locked True for permanent mappings, false otherwise. 92 * @param cacheable True if the mapping is cacheable, false otherwise. 94 93 */ 95 94 void dtlb_insert_mapping(uintptr_t page, uintptr_t frame, int pagesize, … … 104 103 fr.address = frame; 105 104 106 tag. value= ASID_KERNEL;105 tag.context = ASID_KERNEL; 107 106 tag.vpn = pg.vpn; 108 107 … … 127 126 /** Copy PTE to TLB. 128 127 * 129 * @param t Page Table Entry to be copied.130 * @param index Zero if lower 8K-subpage, one if higher 8K-subpage.131 * @param ro If true, the entry will be created read-only, regardless of its132 * w field.128 * @param t Page Table Entry to be copied. 129 * @param index Zero if lower 8K-subpage, one if higher 8K-subpage. 130 * @param ro If true, the entry will be created read-only, regardless 131 * of its w field. 133 132 */ 134 133 void dtlb_pte_copy(pte_t *t, index_t index, bool ro) … … 166 165 /** Copy PTE to ITLB. 167 166 * 168 * @param t 169 * @param index Zero if lower 8K-subpage, one if higher 8K-subpage.167 * @param t Page Table Entry to be copied. 168 * @param index Zero if lower 8K-subpage, one if higher 8K-subpage. 170 169 */ 171 170 void itlb_pte_copy(pte_t *t, index_t index) … … 236 235 * low-level, assembly language part of the fast_data_access_mmu_miss handler. 237 236 * 238 * @param tag Content of the TLB Tag Access register as it existed when the 239 * trap happened. This is to prevent confusion created by clobbered 240 * Tag Access register during a nested DTLB miss. 241 * @param istate Interrupted state saved on the stack. 237 * @param tag Content of the TLB Tag Access register as it existed 238 * when the trap happened. This is to prevent confusion 239 * created by clobbered Tag Access register during a nested 240 * DTLB miss. 241 * @param istate Interrupted state saved on the stack. 242 242 */ 243 243 void fast_data_access_mmu_miss(tlb_tag_access_reg_t tag, istate_t *istate) … … 288 288 /** DTLB protection fault handler. 289 289 * 290 * @param tag Content of the TLB Tag Access register as it existed when the 291 * trap happened. This is to prevent confusion created by clobbered 292 * Tag Access register during a nested DTLB miss. 293 * @param istate Interrupted state saved on the stack. 290 * @param tag Content of the TLB Tag Access register as it existed 291 * when the trap happened. This is to prevent confusion 292 * created by clobbered Tag Access register during a nested 293 * DTLB miss. 294 * @param istate Interrupted state saved on the stack. 294 295 */ 295 296 void fast_data_access_protection(tlb_tag_access_reg_t tag, istate_t *istate) … … 332 333 } 333 334 335 /** Print TLB entry (for debugging purposes). 336 * 337 * The diag field has been left out in order to make this function more generic 338 * (there is no diag field in US3 architeture). 339 * 340 * @param i TLB entry number 341 * @param t TLB entry tag 342 * @param d TLB entry data 343 */ 344 static void print_tlb_entry(int i, tlb_tag_read_reg_t t, tlb_data_t d) 345 { 346 printf("%d: vpn=%#llx, context=%d, v=%d, size=%d, nfo=%d, " 347 "ie=%d, soft2=%#x, pfn=%#x, soft=%#x, l=%d, " 348 "cp=%d, cv=%d, e=%d, p=%d, w=%d, g=%d\n", i, t.vpn, 349 t.context, d.v, d.size, d.nfo, d.ie, d.soft2, 350 d.pfn, d.soft, d.l, d.cp, d.cv, d.e, d.p, d.w, d.g); 351 } 352 353 #if defined (US) 354 334 355 /** Print contents of both TLBs. */ 335 356 void tlb_print(void) … … 343 364 d.value = itlb_data_access_read(i); 344 365 t.value = itlb_tag_read_read(i); 345 346 printf("%d: vpn=%#llx, context=%d, v=%d, size=%d, nfo=%d, " 347 "ie=%d, soft2=%#x, diag=%#x, pfn=%#x, soft=%#x, l=%d, " 348 "cp=%d, cv=%d, e=%d, p=%d, w=%d, g=%d\n", i, t.vpn, 349 t.context, d.v, d.size, d.nfo, d.ie, d.soft2, d.diag, 350 d.pfn, d.soft, d.l, d.cp, d.cv, d.e, d.p, d.w, d.g); 366 print_tlb_entry(i, t, d); 351 367 } 352 368 … … 355 371 d.value = dtlb_data_access_read(i); 356 372 t.value = dtlb_tag_read_read(i); 357 358 printf("%d: vpn=%#llx, context=%d, v=%d, size=%d, nfo=%d, " 359 "ie=%d, soft2=%#x, diag=%#x, pfn=%#x, soft=%#x, l=%d, " 360 "cp=%d, cv=%d, e=%d, p=%d, w=%d, g=%d\n", i, t.vpn, 361 t.context, d.v, d.size, d.nfo, d.ie, d.soft2, d.diag, 362 d.pfn, d.soft, d.l, d.cp, d.cv, d.e, d.p, d.w, d.g); 363 } 364 365 } 373 print_tlb_entry(i, t, d); 374 } 375 } 376 377 #elif defined (US3) 378 379 /** Print contents of all TLBs. */ 380 void tlb_print(void) 381 { 382 int i; 383 tlb_data_t d; 384 tlb_tag_read_reg_t t; 385 386 printf("TLB_ISMALL contents:\n"); 387 for (i = 0; i < tlb_ismall_size(); i++) { 388 d.value = dtlb_data_access_read(TLB_ISMALL, i); 389 t.value = dtlb_tag_read_read(TLB_ISMALL, i); 390 print_tlb_entry(i, t, d); 391 } 392 393 printf("TLB_IBIG contents:\n"); 394 for (i = 0; i < tlb_ibig_size(); i++) { 395 d.value = dtlb_data_access_read(TLB_IBIG, i); 396 t.value = dtlb_tag_read_read(TLB_IBIG, i); 397 print_tlb_entry(i, t, d); 398 } 399 400 printf("TLB_DSMALL contents:\n"); 401 for (i = 0; i < tlb_dsmall_size(); i++) { 402 d.value = dtlb_data_access_read(TLB_DSMALL, i); 403 t.value = dtlb_tag_read_read(TLB_DSMALL, i); 404 print_tlb_entry(i, t, d); 405 } 406 407 printf("TLB_DBIG_1 contents:\n"); 408 for (i = 0; i < tlb_dbig_size(); i++) { 409 d.value = dtlb_data_access_read(TLB_DBIG_0, i); 410 t.value = dtlb_tag_read_read(TLB_DBIG_0, i); 411 print_tlb_entry(i, t, d); 412 } 413 414 printf("TLB_DBIG_2 contents:\n"); 415 for (i = 0; i < tlb_dbig_size(); i++) { 416 d.value = dtlb_data_access_read(TLB_DBIG_1, i); 417 t.value = dtlb_tag_read_read(TLB_DBIG_1, i); 418 print_tlb_entry(i, t, d); 419 } 420 } 421 422 #endif 366 423 367 424 void do_fast_instruction_access_mmu_miss_fault(istate_t *istate, … … 412 469 sfar = dtlb_sfar_read(); 413 470 471 #if defined (US) 414 472 printf("DTLB SFSR: asi=%#x, ft=%#x, e=%d, ct=%d, pr=%d, w=%d, ow=%d, " 415 473 "fv=%d\n", sfsr.asi, sfsr.ft, sfsr.e, sfsr.ct, sfsr.pr, sfsr.w, 416 474 sfsr.ow, sfsr.fv); 475 #elif defined (US3) 476 printf("DTLB SFSR: nf=%d, asi=%#x, tm=%d, ft=%#x, e=%d, ct=%d, pr=%d, " 477 "w=%d, ow=%d, fv=%d\n", sfsr.nf, sfsr.asi, sfsr.tm, sfsr.ft, 478 sfsr.e, sfsr.ct, sfsr.pr, sfsr.w, sfsr.ow, sfsr.fv); 479 #endif 480 417 481 printf("DTLB SFAR: address=%p\n", sfar); 418 482 419 483 dtlb_sfsr_write(0); 420 484 } 485 486 #if defined (US3) 487 /** Invalidates given TLB entry if and only if it is non-locked or global. 488 * 489 * @param tlb TLB number (one of TLB_DSMALL, TLB_DBIG_0, TLB_DBIG_1, 490 * TLB_ISMALL, TLB_IBIG). 491 * @param entry Entry index within the given TLB. 492 */ 493 static void tlb_invalidate_entry(int tlb, index_t entry) 494 { 495 tlb_data_t d; 496 tlb_tag_read_reg_t t; 497 498 if (tlb == TLB_DSMALL || tlb == TLB_DBIG_0 || tlb == TLB_DBIG_1) { 499 d.value = dtlb_data_access_read(tlb, entry); 500 if (!d.l || d.g) { 501 t.value = dtlb_tag_read_read(tlb, entry); 502 d.v = false; 503 dtlb_tag_access_write(t.value); 504 dtlb_data_access_write(tlb, entry, d.value); 505 } 506 } else if (tlb == TLB_ISMALL || tlb == TLB_IBIG) { 507 d.value = itlb_data_access_read(tlb, entry); 508 if (!d.l || d.g) { 509 t.value = itlb_tag_read_read(tlb, entry); 510 d.v = false; 511 itlb_tag_access_write(t.value); 512 itlb_data_access_write(tlb, entry, d.value); 513 } 514 } 515 } 516 #endif 421 517 422 518 /** Invalidate all unlocked ITLB and DTLB entries. */ … … 424 520 { 425 521 int i; 426 tlb_data_t d; 427 tlb_tag_read_reg_t t; 428 522 429 523 /* 430 524 * Walk all ITLB and DTLB entries and remove all unlocked mappings. 431 525 * 432 526 * The kernel doesn't use global mappings so any locked global mappings 433 * found 527 * found must have been created by someone else. Their only purpose now 434 528 * is to collide with proper mappings. Invalidate immediately. It should 435 529 * be safe to invalidate them as late as now. 436 530 */ 531 532 #if defined (US) 533 tlb_data_t d; 534 tlb_tag_read_reg_t t; 437 535 438 536 for (i = 0; i < ITLB_ENTRY_COUNT; i++) { … … 445 543 } 446 544 } 447 545 448 546 for (i = 0; i < DTLB_ENTRY_COUNT; i++) { 449 547 d.value = dtlb_data_access_read(i); … … 455 553 } 456 554 } 457 555 556 #elif defined (US3) 557 558 for (i = 0; i < tlb_ismall_size(); i++) 559 tlb_invalidate_entry(TLB_ISMALL, i); 560 for (i = 0; i < tlb_ibig_size(); i++) 561 tlb_invalidate_entry(TLB_IBIG, i); 562 for (i = 0; i < tlb_dsmall_size(); i++) 563 tlb_invalidate_entry(TLB_DSMALL, i); 564 for (i = 0; i < tlb_dbig_size(); i++) 565 tlb_invalidate_entry(TLB_DBIG_0, i); 566 for (i = 0; i < tlb_dbig_size(); i++) 567 tlb_invalidate_entry(TLB_DBIG_1, i); 568 #endif 569 458 570 } 459 571 … … 485 597 * address space. 486 598 * 487 * @param asid 488 * @param page 489 * @param cnt 599 * @param asid Address Space ID. 600 * @param page First page which to sweep out from ITLB and DTLB. 601 * @param cnt Number of ITLB and DTLB entries to invalidate. 490 602 */ 491 603 void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt) -
kernel/arch/sparc64/src/mm/tsb.c
r0258e67 r965dc18 113 113 tsb->data.size = PAGESIZE_8K; 114 114 tsb->data.pfn = (t->frame >> MMU_FRAME_WIDTH) + index; 115 tsb->data.cp = t->c; 116 tsb->data.p = t->k; /* p as privileged*/117 tsb->data.v = t->p; 115 tsb->data.cp = t->c; /* cp as cache in phys.-idxed, c as cacheable */ 116 tsb->data.p = t->k; /* p as privileged, k as kernel */ 117 tsb->data.v = t->p; /* v as valid, p as present */ 118 118 119 119 write_barrier(); … … 174 174 /** @} 175 175 */ 176 -
kernel/arch/sparc64/src/smp/ipi.c
r0258e67 r965dc18 47 47 #include <panic.h> 48 48 49 /** Set the contents of the outgoing interrupt vector data. 50 * 51 * The first data item (data 0) will be set to the value of func, the 52 * rest of the vector will contain zeros. 53 * 54 * This is a helper function used from within the cross_call function. 55 * 56 * @param func value the first data item of the vector will be set to 57 */ 58 static inline void set_intr_w_data(void (* func)(void)) 59 { 60 #if defined (US) 61 asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_0, (uintptr_t) func); 62 asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_1, 0); 63 asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_2, 0); 64 #elif defined (US3) 65 asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_0, (uintptr_t) func); 66 asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_1, 0); 67 asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_2, 0); 68 asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_3, 0); 69 asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_4, 0); 70 asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_5, 0); 71 asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_6, 0); 72 asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_7, 0); 73 #endif 74 } 75 49 76 /** Invoke function on another processor. 50 77 * … … 74 101 panic("Interrupt Dispatch Status busy bit set\n"); 75 102 103 ASSERT(!(pstate_read() & PSTATE_IE_BIT)); 104 76 105 do { 77 asi_u64_write(ASI_UDB_INTR_W, ASI_UDB_INTR_W_DATA_0, 78 (uintptr_t) func); 79 asi_u64_write(ASI_UDB_INTR_W, ASI_UDB_INTR_W_DATA_1, 0); 80 asi_u64_write(ASI_UDB_INTR_W, ASI_UDB_INTR_W_DATA_2, 0); 81 asi_u64_write(ASI_UDB_INTR_W, 106 set_intr_w_data(func); 107 asi_u64_write(ASI_INTR_W, 82 108 (mid << INTR_VEC_DISPATCH_MID_SHIFT) | 83 ASI_UDB_INTR_W_DISPATCH, 0);109 VA_INTR_W_DISPATCH, 0); 84 110 85 111 membar(); -
kernel/arch/sparc64/src/smp/smp.c
r0258e67 r965dc18 36 36 #include <genarch/ofw/ofw_tree.h> 37 37 #include <cpu.h> 38 #include <arch/cpu_family.h> 38 39 #include <arch/cpu.h> 39 40 #include <arch.h> … … 44 45 #include <synch/waitq.h> 45 46 #include <print.h> 47 #include <arch/cpu_node.h> 46 48 47 49 /** … … 62 64 count_t cnt = 0; 63 65 64 node = ofw_tree_find_child_by_device_type(ofw_tree_lookup("/"), "cpu"); 65 while (node) { 66 cnt++; 67 node = ofw_tree_find_peer_by_device_type(node, "cpu"); 66 if (is_us() || is_us_iii()) { 67 node = ofw_tree_find_child_by_device_type(cpus_parent(), "cpu"); 68 while (node) { 69 cnt++; 70 node = ofw_tree_find_peer_by_device_type(node, "cpu"); 71 } 72 } else if (is_us_iv()) { 73 node = ofw_tree_find_child(cpus_parent(), "cmp"); 74 while (node) { 75 cnt += 2; 76 node = ofw_tree_find_peer_by_name(node, "cmp"); 77 } 68 78 } 69 79 70 80 config.cpu_count = max(1, cnt); 81 } 82 83 /** 84 * Wakes up the CPU which is represented by the "node" OFW tree node. 85 * If "node" represents the current CPU, calling the function has 86 * no effect. 87 */ 88 static void wakeup_cpu(ofw_tree_node_t *node) 89 { 90 uint32_t mid; 91 ofw_tree_property_t *prop; 92 93 /* 'upa-portid' for US, 'portid' for US-III, 'cpuid' for US-IV */ 94 prop = ofw_tree_getprop(node, "upa-portid"); 95 if ((!prop) || (!prop->value)) 96 prop = ofw_tree_getprop(node, "portid"); 97 if ((!prop) || (!prop->value)) 98 prop = ofw_tree_getprop(node, "cpuid"); 99 100 if (!prop || prop->value == NULL) 101 return; 102 103 mid = *((uint32_t *) prop->value); 104 if (CPU->arch.mid == mid) 105 return; 106 107 waking_up_mid = mid; 108 109 if (waitq_sleep_timeout(&ap_completion_wq, 1000000, SYNCH_FLAGS_NONE) == 110 ESYNCH_TIMEOUT) 111 printf("%s: waiting for processor (mid = %" PRIu32 112 ") timed out\n", __func__, mid); 71 113 } 72 114 … … 77 119 int i; 78 120 79 node = ofw_tree_find_child_by_device_type(ofw_tree_lookup("/"), "cpu"); 80 for (i = 0; node; node = ofw_tree_find_peer_by_device_type(node, "cpu"), i++) { 81 uint32_t mid; 82 ofw_tree_property_t *prop; 83 84 prop = ofw_tree_getprop(node, "upa-portid"); 85 if (!prop || !prop->value) 86 continue; 87 88 mid = *((uint32_t *) prop->value); 89 if (CPU->arch.mid == mid) { 90 /* 91 * Skip the current CPU. 92 */ 93 continue; 121 if (is_us() || is_us_iii()) { 122 node = ofw_tree_find_child_by_device_type(cpus_parent(), "cpu"); 123 for (i = 0; node; 124 node = ofw_tree_find_peer_by_device_type(node, "cpu"), i++) 125 wakeup_cpu(node); 126 } else if (is_us_iv()) { 127 node = ofw_tree_find_child(cpus_parent(), "cmp"); 128 while (node) { 129 wakeup_cpu(ofw_tree_find_child(node, "cpu@0")); 130 wakeup_cpu(ofw_tree_find_child(node, "cpu@1")); 131 node = ofw_tree_find_peer_by_name(node, "cmp"); 94 132 } 95 96 /*97 * Processor with ID == mid can proceed with its initialization.98 */99 waking_up_mid = mid;100 101 if (waitq_sleep_timeout(&ap_completion_wq, 1000000, SYNCH_FLAGS_NONE) == ESYNCH_TIMEOUT)102 printf("%s: waiting for processor (mid = %" PRIu32 ") timed out\n",103 __func__, mid);104 133 } 105 134 } -
kernel/arch/sparc64/src/sparc64.c
r0258e67 r965dc18 87 87 */ 88 88 irq_init(1 << 11, 128); 89 89 90 90 standalone_sparc64_console_init(); 91 91 } -
kernel/arch/sparc64/src/start.S
r0258e67 r965dc18 28 28 29 29 #include <arch/arch.h> 30 #include <arch/cpu.h> 30 31 #include <arch/regdef.h> 31 32 #include <arch/boot/boot.h> … … 46 47 47 48 #define BSP_FLAG 1 49 50 /* 51 * 2^PHYSMEM_ADDR_SIZE is the size of the physical address space on 52 * a given processor. 53 */ 54 #if defined (US) 55 #define PHYSMEM_ADDR_SIZE 41 56 #elif defined (US3) 57 #define PHYSMEM_ADDR_SIZE 43 58 #endif 48 59 49 60 /* … … 68 79 andn %o0, %l0, %l6 ! l6 <= start of physical memory 69 80 70 ! Get bits 40:13 of physmem_base.81 ! Get bits (PHYSMEM_ADDR_SIZE - 1):13 of physmem_base. 71 82 srlx %l6, 13, %l5 72 sllx %l5, 13 + (63 - 40), %l5 73 srlx %l5, 63 - 40, %l5 ! l5 <= physmem_base[40:13] 83 84 ! l5 <= physmem_base[(PHYSMEM_ADDR_SIZE - 1):13] 85 sllx %l5, 13 + (63 - (PHYSMEM_ADDR_SIZE - 1)), %l5 86 srlx %l5, 63 - (PHYSMEM_ADDR_SIZE - 1), %l5 74 87 75 88 /* … … 84 97 wrpr %g0, NWINDOWS - 1, %cleanwin ! prevent needless clean_window 85 98 ! traps for kernel 99 100 wrpr %g0, 0, %wstate ! use default spill/fill trap 86 101 87 102 wrpr %g0, 0, %tl ! TL = 0, primary context … … 245 260 /* 246 261 * Precompute kernel 8K TLB data template. 247 * %l5 contains starting physical address bits [40:13] 262 * %l5 contains starting physical address 263 * bits [(PHYSMEM_ADDR_SIZE - 1):13] 248 264 */ 249 265 sethi %hi(kernel_8k_tlb_data_template), %l4 … … 283 299 284 300 301 1: 302 #ifdef CONFIG_SMP 303 /* 304 * Determine the width of the MID and save its mask to %g3. The width 305 * is 306 * * 5 for US and US-IIIi, 307 * * 10 for US3 except US-IIIi. 308 */ 309 #if defined(US) 310 mov 0x1f, %g3 311 #elif defined(US3) 312 mov 0x3ff, %g3 313 rdpr %ver, %g2 314 sllx %g2, 16, %g2 315 srlx %g2, 48, %g2 316 cmp %g2, IMPL_ULTRASPARCIII_I 317 move %xcc, 0x1f, %g3 318 #endif 319 285 320 /* 286 321 * Read MID from the processor. 287 322 */ 288 1: 289 ldxa [%g0] ASI_UPA_CONFIG, %g1 290 srlx %g1, UPA_CONFIG_MID_SHIFT, %g1 291 and %g1, UPA_CONFIG_MID_MASK, %g1 292 293 #ifdef CONFIG_SMP 323 ldxa [%g0] ASI_ICBUS_CONFIG, %g1 324 srlx %g1, ICBUS_CONFIG_MID_SHIFT, %g1 325 and %g1, %g3, %g1 326 294 327 /* 295 328 * Active loop for APs until the BSP picks them up. A processor cannot -
kernel/arch/sparc64/src/trap/interrupt.c
r0258e67 r965dc18 68 68 void interrupt(int n, istate_t *istate) 69 69 { 70 uint64_t status; 70 71 uint64_t intrcv; 71 72 uint64_t data0; 73 status = asi_u64_read(ASI_INTR_DISPATCH_STATUS, 0); 74 if (status & (!INTR_DISPATCH_STATUS_BUSY)) 75 panic("Interrupt Dispatch Status busy bit not set\n"); 72 76 73 77 intrcv = asi_u64_read(ASI_INTR_RECEIVE, 0); 74 data0 = asi_u64_read(ASI_UDB_INTR_R, ASI_UDB_INTR_R_DATA_0); 78 #if defined (US) 79 data0 = asi_u64_read(ASI_INTR_R, ASI_UDB_INTR_R_DATA_0); 80 #elif defined (US3) 81 data0 = asi_u64_read(ASI_INTR_R, VA_INTR_R_DATA_0); 82 #endif 75 83 76 84 irq_t *irq = irq_dispatch_and_lock(data0);
Note:
See TracChangeset
for help on using the changeset viewer.