Compare commits
1 Commits
master
...
arm64_shut
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c31e880b59 |
@@ -31,7 +31,9 @@
|
|||||||
#include <lk/init.h>
|
#include <lk/init.h>
|
||||||
#include <lk/main.h>
|
#include <lk/main.h>
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
|
#include <target.h>
|
||||||
#include <trace.h>
|
#include <trace.h>
|
||||||
|
#include <kernel/vm.h>
|
||||||
|
|
||||||
#define LOCAL_TRACE 0
|
#define LOCAL_TRACE 0
|
||||||
|
|
||||||
@@ -41,6 +43,8 @@ static spin_lock_t arm_boot_cpu_lock = 1;
|
|||||||
static volatile int secondaries_to_init = 0;
|
static volatile int secondaries_to_init = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SECTION_SIZE (1024 * 1024)
|
||||||
|
|
||||||
static void arm64_cpu_early_init(void)
|
static void arm64_cpu_early_init(void)
|
||||||
{
|
{
|
||||||
/* set the vector base */
|
/* set the vector base */
|
||||||
@@ -93,7 +97,76 @@ void arch_idle(void)
|
|||||||
|
|
||||||
void arch_chain_load(void *entry, ulong arg0, ulong arg1, ulong arg2, ulong arg3)
|
void arch_chain_load(void *entry, ulong arg0, ulong arg1, ulong arg2, ulong arg3)
|
||||||
{
|
{
|
||||||
PANIC_UNIMPLEMENTED;
|
int ret;
|
||||||
|
LTRACEF("entry %p, args 0x%lx 0x%lx 0x%lx 0x%lx\n", entry, arg0, arg1, arg2, arg3);
|
||||||
|
|
||||||
|
/* we are going to shut down the system, start by disabling interrupts */
|
||||||
|
arch_disable_ints();
|
||||||
|
|
||||||
|
/* give target and platform a chance to put hardware into a suitable
|
||||||
|
* state for chain loading.
|
||||||
|
*/
|
||||||
|
target_quiesce();
|
||||||
|
platform_quiesce();
|
||||||
|
|
||||||
|
paddr_t entry_pa;
|
||||||
|
paddr_t loader_pa;
|
||||||
|
paddr_t loader_payam;
|
||||||
|
|
||||||
|
#if WITH_KERNEL_VM
|
||||||
|
/* get the physical address of the entry point we're going to branch to */
|
||||||
|
entry_pa = vaddr_to_paddr((addr_t)entry);
|
||||||
|
if (entry_pa == 0) {
|
||||||
|
panic("error translating entry physical address\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add the low bits of the virtual address back */
|
||||||
|
entry_pa |= ((addr_t)entry & 0xfff);
|
||||||
|
|
||||||
|
LTRACEF("entry pa 0x%lx\n", entry_pa);
|
||||||
|
|
||||||
|
/* figure out the mapping for the chain load routine */
|
||||||
|
loader_pa = vaddr_to_paddr((addr_t)&arm_chain_load);
|
||||||
|
if (loader_pa == 0) {
|
||||||
|
panic("error translating loader physical address\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add the low bits of the virtual address back */
|
||||||
|
loader_pa |= ((addr_t)&arm_chain_load & 0xfff);
|
||||||
|
|
||||||
|
paddr_t loader_pa_section = ROUNDDOWN(loader_pa, SECTION_SIZE);
|
||||||
|
|
||||||
|
LTRACEF("loader address %p, phys 0x%lx, surrounding large page 0x%lx\n",
|
||||||
|
&arm_chain_load, loader_pa, loader_pa_section);
|
||||||
|
|
||||||
|
vmm_aspace_t *myspace;
|
||||||
|
ret = vmm_create_aspace(&myspace, "bootload", 0);
|
||||||
|
if (ret != 0) {
|
||||||
|
panic("Could not create new aspace %d\n", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
get_current_thread()->aspace = myspace;
|
||||||
|
thread_sleep(1);
|
||||||
|
|
||||||
|
/* using large pages, map around the target location */
|
||||||
|
if ((ret = arch_mmu_map(&myspace->arch_aspace, loader_pa_section,
|
||||||
|
loader_pa_section, (2 * SECTION_SIZE / PAGE_SIZE), 0)) != 0) {
|
||||||
|
panic("Could not map loader into new space %d\n", ret);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* for non vm case, just branch directly into it */
|
||||||
|
entry_pa = (paddr_t)entry;
|
||||||
|
loader_pa = (paddr_t)&arm_chain_load;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LTRACEF("disabling instruction/data cache\n");
|
||||||
|
arch_disable_cache(UCACHE);
|
||||||
|
|
||||||
|
LTRACEF("branching to physical address of loader, (va --> pa) (%p --> %p)\n",
|
||||||
|
loader_pa, vaddr_to_paddr((addr_t)loader_pa));
|
||||||
|
|
||||||
|
void (*loader)(paddr_t entry, ulong, ulong, ulong, ulong) __NO_RETURN = (void *)loader_pa;
|
||||||
|
loader(entry_pa, arg0, arg1, arg2, arg3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* switch to user mode, set the user stack pointer to user_stack_top, put the svc stack pointer to the top of the kernel stack */
|
/* switch to user mode, set the user stack pointer to user_stack_top, put the svc stack pointer to the top of the kernel stack */
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ FUNCTION(arm64_elX_to_el1)
|
|||||||
cmp x4, #(0b01 << 2)
|
cmp x4, #(0b01 << 2)
|
||||||
bne .notEL1
|
bne .notEL1
|
||||||
/* Already in EL1 */
|
/* Already in EL1 */
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.notEL1:
|
.notEL1:
|
||||||
cmp x4, #(0b10 << 2)
|
cmp x4, #(0b10 << 2)
|
||||||
@@ -146,3 +146,25 @@ FUNCTION(arm64_elX_to_el1)
|
|||||||
|
|
||||||
.Ltarget:
|
.Ltarget:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
/* void arm_chain_load(paddr_t entry, ulong arg0, ulong arg1, ulong arg2, ulong arg3) __NO_RETURN; */
|
||||||
|
/* shut down the system, branching into the secondary system */
|
||||||
|
FUNCTION(arm_chain_load)
|
||||||
|
/* shuffle the args around */
|
||||||
|
mov x5, x0
|
||||||
|
mov x0, x1
|
||||||
|
mov x1, x2
|
||||||
|
mov x2, x3
|
||||||
|
mov x3, x4
|
||||||
|
|
||||||
|
/* Turn off MMU */
|
||||||
|
// LK runs in EL1
|
||||||
|
/* Disable MMU */
|
||||||
|
mrs x6, sctlr_el1
|
||||||
|
bic x6, x6, #(1 << 0) // Disable MMU
|
||||||
|
msr sctlr_el1, x6
|
||||||
|
isb
|
||||||
|
br x5
|
||||||
|
b . // should never reach here
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include <asm.h>
|
#include <asm.h>
|
||||||
#include <arch/ops.h>
|
#include <arch/ops.h>
|
||||||
#include <arch/defines.h>
|
#include <arch/defines.h>
|
||||||
|
#include <arch/asm_macros.h>
|
||||||
|
|
||||||
.text
|
.text
|
||||||
|
|
||||||
@@ -58,3 +59,72 @@ FUNCTION(arch_sync_cache_range)
|
|||||||
cache_range_op dc cvau // clean dcache to PoU by MVA
|
cache_range_op dc cvau // clean dcache to PoU by MVA
|
||||||
cache_range_op ic ivau // invalidate icache to PoU by MVA
|
cache_range_op ic ivau // invalidate icache to PoU by MVA
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
/* void arch_disable_cache(uint flags); */
|
||||||
|
FUNCTION(arch_disable_cache)
|
||||||
|
// LK runs in EL1
|
||||||
|
|
||||||
|
/* Disable iCache and dCache */
|
||||||
|
.inEL1:
|
||||||
|
mrs x4, sctlr_el1
|
||||||
|
bic x4, x4, #(1 << 12) // Disable iCache
|
||||||
|
bic x4, x4, #(1 << 2) // Disable dCache
|
||||||
|
msr sctlr_el1, x4
|
||||||
|
isb
|
||||||
|
|
||||||
|
/* Clean and Invalidate dCache */
|
||||||
|
mrs x0, CLIDR_EL1
|
||||||
|
and w3, w0, #0x07000000 // Bits: 26:24 Level of Coherence
|
||||||
|
lsr w3, w3, #23 // Store 2 x LoC in W3
|
||||||
|
cbz w3, Finished // If 0, we are done
|
||||||
|
mov w10, #0 // store 2x cache level (since csselr starts at bit 1)
|
||||||
|
mov w8, #1
|
||||||
|
|
||||||
|
Loop1:
|
||||||
|
add w2, w10, w10, lsr #1 // Calculate 3x cache level a(w10 + 2w10 = 3w10)
|
||||||
|
lsr w1, w0, w2 // read cType (cache type)
|
||||||
|
and w1, w1, #0x7 // mask 3-bits
|
||||||
|
cmp w1, #2 // types >=2 include data cache
|
||||||
|
b.lt Skip // skip if no data cache implemented
|
||||||
|
msr csselr_el1, x10 // select the cache level
|
||||||
|
isb // sync
|
||||||
|
mrs x1, ccsidr_el1 // read ccsidr (current cache size id)
|
||||||
|
and w2, w1, #0x7 // w2 = log2(linesize) - 4
|
||||||
|
add w2, w2, #4 // w2 = log2(linesize)
|
||||||
|
ubfx w4, w1, #3, #10 // w4 = way number (associativity)
|
||||||
|
clz w5, w4 // w5 = 32 - log2(ways), bit pos in dc operand
|
||||||
|
lsl w9, w4, w5 // w9 = max way number, aligned to position in dc operand
|
||||||
|
lsl w16, w8, w5 // w16 = amount to decrement way number per iteration
|
||||||
|
|
||||||
|
Loop2:
|
||||||
|
ubfx w7, w1, #13, #15 // w7 = max set number
|
||||||
|
lsl w7, w7, w2 // w7= max set number, aligned to position in dc operand
|
||||||
|
lsl w17, w8, w2 // w17 = amount to decrement set number per iteration
|
||||||
|
|
||||||
|
Loop3:
|
||||||
|
orr w11, w10, w9 // w11 = combine way number, cache number and set num for dc operand
|
||||||
|
orr w11, w11, w7
|
||||||
|
dc cisw, x11 // perform clean by set and way
|
||||||
|
subs w7, w7, w17 // decrement set number
|
||||||
|
b.ge Loop3
|
||||||
|
subs x9, x9, x16 // decrement way number
|
||||||
|
b.ge Loop2
|
||||||
|
|
||||||
|
Skip:
|
||||||
|
add w10, w10, #2
|
||||||
|
cmp w3, w10
|
||||||
|
dsb sy
|
||||||
|
b.gt Loop1
|
||||||
|
|
||||||
|
Finished:
|
||||||
|
/* invalidate iCache*/
|
||||||
|
ic ialluis
|
||||||
|
isb
|
||||||
|
|
||||||
|
/* invalidate TLB */
|
||||||
|
tlbi vmalle1
|
||||||
|
dsb sy
|
||||||
|
isb
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ __BEGIN_CDECLS
|
|||||||
|
|
||||||
void arm64_context_switch(vaddr_t *old_sp, vaddr_t new_sp);
|
void arm64_context_switch(vaddr_t *old_sp, vaddr_t new_sp);
|
||||||
|
|
||||||
|
void arm_chain_load(paddr_t entry, ulong arg0, ulong arg1, ulong arg2, ulong arg3) __NO_RETURN;
|
||||||
|
|
||||||
/* exception handling */
|
/* exception handling */
|
||||||
struct arm64_iframe_long {
|
struct arm64_iframe_long {
|
||||||
uint64_t r[30];
|
uint64_t r[30];
|
||||||
|
|||||||
@@ -107,5 +107,9 @@ void platform_early_init(void)
|
|||||||
pmm_add_arena(&arena);
|
pmm_add_arena(&arena);
|
||||||
|
|
||||||
// TODO: Reserve memory regions if needed
|
// TODO: Reserve memory regions if needed
|
||||||
|
struct list_node list = LIST_INITIAL_VALUE(list);
|
||||||
|
pmm_alloc_range(0x01080000, 0x01A80000 / PAGE_SIZE, &list);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,21 +9,22 @@ MODULE_DEPS += \
|
|||||||
dev/timer/arm_generic \
|
dev/timer/arm_generic \
|
||||||
|
|
||||||
MODULE_SRCS += \
|
MODULE_SRCS += \
|
||||||
$(LOCAL_DIR)/platform.c \
|
$(LOCAL_DIR)/platform.c \
|
||||||
$(LOCAL_DIR)/uart.c \
|
$(LOCAL_DIR)/uart.c \
|
||||||
|
|
||||||
ARCH := arm64
|
ARCH := arm64
|
||||||
ARM_CPU := cortex-a53
|
ARM_CPU := cortex-a53
|
||||||
MEMBASE := 0
|
MEMBASE := 0
|
||||||
MEMSIZE := 0x80000000 # 2GB
|
MEMSIZE := 0x80000000 # 2GB
|
||||||
KERNEL_LOAD_OFFSET := 0x01080000
|
KERNEL_LOAD_OFFSET := 0x01A80000
|
||||||
|
|
||||||
LINKER_SCRIPT += \
|
LINKER_SCRIPT += \
|
||||||
$(BUILDDIR)/system-onesegment.ld
|
$(BUILDDIR)/system-onesegment.ld
|
||||||
|
|
||||||
MODULE := $(LOCAL_DIR)
|
MODULE := $(LOCAL_DIR)
|
||||||
|
|
||||||
MODULE_DEPS += \
|
MODULE_DEPS += \
|
||||||
app/shell \
|
app/shell \
|
||||||
|
|
||||||
|
|
||||||
WITH_CPP_SUPPORT=true
|
WITH_CPP_SUPPORT=true
|
||||||
|
|||||||
Reference in New Issue
Block a user