📄 ppcv_cpuconfig_booke.c
字号:
/* * $QNXLicenseC: * Copyright 2007, QNX Software Systems. * * Licensed under the Apache License, Version 2.0 (the "License"). You * may not reproduce, modify or distribute this software except in * compliance with the License. You may obtain a copy of the License * at: http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OF ANY KIND, either express or implied. * * This file may contain contributions from others, either as * contributors under the License or as licensors under other terms. * Please review this entire file for other proprietary rights or license * notices, as well as the QNX Development Suite License Guide at * http://licensing.qnx.com/license-guide/ for other information. * $ */#include "startup.h"// Clean out the TLB except for the one covering entrystatic voidppcbke_tlb_clean1(int cpu) { unsigned i; ppcbke_tlb_t tlb; unsigned covering = -1; unsigned covering_tlb = -1; uint64_t tlb_size; unsigned save_msr; unsigned transfer_idx; int num_entries; int tlb_num;#if 0//NYI: TEMP TESTING HACK return;#endif tlb_num = 0; for(;;) { num_entries = ppcbke_tlb.info(MI_NUM_ENTRIES, tlb_num); if(num_entries < 0) break; for(i = 0; i < num_entries; ++i) { ppcbke_tlb.read(tlb_num, i, &tlb); if(tlb.v) { tlb_size = (uint64_t)0x400 << (tlb.size*2); if((tlb.epn < (uintptr_t)&ppcbke_tlb_clean1) &&((tlb.epn + tlb_size) > (uintptr_t)&ppcbke_tlb_clean1)) { covering = i; covering_tlb = tlb_num; } else { tlb.v = 0; ppcbke_tlb.write(tlb_num, i, &tlb); } } } ++tlb_num; } /* Make sure that TLB slot zero is set up for one-to-one mapping with a size of 256M.//NYI: Should check and make sure 256M is a supported page size.... */ tlb.rpn = 0; tlb.epn = 0; tlb.tid = 0; tlb.attr = PPCBKE_TLB_ATTR_M | PPCBKEM_TLB_ATTR_IPROT | PPCBKEM_TLB_ATTR_SHAREN; tlb.access = PPCBKE_TLB_ACCESS_SR|PPCBKE_TLB_ACCESS_SW|PPCBKE_TLB_ACCESS_SX; tlb.size = PPCBKE_TLB_SIZE_256M; tlb.v = 1; tlb.ts = 1; /* choose a TLB slot that's not zero & not 'covering' */ transfer_idx = (covering ^ 0x02) | 1; /* enable transfer slot */ ppcbke_tlb.write(covering_tlb, transfer_idx, &tlb); save_msr = get_msr(); set_msr(save_msr | (PPC_MSR_IS|PPC_MSR_DS)); ppc_isync(); tlb.v = 0; /* disable old covering slot */ ppcbke_tlb.write(covering_tlb, covering, &tlb); tlb.ts = 0; tlb.v = 1; /* enable new covering entry at slot zero */ ppcbke_tlb.write(covering_tlb, 0, &tlb); set_msr(save_msr); ppc_isync(); tlb.v = 0; /* disable transfer slot */ ppcbke_tlb.write(covering_tlb, transfer_idx, &tlb); // We're going to use PID == 0 for callout mappings and // PID == 1 for startup ones. set_spr(PPCBKE_SPR_PID, 1);}// Clean out the TLB of all the startup mappingsstatic voidppcbke_tlb_clean2(int cpu) { unsigned i; ppcbke_tlb_t tlb; unsigned tlb_num; int num_entries; tlb_num = 0; for(;;) { num_entries = ppcbke_tlb.info(MI_NUM_ENTRIES, tlb_num); if(num_entries < 0) break; for(i = 0; i < num_entries; ++i) { ppcbke_tlb.read(tlb_num, i, &tlb); if(tlb.v && (tlb.tid == 1)) { tlb.v = 0; ppcbke_tlb.write(tlb_num, i, &tlb); } } ++tlb_num; }}static voidset_ivor_range(unsigned spr, unsigned loc, unsigned num) { while(num > 0) { set_spr_indirect(spr, loc); loc += 1 << 4; ++spr; --num; }}voidppcv_cpuconfig1_booke(int cpu) { /* mask all timer interrupts */ set_spr(PPCBKE_SPR_TCR, PPCBKE_TCR_ARE); /* if cpu == 0, init decrementer for full cycle, otherwise kill it */ if(cpu == 0) { set_spr(PPCBKE_SPR_DECAR, ~0L); set_spr(PPC_SPR_DEC, ~0L); } else { set_spr(PPCBKE_SPR_TCR, 0); set_spr(PPC_SPR_DEC, 0); } set_spr(PPCBKE_SPR_TSR, PPCBKE_TSR_DIS); ppcbke_tlb_clean1(cpu);}unsigned short ivor32_47_list;unsigned short ivor48_63_list;voidppcv_cpuconfig2_booke(int cpu) { static const uint32_t handler[] = { 0x7c7043a6, /* mtsprg0 %r3 */ 0x7c7a02a6, /* mfsrr0 %r3 */ 0x38630004, /* addi %r3,%r3,4 */ 0x7c7a03a6, /* mtsrr0 %r3 */ 0x7c7942a6, /* mfsprg0 %r3 */ 0x4c000064 /* rfi */ }; /* Point the exception registers to "safe" locations. The kernel will set these addresses to transfer to the unexpected exception routine. */ set_spr(PPCBKE_SPR_IVPR, 0); /* Install an illegal instruction exception handler that skips over the instruction - this will let us set IVOR's that don't exist on a particular chip. */ memmove(0, handler, sizeof(handler)); icache_flush(0); icache_flush(16); set_spr(PPCBKE_SPR_IVOR6, 0); set_ivor_range(IVOR_LIST_SPR(ivor48_63_list), 48 << 4, IVOR_LIST_NUM(ivor48_63_list)); set_ivor_range(IVOR_LIST_SPR(ivor32_47_list), 32 << 4, IVOR_LIST_NUM(ivor32_47_list)); set_ivor_range(PPCBKE_SPR_IVOR16, 16 << 4, 16); /* have to do these _last_, since IVOR6 gets changed by it */ set_ivor_range(PPCBKE_SPR_IVOR0, 0 << 4, 16); ppcbke_tlb_clean2(cpu); // Get the debug control into a clean state set_msr(get_msr() & ~PPC_MSR_DE); set_spr(PPCBKE_SPR_DBSR, ~0); set_spr(PPCBKE_SPR_DBCR0, PPCBKE_DBCR0_IDM | PPCBKE_DBCR0_ICMP);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -