aboutsummaryrefslogtreecommitdiffstats
path: root/extras/mini-os/arch
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2009-03-02 10:52:07 +0000
committerKeir Fraser <keir.fraser@citrix.com>2009-03-02 10:52:07 +0000
commitbe9ce82fc47d82f3653bb4e25cdd9dbec97356ff (patch)
tree595e258122314a6b6bc21af1afc0631871d9e358 /extras/mini-os/arch
parent6767a71fdd87ab218804a7f63ba71d4c2309b820 (diff)
downloadxen-be9ce82fc47d82f3653bb4e25cdd9dbec97356ff.tar.gz
xen-be9ce82fc47d82f3653bb4e25cdd9dbec97356ff.tar.bz2
xen-be9ce82fc47d82f3653bb4e25cdd9dbec97356ff.zip
minios: general cleanup of mm.c
Major clean up of mm.c. Added comments, fixed coding style, more sensible variable names, mark some local functions static etc. Signed-off-by: Rolf Neugebauer <rolf.neugebauer@netronome.com> Acked-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Diffstat (limited to 'extras/mini-os/arch')
-rw-r--r--extras/mini-os/arch/x86/mm.c489
-rw-r--r--extras/mini-os/arch/x86/setup.c8
2 files changed, 292 insertions, 205 deletions
diff --git a/extras/mini-os/arch/x86/mm.c b/extras/mini-os/arch/x86/mm.c
index 696c4662b6..6a2cb351f3 100644
--- a/extras/mini-os/arch/x86/mm.c
+++ b/extras/mini-os/arch/x86/mm.c
@@ -52,20 +52,26 @@
unsigned long *phys_to_machine_mapping;
unsigned long mfn_zero;
extern char stack[];
-extern void page_walk(unsigned long virt_addr);
+extern void page_walk(unsigned long va);
-void new_pt_frame(unsigned long *pt_pfn, unsigned long prev_l_mfn,
- unsigned long offset, unsigned long level)
+/*
+ * Make pt_pfn a new 'level' page table frame and hook it into the page
+ * table at offset in previous level MFN (pref_l_mfn). pt_pfn is a guest
+ * PFN.
+ */
+static void new_pt_frame(unsigned long *pt_pfn, unsigned long prev_l_mfn,
+ unsigned long offset, unsigned long level)
{
pgentry_t *tab = (pgentry_t *)start_info.pt_base;
unsigned long pt_page = (unsigned long)pfn_to_virt(*pt_pfn);
pgentry_t prot_e, prot_t;
mmu_update_t mmu_updates[1];
+ int rc;
prot_e = prot_t = 0;
- DEBUG("Allocating new L%d pt frame for pt_pfn=%lx, "
- "prev_l_mfn=%lx, offset=%lx",
- level, *pt_pfn, prev_l_mfn, offset);
+ DEBUG("Allocating new L%d pt frame for pfn=%lx, "
+ "prev_l_mfn=%lx, offset=%lx",
+ level, *pt_pfn, prev_l_mfn, offset);
/* We need to clear the page, otherwise we might fail to map it
as a page table page */
@@ -74,56 +80,63 @@ void new_pt_frame(unsigned long *pt_pfn, unsigned long prev_l_mfn,
switch ( level )
{
case L1_FRAME:
- prot_e = L1_PROT;
- prot_t = L2_PROT;
- break;
+ prot_e = L1_PROT;
+ prot_t = L2_PROT;
+ break;
case L2_FRAME:
- prot_e = L2_PROT;
- prot_t = L3_PROT;
- break;
+ prot_e = L2_PROT;
+ prot_t = L3_PROT;
+ break;
#if defined(__x86_64__)
case L3_FRAME:
- prot_e = L3_PROT;
- prot_t = L4_PROT;
- break;
+ prot_e = L3_PROT;
+ prot_t = L4_PROT;
+ break;
#endif
default:
- printk("new_pt_frame() called with invalid level number %d\n", level);
- do_exit();
- break;
+ printk("new_pt_frame() called with invalid level number %d\n", level);
+ do_exit();
+ break;
}
- /* Update the entry */
+ /* Make PFN a page table page */
#if defined(__x86_64__)
tab = pte_to_virt(tab[l4_table_offset(pt_page)]);
#endif
tab = pte_to_virt(tab[l3_table_offset(pt_page)]);
mmu_updates[0].ptr = (tab[l2_table_offset(pt_page)] & PAGE_MASK) +
- sizeof(pgentry_t) * l1_table_offset(pt_page);
+ sizeof(pgentry_t) * l1_table_offset(pt_page);
mmu_updates[0].val = (pgentry_t)pfn_to_mfn(*pt_pfn) << PAGE_SHIFT |
- (prot_e & ~_PAGE_RW);
- if(HYPERVISOR_mmu_update(mmu_updates, 1, NULL, DOMID_SELF) < 0)
+ (prot_e & ~_PAGE_RW);
+
+ if ( (rc = HYPERVISOR_mmu_update(mmu_updates, 1, NULL, DOMID_SELF)) < 0 )
{
- printk("PTE for new page table page could not be updated\n");
- do_exit();
+ printk("ERROR: PTE for new page table page could not be updated\n");
+ printk(" mmu_update failed with rc=%d\n", rc);
+ do_exit();
}
-
- /* Now fill the new page table page with entries.
- Update the page directory as well. */
- mmu_updates[0].ptr = ((pgentry_t)prev_l_mfn << PAGE_SHIFT) + sizeof(pgentry_t) * offset;
+
+ /* Hook the new page table page into the hierarchy */
+ mmu_updates[0].ptr =
+ ((pgentry_t)prev_l_mfn << PAGE_SHIFT) + sizeof(pgentry_t) * offset;
mmu_updates[0].val = (pgentry_t)pfn_to_mfn(*pt_pfn) << PAGE_SHIFT | prot_t;
- if(HYPERVISOR_mmu_update(mmu_updates, 1, NULL, DOMID_SELF) < 0)
+
+ if ( (rc = HYPERVISOR_mmu_update(mmu_updates, 1, NULL, DOMID_SELF)) < 0 )
{
- printk("ERROR: mmu_update failed\n");
- do_exit();
+ printk("ERROR: mmu_update failed with rc=%d\n", rc);
+ do_exit();
}
*pt_pfn += 1;
}
-/* Checks if a pagetable frame is needed (if weren't allocated by Xen) */
-static int need_pt_frame(unsigned long virt_address, int level)
+/*
+ * Checks if a pagetable frame is needed at 'level' to map a given
+ * address. Note, this function is specific to the initial page table
+ * building.
+ */
+static int need_pt_frame(unsigned long va, int level)
{
unsigned long hyp_virt_start = HYPERVISOR_VIRT_START;
#if defined(__x86_64__)
@@ -135,63 +148,71 @@ static int need_pt_frame(unsigned long virt_address, int level)
/* In general frames will _not_ be needed if they were already
allocated to map the hypervisor into our VA space */
#if defined(__x86_64__)
- if(level == L3_FRAME)
+ if ( level == L3_FRAME )
{
- if(l4_table_offset(virt_address) >=
- l4_table_offset(hyp_virt_start) &&
- l4_table_offset(virt_address) <=
- l4_table_offset(hyp_virt_end))
+ if ( l4_table_offset(va) >=
+ l4_table_offset(hyp_virt_start) &&
+ l4_table_offset(va) <=
+ l4_table_offset(hyp_virt_end))
return 0;
return 1;
- } else
+ }
+ else
#endif
- if(level == L2_FRAME)
+ if ( level == L2_FRAME )
{
#if defined(__x86_64__)
- if(l4_table_offset(virt_address) >=
- l4_table_offset(hyp_virt_start) &&
- l4_table_offset(virt_address) <=
- l4_table_offset(hyp_virt_end))
+ if ( l4_table_offset(va) >=
+ l4_table_offset(hyp_virt_start) &&
+ l4_table_offset(va) <=
+ l4_table_offset(hyp_virt_end))
#endif
- if(l3_table_offset(virt_address) >=
- l3_table_offset(hyp_virt_start) &&
- l3_table_offset(virt_address) <=
- l3_table_offset(hyp_virt_end))
+ if ( l3_table_offset(va) >=
+ l3_table_offset(hyp_virt_start) &&
+ l3_table_offset(va) <=
+ l3_table_offset(hyp_virt_end))
return 0;
return 1;
- } else
-
- /* Always need l1 frames */
- if(level == L1_FRAME)
- return 1;
+ }
+ else
+ /* Always need l1 frames */
+ if ( level == L1_FRAME )
+ return 1;
printk("ERROR: Unknown frame level %d, hypervisor %llx,%llx\n",
- level, hyp_virt_start, hyp_virt_end);
+ level, hyp_virt_start, hyp_virt_end);
return -1;
}
-void build_pagetable(unsigned long *start_pfn, unsigned long *max_pfn)
+/*
+ * Build the initial pagetable.
+ */
+static void build_pagetable(unsigned long *start_pfn, unsigned long *max_pfn)
{
unsigned long start_address, end_address;
unsigned long pfn_to_map, pt_pfn = *start_pfn;
static mmu_update_t mmu_updates[L1_PAGETABLE_ENTRIES + 1];
pgentry_t *tab = (pgentry_t *)start_info.pt_base, page;
- unsigned long mfn = pfn_to_mfn(virt_to_pfn(start_info.pt_base));
+ unsigned long pt_mfn = pfn_to_mfn(virt_to_pfn(start_info.pt_base));
unsigned long offset;
int count = 0;
+ int rc;
- pfn_to_map = (start_info.nr_pt_frames - NOT_L1_FRAMES) * L1_PAGETABLE_ENTRIES;
+ pfn_to_map =
+ (start_info.nr_pt_frames - NOT_L1_FRAMES) * L1_PAGETABLE_ENTRIES;
- if (*max_pfn >= virt_to_pfn(HYPERVISOR_VIRT_START))
+ if ( *max_pfn >= virt_to_pfn(HYPERVISOR_VIRT_START) )
{
printk("WARNING: Mini-OS trying to use Xen virtual space. "
"Truncating memory from %dMB to ",
- ((unsigned long)pfn_to_virt(*max_pfn) - (unsigned long)&_text)>>20);
+ ((unsigned long)pfn_to_virt(*max_pfn) -
+ (unsigned long)&_text)>>20);
*max_pfn = virt_to_pfn(HYPERVISOR_VIRT_START - PAGE_SIZE);
printk("%dMB\n",
- ((unsigned long)pfn_to_virt(*max_pfn) - (unsigned long)&_text)>>20);
+ ((unsigned long)pfn_to_virt(*max_pfn) -
+ (unsigned long)&_text)>>20);
}
start_address = (unsigned long)pfn_to_virt(pfn_to_map);
@@ -200,49 +221,53 @@ void build_pagetable(unsigned long *start_pfn, unsigned long *max_pfn)
/* We worked out the virtual memory range to map, now mapping loop */
printk("Mapping memory range 0x%lx - 0x%lx\n", start_address, end_address);
- while(start_address < end_address)
+ while ( start_address < end_address )
{
tab = (pgentry_t *)start_info.pt_base;
- mfn = pfn_to_mfn(virt_to_pfn(start_info.pt_base));
+ pt_mfn = pfn_to_mfn(virt_to_pfn(start_info.pt_base));
#if defined(__x86_64__)
offset = l4_table_offset(start_address);
/* Need new L3 pt frame */
- if(!(start_address & L3_MASK))
- if(need_pt_frame(start_address, L3_FRAME))
- new_pt_frame(&pt_pfn, mfn, offset, L3_FRAME);
+ if ( !(start_address & L3_MASK) )
+ if ( need_pt_frame(start_address, L3_FRAME) )
+ new_pt_frame(&pt_pfn, pt_mfn, offset, L3_FRAME);
page = tab[offset];
- mfn = pte_to_mfn(page);
- tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT);
+ pt_mfn = pte_to_mfn(page);
+ tab = to_virt(mfn_to_pfn(pt_mfn) << PAGE_SHIFT);
#endif
offset = l3_table_offset(start_address);
/* Need new L2 pt frame */
- if(!(start_address & L2_MASK))
- if(need_pt_frame(start_address, L2_FRAME))
- new_pt_frame(&pt_pfn, mfn, offset, L2_FRAME);
+ if ( !(start_address & L2_MASK) )
+ if ( need_pt_frame(start_address, L2_FRAME) )
+ new_pt_frame(&pt_pfn, pt_mfn, offset, L2_FRAME);
page = tab[offset];
- mfn = pte_to_mfn(page);
- tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT);
+ pt_mfn = pte_to_mfn(page);
+ tab = to_virt(mfn_to_pfn(pt_mfn) << PAGE_SHIFT);
offset = l2_table_offset(start_address);
/* Need new L1 pt frame */
- if(!(start_address & L1_MASK))
- if(need_pt_frame(start_address, L1_FRAME))
- new_pt_frame(&pt_pfn, mfn, offset, L1_FRAME);
+ if ( !(start_address & L1_MASK) )
+ if ( need_pt_frame(start_address, L1_FRAME) )
+ new_pt_frame(&pt_pfn, pt_mfn, offset, L1_FRAME);
page = tab[offset];
- mfn = pte_to_mfn(page);
+ pt_mfn = pte_to_mfn(page);
offset = l1_table_offset(start_address);
- mmu_updates[count].ptr = ((pgentry_t)mfn << PAGE_SHIFT) + sizeof(pgentry_t) * offset;
- mmu_updates[count].val = (pgentry_t)pfn_to_mfn(pfn_to_map++) << PAGE_SHIFT | L1_PROT;
+ mmu_updates[count].ptr =
+ ((pgentry_t)pt_mfn << PAGE_SHIFT) + sizeof(pgentry_t) * offset;
+ mmu_updates[count].val =
+ (pgentry_t)pfn_to_mfn(pfn_to_map++) << PAGE_SHIFT | L1_PROT;
count++;
- if (count == L1_PAGETABLE_ENTRIES || pfn_to_map == *max_pfn)
+ if ( count == L1_PAGETABLE_ENTRIES || pfn_to_map == *max_pfn )
{
- if(HYPERVISOR_mmu_update(mmu_updates, count, NULL, DOMID_SELF) < 0)
+ rc = HYPERVISOR_mmu_update(mmu_updates, count, NULL, DOMID_SELF);
+ if ( rc < 0 )
{
- printk("PTE could not be updated\n");
+ printk("ERROR: build_pagetable(): PTE could not be updated\n");
+ printk(" mmu_update failed with rc=%d\n", rc);
do_exit();
}
count = 0;
@@ -253,20 +278,26 @@ void build_pagetable(unsigned long *start_pfn, unsigned long *max_pfn)
*start_pfn = pt_pfn;
}
+/*
+ * Mark portion of the address space read only.
+ */
extern void shared_info;
static void set_readonly(void *text, void *etext)
{
- unsigned long start_address = ((unsigned long) text + PAGE_SIZE - 1) & PAGE_MASK;
+ unsigned long start_address =
+ ((unsigned long) text + PAGE_SIZE - 1) & PAGE_MASK;
unsigned long end_address = (unsigned long) etext;
static mmu_update_t mmu_updates[L1_PAGETABLE_ENTRIES + 1];
pgentry_t *tab = (pgentry_t *)start_info.pt_base, page;
unsigned long mfn = pfn_to_mfn(virt_to_pfn(start_info.pt_base));
unsigned long offset;
int count = 0;
+ int rc;
printk("setting %p-%p readonly\n", text, etext);
- while (start_address + PAGE_SIZE <= end_address) {
+ while ( start_address + PAGE_SIZE <= end_address )
+ {
tab = (pgentry_t *)start_info.pt_base;
mfn = pfn_to_mfn(virt_to_pfn(start_info.pt_base));
@@ -287,20 +318,25 @@ static void set_readonly(void *text, void *etext)
offset = l1_table_offset(start_address);
- if (start_address != (unsigned long)&shared_info) {
- mmu_updates[count].ptr = ((pgentry_t)mfn << PAGE_SHIFT) + sizeof(pgentry_t) * offset;
- mmu_updates[count].val = tab[offset] & ~_PAGE_RW;
- count++;
- } else
- printk("skipped %p\n", start_address);
+ if ( start_address != (unsigned long)&shared_info )
+ {
+ mmu_updates[count].ptr =
+ ((pgentry_t)mfn << PAGE_SHIFT) + sizeof(pgentry_t) * offset;
+ mmu_updates[count].val = tab[offset] & ~_PAGE_RW;
+ count++;
+ }
+ else
+ printk("skipped %p\n", start_address);
start_address += PAGE_SIZE;
- if (count == L1_PAGETABLE_ENTRIES || start_address + PAGE_SIZE > end_address)
+ if ( count == L1_PAGETABLE_ENTRIES ||
+ start_address + PAGE_SIZE > end_address )
{
- if(HYPERVISOR_mmu_update(mmu_updates, count, NULL, DOMID_SELF) < 0)
+ rc = HYPERVISOR_mmu_update(mmu_updates, count, NULL, DOMID_SELF);
+ if ( rc < 0 )
{
- printk("PTE could not be updated\n");
+ printk("ERROR: set_readonly(): PTE could not be updated\n");
do_exit();
}
count = 0;
@@ -308,11 +344,11 @@ static void set_readonly(void *text, void *etext)
}
{
- mmuext_op_t op = {
- .cmd = MMUEXT_TLB_FLUSH_ALL,
- };
- int count;
- HYPERVISOR_mmuext_op(&op, 1, &count, DOMID_SELF);
+ mmuext_op_t op = {
+ .cmd = MMUEXT_TLB_FLUSH_ALL,
+ };
+ int count;
+ HYPERVISOR_mmuext_op(&op, 1, &count, DOMID_SELF);
}
}
@@ -371,7 +407,10 @@ int mem_test(unsigned long *start_va, unsigned long *end_va, int verbose)
}
-static pgentry_t *get_pgt(unsigned long addr)
+/*
+ * get the PTE for virtual address va if it exists. Otherwise NULL.
+ */
+static pgentry_t *get_pgt(unsigned long va)
{
unsigned long mfn;
pgentry_t *tab;
@@ -381,67 +420,78 @@ static pgentry_t *get_pgt(unsigned long addr)
mfn = virt_to_mfn(start_info.pt_base);
#if defined(__x86_64__)
- offset = l4_table_offset(addr);
- if (!(tab[offset] & _PAGE_PRESENT))
+ offset = l4_table_offset(va);
+ if ( !(tab[offset] & _PAGE_PRESENT) )
return NULL;
mfn = pte_to_mfn(tab[offset]);
tab = mfn_to_virt(mfn);
#endif
- offset = l3_table_offset(addr);
- if (!(tab[offset] & _PAGE_PRESENT))
+ offset = l3_table_offset(va);
+ if ( !(tab[offset] & _PAGE_PRESENT) )
return NULL;
mfn = pte_to_mfn(tab[offset]);
tab = mfn_to_virt(mfn);
- offset = l2_table_offset(addr);
- if (!(tab[offset] & _PAGE_PRESENT))
+ offset = l2_table_offset(va);
+ if ( !(tab[offset] & _PAGE_PRESENT) )
return NULL;
mfn = pte_to_mfn(tab[offset]);
tab = mfn_to_virt(mfn);
- offset = l1_table_offset(addr);
+ offset = l1_table_offset(va);
return &tab[offset];
}
-pgentry_t *need_pgt(unsigned long addr)
+
+/*
+ * return a valid PTE for a given virtual address. If PTE does not exist,
+ * allocate page-table pages.
+ */
+pgentry_t *need_pgt(unsigned long va)
{
- unsigned long mfn;
+ unsigned long pt_mfn;
pgentry_t *tab;
unsigned long pt_pfn;
unsigned offset;
tab = (pgentry_t *)start_info.pt_base;
- mfn = virt_to_mfn(start_info.pt_base);
+ pt_mfn = virt_to_mfn(start_info.pt_base);
#if defined(__x86_64__)
- offset = l4_table_offset(addr);
- if (!(tab[offset] & _PAGE_PRESENT)) {
+ offset = l4_table_offset(va);
+ if ( !(tab[offset] & _PAGE_PRESENT) )
+ {
pt_pfn = virt_to_pfn(alloc_page());
- new_pt_frame(&pt_pfn, mfn, offset, L3_FRAME);
+ new_pt_frame(&pt_pfn, pt_mfn, offset, L3_FRAME);
}
ASSERT(tab[offset] & _PAGE_PRESENT);
- mfn = pte_to_mfn(tab[offset]);
- tab = mfn_to_virt(mfn);
+ pt_mfn = pte_to_mfn(tab[offset]);
+ tab = mfn_to_virt(pt_mfn);
#endif
- offset = l3_table_offset(addr);
- if (!(tab[offset] & _PAGE_PRESENT)) {
+ offset = l3_table_offset(va);
+ if ( !(tab[offset] & _PAGE_PRESENT) )
+ {
pt_pfn = virt_to_pfn(alloc_page());
- new_pt_frame(&pt_pfn, mfn, offset, L2_FRAME);
+ new_pt_frame(&pt_pfn, pt_mfn, offset, L2_FRAME);
}
ASSERT(tab[offset] & _PAGE_PRESENT);
- mfn = pte_to_mfn(tab[offset]);
- tab = mfn_to_virt(mfn);
- offset = l2_table_offset(addr);
- if (!(tab[offset] & _PAGE_PRESENT)) {
+ pt_mfn = pte_to_mfn(tab[offset]);
+ tab = mfn_to_virt(pt_mfn);
+ offset = l2_table_offset(va);
+ if ( !(tab[offset] & _PAGE_PRESENT) )
+ {
pt_pfn = virt_to_pfn(alloc_page());
- new_pt_frame(&pt_pfn, mfn, offset, L1_FRAME);
+ new_pt_frame(&pt_pfn, pt_mfn, offset, L1_FRAME);
}
ASSERT(tab[offset] & _PAGE_PRESENT);
- mfn = pte_to_mfn(tab[offset]);
- tab = mfn_to_virt(mfn);
+ pt_mfn = pte_to_mfn(tab[offset]);
+ tab = mfn_to_virt(pt_mfn);
- offset = l1_table_offset(addr);
+ offset = l1_table_offset(va);
return &tab[offset];
}
+/*
+ * Reserve an area of virtual address space for mappings and Heap
+ */
static unsigned long demand_map_area_start;
#ifdef __x86_64__
#define DEMAND_MAP_PAGES ((128ULL << 30) / PAGE_SIZE)
@@ -466,7 +516,8 @@ void arch_init_demand_mapping_area(unsigned long cur_pfn)
demand_map_area_start = (unsigned long) pfn_to_virt(cur_pfn);
cur_pfn += DEMAND_MAP_PAGES;
- printk("Demand map pfns at %lx-%lx.\n", demand_map_area_start, pfn_to_virt(cur_pfn));
+ printk("Demand map pfns at %lx-%lx.\n",
+ demand_map_area_start, pfn_to_virt(cur_pfn));
#ifdef HAVE_LIBC
cur_pfn++;
@@ -477,93 +528,123 @@ void arch_init_demand_mapping_area(unsigned long cur_pfn)
#endif
}
-#define MAP_BATCH ((STACK_SIZE / 2) / sizeof(mmu_update_t))
-void do_map_frames(unsigned long addr,
- unsigned long *f, unsigned long n, unsigned long stride,
- unsigned long increment, domid_t id, int may_fail, unsigned long prot)
-{
- pgentry_t *pgt = NULL;
- unsigned long done = 0;
- unsigned long i;
- int rc;
-
- while (done < n) {
- unsigned long todo;
-
- if (may_fail)
- todo = 1;
- else
- todo = n - done;
-
- if (todo > MAP_BATCH)
- todo = MAP_BATCH;
-
- {
- mmu_update_t mmu_updates[todo];
-
- for (i = 0; i < todo; i++, addr += PAGE_SIZE, pgt++) {
- if (!pgt || !(addr & L1_MASK))
- pgt = need_pgt(addr);
- mmu_updates[i].ptr = virt_to_mach(pgt);
- mmu_updates[i].val = ((pgentry_t)(f[(done + i) * stride] + (done + i) * increment) << PAGE_SHIFT) | prot;
- }
-
- rc = HYPERVISOR_mmu_update(mmu_updates, todo, NULL, id);
- if (rc < 0) {
- if (may_fail)
- f[done * stride] |= 0xF0000000;
- else {
- printk("Map %ld (%lx, ...) at %p failed: %d.\n", todo, f[done * stride] + done * increment, addr, rc);
- do_exit();
- }
- }
- }
-
- done += todo;
- }
-}
-
unsigned long allocate_ondemand(unsigned long n, unsigned long alignment)
{
unsigned long x;
unsigned long y = 0;
/* Find a properly aligned run of n contiguous frames */
- for (x = 0; x <= DEMAND_MAP_PAGES - n; x = (x + y + 1 + alignment - 1) & ~(alignment - 1)) {
+ for ( x = 0;
+ x <= DEMAND_MAP_PAGES - n;
+ x = (x + y + 1 + alignment - 1) & ~(alignment - 1) )
+ {
unsigned long addr = demand_map_area_start + x * PAGE_SIZE;
pgentry_t *pgt = get_pgt(addr);
- for (y = 0; y < n; y++, addr += PAGE_SIZE) {
- if (!(addr & L1_MASK))
+ for ( y = 0; y < n; y++, addr += PAGE_SIZE )
+ {
+ if ( !(addr & L1_MASK) )
pgt = get_pgt(addr);
- if (pgt) {
- if (*pgt & _PAGE_PRESENT)
+ if ( pgt )
+ {
+ if ( *pgt & _PAGE_PRESENT )
break;
pgt++;
}
}
- if (y == n)
+ if ( y == n )
break;
}
- if (y != n) {
+ if ( y != n )
+ {
printk("Failed to find %ld frames!\n", n);
return 0;
}
return demand_map_area_start + x * PAGE_SIZE;
}
-void *map_frames_ex(unsigned long *f, unsigned long n, unsigned long stride,
- unsigned long increment, unsigned long alignment, domid_t id,
- int may_fail, unsigned long prot)
+/*
+ * Map an array of MFNs contiguously into virtual address space starting at
+ * va. map f[i*stride]+i*increment for i in 0..n-1.
+ */
+#define MAP_BATCH ((STACK_SIZE / 2) / sizeof(mmu_update_t))
+void do_map_frames(unsigned long va,
+ unsigned long *mfns, unsigned long n,
+ unsigned long stride, unsigned long incr,
+ domid_t id, int may_fail,
+ unsigned long prot)
+{
+ pgentry_t *pgt = NULL;
+ unsigned long done = 0;
+ unsigned long i;
+ int rc;
+
+ if ( !mfns )
+ {
+ printk("do_map_frames: no mfns supplied\n");
+ return;
+ }
+ DEBUG("va=%p n=0x%lx, mfns[0]=0x%lx stride=0x%lx incr=0x%lx prot=0x%lx\n",
+ va, n, mfns[0], stride, incr, prot);
+
+ while ( done < n )
+ {
+ unsigned long todo;
+
+ if ( may_fail )
+ todo = 1;
+ else
+ todo = n - done;
+
+ if ( todo > MAP_BATCH )
+ todo = MAP_BATCH;
+
+ {
+ mmu_update_t mmu_updates[todo];
+
+ for ( i = 0; i < todo; i++, va += PAGE_SIZE, pgt++)
+ {
+ if ( !pgt || !(va & L1_MASK) )
+ pgt = need_pgt(va);
+
+ mmu_updates[i].ptr = virt_to_mach(pgt) | MMU_NORMAL_PT_UPDATE;
+ mmu_updates[i].val = ((pgentry_t)(mfns[(done + i) * stride] +
+ (done + i) * incr)
+ << PAGE_SHIFT) | prot;
+ }
+
+ rc = HYPERVISOR_mmu_update(mmu_updates, todo, NULL, id);
+ if ( rc < 0 )
+ {
+ if (may_fail)
+ mfns[done * stride] |= 0xF0000000;
+ else {
+ printk("Map %ld (%lx, ...) at %p failed: %d.\n",
+ todo, mfns[done * stride] + done * incr, va, rc);
+ do_exit();
+ }
+ }
+ }
+ done += todo;
+ }
+}
+
+/*
+ * Map an array of MFNs contiguous into virtual address space. Virtual
+ * addresses are allocated from the on demand area.
+ */
+void *map_frames_ex(unsigned long *mfns, unsigned long n,
+ unsigned long stride, unsigned long incr,
+ unsigned long alignment,
+ domid_t id, int may_fail, unsigned long prot)
{
- unsigned long addr = allocate_ondemand(n, alignment);
+ unsigned long va = allocate_ondemand(n, alignment);
- if (!addr)
+ if ( !va )
return NULL;
- /* Found it at x. Map it in. */
- do_map_frames(addr, f, n, stride, increment, id, may_fail, prot);
+ do_map_frames(va, mfns, n, stride, incr, id, may_fail, prot);
- return (void *)addr;
+ return (void *)va;
}
/*
@@ -632,15 +713,19 @@ int mfn_is_ram(unsigned long mfn)
}
+/*
+ * Clear some of the bootstrap memory
+ */
static void clear_bootstrap(void)
{
pte_t nullpte = { };
+ int rc;
/* Use first page as the CoW zero page */
memset(&_text, 0, PAGE_SIZE);
mfn_zero = virt_to_mfn((unsigned long) &_text);
- if (HYPERVISOR_update_va_mapping(0, nullpte, UVMF_INVLPG))
- printk("Unable to unmap NULL page\n");
+ if ( (rc = HYPERVISOR_update_va_mapping(0, nullpte, UVMF_INVLPG)) )
+ printk("Unable to unmap NULL page. rc=%d\n", rc);
}
void arch_init_p2m(unsigned long max_pfn)
@@ -665,19 +750,19 @@ void arch_init_p2m(unsigned long max_pfn)
unsigned long pfn;
l3_list = (unsigned long *)alloc_page();
- for(pfn=0; pfn<max_pfn; pfn++)
+ for ( pfn=0; pfn<max_pfn; pfn++ )
{
- if(!(pfn % (L1_P2M_ENTRIES * L2_P2M_ENTRIES)))
+ if ( !(pfn % (L1_P2M_ENTRIES * L2_P2M_ENTRIES)) )
{
l2_list = (unsigned long*)alloc_page();
- if((pfn >> L3_P2M_SHIFT) > 0)
+ if ( (pfn >> L3_P2M_SHIFT) > 0 )
{
printk("Error: Too many pfns.\n");
do_exit();
}
l3_list[(pfn >> L2_P2M_SHIFT)] = virt_to_mfn(l2_list);
}
- if(!(pfn % (L1_P2M_ENTRIES)))
+ if ( !(pfn % (L1_P2M_ENTRIES)) )
{
l1_list = (unsigned long*)alloc_page();
l2_list[(pfn >> L1_P2M_SHIFT) & L2_P2M_MASK] =
@@ -696,25 +781,25 @@ void arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p)
unsigned long start_pfn, max_pfn, virt_pfns;
- printk(" _text: %p\n", &_text);
- printk(" _etext: %p\n", &_etext);
- printk(" _erodata: %p\n", &_erodata);
- printk(" _edata: %p\n", &_edata);
- printk(" stack start: %p\n", stack);
- printk(" _end: %p\n", &_end);
+ printk(" _text: %p(VA)\n", &_text);
+ printk(" _etext: %p(VA)\n", &_etext);
+ printk(" _erodata: %p(VA)\n", &_erodata);
+ printk(" _edata: %p(VA)\n", &_edata);
+ printk("stack start: %p(VA)\n", stack);
+ printk(" _end: %p(VA)\n", &_end);
/* First page follows page table pages and 3 more pages (store page etc) */
start_pfn = PFN_UP(to_phys(start_info.pt_base)) +
- start_info.nr_pt_frames + 3;
+ start_info.nr_pt_frames + 3;
max_pfn = start_info.nr_pages;
/* We need room for demand mapping and heap, clip available memory */
virt_pfns = DEMAND_MAP_PAGES + HEAP_PAGES;
- if (max_pfn + virt_pfns + 1 < max_pfn)
+ if ( max_pfn + virt_pfns + 1 < max_pfn )
max_pfn = -(virt_pfns + 1);
- printk(" start_pfn: %lx\n", start_pfn);
- printk(" max_pfn: %lx\n", max_pfn);
+ printk(" start_pfn: %lx\n", start_pfn);
+ printk(" max_pfn: %lx\n", max_pfn);
build_pagetable(&start_pfn, &max_pfn);
clear_bootstrap();
diff --git a/extras/mini-os/arch/x86/setup.c b/extras/mini-os/arch/x86/setup.c
index 3671fee332..8509079d3e 100644
--- a/extras/mini-os/arch/x86/setup.c
+++ b/extras/mini-os/arch/x86/setup.c
@@ -63,10 +63,12 @@ void failsafe_callback(void);
static
shared_info_t *map_shared_info(unsigned long pa)
{
- if ( HYPERVISOR_update_va_mapping(
- (unsigned long)shared_info, __pte(pa | 7), UVMF_INVLPG) )
+ int rc;
+
+ if ( (rc = HYPERVISOR_update_va_mapping(
+ (unsigned long)shared_info, __pte(pa | 7), UVMF_INVLPG)) )
{
- printk("Failed to map shared_info!!\n");
+ printk("Failed to map shared_info!! rc=%d\n", rc);
do_exit();
}
return (shared_info_t *)shared_info;