vxKernel/src/drivers/mpu/sh/sh7305/mmu/utlb.c

57 lines
1.4 KiB
C

//---
// vhex:mmu:mmu - MMU driver definition and context management
//---
#include <vhex/drivers/mmu.h>
#include <vhex/arch/sh7305/mmu.h>
#include <vhex/defs/attributes.h>
/* utlb_addr() - get the P4 address of a UTLB address entry */
VINLINE const struct utlb_addr *utlb_addr(uint E)
{
uintptr_t addr = 0xf6000000 | ((E & 0x3f) << 8);
return (void *)addr;
}
/* utlb_data() - get the P4 address of a UTLB data entry */
VINLINE const struct utlb_data *utlb_data(uint E)
{
uintptr_t addr = 0xf7000000 | ((E & 0x3f) << 8);
return (void *)addr;
}
/* mmu_translate(): Get the physical address for a virtual page */
uintptr_t mmu_translate(uintptr_t page, size_t *size)
{
for(int E = 0; E < 64; E++)
{
const struct utlb_addr *addr = utlb_addr(E);
const struct utlb_data *data = utlb_data(E);
if(!addr->V || !data->V) continue;
if((uintptr_t)addr->VPN << 10 == page)
{
/* Magic formula to get the size without using an array
since this code is used even before global data is
posibly initialized */
int sz = ((data->SZ1 << 1) | data->SZ2) << 3;
if(size) *size = 1 << ((0x14100c0a >> sz) & 0xff);
return data->PPN << 10;
}
}
return -1;
}
/* mmu_uram_size(): Get size of user RAM area */
size_t mmu_uram_size(void)
{
size_t size = 0;
size_t pagesize;
while(mmu_translate(0x08100000 + size, &pagesize) != (uintptr_t)-1) {
size += pagesize;
}
return size;
}