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:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2004, Axel Dörfler, [email protected]. All rights reserved.
|
* Copyright 2003-2006, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -16,6 +16,15 @@
|
|||||||
#include <OS.h>
|
#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];
|
segment_descriptor sSegments[16];
|
||||||
page_table_entry_group *sPageTable;
|
page_table_entry_group *sPageTable;
|
||||||
uint32 sPageTableHashMask;
|
uint32 sPageTableHashMask;
|
||||||
@@ -572,16 +581,11 @@ arch_mmu_allocate(void *_virtualAddress, size_t size, uint8 _protection,
|
|||||||
// we only know page sizes
|
// we only know page sizes
|
||||||
size = ROUNDUP(size, B_PAGE_SIZE);
|
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;
|
uint8 protection = 0;
|
||||||
if (_protection & B_WRITE_AREA)
|
if (_protection & B_WRITE_AREA)
|
||||||
protection = 0x02;
|
protection = PAGE_READ_WRITE;
|
||||||
else
|
else
|
||||||
protection = 0x01;
|
protection = PAGE_READ_ONLY;
|
||||||
|
|
||||||
// If no address is given, use the KERNEL_BASE as base address, since
|
// 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.
|
// 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)
|
arch_mmu_init(void)
|
||||||
{
|
{
|
||||||
// get map of physical memory (fill in kernel_args structure)
|
// get map of physical memory (fill in kernel_args structure)
|
||||||
|
|
||||||
size_t total;
|
size_t total;
|
||||||
if (find_physical_memory_ranges(total) < B_OK) {
|
if (find_physical_memory_ranges(total) < B_OK) {
|
||||||
puts("could not find physical memory ranges!");
|
puts("could not find physical memory ranges!");
|
||||||
@@ -831,19 +835,21 @@ arch_mmu_init(void)
|
|||||||
page_table_entry_group *table;
|
page_table_entry_group *table;
|
||||||
size_t tableSize;
|
size_t tableSize;
|
||||||
ppc_get_page_table(&table, &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;
|
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?
|
// can we just keep the page table?
|
||||||
size_t suggestedTableSize = suggested_page_table_size(total);
|
size_t suggestedTableSize = suggested_page_table_size(total);
|
||||||
printf("suggested page table size = %u\n", suggestedTableSize);
|
printf("suggested page table size = %u\n", suggestedTableSize);
|
||||||
if (tableSize < suggestedTableSize) {
|
if (tableSize < suggestedTableSize) {
|
||||||
// nah, we need a new one!
|
// nah, we need a new one!
|
||||||
printf("need new page table, size = %u!\n", suggestedTableSize);
|
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
|
// KERNEL_BASE would be better as virtual address, but
|
||||||
// at least with Apple's OpenFirmware, it makes no
|
// at least with Apple's OpenFirmware, it makes no
|
||||||
// difference - we will have to remap it later
|
// 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);
|
panic("Could not allocate new page table (size = %ld)!!\n", suggestedTableSize);
|
||||||
return B_NO_MEMORY;
|
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);
|
printf("new table at: %p\n", table);
|
||||||
sPageTable = (page_table_entry_group *)table;
|
sPageTable = table;
|
||||||
tableSize = suggestedTableSize;
|
tableSize = suggestedTableSize;
|
||||||
} else {
|
} else {
|
||||||
// ToDo: we could check if the page table is much too large
|
// ToDo: we could check if the page table is much too large
|
||||||
// and create a smaller one in this case (in order to save
|
// and create a smaller one in this case (in order to save
|
||||||
// memory).
|
// memory).
|
||||||
sPageTable = (page_table_entry_group *)table;
|
sPageTable = table;
|
||||||
}
|
}
|
||||||
|
|
||||||
sPageTableHashMask = tableSize / sizeof(page_table_entry_group) - 1;
|
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,
|
// turn off address translation via the page table/segment mechanism,
|
||||||
// identity map the first 256 MB (where our code/data reside)
|
// identity map the first 256 MB (where our code/data reside)
|
||||||
@@ -898,9 +919,30 @@ puts("2");*/
|
|||||||
return B_ERROR;
|
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) {
|
if (physicalTable == NULL) {
|
||||||
puts("arch_mmu_init(): Didn't find physical address of page table!");
|
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) {
|
if (exceptionHandlers == (void *)-1) {
|
||||||
@@ -922,9 +964,11 @@ puts("2");*/
|
|||||||
ppc_set_page_table(physicalTable, tableSize);
|
ppc_set_page_table(physicalTable, tableSize);
|
||||||
invalidate_tlb();
|
invalidate_tlb();
|
||||||
|
|
||||||
// clear BATs
|
if (!realMode) {
|
||||||
reset_ibats();
|
// clear BATs
|
||||||
reset_dbats();
|
reset_ibats();
|
||||||
|
reset_dbats();
|
||||||
|
}
|
||||||
|
|
||||||
set_msr(MSR_MACHINE_CHECK_ENABLED | MSR_FP_AVAILABLE
|
set_msr(MSR_MACHINE_CHECK_ENABLED | MSR_FP_AVAILABLE
|
||||||
| MSR_INST_ADDRESS_TRANSLATION
|
| MSR_INST_ADDRESS_TRANSLATION
|
||||||
|
|||||||
Reference in New Issue
Block a user