/branches/network/kernel/arch/ppc32/Makefile.inc |
---|
29,11 → 29,15 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_NAME = elf32-powerpc |
BFD_ARCH = powerpc:common |
BFD = binary |
TARGET = ppc-linux-gnu |
TOOLCHAIN_DIR = /usr/local/ppc |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ppc |
GCC_CFLAGS += -mcpu=powerpc -msoft-float -m32 |
AFLAGS += -a32 |
/branches/network/kernel/arch/ppc32/include/mm/page.h |
---|
40,8 → 40,6 |
#define PAGE_WIDTH FRAME_WIDTH |
#define PAGE_SIZE FRAME_SIZE |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#ifdef KERNEL |
#ifndef __ASM__ |
/branches/network/kernel/arch/ppc32/include/mm/tlb.h |
---|
36,6 → 36,8 |
#define KERN_ppc32_TLB_H_ |
#include <arch/interrupt.h> |
#include <arch/types.h> |
#include <typedefs.h> |
typedef struct { |
unsigned v : 1; /**< Valid */ |
/branches/network/kernel/arch/ppc32/include/barrier.h |
---|
42,6 → 42,43 |
#define read_barrier() asm volatile ("sync" ::: "memory") |
#define write_barrier() asm volatile ("eieio" ::: "memory") |
/* |
* The IMB sequence used here is valid for all possible cache models |
* on uniprocessor. SMP might require a different sequence. |
* See PowerPC Programming Environment for 32-Bit Microprocessors, |
* chapter 5.1.5.2 |
*/ |
static inline void smc_coherence(void *addr) |
{ |
asm volatile ( |
"dcbst 0, %0\n" |
"sync\n" |
"icbi 0, %0\n" |
"isync\n" |
:: "r" (addr) |
); |
} |
#define COHERENCE_INVAL_MIN 4 |
static inline void smc_coherence_block(void *addr, unsigned long len) |
{ |
unsigned long i; |
for (i = 0; i < len; i += COHERENCE_INVAL_MIN) { |
asm volatile ("dcbst 0, %0\n" :: "r" (addr + i)); |
} |
asm volatile ("sync"); |
for (i = 0; i < len; i += COHERENCE_INVAL_MIN) { |
asm volatile ("icbi 0, %0\n" :: "r" (addr + i)); |
} |
asm volatile ("isync"); |
} |
#endif |
/** @} |
/branches/network/kernel/arch/ppc32/include/memstr.h |
---|
37,10 → 37,10 |
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt)) |
extern void memsetw(uintptr_t dst, size_t cnt, uint16_t x); |
extern void memsetb(uintptr_t dst, size_t cnt, uint8_t x); |
extern void memsetw(void *dst, size_t cnt, uint16_t x); |
extern void memsetb(void *dst, size_t cnt, uint8_t x); |
extern int memcmp(uintptr_t src, uintptr_t dst, int cnt); |
extern int memcmp(const void *a, const void *b, size_t cnt); |
#endif |
/branches/network/kernel/arch/ppc32/include/exception.h |
---|
82,6 → 82,7 |
{ |
istate->pc = retaddr; |
} |
/** Return true if exception happened while in userspace */ |
#include <panic.h> |
static inline int istate_from_uspace(istate_t *istate) |
89,6 → 90,7 |
panic("istate_from_uspace not yet implemented"); |
return 0; |
} |
static inline unative_t istate_get_pc(istate_t *istate) |
{ |
return istate->pc; |
/branches/network/kernel/arch/ppc32/include/boot/boot.h |
---|
38,7 → 38,7 |
#define BOOT_OFFSET 0x8000 |
/* Temporary stack size for boot process */ |
#define TEMP_STACK_SIZE 0x100 |
#define TEMP_STACK_SIZE 0x1000 |
#define TASKMAP_MAX_RECORDS 32 |
#define MEMMAP_MAX_RECORDS 32 |
/branches/network/kernel/arch/ppc32/include/drivers/cuda.h |
---|
36,6 → 36,7 |
#define KERN_ppc32_CUDA_H_ |
#include <arch/types.h> |
#include <typedefs.h> |
extern void cuda_init(devno_t devno, uintptr_t base, size_t size); |
extern int cuda_get_scancode(void); |
/branches/network/kernel/arch/ppc32/include/types.h |
---|
35,10 → 35,6 |
#ifndef KERN_ppc32_TYPES_H_ |
#define KERN_ppc32_TYPES_H_ |
#define NULL 0 |
#define false 0 |
#define true 1 |
typedef signed char int8_t; |
typedef signed short int16_t; |
typedef signed int int32_t; |
61,14 → 57,31 |
typedef uint32_t unative_t; |
typedef int32_t native_t; |
typedef uint8_t bool; |
typedef uint64_t thread_id_t; |
typedef uint64_t task_id_t; |
typedef uint32_t context_id_t; |
/**< Formats for uintptr_t, size_t, count_t and index_t */ |
#define PRIp "x" |
#define PRIs "u" |
#define PRIc "u" |
#define PRIi "u" |
typedef int32_t inr_t; |
typedef int32_t devno_t; |
/**< Formats for (u)int8_t, (u)int16_t, (u)int32_t, (u)int64_t and (u)native_t */ |
#define PRId8 "d" |
#define PRId16 "d" |
#define PRId32 "d" |
#define PRId64 "lld" |
#define PRIdn "d" |
#define PRIu8 "u" |
#define PRIu16 "u" |
#define PRIu32 "u" |
#define PRIu64 "llu" |
#define PRIun "u" |
#define PRIx8 "x" |
#define PRIx16 "x" |
#define PRIx32 "x" |
#define PRIx64 "llx" |
#define PRIxn "x" |
/** Page Table Entry. */ |
typedef struct { |
unsigned p : 1; /**< Present bit. */ |
/branches/network/kernel/arch/ppc32/include/context_offset.h |
---|
73,4 → 73,59 |
#define OFFSET_FR31 0x88 |
#define OFFSET_FPSCR 0x90 |
#ifdef __ASM__ |
# include <arch/asm/regname.h> |
# ctx: address of the structure with saved context |
.macro CONTEXT_SAVE_ARCH_CORE ctx:req |
stw sp, OFFSET_SP(\ctx) |
stw r2, OFFSET_R2(\ctx) |
stw r13, OFFSET_R13(\ctx) |
stw r14, OFFSET_R14(\ctx) |
stw r15, OFFSET_R15(\ctx) |
stw r16, OFFSET_R16(\ctx) |
stw r17, OFFSET_R17(\ctx) |
stw r18, OFFSET_R18(\ctx) |
stw r19, OFFSET_R19(\ctx) |
stw r20, OFFSET_R20(\ctx) |
stw r21, OFFSET_R21(\ctx) |
stw r22, OFFSET_R22(\ctx) |
stw r23, OFFSET_R23(\ctx) |
stw r24, OFFSET_R24(\ctx) |
stw r25, OFFSET_R25(\ctx) |
stw r26, OFFSET_R26(\ctx) |
stw r27, OFFSET_R27(\ctx) |
stw r28, OFFSET_R28(\ctx) |
stw r29, OFFSET_R29(\ctx) |
stw r30, OFFSET_R30(\ctx) |
stw r31, OFFSET_R31(\ctx) |
.endm |
# ctx: address of the structure with saved context |
.macro CONTEXT_RESTORE_ARCH_CORE ctx:req |
lwz sp, OFFSET_SP(\ctx) |
lwz r2, OFFSET_R2(\ctx) |
lwz r13, OFFSET_R13(\ctx) |
lwz r14, OFFSET_R14(\ctx) |
lwz r15, OFFSET_R15(\ctx) |
lwz r16, OFFSET_R16(\ctx) |
lwz r17, OFFSET_R17(\ctx) |
lwz r18, OFFSET_R18(\ctx) |
lwz r19, OFFSET_R19(\ctx) |
lwz r20, OFFSET_R20(\ctx) |
lwz r21, OFFSET_R21(\ctx) |
lwz r22, OFFSET_R22(\ctx) |
lwz r23, OFFSET_R23(\ctx) |
lwz r24, OFFSET_R24(\ctx) |
lwz r25, OFFSET_R25(\ctx) |
lwz r26, OFFSET_R26(\ctx) |
lwz r27, OFFSET_R27(\ctx) |
lwz r28, OFFSET_R28(\ctx) |
lwz r29, OFFSET_R29(\ctx) |
lwz r30, OFFSET_R30(\ctx) |
lwz r31, OFFSET_R31(\ctx) |
.endm |
#endif /* __ASM__ */ |
#endif |
/branches/network/kernel/arch/ppc32/include/byteorder.h |
---|
35,14 → 35,8 |
#ifndef KERN_ppc32_BYTEORDER_H_ |
#define KERN_ppc32_BYTEORDER_H_ |
#include <byteorder.h> |
#define ARCH_IS_BIG_ENDIAN |
#define uint32_t_le2host(n) uint32_t_byteorder_swap(n) |
#define uint64_t_le2host(n) uint64_t_byteorder_swap(n) |
#define uint32_t_be2host(n) (n) |
#define uint64_t_be2host(n) (n) |
#endif |
/** @} |
/branches/network/kernel/arch/ppc32/src/asm.S |
---|
65,6 → 65,10 |
# set stack |
mr sp, r4 |
# %r3 is defined to hold pcb_ptr - set it to 0 |
xor r3, r3, r3 |
# jump to userspace |
199,47 → 203,7 |
rfi |
memsetb: |
rlwimi r5, r5, 8, 16, 23 |
rlwimi r5, r5, 16, 0, 15 |
addi r14, r3, -4 |
cmplwi 0, r4, 4 |
blt 7f |
stwu r5, 4(r14) |
beqlr |
andi. r15, r14, 3 |
add r4, r15, r4 |
subf r14, r15, r14 |
srwi r15, r4, 2 |
mtctr r15 |
bdz 6f |
1: |
stwu r5, 4(r14) |
bdnz 1b |
6: |
andi. r4, r4, 3 |
7: |
cmpwi 0, r4, 0 |
beqlr |
mtctr r4 |
addi r6, r6, 3 |
8: |
stbu r5, 1(r14) |
bdnz 8b |
blr |
b _memsetb |
memcpy: |
memcpy_from_uspace: |
308,4 → 272,6 |
memcpy_from_uspace_failover_address: |
memcpy_to_uspace_failover_address: |
b memcpy_from_uspace_failover_address |
# return zero, failure |
xor r3, r3, r3 |
blr |
/branches/network/kernel/arch/ppc32/src/mm/tlb.c |
---|
47,16 → 47,19 |
* The as->lock must be held on entry to this function |
* if lock is true. |
* |
* @param as Address space. |
* @param lock Lock/unlock the address space. |
* @param badvaddr Faulting virtual address. |
* @param access Access mode that caused the fault. |
* @param istate Pointer to interrupted state. |
* @param pfrc Pointer to variable where as_page_fault() return code will be stored. |
* @return PTE on success, NULL otherwise. |
* @param as Address space. |
* @param lock Lock/unlock the address space. |
* @param badvaddr Faulting virtual address. |
* @param access Access mode that caused the fault. |
* @param istate Pointer to interrupted state. |
* @param pfrc Pointer to variable where as_page_fault() return code |
* will be stored. |
* @return PTE on success, NULL otherwise. |
* |
*/ |
static pte_t *find_mapping_and_check(as_t *as, bool lock, uintptr_t badvaddr, int access, istate_t *istate, int *pfrc) |
static pte_t * |
find_mapping_and_check(as_t *as, bool lock, uintptr_t badvaddr, int access, |
istate_t *istate, int *pfrc) |
{ |
/* |
* Check if the mapping exists in page tables. |
77,27 → 80,27 |
*/ |
page_table_unlock(as, lock); |
switch (rc = as_page_fault(badvaddr, access, istate)) { |
case AS_PF_OK: |
/* |
* The higher-level page fault handler succeeded, |
* The mapping ought to be in place. |
*/ |
page_table_lock(as, lock); |
pte = page_mapping_find(as, badvaddr); |
ASSERT((pte) && (pte->p)); |
*pfrc = 0; |
return pte; |
case AS_PF_DEFER: |
page_table_lock(as, lock); |
*pfrc = rc; |
return NULL; |
case AS_PF_FAULT: |
page_table_lock(as, lock); |
printf("Page fault.\n"); |
*pfrc = rc; |
return NULL; |
default: |
panic("unexpected rc (%d)\n", rc); |
case AS_PF_OK: |
/* |
* The higher-level page fault handler succeeded, |
* The mapping ought to be in place. |
*/ |
page_table_lock(as, lock); |
pte = page_mapping_find(as, badvaddr); |
ASSERT((pte) && (pte->p)); |
*pfrc = 0; |
return pte; |
case AS_PF_DEFER: |
page_table_lock(as, lock); |
*pfrc = rc; |
return NULL; |
case AS_PF_FAULT: |
page_table_lock(as, lock); |
printf("Page fault.\n"); |
*pfrc = rc; |
return NULL; |
default: |
panic("unexpected rc (%d)\n", rc); |
} |
} |
} |
114,7 → 117,8 |
s = get_symtab_entry(istate->lr); |
if (s) |
sym2 = s; |
panic("%p: PHT Refill Exception at %p (%s<-%s)\n", badvaddr, istate->pc, symbol, sym2); |
panic("%p: PHT Refill Exception at %p (%s<-%s)\n", badvaddr, |
istate->pc, symbol, sym2); |
} |
147,7 → 151,8 |
/* Find unused or colliding |
PTE in PTEG */ |
for (i = 0; i < 8; i++) { |
if ((!phte[base + i].v) || ((phte[base + i].vsid == vsid) && (phte[base + i].api == api))) { |
if ((!phte[base + i].v) || ((phte[base + i].vsid == vsid) && |
(phte[base + i].api == api))) { |
found = true; |
break; |
} |
160,7 → 165,9 |
/* Find unused or colliding |
PTE in PTEG */ |
for (i = 0; i < 8; i++) { |
if ((!phte[base2 + i].v) || ((phte[base2 + i].vsid == vsid) && (phte[base2 + i].api == api))) { |
if ((!phte[base2 + i].v) || |
((phte[base2 + i].vsid == vsid) && |
(phte[base2 + i].api == api))) { |
found = true; |
base = base2; |
h = 1; |
214,7 → 221,9 |
/* Find unused or colliding |
PTE in PTEG */ |
for (i = 0; i < 8; i++) { |
if ((!phte_physical[base + i].v) || ((phte_physical[base + i].vsid == vsid) && (phte_physical[base + i].api == api))) { |
if ((!phte_physical[base + i].v) || |
((phte_physical[base + i].vsid == vsid) && |
(phte_physical[base + i].api == api))) { |
found = true; |
break; |
} |
227,7 → 236,9 |
/* Find unused or colliding |
PTE in PTEG */ |
for (i = 0; i < 8; i++) { |
if ((!phte_physical[base2 + i].v) || ((phte_physical[base2 + i].vsid == vsid) && (phte_physical[base2 + i].api == api))) { |
if ((!phte_physical[base2 + i].v) || |
((phte_physical[base2 + i].vsid == vsid) && |
(phte_physical[base2 + i].api == api))) { |
found = true; |
base = base2; |
h = 1; |
254,8 → 265,8 |
/** Process Instruction/Data Storage Interrupt |
* |
* @param n Interrupt vector number. |
* @param istate Interrupted register context. |
* @param n Interrupt vector number. |
* @param istate Interrupted register context. |
* |
*/ |
void pht_refill(int n, istate_t *istate) |
284,21 → 295,22 |
page_table_lock(as, lock); |
pte = find_mapping_and_check(as, lock, badvaddr, PF_ACCESS_READ /* FIXME */, istate, &pfrc); |
pte = find_mapping_and_check(as, lock, badvaddr, |
PF_ACCESS_READ /* FIXME */, istate, &pfrc); |
if (!pte) { |
switch (pfrc) { |
case AS_PF_FAULT: |
goto fail; |
break; |
case AS_PF_DEFER: |
/* |
* The page fault came during copy_from_uspace() |
* or copy_to_uspace(). |
*/ |
page_table_unlock(as, lock); |
return; |
default: |
panic("Unexpected pfrc (%d)\n", pfrc); |
case AS_PF_FAULT: |
goto fail; |
break; |
case AS_PF_DEFER: |
/* |
* The page fault came during copy_from_uspace() |
* or copy_to_uspace(). |
*/ |
page_table_unlock(as, lock); |
return; |
default: |
panic("Unexpected pfrc (%d)\n", pfrc); |
} |
} |
316,8 → 328,8 |
/** Process Instruction/Data Storage Interrupt in Real Mode |
* |
* @param n Interrupt vector number. |
* @param istate Interrupted register context. |
* @param n Interrupt vector number. |
* @param istate Interrupted register context. |
* |
*/ |
bool pht_real_refill(int n, istate_t *istate) |
373,7 → 385,8 |
uint32_t i; |
for (i = 0; i < 8192; i++) { |
if ((phte[i].v) && (phte[i].vsid >= (asid << 4)) && (phte[i].vsid < ((asid << 4) + 16))) |
if ((phte[i].v) && (phte[i].vsid >= (asid << 4)) && |
(phte[i].vsid < ((asid << 4) + 16))) |
phte[i].v = 0; |
} |
tlb_invalidate_all(); |
407,7 → 420,11 |
} \ |
} else \ |
length = 0; \ |
printf(name ": page=%.*p frame=%.*p length=%d KB (mask=%#x)%s%s\n", sizeof(upper) * 2, upper & 0xffff0000, sizeof(lower) * 2, lower & 0xffff0000, length, mask, ((upper >> 1) & 1) ? " supervisor" : "", (upper & 1) ? " user" : ""); |
printf(name ": page=%.*p frame=%.*p length=%d KB (mask=%#x)%s%s\n", \ |
sizeof(upper) * 2, upper & 0xffff0000, sizeof(lower) * 2, \ |
lower & 0xffff0000, length, mask, \ |
((upper >> 1) & 1) ? " supervisor" : "", \ |
(upper & 1) ? " user" : ""); |
void tlb_print(void) |
421,7 → 438,10 |
: "=r" (vsid) |
: "r" (sr << 28) |
); |
printf("vsid[%d]: VSID=%.*p (ASID=%d)%s%s\n", sr, sizeof(vsid) * 2, vsid & 0xffffff, (vsid & 0xffffff) >> 4, ((vsid >> 30) & 1) ? " supervisor" : "", ((vsid >> 29) & 1) ? " user" : ""); |
printf("vsid[%d]: VSID=%.*p (ASID=%d)%s%s\n", sr, |
sizeof(vsid) * 2, vsid & 0xffffff, (vsid & 0xffffff) >> 4, |
((vsid >> 30) & 1) ? " supervisor" : "", |
((vsid >> 29) & 1) ? " user" : ""); |
} |
uint32_t upper; |
/branches/network/kernel/arch/ppc32/src/mm/page.c |
---|
47,13 → 47,16 |
uintptr_t hw_map(uintptr_t physaddr, size_t size) |
{ |
if (last_frame + ALIGN_UP(size, PAGE_SIZE) > KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH)) |
panic("Unable to map physical memory %p (%d bytes)", physaddr, size) |
if (last_frame + ALIGN_UP(size, PAGE_SIZE) > |
KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH)) |
panic("Unable to map physical memory %p (%" PRIs " bytes)", |
physaddr, size) |
uintptr_t virtaddr = PA2KA(last_frame); |
pfn_t i; |
for (i = 0; i < ADDR2PFN(ALIGN_UP(size, PAGE_SIZE)); i++) |
page_mapping_insert(AS_KERNEL, virtaddr + PFN2ADDR(i), physaddr + PFN2ADDR(i), PAGE_NOT_CACHEABLE | PAGE_WRITE); |
page_mapping_insert(AS_KERNEL, virtaddr + PFN2ADDR(i), |
physaddr + PFN2ADDR(i), PAGE_NOT_CACHEABLE | PAGE_WRITE); |
last_frame = ALIGN_UP(last_frame + size, FRAME_SIZE); |
/branches/network/kernel/arch/ppc32/src/interrupt.c |
---|
80,7 → 80,7 |
* Spurious interrupt. |
*/ |
#ifdef CONFIG_DEBUG |
printf("cpu%d: spurious interrupt (inum=%d)\n", CPU->id, inum); |
printf("cpu%u: spurious interrupt (inum=%d)\n", CPU->id, inum); |
#endif |
} |
/branches/network/kernel/arch/ppc32/src/context.S |
---|
26,7 → 26,6 |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
#include <arch/asm/regname.h> |
#include <arch/context_offset.h> |
.text |
34,56 → 33,8 |
.global context_save_arch |
.global context_restore_arch |
.macro CONTEXT_STORE r |
stw sp, OFFSET_SP(\r) |
stw r2, OFFSET_R2(\r) |
stw r13, OFFSET_R13(\r) |
stw r14, OFFSET_R14(\r) |
stw r15, OFFSET_R15(\r) |
stw r16, OFFSET_R16(\r) |
stw r17, OFFSET_R17(\r) |
stw r18, OFFSET_R18(\r) |
stw r19, OFFSET_R19(\r) |
stw r20, OFFSET_R20(\r) |
stw r21, OFFSET_R21(\r) |
stw r22, OFFSET_R22(\r) |
stw r23, OFFSET_R23(\r) |
stw r24, OFFSET_R24(\r) |
stw r25, OFFSET_R25(\r) |
stw r26, OFFSET_R26(\r) |
stw r27, OFFSET_R27(\r) |
stw r28, OFFSET_R28(\r) |
stw r29, OFFSET_R29(\r) |
stw r30, OFFSET_R30(\r) |
stw r31, OFFSET_R31(\r) |
.endm |
.macro CONTEXT_LOAD r |
lwz sp, OFFSET_SP(\r) |
lwz r2, OFFSET_R2(\r) |
lwz r13, OFFSET_R13(\r) |
lwz r14, OFFSET_R14(\r) |
lwz r15, OFFSET_R15(\r) |
lwz r16, OFFSET_R16(\r) |
lwz r17, OFFSET_R17(\r) |
lwz r18, OFFSET_R18(\r) |
lwz r19, OFFSET_R19(\r) |
lwz r20, OFFSET_R20(\r) |
lwz r21, OFFSET_R21(\r) |
lwz r22, OFFSET_R22(\r) |
lwz r23, OFFSET_R23(\r) |
lwz r24, OFFSET_R24(\r) |
lwz r25, OFFSET_R25(\r) |
lwz r26, OFFSET_R26(\r) |
lwz r27, OFFSET_R27(\r) |
lwz r28, OFFSET_R28(\r) |
lwz r29, OFFSET_R29(\r) |
lwz r30, OFFSET_R30(\r) |
lwz r31, OFFSET_R31(\r) |
.endm |
context_save_arch: |
CONTEXT_STORE r3 |
CONTEXT_SAVE_ARCH_CORE r3 |
mflr r4 |
stw r4, OFFSET_PC(r3) |
96,7 → 47,7 |
blr |
context_restore_arch: |
CONTEXT_LOAD r3 |
CONTEXT_RESTORE_ARCH_CORE r3 |
lwz r4, OFFSET_CR(r3) |
mtcr r4 |