-u_long videomem_start_ro; /* for debugging mainly */
-
/* kernel info */
u_long marks[MARK_MAX]; /* loader mark pointers */
u_long kernel_physical_start; /* where does it get relocated */
@@ -146,6 +143,7 @@ int page_info_cmp(const void *a, const
void add_initvectors(void);
void create_configuration(int argc, char **argv, int start_args);
void prepare_and_check_relocation_system(void);
+void compact_relocations(void);
void twirl(void);
int vdu_var(int);
void process_args(int argc, char **argv, int *howto, char *file,
@@ -158,7 +156,7 @@ extern void start_kernel(
int relocate_code_page,
int relocation_pv_offset,
int configuration_structure_in_flat_physical_space,
- int physical_address_of_relocation_tables,
+ int virtual_address_relocation_table,
int physical_address_of_new_L1_pages,
int kernel_entry_point
); /* asm */
@@ -232,105 +230,56 @@ init_datastructures(void)
panic("Can't alloc my initial page tables");
}
-
void
-prepare_and_check_relocation_system(void)
+compact_relocations(void)
{
- int relocate_size, relocate_pages;
- int bank, pages, found;
- u_long dst, src, base, destination, extend;
- u_long *reloc_entry, last_src, length;
-
- /* set the number of relocation entries in the 1st word */
- *reloc_instruction_table = reloc_entries;
-
- /*
- * The relocate information needs to be in one sequential physical
- * space in order to be able to access it as one stream when the MMU
- * is switched off later.
- */
- relocate_size = (reloc_tablesize + nbpp-1) & ~(nbpp-1); /* round up */
- printf("\nPreparing for booting %s ... ", booted_file);
- relocate_pages = relocate_size / nbpp;
-
- relocate_table_pages = free_relocation_page;
- pages = 0;
- while (pages < relocate_pages) {
- src = (u_long)reloc_instruction_table + pages*nbpp;
- dst = relocate_table_pages[pages].logical;
- memcpy((void *)dst, (void *)src, nbpp);
-
- if (pages < relocate_pages - 1) {
- /* check if next page is sequential physically */
- if (relocate_table_pages[pages+1].physical -
- relocate_table_pages[pages].physical != nbpp) {
- /*
- * Non contigunous relocate area ->
- * try again
- */
- printf("*");
- relocate_table_pages += pages;
- pages = 0;
- continue; /* while */
- }
- }
- pages++;
- }
- free_relocation_page = relocate_table_pages + pages;
-
- /* copy the relocation code into this page in start_kernel */
- relocate_code_page = free_relocation_page++;
-
- /*
- * All relocations are pages allocated in one big strict increasing
- * physical DRAM address sequence. When the MMU is switched off all
- * code and data is in this increasing order but not at the right
- * place. This is where the relocation code kicks in; relocation is
- * done in flat physical memory without MMU.
- */
-
- printf("shift and check ... ");
- reloc_entry = reloc_instruction_table + 1;
- last_src = -1;
+ u_long *reloc_entry, current_length, length;
+ u_long src, destination, current_src, current_destination;
+ u_long *current_entry;
+
+ current_entry = reloc_entry = reloc_instruction_table + 1;
+
+ /* prime the loop */
+ current_src = reloc_entry[0];
+ current_destination = reloc_entry[1];
+ current_length = reloc_entry[2];
+
+ reloc_entry += 3;
while (reloc_entry < reloc_pos) {
src = reloc_entry[0];
destination = reloc_entry[1];
length = reloc_entry[2];
- /* paranoia check */
- if ((long) (src - last_src) <= 0)
- printf("relocation sequence challenged -- "
- "booting might fail ");
- last_src = src;
-
- /* check if its gonna be relocated into (PO)DRAM ! */
- extend = destination + length;
- found = 0;
- for (bank = 0; (bank < dram_blocks) && !found; bank++) {
- base = DRAM_addr[bank];
- found = (destination >= base) &&
- (extend <= base + DRAM_pages[bank]*nbpp);
- }
- for (bank = 0; (bank < podram_blocks) && !found; bank++) {
- base = PODRAM_addr[bank];
- found = (destination >= base) &&
- (extend <= base + PODRAM_pages[bank]*nbpp);
+ if (src == (current_src + current_length) &&
+ destination == (current_destination + current_length)) {
+ /* can merge */
+ current_length += length;
+ } else {
+ /* nothing else to do, so save the length */
+ current_entry[2] = current_length;
+ /* fill in next entry */
+ current_entry += 3;
+ current_src = current_entry[0] = src;
+ current_destination = current_entry[1] = destination;
+ current_length = length;
}
- if (!found || (extend > top_physdram)) {
- panic("Internal error: relocating range "
- "[%lx +%lx => %lx] outside (PO)DRAM banks!",
- src, length, destination);
- }
-
reloc_entry += 3;
}
- if (reloc_entry != reloc_pos)
- panic("Relocation instruction table is corrupted");
-
- printf("OK!\n");
+ /* save last length */
+ current_entry[2] = current_length;
+ current_entry += 3;
+
+ /* workout new count of entries */
+ length = current_entry - (reloc_instruction_table + 1);
+ printf("Compacted relocations from %d entries to %ld\n",
+ reloc_entries, length/3);
+
+ /* update table to reflect new size */
+ reloc_entries = length/3;
+ reloc_instruction_table[0] = length/3;
+ reloc_pos = current_entry;
}
-
void
get_memory_configuration(void)
{
@@ -506,8 +455,6 @@ get_memory_configuration(void)
panic("Top is not not aligned on a Mb; "
"remove very small DIMMS?");
- videomem_start_ro = vdu_var(os_VDUVAR_DISPLAY_START);
-
/* pretty print the individual page types */
for (count = 0; count < rom_blocks; count++) {
printf("Found ROM (%d)", count);
@@ -880,9 +827,20 @@ main(int argc, char **argv)
* done relocating and creating information, now update and
* check the relocation mechanism
*/
- prepare_and_check_relocation_system();
+ compact_relocations();
+
+ /*
+ * grab a page to copy the bootstrap code into
+ */
+ relocate_code_page = free_relocation_page++;
printf("\nStarting at 0x%lx, p@0x%lx\n", marks[MARK_ENTRY], kernel_physical_start);
+ printf("%ld entries, first one is 0x%lx->0x%lx for %lx bytes\n",
+ reloc_instruction_table[0],
+ reloc_instruction_table[1],
+ reloc_instruction_table[2],
+ reloc_instruction_table[3]);
+
printf("Will boot in a few secs due to relocation....\n"
"bye bye from RISC OS!");
@@ -897,8 +855,8 @@ main(int argc, char **argv)
/* r1 relocation pv offset */
relocate_code_page->physical-relocate_code_page->logical,
/* r2 configuration structure */ bconfig_new_phys,
- /* r3 relocation table (P) */
- relocate_table_pages->physical, /* one piece! */
+ /* r3 relocation table (l) */
+ (int)reloc_instruction_table, /* one piece! */
/* r4 L1 page descriptor (P) */ new_L1_pages_phys,
/* r5 kernel entry point */ marks[MARK_ENTRY]
);
@@ -1007,6 +965,15 @@ get_relocated_page(u_long destination, i
panic("\n\nToo many relocations! What are you loading ??");
/* record the relocation */
+ if (free_relocation_page->physical & 0x3)
+ panic("\n\nphysical address is not aligned!");
+
+ if (destination & 0x3)
+ panic("\n\ndestination address is not aligned!");
+
+ if (size & 0x3)
+ panic("\n\nsize is not aligned!");
+
*reloc_pos++ = free_relocation_page->physical;
*reloc_pos++ = destination;
*reloc_pos++ = size;
Index: start.S
===================================================================
RCS file: /cvsroot/src/sys/arch/acorn32/stand/boot32/start.S,v
retrieving revision 1.2
diff -u -p -r1.2 start.S
--- start.S 25 Jan 2008 23:18:59 -0000 1.2
+++ start.S 3 Feb 2008 02:21:00 -0000
@@ -37,7 +37,6 @@ ENTRY(relocate_code)
/*
- r0 pointer to configuration structure
- r1 pointer to physical restart point
- - r2 pointer to relocation table (P)
- r3 pointer to physical new L1 page address (P)
- r4 kernel entry point
*/
@@ -73,6 +72,18 @@ ENTRY(relocate_code)
cmp r2, r1
moveq r14, #0 /* mark v3 */
+ /* flush everything out before we turn off the MMU */
+
+ /* flush ID cache */
+ mov r0, #0
+ cmp r14, #0
+ mcreq 15, 0, r0, c7, c0, 0 /* flush v3 ID cache */
+ mcrne 15, 0, r0, c7, c7, 0 /* flush v4 ID cache */
+ mcrne 15, 0, r0, c7, c10, 4 /* drain WB (v4) */
+
+ /* flush TLB */
+ mcr 15, 0, r0, c5, c0, 0 /* flush TLB for v3 and v4 */
+
/* switch off MMU, IDcache and WB and branch to physical code space */
cmp r14, #0
mrcne 15, 0, r0, c1, c0, 0 /* read processor control register if v4*/
@@ -87,23 +98,35 @@ ENTRY(relocate_code)
relocate_code_physical_restart:
/* we are running in physical flat 1:1 space now */
- mov r5, r10 /* r5 = is start of relocation table */
- ldr r6, [r5], #4 /* r4 = number of relocated pages */
+
+ /* make the screen border red */
+ mov r4, #0x03400000
+ mov r0, #0x40000000
+ orr r0, r0, #0xff
+ str r0, [r4]
+
+ adr r5, relocate_table_start
+ ldr r6, [r5], #4 /* r6 = number of relocated pages */
+
loop_relocate_pages:
ldr r2, [r5], #4 /* r2 = from address */
ldr r3, [r5], #4 /* r3 = to address */
ldr r7, [r5], #4 /* r7 = number of bytes to travel */
- mov r1, #0 /* r1 = offset in page */
/* its slow ... we dont know anything about alignment here */
loop_one_page:
- ldrb r0, [r2, r1]
- strb r0, [r3, r1]
- add r1, r1, #1
- cmp r1, r7 /* all bytes copied? */
- bne loop_one_page
+ ldr r0, [r2], #4
+ str r0, [r3], #4
+ subs r7, r7, #4
+ bgt loop_one_page
+
subs r6, r6, #1
bne loop_relocate_pages
+ /* make the screen border go green */
+ mov r0, #0x40000000
+ orr r0, r0, #0xff00
+ str r0, [r4]
+
/* OK! all is relocated... now switch over to the new L1 pages */
/* flush ID cache */
@@ -132,6 +155,11 @@ loop_one_page:
mov r0, r0 /* flat */
/* not flat anymore but we just continue */
+ /* make the screen border go blue */
+ mov r0, #0x40000000
+ orr r0, r0, #0xff0000
+ str r0, [r4]
+
/* call the kernel! */
mov r0, r8 /* saved configuration structure */
mov pc, r12 /* entry point ..... bye bye! */
@@ -139,6 +167,10 @@ loop_one_page:
relocate_code_end:
b relocate_code_end
+relocate_table_start:
+ /* relocation table is copied here, so it must be kept small */
+
+
/* ----------------------------------------------------------------------- */