Removed unsupported architectures.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32071 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,69 +0,0 @@
|
||||
OUTPUT_FORMAT("elf32-shl", "elf32-shl", "elf32-shl")
|
||||
OUTPUT_ARCH(sh)
|
||||
|
||||
ENTRY(__start)
|
||||
SEARCH_DIR("libgcc");
|
||||
SECTIONS
|
||||
{
|
||||
. = 0xc0000000 + SIZEOF_HEADERS;
|
||||
|
||||
.interp : { *(.interp) }
|
||||
.hash : { *(.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) }
|
||||
.rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) }
|
||||
.rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) }
|
||||
.rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) }
|
||||
.rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
|
||||
.rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
|
||||
.rel.got : { *(.rel.got) }
|
||||
.rela.got : { *(.rela.got) }
|
||||
.rel.ctors : { *(.rel.ctors) }
|
||||
.rela.ctors : { *(.rela.ctors) }
|
||||
.rel.dtors : { *(.rel.dtors) }
|
||||
.rela.dtors : { *(.rela.dtors) }
|
||||
.rel.init : { *(.rel.init) }
|
||||
.rela.init : { *(.rela.init) }
|
||||
.rel.fini : { *(.rel.fini) }
|
||||
.rela.fini : { *(.rela.fini) }
|
||||
.rel.bss : { *(.rel.bss) }
|
||||
.rela.bss : { *(.rela.bss) }
|
||||
.rel.plt : { *(.rel.plt) }
|
||||
.rela.plt : { *(.rela.plt) }
|
||||
.init : { *(.init) } =0x9090
|
||||
.plt : { *(.plt) }
|
||||
|
||||
/* text/read-only data */
|
||||
.text : { *(.text .gnu.linkonce.t.*) } =0x9090
|
||||
|
||||
.rodata :
|
||||
{
|
||||
*(.rodata)
|
||||
. = ALIGN(0x1000);
|
||||
} =0x9000
|
||||
|
||||
/* writable data */
|
||||
. = ALIGN(0x1000) + (. & (0x1000 - 1));
|
||||
___data_start = .;
|
||||
.data : { *(.data .gnu.linkonce.d.*) }
|
||||
|
||||
___ctor_list = .;
|
||||
.ctors : { *(.ctors) }
|
||||
___ctor_end = .;
|
||||
___dtor_list = .;
|
||||
.dtors : { *(.dtors) }
|
||||
___dtor_end = .;
|
||||
.got : { *(.got.plt) *(.got) }
|
||||
.dynamic : { *(.dynamic) }
|
||||
|
||||
/* unintialized data (in same segment as writable data) */
|
||||
___bss_start = .;
|
||||
.bss : { *(.bss) }
|
||||
|
||||
. = ALIGN(0x1000);
|
||||
_end = . ;
|
||||
|
||||
/* Strip unnecessary stuff */
|
||||
/DISCARD/ : { *(.comment .note .eh_frame) }
|
||||
}
|
||||
@@ -1,312 +0,0 @@
|
||||
/*
|
||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
#define FUNCTION(name) .align 2 ; .globl _##name ; .type _##name,@function ; _##name
|
||||
|
||||
.text
|
||||
FUNCTION(reboot):
|
||||
mov.l disable_exceptions_addr,r1
|
||||
jsr @r1
|
||||
nop
|
||||
|
||||
mov.l reboot_vector,r0
|
||||
jmp @r0
|
||||
nop
|
||||
|
||||
FUNCTION(dbg_save_registers):
|
||||
rts
|
||||
nop
|
||||
|
||||
.align 2
|
||||
reboot_vector: .long 0xa0000000
|
||||
disable_exceptions_addr: .long _disable_exceptions
|
||||
|
||||
FUNCTION(atomic_add):
|
||||
mov.l r8,@-r15
|
||||
sts.l pr,@-r15
|
||||
|
||||
/* disable interrupts */
|
||||
mov.l disable_interrupts_addr,r1
|
||||
jsr @r1
|
||||
nop
|
||||
|
||||
/* load the value, save it, add to it, and store it back */
|
||||
mov.l @r4,r3
|
||||
mov r3,r8
|
||||
add r5,r3
|
||||
mov.l r3,@r4
|
||||
|
||||
/* restore interrupts */
|
||||
mov.l restore_interrupts_addr,r1
|
||||
jsr @r1
|
||||
mov r0,r4
|
||||
|
||||
/* return value will be old value */
|
||||
mov r8,r0
|
||||
|
||||
/* restore the stack */
|
||||
lds.l @r15+,pr
|
||||
rts
|
||||
mov.l @r15+,r8
|
||||
|
||||
FUNCTION(atomic_and):
|
||||
mov.l r8,@-r15
|
||||
sts.l pr,@-r15
|
||||
|
||||
/* disable interrupts */
|
||||
mov.l disable_interrupts_addr,r1
|
||||
jsr @r1
|
||||
nop
|
||||
|
||||
/* load the value, save it, and it, and store it back */
|
||||
mov.l @r4,r3
|
||||
mov r3,r8
|
||||
and r5,r3
|
||||
mov.l r3,@r4
|
||||
|
||||
/* restore interrupts */
|
||||
mov.l restore_interrupts_addr,r1
|
||||
jsr @r1
|
||||
mov r0,r4
|
||||
|
||||
/* return value will be old value */
|
||||
mov r8,r0
|
||||
|
||||
/* restore the stack */
|
||||
lds.l @r15+,pr
|
||||
rts
|
||||
mov.l @r15+,r8
|
||||
|
||||
FUNCTION(atomic_or):
|
||||
mov.l r8,@-r15
|
||||
sts.l pr,@-r15
|
||||
|
||||
/* disable interrupts */
|
||||
mov.l disable_interrupts_addr,r1
|
||||
jsr @r1
|
||||
nop
|
||||
|
||||
/* load the value, save it, or it, and store it back */
|
||||
mov.l @r4,r3
|
||||
mov r3,r8
|
||||
or r5,r3
|
||||
mov.l r3,@r4
|
||||
|
||||
/* restore interrupts */
|
||||
mov.l restore_interrupts_addr,r1
|
||||
jsr @r1
|
||||
mov r0,r4
|
||||
|
||||
/* return value will be old value */
|
||||
mov r8,r0
|
||||
|
||||
/* restore the stack */
|
||||
lds.l @r15+,pr
|
||||
rts
|
||||
mov.l @r15+,r8
|
||||
|
||||
FUNCTION(atomic_set):
|
||||
mov.l r8,@-r15
|
||||
sts.l pr,@-r15
|
||||
|
||||
/* disable interrupts */
|
||||
mov.l disable_interrupts_addr,r1
|
||||
jsr @r1
|
||||
nop
|
||||
|
||||
/* load the value, save it, and store the new value */
|
||||
mov.l @r4,r8
|
||||
mov.l r5,@r4
|
||||
|
||||
/* restore interrupts */
|
||||
mov.l restore_interrupts_addr,r1
|
||||
jsr @r1
|
||||
mov r0,r4
|
||||
|
||||
/* return value will be old value */
|
||||
mov r8,r0
|
||||
|
||||
/* restore the stack */
|
||||
lds.l @r15+,pr
|
||||
rts
|
||||
mov.l @r15+,r8
|
||||
|
||||
/* int test_and_set(int *val, int set_to, int test_val) */
|
||||
FUNCTION(test_and_set):
|
||||
mov.l r8,@-r15
|
||||
sts.l pr,@-r15
|
||||
|
||||
/* disable interrupts */
|
||||
mov.l disable_interrupts_addr,r1
|
||||
jsr @r1
|
||||
nop
|
||||
|
||||
/* load the value, save it, and store the new value */
|
||||
mov.l @r4,r8 /* load the dest, it will be the return value */
|
||||
cmp/eq r8,r6 /* compare against the test_val */
|
||||
bf _not_equal
|
||||
|
||||
mov.l r5,@r4 /* put the set_to value into the target */
|
||||
|
||||
_not_equal:
|
||||
/* restore interrupts */
|
||||
mov.l restore_interrupts_addr,r1
|
||||
jsr @r1
|
||||
mov r0,r4
|
||||
|
||||
/* return value will be old value */
|
||||
mov r8,r0
|
||||
|
||||
/* restore the stack */
|
||||
lds.l @r15+,pr
|
||||
rts
|
||||
mov.l @r15+,r8
|
||||
|
||||
.align 2
|
||||
disable_interrupts_addr: .long _arch_int_disable_interrupts
|
||||
restore_interrupts_addr: .long _arch_int_restore_interrupts
|
||||
|
||||
FUNCTION(disable_exceptions):
|
||||
mov.l bl_bit_mask,r0
|
||||
stc sr,r1
|
||||
or r0,r1
|
||||
ldc r1,sr /* turn off interrupts/exceptions */
|
||||
rts
|
||||
nop
|
||||
|
||||
FUNCTION(enable_exceptions):
|
||||
mov.l bl_bit_mask,r0
|
||||
not r0,r0
|
||||
stc sr,r1
|
||||
and r0,r1
|
||||
ldc r1,sr
|
||||
rts
|
||||
nop
|
||||
|
||||
.align 2
|
||||
bl_bit_mask: .long 0x10000000
|
||||
|
||||
FUNCTION(arch_int_restore_interrupts):
|
||||
mov.l inverse_imask_bit_mask,r0
|
||||
stc sr,r1 /* get the sr register */
|
||||
and r0,r1 /* zero out the imask part */
|
||||
or r4,r1 /* or in the passed in imask, should only contain imask bits */
|
||||
ldc r1,sr /* put the new status into the sr register */
|
||||
rts
|
||||
nop
|
||||
|
||||
FUNCTION(arch_int_enable_interrupts):
|
||||
mov.l inverse_imask_bit_mask,r0
|
||||
stc sr,r1 /* load the sr register */
|
||||
and r0,r1 /* set the imask to 0 */
|
||||
ldc r1,sr /* put the new status into the sr register */
|
||||
rts
|
||||
nop
|
||||
|
||||
.align 2
|
||||
inverse_imask_bit_mask: .long 0xffffff0f
|
||||
|
||||
FUNCTION(arch_int_disable_interrupts):
|
||||
mov.l imask_bit_mask,r2
|
||||
stc sr,r1 /* load the sr register */
|
||||
mov r1,r0 /* save the old sr register */
|
||||
or r2,r1 /* or in 0xf for the imask */
|
||||
ldc r1,sr /* set the new sr register with the interrupts masked */
|
||||
rts
|
||||
and r2,r0 /* make sure the return value contains only the imask part */
|
||||
|
||||
FUNCTION(arch_int_is_interrupts_enabled):
|
||||
mov.l imask_bit_mask,r2
|
||||
stc sr,r0 /* load the sr register */
|
||||
and r2,r0 /* mask out just the interrupt level */
|
||||
cmp/eq #0,r0 /* check for zero */
|
||||
bt _ints_is_enabled
|
||||
nop
|
||||
|
||||
rts
|
||||
mov #0,r0 /* return false */
|
||||
|
||||
_ints_is_enabled:
|
||||
rts
|
||||
mov #1,r0 /* return true */
|
||||
|
||||
.align 2
|
||||
imask_bit_mask: .long 0x000000f0
|
||||
|
||||
FUNCTION(get_sr):
|
||||
stc sr,r0
|
||||
rts
|
||||
nop
|
||||
|
||||
FUNCTION(get_fpscr):
|
||||
sts fpscr,r0
|
||||
rts
|
||||
nop
|
||||
|
||||
// void sh4_context_switch(unsigned int **old_esp, unsigned int *new_esp);
|
||||
FUNCTION(sh4_context_switch):
|
||||
fmov.s fr12,@-r15
|
||||
fmov.s fr13,@-r15
|
||||
fmov.s fr14,@-r15
|
||||
fmov.s fr15,@-r15
|
||||
sts.l fpscr,@-r15
|
||||
sts.l mach,@-r15
|
||||
sts.l macl,@-r15
|
||||
mov.l r8,@-r15
|
||||
mov.l r9,@-r15
|
||||
mov.l r10,@-r15
|
||||
mov.l r11,@-r15
|
||||
mov.l r12,@-r15
|
||||
mov.l r13,@-r15
|
||||
mov.l r14,@-r15
|
||||
sts.l pr,@-r15
|
||||
|
||||
mov.l r15,@r4
|
||||
mov r5,r15
|
||||
|
||||
lds.l @r15+,pr
|
||||
mov.l @r15+,r14
|
||||
mov.l @r15+,r13
|
||||
mov.l @r15+,r12
|
||||
mov.l @r15+,r11
|
||||
mov.l @r15+,r10
|
||||
mov.l @r15+,r9
|
||||
mov.l @r15+,r8
|
||||
lds.l @r15+,macl
|
||||
lds.l @r15+,mach
|
||||
lds.l @r15+,fpscr
|
||||
fmov.s @r15+,fr15
|
||||
fmov.s @r15+,fr14
|
||||
fmov.s @r15+,fr13
|
||||
fmov.s @r15+,fr12
|
||||
|
||||
rts
|
||||
nop
|
||||
|
||||
FUNCTION(sh4_function_caller):
|
||||
_fc_loop:
|
||||
mov.l @r15+,r2
|
||||
jsr @r2
|
||||
nop
|
||||
bra _fc_loop
|
||||
nop
|
||||
|
||||
// void sh4_switch_stack_and_call(addr stack, void (*func)(void *), void *arg);
|
||||
FUNCTION(sh4_switch_stack_and_call):
|
||||
mov r4,r15
|
||||
jsr @r5
|
||||
mov r6,r4
|
||||
|
||||
// void sh4_enter_uspace(addr entry, void *args, addr ustack_top);
|
||||
FUNCTION(sh4_enter_uspace):
|
||||
ldc r4,spc // load the program counter it will switch to
|
||||
mov r5,r4 // load the args
|
||||
mov r6,r15 // restore the user stack
|
||||
mov.l uspace_sr,r0
|
||||
ldc r0,ssr
|
||||
rte
|
||||
nop
|
||||
|
||||
uspace_sr: .long 0x00000000
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
/*
|
||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#include <ktypes.h>
|
||||
#include <user_atomic.h>
|
||||
|
||||
// The code below does only work on single CPU SH4 systems.
|
||||
// Interrupts must be disabled during execution, too.
|
||||
|
||||
int32
|
||||
_user_atomic_add(vint32 *uval, int32 incr)
|
||||
{
|
||||
int32 val;
|
||||
int32 ret;
|
||||
|
||||
if ((addr)uval >= KERNEL_BASE && (addr)uval <= KERNEL_TOP)
|
||||
goto error;
|
||||
|
||||
if (user_memcpy(&val, (int32 *)uval, sizeof(val)) < 0)
|
||||
goto error;
|
||||
|
||||
ret = val;
|
||||
val += incr;
|
||||
|
||||
if (user_memcpy((int32 *)uval, &val, sizeof(val)) < 0)
|
||||
goto error;
|
||||
|
||||
return ret;
|
||||
|
||||
error:
|
||||
// XXX kill the app
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
_user_atomic_and(vint32 *uval, int32 incr)
|
||||
{
|
||||
int val;
|
||||
int ret;
|
||||
|
||||
if ((addr)uval >= KERNEL_BASE && (addr)uval <= KERNEL_TOP)
|
||||
goto error;
|
||||
|
||||
if (user_memcpy(&val, (int32 *)uval, sizeof(val)) < 0)
|
||||
goto error;
|
||||
|
||||
ret = val;
|
||||
val &= incr;
|
||||
|
||||
if (user_memcpy((int32 *)uval, &val, sizeof(val)) < 0)
|
||||
goto error;
|
||||
|
||||
return ret;
|
||||
|
||||
error:
|
||||
// XXX kill the app
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
_user_atomic_or(vint32 *uval, int32 incr)
|
||||
{
|
||||
int val;
|
||||
int ret;
|
||||
|
||||
if ((addr)uval >= KERNEL_BASE && (addr)uval <= KERNEL_TOP)
|
||||
goto error;
|
||||
|
||||
if (user_memcpy(&val, (int32 *)uval, sizeof(val)) < 0)
|
||||
goto error;
|
||||
|
||||
ret = val;
|
||||
val |= incr;
|
||||
|
||||
if (user_memcpy((int32 *)uval, &val, sizeof(val)) < 0)
|
||||
goto error;
|
||||
|
||||
return ret;
|
||||
|
||||
error:
|
||||
// XXX kill the app
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
_user_atomic_set(vint32 *uval, int32 set_to)
|
||||
{
|
||||
int val;
|
||||
int ret;
|
||||
|
||||
if ((addr)uval >= KERNEL_BASE && (addr)uval <= KERNEL_TOP)
|
||||
goto error;
|
||||
|
||||
if (user_memcpy(&val, (int32 *)uval, sizeof(val)) < 0)
|
||||
goto error;
|
||||
|
||||
ret = val;
|
||||
val = set_to;
|
||||
|
||||
if (user_memcpy((int32 *)uval, &val, sizeof(val)) < 0)
|
||||
goto error;
|
||||
|
||||
return ret;
|
||||
|
||||
error:
|
||||
// XXX kill the app
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
_user_atomic_test_and_set(vint32 *uval, int32 set_to, int32 test_val)
|
||||
{
|
||||
int val;
|
||||
int ret;
|
||||
|
||||
if ((addr)uval >= KERNEL_BASE && (addr)uval <= KERNEL_TOP)
|
||||
goto error;
|
||||
|
||||
if (user_memcpy(&val, (int32 *)uval, sizeof(val)) < 0)
|
||||
goto error;
|
||||
|
||||
ret = val;
|
||||
if (val == test_val) {
|
||||
val = set_to;
|
||||
if (user_memcpy((int32 *)uval, &val, sizeof(val)) < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
error:
|
||||
// XXX kill the app
|
||||
return -1;
|
||||
}
|
||||
@@ -1,173 +0,0 @@
|
||||
/*
|
||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
|
||||
#include <kernel/arch/cpu.h>
|
||||
#include <kernel/debug.h>
|
||||
#include <kernel/int.h>
|
||||
#include <boot/stage2.h>
|
||||
|
||||
static vcpu_struct *vcpu;
|
||||
|
||||
|
||||
int
|
||||
arch_cpu_preboot_init(kernel_args *ka)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
arch_cpu_init(kernel_args *ka)
|
||||
{
|
||||
vcpu = ka->arch_args.vcpu;
|
||||
|
||||
vcpu->kernel_asid = 0;
|
||||
vcpu->user_asid = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
arch_cpu_init2(kernel_args *ka)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sh4_set_kstack(addr kstack)
|
||||
{
|
||||
// dprintf("sh4_set_kstack: setting kstack to 0x%x\n", kstack);
|
||||
vcpu->kstack = (unsigned int *)kstack;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sh4_set_user_pgdir(addr pgdir)
|
||||
{
|
||||
// dprintf("sh4_set_user_pgdir: setting pgdir to 0x%x\n", pgdir);
|
||||
if((addr)vcpu->user_pgdir != pgdir)
|
||||
arch_cpu_global_TLB_invalidate();
|
||||
vcpu->user_pgdir = (unsigned int *)pgdir;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sh4_invl_page(addr va)
|
||||
{
|
||||
int state;
|
||||
int i;
|
||||
|
||||
va = ROUNDOWN(va, PAGE_SIZE);
|
||||
|
||||
state = int_disable_interrupts();
|
||||
|
||||
// wipe it out of the data tlbs
|
||||
for(i=0; i<UTLB_COUNT; i++) {
|
||||
struct utlb_addr_array *ua = (struct utlb_addr_array *)(UTLB + (i << UTLB_ADDR_SHIFT));
|
||||
if(ua->vpn == (va >> 10))
|
||||
ua->valid = 0;
|
||||
}
|
||||
|
||||
// wipe it out of the instruction tlbs
|
||||
for(i=0; i<ITLB_COUNT; i++) {
|
||||
struct itlb_addr_array *ia = (struct itlb_addr_array *)(ITLB + (i << ITLB_ADDR_SHIFT));
|
||||
if(ia->vpn == (va >> 10))
|
||||
ia->valid = 0;
|
||||
}
|
||||
|
||||
int_restore_interrupts(state);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
arch_cpu_invalidate_TLB_range(addr start, addr end)
|
||||
{
|
||||
int num_pages = end/PAGE_SIZE - start/PAGE_SIZE;
|
||||
while ( num_pages-- >= 0 ) {
|
||||
sh4_invl_page(start);
|
||||
start += PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
arch_cpu_invalidate_TLB_list(addr pages[], int num_pages)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<num_pages; i++) {
|
||||
sh4_invl_page(pages[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
arch_cpu_global_TLB_invalidate()
|
||||
{
|
||||
int state;
|
||||
int i;
|
||||
|
||||
state = int_disable_interrupts();
|
||||
|
||||
// wipe out the data tlbs
|
||||
for(i=0; i<UTLB_COUNT; i++) {
|
||||
struct utlb_addr_array *ua = (struct utlb_addr_array *)(UTLB + (i << UTLB_ADDR_SHIFT));
|
||||
ua->valid = 0;
|
||||
}
|
||||
|
||||
// wipe out the instruction tlbs
|
||||
for(i=0; i<ITLB_COUNT; i++) {
|
||||
struct itlb_addr_array *ia = (struct itlb_addr_array *)(ITLB + (i << ITLB_ADDR_SHIFT));
|
||||
ia->valid = 0;
|
||||
}
|
||||
|
||||
int_restore_interrupts(state);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr *fault_handler)
|
||||
{
|
||||
char *tmp = (char *)to;
|
||||
char *s = (char *)from;
|
||||
|
||||
*fault_handler = (addr)&&error;
|
||||
|
||||
while(size--)
|
||||
*tmp++ = *s++;
|
||||
|
||||
*fault_handler = 0;
|
||||
|
||||
return 0;
|
||||
error:
|
||||
*fault_handler = 0;
|
||||
return ERR_VM_BAD_USER_MEMORY;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
arch_cpu_user_memset(void *s, char c, size_t count, addr *fault_handler)
|
||||
{
|
||||
char *xs = (char *) s;
|
||||
|
||||
*fault_handler = (addr)&&error;
|
||||
|
||||
while (count--)
|
||||
*xs++ = c;
|
||||
|
||||
*fault_handler = 0;
|
||||
|
||||
return 0;
|
||||
error:
|
||||
*fault_handler = 0;
|
||||
return ERR_VM_BAD_USER_MEMORY;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
arch_cpu_idle(void)
|
||||
{
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
#include <kernel/kernel.h>
|
||||
#include <boot/stage2.h>
|
||||
|
||||
#include <kernel/arch/dbg_console.h>
|
||||
|
||||
int arch_dbg_con_init(kernel_args *ka)
|
||||
{
|
||||
volatile uint16 *scif16 = (uint16*)0xffe80000;
|
||||
volatile uint8 *scif8 = (uint8*)0xffe80000;
|
||||
int x;
|
||||
|
||||
/* Disable interrupts, transmit/receive, and use internal clock */
|
||||
scif16[8/2] = 0;
|
||||
|
||||
/* 8N1, use P0 clock */
|
||||
scif16[0] = 0;
|
||||
|
||||
/* Set baudrate, N = P0/(32*B)-1 */
|
||||
// scif8[4] = (50000000 / (32 * baud_rate)) - 1;
|
||||
|
||||
// scif8[4] = 80; // 19200
|
||||
// scif8[4] = 40; // 38400
|
||||
// scif8[4] = 26; // 57600
|
||||
scif8[4] = 13; // 115200
|
||||
|
||||
/* Reset FIFOs, enable hardware flow control */
|
||||
scif16[24/2] = 4; //12;
|
||||
|
||||
for(x = 0; x < 100000; x++);
|
||||
scif16[24/2] = 0; //8;
|
||||
|
||||
/* Disable manual pin control */
|
||||
scif16[32/2] = 0;
|
||||
|
||||
/* Clear status */
|
||||
scif16[16/2] = 0x60;
|
||||
scif16[36/2] = 0;
|
||||
|
||||
/* Enable transmit/receive */
|
||||
scif16[8/2] = 0x30;
|
||||
|
||||
for(x = 0; x < 100000; x++);
|
||||
|
||||
arch_dbg_con_puts("serial initted\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char arch_dbg_con_read()
|
||||
{
|
||||
volatile uint16 *status = (uint16*)0xffe8001c;
|
||||
volatile uint16 *ack = (uint16*)0xffe80010;
|
||||
volatile uint8 *fifo = (uint8*)0xffe80014;
|
||||
char c;
|
||||
|
||||
/* Check input FIFO */
|
||||
while ((*status & 0x1f) == 0);
|
||||
|
||||
/* Get the input char */
|
||||
c = *fifo;
|
||||
|
||||
/* Ack */
|
||||
*ack &= 0x6d;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Flush all FIFO'd bytes out of the serial port buffer */
|
||||
static void arch_dbg_con_flush() {
|
||||
volatile uint16 *ack = (uint16*)0xffe80010;
|
||||
|
||||
*ack &= 0xbf;
|
||||
while (!(*ack & 0x40))
|
||||
;
|
||||
*ack &= 0xbf;
|
||||
}
|
||||
|
||||
static void _arch_dbg_con_putch(const char c)
|
||||
{
|
||||
volatile uint16 *ack = (uint16*)0xffe80010;
|
||||
volatile uint8 *fifo = (uint8*)0xffe8000c;
|
||||
|
||||
/* Wait until the transmit buffer has space */
|
||||
while (!(*ack & 0x20))
|
||||
;
|
||||
/* Send the char */
|
||||
*fifo = c;
|
||||
|
||||
/* Clear status */
|
||||
*ack &= 0x9f;
|
||||
}
|
||||
|
||||
char arch_dbg_con_putch(const char c)
|
||||
{
|
||||
if (c == '\n') {
|
||||
_arch_dbg_con_putch('\r');
|
||||
_arch_dbg_con_putch('\n');
|
||||
} else if (c != '\r')
|
||||
_arch_dbg_con_putch(c);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void arch_dbg_con_puts(const char *s)
|
||||
{
|
||||
while(*s != '\0') {
|
||||
arch_dbg_con_putch(*s);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
/*
|
||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
#include <kernel/kernel.h>
|
||||
#include <kernel/debug.h>
|
||||
#include <kernel/arch/debug.h>
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
/*
|
||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
#include <boot/stage2.h>
|
||||
|
||||
int arch_faults_init(kernel_args *ka)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
/*
|
||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
#include <boot/stage2.h>
|
||||
#include <arch/sh4/vcpu.h>
|
||||
#include <arch/sh4/sh4.h>
|
||||
|
||||
#include <kernel/debug.h>
|
||||
#include <kernel/int.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <kernel/vm_priv.h>
|
||||
#include <kernel/faults_priv.h>
|
||||
#include <kernel/syscalls.h>
|
||||
|
||||
#include <kernel/arch/sh4/cpu.h>
|
||||
|
||||
#define MAX_ARGS 16
|
||||
|
||||
struct vector *vector_table;
|
||||
|
||||
void arch_int_enable_io_interrupt(int irq)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void arch_int_disable_io_interrupt(int irq)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static int sh4_handle_exception(void *_frame)
|
||||
//static int sh4_handle_exception(unsigned int code, unsigned int pc, unsigned int trap, unsigned int page_fault_addr)
|
||||
{
|
||||
struct iframe *frame = (struct iframe *)_frame;
|
||||
int ret;
|
||||
|
||||
// NOTE: not safe to do anything that may involve the FPU before
|
||||
// it is certain it is not an fpu exception
|
||||
|
||||
// dprintf("sh4_handle_exception: frame 0x%x code 0x%x, pc 0x%x, ssr 0x%x, sr 0x%x, pr 0x%x\n",
|
||||
// frame, frame->excode, frame->spc, frame->ssr, get_sr(), frame->pr);
|
||||
// dprintf("regs: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
|
||||
// frame->r0, frame->r1, frame->r2, frame->r3, frame->r4, frame->r5, frame->r6, frame->r7,
|
||||
// frame->r8, frame->r9, frame->r10, frame->r11, frame->r12, frame->r13, frame->r14, frame->sgr);
|
||||
switch(frame->excode) {
|
||||
case 0: // reset
|
||||
case 1: // manual reset
|
||||
case 5: // TLB protection violation (read)
|
||||
case 6: // TLB protection violation (write)
|
||||
case 7: // data address error (read)
|
||||
case 8: // data address error (write)
|
||||
case 10: // TLB multi hit
|
||||
case 12: // illegal instruction
|
||||
case 13: // slot illegal instruction
|
||||
dprintf("about to gpf at pc 0x%x, excode %d\n", frame->spc, frame->excode);
|
||||
ret = general_protection_fault(frame->excode);
|
||||
break;
|
||||
case 11: { // TRAPA
|
||||
/*
|
||||
** arg layout:
|
||||
** r4-r7: arg 1 - 4
|
||||
** r0-r3: arg 5 - 8
|
||||
** r8-r13: arg 8 - 13
|
||||
*/
|
||||
unsigned int *trap = (unsigned int *)0xff000020;
|
||||
uint64 retcode;
|
||||
unsigned int args[MAX_ARGS];
|
||||
|
||||
int_enable_interrupts();
|
||||
|
||||
thread_atkernel_entry();
|
||||
|
||||
// XXX redo this to be stack-based
|
||||
args[0] = frame->r4;
|
||||
args[1] = frame->r5;
|
||||
args[2] = frame->r6;
|
||||
args[3] = frame->r7;
|
||||
args[4] = frame->r0;
|
||||
args[5] = frame->r1;
|
||||
args[6] = frame->r2;
|
||||
args[7] = frame->r3;
|
||||
args[8] = frame->r8;
|
||||
|
||||
ret = syscall_dispatcher(*trap >> 2, args, &retcode);
|
||||
frame->r0 = retcode & 0xffffffff;
|
||||
frame->r1 = retcode >> 32;
|
||||
break;
|
||||
}
|
||||
case 9: { // FPU exception
|
||||
int fpu_fault_code;
|
||||
switch(frame->fpscr & 0x0003f000) {
|
||||
case 0x1000:
|
||||
fpu_fault_code = FPU_FAULT_CODE_INEXACT;
|
||||
break;
|
||||
case 0x2000:
|
||||
fpu_fault_code = FPU_FAULT_CODE_UNDERFLOW;
|
||||
break;
|
||||
case 0x4000:
|
||||
fpu_fault_code = FPU_FAULT_CODE_OVERFLOW;
|
||||
break;
|
||||
case 0x8000:
|
||||
fpu_fault_code = FPU_FAULT_CODE_DIVBYZERO;
|
||||
break;
|
||||
case 0x10000:
|
||||
fpu_fault_code = FPU_FAULT_CODE_INVALID_OP;
|
||||
break;
|
||||
case 0x20000:
|
||||
fpu_fault_code = FPU_FAULT_CODE_UNKNOWN;
|
||||
break;
|
||||
default:
|
||||
// XXX handle better
|
||||
fpu_fault_code = FPU_FAULT_CODE_UNKNOWN;
|
||||
}
|
||||
ret = fpu_fault(fpu_fault_code);
|
||||
break;
|
||||
}
|
||||
case 64: // FPU disable exception
|
||||
case 65: // Slot FPU disable exception
|
||||
ret = fpu_disable_fault();
|
||||
break;
|
||||
case EXCEPTION_PAGE_FAULT_READ:
|
||||
case EXCEPTION_PAGE_FAULT_WRITE: {
|
||||
addr newip;
|
||||
if((frame->ssr & 0x000000f0) == 0) {
|
||||
// dprintf("page_fault: enabling interrupts\n");
|
||||
int_enable_interrupts();
|
||||
}
|
||||
ret = vm_page_fault(frame->page_fault_addr, frame->spc,
|
||||
frame->excode == EXCEPTION_PAGE_FAULT_WRITE, (frame->ssr & 0x40000000) == 0, &newip);
|
||||
if(newip != 0)
|
||||
frame->spc = newip;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ret = int_io_interrupt_handler(frame->excode);
|
||||
}
|
||||
if(ret == INT_RESCHEDULE) {
|
||||
int state = int_disable_interrupts();
|
||||
GRAB_THREAD_LOCK();
|
||||
thread_resched();
|
||||
RELEASE_THREAD_LOCK();
|
||||
int_restore_interrupts(state);
|
||||
}
|
||||
if(!(frame->ssr & 0x40000000) || (frame->excode == 11)) {
|
||||
thread_atkernel_exit();
|
||||
}
|
||||
|
||||
// dprintf("sh4_handle_exception: exit\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arch_int_init(kernel_args *ka)
|
||||
{
|
||||
int i;
|
||||
|
||||
dprintf("arch_int_init: entry\n");
|
||||
|
||||
vector_table = (struct vector *)ka->arch_args.vcpu->vt;
|
||||
dprintf("arch_int_init: vector table 0x%x\n", vector_table);
|
||||
|
||||
// set up the vectors
|
||||
// handle all of them
|
||||
for(i=0; i<256; i++)
|
||||
vector_table[i].func = &sh4_handle_exception;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arch_int_init2(kernel_args *ka)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,151 +0,0 @@
|
||||
/*
|
||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
#include <kernel/kernel.h>
|
||||
#include <kernel/vm.h>
|
||||
#include <kernel/vm_priv.h>
|
||||
#include <kernel/debug.h>
|
||||
|
||||
#include <kernel/arch/pmap.h>
|
||||
|
||||
#include <boot/stage2.h>
|
||||
#include <arch/sh4/sh4.h>
|
||||
#include <arch/sh4/vcpu.h>
|
||||
|
||||
#include <nulibc/string.h>
|
||||
|
||||
#define CHATTY_PMAP 0
|
||||
|
||||
static vcpu_struct *vcpu;
|
||||
|
||||
#define PHYS_TO_P1(x) ((x) + P1_AREA)
|
||||
|
||||
int arch_pmap_init(kernel_args *ka)
|
||||
{
|
||||
dprintf("arch_pmap_init: entry\n");
|
||||
|
||||
vcpu = ka->arch_args.vcpu;
|
||||
|
||||
dprintf("examining vcpu structure @ 0x%x:\n", vcpu);
|
||||
dprintf("kernel_pgdir = 0x%x\n", vcpu->kernel_pgdir);
|
||||
dprintf("user_pgdir = 0x%x\n", vcpu->user_pgdir);
|
||||
dprintf("kernel_asid = 0x%x\n", vcpu->kernel_asid);
|
||||
dprintf("user_asid = 0x%x\n", vcpu->user_asid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arch_pmap_init2(kernel_args *ka)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pmap_map_page(addr paddr, addr vaddr, int lock)
|
||||
{
|
||||
struct pdent *pd = NULL;
|
||||
struct ptent *pt;
|
||||
unsigned int index = 0;
|
||||
|
||||
#if CHATTY_PMAP
|
||||
dprintf("pmap_map_page: entry paddr 0x%x vaddr 0x%x lock 0x%x\n", paddr, vaddr, lock);
|
||||
#endif
|
||||
|
||||
if(vaddr < P1_AREA) {
|
||||
pd = (struct pdent *)vcpu->user_pgdir;
|
||||
index = vaddr >> 22;
|
||||
} else if(vaddr >= P3_AREA && vaddr < P4_AREA) {
|
||||
pd = (struct pdent *)vcpu->kernel_pgdir;
|
||||
index = (vaddr & 0x7fffffff) >> 22;
|
||||
} else {
|
||||
// invalid area to map pages
|
||||
panic("pmap_map_page: invalid vaddr 0x%x\n", vaddr);
|
||||
}
|
||||
|
||||
if(pd[index].v == 0) {
|
||||
// need to allocate a pagetable
|
||||
unsigned int pgtable;
|
||||
|
||||
// get a free page for a pagetable
|
||||
vm_get_free_page(&pgtable);
|
||||
pgtable *= PAGE_SIZE;
|
||||
|
||||
// zero out the page
|
||||
memset((void *)PHYS_TO_P1(pgtable), 0, PAGE_SIZE);
|
||||
|
||||
// stick it in the page dir
|
||||
pd[index].ppn = pgtable >> 12;
|
||||
pd[index].v = 1;
|
||||
}
|
||||
|
||||
// get the pagetable
|
||||
pt = (struct ptent *)PHYS_TO_P1(pd[index].ppn << 12);
|
||||
index = (vaddr >> 12) & 0x000003ff;
|
||||
|
||||
// insert the mapping
|
||||
pt[index].wt = 0;
|
||||
pt[index].pr = (lock & LOCK_KERNEL) ? (lock & 0x1) : (lock | 0x2);
|
||||
pt[index].ppn = paddr >> 12;
|
||||
pt[index].tlb_ent = 0;
|
||||
pt[index].c = 1;
|
||||
pt[index].sz = 0x1; // 4k page
|
||||
pt[index].sh = 0; // XXX shared?
|
||||
pt[index].d = 0;
|
||||
pt[index].v = 1;
|
||||
|
||||
arch_pmap_invl_page(vaddr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pmap_unmap_page(addr vaddr)
|
||||
{
|
||||
panic("pmap_unmap_page unimplemented!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void arch_pmap_invl_page(addr vaddr)
|
||||
{
|
||||
#if CHATTY_PMAP
|
||||
dprintf("arch_pmap_invl_page: vaddr 0x%x\n", vaddr);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
int pmap_get_page_mapping(addr vaddr, addr *paddr)
|
||||
{
|
||||
struct pdent *pd = NULL;
|
||||
struct ptent *pt;
|
||||
unsigned int index = 0;
|
||||
|
||||
if(vaddr < P1_AREA) {
|
||||
pd = (struct pdent *)vcpu->user_pgdir;
|
||||
index = vaddr >> 22;
|
||||
} else if(vaddr >= P3_AREA && vaddr < P4_AREA) {
|
||||
pd = (struct pdent *)vcpu->kernel_pgdir;
|
||||
index = (vaddr & 0x7fffffff) >> 22;
|
||||
} else if(vaddr >= P1_AREA && vaddr < P2_AREA) {
|
||||
// this region is identity mapped with a shift
|
||||
*paddr = vaddr - P1_AREA;
|
||||
return 0;
|
||||
} else if(vaddr >= P2_AREA && vaddr < P3_AREA) {
|
||||
// this region is identity mapped with a shift
|
||||
*paddr = vaddr - P2_AREA;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(pd[index].v == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// get the pagetable
|
||||
pt = (struct ptent *)PHYS_TO_P1(pd[index].ppn << 12);
|
||||
index = (vaddr >> 12) & 0x000003ff;
|
||||
|
||||
if(pt[index].v == 0) {
|
||||
return -1;
|
||||
}
|
||||
*paddr = pt[index].ppn << 12;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
#include <kernel/debug.h>
|
||||
#include <kernel/arch/smp.h>
|
||||
|
||||
int arch_smp_init(kernel_args *ka)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arch_smp_get_current_cpu()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void arch_smp_send_ici(int target_cpu)
|
||||
{
|
||||
panic("called arch_smp_send_ici!\n");
|
||||
}
|
||||
|
||||
void arch_smp_send_broadcast_ici()
|
||||
{
|
||||
panic("called arch_smp_send_broadcast_ici\n");
|
||||
}
|
||||
|
||||
@@ -1,134 +0,0 @@
|
||||
/*
|
||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
#include <kernel/kernel.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <kernel/debug.h>
|
||||
#include <kernel/int.h>
|
||||
#include <kernel/vm_priv.h>
|
||||
#include <kernel/arch/cpu.h>
|
||||
#include <nulibc/string.h>
|
||||
|
||||
static struct thread *curr_thread = NULL;
|
||||
|
||||
int arch_proc_init_proc_struct(struct proc *p, bool kernel)
|
||||
{
|
||||
#if 0
|
||||
if(!kernel) {
|
||||
unsigned int page;
|
||||
if(vm_get_free_page(&page) < 0) {
|
||||
panic("arch_proc_init_proc_struct: could not find free frame for page dir\n");
|
||||
}
|
||||
p->arch_info.pgdir = (unsigned int *)PHYS_ADDR_TO_P1(page * PAGE_SIZE);
|
||||
memset(p->arch_info.pgdir, 0, PAGE_SIZE);
|
||||
} else {
|
||||
p->arch_info.pgdir = NULL;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arch_thread_init_thread_struct(struct thread *t)
|
||||
{
|
||||
t->arch_info.sp = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arch_thread_initialize_kthread_stack(struct thread *t, int (*start_func)(void), void (*entry_func)(void), void (*exit_func)(void))
|
||||
{
|
||||
unsigned int *kstack = (unsigned int *)t->kernel_stack_base;
|
||||
unsigned int kstack_size = KSTACK_SIZE;
|
||||
unsigned int *kstack_top = kstack + kstack_size / sizeof(unsigned int);
|
||||
int i;
|
||||
|
||||
// clear the kernel stack
|
||||
memset(kstack, 0, kstack_size);
|
||||
|
||||
// set the final return address to be thread_kthread_exit
|
||||
kstack_top--;
|
||||
*kstack_top = (unsigned int)exit_func;
|
||||
|
||||
// set the return address to be the start of the first function
|
||||
kstack_top--;
|
||||
*kstack_top = (unsigned int)start_func;
|
||||
|
||||
// set the return address to be the start of the entry (thread setup) function
|
||||
kstack_top--;
|
||||
*kstack_top = (unsigned int)entry_func;
|
||||
|
||||
// simulate the important registers being pushed
|
||||
for(i=0; i<7+2+5; i++) {
|
||||
kstack_top--;
|
||||
*kstack_top = 0;
|
||||
}
|
||||
|
||||
// set the address of the function caller function
|
||||
// that will in turn call all of the above functions
|
||||
// pushed onto the stack
|
||||
kstack_top--;
|
||||
*kstack_top = (unsigned int)sh4_function_caller;
|
||||
|
||||
// save the sp
|
||||
t->arch_info.sp = kstack_top;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void arch_thread_context_switch(struct thread *t_from, struct thread *t_to)
|
||||
{
|
||||
#if 0
|
||||
int i;
|
||||
dprintf("arch_thread_context_switch: 0x%x->0x%x to sp 0x%x\n",
|
||||
t_from->id, t_to->id, t_to->arch_info.sp);
|
||||
#endif
|
||||
#if 0
|
||||
for(i=0; i<8; i++) {
|
||||
dprintf("sp[%d] = 0x%x\n", i, t_to->arch_info.sp[i]);
|
||||
}
|
||||
#endif
|
||||
sh4_set_kstack(t_to->kernel_stack_base + KSTACK_SIZE);
|
||||
|
||||
if(t_to->proc->aspace != NULL) {
|
||||
sh4_set_user_pgdir(vm_translation_map_get_pgdir(&t_to->proc->aspace->translation_map));
|
||||
} else {
|
||||
sh4_set_user_pgdir(NULL);
|
||||
}
|
||||
sh4_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: 0x%x\n", at->sp);
|
||||
}
|
||||
|
||||
void arch_thread_enter_uspace(addr entry, void *args, addr ustack_top)
|
||||
{
|
||||
dprintf("arch_thread_entry_uspace: entry 0x%x, ustack_top 0x%x\n",
|
||||
entry, ustack_top);
|
||||
|
||||
int_disable_interrupts();
|
||||
|
||||
sh4_set_kstack(thread_get_current_thread()->kernel_stack_base + KSTACK_SIZE);
|
||||
|
||||
sh4_enter_uspace(entry, args, ustack_top - 4);
|
||||
// never get to here
|
||||
}
|
||||
|
||||
void arch_thread_switch_kstack_and_call(struct thread *t, addr new_kstack, void (*func)(void *), void *arg)
|
||||
{
|
||||
sh4_switch_stack_and_call(new_kstack, func, arg);
|
||||
}
|
||||
|
||||
struct thread *arch_thread_get_current_thread(void)
|
||||
{
|
||||
return curr_thread;
|
||||
}
|
||||
|
||||
void arch_thread_set_current_thread(struct thread *t)
|
||||
{
|
||||
curr_thread = t;
|
||||
}
|
||||
|
||||
@@ -1,147 +0,0 @@
|
||||
/*
|
||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
#include <kernel/kernel.h>
|
||||
#include <boot/stage2.h>
|
||||
#include <arch/sh4/sh4.h>
|
||||
#include <kernel/int.h>
|
||||
#include <kernel/debug.h>
|
||||
#include <kernel/timer.h>
|
||||
#include <kernel/arch/cpu.h>
|
||||
|
||||
#define timer_rate 12500000
|
||||
#define max_timer_interval ((bigtime_t)0xffffffff * 1000000 / timer_rate)
|
||||
#define min_timer_interval ((bigtime_t)0x1000)
|
||||
|
||||
#define SYSTEM_TIME_TIMER_QUANTA 0xffffffff
|
||||
static const bigtime_t system_time_timer_period = (bigtime_t)SYSTEM_TIME_TIMER_QUANTA * timer_rate / 1000000;
|
||||
static volatile bigtime_t base_system_time = 0;
|
||||
|
||||
bigtime_t system_time()
|
||||
{
|
||||
bigtime_t outtime;
|
||||
uint32 timer_val;
|
||||
int state = int_disable_interrupts();
|
||||
|
||||
restart:
|
||||
timer_val = SYSTEM_TIME_TIMER_QUANTA - *(uint32 *)TCNT1;
|
||||
|
||||
if(*(uint16 *)TCR1 & 0x0100) {
|
||||
// underflow has occurred already
|
||||
outtime = base_system_time + system_time_timer_period + (bigtime_t)timer_val * 1000000 / timer_rate;
|
||||
} else {
|
||||
outtime = base_system_time + (bigtime_t)timer_val * 1000000 / timer_rate;
|
||||
if(*(uint16 *)TCR1 & 0x0100) {
|
||||
// an underflow must have happened since we checked last, redo
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
|
||||
int_restore_interrupts(state);
|
||||
|
||||
return outtime;
|
||||
}
|
||||
|
||||
static void start_timer(int timer)
|
||||
{
|
||||
uint8 old_val = *(uint8 *)TSTR;
|
||||
*(uint8 *)TSTR = old_val | (0x1 << timer % 3);
|
||||
}
|
||||
|
||||
static void stop_timer(int timer)
|
||||
{
|
||||
uint8 old_val = *(uint8 *)TSTR;
|
||||
*(uint8 *)TSTR = old_val & ~(0x1 << timer %3);
|
||||
}
|
||||
|
||||
static void setup_timer(int timer, bigtime_t relative_timeout)
|
||||
{
|
||||
uint32 timer_val;
|
||||
|
||||
if(relative_timeout < min_timer_interval) {
|
||||
timer_val = min_timer_interval * timer_rate / 1000000;
|
||||
} else if(relative_timeout < max_timer_interval) {
|
||||
timer_val = relative_timeout * timer_rate / 1000000;
|
||||
} else {
|
||||
timer_val = 0xffffffff;
|
||||
}
|
||||
|
||||
switch(timer) {
|
||||
case 0:
|
||||
*(uint16 *)TCR0 = 0x0020;
|
||||
*(uint32 *)TCNT0 = timer_val;
|
||||
*(uint32 *)TCOR0 = timer_val;
|
||||
break;
|
||||
case 1:
|
||||
*(uint16 *)TCR1 = 0x0020;
|
||||
*(uint32 *)TCNT1 = timer_val;
|
||||
*(uint32 *)TCOR1 = timer_val;
|
||||
break;
|
||||
case 2:
|
||||
*(uint16 *)TCR2 = 0x0020;
|
||||
*(uint32 *)TCNT2 = timer_val;
|
||||
*(uint32 *)TCOR2 = timer_val;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void arch_timer_set_hardware_timer(bigtime_t timeout)
|
||||
{
|
||||
stop_timer(0);
|
||||
setup_timer(0, timeout);
|
||||
start_timer(0);
|
||||
}
|
||||
|
||||
void arch_timer_clear_hardware_timer()
|
||||
{
|
||||
stop_timer(0);
|
||||
}
|
||||
|
||||
static int timer_interrupt0()
|
||||
{
|
||||
stop_timer(0);
|
||||
return timer_interrupt();
|
||||
}
|
||||
|
||||
static void setup_system_time_timer()
|
||||
{
|
||||
*(uint16 *)TCR1 = 0x0020;
|
||||
*(uint32 *)TCNT1 = SYSTEM_TIME_TIMER_QUANTA;
|
||||
*(uint32 *)TCOR1 = SYSTEM_TIME_TIMER_QUANTA;
|
||||
}
|
||||
|
||||
static int timer_interrupt1()
|
||||
{
|
||||
base_system_time += system_time_timer_period;
|
||||
*(uint16 *)TCR1 = 0x0020; // mask out the underflow bit
|
||||
return INT_NO_RESCHEDULE;
|
||||
}
|
||||
|
||||
int arch_init_timer(kernel_args *ka)
|
||||
{
|
||||
int i;
|
||||
uint8 old_val8;
|
||||
uint16 old_val16;
|
||||
dprintf("arch_init_timer: entry\n");
|
||||
|
||||
int_set_io_interrupt_handler(32, &timer_interrupt0, NULL);
|
||||
int_set_io_interrupt_handler(33, &timer_interrupt1, NULL);
|
||||
|
||||
// stop all of the timers
|
||||
*(uint8 *)TSTR = 0;
|
||||
|
||||
// enable the interrupt on timer 0 & 1 & disable 2
|
||||
old_val16 = *(uint16 *)IPRA;
|
||||
*(uint16 *)IPRA = (old_val16 & 0x000f) | 0xef00;
|
||||
|
||||
// start timer 1 counting forever
|
||||
base_system_time = 0;
|
||||
setup_system_time_timer();
|
||||
start_timer(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
#include <kernel/kernel.h>
|
||||
#include <kernel/debug.h>
|
||||
#include <kernel/arch/vm.h>
|
||||
#include <kernel/arch/sh4/cpu.h>
|
||||
#include <boot/stage2.h>
|
||||
|
||||
int arch_vm_init(kernel_args *ka)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arch_vm_init2(kernel_args *ka)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arch_vm_init_endvm(kernel_args *ka)
|
||||
{
|
||||
|
||||
dprintf("arch_vm_init_endvm: entry\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void arch_vm_aspace_swap(vm_address_space *aspace)
|
||||
{
|
||||
sh4_set_user_pgdir(vm_translation_map_get_pgdir(&aspace->translation_map));
|
||||
}
|
||||
|
||||
@@ -1,424 +0,0 @@
|
||||
/*
|
||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
#include <kernel/kernel.h>
|
||||
#include <kernel/arch/vm_translation_map.h>
|
||||
#include <kernel/heap.h>
|
||||
#include <kernel/int.h>
|
||||
#include <kernel/smp.h>
|
||||
#include <kernel/vm.h>
|
||||
#include <kernel/vm_page.h>
|
||||
#include <kernel/vm_priv.h>
|
||||
#include <kernel/arch/cpu.h>
|
||||
#include <kernel/debug.h>
|
||||
#include <nulibc/string.h>
|
||||
#include <boot/stage2.h>
|
||||
|
||||
#include <arch/sh4/sh4.h>
|
||||
#include <arch/sh4/vcpu.h>
|
||||
|
||||
typedef struct vm_translation_map_arch_info_struct {
|
||||
addr pgdir_virt;
|
||||
addr pgdir_phys;
|
||||
bool is_user;
|
||||
} vm_translation_map_arch_info;
|
||||
|
||||
static vcpu_struct *vcpu;
|
||||
|
||||
#define CHATTY_TMAP 0
|
||||
|
||||
#define PHYS_TO_P1(x) ((x) + P1_AREA)
|
||||
|
||||
static void destroy_tmap(vm_translation_map *map)
|
||||
{
|
||||
int state;
|
||||
vm_translation_map *entry;
|
||||
vm_translation_map *last = NULL;
|
||||
|
||||
if(map == NULL)
|
||||
return;
|
||||
|
||||
if(map->arch_data->pgdir_virt != NULL)
|
||||
kfree((void *)map->arch_data->pgdir_virt);
|
||||
|
||||
kfree(map->arch_data);
|
||||
}
|
||||
|
||||
static int lock_tmap(vm_translation_map *map)
|
||||
{
|
||||
// dprintf("lock_tmap: map 0x%x\n", map);
|
||||
if(recursive_lock_lock(&map->lock) == true) {
|
||||
// we were the first one to grab the lock
|
||||
// dprintf("clearing invalidated page count\n");
|
||||
// map->arch_data->num_invalidate_pages = 0;
|
||||
}
|
||||
|
||||
return 0;}
|
||||
|
||||
static int unlock_tmap(vm_translation_map *map)
|
||||
{
|
||||
if(recursive_lock_get_recursion(&map->lock) == 1) {
|
||||
// XXX flush any TLB ents we wanted to
|
||||
}
|
||||
recursive_lock_unlock(&map->lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int map_tmap(vm_translation_map *map, addr va, addr pa, unsigned int lock)
|
||||
{
|
||||
struct pdent *pd = NULL;
|
||||
struct ptent *pt;
|
||||
unsigned int index;
|
||||
|
||||
#if CHATTY_TMAP
|
||||
dprintf("map_tmap: va 0x%x pa 0x%x lock 0x%x\n", va, pa, lock);
|
||||
#endif
|
||||
|
||||
if(map->arch_data->is_user) {
|
||||
if(va >= P1_AREA) {
|
||||
// invalid
|
||||
panic("map_tmap: asked to map va 0x%x in user space aspace\n", va);
|
||||
}
|
||||
pd = (struct pdent *)map->arch_data->pgdir_phys;
|
||||
index = va >> 22;
|
||||
} else {
|
||||
if(va < P3_AREA && va >= P4_AREA) {
|
||||
panic("map_tmap: asked to map va 0x%x in kernel space aspace\n", va);
|
||||
}
|
||||
pd = (struct pdent *)vcpu->kernel_pgdir;
|
||||
index = (va & 0x7fffffff) >> 22;
|
||||
}
|
||||
|
||||
if(pd[index].v == 0) {
|
||||
vm_page *page;
|
||||
unsigned int pgtable;
|
||||
|
||||
page = vm_page_allocate_page(PAGE_STATE_CLEAR);
|
||||
pgtable = page->ppn * PAGE_SIZE;
|
||||
|
||||
// XXX remove when real clear pages support is there
|
||||
memset((void *)PHYS_TO_P1(pgtable), 0, PAGE_SIZE);
|
||||
|
||||
pd[index].ppn = pgtable >> 12;
|
||||
pd[index].v = 1;
|
||||
}
|
||||
|
||||
// get the pagetable
|
||||
pt = (struct ptent *)PHYS_TO_P1(pd[index].ppn << 12);
|
||||
index = (va >> 12) & 0x000003ff;
|
||||
|
||||
if(pt[index].v)
|
||||
panic("map_tmap: va 0x%x already mapped to pa 0x%x\n", va, pt[index].ppn << 12);
|
||||
|
||||
// insert the mapping
|
||||
pt[index].wt = 0;
|
||||
pt[index].pr = (lock & LOCK_KERNEL) ? (lock & 0x1) : (lock | 0x2);
|
||||
pt[index].ppn = pa >> 12;
|
||||
pt[index].tlb_ent = 0;
|
||||
pt[index].c = 1;
|
||||
pt[index].sz = 0x1; // 4k page
|
||||
pt[index].sh = 0;
|
||||
pt[index].d = 0;
|
||||
pt[index].v = 1;
|
||||
|
||||
sh4_invl_page(va);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unmap_tmap(vm_translation_map *map, addr start, addr end)
|
||||
{
|
||||
struct pdent *pd;
|
||||
struct ptent *pt;
|
||||
unsigned int index;
|
||||
|
||||
start = ROUNDOWN(start, PAGE_SIZE);
|
||||
end = ROUNDUP(end, PAGE_SIZE);
|
||||
|
||||
#if CHATTY_TMAP
|
||||
dprintf("unmap_tmap: asked to free pages 0x%x to 0x%x\n", start, end);
|
||||
#endif
|
||||
|
||||
for(; start < end; start += PAGE_SIZE) {
|
||||
if(map->arch_data->is_user) {
|
||||
if(start >= P1_AREA) {
|
||||
// invalid
|
||||
panic("unmap_tmap: asked to unmap va 0x%x in user space aspace\n", start);
|
||||
}
|
||||
pd = (struct pdent *)map->arch_data->pgdir_phys;
|
||||
index = start >> 22;
|
||||
} else {
|
||||
if(start < P3_AREA && start >= P4_AREA) {
|
||||
panic("unmap_tmap: asked to unmap va 0x%x in kernel space aspace\n", start);
|
||||
}
|
||||
pd = (struct pdent *)vcpu->kernel_pgdir;
|
||||
index = (start & 0x7fffffff) >> 22;
|
||||
}
|
||||
|
||||
if(pd[index].v == 0)
|
||||
continue;
|
||||
|
||||
// get the pagetable
|
||||
pt = (struct ptent *)PHYS_TO_P1(pd[index].ppn << 12);
|
||||
index = (start >> 12) & 0x000003ff;
|
||||
|
||||
if(pt[index].v == 0)
|
||||
continue;
|
||||
|
||||
pt[index].v = 0;
|
||||
|
||||
sh4_invl_page(start);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int query_tmap(vm_translation_map *map, addr va, addr *out_physical, unsigned int *out_flags)
|
||||
{
|
||||
struct pdent *pd;
|
||||
struct ptent *pt;
|
||||
unsigned int index;
|
||||
|
||||
// default the flags to not present
|
||||
*out_flags = 0;
|
||||
*out_physical = 0;
|
||||
|
||||
if(map->arch_data->is_user) {
|
||||
if(va >= P1_AREA) {
|
||||
// invalid
|
||||
return ERR_VM_GENERAL;
|
||||
}
|
||||
pd = (struct pdent *)map->arch_data->pgdir_phys;
|
||||
index = va >> 22;
|
||||
} else {
|
||||
if(va < P3_AREA && va >= P4_AREA) {
|
||||
return ERR_VM_GENERAL;
|
||||
}
|
||||
pd = (struct pdent *)vcpu->kernel_pgdir;
|
||||
index = (va & 0x7fffffff) >> 22;
|
||||
}
|
||||
|
||||
if(pd[index].v == 0) {
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
// get the pagetable
|
||||
pt = (struct ptent *)PHYS_TO_P1(pd[index].ppn << 12);
|
||||
index = (va >> 12) & 0x000003ff;
|
||||
|
||||
*out_physical = pt[index].ppn << 12;
|
||||
|
||||
// read in the page state flags, clearing the modified and accessed flags in the process
|
||||
*out_flags = 0;
|
||||
*out_flags |= (pt[index].pr & 0x1) ? LOCK_RW : LOCK_RO;
|
||||
*out_flags |= (pt[index].pr & 0x2) ? 0 : LOCK_KERNEL;
|
||||
*out_flags |= pt[index].d ? PAGE_MODIFIED : 0;
|
||||
// *out_flags |= pt[index].accessed ? PAGE_ACCESSED : 0; // not emulating the accessed bit yet
|
||||
*out_flags |= pt[index].v ? PAGE_PRESENT : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static addr get_mapped_size_tmap(vm_translation_map *map)
|
||||
{
|
||||
return map->map_count;
|
||||
}
|
||||
|
||||
static int protect_tmap(vm_translation_map *map, addr base, addr top, unsigned int attributes)
|
||||
{
|
||||
// XXX finish
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int clear_flags_tmap(vm_translation_map *map, addr va, unsigned int flags)
|
||||
{
|
||||
struct pdent *pd;
|
||||
struct ptent *pt;
|
||||
unsigned int index;
|
||||
int tlb_flush = false;
|
||||
|
||||
if(map->arch_data->is_user) {
|
||||
if(va >= P1_AREA) {
|
||||
// invalid
|
||||
return ERR_VM_GENERAL;
|
||||
}
|
||||
pd = (struct pdent *)map->arch_data->pgdir_phys;
|
||||
index = va >> 22;
|
||||
} else {
|
||||
if(va < P3_AREA && va >= P4_AREA) {
|
||||
return ERR_VM_GENERAL;
|
||||
}
|
||||
pd = (struct pdent *)vcpu->kernel_pgdir;
|
||||
index = (va & 0x7fffffff) >> 22;
|
||||
}
|
||||
|
||||
if(pd[index].v == 0) {
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
// get the pagetable
|
||||
pt = (struct ptent *)PHYS_TO_P1(pd[index].ppn << 12);
|
||||
index = (va >> 12) & 0x000003ff;
|
||||
|
||||
// clear out the flags we've been requested to clear
|
||||
if(flags & PAGE_MODIFIED) {
|
||||
pt[index].d = 0;
|
||||
tlb_flush = true;
|
||||
}
|
||||
if(flags & PAGE_ACCESSED) {
|
||||
// pt[index].accessed = 0;
|
||||
// tlb_flush = true;
|
||||
}
|
||||
|
||||
if(tlb_flush)
|
||||
sh4_invl_page(va);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void flush_tmap(vm_translation_map *map)
|
||||
{
|
||||
// no-op, we aren't caching any tlb invalidations
|
||||
}
|
||||
|
||||
static int get_physical_page_tmap(addr pa, addr *va, int flags)
|
||||
{
|
||||
if(pa >= PHYS_ADDR_SIZE)
|
||||
panic("get_physical_page_tmap: passed invalid address 0x%x\n", pa);
|
||||
*va = PHYS_ADDR_TO_P1(pa);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
static int put_physical_page_tmap(addr va)
|
||||
{
|
||||
if(va < P1_AREA && va >= P2_AREA)
|
||||
panic("put_physical_page_tmap: bad address passed 0x%x\n", va);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if(new_map == NULL)
|
||||
return -1;
|
||||
|
||||
// initialize the new object
|
||||
new_map->ops = &tmap_ops;
|
||||
new_map->map_count = 0;
|
||||
if(recursive_lock_create(&new_map->lock) < 0)
|
||||
return ERR_NO_MEMORY;
|
||||
|
||||
new_map->arch_data = kmalloc(sizeof(vm_translation_map_arch_info));
|
||||
if(new_map == NULL)
|
||||
panic("error allocating translation map object!\n");
|
||||
|
||||
if(!kernel) {
|
||||
// user
|
||||
// allocate a pgdir
|
||||
new_map->arch_data->pgdir_virt = (addr)kmalloc(PAGE_SIZE);
|
||||
if(new_map->arch_data->pgdir_virt == NULL) {
|
||||
kfree(new_map->arch_data);
|
||||
return -1;
|
||||
}
|
||||
if(((addr)new_map->arch_data->pgdir_virt % PAGE_SIZE) != 0)
|
||||
panic("vm_translation_map_create: malloced pgdir and found it wasn't aligned!\n");
|
||||
vm_get_page_mapping(vm_get_kernel_aspace_id(), (addr)new_map->arch_data->pgdir_virt, (addr *)&new_map->arch_data->pgdir_phys);
|
||||
new_map->arch_data->pgdir_phys = PHYS_TO_P1(new_map->arch_data->pgdir_phys);
|
||||
// zero out the new pgdir
|
||||
memset((void *)new_map->arch_data->pgdir_virt, 0, PAGE_SIZE);
|
||||
new_map->arch_data->is_user = true;
|
||||
} else {
|
||||
// kernel
|
||||
// we already know the kernel pgdir mapping
|
||||
(addr)new_map->arch_data->pgdir_virt = NULL;
|
||||
(addr)new_map->arch_data->pgdir_phys = vcpu->kernel_pgdir;
|
||||
new_map->arch_data->is_user = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vm_translation_map_module_init(kernel_args *ka)
|
||||
{
|
||||
vcpu = ka->arch_args.vcpu;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vm_translation_map_module_init2(kernel_args *ka)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vm_translation_map_module_init_post_sem(kernel_args *ka)
|
||||
{
|
||||
}
|
||||
|
||||
// XXX horrible back door to map a page quickly regardless of translation map object, etc.
|
||||
// used only during VM setup
|
||||
int vm_translation_map_quick_map(kernel_args *ka, addr va, addr pa, unsigned int lock, addr (*get_free_page)(kernel_args *))
|
||||
{
|
||||
struct pdent *pd = NULL;
|
||||
struct ptent *pt;
|
||||
unsigned int index;
|
||||
|
||||
#if CHATTY_TMAP
|
||||
dprintf("quick_tmap: va 0x%x pa 0x%x lock 0x%x\n", va, pa, lock);
|
||||
#endif
|
||||
|
||||
if(va < P3_AREA && va >= P4_AREA) {
|
||||
panic("quick_tmap: asked to map invalid va 0x%x\n", va);
|
||||
}
|
||||
pd = (struct pdent *)vcpu->kernel_pgdir;
|
||||
index = (va & 0x7fffffff) >> 22;
|
||||
|
||||
if(pd[index].v == 0) {
|
||||
vm_page *page;
|
||||
unsigned int pgtable;
|
||||
|
||||
pgtable = (*get_free_page)(ka) * PAGE_SIZE;
|
||||
|
||||
memset((void *)PHYS_TO_P1(pgtable), 0, PAGE_SIZE);
|
||||
|
||||
pd[index].ppn = pgtable >> 12;
|
||||
pd[index].v = 1;
|
||||
}
|
||||
|
||||
// get the pagetable
|
||||
pt = (struct ptent *)PHYS_TO_P1(pd[index].ppn << 12);
|
||||
index = (va >> 12) & 0x000003ff;
|
||||
|
||||
// insert the mapping
|
||||
pt[index].wt = 0;
|
||||
pt[index].pr = (lock & LOCK_KERNEL) ? (lock & 0x1) : (lock | 0x2);
|
||||
pt[index].ppn = pa >> 12;
|
||||
pt[index].tlb_ent = 0;
|
||||
pt[index].c = 1;
|
||||
pt[index].sz = 0x1; // 4k page
|
||||
pt[index].sh = 0;
|
||||
pt[index].d = 0;
|
||||
pt[index].v = 1;
|
||||
|
||||
sh4_invl_page(va);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
addr vm_translation_map_get_pgdir(vm_translation_map *map)
|
||||
{
|
||||
return (addr)map->arch_data->pgdir_phys;
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
OUTPUT_FORMAT("elf32-shl", "elf32-shl", "elf32-shl")
|
||||
OUTPUT_ARCH(sh)
|
||||
|
||||
ENTRY(__start)
|
||||
SEARCH_DIR("libgcc");
|
||||
SECTIONS
|
||||
{
|
||||
. = 0xc0000000 + SIZEOF_HEADERS;
|
||||
|
||||
.interp : { *(.interp) }
|
||||
.hash : { *(.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) }
|
||||
.rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) }
|
||||
.rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) }
|
||||
.rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) }
|
||||
.rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
|
||||
.rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
|
||||
.rel.got : { *(.rel.got) }
|
||||
.rela.got : { *(.rela.got) }
|
||||
.rel.ctors : { *(.rel.ctors) }
|
||||
.rela.ctors : { *(.rela.ctors) }
|
||||
.rel.dtors : { *(.rel.dtors) }
|
||||
.rela.dtors : { *(.rela.dtors) }
|
||||
.rel.init : { *(.rel.init) }
|
||||
.rela.init : { *(.rela.init) }
|
||||
.rel.fini : { *(.rel.fini) }
|
||||
.rela.fini : { *(.rela.fini) }
|
||||
.rel.bss : { *(.rel.bss) }
|
||||
.rela.bss : { *(.rela.bss) }
|
||||
.rel.plt : { *(.rel.plt) }
|
||||
.rela.plt : { *(.rela.plt) }
|
||||
.init : { *(.init) } =0x9090
|
||||
.plt : { *(.plt) }
|
||||
|
||||
/* text/read-only data */
|
||||
.text : { *(.text .gnu.linkonce.t.*) } =0x9090
|
||||
|
||||
.rodata :
|
||||
{
|
||||
*(.rodata)
|
||||
. = ALIGN(0x1000);
|
||||
} =0x9000
|
||||
|
||||
/* writable data */
|
||||
. = ALIGN(0x1000);
|
||||
___data_start = .;
|
||||
.data : { *(.data .gnu.linkonce.d.*) }
|
||||
|
||||
___ctor_list = .;
|
||||
.ctors : { *(.ctors) }
|
||||
___ctor_end = .;
|
||||
___dtor_list = .;
|
||||
.dtors : { *(.dtors) }
|
||||
___dtor_end = .;
|
||||
.got : { *(.got.plt) *(.got) }
|
||||
.dynamic : { *(.dynamic) }
|
||||
|
||||
/* unintialized data (in same segment as writable data) */
|
||||
___bss_start = .;
|
||||
.bss : { *(.bss) }
|
||||
|
||||
. = ALIGN(0x1000);
|
||||
_end = . ;
|
||||
|
||||
/* Strip unnecessary stuff */
|
||||
/DISCARD/ : { *(.comment .note .eh_frame) }
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
# sparc kernel makefile
|
||||
# included from kernel.mk
|
||||
KERNEL_ARCH_OBJ_DIR = $(KERNEL_ARCH_DIR)/$(OBJ_DIR)
|
||||
KERNEL_OBJS += \
|
||||
|
||||
KERNEL_ARCH_INCLUDES = $(KERNEL_INCLUDES)
|
||||
|
||||
$(KERNEL_ARCH_OBJ_DIR)/%.o: $(KERNEL_ARCH_DIR)/%.c
|
||||
@mkdir -p $(KERNEL_ARCH_OBJ_DIR)
|
||||
$(CC) -c $< $(GLOBAL_CFLAGS) $(KERNEL_ARCH_INCLUDES) -o $@
|
||||
|
||||
$(KERNEL_ARCH_OBJ_DIR)/%.d: $(KERNEL_ARCH_DIR)/%.c
|
||||
@mkdir -p $(KERNEL_ARCH_OBJ_DIR)
|
||||
@echo "making deps for $<..."
|
||||
@(echo -n $(dir $@); $(CC) $(GLOBAL_CFLAGS) $(KERNEL_ARCH_INCLUDES) -M -MG $<) > $@
|
||||
|
||||
$(KERNEL_ARCH_OBJ_DIR)/%.d: $(KERNEL_ARCH_DIR)/%.S
|
||||
@mkdir -p $(KERNEL_ARCH_OBJ_DIR)
|
||||
@echo "making deps for $<..."
|
||||
@(echo -n $(dir $@);$(CC) $(GLOBAL_CFLAGS) $(KERNEL_ARCH_INCLUDES) -M -MG $<) > $@
|
||||
|
||||
$(KERNEL_ARCH_OBJ_DIR)/%.o: $(KERNEL_ARCH_DIR)/%.S
|
||||
@mkdir -p $(KERNEL_ARCH_OBJ_DIR)
|
||||
$(CC) -c $< $(GLOBAL_CFLAGS) $(KERNEL_ARCH_INCLUDES) -o $@
|
||||
@@ -1,24 +0,0 @@
|
||||
# sparc64 kernel makefile
|
||||
# included from kernel.mk
|
||||
KERNEL_ARCH_OBJ_DIR = $(KERNEL_ARCH_DIR)/$(OBJ_DIR)
|
||||
KERNEL_OBJS += \
|
||||
|
||||
KERNEL_ARCH_INCLUDES = $(KERNEL_INCLUDES)
|
||||
|
||||
$(KERNEL_ARCH_OBJ_DIR)/%.o: $(KERNEL_ARCH_DIR)/%.c
|
||||
@mkdir -p $(KERNEL_ARCH_OBJ_DIR)
|
||||
$(CC) -c $< $(GLOBAL_CFLAGS) $(KERNEL_ARCH_INCLUDES) -o $@
|
||||
|
||||
$(KERNEL_ARCH_OBJ_DIR)/%.d: $(KERNEL_ARCH_DIR)/%.c
|
||||
@mkdir -p $(KERNEL_ARCH_OBJ_DIR)
|
||||
@echo "making deps for $<..."
|
||||
@($(ECHO) -n $(dir $@); $(CC) $(GLOBAL_CFLAGS) $(KERNEL_ARCH_INCLUDES) -M -MG $<) > $@
|
||||
|
||||
$(KERNEL_ARCH_OBJ_DIR)/%.d: $(KERNEL_ARCH_DIR)/%.S
|
||||
@mkdir -p $(KERNEL_ARCH_OBJ_DIR)
|
||||
@echo "making deps for $<..."
|
||||
@($(ECHO) -n $(dir $@);$(CC) $(GLOBAL_CFLAGS) $(KERNEL_ARCH_INCLUDES) -M -MG $<) > $@
|
||||
|
||||
$(KERNEL_ARCH_OBJ_DIR)/%.o: $(KERNEL_ARCH_DIR)/%.S
|
||||
@mkdir -p $(KERNEL_ARCH_OBJ_DIR)
|
||||
$(CC) -c $< $(GLOBAL_CFLAGS) $(KERNEL_ARCH_INCLUDES) -o $@
|
||||
Reference in New Issue
Block a user