HelenOS sources
This source file includes following definitions.
- frame_available
- frame_safe
- frame_add_region
- frame_low_arch_init
- frame_high_arch_init
- physmem_print
#include <macros.h>
#include <arch/mm/frame.h>
#include <arch/mm/tlb.h>
#include <interrupt.h>
#include <mm/frame.h>
#include <mm/asid.h>
#include <config.h>
#ifdef MACHINE_msim
#include <arch/mach/msim/msim.h>
#endif
#include <arch/arch.h>
#include <stdio.h>
#define ZERO_PAGE_MASK TLB_PAGE_MASK_256K
#define ZERO_FRAMES 2048
#define ZERO_PAGE_WIDTH 18
#define ZERO_PAGE_SIZE (1 << ZERO_PAGE_WIDTH)
#define ZERO_PAGE_ASID ASID_INVALID
#define ZERO_PAGE_TLBI 0
#define ZERO_PAGE_ADDR 0
#define ZERO_PAGE_OFFSET (ZERO_PAGE_SIZE / sizeof(uint32_t) - 1)
#define ZERO_PAGE_VALUE (((volatile uint32_t *) ZERO_PAGE_ADDR)[ZERO_PAGE_OFFSET])
#define ZERO_PAGE_VALUE_KSEG1(frame) \
(((volatile uint32_t *) PA2KSEG1(frame << ZERO_PAGE_WIDTH))[ZERO_PAGE_OFFSET])
#define MAX_REGIONS 32
typedef struct {
pfn_t start;
pfn_t count;
} phys_region_t;
static size_t phys_regions_count = 0;
static phys_region_t phys_regions[MAX_REGIONS];
static bool frame_available(pfn_t frame)
{
#ifdef MACHINE_msim
if (frame == (KSEG12PA(MSIM_VIDEORAM) >> ZERO_PAGE_WIDTH))
return false;
if (frame == (KSEG12PA(MSIM_KBD_ADDRESS) >> ZERO_PAGE_WIDTH))
return false;
#endif
#if defined(MACHINE_lmalta) || defined(MACHINE_bmalta)
if (frame >= (sdram_size >> ZERO_PAGE_WIDTH))
return false;
#endif
return true;
}
static bool frame_safe(pfn_t frame)
{
if ((frame << ZERO_PAGE_WIDTH) < KA2PA(config.base))
return false;
if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
KA2PA(config.base), config.kernel_size))
return false;
if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
KA2PA(ballocs.base), ballocs.size))
return false;
bool safe = true;
size_t i;
for (i = 0; i < init.cnt; i++)
if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
init.tasks[i].paddr, init.tasks[i].size)) {
safe = false;
break;
}
return safe;
}
static void frame_add_region(pfn_t start_frame, pfn_t end_frame, bool low)
{
if (end_frame <= start_frame)
return;
uintptr_t base = start_frame << ZERO_PAGE_WIDTH;
size_t size = (end_frame - start_frame) << ZERO_PAGE_WIDTH;
if (!frame_adjust_zone_bounds(low, &base, &size))
return;
pfn_t first = ADDR2PFN(base);
size_t count = SIZE2FRAMES(size);
pfn_t conf_frame;
if (low) {
if (first == 0)
conf_frame = 1;
else
conf_frame = first;
zone_create(first, count, conf_frame,
ZONE_AVAILABLE | ZONE_LOWMEM);
} else {
conf_frame = zone_external_conf_alloc(count);
if (conf_frame != 0)
zone_create(first, count, conf_frame,
ZONE_AVAILABLE | ZONE_HIGHMEM);
}
if (phys_regions_count < MAX_REGIONS) {
phys_regions[phys_regions_count].start = first;
phys_regions[phys_regions_count].count = count;
phys_regions_count++;
}
}
void frame_low_arch_init(void)
{
ipl_t ipl = interrupts_disable();
cp0_pagemask_write(ZERO_PAGE_MASK);
cp0_entry_lo0_write(0);
cp0_entry_lo1_write(0);
cp0_entry_hi_write(0);
size_t i;
for (i = 0; i < TLB_ENTRY_COUNT; i++) {
cp0_index_write(i);
tlbwi();
}
pfn_t start_frame = 0;
pfn_t frame;
bool avail = true;
for (frame = 0; frame < ZERO_FRAMES; frame++) {
if (!frame_available(frame))
avail = false;
else {
if (frame_safe(frame)) {
entry_lo_t lo0;
entry_lo_t lo1;
entry_hi_t hi;
tlb_prepare_entry_lo(&lo0, false, true, true, false, frame << (ZERO_PAGE_WIDTH - 12));
tlb_prepare_entry_lo(&lo1, false, false, false, false, 0);
tlb_prepare_entry_hi(&hi, ZERO_PAGE_ASID, ZERO_PAGE_ADDR);
cp0_pagemask_write(ZERO_PAGE_MASK);
cp0_entry_lo0_write(lo0.value);
cp0_entry_lo1_write(lo1.value);
cp0_entry_hi_write(hi.value);
cp0_index_write(ZERO_PAGE_TLBI);
tlbwi();
ZERO_PAGE_VALUE = 0;
if (ZERO_PAGE_VALUE != 0)
avail = false;
else {
ZERO_PAGE_VALUE = 0xdeadbeef;
if (ZERO_PAGE_VALUE != 0xdeadbeef)
avail = false;
}
}
}
if (!avail) {
frame_add_region(start_frame, frame, true);
start_frame = frame + 1;
avail = true;
}
}
frame_add_region(start_frame, frame, true);
frame_mark_unavailable(0, 1);
#if defined(MACHINE_lmalta) || defined(MACHINE_bmalta)
frame_mark_unavailable(0, 1024 * 1024 / FRAME_SIZE);
#endif
cp0_pagemask_write(ZERO_PAGE_MASK);
cp0_entry_lo0_write(0);
cp0_entry_lo1_write(0);
cp0_entry_hi_write(0);
cp0_index_write(ZERO_PAGE_TLBI);
tlbwi();
interrupts_restore(ipl);
}
void frame_high_arch_init(void)
{
}
void physmem_print(void)
{
printf("[base ] [size ]\n");
size_t i;
for (i = 0; i < phys_regions_count; i++) {
printf("%#010x %10u\n",
PFN2ADDR(phys_regions[i].start), PFN2ADDR(phys_regions[i].count));
}
}
HelenOS homepage, sources at GitHub