📄 ppcv_map_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"// We're going to use PID == 0 for callout mappings and// PID == 1 for startup ones.void *ppcv_map_booke(unsigned size, paddr_t phys, unsigned prot_flags) { unsigned i; unsigned free = -1; ppcbke_tlb_t tlb; uint64_t tlb_size; paddr64_t paddr; paddr64_t end; unsigned access; static uintptr_t next_vaddr = 0x80000000; unsigned tlb_num; unsigned supported; paddr = phys;#if 0//NYI: TEMP TESTING HACKreturn((void *)(uintptr_t)paddr);#endif end = paddr + size - 1; if((end < MEG(256)) && ((prot_flags & (PROT_CALLOUT|PROT_NOCACHE)) == 0)) { // A cachable startup request in the first 256M of memory. // Can just use the one-to-one mapping. return((void *)(uintptr_t)paddr); } supported = 0; i = 0; tlb_num = 0; for(;;) { int curr; curr = ppcbke_tlb.info(MI_PAGESIZES, i); if(curr < 0) break; if(curr > supported) { // We want to use the TLB with the greatest # of supported sizes. // Not exactly what we're testing for here, but close enough // for jazz. supported = curr; tlb_num = i; } ++i; } for(i = ppcbke_tlb.info(MI_NUM_ENTRIES, tlb_num); i > 0; --i) { ppcbke_tlb.read(tlb_num, i, &tlb); if(tlb.v) { tlb_size = (uint64_t)0x400 << (tlb.size*2); if((tlb.rpn <= paddr) && (end < (tlb.rpn + tlb_size))) { if(!(prot_flags & PROT_NOCACHE) || (tlb.attr & PPCBKE_TLB_ATTR_I)) { // We can reuse this TLB entry. if((prot_flags & PROT_CALLOUT) && (tlb.tid != 0)) { //It's a startup mapping, we need to make it a callout one. tlb.tid = 0; ppcbke_tlb.write(tlb_num, i, &tlb); } return (void *)(tlb.epn + (uintptr_t)(paddr - tlb.rpn)); } } } else { free = i; } } if(free == -1) { crash("No TLB to map 0x%L for %d bytes.\n", paddr, size); } supported = ppcbke_tlb.info(MI_PAGESIZES, tlb_num); i = PPCBKE_TLB_SIZE_1K; for( ;; ) { if(i > PPCBKE_TLB_SIZE_1T) { crash("No supported TLB size to map 0x%L for %d bytes.\n", paddr, size); } if(supported & (1 << i)) { tlb_size = (uint64_t)0x400 * (1 << (i*2)); tlb.rpn = paddr & ~(tlb_size - 1); if(end < (tlb.rpn + tlb_size)) break; } ++i; } tlb.size = i; tlb.epn = (next_vaddr + ((uintptr_t)tlb_size-1)) & ~((uintptr_t)tlb_size-1); next_vaddr = tlb.epn + (uintptr_t)tlb_size; tlb.tid = (prot_flags & PROT_CALLOUT) ? 0 : 1; tlb.attr = PPCBKEM_TLB_ATTR_SHAREN | PPCBKEM_TLB_ATTR_IPROT; if(prot_flags & PROT_NOCACHE) { tlb.attr |= PPCBKE_TLB_ATTR_I|PPCBKE_TLB_ATTR_G; } access = 0; if(prot_flags & PROT_READ) access |= PPCBKE_TLB_ACCESS_SR; if(prot_flags & PROT_WRITE) access |= PPCBKE_TLB_ACCESS_SW; if(prot_flags & PROT_EXEC) access |= PPCBKE_TLB_ACCESS_SX; if(prot_flags & PROT_USER) access |= (access << 3); tlb.access = access; tlb.ts = 0; tlb.v = 1; ppcbke_tlb.write(tlb_num, free, &tlb); return (void *)(tlb.epn + (uintptr_t)(paddr - tlb.rpn));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -