We use the generic physical page mapper for PPC now. I realized that it
is actually not that nice for PPC since we don't have large pages. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15860 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
SubDir HAIKU_TOP src system kernel arch ppc ;
|
SubDir HAIKU_TOP src system kernel arch ppc ;
|
||||||
|
|
||||||
|
SubDirHdrs $(SUBDIR) $(DOTDOT) generic ;
|
||||||
|
|
||||||
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) generic ] ;
|
||||||
|
|
||||||
KernelStaticLibrary libppc :
|
KernelStaticLibrary libppc :
|
||||||
arch_atomic.c
|
arch_atomic.c
|
||||||
arch_cpu.c
|
arch_cpu.c
|
||||||
@@ -20,6 +24,8 @@ KernelStaticLibrary libppc :
|
|||||||
arch_vm.cpp
|
arch_vm.cpp
|
||||||
arch_vm_translation_map.cpp
|
arch_vm_translation_map.cpp
|
||||||
arch_asm.S
|
arch_asm.S
|
||||||
|
|
||||||
|
generic_vm_physical_page_mapper.cpp
|
||||||
:
|
:
|
||||||
$(TARGET_KERNEL_PIC_CCFLAGS) -Wno-unused
|
$(TARGET_KERNEL_PIC_CCFLAGS) -Wno-unused
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -61,10 +61,6 @@
|
|||||||
|
|
||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
* The page table lies in physical memory and is identity mapped. Either
|
|
||||||
the boot loader should already map it into the kernel address space or
|
|
||||||
we need to remap here. Otherwise we can't create the area for obvious
|
|
||||||
reasons.
|
|
||||||
* If we want to continue to use the OF services, we would need to add
|
* If we want to continue to use the OF services, we would need to add
|
||||||
its address mappings to the kernel space. Unfortunately some stuff
|
its address mappings to the kernel space. Unfortunately some stuff
|
||||||
(especially RAM) is mapped in an address range without the kernel
|
(especially RAM) is mapped in an address range without the kernel
|
||||||
@@ -87,6 +83,7 @@
|
|||||||
#include <arch_mmu.h>
|
#include <arch_mmu.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "generic_vm_physical_page_mapper.h"
|
||||||
|
|
||||||
static struct page_table_entry_group *sPageTable;
|
static struct page_table_entry_group *sPageTable;
|
||||||
static size_t sPageTableSize;
|
static size_t sPageTableSize;
|
||||||
@@ -94,10 +91,16 @@ static uint32 sPageTableHashMask;
|
|||||||
static area_id sPageTableArea;
|
static area_id sPageTableArea;
|
||||||
|
|
||||||
|
|
||||||
// 512 MB of iospace
|
// 64 MB of iospace
|
||||||
#define IOSPACE_SIZE (512*1024*1024)
|
#define IOSPACE_SIZE (64*1024*1024)
|
||||||
// put it 512 MB into kernel space
|
// We only have small (4 KB) pages. The only reason for choosing greater chunk
|
||||||
#define IOSPACE_BASE (KERNEL_BASE + IOSPACE_SIZE)
|
// size is to keep the waste of memory limited, since the generic page mapper
|
||||||
|
// allocates structures per physical/virtual chunk.
|
||||||
|
// TODO: Implement a page mapper more suitable for small pages!
|
||||||
|
#define IOSPACE_CHUNK_SIZE (16 * B_PAGE_SIZE)
|
||||||
|
|
||||||
|
static addr_t sIOSpaceBase;
|
||||||
|
|
||||||
|
|
||||||
// The VSID is a 24 bit number. The lower three bits are defined by the
|
// The VSID is a 24 bit number. The lower three bits are defined by the
|
||||||
// (effective) segment number, which leaves us with a 21 bit space of
|
// (effective) segment number, which leaves us with a 21 bit space of
|
||||||
@@ -362,6 +365,19 @@ query_tmap(vm_translation_map *map, addr_t va, addr_t *_outPhysical, uint32 *_ou
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
map_iospace_chunk(addr_t va, addr_t pa)
|
||||||
|
{
|
||||||
|
pa &= ~(B_PAGE_SIZE - 1); // make sure it's page aligned
|
||||||
|
va &= ~(B_PAGE_SIZE - 1); // make sure it's page aligned
|
||||||
|
if (va < sIOSpaceBase || va >= (sIOSpaceBase + IOSPACE_SIZE))
|
||||||
|
panic("map_iospace_chunk: passed invalid va 0x%lx\n", va);
|
||||||
|
|
||||||
|
// map the pages
|
||||||
|
return ppc_map_address_range(va, pa, IOSPACE_CHUNK_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static addr_t
|
static addr_t
|
||||||
get_mapped_size_tmap(vm_translation_map *map)
|
get_mapped_size_tmap(vm_translation_map *map)
|
||||||
{
|
{
|
||||||
@@ -418,23 +434,14 @@ flush_tmap(vm_translation_map *map)
|
|||||||
static status_t
|
static status_t
|
||||||
get_physical_page_tmap(addr_t pa, addr_t *va, uint32 flags)
|
get_physical_page_tmap(addr_t pa, addr_t *va, uint32 flags)
|
||||||
{
|
{
|
||||||
pa = ROUNDOWN(pa, PAGE_SIZE);
|
return generic_get_physical_page(pa, va, flags);
|
||||||
|
|
||||||
if (pa > IOSPACE_SIZE)
|
|
||||||
panic("get_physical_page_tmap: asked for pa 0x%lx, cannot provide\n", pa);
|
|
||||||
|
|
||||||
*va = (IOSPACE_BASE + pa);
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
put_physical_page_tmap(addr_t va)
|
put_physical_page_tmap(addr_t va)
|
||||||
{
|
{
|
||||||
if (va < IOSPACE_BASE || va >= IOSPACE_BASE + IOSPACE_SIZE)
|
return generic_put_physical_page(va);
|
||||||
panic("put_physical_page_tmap: va 0x%lx out of iospace region\n", va);
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -538,6 +545,52 @@ arch_vm_translation_map_init(kernel_args *args)
|
|||||||
sPageTableSize = args->arch_args.page_table.size;
|
sPageTableSize = args->arch_args.page_table.size;
|
||||||
sPageTableHashMask = sPageTableSize / sizeof(page_table_entry_group) - 1;
|
sPageTableHashMask = sPageTableSize / sizeof(page_table_entry_group) - 1;
|
||||||
|
|
||||||
|
// init physical page mapper
|
||||||
|
status_t error = generic_vm_physical_page_mapper_init(args,
|
||||||
|
map_iospace_chunk, &sIOSpaceBase, IOSPACE_SIZE, IOSPACE_CHUNK_SIZE);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
arch_vm_translation_map_init_post_area(kernel_args *args)
|
||||||
|
{
|
||||||
|
// If the page table doesn't lie within the kernel address space, we
|
||||||
|
// remap it.
|
||||||
|
if (!IS_KERNEL_ADDRESS(sPageTable)) {
|
||||||
|
addr_t newAddress = (addr_t)sPageTable;
|
||||||
|
status_t error = ppc_remap_address_range(&newAddress, sPageTableSize,
|
||||||
|
false);
|
||||||
|
if (error != B_OK) {
|
||||||
|
panic("arch_vm_translation_map_init_post_area(): Failed to remap "
|
||||||
|
"the page table!");
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the new page table address
|
||||||
|
addr_t oldVirtualBase = (addr_t)(sPageTable);
|
||||||
|
sPageTable = (page_table_entry_group*)newAddress;
|
||||||
|
|
||||||
|
// unmap the old pages
|
||||||
|
ppc_unmap_address_range(oldVirtualBase, sPageTableSize);
|
||||||
|
|
||||||
|
// TODO: We should probably map the page table via BAT. It is relatively large,
|
||||||
|
// and due to being a hash table the access patterns might look sporadic, which
|
||||||
|
// certainly isn't to the liking of the TLB.
|
||||||
|
}
|
||||||
|
|
||||||
|
// create an area to cover the page table
|
||||||
|
sPageTableArea = create_area("page_table", (void **)&sPageTable, B_EXACT_ADDRESS,
|
||||||
|
sPageTableSize, B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
|
||||||
|
|
||||||
|
// init physical page mapper
|
||||||
|
status_t error = generic_vm_physical_page_mapper_init_post_area(args);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -545,10 +598,64 @@ arch_vm_translation_map_init(kernel_args *args)
|
|||||||
status_t
|
status_t
|
||||||
arch_vm_translation_map_init_post_sem(kernel_args *args)
|
arch_vm_translation_map_init_post_sem(kernel_args *args)
|
||||||
{
|
{
|
||||||
|
// init physical page mapper
|
||||||
|
return generic_vm_physical_page_mapper_init_post_sem(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Directly maps a page without having knowledge of any kernel structures.
|
||||||
|
* Used only during VM setup.
|
||||||
|
* It currently ignores the "attributes" parameter and sets all pages
|
||||||
|
* read/write.
|
||||||
|
*/
|
||||||
|
|
||||||
|
status_t
|
||||||
|
arch_vm_translation_map_early_map(kernel_args *ka, addr_t virtualAddress, addr_t physicalAddress,
|
||||||
|
uint8 attributes, addr_t (*get_free_page)(kernel_args *))
|
||||||
|
{
|
||||||
|
uint32 virtualSegmentID = get_sr((void *)virtualAddress) & 0xffffff;
|
||||||
|
|
||||||
|
uint32 hash = page_table_entry::PrimaryHash(virtualSegmentID, (uint32)virtualAddress);
|
||||||
|
page_table_entry_group *group = &sPageTable[hash & sPageTableHashMask];
|
||||||
|
|
||||||
|
for (int32 i = 0; i < 8; i++) {
|
||||||
|
// 8 entries in a group
|
||||||
|
if (group->entry[i].valid)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
fill_page_table_entry(&group->entry[i], virtualSegmentID, virtualAddress, physicalAddress, PTE_READ_WRITE, false);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
hash = page_table_entry::SecondaryHash(hash);
|
||||||
|
group = &sPageTable[hash & sPageTableHashMask];
|
||||||
|
|
||||||
|
for (int32 i = 0; i < 8; i++) {
|
||||||
|
if (group->entry[i].valid)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
fill_page_table_entry(&group->entry[i], virtualSegmentID, virtualAddress, physicalAddress, PTE_READ_WRITE, true);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// XXX currently assumes this translation map is active
|
||||||
|
|
||||||
|
status_t
|
||||||
|
arch_vm_translation_map_early_query(addr_t va, addr_t *out_physical)
|
||||||
|
{
|
||||||
|
//PANIC_UNIMPLEMENTED();
|
||||||
|
panic("vm_translation_map_quick_query(): not yet implemented\n");
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ppc_map_address_range(addr_t virtualAddress, addr_t physicalAddress,
|
ppc_map_address_range(addr_t virtualAddress, addr_t physicalAddress,
|
||||||
size_t size)
|
size_t size)
|
||||||
@@ -622,135 +729,3 @@ ppc_remap_address_range(addr_t *_virtualAddress, size_t size, bool unmap)
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
arch_vm_translation_map_init_post_area(kernel_args *args)
|
|
||||||
{
|
|
||||||
// If the page table doesn't lie within the kernel address space, we
|
|
||||||
// remap it.
|
|
||||||
if (!IS_KERNEL_ADDRESS(sPageTable)) {
|
|
||||||
addr_t newAddress = (addr_t)sPageTable;
|
|
||||||
status_t error = ppc_remap_address_range(&newAddress, sPageTableSize,
|
|
||||||
false);
|
|
||||||
if (error != B_OK) {
|
|
||||||
panic("arch_vm_translation_map_init_post_area(): Failed to remap "
|
|
||||||
"the page table!");
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set the new page table address
|
|
||||||
addr_t oldVirtualBase = (addr_t)(sPageTable);
|
|
||||||
sPageTable = (page_table_entry_group*)newAddress;
|
|
||||||
|
|
||||||
// unmap the old pages
|
|
||||||
ppc_unmap_address_range(oldVirtualBase, sPageTableSize);
|
|
||||||
|
|
||||||
// TODO: We should probably map the page table via BAT. It is relatively large,
|
|
||||||
// and due to being a hash table the access patterns might look sporadic, which
|
|
||||||
// certainly isn't to the liking of the TLB.
|
|
||||||
}
|
|
||||||
|
|
||||||
// create an area to cover the page table
|
|
||||||
sPageTableArea = create_area("page_table", (void **)&sPageTable, B_EXACT_ADDRESS,
|
|
||||||
sPageTableSize, B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// ToDo: for now just map 0 - 512MB of physical memory to the iospace region
|
|
||||||
block_address_translation bat;
|
|
||||||
|
|
||||||
bat.Clear();
|
|
||||||
bat.SetVirtualAddress((void *)IOSPACE_BASE);
|
|
||||||
bat.page_index = IOSPACE_BASE;
|
|
||||||
bat.length = BAT_LENGTH_256MB;
|
|
||||||
bat.kernel_valid = true;
|
|
||||||
bat.SetPhysicalAddress(NULL);
|
|
||||||
bat.memory_coherent = true;
|
|
||||||
bat.protection = BAT_READ_WRITE;
|
|
||||||
|
|
||||||
set_ibat2(&bat);
|
|
||||||
set_dbat2(&bat);
|
|
||||||
isync();
|
|
||||||
|
|
||||||
bat.SetVirtualAddress((void *)(IOSPACE_BASE + 256 * 1024 * 1024));
|
|
||||||
bat.SetPhysicalAddress((void *)(256 * 1024 * 1024));
|
|
||||||
|
|
||||||
set_ibat3(&bat);
|
|
||||||
set_dbat3(&bat);
|
|
||||||
isync();
|
|
||||||
/*
|
|
||||||
int ibats[8], dbats[8];
|
|
||||||
|
|
||||||
getibats(ibats);
|
|
||||||
getdbats(dbats);
|
|
||||||
|
|
||||||
// use bat 2 & 3 to do this
|
|
||||||
ibats[4] = dbats[4] = IOSPACE_BASE | BATU_LEN_256M | BATU_VS;
|
|
||||||
ibats[5] = dbats[5] = 0x0 | BATL_MC | BATL_PP_RW;
|
|
||||||
ibats[6] = dbats[6] = (IOSPACE_BASE + 256*1024*1024) | BATU_LEN_256M | BATU_VS;
|
|
||||||
ibats[7] = dbats[7] = (256*1024*1024) | BATL_MC | BATL_PP_RW;
|
|
||||||
|
|
||||||
setibats(ibats);
|
|
||||||
setdbats(dbats);
|
|
||||||
*/
|
|
||||||
|
|
||||||
// create a region to cover the iospace
|
|
||||||
void *temp = (void *)IOSPACE_BASE;
|
|
||||||
vm_create_null_area(vm_kernel_address_space_id(), "iospace", &temp,
|
|
||||||
B_EXACT_ADDRESS, IOSPACE_SIZE);
|
|
||||||
|
|
||||||
// TODO: Create areas for all OF mappings we want to keep. And unmap the others.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Directly maps a page without having knowledge of any kernel structures.
|
|
||||||
* Used only during VM setup.
|
|
||||||
* It currently ignores the "attributes" parameter and sets all pages
|
|
||||||
* read/write.
|
|
||||||
*/
|
|
||||||
|
|
||||||
status_t
|
|
||||||
arch_vm_translation_map_early_map(kernel_args *ka, addr_t virtualAddress, addr_t physicalAddress,
|
|
||||||
uint8 attributes, addr_t (*get_free_page)(kernel_args *))
|
|
||||||
{
|
|
||||||
uint32 virtualSegmentID = get_sr((void *)virtualAddress) & 0xffffff;
|
|
||||||
|
|
||||||
uint32 hash = page_table_entry::PrimaryHash(virtualSegmentID, (uint32)virtualAddress);
|
|
||||||
page_table_entry_group *group = &sPageTable[hash & sPageTableHashMask];
|
|
||||||
|
|
||||||
for (int32 i = 0; i < 8; i++) {
|
|
||||||
// 8 entries in a group
|
|
||||||
if (group->entry[i].valid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
fill_page_table_entry(&group->entry[i], virtualSegmentID, virtualAddress, physicalAddress, PTE_READ_WRITE, false);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
hash = page_table_entry::SecondaryHash(hash);
|
|
||||||
group = &sPageTable[hash & sPageTableHashMask];
|
|
||||||
|
|
||||||
for (int32 i = 0; i < 8; i++) {
|
|
||||||
if (group->entry[i].valid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
fill_page_table_entry(&group->entry[i], virtualSegmentID, virtualAddress, physicalAddress, PTE_READ_WRITE, true);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// XXX currently assumes this translation map is active
|
|
||||||
|
|
||||||
status_t
|
|
||||||
arch_vm_translation_map_early_query(addr_t va, addr_t *out_physical)
|
|
||||||
{
|
|
||||||
//PANIC_UNIMPLEMENTED();
|
|
||||||
panic("vm_translation_map_quick_query(): not yet implemented\n");
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user