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:
Axel Dörfler 2003-10-17 13:57:28 +00:00
parent 78a4f584f5
commit f8e89e479d
13 changed files with 1891 additions and 136 deletions

View File

@ -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
;

View File

@ -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

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View 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:

View File

@ -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;
}

View File

@ -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));
}

View File

@ -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");
}

View File

@ -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;
}

View 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)
{
}

View 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));
}