[arch][or1k] add or1k (OpenRISC 1000) architecture
This add support for the OpenRISC 1000 architecture, and as the architecture specification defines an on-chip tick-timer and interrupt controller, drivers for those are included in this commit. Support to utilize the MMU is implemented, and it can be opted in and out with WITH_KERNEL_VM
This commit is contained in:
45
arch/or1k/arch.c
Normal file
45
arch/or1k/arch.c
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <trace.h>
|
||||
#include <err.h>
|
||||
#include <arch/or1k.h>
|
||||
#include <arch/ops.h>
|
||||
#include <arch/mmu.h>
|
||||
|
||||
void arch_early_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void arch_init(void)
|
||||
{
|
||||
TRACE;
|
||||
}
|
||||
|
||||
void arch_idle(void)
|
||||
{
|
||||
}
|
||||
|
||||
void arch_chain_load(void *entry, ulong arg0, ulong arg1, ulong arg2, ulong arg3)
|
||||
{
|
||||
PANIC_UNIMPLEMENTED;
|
||||
}
|
||||
58
arch/or1k/asm.S
Normal file
58
arch/or1k/asm.S
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Stefan Kristiansson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <asm.h>
|
||||
|
||||
/* void or1k_context_switch(
|
||||
struct or1k_context_switch_frame *oldcs,
|
||||
struct or1k_context_switch_frame *newcs); */
|
||||
FUNCTION(or1k_context_switch)
|
||||
/* save old context */
|
||||
l.sw 0(r3), r1
|
||||
l.sw 4(r3), r2
|
||||
l.sw 8(r3), r9
|
||||
l.sw 12(r3), r10
|
||||
l.sw 16(r3), r14
|
||||
l.sw 20(r3), r16
|
||||
l.sw 24(r3), r18
|
||||
l.sw 28(r3), r20
|
||||
l.sw 32(r3), r22
|
||||
l.sw 36(r3), r24
|
||||
l.sw 40(r3), r26
|
||||
l.sw 44(r3), r28
|
||||
l.sw 48(r3), r30
|
||||
|
||||
/* restore new context */
|
||||
l.lwz r30, 48(r4)
|
||||
l.lwz r28, 44(r4)
|
||||
l.lwz r26, 40(r4)
|
||||
l.lwz r24, 36(r4)
|
||||
l.lwz r22, 32(r4)
|
||||
l.lwz r20, 28(r4)
|
||||
l.lwz r18, 24(r4)
|
||||
l.lwz r16, 20(r4)
|
||||
l.lwz r14, 16(r4)
|
||||
l.lwz r10, 12(r4)
|
||||
l.lwz r9, 8(r4)
|
||||
l.lwz r2, 4(r4)
|
||||
l.jr r9
|
||||
l.lwz r1, 0(r4)
|
||||
132
arch/or1k/cache-ops.c
Normal file
132
arch/or1k/cache-ops.c
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Stefan Kristiansson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <arch/ops.h>
|
||||
#include <arch/or1k.h>
|
||||
|
||||
static inline uint32_t dc_block_size(void)
|
||||
{
|
||||
uint32_t dccfgr = mfspr(OR1K_SPR_SYS_DCCFGR_ADDR);
|
||||
|
||||
return dccfgr & OR1K_SPR_SYS_DCCFGR_CBS_MASK ? 32 : 16;
|
||||
}
|
||||
|
||||
static inline uint32_t dc_sets(void)
|
||||
{
|
||||
uint32_t dccfgr = mfspr(OR1K_SPR_SYS_DCCFGR_ADDR);
|
||||
|
||||
return 1 << OR1K_SPR_SYS_DCCFGR_NCS_GET(dccfgr);
|
||||
}
|
||||
|
||||
static inline uint32_t ic_block_size(void)
|
||||
{
|
||||
uint32_t iccfgr = mfspr(OR1K_SPR_SYS_ICCFGR_ADDR);
|
||||
|
||||
return iccfgr & OR1K_SPR_SYS_ICCFGR_CBS_MASK ? 32 : 16;
|
||||
}
|
||||
|
||||
static inline uint32_t ic_sets(void)
|
||||
{
|
||||
uint32_t iccfgr = mfspr(OR1K_SPR_SYS_ICCFGR_ADDR);
|
||||
|
||||
return 1 << OR1K_SPR_SYS_ICCFGR_NCS_GET(iccfgr);
|
||||
}
|
||||
|
||||
void arch_invalidate_cache_all(void)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t cache_size;
|
||||
uint32_t block_size;
|
||||
|
||||
block_size = ic_block_size();
|
||||
cache_size = block_size * ic_sets();
|
||||
for (i = 0; i < cache_size; i += block_size)
|
||||
mtspr(OR1K_SPR_ICACHE_ICBIR_ADDR, i);
|
||||
|
||||
block_size = dc_block_size();
|
||||
cache_size = block_size * dc_sets();
|
||||
for (i = 0; i < cache_size; i += block_size)
|
||||
mtspr(OR1K_SPR_DCACHE_DCBIR_ADDR, i);
|
||||
}
|
||||
|
||||
void arch_disable_cache(uint flags)
|
||||
{
|
||||
uint32_t sr = mfspr(OR1K_SPR_SYS_SR_ADDR);
|
||||
|
||||
if (flags & ICACHE)
|
||||
sr &= ~OR1K_SPR_SYS_SR_ICE_MASK;
|
||||
if (flags & DCACHE)
|
||||
sr &= ~OR1K_SPR_SYS_SR_DCE_MASK;
|
||||
|
||||
mtspr(OR1K_SPR_SYS_SR_ADDR, sr);
|
||||
}
|
||||
|
||||
void arch_enable_cache(uint flags)
|
||||
{
|
||||
uint32_t sr = mfspr(OR1K_SPR_SYS_SR_ADDR);
|
||||
|
||||
if (flags & ICACHE)
|
||||
sr |= OR1K_SPR_SYS_SR_ICE_MASK;
|
||||
if (flags & DCACHE)
|
||||
sr |= OR1K_SPR_SYS_SR_DCE_MASK;
|
||||
|
||||
mtspr(OR1K_SPR_SYS_SR_ADDR, sr);
|
||||
}
|
||||
|
||||
/* flush dcache */
|
||||
void arch_clean_cache_range(addr_t start, size_t len)
|
||||
{
|
||||
addr_t addr;
|
||||
uint32_t block_size = dc_block_size();
|
||||
|
||||
for (addr = start; addr < start + len; addr += block_size)
|
||||
mtspr(OR1K_SPR_DCACHE_DCBFR_ADDR, addr);
|
||||
}
|
||||
|
||||
/* invalidate dcache */
|
||||
void arch_invalidate_cache_range(addr_t start, size_t len)
|
||||
{
|
||||
addr_t addr;
|
||||
uint32_t block_size = dc_block_size();
|
||||
|
||||
for (addr = start; addr < start + len; addr += block_size)
|
||||
mtspr(OR1K_SPR_DCACHE_DCBIR_ADDR, addr);
|
||||
}
|
||||
|
||||
/* flush + invalidate dcache */
|
||||
void arch_clean_invalidate_cache_range(addr_t start, size_t len)
|
||||
{
|
||||
/* invalidate is implied by flush on or1k */
|
||||
arch_clean_cache_range(start, len);
|
||||
}
|
||||
|
||||
/* flush dcache + invalidate icache */
|
||||
void arch_sync_cache_range(addr_t start, size_t len)
|
||||
{
|
||||
addr_t addr;
|
||||
uint32_t block_size = ic_block_size();
|
||||
|
||||
arch_clean_cache_range(start, len);
|
||||
for (addr = start; addr < start + len; addr += block_size)
|
||||
mtspr(OR1K_SPR_ICACHE_ICBIR_ADDR, addr);
|
||||
}
|
||||
46
arch/or1k/exceptions.c
Normal file
46
arch/or1k/exceptions.c
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Stefan Kristiansson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <kernel/thread.h>
|
||||
|
||||
enum handler_return platform_irq(void);
|
||||
enum handler_return platform_tick(void);
|
||||
|
||||
void or1k_irq(void)
|
||||
{
|
||||
inc_critical_section();
|
||||
|
||||
if (platform_irq() == INT_RESCHEDULE)
|
||||
thread_preempt();
|
||||
|
||||
dec_critical_section();
|
||||
}
|
||||
|
||||
void or1k_tick(void)
|
||||
{
|
||||
inc_critical_section();
|
||||
|
||||
if (platform_tick() == INT_RESCHEDULE)
|
||||
thread_preempt();
|
||||
|
||||
dec_critical_section();
|
||||
}
|
||||
105
arch/or1k/faults.c
Normal file
105
arch/or1k/faults.c
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Stefan Kristiansson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <debug.h>
|
||||
#include <arch/or1k.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <platform.h>
|
||||
|
||||
static void dump_fault_frame(struct or1k_iframe *frame)
|
||||
{
|
||||
addr_t stack = (addr_t)((char *)frame + 128 + sizeof(frame));
|
||||
|
||||
dprintf(CRITICAL, "r0: 0x%08x r1: 0x%08x: r2: 0x%08x r3: 0x%08x\n",
|
||||
0, (uint32_t)stack, frame->r2, frame->r3);
|
||||
dprintf(CRITICAL, "r4: 0x%08x r5: 0x%08x: r6: 0x%08x r7: 0x%08x\n",
|
||||
frame->r4, frame->r5, frame->r6, frame->r7);
|
||||
dprintf(CRITICAL, "r8: 0x%08x r9: 0x%08x: r10: 0x%08x r11: 0x%08x\n",
|
||||
frame->r8, frame->r9, frame->r10, frame->r11);
|
||||
dprintf(CRITICAL, "r12: 0x%08x r13: 0x%08x: r14: 0x%08x r15: 0x%08x\n",
|
||||
frame->r12, frame->r13, frame->r14, frame->r15);
|
||||
dprintf(CRITICAL, "r16: 0x%08x r17: 0x%08x: r18: 0x%08x r19: 0x%08x\n",
|
||||
frame->r16, frame->r17, frame->r18, frame->r19);
|
||||
dprintf(CRITICAL, "r20: 0x%08x r21: 0x%08x: r22: 0x%08x r23: 0x%08x\n",
|
||||
frame->r20, frame->r21, frame->r22, frame->r23);
|
||||
dprintf(CRITICAL, "r24: 0x%08x r25: 0x%08x: r26: 0x%08x r27: 0x%08x\n",
|
||||
frame->r24, frame->r25, frame->r26, frame->r27);
|
||||
dprintf(CRITICAL, "r28: 0x%08x r29: 0x%08x: r30: 0x%08x r31: 0x%08x\n",
|
||||
frame->r28, frame->r29, frame->r30, frame->r31);
|
||||
dprintf(CRITICAL, "PC: 0x%08x SR: 0x%08x\n",
|
||||
frame->pc, frame->sr);
|
||||
|
||||
dprintf(CRITICAL, "bottom of stack at 0x%08x:\n", (unsigned int)stack);
|
||||
hexdump((void *)stack, 128);
|
||||
|
||||
}
|
||||
|
||||
static void exception_die(struct or1k_iframe *frame, const char *msg)
|
||||
{
|
||||
inc_critical_section();
|
||||
dprintf(CRITICAL, msg);
|
||||
dump_fault_frame(frame);
|
||||
|
||||
platform_halt(HALT_ACTION_HALT, HALT_REASON_SW_PANIC);
|
||||
for (;;);
|
||||
}
|
||||
|
||||
void or1k_busfault_handler(struct or1k_iframe *frame, uint32_t addr)
|
||||
{
|
||||
dprintf(CRITICAL, "unhandled busfault (EEAR: 0x%08x)", addr);
|
||||
exception_die(frame, ", halting\n");
|
||||
}
|
||||
|
||||
void or1k_data_pagefault_handler(struct or1k_iframe *frame, uint32_t addr)
|
||||
{
|
||||
dprintf(CRITICAL, "unhandled data pagefault (EEAR: 0x%08x)", addr);
|
||||
exception_die(frame, ", halting\n");
|
||||
}
|
||||
|
||||
void or1k_instruction_pagefault_handler(struct or1k_iframe *frame, uint32_t addr)
|
||||
{
|
||||
dprintf(CRITICAL, "unhandled instruction pagefault (EEAR: 0x%08x)", addr);
|
||||
exception_die(frame, ", halting\n");
|
||||
}
|
||||
|
||||
void or1k_alignment_handler(struct or1k_iframe *frame, uint32_t addr)
|
||||
{
|
||||
dprintf(CRITICAL, "unhandled unaligned access (EEAR: 0x%08x)", addr);
|
||||
exception_die(frame, ", halting\n");
|
||||
}
|
||||
|
||||
void or1k_illegal_instruction_handler(struct or1k_iframe *frame, uint32_t addr)
|
||||
{
|
||||
dprintf(CRITICAL, "unhandled illegal instruction (EEAR: 0x%08x)", addr);
|
||||
exception_die(frame, ", halting\n");
|
||||
}
|
||||
|
||||
void or1k_syscall_handler(struct or1k_iframe *frame)
|
||||
{
|
||||
exception_die(frame, "unhandled syscall, halting\n");
|
||||
}
|
||||
|
||||
void or1k_unhandled_exception(struct or1k_iframe *frame, uint32_t vector)
|
||||
{
|
||||
dprintf(CRITICAL, "unhandled exception (vector: 0x%08x)", vector);
|
||||
exception_die(frame, ", halting\n");
|
||||
}
|
||||
96
arch/or1k/include/arch/arch_ops.h
Normal file
96
arch/or1k/include/arch/arch_ops.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Stefan Kristiansson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <compiler.h>
|
||||
#include <arch/or1k.h>
|
||||
|
||||
#ifndef ASSEMBLY
|
||||
static inline void arch_enable_ints(void)
|
||||
{
|
||||
uint32_t sr = mfspr(OR1K_SPR_SYS_SR_ADDR);
|
||||
|
||||
sr |= OR1K_SPR_SYS_SR_IEE_MASK | OR1K_SPR_SYS_SR_TEE_MASK;
|
||||
mtspr(OR1K_SPR_SYS_SR_ADDR, sr);
|
||||
}
|
||||
|
||||
static inline void arch_disable_ints(void)
|
||||
{
|
||||
uint32_t sr = mfspr(OR1K_SPR_SYS_SR_ADDR);
|
||||
|
||||
sr &= ~(OR1K_SPR_SYS_SR_IEE_MASK | OR1K_SPR_SYS_SR_TEE_MASK);
|
||||
mtspr(OR1K_SPR_SYS_SR_ADDR, sr);
|
||||
}
|
||||
|
||||
static inline int atomic_add(volatile int *ptr, int val)
|
||||
{
|
||||
return __atomic_fetch_add(ptr, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
|
||||
static inline int atomic_or(volatile int *ptr, int val)
|
||||
{
|
||||
return __atomic_fetch_or(ptr, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
|
||||
static inline int atomic_and(volatile int *ptr, int val)
|
||||
{
|
||||
return __atomic_fetch_and(ptr, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
|
||||
static inline int atomic_swap(volatile int *ptr, int val)
|
||||
{
|
||||
return __atomic_exchange_n(ptr, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
|
||||
static inline int atomic_cmpxchg(volatile int *ptr, int oldval, int newval)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"1: l.lwa %0, 0(%1) \n"
|
||||
" l.sfeq %0, %2 \n"
|
||||
" l.bnf 1f \n"
|
||||
" l.nop \n"
|
||||
" l.swa 0(%1), %3 \n"
|
||||
" l.bnf 1b \n"
|
||||
"1: l.nop \n"
|
||||
: "=&r"(oldval)
|
||||
: "r"(ptr), "r"(oldval), "r"(newval)
|
||||
: "cc", "memory");
|
||||
|
||||
return oldval;
|
||||
}
|
||||
|
||||
/* use a global pointer to store the current_thread */
|
||||
extern struct thread *_current_thread;
|
||||
|
||||
static inline struct thread *get_current_thread(void)
|
||||
{
|
||||
return _current_thread;
|
||||
}
|
||||
|
||||
static inline void set_current_thread(struct thread *t)
|
||||
{
|
||||
_current_thread = t;
|
||||
}
|
||||
|
||||
static inline uint32_t arch_cycle_count(void) { return 0; }
|
||||
#endif // !ASSEMBLY
|
||||
51
arch/or1k/include/arch/arch_thread.h
Normal file
51
arch/or1k/include/arch/arch_thread.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Stefan Kristiansson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
struct or1k_context_switch_frame {
|
||||
uint32_t r1; // stack pointer
|
||||
uint32_t r2; // frame pointer
|
||||
|
||||
uint32_t r9; // link register
|
||||
|
||||
/* callee saved */
|
||||
uint32_t r10;
|
||||
uint32_t r14;
|
||||
uint32_t r16;
|
||||
uint32_t r18;
|
||||
uint32_t r20;
|
||||
uint32_t r22;
|
||||
uint32_t r24;
|
||||
uint32_t r26;
|
||||
uint32_t r28;
|
||||
uint32_t r30;
|
||||
};
|
||||
|
||||
struct arch_thread {
|
||||
struct or1k_context_switch_frame cs_frame;
|
||||
};
|
||||
|
||||
void or1k_context_switch(struct or1k_context_switch_frame *oldcs,
|
||||
struct or1k_context_switch_frame *newcs);
|
||||
31
arch/or1k/include/arch/defines.h
Normal file
31
arch/or1k/include/arch/defines.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Stefan Kristiansson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#define PAGE_SIZE 8192
|
||||
#define PAGE_SIZE_SHIFT 13
|
||||
|
||||
/* Cache line can be configured, but this is max */
|
||||
#define CACHE_LINE 32
|
||||
|
||||
#define ARCH_DEFAULT_STACK_SIZE 8192
|
||||
2417
arch/or1k/include/arch/or1k-sprs.h
Normal file
2417
arch/or1k/include/arch/or1k-sprs.h
Normal file
File diff suppressed because it is too large
Load Diff
98
arch/or1k/include/arch/or1k.h
Normal file
98
arch/or1k/include/arch/or1k.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Stefan Kristiansson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <arch/or1k-sprs.h>
|
||||
|
||||
#define mtspr(_spr, _val) \
|
||||
__asm__ __volatile__( \
|
||||
"l.mtspr r0, %1, %0" \
|
||||
: \
|
||||
: "K" (_spr), "r" (_val) \
|
||||
)
|
||||
|
||||
#define mtspr_off(_spr, _off, _val) \
|
||||
__asm__ __volatile__ ( \
|
||||
"l.mtspr %0, %1, %2" \
|
||||
: \
|
||||
: "r" (_off), "r" (_val), "K" (_spr) \
|
||||
)
|
||||
|
||||
#define mfspr(_spr) \
|
||||
({ \
|
||||
uint32_t _val; \
|
||||
__asm__ __volatile__( \
|
||||
"l.mfspr %0, r0, %1" \
|
||||
: "=r"(_val) \
|
||||
: "K" (_spr) \
|
||||
); \
|
||||
_val; \
|
||||
})
|
||||
|
||||
#define mfspr_off(_spr, _off) \
|
||||
({ \
|
||||
uint32_t _val; \
|
||||
__asm__ __volatile__ ( \
|
||||
"l.mfspr %0, %1, %2" \
|
||||
: "=r" (_val) \
|
||||
: "r" (_off), "K" (_spr) \
|
||||
); \
|
||||
_val; \
|
||||
})
|
||||
|
||||
#ifndef ASSEMBLY
|
||||
struct or1k_iframe {
|
||||
uint32_t r2;
|
||||
uint32_t r3;
|
||||
uint32_t r4;
|
||||
uint32_t r5;
|
||||
uint32_t r6;
|
||||
uint32_t r7;
|
||||
uint32_t r8;
|
||||
uint32_t r9;
|
||||
uint32_t r10;
|
||||
uint32_t r11;
|
||||
uint32_t r12;
|
||||
uint32_t r13;
|
||||
uint32_t r14;
|
||||
uint32_t r15;
|
||||
uint32_t r16;
|
||||
uint32_t r17;
|
||||
uint32_t r18;
|
||||
uint32_t r19;
|
||||
uint32_t r20;
|
||||
uint32_t r21;
|
||||
uint32_t r22;
|
||||
uint32_t r23;
|
||||
uint32_t r24;
|
||||
uint32_t r25;
|
||||
uint32_t r26;
|
||||
uint32_t r27;
|
||||
uint32_t r28;
|
||||
uint32_t r29;
|
||||
uint32_t r30;
|
||||
uint32_t r31;
|
||||
uint32_t pc;
|
||||
uint32_t sr;
|
||||
};
|
||||
#endif // !ASSEMBLY
|
||||
37
arch/or1k/include/arch/or1k/mmu.h
Normal file
37
arch/or1k/include/arch/or1k/mmu.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Stefan Kristiansson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#pragma once
|
||||
#define SECTION_SIZE (16U*1024U*1024U)
|
||||
|
||||
#define OR1K_MMU_PG_FLAGS_MASK 0x7ffU
|
||||
#define OR1K_MMU_PG_PRESENT 0x400
|
||||
#define OR1K_MMU_PG_L 0x200
|
||||
#define OR1K_MMU_PG_X 0x100
|
||||
#define OR1K_MMU_PG_W 0x080
|
||||
#define OR1K_MMU_PG_U 0x040
|
||||
#define OR1K_MMU_PG_D 0x020
|
||||
#define OR1K_MMU_PG_A 0x010
|
||||
#define OR1K_MMU_PG_WOM 0x008
|
||||
#define OR1K_MMU_PG_WBC 0x004
|
||||
#define OR1K_MMU_PG_CI 0x002
|
||||
#define OR1K_MMU_PG_CC 0x001
|
||||
98
arch/or1k/linker.ld
Normal file
98
arch/or1k/linker.ld
Normal file
@@ -0,0 +1,98 @@
|
||||
OUTPUT_FORMAT("elf32-or1k", "elf32-or1k", "elf32-or1k")
|
||||
OUTPUT_ARCH(or1k)
|
||||
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = %KERNEL_BASE% + %KERNEL_LOAD_OFFSET%;
|
||||
|
||||
_start = .;
|
||||
|
||||
/* vector table goes at 0 */
|
||||
.vectors : AT(0) {
|
||||
KEEP(*(.vectors))
|
||||
}
|
||||
|
||||
/* text/read-only data */
|
||||
/* set the load address to physical MEMBASE */
|
||||
.text : AT(%MEMBASE% + %KERNEL_LOAD_OFFSET% + SIZEOF(.vectors)) {
|
||||
KEEP(*(.text.boot))
|
||||
*(.text* .gnu.linkonce.t.*)
|
||||
}
|
||||
|
||||
.interp : { *(.interp) }
|
||||
.hash : { *(.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) }
|
||||
.rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) }
|
||||
.rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) }
|
||||
.rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) }
|
||||
.rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
|
||||
.rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
|
||||
.rel.got : { *(.rel.got) }
|
||||
.rela.got : { *(.rela.got) }
|
||||
.rel.ctors : { *(.rel.ctors) }
|
||||
.rela.ctors : { *(.rela.ctors) }
|
||||
.rel.dtors : { *(.rel.dtors) }
|
||||
.rela.dtors : { *(.rela.dtors) }
|
||||
.rel.init : { *(.rel.init) }
|
||||
.rela.init : { *(.rela.init) }
|
||||
.rel.fini : { *(.rel.fini) }
|
||||
.rela.fini : { *(.rela.fini) }
|
||||
.rel.bss : { *(.rel.bss) }
|
||||
.rela.bss : { *(.rela.bss) }
|
||||
.rel.plt : { *(.rel.plt) }
|
||||
.rela.plt : { *(.rela.plt) }
|
||||
.init : { *(.init) }
|
||||
.plt : { *(.plt) }
|
||||
|
||||
.rodata : ALIGN(4) {
|
||||
__rodata_start = .;
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
INCLUDE "arch/shared_rodata_sections.ld"
|
||||
. = ALIGN(4);
|
||||
__rodata_end = .;
|
||||
}
|
||||
|
||||
|
||||
.data : ALIGN(4) {
|
||||
/* writable data */
|
||||
__data_start_rom = .;
|
||||
/* in one segment binaries, the rom data address is on top of the ram data address */
|
||||
__data_start = .;
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
INCLUDE "arch/shared_data_sections.ld"
|
||||
__ctor_list = .;
|
||||
KEEP(*(.ctors .init_array))
|
||||
__ctor_end = .;
|
||||
__dtor_list = .;
|
||||
KEEP(*(.dtors .fini_array))
|
||||
__dtor_end = .;
|
||||
*(.got*)
|
||||
*(.dynamic)
|
||||
|
||||
__data_end = .;
|
||||
}
|
||||
|
||||
|
||||
/* unintialized data (in same segment as writable data) */
|
||||
.bss : ALIGN(4) {
|
||||
KEEP(*(.bss.prebss.*))
|
||||
. = ALIGN(4);
|
||||
__bss_start = .;
|
||||
*(.bss .bss.*)
|
||||
*(.gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end = .;
|
||||
}
|
||||
|
||||
_end = .;
|
||||
|
||||
. = %KERNEL_BASE% + %MEMSIZE%;
|
||||
_end_of_ram = .;
|
||||
|
||||
/* Strip unnecessary stuff */
|
||||
/DISCARD/ : { *(.comment .note .eh_frame) }
|
||||
}
|
||||
214
arch/or1k/mmu.c
Normal file
214
arch/or1k/mmu.c
Normal file
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Stefan Kristiansson
|
||||
* Based on arch/arm/arm/mmu.c
|
||||
* Copyright (c) 2008-2014 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <trace.h>
|
||||
#include <err.h>
|
||||
#include <string.h>
|
||||
#include <arch/mmu.h>
|
||||
#include <arch/or1k.h>
|
||||
#include <arch/or1k/mmu.h>
|
||||
#include <kernel/vm.h>
|
||||
|
||||
#define LOCAL_TRACE 0
|
||||
|
||||
#if WITH_KERNEL_VM
|
||||
|
||||
uint32_t or1k_kernel_translation_table[256] __ALIGNED(8192) __SECTION(".bss.prebss.translation_table");
|
||||
|
||||
/* Pessimistic tlb invalidation, which rather invalidate too much.
|
||||
* TODO: make it more precise. */
|
||||
void or1k_invalidate_tlb(vaddr_t vaddr, uint count)
|
||||
{
|
||||
uint32_t dmmucfgr = mfspr(OR1K_SPR_SYS_DMMUCFGR_ADDR);
|
||||
uint32_t immucfgr = mfspr(OR1K_SPR_SYS_IMMUCFGR_ADDR);
|
||||
uint32_t num_dtlb_ways = OR1K_SPR_SYS_DMMUCFGR_NTW_GET(dmmucfgr) + 1;
|
||||
uint32_t num_dtlb_sets = 1 << OR1K_SPR_SYS_DMMUCFGR_NTS_GET(dmmucfgr);
|
||||
uint32_t num_itlb_ways = OR1K_SPR_SYS_IMMUCFGR_NTW_GET(immucfgr) + 1;
|
||||
uint32_t num_itlb_sets = 1 << OR1K_SPR_SYS_IMMUCFGR_NTS_GET(immucfgr);
|
||||
uint32_t offs;
|
||||
|
||||
for (; count; count--) {
|
||||
offs = (vaddr >> PAGE_SIZE_SHIFT) & (num_dtlb_sets-1);
|
||||
switch (num_dtlb_ways) {
|
||||
case 4:
|
||||
mtspr_off(0, OR1K_SPR_DMMU_DTLBW_MR_ADDR(3, offs), 0);
|
||||
case 3:
|
||||
mtspr_off(0, OR1K_SPR_DMMU_DTLBW_MR_ADDR(2, offs), 0);
|
||||
case 2:
|
||||
mtspr_off(0, OR1K_SPR_DMMU_DTLBW_MR_ADDR(1, offs), 0);
|
||||
case 1:
|
||||
mtspr_off(0, OR1K_SPR_DMMU_DTLBW_MR_ADDR(0, offs), 0);
|
||||
}
|
||||
|
||||
offs = (vaddr >> PAGE_SIZE_SHIFT) & (num_itlb_sets-1);
|
||||
switch (num_itlb_ways) {
|
||||
case 4:
|
||||
mtspr_off(0, OR1K_SPR_IMMU_ITLBW_MR_ADDR(3, offs), 0);
|
||||
case 3:
|
||||
mtspr_off(0, OR1K_SPR_IMMU_ITLBW_MR_ADDR(2, offs), 0);
|
||||
case 2:
|
||||
mtspr_off(0, OR1K_SPR_IMMU_ITLBW_MR_ADDR(1, offs), 0);
|
||||
case 1:
|
||||
mtspr_off(0, OR1K_SPR_IMMU_ITLBW_MR_ADDR(0, offs), 0);
|
||||
}
|
||||
vaddr += PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
status_t arch_mmu_query(vaddr_t vaddr, paddr_t *paddr, uint *flags)
|
||||
{
|
||||
uint index = vaddr / SECTION_SIZE;
|
||||
uint32_t pte = or1k_kernel_translation_table[index];
|
||||
uint32_t vmask = SECTION_SIZE-1;
|
||||
|
||||
if (!(pte & OR1K_MMU_PG_PRESENT))
|
||||
return ERR_NOT_FOUND;
|
||||
|
||||
/* not a l1 entry */
|
||||
if (!(pte & OR1K_MMU_PG_L)) {
|
||||
uint32_t *l2_table = paddr_to_kvaddr(pte & ~OR1K_MMU_PG_FLAGS_MASK);
|
||||
index = (vaddr % SECTION_SIZE) / PAGE_SIZE;
|
||||
pte = l2_table[index];
|
||||
vmask = PAGE_SIZE-1;
|
||||
}
|
||||
|
||||
if (paddr)
|
||||
*paddr = (pte & ~OR1K_MMU_PG_FLAGS_MASK) | (vaddr & vmask);
|
||||
|
||||
if (flags) {
|
||||
*flags = 0;
|
||||
if (pte & OR1K_MMU_PG_U)
|
||||
*flags |= ARCH_MMU_FLAG_PERM_USER;
|
||||
if (!(pte & OR1K_MMU_PG_X))
|
||||
*flags |= ARCH_MMU_FLAG_PERM_NO_EXECUTE;
|
||||
if (!(pte & OR1K_MMU_PG_W))
|
||||
*flags |= ARCH_MMU_FLAG_PERM_RO;
|
||||
if (pte & OR1K_MMU_PG_CI)
|
||||
*flags |= ARCH_MMU_FLAG_UNCACHED;
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int arch_mmu_unmap(vaddr_t vaddr, uint count)
|
||||
{
|
||||
LTRACEF("vaddr = 0x%x, count = %d\n", vaddr, count);
|
||||
|
||||
if (!IS_PAGE_ALIGNED(vaddr))
|
||||
return ERR_INVALID_ARGS;
|
||||
|
||||
uint unmapped = 0;
|
||||
while (count) {
|
||||
uint index = vaddr / SECTION_SIZE;
|
||||
uint32_t pte = or1k_kernel_translation_table[index];
|
||||
if (!(pte & OR1K_MMU_PG_PRESENT)) {
|
||||
vaddr += PAGE_SIZE;
|
||||
count--;
|
||||
continue;
|
||||
}
|
||||
/* Unmapping of l2 tables is not implemented (yet) */
|
||||
if (!(pte & OR1K_MMU_PG_L) || !IS_ALIGNED(vaddr, SECTION_SIZE) || count < SECTION_SIZE / PAGE_SIZE)
|
||||
PANIC_UNIMPLEMENTED;
|
||||
|
||||
or1k_kernel_translation_table[index] = 0;
|
||||
or1k_invalidate_tlb(vaddr, SECTION_SIZE / PAGE_SIZE);
|
||||
vaddr += SECTION_SIZE;
|
||||
count -= SECTION_SIZE / PAGE_SIZE;
|
||||
unmapped += SECTION_SIZE / PAGE_SIZE;
|
||||
}
|
||||
|
||||
return unmapped;
|
||||
}
|
||||
|
||||
int arch_mmu_map(vaddr_t vaddr, paddr_t paddr, uint count, uint flags)
|
||||
{
|
||||
uint l1_index;
|
||||
uint32_t pte;
|
||||
uint32_t arch_flags = 0;
|
||||
|
||||
LTRACEF("vaddr = 0x%x, paddr = 0x%x, count = %d, flags = 0x%x\n", vaddr, paddr, count, flags);
|
||||
|
||||
if (!IS_PAGE_ALIGNED(vaddr) || !IS_PAGE_ALIGNED(paddr))
|
||||
return ERR_INVALID_ARGS;
|
||||
|
||||
if (flags & ARCH_MMU_FLAG_PERM_USER)
|
||||
arch_flags |= OR1K_MMU_PG_U;
|
||||
if (!(flags & ARCH_MMU_FLAG_PERM_NO_EXECUTE))
|
||||
arch_flags |= OR1K_MMU_PG_X;
|
||||
if (flags & ARCH_MMU_FLAG_CACHE_MASK)
|
||||
arch_flags |= OR1K_MMU_PG_CI;
|
||||
if (!(flags & ARCH_MMU_FLAG_PERM_RO))
|
||||
arch_flags |= OR1K_MMU_PG_W;
|
||||
|
||||
uint mapped = 0;
|
||||
while (count) {
|
||||
l1_index = vaddr / SECTION_SIZE;
|
||||
if (IS_ALIGNED(vaddr, SECTION_SIZE) && IS_ALIGNED(paddr, SECTION_SIZE) && count >= SECTION_SIZE / PAGE_SIZE) {
|
||||
or1k_kernel_translation_table[l1_index] = (paddr & ~(SECTION_SIZE-1)) | arch_flags | OR1K_MMU_PG_PRESENT | OR1K_MMU_PG_L;
|
||||
count -= SECTION_SIZE / PAGE_SIZE;
|
||||
mapped += SECTION_SIZE / PAGE_SIZE;
|
||||
vaddr += SECTION_SIZE;
|
||||
paddr += SECTION_SIZE;
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t *l2_table;
|
||||
|
||||
pte = or1k_kernel_translation_table[l1_index];
|
||||
|
||||
/* FIXME: l1 already mapped as a section */
|
||||
if (pte & OR1K_MMU_PG_PRESENT && pte & OR1K_MMU_PG_L)
|
||||
PANIC_UNIMPLEMENTED;
|
||||
|
||||
if (pte & OR1K_MMU_PG_PRESENT) {
|
||||
l2_table = paddr_to_kvaddr(pte & ~OR1K_MMU_PG_FLAGS_MASK);
|
||||
LTRACEF("l2_table at %p\n", l2_table);
|
||||
} else {
|
||||
l2_table = pmm_alloc_kpage();
|
||||
if (!l2_table) {
|
||||
TRACEF("failed to allocate pagetable\n");
|
||||
return mapped;
|
||||
}
|
||||
|
||||
memset(l2_table, 0, PAGE_SIZE);
|
||||
paddr_t l2_pa = kvaddr_to_paddr(l2_table);
|
||||
LTRACEF("allocated pagetable at %p, pa 0x%lx\n", l2_table, l2_pa);
|
||||
or1k_kernel_translation_table[l1_index] = l2_pa | arch_flags | OR1K_MMU_PG_PRESENT;
|
||||
}
|
||||
|
||||
uint l2_index = (vaddr % SECTION_SIZE) / PAGE_SIZE;
|
||||
|
||||
LTRACEF("l2_index = 0x%x, vaddr = 0x%x, paddr = 0x%x\n", l2_index, vaddr, paddr);
|
||||
l2_table[l2_index] = paddr | arch_flags | OR1K_MMU_PG_PRESENT | OR1K_MMU_PG_L;
|
||||
|
||||
count--;
|
||||
mapped++;
|
||||
vaddr += PAGE_SIZE;
|
||||
paddr += PAGE_SIZE;
|
||||
}
|
||||
|
||||
return mapped;
|
||||
}
|
||||
|
||||
#endif /* WITH_KERNEL_VM */
|
||||
52
arch/or1k/rules.mk
Normal file
52
arch/or1k/rules.mk
Normal file
@@ -0,0 +1,52 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
MODULE := $(LOCAL_DIR)
|
||||
|
||||
GLOBAL_INCLUDES += \
|
||||
$(LOCAL_DIR)/include
|
||||
|
||||
MODULE_SRCS += \
|
||||
$(LOCAL_DIR)/start.S \
|
||||
$(LOCAL_DIR)/arch.c \
|
||||
$(LOCAL_DIR)/asm.S \
|
||||
$(LOCAL_DIR)/exceptions.c \
|
||||
$(LOCAL_DIR)/thread.c \
|
||||
$(LOCAL_DIR)/cache-ops.c \
|
||||
$(LOCAL_DIR)/mmu.c \
|
||||
$(LOCAL_DIR)/faults.c
|
||||
|
||||
# set the default toolchain to or1k elf and set a #define
|
||||
ifndef TOOLCHAIN_PREFIX
|
||||
TOOLCHAIN_PREFIX := or1k-elf-
|
||||
endif
|
||||
|
||||
LIBGCC := $(shell $(TOOLCHAIN_PREFIX)gcc $(CFLAGS) -print-libgcc-file-name)
|
||||
$(info LIBGCC = $(LIBGCC))
|
||||
|
||||
cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc /dev/null 2>&1`"; \
|
||||
then echo "$(2)"; else echo "$(3)"; fi ;)
|
||||
|
||||
ARCH_OPTFLAGS := -O2
|
||||
|
||||
GLOBAL_LDFLAGS += -relax
|
||||
|
||||
KERNEL_BASE ?= $(MEMBASE)
|
||||
KERNEL_LOAD_OFFSET ?= 0
|
||||
|
||||
GLOBAL_DEFINES += \
|
||||
KERNEL_BASE=$(KERNEL_BASE) \
|
||||
KERNEL_LOAD_OFFSET=$(KERNEL_LOAD_OFFSET)
|
||||
|
||||
# potentially generated files that should be cleaned out with clean make rule
|
||||
GENERATED += \
|
||||
$(BUILDDIR)/linker.ld
|
||||
|
||||
# rules for generating the linker
|
||||
$(BUILDDIR)/linker.ld: $(LOCAL_DIR)/linker.ld $(wildcard arch/*.ld)
|
||||
@echo generating $@
|
||||
@$(MKDIR)
|
||||
$(NOECHO)sed "s/%MEMBASE%/$(MEMBASE)/;s/%MEMSIZE%/$(MEMSIZE)/;s/%KERNEL_BASE%/$(KERNEL_BASE)/;s/%KERNEL_LOAD_OFFSET%/$(KERNEL_LOAD_OFFSET)/" < $< > $@
|
||||
|
||||
LINKER_SCRIPT += $(BUILDDIR)/linker.ld
|
||||
|
||||
include make/module.mk
|
||||
525
arch/or1k/start.S
Normal file
525
arch/or1k/start.S
Normal file
@@ -0,0 +1,525 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Stefan Kristiansson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <asm.h>
|
||||
#include <arch/ops.h>
|
||||
#include <arch/or1k/mmu.h>
|
||||
#include <kernel/vm.h>
|
||||
|
||||
#define RED_ZONE 128
|
||||
#define EXCEPTION_FRAME (128 + RED_ZONE)
|
||||
|
||||
/* clobbers r9 and rd, result will be in rd */
|
||||
#define get_va_to_pa_offs(rd) \
|
||||
l.movhi rd, hi(.+12) ;\
|
||||
l.jal .+8 ;\
|
||||
l.ori rd, rd, lo(.+4) ;\
|
||||
l.sub rd, rd, r9
|
||||
|
||||
/* clobbers r9 and rd, result will be in rd */
|
||||
#define to_phys(sym, rd) \
|
||||
get_va_to_pa_offs(rd) ;\
|
||||
l.movhi r9, hi(sym) ;\
|
||||
l.ori r9, r9, lo(sym) ;\
|
||||
l.sub rd, r9, rd
|
||||
|
||||
.macro exception_entry
|
||||
#if WITH_KERNEL_VM
|
||||
l.sw 0(r0), r31
|
||||
l.sw 4(r0), r9
|
||||
get_va_to_pa_offs(r31)
|
||||
l.sub r1, r1, r31
|
||||
l.lwz r9, 4(r0)
|
||||
#endif
|
||||
l.addi r1, r1, -EXCEPTION_FRAME
|
||||
l.sw 0(r1), r2
|
||||
l.sw 4(r1), r3
|
||||
l.sw 8(r1), r4
|
||||
l.sw 12(r1), r5
|
||||
l.sw 16(r1), r6
|
||||
l.sw 20(r1), r7
|
||||
l.sw 24(r1), r8
|
||||
l.sw 28(r1), r9
|
||||
l.sw 32(r1), r10
|
||||
l.sw 36(r1), r11
|
||||
l.sw 40(r1), r12
|
||||
l.sw 44(r1), r13
|
||||
l.sw 48(r1), r14
|
||||
l.sw 52(r1), r15
|
||||
l.sw 56(r1), r16
|
||||
l.sw 60(r1), r17
|
||||
l.sw 64(r1), r18
|
||||
l.sw 68(r1), r19
|
||||
l.sw 72(r1), r20
|
||||
l.sw 76(r1), r21
|
||||
l.sw 80(r1), r22
|
||||
l.sw 84(r1), r23
|
||||
l.sw 88(r1), r24
|
||||
l.sw 92(r1), r25
|
||||
l.sw 96(r1), r26
|
||||
l.sw 100(r1), r27
|
||||
l.sw 104(r1), r28
|
||||
l.sw 108(r1), r29
|
||||
l.sw 112(r1), r30
|
||||
l.mfspr r3, r0, OR1K_SPR_SYS_EPCR_ADDR(0)
|
||||
l.sw 120(r1), r3
|
||||
l.mfspr r3, r0, OR1K_SPR_SYS_ESR_ADDR(0)
|
||||
l.sw 124(r1), r3
|
||||
#if WITH_KERNEL_VM
|
||||
l.add r1, r1, r31
|
||||
l.lwz r31, 0(r0)
|
||||
|
||||
/* enable dmmu and immu */
|
||||
l.mfspr r9, r0, OR1K_SPR_SYS_SR_ADDR
|
||||
l.ori r9, r9, OR1K_SPR_SYS_SR_DME_MASK | OR1K_SPR_SYS_SR_IME_MASK
|
||||
l.mtspr r0, r9, OR1K_SPR_SYS_ESR_ADDR(0)
|
||||
|
||||
l.movhi r9, hi(.+16)
|
||||
l.ori r9, r9, lo(.+12)
|
||||
l.mtspr r0, r9, OR1K_SPR_SYS_EPCR_ADDR(0)
|
||||
l.rfe
|
||||
#endif
|
||||
l.sw 116(r1), r31
|
||||
.endm
|
||||
|
||||
.section ".vectors", "ax"
|
||||
.org 0x100
|
||||
.global _reset
|
||||
_reset:
|
||||
l.jal start
|
||||
l.nop
|
||||
|
||||
.org 0x200
|
||||
bus_error_exception:
|
||||
exception_entry
|
||||
l.mfspr r4, r0, OR1K_SPR_SYS_EEAR_ADDR(0)
|
||||
l.jal or1k_busfault_handler
|
||||
l.ori r3, r1, 0
|
||||
l.j return_from_exception
|
||||
l.nop
|
||||
|
||||
.org 0x300
|
||||
data_pagefault_exception:
|
||||
exception_entry
|
||||
l.mfspr r4, r0, OR1K_SPR_SYS_EEAR_ADDR(0)
|
||||
l.jal or1k_data_pagefault_handler
|
||||
l.ori r3, r1, 0
|
||||
l.j return_from_exception
|
||||
l.nop
|
||||
|
||||
.org 0x400
|
||||
instruction_pagefault_exception:
|
||||
exception_entry
|
||||
l.mfspr r4, r0, OR1K_SPR_SYS_EEAR_ADDR(0)
|
||||
l.jal or1k_instruction_pagefault_handler
|
||||
l.ori r3, r1, 0
|
||||
l.j return_from_exception
|
||||
l.nop
|
||||
|
||||
.org 0x500
|
||||
tick_timer_exception:
|
||||
exception_entry
|
||||
l.jal or1k_tick
|
||||
l.nop
|
||||
l.j return_from_exception
|
||||
l.nop
|
||||
|
||||
.org 0x600
|
||||
alignment_exception:
|
||||
exception_entry
|
||||
l.mfspr r4, r0, OR1K_SPR_SYS_EEAR_ADDR(0)
|
||||
l.jal or1k_alignment_handler
|
||||
l.ori r3, r1, 0
|
||||
l.j return_from_exception
|
||||
l.nop
|
||||
|
||||
.org 0x700
|
||||
illegal_instruction_exception:
|
||||
exception_entry
|
||||
l.mfspr r4, r0, OR1K_SPR_SYS_EEAR_ADDR(0)
|
||||
l.jal or1k_illegal_instruction_handler
|
||||
l.ori r3, r1, 0
|
||||
l.j return_from_exception
|
||||
l.nop
|
||||
|
||||
.org 0x800
|
||||
external_interrupt_exception:
|
||||
exception_entry
|
||||
l.jal or1k_irq
|
||||
l.nop
|
||||
l.j return_from_exception
|
||||
l.nop
|
||||
|
||||
.org 0x900
|
||||
dtlb_miss_exception:
|
||||
#if WITH_KERNEL_VM
|
||||
l.sw 0(r0), r3
|
||||
l.sw 4(r0), r4
|
||||
l.sw 8(r0), r9
|
||||
|
||||
to_phys(or1k_kernel_translation_table, r3)
|
||||
l.mfspr r4, r0, OR1K_SPR_SYS_EEAR_ADDR(0)
|
||||
/* l1 index */
|
||||
l.srli r9, r4, 24
|
||||
l.slli r9, r9, 2
|
||||
|
||||
l.add r3, r3, r9
|
||||
|
||||
l.lwz r3, 0(r3) /* l1 entry */
|
||||
l.andi r9, r3, OR1K_MMU_PG_PRESENT
|
||||
l.sfnei r9, OR1K_MMU_PG_PRESENT
|
||||
l.bf dtlb_miss_fault
|
||||
l.andi r9, r3, OR1K_MMU_PG_L
|
||||
|
||||
l.sfeqi r9, OR1K_MMU_PG_L
|
||||
/* l2_index */
|
||||
l.srli r4, r4, 13
|
||||
l.bf 1f
|
||||
l.andi r4, r4, 0x7ff
|
||||
l.slli r4, r4, 2
|
||||
l.addi r9, r0, 0xffffe000 /* PAGE_SIZE-1 */
|
||||
l.and r9, r3, r9
|
||||
l.add r9, r9, r4
|
||||
l.j 2f
|
||||
l.lwz r9, 0(r9) /* l2 entry */
|
||||
|
||||
/* use bits [23:13] from EEAR */
|
||||
1: l.slli r4, r4, 13
|
||||
l.or r9, r3, r4
|
||||
|
||||
2: l.ori r3,r0,0xf351 /* sw emulation of dmmupr */
|
||||
l.srli r4,r9,4 /* get PP Index * 4 */
|
||||
l.andi r4,r4,0xc /* mask everything but PPI (without X) (& 0b01100)*/
|
||||
l.srl r3,r3,r4 /* get protection bits from "dmmupr" */
|
||||
/*
|
||||
* The protection bits are unconvienently the "wrong" way in DMMUPR
|
||||
* compared to DTLBR (UWE|URE|SWE|SRE vs SWE|SRE|UWE|URE), so we have
|
||||
* to swap their places...
|
||||
*/
|
||||
l.andi r4,r3,0x3 /* SWE|SRE */
|
||||
l.slli r4,r4,8 /* 1:0 -> 9:8 */
|
||||
l.andi r3,r3,0xc /* UWE|URE */
|
||||
l.slli r3,r3,4 /* 3:2 -> 7:6 */
|
||||
l.or r3,r3,r4
|
||||
|
||||
l.addi r4,r0,0xffffe03f /* protection bit mask */
|
||||
l.and r4,r9,r4 /* apply the mask */
|
||||
l.or r9,r4,r3 /* apply protection bits */
|
||||
|
||||
l.mfspr r3, r0, OR1K_SPR_SYS_DMMUCFGR_ADDR
|
||||
l.slli r3, r3, 31-OR1K_SPR_SYS_DMMUCFGR_NTS_MSB
|
||||
l.srli r3, r3, 31-OR1K_SPR_SYS_DMMUCFGR_NTS_LSB
|
||||
l.ori r4, r0, 1
|
||||
l.sll r3, r4, r3
|
||||
l.addi r3, r3, -1
|
||||
l.mfspr r4, r0, OR1K_SPR_SYS_EEAR_ADDR(0)
|
||||
l.srli r4, r4, 13
|
||||
l.and r3, r4, r3
|
||||
l.mtspr r3, r9, OR1K_SPR_DMMU_DTLBW_TR_ADDR(0,0)
|
||||
l.slli r4, r4, 13
|
||||
l.ori r4, r4, OR1K_SPR_DMMU_DTLBW_MR_V_MASK
|
||||
l.mtspr r3, r4, OR1K_SPR_DMMU_DTLBW_MR_ADDR(0,0)
|
||||
|
||||
l.lwz r3, 0(r0)
|
||||
l.lwz r4, 4(r0)
|
||||
l.lwz r9, 8(r0)
|
||||
l.rfe
|
||||
#endif /* WITH_KERNEL_VM */
|
||||
|
||||
dtlb_miss_fault:
|
||||
l.lwz r3, 0(r0)
|
||||
l.lwz r4, 4(r0)
|
||||
l.j data_pagefault_exception
|
||||
l.lwz r9, 8(r0)
|
||||
|
||||
.org 0xa00
|
||||
itlb_miss_exception:
|
||||
#if WITH_KERNEL_VM
|
||||
l.sw 0(r0), r3
|
||||
l.sw 4(r0), r4
|
||||
l.sw 8(r0), r9
|
||||
|
||||
to_phys(or1k_kernel_translation_table, r3)
|
||||
l.mfspr r4, r0, OR1K_SPR_SYS_EEAR_ADDR(0)
|
||||
/* l1 index */
|
||||
l.srli r9, r4, 24
|
||||
l.slli r9, r9, 2
|
||||
|
||||
l.add r3, r3, r9
|
||||
l.lwz r3, 0(r3) /* l1 entry */
|
||||
|
||||
l.andi r9, r3, OR1K_MMU_PG_PRESENT
|
||||
l.sfnei r9, OR1K_MMU_PG_PRESENT
|
||||
l.bf itlb_miss_fault
|
||||
l.andi r9, r3, OR1K_MMU_PG_L
|
||||
l.sfeqi r9, OR1K_MMU_PG_L
|
||||
/* l2 index */
|
||||
l.srli r4, r4, 13
|
||||
l.bf 1f
|
||||
l.andi r4, r4, 0x7ff
|
||||
|
||||
l.slli r4, r4, 2
|
||||
l.addi r9, r0, 0xffffe000 /* PAGE_SIZE-1 */
|
||||
l.and r9, r3, r9
|
||||
l.add r9, r9, r4
|
||||
l.j 2f
|
||||
l.lwz r9, 0(r9) /* l2 entry */
|
||||
|
||||
/* use bits [23:13] from EEAR */
|
||||
1: l.slli r4, r4, 13
|
||||
l.or r9, r3, r4
|
||||
|
||||
2: l.ori r3, r0, 0xd00 /* sw emulation of immupr */
|
||||
l.srli r4, r9, 5 /* get PP Index * 2 */
|
||||
l.andi r4, r4, 0xa /* mask everything but PPI (without W) (& 0b1010)*/
|
||||
l.srl r3, r3, r4 /* get protection bits from "immupr" */
|
||||
l.andi r3, r3, 0x3 /* mask everything else out */
|
||||
l.slli r3, r3, 6 /* and put them in their spot */
|
||||
l.addi r4, r0, 0xffffe03f /* protection bit mask */
|
||||
l.and r4, r9, r4 /* apply the mask */
|
||||
l.or r9, r4, r3 /* apply protection bits */
|
||||
|
||||
l.mfspr r3, r0, OR1K_SPR_SYS_IMMUCFGR_ADDR
|
||||
l.slli r3, r3, 31-OR1K_SPR_SYS_IMMUCFGR_NTS_MSB
|
||||
l.srli r3, r3, 31-OR1K_SPR_SYS_IMMUCFGR_NTS_LSB
|
||||
l.ori r4, r0, 1
|
||||
l.sll r3, r4, r3
|
||||
l.addi r3, r3, -1
|
||||
l.mfspr r4, r0, OR1K_SPR_SYS_EEAR_ADDR(0)
|
||||
l.srli r4, r4, 13
|
||||
l.and r3, r4, r3
|
||||
l.mtspr r3, r9, OR1K_SPR_IMMU_ITLBW_TR_ADDR(0,0)
|
||||
|
||||
l.slli r4, r4, 13
|
||||
l.ori r4, r4, OR1K_SPR_IMMU_ITLBW_MR_V_MASK
|
||||
l.mtspr r3, r4, OR1K_SPR_IMMU_ITLBW_MR_ADDR(0,0)
|
||||
|
||||
l.lwz r3, 0(r0)
|
||||
l.lwz r4, 4(r0)
|
||||
l.lwz r9, 8(r0)
|
||||
l.rfe
|
||||
#endif /* WITH_KERNEL_VM */
|
||||
|
||||
itlb_miss_fault:
|
||||
l.lwz r3, 0(r0)
|
||||
l.lwz r4, 4(r0)
|
||||
l.j instruction_pagefault_exception
|
||||
l.lwz r9, 8(r0)
|
||||
|
||||
.org 0xb00
|
||||
range_exception:
|
||||
exception_entry
|
||||
l.ori r4, r0, 0xb00
|
||||
l.jal or1k_unhandled_exception
|
||||
l.ori r3, r1, 0
|
||||
l.j return_from_exception
|
||||
l.nop
|
||||
|
||||
.org 0xc00
|
||||
syscall_exception:
|
||||
exception_entry
|
||||
l.jal or1k_syscall_handler
|
||||
l.ori r3, r1, 0
|
||||
l.j return_from_exception
|
||||
l.nop
|
||||
|
||||
.org 0xd00
|
||||
fpu_exception:
|
||||
exception_entry
|
||||
l.ori r4, r0, 0xd00
|
||||
l.jal or1k_unhandled_exception
|
||||
l.ori r3, r1, 0
|
||||
l.j return_from_exception
|
||||
l.nop
|
||||
|
||||
.org 0xe00
|
||||
trap_exception:
|
||||
exception_entry
|
||||
l.ori r4, r0, 0xe00
|
||||
l.jal or1k_unhandled_exception
|
||||
l.ori r3, r1, 0
|
||||
l.j return_from_exception
|
||||
l.nop
|
||||
|
||||
.section ".text.boot"
|
||||
FUNCTION(start)
|
||||
/* set stack pointer to point at top of default stack */
|
||||
l.movhi r1, hi(default_stack_top)
|
||||
l.ori r1, r1, lo(default_stack_top)
|
||||
|
||||
#if WITH_KERNEL_VM
|
||||
/* invalidate tlbs */
|
||||
l.ori r3, r0, OR1K_SPR_DMMU_DTLBW_MR_ADDR(0, 0)
|
||||
l.ori r4, r0, OR1K_SPR_IMMU_ITLBW_MR_ADDR(0, 0)
|
||||
l.addi r6, r0, 3 /* Maximum number of ways - 1 */
|
||||
|
||||
1: l.addi r5, r0, 127 /* Maximum number of sets - 1 */
|
||||
2: l.mtspr r3, r0, 0x0
|
||||
l.mtspr r4, r0, 0x0
|
||||
|
||||
l.addi r3, r3, 1
|
||||
l.addi r4, r4, 1
|
||||
l.sfeq r5, r0
|
||||
l.bnf 2b
|
||||
l.addi r5, r5, -1
|
||||
|
||||
l.addi r3, r3, 128
|
||||
l.addi r4, r4, 128
|
||||
|
||||
l.sfeq r6, r0
|
||||
l.bnf 1b
|
||||
l.addi r6, r6, -1
|
||||
|
||||
/* setup initial mappings */
|
||||
get_va_to_pa_offs(r3)
|
||||
l.movhi r4, hi(or1k_kernel_translation_table)
|
||||
l.ori r4, r4, lo(or1k_kernel_translation_table)
|
||||
l.sub r4, r4, r3 /* to phys */
|
||||
l.movhi r5, hi(mmu_initial_mappings)
|
||||
l.ori r5, r5, lo(mmu_initial_mappings)
|
||||
l.sub r5, r5, r3 /* to phys */
|
||||
|
||||
/* clear the translation table */
|
||||
l.addi r3, r4, 255*4
|
||||
0: l.sw 0(r3), r0
|
||||
l.sfeq r3, r4
|
||||
l.bnf 0b
|
||||
l.addi r3, r3, -4
|
||||
|
||||
1: l.lwz r6, 0(r5) /* phys */
|
||||
l.lwz r7, 4(r5) /* virt */
|
||||
l.lwz r8, 8(r5) /* size */
|
||||
l.lwz r9, 12(r5) /* flags */
|
||||
l.lwz r10, 16(r5) /* name */
|
||||
l.addi r5, r5, 20
|
||||
|
||||
/* divide with 16MB */
|
||||
l.srli r6, r6, 24
|
||||
l.srli r7, r7, 24
|
||||
l.srli r8, r8, 24
|
||||
|
||||
l.sfeqi r8, 0
|
||||
l.bf .Linitial_mapping_done
|
||||
l.nop
|
||||
|
||||
2: l.slli r3, r7, 2
|
||||
l.add r3, r4, r3
|
||||
l.slli r10, r6, 24
|
||||
l.ori r10, r10, OR1K_MMU_PG_PRESENT | OR1K_MMU_PG_X | OR1K_MMU_PG_W | OR1K_MMU_PG_L
|
||||
l.sfeqi r9, MMU_INITIAL_MAPPING_FLAG_UNCACHED
|
||||
l.bf 3f
|
||||
l.sfeqi r9, MMU_INITIAL_MAPPING_FLAG_DEVICE
|
||||
l.bnf 4f
|
||||
l.nop
|
||||
3: l.ori r10, r10, OR1K_MMU_PG_CI
|
||||
4: l.sw 0(r3), r10
|
||||
l.addi r6, r6, 1
|
||||
l.addi r8, r8, -1
|
||||
l.sfeqi r8, 0
|
||||
l.bnf 2b
|
||||
l.addi r7, r7, 1
|
||||
|
||||
l.j 1b
|
||||
l.nop
|
||||
|
||||
.Linitial_mapping_done:
|
||||
/* enable mmu */
|
||||
l.mfspr r3, r0, OR1K_SPR_SYS_SR_ADDR
|
||||
l.ori r3, r3, OR1K_SPR_SYS_SR_DME_MASK | OR1K_SPR_SYS_SR_IME_MASK
|
||||
l.mtspr r0, r3, OR1K_SPR_SYS_ESR_ADDR(0)
|
||||
/* setup pc to use virtual addresses */
|
||||
l.movhi r3, hi(.+16)
|
||||
l.ori r3, r3, lo(.+12)
|
||||
l.mtspr r0, r3, OR1K_SPR_SYS_EPCR_ADDR(0)
|
||||
l.rfe
|
||||
#endif
|
||||
|
||||
/* invalidate and enable caches */
|
||||
l.jal arch_invalidate_cache_all
|
||||
l.nop
|
||||
l.jal arch_enable_cache
|
||||
l.ori r3, r0, UCACHE
|
||||
|
||||
/* clear bss */
|
||||
l.movhi r3, hi(__bss_start)
|
||||
l.ori r3, r3, lo(__bss_start)
|
||||
l.movhi r4, hi(__bss_end)
|
||||
l.ori r4, r4, lo(__bss_end)
|
||||
1: l.sw 0(r3), r0
|
||||
l.sfltu r3, r4
|
||||
l.bf 1b
|
||||
l.addi r3, r3, 4
|
||||
|
||||
/* arguments to main */
|
||||
l.ori r3, r0, 1
|
||||
l.ori r4, r0, 2
|
||||
l.ori r5, r0, 3
|
||||
l.jal lk_main
|
||||
l.ori r6, r0, 4
|
||||
|
||||
/* shouldn't happen, but loop if it does */
|
||||
l.j 0
|
||||
l.nop
|
||||
|
||||
FUNCTION(return_from_exception)
|
||||
l.lwz r3, 120(r1)
|
||||
l.mtspr r0, r3, OR1K_SPR_SYS_EPCR_BASE
|
||||
l.lwz r3, 124(r1)
|
||||
l.mtspr r0, r3, OR1K_SPR_SYS_ESR_BASE
|
||||
l.lwz r2, 0(r1)
|
||||
l.lwz r3, 4(r1)
|
||||
l.lwz r4, 8(r1)
|
||||
l.lwz r5, 12(r1)
|
||||
l.lwz r6, 16(r1)
|
||||
l.lwz r7, 20(r1)
|
||||
l.lwz r8, 24(r1)
|
||||
l.lwz r9, 28(r1)
|
||||
l.lwz r10, 32(r1)
|
||||
l.lwz r11, 36(r1)
|
||||
l.lwz r12, 40(r1)
|
||||
l.lwz r13, 44(r1)
|
||||
l.lwz r14, 48(r1)
|
||||
l.lwz r15, 52(r1)
|
||||
l.lwz r16, 56(r1)
|
||||
l.lwz r17, 60(r1)
|
||||
l.lwz r18, 64(r1)
|
||||
l.lwz r19, 68(r1)
|
||||
l.lwz r20, 72(r1)
|
||||
l.lwz r21, 76(r1)
|
||||
l.lwz r22, 80(r1)
|
||||
l.lwz r23, 84(r1)
|
||||
l.lwz r24, 88(r1)
|
||||
l.lwz r25, 92(r1)
|
||||
l.lwz r26, 96(r1)
|
||||
l.lwz r27, 100(r1)
|
||||
l.lwz r28, 104(r1)
|
||||
l.lwz r29, 108(r1)
|
||||
l.lwz r30, 112(r1)
|
||||
l.lwz r31, 116(r1)
|
||||
l.addi r1, r1, EXCEPTION_FRAME
|
||||
l.rfe
|
||||
|
||||
.section ".bss"
|
||||
.align 8
|
||||
LOCAL_DATA(default_stack)
|
||||
.skip 8192
|
||||
LOCAL_DATA(default_stack_top)
|
||||
76
arch/or1k/thread.c
Normal file
76
arch/or1k/thread.c
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Stefan Kristiansson
|
||||
* Based on arch/microblaze/thread.c
|
||||
* Copyright (c) 2015 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <debug.h>
|
||||
#include <trace.h>
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <kernel/thread.h>
|
||||
|
||||
#define LOCAL_TRACE 0
|
||||
|
||||
struct thread *_current_thread;
|
||||
|
||||
static void initial_thread_func(void) __NO_RETURN;
|
||||
static void initial_thread_func(void)
|
||||
{
|
||||
thread_t *ct = get_current_thread();
|
||||
|
||||
#if LOCAL_TRACE
|
||||
LTRACEF("thread %p calling %p with arg %p\n", ct, ct->entry, ct->arg);
|
||||
dump_thread(ct);
|
||||
#endif
|
||||
|
||||
/* exit the implicit critical section we're within */
|
||||
exit_critical_section();
|
||||
|
||||
int ret = ct->entry(ct->arg);
|
||||
|
||||
LTRACEF("thread %p exiting with %d\n", ct, ret);
|
||||
|
||||
thread_exit(ret);
|
||||
}
|
||||
|
||||
void arch_thread_initialize(thread_t *t)
|
||||
{
|
||||
LTRACEF("t %p (%s)\n", t, t->name);
|
||||
|
||||
/* some registers we want to clone for the new thread */
|
||||
register uint32_t r2 asm("r2");
|
||||
|
||||
/* zero out the thread context */
|
||||
memset(&t->arch.cs_frame, 0, sizeof(t->arch.cs_frame));
|
||||
|
||||
t->arch.cs_frame.r1 = (vaddr_t)t->stack + t->stack_size;
|
||||
t->arch.cs_frame.r2 = r2;
|
||||
t->arch.cs_frame.r9 = (vaddr_t)initial_thread_func;
|
||||
}
|
||||
|
||||
void arch_context_switch(thread_t *oldthread, thread_t *newthread)
|
||||
{
|
||||
LTRACEF("old %p (%s), new %p (%s)\n", oldthread, oldthread->name, newthread, newthread->name);
|
||||
|
||||
or1k_context_switch(&oldthread->arch.cs_frame, &newthread->arch.cs_frame);
|
||||
}
|
||||
80
dev/interrupt/or1k_pic/or1k_pic.c
Normal file
80
dev/interrupt/or1k_pic/or1k_pic.c
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Stefan Kristiansson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <err.h>
|
||||
#include <debug.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <platform/interrupts.h>
|
||||
#include <platform/pic.h>
|
||||
#include <arch/or1k.h>
|
||||
|
||||
struct int_handler_struct {
|
||||
int_handler handler;
|
||||
void *arg;
|
||||
};
|
||||
|
||||
static struct int_handler_struct int_handler_table[MAX_INT];
|
||||
|
||||
void register_int_handler(unsigned int vector, int_handler handler, void *arg)
|
||||
{
|
||||
if (vector >= MAX_INT)
|
||||
panic("%s: vector out of range %d\n", __FUNCTION__, vector);
|
||||
|
||||
enter_critical_section();
|
||||
|
||||
int_handler_table[vector].handler = handler;
|
||||
int_handler_table[vector].arg = arg;
|
||||
|
||||
exit_critical_section();
|
||||
}
|
||||
|
||||
status_t mask_interrupt(unsigned int vector)
|
||||
{
|
||||
if (vector >= MAX_INT)
|
||||
return ERR_INVALID_ARGS;
|
||||
|
||||
mtspr(OR1K_SPR_PIC_PICMR_ADDR, mfspr(OR1K_SPR_PIC_PICMR_ADDR) & ~(1 << vector));
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t unmask_interrupt(unsigned int vector)
|
||||
{
|
||||
if (vector >= MAX_INT)
|
||||
return ERR_INVALID_ARGS;
|
||||
|
||||
mtspr(OR1K_SPR_PIC_PICMR_ADDR, mfspr(OR1K_SPR_PIC_PICMR_ADDR) | (1 << vector));
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
enum handler_return platform_irq(void)
|
||||
{
|
||||
enum handler_return ret = INT_NO_RESCHEDULE;
|
||||
|
||||
uint irq = __builtin_ffs(mfspr(OR1K_SPR_PIC_PICSR_ADDR)) - 1;
|
||||
|
||||
if (irq < MAX_INT && int_handler_table[irq].handler)
|
||||
ret = int_handler_table[irq].handler(int_handler_table[irq].arg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
11
dev/interrupt/or1k_pic/rules.mk
Normal file
11
dev/interrupt/or1k_pic/rules.mk
Normal file
@@ -0,0 +1,11 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
MODULE := $(LOCAL_DIR)
|
||||
|
||||
GLOBAL_INCLUDES += \
|
||||
$(LOCAL_DIR)/include
|
||||
|
||||
MODULE_SRCS += \
|
||||
$(LOCAL_DIR)/or1k_pic.c
|
||||
|
||||
include make/module.mk
|
||||
27
dev/timer/or1k_ticktimer/include/dev/timer/or1k_ticktimer.h
Normal file
27
dev/timer/or1k_ticktimer/include/dev/timer/or1k_ticktimer.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Stefan Kristiansson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
void or1k_ticktimer_init(uint32_t freq);
|
||||
93
dev/timer/or1k_ticktimer/or1k_ticktimer.c
Normal file
93
dev/timer/or1k_ticktimer/or1k_ticktimer.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Stefan Kristiansson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <trace.h>
|
||||
#include <err.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <platform/timer.h>
|
||||
#include <platform/debug.h>
|
||||
#include <sys/types.h>
|
||||
#include <arch/or1k.h>
|
||||
|
||||
#define LOCAL_TRACE 0
|
||||
|
||||
static platform_timer_callback timer_cb;
|
||||
static void *timer_arg;
|
||||
|
||||
static uint32_t timer_freq;
|
||||
|
||||
static volatile uint64_t ticks = 0;
|
||||
|
||||
status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, lk_time_t interval)
|
||||
{
|
||||
LTRACEF("cb %p, arg %p, interval %ld\n", callback, arg, interval);
|
||||
|
||||
uint32_t ttmr = (uint64_t)timer_freq * interval / 1000;
|
||||
LTRACEF("count 0x%x\n", ttmr);
|
||||
|
||||
timer_cb = callback;
|
||||
timer_arg = arg;
|
||||
|
||||
/* disable timer before doing changes */
|
||||
mtspr(OR1K_SPR_TICK_TTMR_ADDR, 0);
|
||||
/* reset timer counter */
|
||||
mtspr(OR1K_SPR_TICK_TTCR_ADDR, 0);
|
||||
/* enable timer with given interval in 'restart' mode */
|
||||
ttmr = OR1K_SPR_TICK_TTMR_MODE_SET(ttmr | OR1K_SPR_TICK_TTMR_IE_MASK,
|
||||
OR1K_SPR_TICK_TTMR_MODE_RESTART);
|
||||
mtspr(OR1K_SPR_TICK_TTMR_ADDR, ttmr);
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
lk_bigtime_t current_time_hires(void)
|
||||
{
|
||||
return (lk_bigtime_t)ticks * 10000;
|
||||
}
|
||||
|
||||
lk_time_t current_time(void)
|
||||
{
|
||||
return (lk_time_t)ticks * 10;
|
||||
}
|
||||
|
||||
enum handler_return platform_tick(void)
|
||||
{
|
||||
ticks++;
|
||||
|
||||
/* clear pending interrupt flag */
|
||||
mtspr(OR1K_SPR_TICK_TTMR_ADDR,
|
||||
mfspr(OR1K_SPR_TICK_TTMR_ADDR) & ~(OR1K_SPR_TICK_TTMR_IP_MASK));
|
||||
|
||||
return timer_cb(timer_arg, ticks * 10);
|
||||
}
|
||||
|
||||
void or1k_ticktimer_init(uint32_t freq)
|
||||
{
|
||||
timer_freq = freq;
|
||||
/* disable timer */
|
||||
mtspr(OR1K_SPR_TICK_TTMR_ADDR, 0);
|
||||
/* reset timer counter */
|
||||
mtspr(OR1K_SPR_TICK_TTCR_ADDR, 0);
|
||||
/* clear pending interrupt flag */
|
||||
mtspr(OR1K_SPR_TICK_TTMR_ADDR,
|
||||
mfspr(OR1K_SPR_TICK_TTMR_ADDR) & ~(OR1K_SPR_TICK_TTMR_IP_MASK));
|
||||
}
|
||||
14
dev/timer/or1k_ticktimer/rules.mk
Normal file
14
dev/timer/or1k_ticktimer/rules.mk
Normal file
@@ -0,0 +1,14 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
MODULE := $(LOCAL_DIR)
|
||||
|
||||
GLOBAL_INCLUDES += \
|
||||
$(LOCAL_DIR)/include
|
||||
|
||||
#GLOBAL_DEFINES += \
|
||||
# PLATFORM_HAS_DYNAMIC_TIMER=1
|
||||
|
||||
MODULE_SRCS += \
|
||||
$(LOCAL_DIR)/or1k_ticktimer.c
|
||||
|
||||
include make/module.mk
|
||||
0
lib/libc/string/arch/or1k/rules.mk
Normal file
0
lib/libc/string/arch/or1k/rules.mk
Normal file
Reference in New Issue
Block a user