Added some hacks to get the boot loader to work on the Pegasos.

Doesn't come far yet, though.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16091 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2006-01-25 20:05:11 +00:00
parent 818feababe
commit a268fbfe48

View File

@ -1,5 +1,5 @@
/*
* Copyright 2003-2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Copyright 2003-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
@ -16,6 +16,15 @@
#include <OS.h>
// set protection to WIMGNPP: -----PP
// PP: 00 - no access
// 01 - read only
// 10 - read/write
// 11 - read only
#define PAGE_READ_ONLY 0x01
#define PAGE_READ_WRITE 0x02
segment_descriptor sSegments[16];
page_table_entry_group *sPageTable;
uint32 sPageTableHashMask;
@ -572,16 +581,11 @@ arch_mmu_allocate(void *_virtualAddress, size_t size, uint8 _protection,
// we only know page sizes
size = ROUNDUP(size, B_PAGE_SIZE);
// set protection to WIMGNPP: -----PP
// PP: 00 - no access
// 01 - read only
// 10 - read/write
// 11 - read only
uint8 protection = 0;
if (_protection & B_WRITE_AREA)
protection = 0x02;
protection = PAGE_READ_WRITE;
else
protection = 0x01;
protection = PAGE_READ_ONLY;
// If no address is given, use the KERNEL_BASE as base address, since
// that avoids trouble in the kernel, when we decide to keep the region.
@ -817,7 +821,7 @@ extern "C" status_t
arch_mmu_init(void)
{
// get map of physical memory (fill in kernel_args structure)
size_t total;
if (find_physical_memory_ranges(total) < B_OK) {
puts("could not find physical memory ranges!");
@ -831,19 +835,21 @@ arch_mmu_init(void)
page_table_entry_group *table;
size_t tableSize;
ppc_get_page_table(&table, &tableSize);
printf("-> table = %p, size = %u\n", table, tableSize);
if (table == NULL && tableSize == 0) {
puts("OpenFirmware is in real addressing mode!");
}
oldTable = table;
bool realMode = false;
// TODO: read these values out of the OF settings
addr_t realBase = 0;
addr_t realSize = 0x400000;
// can we just keep the page table?
size_t suggestedTableSize = suggested_page_table_size(total);
printf("suggested page table size = %u\n", suggestedTableSize);
if (tableSize < suggestedTableSize) {
// nah, we need a new one!
printf("need new page table, size = %u!\n", suggestedTableSize);
table = (page_table_entry_group *)of_claim(0, suggestedTableSize, suggestedTableSize);
table = (page_table_entry_group *)of_claim(NULL, suggestedTableSize, suggestedTableSize);
// KERNEL_BASE would be better as virtual address, but
// at least with Apple's OpenFirmware, it makes no
// difference - we will have to remap it later
@ -851,17 +857,32 @@ arch_mmu_init(void)
panic("Could not allocate new page table (size = %ld)!!\n", suggestedTableSize);
return B_NO_MEMORY;
}
if (table == NULL) {
// work-around for the broken Pegasos OpenFirmware
puts("broken OpenFirmware detected (claim doesn't work).");
realMode = true;
addr_t tableBase = 0;
for (int32 i = 0; tableBase < realBase + realSize * 3; i++) {
tableBase = suggestedTableSize * i;
}
table = (page_table_entry_group *)tableBase;
}
printf("new table at: %p\n", table);
sPageTable = (page_table_entry_group *)table;
sPageTable = table;
tableSize = suggestedTableSize;
} else {
// ToDo: we could check if the page table is much too large
// and create a smaller one in this case (in order to save
// memory).
sPageTable = (page_table_entry_group *)table;
sPageTable = table;
}
sPageTableHashMask = tableSize / sizeof(page_table_entry_group) - 1;
memset(sPageTable, 0, tableSize);
if (sPageTable != oldTable)
memset(sPageTable, 0, tableSize);
// turn off address translation via the page table/segment mechanism,
// identity map the first 256 MB (where our code/data reside)
@ -898,9 +919,30 @@ puts("2");*/
return B_ERROR;
}
#if 0
block_address_translation bats[8];
getibats(bats);
for (int32 i = 0; i < 8; i++)
printf("page index %u, length %u, ppn %u\n", bats[i].page_index, bats[i].length, bats[i].physical_block_number);
#endif
if (physicalTable == NULL) {
puts("arch_mmu_init(): Didn't find physical address of page table!");
return B_ERROR;
if (!realMode)
return B_ERROR;
// Pegasos work-around
//map_range((void *)realBase, (void *)realBase, realSize * 2, PAGE_READ_WRITE);
//map_range((void *)(total - realSize), (void *)(total - realSize), realSize, PAGE_READ_WRITE);
//map_range((void *)table, (void *)table, tableSize, PAGE_READ_WRITE);
insert_physical_allocated_range((void *)realBase, realSize * 2);
insert_virtual_allocated_range((void *)realBase, realSize * 2);
insert_physical_allocated_range((void *)(total - realSize), realSize);
insert_virtual_allocated_range((void *)(total - realSize), realSize);
insert_physical_allocated_range((void *)table, tableSize);
insert_virtual_allocated_range((void *)table, tableSize);
physicalTable = table;
}
if (exceptionHandlers == (void *)-1) {
@ -922,9 +964,11 @@ puts("2");*/
ppc_set_page_table(physicalTable, tableSize);
invalidate_tlb();
// clear BATs
reset_ibats();
reset_dbats();
if (!realMode) {
// clear BATs
reset_ibats();
reset_dbats();
}
set_msr(MSR_MACHINE_CHECK_ENABLED | MSR_FP_AVAILABLE
| MSR_INST_ADDRESS_TRANSLATION