Merge branch 'for-next/arm'
This commit is contained in:
commit
78c371d3e7
|
@ -1,6 +1,7 @@
|
|||
#include <types.h>
|
||||
|
||||
#include <asm/cache.h>
|
||||
#include <asm/barebox-arm.h>
|
||||
|
||||
#include "entry.h"
|
||||
|
||||
|
@ -26,7 +27,7 @@
|
|||
void __naked __noreturn barebox_arm_entry(unsigned long membase,
|
||||
unsigned long memsize, void *boarddata)
|
||||
{
|
||||
arm_setup_stack(membase + memsize - 16);
|
||||
arm_setup_stack(arm_mem_stack(membase, membase + memsize) + STACK_SIZE - 16);
|
||||
arm_early_mmu_cache_invalidate();
|
||||
|
||||
if (IS_ENABLED(CONFIG_PBL_MULTI_IMAGES))
|
||||
|
|
|
@ -272,59 +272,149 @@ static int arm_mmu_remap_sdram(struct memory_bank *bank)
|
|||
*/
|
||||
#define ARM_VECTORS_SIZE (sizeof(u32) * 8 * 2)
|
||||
|
||||
#define ARM_HIGH_VECTORS 0xffff0000
|
||||
#define ARM_LOW_VECTORS 0x0
|
||||
|
||||
/**
|
||||
* create_vector_table - create a vector table at given address
|
||||
* @adr - The address where the vector table should be created
|
||||
*
|
||||
* After executing this function the vector table is found at the
|
||||
* virtual address @adr.
|
||||
*/
|
||||
static void create_vector_table(unsigned long adr)
|
||||
{
|
||||
struct resource *vectors_sdram;
|
||||
void *vectors;
|
||||
u32 *exc;
|
||||
int idx;
|
||||
|
||||
vectors_sdram = request_sdram_region("vector table", adr, SZ_4K);
|
||||
if (vectors_sdram) {
|
||||
/*
|
||||
* The vector table address is inside the SDRAM physical
|
||||
* address space. Use the existing identity mapping for
|
||||
* the vector table.
|
||||
*/
|
||||
pr_debug("Creating vector table, virt = phys = 0x%08lx\n", adr);
|
||||
vectors = (void *)vectors_sdram->start;
|
||||
} else {
|
||||
/*
|
||||
* The vector table address is outside of SDRAM. Create
|
||||
* a secondary page table for the section and map
|
||||
* allocated memory to the vector address.
|
||||
*/
|
||||
vectors = xmemalign(PAGE_SIZE, PAGE_SIZE);
|
||||
pr_debug("Creating vector table, virt = 0x%p, phys = 0x%08lx\n",
|
||||
vectors, adr);
|
||||
exc = arm_create_pte(adr);
|
||||
idx = (adr & (SZ_1M - 1)) >> PAGE_SHIFT;
|
||||
exc[idx] = (u32)vectors | PTE_TYPE_SMALL | pte_flags_cached;
|
||||
}
|
||||
|
||||
arm_fixup_vectors();
|
||||
|
||||
memset(vectors, 0, PAGE_SIZE);
|
||||
memcpy(vectors, __exceptions_start, __exceptions_stop - __exceptions_start);
|
||||
}
|
||||
|
||||
/**
|
||||
* set_vector_table - let CPU use the vector table at given address
|
||||
* @adr - The address of the vector table
|
||||
*
|
||||
* Depending on the CPU the possibilities differ. ARMv7 and later allow
|
||||
* to map the vector table to arbitrary addresses. Other CPUs only allow
|
||||
* vectors at 0xffff0000 or at 0x0.
|
||||
*/
|
||||
static int set_vector_table(unsigned long adr)
|
||||
{
|
||||
u32 cr;
|
||||
|
||||
if (cpu_architecture() >= CPU_ARCH_ARMv7) {
|
||||
pr_debug("Vectors are at 0x%08lx\n", adr);
|
||||
set_vbar(adr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (adr == ARM_HIGH_VECTORS) {
|
||||
cr = get_cr();
|
||||
cr |= CR_V;
|
||||
set_cr(cr);
|
||||
cr = get_cr();
|
||||
if (cr & CR_V) {
|
||||
pr_debug("Vectors are at 0x%08lx\n", adr);
|
||||
return 0;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (adr == ARM_LOW_VECTORS) {
|
||||
cr = get_cr();
|
||||
cr &= ~CR_V;
|
||||
set_cr(cr);
|
||||
cr = get_cr();
|
||||
if (cr & CR_V) {
|
||||
return -EINVAL;
|
||||
} else {
|
||||
pr_debug("Vectors are at 0x%08lx\n", adr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void create_zero_page(void)
|
||||
{
|
||||
struct resource *zero_sdram;
|
||||
u32 *zero;
|
||||
|
||||
zero_sdram = request_sdram_region("zero page", 0x0, SZ_4K);
|
||||
if (zero_sdram) {
|
||||
/*
|
||||
* Here we would need to set the second level page table
|
||||
* entry to faulting. This is not yet implemented.
|
||||
*/
|
||||
pr_debug("zero page is in SDRAM area, currently not supported\n");
|
||||
} else {
|
||||
zero = arm_create_pte(0x0);
|
||||
zero[0] = 0;
|
||||
pr_debug("Created zero page\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Map vectors and zero page
|
||||
*/
|
||||
static void vectors_init(void)
|
||||
{
|
||||
u32 *exc, *zero = NULL;
|
||||
void *vectors;
|
||||
u32 cr;
|
||||
|
||||
cr = get_cr();
|
||||
cr |= CR_V;
|
||||
set_cr(cr);
|
||||
cr = get_cr();
|
||||
|
||||
if (cr & CR_V) {
|
||||
/*
|
||||
* If we can use high vectors, create the second level
|
||||
* page table for the high vectors and zero page
|
||||
*/
|
||||
exc = arm_create_pte(0xfff00000);
|
||||
zero = arm_create_pte(0x0);
|
||||
|
||||
/* Set the zero page to faulting */
|
||||
zero[0] = 0;
|
||||
} else {
|
||||
/*
|
||||
* Otherwise map the vectors to the zero page. We have to
|
||||
* live without being able to catch NULL pointer dereferences
|
||||
*/
|
||||
exc = arm_create_pte(0x0);
|
||||
|
||||
if (cpu_architecture() >= CPU_ARCH_ARMv7) {
|
||||
/*
|
||||
* ARMv7 CPUs allow to remap low vectors from
|
||||
* 0x0 to an arbitrary address using VBAR
|
||||
* register, so let's make sure we have it
|
||||
* pointing to the correct address
|
||||
*/
|
||||
set_vbar(0x0);
|
||||
}
|
||||
/*
|
||||
* First try to use the vectors where they actually are, works
|
||||
* on ARMv7 and later.
|
||||
*/
|
||||
if (!set_vector_table((unsigned long)__exceptions_start)) {
|
||||
arm_fixup_vectors();
|
||||
create_zero_page();
|
||||
return;
|
||||
}
|
||||
|
||||
arm_fixup_vectors();
|
||||
/*
|
||||
* Next try high vectors at 0xffff0000.
|
||||
*/
|
||||
if (!set_vector_table(ARM_HIGH_VECTORS)) {
|
||||
create_zero_page();
|
||||
create_vector_table(ARM_HIGH_VECTORS);
|
||||
return;
|
||||
}
|
||||
|
||||
vectors = xmemalign(PAGE_SIZE, PAGE_SIZE);
|
||||
memset(vectors, 0, PAGE_SIZE);
|
||||
memcpy(vectors, __exceptions_start, __exceptions_stop - __exceptions_start);
|
||||
|
||||
if (cr & CR_V)
|
||||
exc[256 - 16] = (u32)vectors | PTE_TYPE_SMALL |
|
||||
pte_flags_cached;
|
||||
else
|
||||
exc[0] = (u32)vectors | PTE_TYPE_SMALL | pte_flags_cached;
|
||||
/*
|
||||
* As a last resort use low vectors at 0x0. With this we can't
|
||||
* set the zero page to faulting and can't catch NULL pointer
|
||||
* exceptions.
|
||||
*/
|
||||
set_vector_table(ARM_LOW_VECTORS);
|
||||
create_vector_table(ARM_LOW_VECTORS);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -193,7 +193,7 @@ __noreturn void barebox_non_pbl_start(unsigned long membase,
|
|||
if (totalsize) {
|
||||
unsigned long mem = arm_mem_boarddata(membase, endmem,
|
||||
totalsize);
|
||||
pr_debug("found %s in boarddata, copying to 0x%lu\n",
|
||||
pr_debug("found %s in boarddata, copying to 0x%08lx\n",
|
||||
name, mem);
|
||||
barebox_boarddata = memcpy((void *)mem, boarddata,
|
||||
totalsize);
|
||||
|
|
|
@ -60,7 +60,7 @@ void __noreturn barebox_multi_pbl_start(unsigned long membase,
|
|||
* to the current address. Otherwise it may be a readonly location.
|
||||
* Copy and relocate to the start of the memory in this case.
|
||||
*/
|
||||
if (pc > membase && pc < membase + memsize)
|
||||
if (pc > membase && pc - membase < memsize)
|
||||
relocate_to_current_adr();
|
||||
else
|
||||
relocate_to_adr(membase);
|
||||
|
|
|
@ -97,7 +97,7 @@ void *barebox_arm_boot_dtb(void);
|
|||
static inline unsigned long arm_mem_stack(unsigned long membase,
|
||||
unsigned long endmem)
|
||||
{
|
||||
return endmem - STACK_SIZE;
|
||||
return endmem - SZ_64K - STACK_SIZE;
|
||||
}
|
||||
|
||||
static inline unsigned long arm_mem_ttb(unsigned long membase,
|
||||
|
|
|
@ -43,6 +43,7 @@ SECTIONS
|
|||
__bare_init_start = .;
|
||||
*(.text_bare_init*)
|
||||
__bare_init_end = .;
|
||||
. = ALIGN(4);
|
||||
__exceptions_start = .;
|
||||
KEEP(*(.text_exceptions*))
|
||||
__exceptions_stop = .;
|
||||
|
|
Loading…
Reference in New Issue