Adoption of Travis' PPC code. Changed to our VM structures and slightly
different arch-specific CPU functions. Fixed some bugs. Not tested. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5069 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
78a4f584f5
commit
f8e89e479d
@ -7,16 +7,16 @@ KernelStaticLibrary libppc :
|
||||
<$(SOURCE_GRIST)>arch_dbg_console.c
|
||||
<$(SOURCE_GRIST)>arch_debug.c
|
||||
<$(SOURCE_GRIST)>arch_elf.c
|
||||
<$(SOURCE_GRIST)>arch_exceptions.S
|
||||
<$(SOURCE_GRIST)>arch_faults.c
|
||||
<$(SOURCE_GRIST)>arch_int.c
|
||||
<$(SOURCE_GRIST)>arch_mmu.cpp
|
||||
<$(SOURCE_GRIST)>arch_smp.c
|
||||
<$(SOURCE_GRIST)>arch_thread.c
|
||||
<$(SOURCE_GRIST)>arch_timer.c
|
||||
<$(SOURCE_GRIST)>arch_vm.c
|
||||
<$(SOURCE_GRIST)>arch_vm_translation_map.c
|
||||
<$(SOURCE_GRIST)>arch_vm.cpp
|
||||
<$(SOURCE_GRIST)>arch_vm_translation_map.cpp
|
||||
<$(SOURCE_GRIST)>arch_asm.S
|
||||
# <$(SOURCE_GRIST)>arch_interrupts.S
|
||||
:
|
||||
-fno-pic -Wno-unused
|
||||
;
|
||||
|
@ -1,22 +1,215 @@
|
||||
/*
|
||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||
** Copyright 2003, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
#define FUNC(name) .align 4 ; .globl ##name ; ##name:
|
||||
#define FUNCTION(x) .global x; .type x,@function; x
|
||||
|
||||
.text
|
||||
.globl reboot
|
||||
reboot:
|
||||
|
||||
.globl arch_int_restore_interrupts
|
||||
arch_int_restore_interrupts:
|
||||
// ToDo: fixme
|
||||
FUNCTION(reboot):
|
||||
b .
|
||||
|
||||
.globl arch_int_enable_interrupts
|
||||
arch_int_enable_interrupts:
|
||||
|
||||
.globl arch_int_disable_interrupts
|
||||
arch_int_disable_interrupts:
|
||||
/* void arch_int_enable_interrupts(void) */
|
||||
FUNCTION(arch_int_enable_interrupts):
|
||||
mfmsr %r3 // load msr
|
||||
|
||||
.global dbg_save_registers
|
||||
dbg_save_registers:
|
||||
/*
|
||||
li %r4, 1
|
||||
insrwi %r3, %r4, 1, 16 // set the EE bit
|
||||
*/
|
||||
|
||||
li %r4, 0
|
||||
ori %r4, %r4, (1 << 15) // create a mask for EE bit of MSR
|
||||
or %r3, %r3, %r4 // set the EE bit
|
||||
|
||||
mtmsr %r3 // put it back into the msr
|
||||
blr
|
||||
|
||||
/* void arch_int_disable_interrupts(void) */
|
||||
FUNCTION(arch_int_disable_interrupts):
|
||||
mfmsr %r3 // load msr
|
||||
|
||||
/*
|
||||
li %r4, 0
|
||||
rlwinm %r3, %r4, 15, 16, 16 // mask the EE bit
|
||||
*/
|
||||
|
||||
li %r4, 0
|
||||
ori %r4, %r4, (1 << 15) // create a mask for EE bit of MSR
|
||||
andc %r3, %r3, %r4 // mask the EE bit
|
||||
|
||||
mtmsr %r3 // put it back into the msr
|
||||
blr
|
||||
|
||||
/* bool arch_int_are_interrupts_enabled(void) */
|
||||
FUNCTION(arch_int_are_interrupts_enabled):
|
||||
mfmsr %r3 // load msr
|
||||
extrwi %r3, %r3, 1, 16 // mask out the EE bit
|
||||
blr
|
||||
|
||||
// ToDo: fixme
|
||||
FUNCTION(dbg_save_registers):
|
||||
blr
|
||||
|
||||
/* long long get_time_base(void) */
|
||||
FUNCTION(get_time_base):
|
||||
1:
|
||||
mftbu %r3 // get the upper time base register
|
||||
mftb %r4 // get the lower time base register
|
||||
mftbu %r5 // get the upper again
|
||||
cmpw %r5, %r3 // see if it changed while we were reading the lower
|
||||
bne- 1b // if so, repeat
|
||||
blr
|
||||
|
||||
/* void getibats(int bats[8]); */
|
||||
FUNCTION(getibats):
|
||||
mfibatu %r0,0
|
||||
stw %r0,0(%r3)
|
||||
mfibatl %r0,0
|
||||
stwu %r0,4(%r3)
|
||||
mfibatu %r0,1
|
||||
stwu %r0,4(%r3)
|
||||
mfibatl %r0,1
|
||||
stwu %r0,4(%r3)
|
||||
mfibatu %r0,2
|
||||
stwu %r0,4(%r3)
|
||||
mfibatl %r0,2
|
||||
stwu %r0,4(%r3)
|
||||
mfibatu %r0,3
|
||||
stwu %r0,4(%r3)
|
||||
mfibatl %r0,3
|
||||
stwu %r0,4(%r3)
|
||||
blr
|
||||
|
||||
// void setibats(int bats[8]);
|
||||
FUNCTION(setibats):
|
||||
lwz %r0,0(%r3)
|
||||
mtibatu 0,%r0
|
||||
isync
|
||||
lwzu %r0,4(%r3)
|
||||
mtibatl 0,%r0
|
||||
isync
|
||||
lwzu %r0,4(%r3)
|
||||
mtibatu 1,%r0
|
||||
isync
|
||||
lwzu %r0,4(%r3)
|
||||
mtibatl 1,%r0
|
||||
isync
|
||||
lwzu %r0,4(%r3)
|
||||
mtibatu 2,%r0
|
||||
isync
|
||||
lwzu %r0,4(%r3)
|
||||
mtibatl 2,%r0
|
||||
isync
|
||||
lwzu %r0,4(%r3)
|
||||
mtibatu 3,%r0
|
||||
isync
|
||||
lwzu %r0,4(%r3)
|
||||
mtibatl 3,%r0
|
||||
isync
|
||||
|
||||
blr
|
||||
|
||||
// void getdbats(int bats[8]);
|
||||
FUNCTION(getdbats):
|
||||
mfdbatu %r0,0
|
||||
stw %r0,0(%r3)
|
||||
mfdbatl %r0,0
|
||||
stwu %r0,4(%r3)
|
||||
mfdbatu %r0,1
|
||||
stwu %r0,4(%r3)
|
||||
mfdbatl %r0,1
|
||||
stwu %r0,4(%r3)
|
||||
mfdbatu %r0,2
|
||||
stwu %r0,4(%r3)
|
||||
mfdbatl %r0,2
|
||||
stwu %r0,4(%r3)
|
||||
mfdbatu %r0,3
|
||||
stwu %r0,4(%r3)
|
||||
mfdbatl %r0,3
|
||||
stwu %r0,4(%r3)
|
||||
blr
|
||||
|
||||
// void setdbats(int bats[8]);
|
||||
FUNCTION(setdbats):
|
||||
lwz %r0,0(%r3)
|
||||
mtdbatu 0,%r0
|
||||
lwzu %r0,4(%r3)
|
||||
mtdbatl 0,%r0
|
||||
lwzu %r0,4(%r3)
|
||||
mtdbatu 1,%r0
|
||||
lwzu %r0,4(%r3)
|
||||
mtdbatl 1,%r0
|
||||
lwzu %r0,4(%r3)
|
||||
mtdbatu 2,%r0
|
||||
lwzu %r0,4(%r3)
|
||||
mtdbatl 2,%r0
|
||||
lwzu %r0,4(%r3)
|
||||
mtdbatu 3,%r0
|
||||
lwzu %r0,4(%r3)
|
||||
mtdbatl 3,%r0
|
||||
sync
|
||||
|
||||
blr
|
||||
|
||||
// unsigned int gethid0();
|
||||
FUNCTION(gethid0):
|
||||
mfspr %r3, 1008
|
||||
blr
|
||||
|
||||
// void sethid0(unsigned int val);
|
||||
FUNCTION(sethid0):
|
||||
mtspr 1008, %r3
|
||||
blr
|
||||
|
||||
// unsigned int getl2cr();
|
||||
FUNCTION(getl2cr):
|
||||
mfspr %r3, 1017
|
||||
blr
|
||||
|
||||
// void setl2cr(unsigned int val);
|
||||
FUNCTION(setl2cr):
|
||||
mtspr 1017, %r3
|
||||
blr
|
||||
|
||||
// void ppc_context_switch(addr_t *old_sp, addr_t new_sp);
|
||||
FUNCTION(ppc_context_switch):
|
||||
|
||||
// regs to push on the stack: r13-r31, cr, r2, lr
|
||||
#define SAVE_FRAME_SIZE (((31 - 13 + 1) + 1 + 1 + 1) * 4)
|
||||
|
||||
// push the old regs we need to save on the stack
|
||||
addi %sp, %sp, -SAVE_FRAME_SIZE
|
||||
stmw %r13, 12(%sp)
|
||||
stw %r2, 8(%sp)
|
||||
mfcr %r0
|
||||
stw %r0, 4(%sp)
|
||||
mflr %r0
|
||||
stw %r0, 0(%sp)
|
||||
|
||||
// save the old stack pointer
|
||||
stw %sp, 0(%r3)
|
||||
|
||||
// restore the new stack pointer
|
||||
mr %sp, %r4
|
||||
|
||||
// restore the new regs
|
||||
lwz %r0, 0(%sp)
|
||||
mtlr %r0
|
||||
lwz %r0, 4(%sp)
|
||||
mtcr %r0
|
||||
lwz %r2, 8(%sp)
|
||||
lmw %r13, 12(%sp)
|
||||
addi %sp, %sp, SAVE_FRAME_SIZE
|
||||
|
||||
blr
|
||||
|
||||
// void arch_thread_switch_kstack_and_call(addr_t new_kstack, void (*func)(void *), void *arg)
|
||||
FUNCTION(arch_thread_switch_kstack_and_call):
|
||||
mr %sp, %r3 // set the new stack pointer
|
||||
mtctr %r4 // move the target function into CTR
|
||||
mr %r3, %r5 // move the arg to this func to the new arg
|
||||
bctr
|
||||
|
||||
|
@ -1,136 +1,186 @@
|
||||
/*
|
||||
** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
|
||||
|
||||
#include <kernel.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <malloc.h>
|
||||
#include <vm.h>
|
||||
#include <debug.h>
|
||||
#include <smp.h>
|
||||
#include <Errors.h>
|
||||
#include <kerrors.h>
|
||||
#include <tls.h>
|
||||
|
||||
#include <boot/stage2.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <boot/kernel_args.h>
|
||||
|
||||
|
||||
int
|
||||
int
|
||||
arch_cpu_preboot_init(kernel_args *ka)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
int
|
||||
arch_cpu_init(kernel_args *ka)
|
||||
{
|
||||
//setup_system_time(ka->arch_args.system_time_cv_factor);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
int
|
||||
arch_cpu_init2(kernel_args *ka)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define CACHELINE 32
|
||||
|
||||
void
|
||||
arch_cpu_invalidate_TLB_range(addr start, addr end)
|
||||
void
|
||||
arch_cpu_sync_icache(void *address, size_t len)
|
||||
{
|
||||
int num_pages = end/PAGE_SIZE - start/PAGE_SIZE;
|
||||
while (num_pages-- >= 0) {
|
||||
//invalidate_TLB(start);
|
||||
int l, off;
|
||||
char *p;
|
||||
|
||||
off = (unsigned int)address & (CACHELINE - 1);
|
||||
len += off;
|
||||
|
||||
l = len;
|
||||
p = (char *)address - off;
|
||||
do {
|
||||
asm volatile ("dcbst 0,%0" :: "r"(p));
|
||||
p += CACHELINE;
|
||||
} while((l -= CACHELINE) > 0);
|
||||
asm volatile ("sync");
|
||||
p = (char *)address - off;
|
||||
do {
|
||||
asm volatile ("icbi 0,%0" :: "r"(p));
|
||||
p += CACHELINE;
|
||||
} while((len -= CACHELINE) > 0);
|
||||
asm volatile ("sync");
|
||||
asm volatile ("isync");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
arch_cpu_invalidate_TLB_range(addr_t start, addr_t end)
|
||||
{
|
||||
asm volatile("sync");
|
||||
while(start < end) {
|
||||
asm volatile("tlbie %0" :: "r" (start));
|
||||
asm volatile("eieio");
|
||||
asm volatile("sync");
|
||||
start += PAGE_SIZE;
|
||||
}
|
||||
asm volatile("tlbsync");
|
||||
asm volatile("sync");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
arch_cpu_invalidate_TLB_list(addr pages[], int num_pages)
|
||||
void
|
||||
arch_cpu_invalidate_TLB_list(addr_t pages[], int num_pages)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < num_pages; i++) {
|
||||
//invalidate_TLB(pages[i]);
|
||||
|
||||
asm volatile("sync");
|
||||
for(i = 0; i < num_pages; i++) {
|
||||
asm volatile("tlbie %0" :: "r" (pages[i]));
|
||||
asm volatile("eieio");
|
||||
asm volatile("sync");
|
||||
}
|
||||
asm volatile("tlbsync");
|
||||
asm volatile("sync");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
void
|
||||
arch_cpu_global_TLB_invalidate(void)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
asm volatile("sync");
|
||||
for(i=0; i< 0x40000; i += 0x1000) {
|
||||
asm volatile("tlbie %0" :: "r" (i));
|
||||
asm volatile("eieio");
|
||||
asm volatile("sync");
|
||||
}
|
||||
asm volatile("tlbsync");
|
||||
asm volatile("sync");
|
||||
}
|
||||
|
||||
|
||||
// ToDo: doesn't belong here!
|
||||
#include <OS.h>
|
||||
|
||||
long long
|
||||
system_time(void)
|
||||
{
|
||||
bigtime_t time_base = get_time_base();
|
||||
|
||||
return (time_base * 1000000) / ((66*1000*1000) / 4);
|
||||
// ToDo: remove hard coded
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr *faultHandler)
|
||||
arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr *fault_handler)
|
||||
{
|
||||
char *tmp = (char *)to;
|
||||
char *s = (char *)from;
|
||||
|
||||
*faultHandler = (addr)&&error;
|
||||
*fault_handler = (addr)&&error;
|
||||
|
||||
while (size--)
|
||||
*tmp++ = *s++;
|
||||
|
||||
*faultHandler = 0;
|
||||
*fault_handler = 0;
|
||||
return 0;
|
||||
|
||||
error:
|
||||
*faultHandler = 0;
|
||||
*fault_handler = 0;
|
||||
return B_BAD_ADDRESS;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
arch_cpu_user_strcpy(char *to, const char *from, addr *faultHandler)
|
||||
arch_cpu_user_strcpy(char *to, const char *from, addr *fault_handler)
|
||||
{
|
||||
*faultHandler = (addr)&&error;
|
||||
*fault_handler = (addr)&&error;
|
||||
|
||||
while ((*to++ = *from++) != '\0')
|
||||
;
|
||||
|
||||
*faultHandler = 0;
|
||||
*fault_handler = 0;
|
||||
return 0;
|
||||
|
||||
error:
|
||||
*faultHandler = 0;
|
||||
*fault_handler = 0;
|
||||
return B_BAD_ADDRESS;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
arch_cpu_user_strncpy(char *to, const char *from, size_t size, addr *faultHandler)
|
||||
arch_cpu_user_strncpy(char *to, const char *from, size_t size, addr *fault_handler)
|
||||
{
|
||||
*faultHandler = (addr)&&error;
|
||||
*fault_handler = (addr)&&error;
|
||||
|
||||
while(size-- && (*to++ = *from++) != '\0')
|
||||
;
|
||||
|
||||
*faultHandler = 0;
|
||||
*fault_handler = 0;
|
||||
return 0;
|
||||
|
||||
error:
|
||||
*faultHandler = 0;
|
||||
*fault_handler = 0;
|
||||
return B_BAD_ADDRESS;
|
||||
}
|
||||
|
||||
/*! \brief Copies at most (\a size - 1) characters from the string in \a from to
|
||||
the string in \a to, NULL-terminating the result.
|
||||
|
||||
\param to Pointer to the destination C-string.
|
||||
\param from Pointer to the source C-string.
|
||||
\param size Size in bytes of the string buffer pointed to by \a to.
|
||||
|
||||
\return strlen(\a from).
|
||||
*/
|
||||
/** \brief Copies at most (\a size - 1) characters from the string in \a from to
|
||||
* the string in \a to, NULL-terminating the result.
|
||||
*
|
||||
* \param to Pointer to the destination C-string.
|
||||
* \param from Pointer to the source C-string.
|
||||
* \param size Size in bytes of the string buffer pointed to by \a to.
|
||||
*
|
||||
* \return strlen(\a from).
|
||||
*/
|
||||
|
||||
int
|
||||
arch_cpu_user_strlcpy(char *to, const char *from, size_t size, addr *faultHandler)
|
||||
{
|
||||
@ -158,21 +208,22 @@ error:
|
||||
return B_BAD_ADDRESS;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
arch_cpu_user_memset(void *s, char c, size_t count, addr *faultHandler)
|
||||
arch_cpu_user_memset(void *s, char c, size_t count, addr *fault_handler)
|
||||
{
|
||||
char *xs = (char *)s;
|
||||
|
||||
*faultHandler = (addr)&&error;
|
||||
*fault_handler = (addr)&&error;
|
||||
|
||||
while (count--)
|
||||
*xs++ = c;
|
||||
|
||||
*faultHandler = 0;
|
||||
*fault_handler = 0;
|
||||
return 0;
|
||||
|
||||
error:
|
||||
*faultHandler = 0;
|
||||
*fault_handler = 0;
|
||||
return B_BAD_ADDRESS;
|
||||
}
|
||||
|
||||
@ -180,14 +231,6 @@ error:
|
||||
void
|
||||
arch_cpu_idle(void)
|
||||
{
|
||||
switch (smp_get_num_cpus()) {
|
||||
case 0:
|
||||
panic("You need at least 1 CPU to run OpenBeOS\n");
|
||||
case 1:
|
||||
//hlt();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,44 +1,286 @@
|
||||
/*
|
||||
/*
|
||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
|
||||
|
||||
#include <kernel.h>
|
||||
#include <boot/stage2.h>
|
||||
|
||||
#include <vm.h>
|
||||
#include <boot/kernel_args.h>
|
||||
#include <arch/dbg_console.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
int
|
||||
|
||||
#define FRAMEBUFFER_DBG_CONSOLE 1
|
||||
|
||||
#if FRAMEBUFFER_DBG_CONSOLE
|
||||
unsigned char FONT[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
||||
0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, /* '!' */
|
||||
0x00, 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* '"' */
|
||||
0x00, 0x00, 0x14, 0x14, 0x3e, 0x14, 0x3e, 0x14, 0x14, 0x00, 0x00, 0x00, /* '#' */
|
||||
0x00, 0x00, 0x08, 0x3c, 0x0a, 0x1c, 0x28, 0x1e, 0x08, 0x00, 0x00, 0x00, /* '$' */
|
||||
0x00, 0x00, 0x06, 0x26, 0x10, 0x08, 0x04, 0x32, 0x30, 0x00, 0x00, 0x00, /* '%' */
|
||||
0x00, 0x00, 0x1c, 0x02, 0x02, 0x04, 0x2a, 0x12, 0x2c, 0x00, 0x00, 0x00, /* '&' */
|
||||
0x00, 0x18, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ''' */
|
||||
0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x00, /* '(' */
|
||||
0x02, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x02, 0x00, /* ')' */
|
||||
0x00, 0x00, 0x00, 0x08, 0x2a, 0x1c, 0x2a, 0x08, 0x00, 0x00, 0x00, 0x00, /* '*' */
|
||||
0x00, 0x00, 0x00, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* '+' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x08, 0x04, 0x00, /* ',' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* '-' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, /* '.' */
|
||||
0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, /* '/' */
|
||||
0x00, 0x1c, 0x22, 0x32, 0x2a, 0x26, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /* '0' */
|
||||
0x00, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, /* '1' */
|
||||
0x00, 0x1c, 0x22, 0x20, 0x10, 0x08, 0x04, 0x02, 0x3e, 0x00, 0x00, 0x00, /* '2' */
|
||||
0x00, 0x1c, 0x22, 0x20, 0x18, 0x20, 0x20, 0x22, 0x1c, 0x00, 0x00, 0x00, /* '3' */
|
||||
0x00, 0x10, 0x18, 0x18, 0x14, 0x14, 0x3e, 0x10, 0x38, 0x00, 0x00, 0x00, /* '4' */
|
||||
0x00, 0x3e, 0x02, 0x02, 0x1e, 0x20, 0x20, 0x22, 0x1c, 0x00, 0x00, 0x00, /* '5' */
|
||||
0x00, 0x18, 0x04, 0x02, 0x1e, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /* '6' */
|
||||
0x00, 0x3e, 0x22, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x00, 0x00, 0x00, /* '7' */
|
||||
0x00, 0x1c, 0x22, 0x22, 0x1c, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /* '8' */
|
||||
0x00, 0x1c, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x10, 0x0c, 0x00, 0x00, 0x00, /* '9' */
|
||||
0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, /* ':' */
|
||||
0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x08, 0x04, 0x00, /* ';' */
|
||||
0x00, 0x00, 0x00, 0x30, 0x0c, 0x03, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, /* '<' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, /* '=' */
|
||||
0x00, 0x00, 0x00, 0x03, 0x0c, 0x30, 0x0c, 0x03, 0x00, 0x00, 0x00, 0x00, /* '>' */
|
||||
0x00, 0x1c, 0x22, 0x20, 0x10, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, /* '?' */
|
||||
0x00, 0x00, 0x1c, 0x22, 0x3a, 0x3a, 0x1a, 0x02, 0x1c, 0x00, 0x00, 0x00, /* '@' */
|
||||
0x00, 0x00, 0x08, 0x14, 0x22, 0x22, 0x3e, 0x22, 0x22, 0x00, 0x00, 0x00, /* 'A' */
|
||||
0x00, 0x00, 0x1e, 0x22, 0x22, 0x1e, 0x22, 0x22, 0x1e, 0x00, 0x00, 0x00, /* 'B' */
|
||||
0x00, 0x00, 0x1c, 0x22, 0x02, 0x02, 0x02, 0x22, 0x1c, 0x00, 0x00, 0x00, /* 'C' */
|
||||
0x00, 0x00, 0x0e, 0x12, 0x22, 0x22, 0x22, 0x12, 0x0e, 0x00, 0x00, 0x00, /* 'D' */
|
||||
0x00, 0x00, 0x3e, 0x02, 0x02, 0x1e, 0x02, 0x02, 0x3e, 0x00, 0x00, 0x00, /* 'E' */
|
||||
0x00, 0x00, 0x3e, 0x02, 0x02, 0x1e, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, /* 'F' */
|
||||
0x00, 0x00, 0x1c, 0x22, 0x02, 0x32, 0x22, 0x22, 0x3c, 0x00, 0x00, 0x00, /* 'G' */
|
||||
0x00, 0x00, 0x22, 0x22, 0x22, 0x3e, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, /* 'H' */
|
||||
0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, /* 'I' */
|
||||
0x00, 0x00, 0x38, 0x20, 0x20, 0x20, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /* 'J' */
|
||||
0x00, 0x00, 0x22, 0x12, 0x0a, 0x06, 0x0a, 0x12, 0x22, 0x00, 0x00, 0x00, /* 'K' */
|
||||
0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x3e, 0x00, 0x00, 0x00, /* 'L' */
|
||||
0x00, 0x00, 0x22, 0x36, 0x2a, 0x2a, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, /* 'M' */
|
||||
0x00, 0x00, 0x22, 0x26, 0x26, 0x2a, 0x32, 0x32, 0x22, 0x00, 0x00, 0x00, /* 'N' */
|
||||
0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /* 'O' */
|
||||
0x00, 0x00, 0x1e, 0x22, 0x22, 0x1e, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, /* 'P' */
|
||||
0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c, 0x30, 0x00, 0x00, /* 'Q' */
|
||||
0x00, 0x00, 0x1e, 0x22, 0x22, 0x1e, 0x0a, 0x12, 0x22, 0x00, 0x00, 0x00, /* 'R' */
|
||||
0x00, 0x00, 0x1c, 0x22, 0x02, 0x1c, 0x20, 0x22, 0x1c, 0x00, 0x00, 0x00, /* 'S' */
|
||||
0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, /* 'T' */
|
||||
0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /* 'U' */
|
||||
0x00, 0x00, 0x22, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08, 0x00, 0x00, 0x00, /* 'V' */
|
||||
0x00, 0x00, 0x22, 0x22, 0x22, 0x2a, 0x2a, 0x36, 0x22, 0x00, 0x00, 0x00, /* 'W' */
|
||||
0x00, 0x00, 0x22, 0x22, 0x14, 0x08, 0x14, 0x22, 0x22, 0x00, 0x00, 0x00, /* 'X' */
|
||||
0x00, 0x00, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, /* 'Y' */
|
||||
0x00, 0x00, 0x3e, 0x20, 0x10, 0x08, 0x04, 0x02, 0x3e, 0x00, 0x00, 0x00, /* 'Z' */
|
||||
0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, /* '[' */
|
||||
0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x00, 0x00, /* '\' */
|
||||
0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0e, 0x00, /* ']' */
|
||||
0x00, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* '^' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, /* '_' */
|
||||
0x00, 0x0c, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* '`' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x3c, 0x22, 0x22, 0x32, 0x2c, 0x00, 0x00, 0x00, /* 'a' */
|
||||
0x00, 0x02, 0x02, 0x02, 0x1e, 0x22, 0x22, 0x22, 0x1e, 0x00, 0x00, 0x00, /* 'b' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x3c, 0x02, 0x02, 0x02, 0x3c, 0x00, 0x00, 0x00, /* 'c' */
|
||||
0x00, 0x20, 0x20, 0x20, 0x3c, 0x22, 0x22, 0x22, 0x3c, 0x00, 0x00, 0x00, /* 'd' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x3e, 0x02, 0x1c, 0x00, 0x00, 0x00, /* 'e' */
|
||||
0x00, 0x38, 0x04, 0x04, 0x1e, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, /* 'f' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x3c, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x20, 0x1c, /* 'g' */
|
||||
0x00, 0x02, 0x02, 0x02, 0x1e, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, /* 'h' */
|
||||
0x00, 0x08, 0x08, 0x00, 0x0c, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, /* 'i' */
|
||||
0x00, 0x10, 0x10, 0x00, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0e, /* 'j' */
|
||||
0x00, 0x02, 0x02, 0x02, 0x12, 0x0a, 0x06, 0x0a, 0x12, 0x00, 0x00, 0x00, /* 'k' */
|
||||
0x00, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, /* 'l' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x16, 0x2a, 0x2a, 0x2a, 0x22, 0x00, 0x00, 0x00, /* 'm' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x1a, 0x26, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, /* 'n' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /* 'o' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x1e, 0x22, 0x22, 0x22, 0x1e, 0x02, 0x02, 0x02, /* 'p' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x3c, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x20, 0x20, /* 'q' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x1a, 0x06, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, /* 'r' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x3c, 0x02, 0x1c, 0x20, 0x1e, 0x00, 0x00, 0x00, /* 's' */
|
||||
0x00, 0x08, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x08, 0x30, 0x00, 0x00, 0x00, /* 't' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x32, 0x2c, 0x00, 0x00, 0x00, /* 'u' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x36, 0x14, 0x14, 0x08, 0x08, 0x00, 0x00, 0x00, /* 'v' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x22, 0x2a, 0x2a, 0x2a, 0x14, 0x00, 0x00, 0x00, /* 'w' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x22, 0x14, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, /* 'x' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x20, 0x1c, /* 'y' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x3e, 0x10, 0x08, 0x04, 0x3e, 0x00, 0x00, 0x00, /* 'z' */
|
||||
0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x10, 0x10, 0x10, 0x10, 0x20, 0x00, /* '{' */
|
||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, /* '|' */
|
||||
0x02, 0x04, 0x04, 0x04, 0x04, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x00, /* '}' */
|
||||
0x00, 0x04, 0x2a, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* '~' */
|
||||
0x00, 0x00, 0x00, 0x08, 0x08, 0x14, 0x14, 0x22, 0x3e, 0x00, 0x00, 0x00, /* '' */
|
||||
};
|
||||
|
||||
static unsigned char *framebuffer;
|
||||
static unsigned int draw_color;
|
||||
static unsigned int back_color;
|
||||
static int char_x,char_y;
|
||||
static int screen_size_x, screen_size_y;
|
||||
static int screen_depth;
|
||||
static int num_cols, num_rows;
|
||||
|
||||
#define CHAR_WIDTH 6
|
||||
#define CHAR_HEIGHT 12
|
||||
|
||||
|
||||
static void
|
||||
draw_char(unsigned char c, int x, int y)
|
||||
{
|
||||
int i,j;
|
||||
unsigned char *base = &framebuffer[y*screen_size_x + x];
|
||||
unsigned char line;
|
||||
|
||||
for(i=0; i<CHAR_HEIGHT; i++) {
|
||||
line = FONT[c*CHAR_HEIGHT + i];
|
||||
for(j=0; j<CHAR_WIDTH; j++) {
|
||||
base[j] = (line & 0x1) ? draw_color : back_color;
|
||||
line = line >> 1;
|
||||
}
|
||||
base += screen_size_x;
|
||||
}
|
||||
}
|
||||
|
||||
#define SCROLL 0
|
||||
|
||||
|
||||
static void
|
||||
arch_dbg_putchar(char c)
|
||||
{
|
||||
if(c == '\n') {
|
||||
char_x = 0;
|
||||
char_y++;
|
||||
#if !SCROLL
|
||||
memset(framebuffer + ((char_y < num_rows) ? char_y : 0) * CHAR_HEIGHT * screen_size_x, back_color, screen_size_x*CHAR_HEIGHT);
|
||||
#endif
|
||||
} else {
|
||||
draw_char(c, char_x * CHAR_WIDTH, char_y * CHAR_HEIGHT);
|
||||
char_x++;
|
||||
}
|
||||
if(char_x >= num_cols) {
|
||||
char_x = 0;
|
||||
char_y++;
|
||||
}
|
||||
if(char_y >= num_rows) {
|
||||
#if SCROLL
|
||||
// scroll up
|
||||
memcpy(framebuffer, framebuffer + screen_size_x*CHAR_HEIGHT, screen_size_x * screen_size_y - screen_size_x*CHAR_HEIGHT);
|
||||
memset(framebuffer + (screen_size_y-CHAR_HEIGHT)*screen_size_x, back_color, screen_size_x*CHAR_HEIGHT);
|
||||
char_y--;
|
||||
#else
|
||||
// wrap around
|
||||
char_y = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
arch_dbg_con_init(kernel_args *ka)
|
||||
{
|
||||
#if FRAMEBUFFER_DBG_CONSOLE
|
||||
framebuffer = (unsigned char *)ka->fb.mapping.start;
|
||||
screen_size_x = ka->fb.x_size;
|
||||
screen_size_y = ka->fb.y_size;
|
||||
|
||||
back_color = 0x0;
|
||||
draw_color = 0xff;
|
||||
char_x = 0;
|
||||
char_y = ka->cons_line;
|
||||
screen_depth = ka->fb.bit_depth;
|
||||
|
||||
num_cols = screen_size_x / CHAR_WIDTH;
|
||||
num_rows = screen_size_y / CHAR_HEIGHT;
|
||||
|
||||
#endif
|
||||
|
||||
return B_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
arch_dbg_con_init2(kernel_args *ka)
|
||||
{
|
||||
#if 0
|
||||
#if FRAMEBUFFER_DBG_CONSOLE
|
||||
region_id fb_region;
|
||||
void *new_framebuffer;
|
||||
|
||||
/* remap the framebuffer into kernel space and remove the BAT entry mapping it currently */
|
||||
fb_region = vm_map_physical_memory(vm_get_kernel_aspace_id(), "framebuffer", &new_framebuffer,
|
||||
REGION_ADDR_ANY_ADDRESS, ka->fb.phys_addr.size, LOCK_RW|LOCK_KERNEL, ka->fb.phys_addr.start);
|
||||
if(fb_region < 0)
|
||||
panic("arch_dbg_con_init2: unable to remap framebuffer into kernel space\n");
|
||||
dprintf("framebuffer now at %p, phys addr 0x%x\n", new_framebuffer, ka->fb.phys_addr.start);
|
||||
|
||||
dprintf("compare %d\n", memcmp(framebuffer, new_framebuffer, ka->fb.phys_addr.size));
|
||||
|
||||
#endif
|
||||
#endif
|
||||
return B_NO_ERROR;
|
||||
}
|
||||
|
||||
char arch_dbg_con_read()
|
||||
{
|
||||
for(;;);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
char
|
||||
arch_dbg_con_read()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_arch_dbg_con_putch(const char c)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
char
|
||||
arch_dbg_con_putch(const char c)
|
||||
char arch_dbg_con_putch(const char c)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
arch_dbg_con_puts(const char *s)
|
||||
void arch_dbg_con_puts(const char *str)
|
||||
{
|
||||
while(*str) {
|
||||
arch_dbg_putchar(*str);
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t arch_dbg_con_write(const void *buf, ssize_t len)
|
||||
{
|
||||
ssize_t i;
|
||||
|
||||
for(i = 0; i < len; i++)
|
||||
arch_dbg_putchar(((char *)buf)[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include <arch/debug.h>
|
||||
|
||||
|
||||
// ToDo: will put stack trace and disassembly routines here
|
||||
// ToDo: put stack trace and disassembly routines here
|
||||
|
||||
|
||||
void
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
** Copyright 2002, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
|
||||
|
||||
@ -9,28 +9,97 @@
|
||||
#include <elf_priv.h>
|
||||
#include <arch/elf.h>
|
||||
|
||||
#define ELF_TRACE 0
|
||||
#if ELF_TRACE
|
||||
# define TRACE(x) dprintf x
|
||||
#else
|
||||
# define TRACE(x) ;
|
||||
#endif
|
||||
|
||||
#define CHATTY 0
|
||||
|
||||
|
||||
int
|
||||
int
|
||||
arch_elf_relocate_rel(struct elf_image_info *image, const char *sym_prepend,
|
||||
struct elf_image_info *resolve_image, struct Elf32_Rel *rel, int rel_len)
|
||||
{
|
||||
dprintf("arch_elf_relocate_rel: not supported on PPC\n");
|
||||
return B_ERROR;
|
||||
// there are no rel entries in PPC elf
|
||||
return B_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
int
|
||||
arch_elf_relocate_rela(struct elf_image_info *image, const char *sym_prepend,
|
||||
struct elf_image_info *resolve_image, struct Elf32_Rela *rel, int rel_len)
|
||||
{
|
||||
dprintf("arch_elf_relocate_rela: not supported on PPC\n");
|
||||
return B_ERROR;
|
||||
int i;
|
||||
struct Elf32_Sym *sym;
|
||||
int vlErr;
|
||||
addr_t S = 0;
|
||||
addr_t final_val;
|
||||
|
||||
#define P ((addr_t)(image->regions[0].delta + rel[i].r_offset))
|
||||
#define A ((addr_t)rel[i].r_addend)
|
||||
#define B (image->regions[0].delta)
|
||||
|
||||
for (i = 0; i * (int)sizeof(struct Elf32_Rela) < rel_len; i++) {
|
||||
#if CHATTY
|
||||
dprintf("looking at rel type %d, offset 0x%x, sym 0x%x, addend 0x%x\n",
|
||||
ELF32_R_TYPE(rel[i].r_info), rel[i].r_offset, ELF32_R_SYM(rel[i].r_info), rel[i].r_addend);
|
||||
#endif
|
||||
switch (ELF32_R_TYPE(rel[i].r_info)) {
|
||||
case R_PPC_ADDR32:
|
||||
case R_PPC_ADDR24:
|
||||
case R_PPC_ADDR16:
|
||||
case R_PPC_ADDR16_LO:
|
||||
case R_PPC_ADDR16_HI:
|
||||
case R_PPC_ADDR16_HA:
|
||||
case R_PPC_REL24:
|
||||
sym = SYMBOL(image, ELF32_R_SYM(rel[i].r_info));
|
||||
|
||||
vlErr = elf_resolve_symbol(image, sym, resolve_image, sym_prepend, &S);
|
||||
if (vlErr<0)
|
||||
return vlErr;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (ELF32_R_TYPE(rel[i].r_info)) {
|
||||
case R_PPC_NONE:
|
||||
continue;
|
||||
|
||||
case R_PPC_ADDR32:
|
||||
final_val = S + A;
|
||||
break;
|
||||
|
||||
case R_PPC_ADDR16:
|
||||
*(Elf32_Half*)P = S;
|
||||
continue;
|
||||
|
||||
case R_PPC_ADDR16_LO:
|
||||
*(Elf32_Half*)P = S & 0xffff;
|
||||
continue;
|
||||
|
||||
case R_PPC_ADDR16_HI:
|
||||
*(Elf32_Half*)P = (S >> 16) & 0xffff;
|
||||
continue;
|
||||
|
||||
case R_PPC_ADDR16_HA:
|
||||
*(Elf32_Half*)P = ((S >> 16) + ((S & 0x8000) ? 1 : 0)) & 0xFFFF;
|
||||
continue;
|
||||
|
||||
case R_PPC_REL24:
|
||||
final_val = (*(Elf32_Word *)P & 0xff000003) | ((S + A - P) & 0x3fffffc);
|
||||
break;
|
||||
|
||||
case R_PPC_RELATIVE:
|
||||
final_val = B + A;
|
||||
break;
|
||||
|
||||
default:
|
||||
dprintf("arch_elf_relocate_rela: unhandled relocation type %d\n", ELF32_R_TYPE(rel[i].r_info));
|
||||
return B_ERROR;
|
||||
}
|
||||
#if CHATTY
|
||||
dprintf("going to put 0x%x at 0x%x\n", final_val, P);
|
||||
#endif
|
||||
*(addr_t *)P = final_val;
|
||||
}
|
||||
|
||||
return B_NO_ERROR;
|
||||
|
||||
}
|
||||
|
||||
|
387
src/kernel/core/arch/ppc/arch_exceptions.S
Normal file
387
src/kernel/core/arch/ppc/arch_exceptions.S
Normal file
@ -0,0 +1,387 @@
|
||||
/*
|
||||
** Copyright 2003, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
#define FUNCTION(x) .global x; .type x,@function; x
|
||||
#define LOCAL_FUNCTION(x) .type x,@function; x
|
||||
|
||||
/*
|
||||
** General exception handling pseudocode:
|
||||
** save %r0 into sprg0
|
||||
** save %r2 into sprg1
|
||||
** save %r1 into sprg2
|
||||
** save cr into %r2 (will mess up cr in the conditional check below)
|
||||
** load saved msr into %r0
|
||||
** see if was in kernel mode
|
||||
** if not,
|
||||
** load kernel stack from EAR into %r1
|
||||
** restore cr from %r2
|
||||
** set up in BAT 0 (instruction and data) a identity mapping of 0x0
|
||||
** load old msr
|
||||
** merge old msr mmu bits with current msr
|
||||
** load new msr (should turn the mmu on)
|
||||
** save lr into sprg3
|
||||
** set up and branch to the next instruction (moving the program counter into kernel space)
|
||||
** remove the BAT mapping
|
||||
** set up stack frame and push everything
|
||||
*/
|
||||
|
||||
#define VEC_ENTRY() \
|
||||
mtsprg0 %r0 ; /* save %r0 */ \
|
||||
mtsprg1 %r2 ; /* save %r2 */ \
|
||||
mtsprg2 %r1 ; /* save the old stack */ \
|
||||
mfcr %r2 ; /* save cr */ \
|
||||
\
|
||||
mfsrr1 %r0 ; /* load saved msr */ \
|
||||
andi. %r0, %r0, (1 << 14) ; /* see if it was in kernel mode */ \
|
||||
beq- 0f ; /* yep */ \
|
||||
\
|
||||
/* load the kernel stack */ \
|
||||
mfear %r1 ; /* load the kernel stack pointer from the EAR reg */ \
|
||||
0: \
|
||||
mtcrf 0xff, %r2 ; /* restore the CR, it was messed up in the previous compare */ \
|
||||
\
|
||||
/* we are going to turn on the mmu, lets have a BAT entry in place to keep us identity mapped */ \
|
||||
li %r0, 0x2 ; /* BATU_VS */ \
|
||||
mtibatu 0, %r0 ; /* load the upper word of the instruction BAT */ \
|
||||
mtdbatu 0, %r0 ; /* load the upper word of the data BAT */ \
|
||||
li %r0, 0x10|0x2 ; /* BATL_MC | BATL_PP_RW */ \
|
||||
mtibatl 0, %r0 ; /* load the lower word of the instruction BAT */ \
|
||||
mtdbatl 0, %r0 ; /* load the lower word of the data BAT */ \
|
||||
isync ; \
|
||||
sync ; \
|
||||
\
|
||||
/* turn the mmu back on */ \
|
||||
mfsrr1 %r0 ; /* load saved msr */ \
|
||||
rlwinm %r0, %r0, 28, 30, 31 ; /* extract mmu bits */ \
|
||||
mfmsr %r2 ; /* load the current msr */ \
|
||||
rlwimi %r2, %r0, 4, 26, 27 ; /* merge the mmu bits with the current msr */ \
|
||||
mtmsr %r2 ; /* load the new msr (turning the mmu back on */ \
|
||||
isync ; \
|
||||
\
|
||||
mflr %r0 ; /* load the lr */ \
|
||||
mtsprg 3, %r0 ; /* save it */ \
|
||||
lis %r0, 1f@h ; /* load the address of a label in a few instructions */ \
|
||||
ori %r0, %r0, 1f@l ; /* we will jump to it to get the program counter into the kernel region */ \
|
||||
mtlr %r0 ; /* get ready to jump to this label */ \
|
||||
blr ; /* branch to the next instruction (with the mmu on) */ \
|
||||
1: \
|
||||
/* turn the BAT back off */ \
|
||||
li %r2, 0 ; \
|
||||
mtibatu 0, %r2 ; \
|
||||
mtdbatu 0, %r2 ; \
|
||||
mtibatl 0, %r2 ; \
|
||||
mtdbatl 0, %r2 ; \
|
||||
isync ; \
|
||||
sync ; \
|
||||
\
|
||||
bl __save_regs ; /* dump an iframe on the stack */
|
||||
|
||||
.global __irqvec_start
|
||||
__irqvec_start:
|
||||
.long 0
|
||||
|
||||
/* called by the tail end of the VEC_ENTRY macro
|
||||
** register expectations:
|
||||
** %r1 - stack
|
||||
** sprg0 - old %r0
|
||||
** sprg1 - old %r2
|
||||
** sprg2 - old stack (%r1)
|
||||
** sprg3 - old lr
|
||||
** all other regs should have been unmodified by the exception handler,
|
||||
** and ready to be saved
|
||||
*/
|
||||
FUNCTION(__save_regs):
|
||||
mfsprg %r0, 0
|
||||
stwu %r0, -4(%r1) /* push %r0 */
|
||||
mfsprg %r0, 2
|
||||
stwu %r0, -4(%r1) /* push old %r1 (stack) */
|
||||
mfsprg %r0, 1
|
||||
stwu %r0, -4(%r1) /* push %r2 */
|
||||
stwu %r3, -4(%r1) /* push %r3-%r31 */
|
||||
stwu %r4, -4(%r1) /* push %r3-%r31 */
|
||||
stwu %r5, -4(%r1) /* push %r3-%r31 */
|
||||
stwu %r6, -4(%r1) /* push %r3-%r31 */
|
||||
stwu %r7, -4(%r1) /* push %r3-%r31 */
|
||||
stwu %r8, -4(%r1) /* push %r3-%r31 */
|
||||
stwu %r9, -4(%r1) /* push %r3-%r31 */
|
||||
stwu %r10, -4(%r1) /* push %r3-%r31 */
|
||||
stwu %r11, -4(%r1) /* push %r3-%r31 */
|
||||
stwu %r12, -4(%r1) /* push %r3-%r31 */
|
||||
|
||||
/* strictly speaking, we dont need to save %r13-%r31, but I will for now */
|
||||
stwu %r13, -4(%r1) /* push %r3-%r31 */
|
||||
stwu %r14, -4(%r1) /* push %r3-%r31 */
|
||||
stwu %r15, -4(%r1) /* push %r3-%r31 */
|
||||
stwu %r16, -4(%r1) /* push %r3-%r31 */
|
||||
stwu %r17, -4(%r1) /* push %r3-%r31 */
|
||||
stwu %r18, -4(%r1) /* push %r3-%r31 */
|
||||
stwu %r19, -4(%r1) /* push %r3-%r31 */
|
||||
stwu %r20, -4(%r1) /* push %r3-%r31 */
|
||||
stwu %r21, -4(%r1) /* push %r3-%r31 */
|
||||
stwu %r22, -4(%r1) /* push %r3-%r31 */
|
||||
stwu %r23, -4(%r1) /* push %r3-%r31 */
|
||||
stwu %r24, -4(%r1) /* push %r3-%r31 */
|
||||
stwu %r25, -4(%r1) /* push %r3-%r31 */
|
||||
stwu %r26, -4(%r1) /* push %r3-%r31 */
|
||||
stwu %r27, -4(%r1) /* push %r3-%r31 */
|
||||
stwu %r28, -4(%r1) /* push %r3-%r31 */
|
||||
stwu %r29, -4(%r1) /* push %r3-%r31 */
|
||||
stwu %r30, -4(%r1) /* push %r3-%r31 */
|
||||
stwu %r31, -4(%r1) /* push %r3-%r31 */
|
||||
|
||||
/* save some of the other regs */
|
||||
mfctr %r0
|
||||
stwu %r0, -4(%r1) /* push CTR */
|
||||
mfxer %r0
|
||||
stwu %r0, -4(%r1) /* push XER */
|
||||
mfcr %r0
|
||||
stwu %r0, -4(%r1) /* push CR */
|
||||
mfsprg %r0, 3
|
||||
stwu %r0, -4(%r1) /* push LR */
|
||||
mfspr %r0, %dsisr
|
||||
stwu %r0, -4(%r1) /* push DSISR */
|
||||
mfspr %r0, %dar
|
||||
stwu %r0, -4(%r1) /* push DAR */
|
||||
mfspr %r0, %srr1
|
||||
stwu %r0, -4(%r1) /* push SRR1 */
|
||||
mfspr %r0, %srr0
|
||||
stwu %r0, -4(%r1) /* push SRR0 */
|
||||
|
||||
addi %r1, %r1, -8 /* adjust the stack pointer to leave some padding on it for C */
|
||||
|
||||
/* get outta here */
|
||||
blr
|
||||
|
||||
/* not enough space for __restore_regs_and_rfi here, see below */
|
||||
|
||||
.skip 0x100 - (. - __irqvec_start)
|
||||
FUNCTION(system_reset_exception):
|
||||
VEC_ENTRY();
|
||||
li %r3, 0x100
|
||||
addi %r4, %r1, 8
|
||||
bl ppc_exception_entry
|
||||
bl __restore_regs_and_rfi
|
||||
|
||||
.skip 0x200 - (. - __irqvec_start)
|
||||
FUNCTION(machine_check_exception):
|
||||
VEC_ENTRY();
|
||||
li %r3, 0x200
|
||||
addi %r4, %r1, 8
|
||||
bl ppc_exception_entry
|
||||
bl __restore_regs_and_rfi
|
||||
|
||||
.skip 0x300 - (. - __irqvec_start)
|
||||
FUNCTION(DSI_exception):
|
||||
VEC_ENTRY();
|
||||
li %r3, 0x300
|
||||
addi %r4, %r1, 8
|
||||
bl ppc_exception_entry
|
||||
bl __restore_regs_and_rfi
|
||||
|
||||
.skip 0x400 - (. - __irqvec_start)
|
||||
FUNCTION(ISI_exception):
|
||||
VEC_ENTRY();
|
||||
li %r3, 0x400
|
||||
addi %r4, %r1, 8
|
||||
bl ppc_exception_entry
|
||||
bl __restore_regs_and_rfi
|
||||
|
||||
.skip 0x500 - (. - __irqvec_start)
|
||||
FUNCTION(external_interrupt_exception):
|
||||
VEC_ENTRY();
|
||||
li %r3, 0x500
|
||||
addi %r4, %r1, 8
|
||||
bl ppc_exception_entry
|
||||
bl __restore_regs_and_rfi
|
||||
|
||||
.skip 0x600 - (. - __irqvec_start)
|
||||
FUNCTION(alignment_exception):
|
||||
VEC_ENTRY();
|
||||
li %r3, 0x600
|
||||
addi %r4, %r1, 8
|
||||
bl ppc_exception_entry
|
||||
bl __restore_regs_and_rfi
|
||||
|
||||
.skip 0x700 - (. - __irqvec_start)
|
||||
FUNCTION(program_exception):
|
||||
VEC_ENTRY();
|
||||
li %r3, 0x700
|
||||
addi %r4, %r1, 8
|
||||
bl ppc_exception_entry
|
||||
bl __restore_regs_and_rfi
|
||||
|
||||
.skip 0x800 - (. - __irqvec_start)
|
||||
FUNCTION(FP_unavailable_exception):
|
||||
VEC_ENTRY();
|
||||
li %r3, 0x800
|
||||
addi %r4, %r1, 8
|
||||
bl ppc_exception_entry
|
||||
bl __restore_regs_and_rfi
|
||||
|
||||
.skip 0x900 - (. - __irqvec_start)
|
||||
FUNCTION(decrementer_exception):
|
||||
VEC_ENTRY();
|
||||
li %r3, 0x900
|
||||
addi %r4, %r1, 8
|
||||
bl ppc_exception_entry
|
||||
bl __restore_regs_and_rfi
|
||||
|
||||
/* called at the tail end of each of the exceptions
|
||||
** placed here because of the space between these two
|
||||
** exception handlers.
|
||||
*/
|
||||
FUNCTION(__restore_regs_and_rfi):
|
||||
addi %r1, %r1, 8 /* adjust the stack pointer to get it back to the base of the iframe */
|
||||
|
||||
lwz %r0, 0(%r1) /* SRR0 */
|
||||
mtspr %srr0, %r0
|
||||
lwzu %r0, 4(%r1) /* SRR1 */
|
||||
mtspr %srr1, %r0
|
||||
lwzu %r0, 4(%r1) /* DAR */
|
||||
mtspr %dar, %r0
|
||||
lwzu %r0, 4(%r1) /* DSISR */
|
||||
mtspr %dsisr, %r0
|
||||
lwzu %r0, 4(%r1) /* LR */
|
||||
mtlr %r0
|
||||
lwzu %r0, 4(%r1) /* CR */
|
||||
mtcr %r0
|
||||
lwzu %r0, 4(%r1) /* XER */
|
||||
mtxer %r0
|
||||
lwzu %r0, 4(%r1) /* CTR */
|
||||
mtctr %r0
|
||||
|
||||
/* strictly speaking, we dont really need to have saved these regs */
|
||||
lwzu %r31, 4(%r1)
|
||||
lwzu %r30, 4(%r1)
|
||||
lwzu %r29, 4(%r1)
|
||||
lwzu %r28, 4(%r1)
|
||||
lwzu %r27, 4(%r1)
|
||||
lwzu %r26, 4(%r1)
|
||||
lwzu %r25, 4(%r1)
|
||||
lwzu %r24, 4(%r1)
|
||||
lwzu %r23, 4(%r1)
|
||||
lwzu %r22, 4(%r1)
|
||||
lwzu %r21, 4(%r1)
|
||||
lwzu %r20, 4(%r1)
|
||||
lwzu %r19, 4(%r1)
|
||||
lwzu %r18, 4(%r1)
|
||||
lwzu %r17, 4(%r1)
|
||||
lwzu %r16, 4(%r1)
|
||||
lwzu %r15, 4(%r1)
|
||||
lwzu %r14, 4(%r1)
|
||||
lwzu %r13, 4(%r1)
|
||||
|
||||
lwzu %r12, 4(%r1)
|
||||
lwzu %r11, 4(%r1)
|
||||
lwzu %r10, 4(%r1)
|
||||
lwzu %r9, 4(%r1)
|
||||
lwzu %r8, 4(%r1)
|
||||
lwzu %r7, 4(%r1)
|
||||
lwzu %r6, 4(%r1)
|
||||
lwzu %r5, 4(%r1)
|
||||
lwzu %r4, 4(%r1)
|
||||
lwzu %r3, 4(%r1)
|
||||
lwzu %r2, 4(%r1)
|
||||
lwz %r0, 8(%r1)
|
||||
lwz %r1, 4(%r1)
|
||||
|
||||
/* get out of here */
|
||||
rfi
|
||||
|
||||
.skip 0xc00 - (. - __irqvec_start)
|
||||
FUNCTION(system_call_exception):
|
||||
VEC_ENTRY();
|
||||
li %r3, 0xc00
|
||||
addi %r4, %r1, 8
|
||||
bl ppc_exception_entry
|
||||
bl __restore_regs_and_rfi
|
||||
|
||||
.skip 0xd00 - (. - __irqvec_start)
|
||||
FUNCTION(trace_exception):
|
||||
VEC_ENTRY();
|
||||
li %r3, 0xd00
|
||||
addi %r4, %r1, 8
|
||||
bl ppc_exception_entry
|
||||
bl __restore_regs_and_rfi
|
||||
|
||||
.skip 0xe00 - (. - __irqvec_start)
|
||||
FUNCTION(FP_assist_exception):
|
||||
VEC_ENTRY();
|
||||
li %r3, 0xe00
|
||||
addi %r4, %r1, 8
|
||||
bl ppc_exception_entry
|
||||
bl __restore_regs_and_rfi
|
||||
|
||||
.skip 0xf00 - (. - __irqvec_start)
|
||||
FUNCTION(perf_monitor_exception):
|
||||
/* XXX deal with this, normal VEC_ENTRY code is too big to fit here */
|
||||
rfi
|
||||
|
||||
.skip 0xf20 - (. - __irqvec_start)
|
||||
FUNCTION(altivec_unavailable_exception):
|
||||
VEC_ENTRY();
|
||||
li %r3, 0xf20
|
||||
addi %r4, %r1, 8
|
||||
bl ppc_exception_entry
|
||||
bl __restore_regs_and_rfi
|
||||
|
||||
.skip 0x1000 - (. - __irqvec_start)
|
||||
FUNCTION(ITLB_miss_exception):
|
||||
VEC_ENTRY();
|
||||
li %r3, 0x1000
|
||||
addi %r4, %r1, 8
|
||||
bl ppc_exception_entry
|
||||
bl __restore_regs_and_rfi
|
||||
|
||||
.skip 0x1100 - (. - __irqvec_start)
|
||||
FUNCTION(DTLB_miss_on_load_exception):
|
||||
VEC_ENTRY();
|
||||
li %r3, 0x1100
|
||||
addi %r4, %r1, 8
|
||||
bl ppc_exception_entry
|
||||
bl __restore_regs_and_rfi
|
||||
|
||||
.skip 0x1200 - (. - __irqvec_start)
|
||||
FUNCTION(DTLB_miss_on_store_exception):
|
||||
VEC_ENTRY();
|
||||
li %r3, 0x1200
|
||||
addi %r4, %r1, 8
|
||||
bl ppc_exception_entry
|
||||
bl __restore_regs_and_rfi
|
||||
|
||||
.skip 0x1300 - (. - __irqvec_start)
|
||||
FUNCTION(instruction_address_breakpoint_exception):
|
||||
VEC_ENTRY();
|
||||
li %r3, 0x1300
|
||||
addi %r4, %r1, 8
|
||||
bl ppc_exception_entry
|
||||
bl __restore_regs_and_rfi
|
||||
|
||||
.skip 0x1400 - (. - __irqvec_start)
|
||||
FUNCTION(system_management_exception):
|
||||
VEC_ENTRY();
|
||||
li %r3, 0x1400
|
||||
addi %r4, %r1, 8
|
||||
bl ppc_exception_entry
|
||||
bl __restore_regs_and_rfi
|
||||
|
||||
.skip 0x1600 - (. - __irqvec_start)
|
||||
FUNCTION(altivec_assist_exception):
|
||||
VEC_ENTRY();
|
||||
li %r3, 0x1600
|
||||
addi %r4, %r1, 8
|
||||
bl ppc_exception_entry
|
||||
bl __restore_regs_and_rfi
|
||||
|
||||
.skip 0x1700 - (. - __irqvec_start)
|
||||
FUNCTION(thermal_management_exception):
|
||||
VEC_ENTRY();
|
||||
li %r3, 0x1700
|
||||
addi %r4, %r1, 8
|
||||
bl ppc_exception_entry
|
||||
bl __restore_regs_and_rfi
|
||||
|
||||
.global __irqvec_end
|
||||
__irqvec_end:
|
||||
|
@ -4,41 +4,179 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <boot/stage2.h>
|
||||
#include <boot/kernel_args.h>
|
||||
|
||||
#include <int.h>
|
||||
#include <vm.h>
|
||||
#include <vm_priv.h>
|
||||
#include <timer.h>
|
||||
#include <thread.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
// defined in arch_exceptions.S
|
||||
extern int __irqvec_start;
|
||||
extern int __irqvec_end;
|
||||
|
||||
|
||||
bool
|
||||
arch_int_is_interrupts_enabled(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
void
|
||||
arch_int_enable_io_interrupt(int irq)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
void
|
||||
arch_int_disable_io_interrupt(int irq)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
static void
|
||||
print_iframe(struct iframe *frame)
|
||||
{
|
||||
dprintf("iframe at %p:\n", frame);
|
||||
dprintf("r0-r3: 0x%08lx 0x%08lx 0x%08lx 0x%08lx\n", frame->r0, frame->r1, frame->r2, frame->r3);
|
||||
dprintf("r4-r7: 0x%08lx 0x%08lx 0x%08lx 0x%08lx\n", frame->r4, frame->r5, frame->r6, frame->r7);
|
||||
dprintf("r8-r11: 0x%08lx 0x%08lx 0x%08lx 0x%08lx\n", frame->r8, frame->r9, frame->r10, frame->r11);
|
||||
dprintf("r12-r15: 0x%08lx 0x%08lx 0x%08lx 0x%08lx\n", frame->r12, frame->r13, frame->r14, frame->r15);
|
||||
dprintf("r16-r19: 0x%08lx 0x%08lx 0x%08lx 0x%08lx\n", frame->r16, frame->r17, frame->r18, frame->r19);
|
||||
dprintf("r20-r23: 0x%08lx 0x%08lx 0x%08lx 0x%08lx\n", frame->r20, frame->r21, frame->r22, frame->r23);
|
||||
dprintf("r24-r27: 0x%08lx 0x%08lx 0x%08lx 0x%08lx\n", frame->r24, frame->r25, frame->r26, frame->r27);
|
||||
dprintf("r28-r31: 0x%08lx 0x%08lx 0x%08lx 0x%08lx\n", frame->r28, frame->r29, frame->r30, frame->r31);
|
||||
dprintf(" ctr 0x%08lx xer 0x%08lx\n", frame->ctr, frame->xer);
|
||||
dprintf(" cr 0x%08lx lr 0x%08lx\n", frame->cr, frame->lr);
|
||||
dprintf(" dsisr 0x%08lx dar 0x%08lx\n", frame->dsisr, frame->dar);
|
||||
dprintf(" srr1 0x%08lx srr0 0x%08lx\n", frame->srr1, frame->srr0);
|
||||
}
|
||||
|
||||
|
||||
void ppc_exception_entry(int vector, struct iframe *iframe);
|
||||
void
|
||||
ppc_exception_entry(int vector, struct iframe *iframe)
|
||||
{
|
||||
int ret = B_HANDLED_INTERRUPT;
|
||||
|
||||
if (vector != 0x900)
|
||||
dprintf("ppc_exception_entry: time %Ld vector 0x%x, iframe %p\n", system_time(), vector, iframe);
|
||||
|
||||
switch (vector) {
|
||||
case 0x100: // system reset
|
||||
panic("system reset exception\n");
|
||||
break;
|
||||
case 0x200: // machine check
|
||||
panic("machine check exception\n");
|
||||
break;
|
||||
case 0x300: // DSI
|
||||
case 0x400: // ISI
|
||||
{
|
||||
addr_t newip;
|
||||
|
||||
ret = vm_page_fault(iframe->dar, iframe->srr0,
|
||||
iframe->dsisr & (1 << 25), // store or load
|
||||
iframe->srr1 & (1 << 14), // was the system in user or supervisor
|
||||
&newip);
|
||||
if (newip != 0) {
|
||||
// the page fault handler wants us to modify the iframe to set the
|
||||
// IP the cpu will return to to be this ip
|
||||
iframe->srr0 = newip;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x500: // external interrupt
|
||||
panic("external interrrupt exception: unimplemented\n");
|
||||
break;
|
||||
case 0x600: // alignment exception
|
||||
panic("alignment exception: unimplemented\n");
|
||||
break;
|
||||
case 0x700: // program exception
|
||||
panic("program exception: unimplemented\n");
|
||||
break;
|
||||
case 0x800: // FP unavailable exception
|
||||
panic("FP unavailable exception: unimplemented\n");
|
||||
break;
|
||||
case 0x900: // decrementer exception
|
||||
ret = timer_interrupt();
|
||||
break;
|
||||
case 0xc00: // system call
|
||||
panic("system call exception: unimplemented\n");
|
||||
break;
|
||||
case 0xd00: // trace exception
|
||||
panic("trace exception: unimplemented\n");
|
||||
break;
|
||||
case 0xe00: // FP assist exception
|
||||
panic("FP assist exception: unimplemented\n");
|
||||
break;
|
||||
case 0xf00: // performance monitor exception
|
||||
panic("performance monitor exception: unimplemented\n");
|
||||
break;
|
||||
case 0xf20: // alitivec unavailable exception
|
||||
panic("alitivec unavailable exception: unimplemented\n");
|
||||
break;
|
||||
case 0x1000:
|
||||
case 0x1100:
|
||||
case 0x1200:
|
||||
panic("TLB miss exception: unimplemented\n");
|
||||
break;
|
||||
case 0x1300: // instruction address exception
|
||||
panic("instruction address exception: unimplemented\n");
|
||||
break;
|
||||
case 0x1400: // system management exception
|
||||
panic("system management exception: unimplemented\n");
|
||||
break;
|
||||
case 0x1600: // altivec assist exception
|
||||
panic("altivec assist exception: unimplemented\n");
|
||||
break;
|
||||
case 0x1700: // thermal management exception
|
||||
panic("thermal management exception: unimplemented\n");
|
||||
break;
|
||||
default:
|
||||
dprintf("unhandled exception type 0x%x\n", vector);
|
||||
print_iframe(iframe);
|
||||
panic("unhandled exception type\n");
|
||||
}
|
||||
|
||||
if (ret == B_INVOKE_SCHEDULER) {
|
||||
int state = disable_interrupts();
|
||||
GRAB_THREAD_LOCK();
|
||||
scheduler_reschedule();
|
||||
RELEASE_THREAD_LOCK();
|
||||
restore_interrupts(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
arch_int_init(kernel_args *ka)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
int
|
||||
arch_int_init2(kernel_args *ka)
|
||||
{
|
||||
region_id exception_region;
|
||||
void *ex_handlers;
|
||||
|
||||
// create a region to map the irq vector code into (physical addres 0x0)
|
||||
ex_handlers = (void *)ka->arch_args.exception_handlers.start;
|
||||
exception_region = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "exception_handlers",
|
||||
&ex_handlers, REGION_ADDR_EXACT_ADDRESS,
|
||||
ka->arch_args.exception_handlers.size, REGION_WIRING_WIRED_ALREADY, LOCK_RW|LOCK_KERNEL);
|
||||
if (exception_region < 0)
|
||||
panic("arch_int_init2: could not create exception handler region\n");
|
||||
|
||||
dprintf("exception handlers at %p\n", ex_handlers);
|
||||
|
||||
// copy the handlers into this area
|
||||
memcpy(ex_handlers, &__irqvec_start, ka->arch_args.exception_handlers.size);
|
||||
arch_cpu_sync_icache(0, 0x3000);
|
||||
|
||||
// make sure the IP bit isn't set (putting the exceptions at 0x0)
|
||||
set_msr(get_msr() & ~MSR_IP);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -30,17 +30,17 @@ page_table_entry::SecondaryHash(uint32 primaryHash)
|
||||
|
||||
|
||||
void
|
||||
ppc_get_page_table(void **_pageTable, size_t *_size)
|
||||
ppc_get_page_table(page_table_entry_group **_pageTable, size_t *_size)
|
||||
{
|
||||
uint32 sdr1 = get_sdr1();
|
||||
|
||||
*_pageTable = (void *)(sdr1 & 0xffff0000);
|
||||
*_pageTable = (page_table_entry_group *)(sdr1 & 0xffff0000);
|
||||
*_size = ((sdr1 & 0x1ff) + 1) << 16;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ppc_set_page_table(void *pageTable, size_t size)
|
||||
ppc_set_page_table(page_table_entry_group *pageTable, size_t size)
|
||||
{
|
||||
set_sdr1(((uint32)pageTable & 0xffff0000) | (((size >> 16) - 1 ) & 0x1ff));
|
||||
}
|
||||
|
@ -8,6 +8,8 @@
|
||||
#include <thread.h>
|
||||
#include <boot/stage2.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
int
|
||||
arch_team_init_team_struct(struct team *team, bool kernel)
|
||||
@ -19,6 +21,9 @@ arch_team_init_team_struct(struct team *team, bool kernel)
|
||||
int
|
||||
arch_thread_init_thread_struct(struct thread *t)
|
||||
{
|
||||
// set up an initial state (stack & fpu)
|
||||
memset(&t->arch_info, 0, sizeof(t->arch_info));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -26,20 +31,38 @@ arch_thread_init_thread_struct(struct thread *t)
|
||||
int
|
||||
arch_thread_init_kthread_stack(struct thread *t, int (*start_func)(void), void (*entry_func)(void), void (*exit_func)(void))
|
||||
{
|
||||
addr_t *kstack = (addr_t *)t->kernel_stack_base;
|
||||
size_t kstack_size = KSTACK_SIZE;
|
||||
addr_t *kstack_top = kstack + kstack_size / sizeof(addr_t) - 2 * 4;
|
||||
|
||||
// r13-r31, cr, r2
|
||||
kstack_top -= (31 - 13 + 1) + 1 + 1;
|
||||
|
||||
// set the saved lr address to be the start_func
|
||||
kstack_top--;
|
||||
*kstack_top = (addr_t)start_func;
|
||||
|
||||
// save this stack position
|
||||
t->arch_info.sp = (void *)kstack_top;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// ToDo: we are single proc for now
|
||||
static struct thread *current_thread = NULL;
|
||||
|
||||
struct thread *
|
||||
arch_thread_get_current_thread(void)
|
||||
{
|
||||
return NULL;
|
||||
return current_thread;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
arch_thread_set_current_thread(struct thread *thread)
|
||||
void
|
||||
arch_thread_set_current_thread(struct thread *t)
|
||||
{
|
||||
current_thread = t;
|
||||
}
|
||||
|
||||
|
||||
@ -58,18 +81,37 @@ arch_thread_switch_kstack_and_call(struct thread *t, addr new_kstack, void (*fun
|
||||
void
|
||||
arch_thread_context_switch(struct thread *t_from, struct thread *t_to)
|
||||
{
|
||||
// set the new kernel stack in the EAR register.
|
||||
// this is used in the exception handler code to decide what kernel stack to
|
||||
// switch to if the exception had happened when the processor was in user mode
|
||||
asm("mtear %0" :: "g"(t_to->kernel_stack_base + KSTACK_SIZE - 8));
|
||||
|
||||
// switch the asids if we need to
|
||||
if (t_to->team->_aspace_id >= 0) {
|
||||
// the target thread has is user space
|
||||
if (t_from->team->_aspace_id != t_to->team->_aspace_id) {
|
||||
// switching to a new address space
|
||||
ppc_translation_map_change_asid(&t_to->team->aspace->translation_map);
|
||||
}
|
||||
}
|
||||
|
||||
ppc_context_switch(&t_from->arch_info.sp, t_to->arch_info.sp);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
arch_thread_dump_info(void *info)
|
||||
{
|
||||
struct arch_thread *at = (struct arch_thread *)info;
|
||||
|
||||
dprintf("\tsp: %p\n", at->sp);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
arch_thread_enter_uspace(struct thread *thread, addr entry, void *arg1, void *arg2)
|
||||
{
|
||||
panic("arch_thread_enter_uspace(): not yet implemented\n");
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
@ -6,23 +6,41 @@
|
||||
|
||||
#include <boot/stage2.h>
|
||||
#include <kernel.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <timer.h>
|
||||
#include <arch/timer.h>
|
||||
|
||||
|
||||
void
|
||||
static bigtime_t sTickRate;
|
||||
|
||||
|
||||
void
|
||||
arch_timer_set_hardware_timer(bigtime_t timeout)
|
||||
{
|
||||
bigtime_t new_val_64;
|
||||
|
||||
if(timeout < 1000)
|
||||
timeout = 1000;
|
||||
|
||||
new_val_64 = (timeout * sTickRate) / 1000000;
|
||||
|
||||
asm("mtdec %0" :: "r"((uint32)new_val_64));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
void
|
||||
arch_timer_clear_hardware_timer()
|
||||
{
|
||||
asm("mtdec %0" :: "r"(0x7fffffff));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
int
|
||||
arch_init_timer(kernel_args *ka)
|
||||
{
|
||||
sTickRate = (66*1000*1000) / 4; // ToDo: fix
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
107
src/kernel/core/arch/ppc/arch_vm.cpp
Normal file
107
src/kernel/core/arch/ppc/arch_vm.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
|
||||
|
||||
#include <kernel.h>
|
||||
#include <boot/kernel_args.h>
|
||||
|
||||
#include <arch/vm.h>
|
||||
#include <arch_mmu.h>
|
||||
|
||||
|
||||
int
|
||||
arch_vm_init(kernel_args *ka)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
arch_vm_init2(kernel_args *ka)
|
||||
{
|
||||
// int bats[8];
|
||||
// int i;
|
||||
|
||||
#if 0
|
||||
// print out any bat mappings
|
||||
getibats(bats);
|
||||
dprintf("ibats:\n");
|
||||
for(i = 0; i < 4; i++)
|
||||
dprintf("0x%x 0x%x\n", bats[i*2], bats[i*2+1]);
|
||||
getdbats(bats);
|
||||
dprintf("dbats:\n");
|
||||
for(i = 0; i < 4; i++)
|
||||
dprintf("0x%x 0x%x\n", bats[i*2], bats[i*2+1]);
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
// turn off the first 2 BAT mappings (3 & 4 are used by the lower level code)
|
||||
block_address_translation bat;
|
||||
bat.Clear();
|
||||
|
||||
set_ibat0(&bat);
|
||||
set_ibat1(&bat);
|
||||
set_dbat0(&bat);
|
||||
set_dbat1(&bat);
|
||||
/* getibats(bats);
|
||||
memset(bats, 0, 2 * 2);
|
||||
setibats(bats);
|
||||
getdbats(bats);
|
||||
memset(bats, 0, 2 * 2);
|
||||
setdbats(bats);
|
||||
*/
|
||||
#endif
|
||||
#if 0
|
||||
// just clear the first BAT mapping (0 - 256MB)
|
||||
dprintf("msr 0x%x\n", getmsr());
|
||||
{
|
||||
unsigned int reg;
|
||||
asm("mr %0,1" : "=r"(reg));
|
||||
dprintf("sp 0x%x\n", reg);
|
||||
}
|
||||
dprintf("ka %p\n", ka);
|
||||
|
||||
getibats(bats);
|
||||
dprintf("ibats:\n");
|
||||
for(i = 0; i < 4; i++)
|
||||
dprintf("0x%x 0x%x\n", bats[i*2], bats[i*2+1]);
|
||||
bats[0] = bats[1] = 0;
|
||||
setibats(bats);
|
||||
getdbats(bats);
|
||||
dprintf("dbats:\n");
|
||||
for(i = 0; i < 4; i++)
|
||||
dprintf("0x%x 0x%x\n", bats[i*2], bats[i*2+1]);
|
||||
bats[0] = bats[1] = 0;
|
||||
setdbats(bats);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
arch_vm_init_existing_maps(kernel_args *ka)
|
||||
{
|
||||
void *temp = (void *)ka->fb.mapping.start;
|
||||
|
||||
// create a region for the framebuffer
|
||||
vm_create_anonymous_region(vm_get_kernel_aspace_id(), "framebuffer", &temp, REGION_ADDR_EXACT_ADDRESS,
|
||||
ka->fb.mapping.size, REGION_WIRING_WIRED_ALREADY, LOCK_RW|LOCK_KERNEL);
|
||||
|
||||
return B_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
arch_vm_init_endvm(kernel_args *ka)
|
||||
{
|
||||
return B_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
arch_vm_aspace_swap(vm_address_space *aspace)
|
||||
{
|
||||
}
|
||||
|
516
src/kernel/core/arch/ppc/arch_vm_translation_map.cpp
Normal file
516
src/kernel/core/arch/ppc/arch_vm_translation_map.cpp
Normal file
@ -0,0 +1,516 @@
|
||||
/*
|
||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <kernel.h>
|
||||
#include <vm.h>
|
||||
#include <vm_priv.h>
|
||||
#include <int.h>
|
||||
#include <boot/kernel_args.h>
|
||||
#include <arch/vm_translation_map.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <arch_mmu.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
static struct page_table_entry_group *sPageTable;
|
||||
static size_t sPageTableSize;
|
||||
static uint32 sPageTableHashMask;
|
||||
static area_id sPageTableRegion;
|
||||
|
||||
|
||||
// 512 MB of iospace
|
||||
#define IOSPACE_SIZE (512*1024*1024)
|
||||
// put it 512 MB into kernel space
|
||||
#define IOSPACE_BASE (KERNEL_BASE + IOSPACE_SIZE)
|
||||
|
||||
#define MAX_ASIDS (PAGE_SIZE * 8)
|
||||
static uint32 asid_bitmap[MAX_ASIDS / (sizeof(uint32) * 8)];
|
||||
spinlock asid_bitmap_lock;
|
||||
#define ASID_SHIFT 4
|
||||
#define VADDR_TO_ASID(map, vaddr) \
|
||||
(((map)->arch_data->asid_base << ASID_SHIFT) + ((vaddr) / 0x10000000))
|
||||
|
||||
// vm_translation object stuff
|
||||
typedef struct vm_translation_map_arch_info_struct {
|
||||
int asid_base; // shift left by ASID_SHIFT to get the base asid to use
|
||||
} vm_translation_map_arch_info;
|
||||
|
||||
|
||||
static int
|
||||
lock_tmap(vm_translation_map *map)
|
||||
{
|
||||
recursive_lock_lock(&map->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
unlock_tmap(vm_translation_map *map)
|
||||
{
|
||||
recursive_lock_unlock(&map->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
destroy_tmap(vm_translation_map *map)
|
||||
{
|
||||
if (map->map_count > 0) {
|
||||
panic("vm_translation_map.destroy_tmap: map %p has positive map count %d\n", map, map->map_count);
|
||||
}
|
||||
|
||||
// mark the asid not in use
|
||||
atomic_and((vint32 *)&asid_bitmap[map->arch_data->asid_base / 32],
|
||||
~(1 << (map->arch_data->asid_base % 32)));
|
||||
|
||||
free(map->arch_data);
|
||||
recursive_lock_destroy(&map->lock);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
fill_page_table_entry(page_table_entry *entry, uint32 virtualSegmentID,
|
||||
addr_t virtualAddress, addr_t physicalAddress, uint8 protection,
|
||||
bool secondaryHash)
|
||||
{
|
||||
// lower 32 bit - set at once
|
||||
entry->physical_page_number = physicalAddress / B_PAGE_SIZE;
|
||||
entry->_reserved0 = 0;
|
||||
entry->referenced = false;
|
||||
entry->changed = false;
|
||||
entry->write_through = false;
|
||||
entry->caching_inhibited = false;
|
||||
entry->memory_coherent = false;
|
||||
entry->guarded = false;
|
||||
entry->_reserved1 = 0;
|
||||
entry->page_protection = protection & 0x3;
|
||||
eieio();
|
||||
// we need to make sure that the lower 32 bit were
|
||||
// already written when the entry becomes valid
|
||||
|
||||
// upper 32 bit
|
||||
entry->virtual_segment_id = virtualSegmentID;
|
||||
entry->secondary_hash = secondaryHash;
|
||||
entry->abbr_page_index = (virtualAddress >> 22) & 0x3f;
|
||||
entry->valid = true;
|
||||
|
||||
// ToDo: this is probably a bit too much sledge hammer
|
||||
arch_cpu_global_TLB_invalidate();
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
map_tmap(vm_translation_map *map, addr_t virtualAddress, addr_t physicalAddress, unsigned int attributes)
|
||||
{
|
||||
// lookup the vsid based off the va
|
||||
uint32 virtualSegmentID = VADDR_TO_ASID(map, virtualAddress);
|
||||
|
||||
if (attributes & LOCK_KERNEL)
|
||||
attributes = 0; // all kernel mappings are R/W to supervisor code
|
||||
else
|
||||
attributes = (attributes & LOCK_RW) ? PTE_READ_WRITE : PTE_READ_ONLY;
|
||||
|
||||
//dprintf("vm_translation_map.map_tmap: vsid %d, pa 0x%lx, va 0x%lx\n", vsid, pa, va);
|
||||
|
||||
// Search for a free page table slot using the primary hash value
|
||||
|
||||
uint32 hash = page_table_entry::PrimaryHash(virtualSegmentID, virtualAddress);
|
||||
page_table_entry_group *group = &sPageTable[hash & sPageTableHashMask];
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
page_table_entry *entry = &group->entry[i];
|
||||
|
||||
if (entry->valid)
|
||||
continue;
|
||||
|
||||
fill_page_table_entry(entry, virtualSegmentID, virtualAddress, physicalAddress,
|
||||
attributes, false);
|
||||
map->map_count++;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// Didn't found one, try the secondary hash value
|
||||
|
||||
hash = page_table_entry::SecondaryHash(hash);
|
||||
group = &sPageTable[hash & sPageTableHashMask];
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
page_table_entry *entry = &group->entry[i];
|
||||
|
||||
if (entry->valid)
|
||||
continue;
|
||||
|
||||
fill_page_table_entry(entry, virtualSegmentID, virtualAddress, physicalAddress,
|
||||
attributes, false);
|
||||
map->map_count++;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
panic("vm_translation_map.map_tmap: hash table full\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static page_table_entry *
|
||||
lookup_pagetable_entry(vm_translation_map *map, addr_t virtualAddress)
|
||||
{
|
||||
// lookup the vsid based off the va
|
||||
uint32 virtualSegmentID = VADDR_TO_ASID(map, virtualAddress);
|
||||
|
||||
// dprintf("vm_translation_map.lookup_pagetable_entry: vsid %d, va 0x%lx\n", vsid, va);
|
||||
|
||||
|
||||
// Search for the page table entry using the primary hash value
|
||||
|
||||
uint32 hash = page_table_entry::PrimaryHash(virtualSegmentID, virtualAddress);
|
||||
page_table_entry_group *group = &sPageTable[hash & sPageTableHashMask];
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
page_table_entry *entry = &group->entry[i];
|
||||
|
||||
if (entry->virtual_segment_id == virtualSegmentID
|
||||
&& entry->secondary_hash == false
|
||||
&& entry->abbr_page_index == ((virtualAddress >> 22) & 0x3f))
|
||||
return entry;
|
||||
}
|
||||
|
||||
// Didn't found it, try the secondary hash value
|
||||
|
||||
hash = page_table_entry::SecondaryHash(hash);
|
||||
group = &sPageTable[hash & sPageTableHashMask];
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
page_table_entry *entry = &group->entry[i];
|
||||
|
||||
if (entry->virtual_segment_id == virtualSegmentID
|
||||
&& entry->secondary_hash == true
|
||||
&& entry->abbr_page_index == ((virtualAddress >> 22) & 0x3f))
|
||||
return entry;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
unmap_tmap(vm_translation_map *map, addr_t start, addr_t end)
|
||||
{
|
||||
page_table_entry *entry;
|
||||
|
||||
start = ROUNDOWN(start, PAGE_SIZE);
|
||||
end = ROUNDUP(end, PAGE_SIZE);
|
||||
|
||||
dprintf("vm_translation_map.unmap_tmap: start 0x%lx, end 0x%lx\n", start, end);
|
||||
|
||||
while (start < end) {
|
||||
entry = lookup_pagetable_entry(map, start);
|
||||
if (entry) {
|
||||
// unmap this page
|
||||
entry->valid = 0;
|
||||
arch_cpu_global_TLB_invalidate();
|
||||
map->map_count--;
|
||||
}
|
||||
|
||||
start += B_PAGE_SIZE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
query_tmap(vm_translation_map *map, addr_t va, addr_t *out_physical, unsigned int *out_flags)
|
||||
{
|
||||
page_table_entry *entry;
|
||||
|
||||
// default the flags to not present
|
||||
*out_flags = 0;
|
||||
*out_physical = 0;
|
||||
|
||||
entry = lookup_pagetable_entry(map, va);
|
||||
if (entry == NULL)
|
||||
return B_NO_ERROR;
|
||||
|
||||
*out_flags |= (entry->page_protection == PTE_READ_ONLY) ? LOCK_RO : LOCK_RW;
|
||||
if (va >= KERNEL_BASE)
|
||||
*out_flags |= LOCK_KERNEL; // XXX is this enough?
|
||||
*out_flags |= entry->changed ? PAGE_MODIFIED : 0;
|
||||
*out_flags |= entry->referenced ? PAGE_ACCESSED : 0;
|
||||
*out_flags |= entry->valid ? PAGE_PRESENT : 0;
|
||||
|
||||
*out_physical = entry->physical_page_number * B_PAGE_SIZE;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static addr_t
|
||||
get_mapped_size_tmap(vm_translation_map *map)
|
||||
{
|
||||
return map->map_count;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
protect_tmap(vm_translation_map *map, addr_t base, addr_t top, unsigned int attributes)
|
||||
{
|
||||
// XXX finish
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
clear_flags_tmap(vm_translation_map *map, addr_t virtualAddress, unsigned int flags)
|
||||
{
|
||||
page_table_entry *entry = lookup_pagetable_entry(map, virtualAddress);
|
||||
if (entry == NULL)
|
||||
return B_NO_ERROR;
|
||||
|
||||
if (flags & PAGE_MODIFIED)
|
||||
entry->changed = false;
|
||||
if (flags & PAGE_ACCESSED)
|
||||
entry->referenced = false;
|
||||
|
||||
arch_cpu_global_TLB_invalidate();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
flush_tmap(vm_translation_map *map)
|
||||
{
|
||||
arch_cpu_global_TLB_invalidate();
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
get_physical_page_tmap(addr_t pa, addr_t *va, int flags)
|
||||
{
|
||||
pa = ROUNDOWN(pa, PAGE_SIZE);
|
||||
|
||||
if(pa > IOSPACE_SIZE)
|
||||
panic("get_physical_page_tmap: asked for pa 0x%lx, cannot provide\n", pa);
|
||||
|
||||
*va = (IOSPACE_BASE + pa);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
put_physical_page_tmap(addr_t va)
|
||||
{
|
||||
if (va < IOSPACE_BASE || va >= IOSPACE_BASE + IOSPACE_SIZE)
|
||||
panic("put_physical_page_tmap: va 0x%lx out of iospace region\n", va);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static vm_translation_map_ops tmap_ops = {
|
||||
destroy_tmap,
|
||||
lock_tmap,
|
||||
unlock_tmap,
|
||||
map_tmap,
|
||||
unmap_tmap,
|
||||
query_tmap,
|
||||
get_mapped_size_tmap,
|
||||
protect_tmap,
|
||||
clear_flags_tmap,
|
||||
flush_tmap,
|
||||
get_physical_page_tmap,
|
||||
put_physical_page_tmap
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
vm_translation_map_create(vm_translation_map *new_map, bool kernel)
|
||||
{
|
||||
// initialize the new object
|
||||
new_map->ops = &tmap_ops;
|
||||
new_map->map_count = 0;
|
||||
if (recursive_lock_init(&new_map->lock, "map lock") < B_OK)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
new_map->arch_data = (vm_translation_map_arch_info *)malloc(sizeof(vm_translation_map_arch_info));
|
||||
if (new_map->arch_data == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
cpu_status state = disable_interrupts();
|
||||
acquire_spinlock(&asid_bitmap_lock);
|
||||
|
||||
// allocate a ASID base for this one
|
||||
if (kernel) {
|
||||
new_map->arch_data->asid_base = 0; // set up by the bootloader
|
||||
asid_bitmap[0] |= 0x1;
|
||||
} else {
|
||||
int i = 0;
|
||||
|
||||
while (i < MAX_ASIDS) {
|
||||
if (asid_bitmap[i / 32] == 0xffffffff) {
|
||||
i += 32;
|
||||
continue;
|
||||
}
|
||||
if ((asid_bitmap[i / 32] & (1 << (i % 32))) == 0) {
|
||||
// we found it
|
||||
asid_bitmap[i / 32] |= 1 << (i % 32);
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (i >= MAX_ASIDS)
|
||||
panic("vm_translation_map_create: out of ASIDS\n");
|
||||
new_map->arch_data->asid_base = i;
|
||||
}
|
||||
|
||||
release_spinlock(&asid_bitmap_lock);
|
||||
restore_interrupts(state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
vm_translation_map_module_init(kernel_args *args)
|
||||
{
|
||||
sPageTable = (page_table_entry_group *)args->arch_args.page_table.start;
|
||||
sPageTableSize = args->arch_args.page_table.size;
|
||||
sPageTableHashMask = (sPageTableSize >> 6) - 1;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
vm_translation_map_module_init_post_sem(kernel_args *ka)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
vm_translation_map_module_init2(kernel_args *ka)
|
||||
{
|
||||
// create a region to cover the page table
|
||||
sPageTableRegion = vm_create_anonymous_region(vm_get_kernel_aspace_id(),
|
||||
"page_table", (void **)&sPageTable, REGION_ADDR_EXACT_ADDRESS,
|
||||
sPageTableSize, REGION_WIRING_WIRED_ALREADY, LOCK_KERNEL | LOCK_RW);
|
||||
|
||||
// ToDo: for now just map 0 - 512MB of physical memory to the iospace region
|
||||
block_address_translation bat;
|
||||
|
||||
bat.Clear();
|
||||
bat.SetVirtualAddress((void *)IOSPACE_BASE);
|
||||
bat.page_index = IOSPACE_BASE;
|
||||
bat.length = BAT_LENGTH_256MB;
|
||||
bat.kernel_valid = true;
|
||||
bat.SetPhysicalAddress(NULL);
|
||||
bat.memory_coherent = true;
|
||||
bat.protection = BAT_READ_WRITE;
|
||||
|
||||
set_ibat2(&bat);
|
||||
set_dbat2(&bat);
|
||||
isync();
|
||||
|
||||
bat.SetVirtualAddress((void *)(IOSPACE_BASE + 256 * 1024 * 1024));
|
||||
bat.SetPhysicalAddress((void *)(256 * 1024 * 1024));
|
||||
|
||||
set_ibat3(&bat);
|
||||
set_dbat3(&bat);
|
||||
isync();
|
||||
/*
|
||||
int ibats[8], dbats[8];
|
||||
|
||||
getibats(ibats);
|
||||
getdbats(dbats);
|
||||
|
||||
// use bat 2 & 3 to do this
|
||||
ibats[4] = dbats[4] = IOSPACE_BASE | BATU_LEN_256M | BATU_VS;
|
||||
ibats[5] = dbats[5] = 0x0 | BATL_MC | BATL_PP_RW;
|
||||
ibats[6] = dbats[6] = (IOSPACE_BASE + 256*1024*1024) | BATU_LEN_256M | BATU_VS;
|
||||
ibats[7] = dbats[7] = (256*1024*1024) | BATL_MC | BATL_PP_RW;
|
||||
|
||||
setibats(ibats);
|
||||
setdbats(dbats);
|
||||
*/
|
||||
|
||||
// create a region to cover the iospace
|
||||
void *temp = (void *)IOSPACE_BASE;
|
||||
vm_create_null_region(vm_get_kernel_aspace_id(), "iospace", &temp,
|
||||
REGION_ADDR_EXACT_ADDRESS, IOSPACE_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** Directly maps a page without having knowledge of any kernel structures.
|
||||
* Used only during VM setup.
|
||||
* It currently ignores the "attributes" parameter and sets all pages
|
||||
* read/write.
|
||||
*/
|
||||
|
||||
int
|
||||
vm_translation_map_quick_map(kernel_args *ka, addr_t virtualAddress, addr_t physicalAddress, uint8 attributes, addr_t (*get_free_page)(kernel_args *))
|
||||
{
|
||||
uint32 virtualSegmentID = get_sr((void *)virtualAddress) & 0xffffff;
|
||||
|
||||
uint32 hash = page_table_entry::PrimaryHash(virtualSegmentID, (uint32)virtualAddress);
|
||||
page_table_entry_group *group = &sPageTable[hash & sPageTableHashMask];
|
||||
|
||||
for (int32 i = 0; i < 8; i++) {
|
||||
// 8 entries in a group
|
||||
if (group->entry[i].valid)
|
||||
continue;
|
||||
|
||||
fill_page_table_entry(&group->entry[i], virtualSegmentID, virtualAddress, physicalAddress, PTE_READ_WRITE, false);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
hash = page_table_entry::SecondaryHash(hash);
|
||||
group = &sPageTable[hash & sPageTableHashMask];
|
||||
|
||||
for (int32 i = 0; i < 8; i++) {
|
||||
if (group->entry[i].valid)
|
||||
continue;
|
||||
|
||||
fill_page_table_entry(&group->entry[i], virtualSegmentID, virtualAddress, physicalAddress, PTE_READ_WRITE, true);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
// XXX currently assumes this translation map is active
|
||||
|
||||
int
|
||||
vm_translation_map_quick_query(addr_t va, addr_t *out_physical)
|
||||
{
|
||||
//PANIC_UNIMPLEMENTED();
|
||||
panic("vm_translation_map_quick_query(): not yet implemented\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ppc_translation_map_change_asid(vm_translation_map *map)
|
||||
{
|
||||
// this code depends on the kernel being at 0x80000000, fix if we change that
|
||||
#if KERNEL_BASE != 0x80000000
|
||||
#error fix me
|
||||
#endif
|
||||
int asid_base = map->arch_data->asid_base;
|
||||
|
||||
asm("mtsr 0,%0" :: "g"(asid_base));
|
||||
asm("mtsr 1,%0" :: "g"(asid_base+1));
|
||||
asm("mtsr 2,%0" :: "g"(asid_base+2));
|
||||
asm("mtsr 3,%0" :: "g"(asid_base+3));
|
||||
asm("mtsr 4,%0" :: "g"(asid_base+4));
|
||||
asm("mtsr 5,%0" :: "g"(asid_base+5));
|
||||
asm("mtsr 6,%0" :: "g"(asid_base+6));
|
||||
asm("mtsr 7,%0" :: "g"(asid_base+7));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user