Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
This commit is contained in:
commit
c4a7c77fcb
|
@ -249,8 +249,6 @@ struct tt_entry *sparc_ttable;
|
||||||
|
|
||||||
struct pt_regs fake_swapper_regs;
|
struct pt_regs fake_swapper_regs;
|
||||||
|
|
||||||
extern void paging_init(void);
|
|
||||||
|
|
||||||
void __init setup_arch(char **cmdline_p)
|
void __init setup_arch(char **cmdline_p)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
|
@ -540,8 +540,11 @@ bootup_user_stack_end:
|
||||||
prom_tba: .xword 0
|
prom_tba: .xword 0
|
||||||
tlb_type: .word 0 /* Must NOT end up in BSS */
|
tlb_type: .word 0 /* Must NOT end up in BSS */
|
||||||
.section ".fixup",#alloc,#execinstr
|
.section ".fixup",#alloc,#execinstr
|
||||||
.globl __ret_efault
|
|
||||||
|
.globl __ret_efault, __retl_efault
|
||||||
__ret_efault:
|
__ret_efault:
|
||||||
ret
|
ret
|
||||||
restore %g0, -EFAULT, %o0
|
restore %g0, -EFAULT, %o0
|
||||||
|
__retl_efault:
|
||||||
|
retl
|
||||||
|
mov -EFAULT, %o0
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include <asm/visasm.h>
|
#include <asm/visasm.h>
|
||||||
#include <asm/spitfire.h>
|
#include <asm/spitfire.h>
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
|
#include <asm/cpudata.h>
|
||||||
|
|
||||||
/* Returning from ptrace is a bit tricky because the syscall return
|
/* Returning from ptrace is a bit tricky because the syscall return
|
||||||
* low level code assumes any value returned which is negative and
|
* low level code assumes any value returned which is negative and
|
||||||
|
@ -132,12 +133,16 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
|
||||||
if ((uaddr ^ (unsigned long) kaddr) & (1UL << 13)) {
|
if ((uaddr ^ (unsigned long) kaddr) & (1UL << 13)) {
|
||||||
unsigned long start = __pa(kaddr);
|
unsigned long start = __pa(kaddr);
|
||||||
unsigned long end = start + len;
|
unsigned long end = start + len;
|
||||||
|
unsigned long dcache_line_size;
|
||||||
|
|
||||||
|
dcache_line_size = local_cpu_data().dcache_line_size;
|
||||||
|
|
||||||
if (tlb_type == spitfire) {
|
if (tlb_type == spitfire) {
|
||||||
for (; start < end; start += 32)
|
for (; start < end; start += dcache_line_size)
|
||||||
spitfire_put_dcache_tag(start & 0x3fe0, 0x0);
|
spitfire_put_dcache_tag(start & 0x3fe0, 0x0);
|
||||||
} else {
|
} else {
|
||||||
for (; start < end; start += 32)
|
start &= ~(dcache_line_size - 1);
|
||||||
|
for (; start < end; start += dcache_line_size)
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
"stxa %%g0, [%0] %1\n\t"
|
"stxa %%g0, [%0] %1\n\t"
|
||||||
"membar #Sync"
|
"membar #Sync"
|
||||||
|
@ -150,8 +155,11 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
|
||||||
if (write && tlb_type == spitfire) {
|
if (write && tlb_type == spitfire) {
|
||||||
unsigned long start = (unsigned long) kaddr;
|
unsigned long start = (unsigned long) kaddr;
|
||||||
unsigned long end = start + len;
|
unsigned long end = start + len;
|
||||||
|
unsigned long icache_line_size;
|
||||||
|
|
||||||
for (; start < end; start += 32)
|
icache_line_size = local_cpu_data().icache_line_size;
|
||||||
|
|
||||||
|
for (; start < end; start += icache_line_size)
|
||||||
flushi(start);
|
flushi(start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -464,8 +464,6 @@ static void __init boot_flags_init(char *commands)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int prom_probe_memory(void);
|
|
||||||
extern unsigned long start, end;
|
|
||||||
extern void panic_setup(char *, int *);
|
extern void panic_setup(char *, int *);
|
||||||
|
|
||||||
extern unsigned short root_flags;
|
extern unsigned short root_flags;
|
||||||
|
@ -492,12 +490,8 @@ void register_prom_callbacks(void)
|
||||||
"' linux-.soft2 to .soft2");
|
"' linux-.soft2 to .soft2");
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void paging_init(void);
|
|
||||||
|
|
||||||
void __init setup_arch(char **cmdline_p)
|
void __init setup_arch(char **cmdline_p)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
/* Initialize PROM console and command line. */
|
/* Initialize PROM console and command line. */
|
||||||
*cmdline_p = prom_getbootargs();
|
*cmdline_p = prom_getbootargs();
|
||||||
strcpy(saved_command_line, *cmdline_p);
|
strcpy(saved_command_line, *cmdline_p);
|
||||||
|
@ -516,21 +510,6 @@ void __init setup_arch(char **cmdline_p)
|
||||||
boot_flags_init(*cmdline_p);
|
boot_flags_init(*cmdline_p);
|
||||||
|
|
||||||
idprom_init();
|
idprom_init();
|
||||||
(void) prom_probe_memory();
|
|
||||||
|
|
||||||
phys_base = 0xffffffffffffffffUL;
|
|
||||||
for (i = 0; sp_banks[i].num_bytes != 0; i++) {
|
|
||||||
unsigned long top;
|
|
||||||
|
|
||||||
if (sp_banks[i].base_addr < phys_base)
|
|
||||||
phys_base = sp_banks[i].base_addr;
|
|
||||||
top = sp_banks[i].base_addr +
|
|
||||||
sp_banks[i].num_bytes;
|
|
||||||
}
|
|
||||||
pfn_base = phys_base >> PAGE_SHIFT;
|
|
||||||
|
|
||||||
kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL;
|
|
||||||
kern_size = (unsigned long)&_end - (unsigned long)KERNBASE;
|
|
||||||
|
|
||||||
if (!root_flags)
|
if (!root_flags)
|
||||||
root_mountflags &= ~MS_RDONLY;
|
root_mountflags &= ~MS_RDONLY;
|
||||||
|
|
|
@ -157,173 +157,199 @@ sys32_socketcall: /* %o0=call, %o1=args */
|
||||||
or %g2, %lo(__socketcall_table_begin), %g2
|
or %g2, %lo(__socketcall_table_begin), %g2
|
||||||
jmpl %g2 + %o0, %g0
|
jmpl %g2 + %o0, %g0
|
||||||
nop
|
nop
|
||||||
|
do_einval:
|
||||||
|
retl
|
||||||
|
mov -EINVAL, %o0
|
||||||
|
|
||||||
/* Each entry is exactly 32 bytes. */
|
|
||||||
.align 32
|
.align 32
|
||||||
__socketcall_table_begin:
|
__socketcall_table_begin:
|
||||||
|
|
||||||
|
/* Each entry is exactly 32 bytes. */
|
||||||
do_sys_socket: /* sys_socket(int, int, int) */
|
do_sys_socket: /* sys_socket(int, int, int) */
|
||||||
ldswa [%o1 + 0x0] %asi, %o0
|
1: ldswa [%o1 + 0x0] %asi, %o0
|
||||||
sethi %hi(sys_socket), %g1
|
sethi %hi(sys_socket), %g1
|
||||||
ldswa [%o1 + 0x8] %asi, %o2
|
2: ldswa [%o1 + 0x8] %asi, %o2
|
||||||
jmpl %g1 + %lo(sys_socket), %g0
|
jmpl %g1 + %lo(sys_socket), %g0
|
||||||
ldswa [%o1 + 0x4] %asi, %o1
|
3: ldswa [%o1 + 0x4] %asi, %o1
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
do_sys_bind: /* sys_bind(int fd, struct sockaddr *, int) */
|
do_sys_bind: /* sys_bind(int fd, struct sockaddr *, int) */
|
||||||
ldswa [%o1 + 0x0] %asi, %o0
|
4: ldswa [%o1 + 0x0] %asi, %o0
|
||||||
sethi %hi(sys_bind), %g1
|
sethi %hi(sys_bind), %g1
|
||||||
ldswa [%o1 + 0x8] %asi, %o2
|
5: ldswa [%o1 + 0x8] %asi, %o2
|
||||||
jmpl %g1 + %lo(sys_bind), %g0
|
jmpl %g1 + %lo(sys_bind), %g0
|
||||||
lduwa [%o1 + 0x4] %asi, %o1
|
6: lduwa [%o1 + 0x4] %asi, %o1
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
do_sys_connect: /* sys_connect(int, struct sockaddr *, int) */
|
do_sys_connect: /* sys_connect(int, struct sockaddr *, int) */
|
||||||
ldswa [%o1 + 0x0] %asi, %o0
|
7: ldswa [%o1 + 0x0] %asi, %o0
|
||||||
sethi %hi(sys_connect), %g1
|
sethi %hi(sys_connect), %g1
|
||||||
ldswa [%o1 + 0x8] %asi, %o2
|
8: ldswa [%o1 + 0x8] %asi, %o2
|
||||||
jmpl %g1 + %lo(sys_connect), %g0
|
jmpl %g1 + %lo(sys_connect), %g0
|
||||||
lduwa [%o1 + 0x4] %asi, %o1
|
9: lduwa [%o1 + 0x4] %asi, %o1
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
do_sys_listen: /* sys_listen(int, int) */
|
do_sys_listen: /* sys_listen(int, int) */
|
||||||
ldswa [%o1 + 0x0] %asi, %o0
|
10: ldswa [%o1 + 0x0] %asi, %o0
|
||||||
sethi %hi(sys_listen), %g1
|
sethi %hi(sys_listen), %g1
|
||||||
jmpl %g1 + %lo(sys_listen), %g0
|
jmpl %g1 + %lo(sys_listen), %g0
|
||||||
ldswa [%o1 + 0x4] %asi, %o1
|
11: ldswa [%o1 + 0x4] %asi, %o1
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
do_sys_accept: /* sys_accept(int, struct sockaddr *, int *) */
|
do_sys_accept: /* sys_accept(int, struct sockaddr *, int *) */
|
||||||
ldswa [%o1 + 0x0] %asi, %o0
|
12: ldswa [%o1 + 0x0] %asi, %o0
|
||||||
sethi %hi(sys_accept), %g1
|
sethi %hi(sys_accept), %g1
|
||||||
lduwa [%o1 + 0x8] %asi, %o2
|
13: lduwa [%o1 + 0x8] %asi, %o2
|
||||||
jmpl %g1 + %lo(sys_accept), %g0
|
jmpl %g1 + %lo(sys_accept), %g0
|
||||||
lduwa [%o1 + 0x4] %asi, %o1
|
14: lduwa [%o1 + 0x4] %asi, %o1
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
do_sys_getsockname: /* sys_getsockname(int, struct sockaddr *, int *) */
|
do_sys_getsockname: /* sys_getsockname(int, struct sockaddr *, int *) */
|
||||||
ldswa [%o1 + 0x0] %asi, %o0
|
15: ldswa [%o1 + 0x0] %asi, %o0
|
||||||
sethi %hi(sys_getsockname), %g1
|
sethi %hi(sys_getsockname), %g1
|
||||||
lduwa [%o1 + 0x8] %asi, %o2
|
16: lduwa [%o1 + 0x8] %asi, %o2
|
||||||
jmpl %g1 + %lo(sys_getsockname), %g0
|
jmpl %g1 + %lo(sys_getsockname), %g0
|
||||||
lduwa [%o1 + 0x4] %asi, %o1
|
17: lduwa [%o1 + 0x4] %asi, %o1
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
do_sys_getpeername: /* sys_getpeername(int, struct sockaddr *, int *) */
|
do_sys_getpeername: /* sys_getpeername(int, struct sockaddr *, int *) */
|
||||||
ldswa [%o1 + 0x0] %asi, %o0
|
18: ldswa [%o1 + 0x0] %asi, %o0
|
||||||
sethi %hi(sys_getpeername), %g1
|
sethi %hi(sys_getpeername), %g1
|
||||||
lduwa [%o1 + 0x8] %asi, %o2
|
19: lduwa [%o1 + 0x8] %asi, %o2
|
||||||
jmpl %g1 + %lo(sys_getpeername), %g0
|
jmpl %g1 + %lo(sys_getpeername), %g0
|
||||||
lduwa [%o1 + 0x4] %asi, %o1
|
20: lduwa [%o1 + 0x4] %asi, %o1
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
do_sys_socketpair: /* sys_socketpair(int, int, int, int *) */
|
do_sys_socketpair: /* sys_socketpair(int, int, int, int *) */
|
||||||
ldswa [%o1 + 0x0] %asi, %o0
|
21: ldswa [%o1 + 0x0] %asi, %o0
|
||||||
sethi %hi(sys_socketpair), %g1
|
sethi %hi(sys_socketpair), %g1
|
||||||
ldswa [%o1 + 0x8] %asi, %o2
|
22: ldswa [%o1 + 0x8] %asi, %o2
|
||||||
lduwa [%o1 + 0xc] %asi, %o3
|
23: lduwa [%o1 + 0xc] %asi, %o3
|
||||||
jmpl %g1 + %lo(sys_socketpair), %g0
|
jmpl %g1 + %lo(sys_socketpair), %g0
|
||||||
ldswa [%o1 + 0x4] %asi, %o1
|
24: ldswa [%o1 + 0x4] %asi, %o1
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
do_sys_send: /* sys_send(int, void *, size_t, unsigned int) */
|
do_sys_send: /* sys_send(int, void *, size_t, unsigned int) */
|
||||||
ldswa [%o1 + 0x0] %asi, %o0
|
25: ldswa [%o1 + 0x0] %asi, %o0
|
||||||
sethi %hi(sys_send), %g1
|
sethi %hi(sys_send), %g1
|
||||||
lduwa [%o1 + 0x8] %asi, %o2
|
26: lduwa [%o1 + 0x8] %asi, %o2
|
||||||
lduwa [%o1 + 0xc] %asi, %o3
|
27: lduwa [%o1 + 0xc] %asi, %o3
|
||||||
jmpl %g1 + %lo(sys_send), %g0
|
jmpl %g1 + %lo(sys_send), %g0
|
||||||
lduwa [%o1 + 0x4] %asi, %o1
|
28: lduwa [%o1 + 0x4] %asi, %o1
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
do_sys_recv: /* sys_recv(int, void *, size_t, unsigned int) */
|
do_sys_recv: /* sys_recv(int, void *, size_t, unsigned int) */
|
||||||
ldswa [%o1 + 0x0] %asi, %o0
|
29: ldswa [%o1 + 0x0] %asi, %o0
|
||||||
sethi %hi(sys_recv), %g1
|
sethi %hi(sys_recv), %g1
|
||||||
lduwa [%o1 + 0x8] %asi, %o2
|
30: lduwa [%o1 + 0x8] %asi, %o2
|
||||||
lduwa [%o1 + 0xc] %asi, %o3
|
31: lduwa [%o1 + 0xc] %asi, %o3
|
||||||
jmpl %g1 + %lo(sys_recv), %g0
|
jmpl %g1 + %lo(sys_recv), %g0
|
||||||
lduwa [%o1 + 0x4] %asi, %o1
|
32: lduwa [%o1 + 0x4] %asi, %o1
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
do_sys_sendto: /* sys_sendto(int, u32, compat_size_t, unsigned int, u32, int) */
|
do_sys_sendto: /* sys_sendto(int, u32, compat_size_t, unsigned int, u32, int) */
|
||||||
ldswa [%o1 + 0x0] %asi, %o0
|
33: ldswa [%o1 + 0x0] %asi, %o0
|
||||||
sethi %hi(sys_sendto), %g1
|
sethi %hi(sys_sendto), %g1
|
||||||
lduwa [%o1 + 0x8] %asi, %o2
|
34: lduwa [%o1 + 0x8] %asi, %o2
|
||||||
lduwa [%o1 + 0xc] %asi, %o3
|
35: lduwa [%o1 + 0xc] %asi, %o3
|
||||||
lduwa [%o1 + 0x10] %asi, %o4
|
36: lduwa [%o1 + 0x10] %asi, %o4
|
||||||
ldswa [%o1 + 0x14] %asi, %o5
|
37: ldswa [%o1 + 0x14] %asi, %o5
|
||||||
jmpl %g1 + %lo(sys_sendto), %g0
|
jmpl %g1 + %lo(sys_sendto), %g0
|
||||||
lduwa [%o1 + 0x4] %asi, %o1
|
38: lduwa [%o1 + 0x4] %asi, %o1
|
||||||
do_sys_recvfrom: /* sys_recvfrom(int, u32, compat_size_t, unsigned int, u32, u32) */
|
do_sys_recvfrom: /* sys_recvfrom(int, u32, compat_size_t, unsigned int, u32, u32) */
|
||||||
ldswa [%o1 + 0x0] %asi, %o0
|
39: ldswa [%o1 + 0x0] %asi, %o0
|
||||||
sethi %hi(sys_recvfrom), %g1
|
sethi %hi(sys_recvfrom), %g1
|
||||||
lduwa [%o1 + 0x8] %asi, %o2
|
40: lduwa [%o1 + 0x8] %asi, %o2
|
||||||
lduwa [%o1 + 0xc] %asi, %o3
|
41: lduwa [%o1 + 0xc] %asi, %o3
|
||||||
lduwa [%o1 + 0x10] %asi, %o4
|
42: lduwa [%o1 + 0x10] %asi, %o4
|
||||||
lduwa [%o1 + 0x14] %asi, %o5
|
43: lduwa [%o1 + 0x14] %asi, %o5
|
||||||
jmpl %g1 + %lo(sys_recvfrom), %g0
|
jmpl %g1 + %lo(sys_recvfrom), %g0
|
||||||
lduwa [%o1 + 0x4] %asi, %o1
|
44: lduwa [%o1 + 0x4] %asi, %o1
|
||||||
do_sys_shutdown: /* sys_shutdown(int, int) */
|
do_sys_shutdown: /* sys_shutdown(int, int) */
|
||||||
ldswa [%o1 + 0x0] %asi, %o0
|
45: ldswa [%o1 + 0x0] %asi, %o0
|
||||||
sethi %hi(sys_shutdown), %g1
|
sethi %hi(sys_shutdown), %g1
|
||||||
jmpl %g1 + %lo(sys_shutdown), %g0
|
jmpl %g1 + %lo(sys_shutdown), %g0
|
||||||
ldswa [%o1 + 0x4] %asi, %o1
|
46: ldswa [%o1 + 0x4] %asi, %o1
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
do_sys_setsockopt: /* compat_sys_setsockopt(int, int, int, char *, int) */
|
do_sys_setsockopt: /* compat_sys_setsockopt(int, int, int, char *, int) */
|
||||||
ldswa [%o1 + 0x0] %asi, %o0
|
47: ldswa [%o1 + 0x0] %asi, %o0
|
||||||
sethi %hi(compat_sys_setsockopt), %g1
|
sethi %hi(compat_sys_setsockopt), %g1
|
||||||
ldswa [%o1 + 0x8] %asi, %o2
|
48: ldswa [%o1 + 0x8] %asi, %o2
|
||||||
lduwa [%o1 + 0xc] %asi, %o3
|
49: lduwa [%o1 + 0xc] %asi, %o3
|
||||||
ldswa [%o1 + 0x10] %asi, %o4
|
50: ldswa [%o1 + 0x10] %asi, %o4
|
||||||
jmpl %g1 + %lo(compat_sys_setsockopt), %g0
|
jmpl %g1 + %lo(compat_sys_setsockopt), %g0
|
||||||
ldswa [%o1 + 0x4] %asi, %o1
|
51: ldswa [%o1 + 0x4] %asi, %o1
|
||||||
nop
|
nop
|
||||||
do_sys_getsockopt: /* compat_sys_getsockopt(int, int, int, u32, u32) */
|
do_sys_getsockopt: /* compat_sys_getsockopt(int, int, int, u32, u32) */
|
||||||
ldswa [%o1 + 0x0] %asi, %o0
|
52: ldswa [%o1 + 0x0] %asi, %o0
|
||||||
sethi %hi(compat_sys_getsockopt), %g1
|
sethi %hi(compat_sys_getsockopt), %g1
|
||||||
ldswa [%o1 + 0x8] %asi, %o2
|
53: ldswa [%o1 + 0x8] %asi, %o2
|
||||||
lduwa [%o1 + 0xc] %asi, %o3
|
54: lduwa [%o1 + 0xc] %asi, %o3
|
||||||
lduwa [%o1 + 0x10] %asi, %o4
|
55: lduwa [%o1 + 0x10] %asi, %o4
|
||||||
jmpl %g1 + %lo(compat_sys_getsockopt), %g0
|
jmpl %g1 + %lo(compat_sys_getsockopt), %g0
|
||||||
ldswa [%o1 + 0x4] %asi, %o1
|
56: ldswa [%o1 + 0x4] %asi, %o1
|
||||||
nop
|
nop
|
||||||
do_sys_sendmsg: /* compat_sys_sendmsg(int, struct compat_msghdr *, unsigned int) */
|
do_sys_sendmsg: /* compat_sys_sendmsg(int, struct compat_msghdr *, unsigned int) */
|
||||||
ldswa [%o1 + 0x0] %asi, %o0
|
57: ldswa [%o1 + 0x0] %asi, %o0
|
||||||
sethi %hi(compat_sys_sendmsg), %g1
|
sethi %hi(compat_sys_sendmsg), %g1
|
||||||
lduwa [%o1 + 0x8] %asi, %o2
|
58: lduwa [%o1 + 0x8] %asi, %o2
|
||||||
jmpl %g1 + %lo(compat_sys_sendmsg), %g0
|
jmpl %g1 + %lo(compat_sys_sendmsg), %g0
|
||||||
lduwa [%o1 + 0x4] %asi, %o1
|
59: lduwa [%o1 + 0x4] %asi, %o1
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
do_sys_recvmsg: /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int) */
|
do_sys_recvmsg: /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int) */
|
||||||
ldswa [%o1 + 0x0] %asi, %o0
|
60: ldswa [%o1 + 0x0] %asi, %o0
|
||||||
sethi %hi(compat_sys_recvmsg), %g1
|
sethi %hi(compat_sys_recvmsg), %g1
|
||||||
lduwa [%o1 + 0x8] %asi, %o2
|
61: lduwa [%o1 + 0x8] %asi, %o2
|
||||||
jmpl %g1 + %lo(compat_sys_recvmsg), %g0
|
jmpl %g1 + %lo(compat_sys_recvmsg), %g0
|
||||||
lduwa [%o1 + 0x4] %asi, %o1
|
62: lduwa [%o1 + 0x4] %asi, %o1
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
__socketcall_table_end:
|
|
||||||
|
|
||||||
do_einval:
|
|
||||||
retl
|
|
||||||
mov -EINVAL, %o0
|
|
||||||
do_efault:
|
|
||||||
retl
|
|
||||||
mov -EFAULT, %o0
|
|
||||||
|
|
||||||
.section __ex_table
|
.section __ex_table
|
||||||
.align 4
|
.align 4
|
||||||
.word __socketcall_table_begin, 0, __socketcall_table_end, do_efault
|
.word 1b, __retl_efault, 2b, __retl_efault
|
||||||
|
.word 3b, __retl_efault, 4b, __retl_efault
|
||||||
|
.word 5b, __retl_efault, 6b, __retl_efault
|
||||||
|
.word 7b, __retl_efault, 8b, __retl_efault
|
||||||
|
.word 9b, __retl_efault, 10b, __retl_efault
|
||||||
|
.word 11b, __retl_efault, 12b, __retl_efault
|
||||||
|
.word 13b, __retl_efault, 14b, __retl_efault
|
||||||
|
.word 15b, __retl_efault, 16b, __retl_efault
|
||||||
|
.word 17b, __retl_efault, 18b, __retl_efault
|
||||||
|
.word 19b, __retl_efault, 20b, __retl_efault
|
||||||
|
.word 21b, __retl_efault, 22b, __retl_efault
|
||||||
|
.word 23b, __retl_efault, 24b, __retl_efault
|
||||||
|
.word 25b, __retl_efault, 26b, __retl_efault
|
||||||
|
.word 27b, __retl_efault, 28b, __retl_efault
|
||||||
|
.word 29b, __retl_efault, 30b, __retl_efault
|
||||||
|
.word 31b, __retl_efault, 32b, __retl_efault
|
||||||
|
.word 33b, __retl_efault, 34b, __retl_efault
|
||||||
|
.word 35b, __retl_efault, 36b, __retl_efault
|
||||||
|
.word 37b, __retl_efault, 38b, __retl_efault
|
||||||
|
.word 39b, __retl_efault, 40b, __retl_efault
|
||||||
|
.word 41b, __retl_efault, 42b, __retl_efault
|
||||||
|
.word 43b, __retl_efault, 44b, __retl_efault
|
||||||
|
.word 45b, __retl_efault, 46b, __retl_efault
|
||||||
|
.word 47b, __retl_efault, 48b, __retl_efault
|
||||||
|
.word 49b, __retl_efault, 50b, __retl_efault
|
||||||
|
.word 51b, __retl_efault, 52b, __retl_efault
|
||||||
|
.word 53b, __retl_efault, 54b, __retl_efault
|
||||||
|
.word 55b, __retl_efault, 56b, __retl_efault
|
||||||
|
.word 57b, __retl_efault, 58b, __retl_efault
|
||||||
|
.word 59b, __retl_efault, 60b, __retl_efault
|
||||||
|
.word 61b, __retl_efault, 62b, __retl_efault
|
||||||
.previous
|
.previous
|
||||||
|
|
|
@ -189,19 +189,18 @@ void spitfire_data_access_exception(struct pt_regs *regs, unsigned long sfsr, un
|
||||||
|
|
||||||
if (regs->tstate & TSTATE_PRIV) {
|
if (regs->tstate & TSTATE_PRIV) {
|
||||||
/* Test if this comes from uaccess places. */
|
/* Test if this comes from uaccess places. */
|
||||||
unsigned long fixup;
|
const struct exception_table_entry *entry;
|
||||||
unsigned long g2 = regs->u_regs[UREG_G2];
|
|
||||||
|
|
||||||
if ((fixup = search_extables_range(regs->tpc, &g2))) {
|
entry = search_exception_tables(regs->tpc);
|
||||||
/* Ouch, somebody is trying ugly VM hole tricks on us... */
|
if (entry) {
|
||||||
|
/* Ouch, somebody is trying VM hole tricks on us... */
|
||||||
#ifdef DEBUG_EXCEPTIONS
|
#ifdef DEBUG_EXCEPTIONS
|
||||||
printk("Exception: PC<%016lx> faddr<UNKNOWN>\n", regs->tpc);
|
printk("Exception: PC<%016lx> faddr<UNKNOWN>\n", regs->tpc);
|
||||||
printk("EX_TABLE: insn<%016lx> fixup<%016lx> "
|
printk("EX_TABLE: insn<%016lx> fixup<%016lx>\n",
|
||||||
"g2<%016lx>\n", regs->tpc, fixup, g2);
|
regs->tpc, entry->fixup);
|
||||||
#endif
|
#endif
|
||||||
regs->tpc = fixup;
|
regs->tpc = entry->fixup;
|
||||||
regs->tnpc = regs->tpc + 4;
|
regs->tnpc = regs->tpc + 4;
|
||||||
regs->u_regs[UREG_G2] = g2;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* Shit... */
|
/* Shit... */
|
||||||
|
@ -758,26 +757,12 @@ void __init cheetah_ecache_flush_init(void)
|
||||||
ecache_flush_size = (2 * largest_size);
|
ecache_flush_size = (2 * largest_size);
|
||||||
ecache_flush_linesize = smallest_linesize;
|
ecache_flush_linesize = smallest_linesize;
|
||||||
|
|
||||||
/* Discover a physically contiguous chunk of physical
|
ecache_flush_physbase = find_ecache_flush_span(ecache_flush_size);
|
||||||
* memory in 'sp_banks' of size ecache_flush_size calculated
|
|
||||||
* above. Store the physical base of this area at
|
|
||||||
* ecache_flush_physbase.
|
|
||||||
*/
|
|
||||||
for (node = 0; ; node++) {
|
|
||||||
if (sp_banks[node].num_bytes == 0)
|
|
||||||
break;
|
|
||||||
if (sp_banks[node].num_bytes >= ecache_flush_size) {
|
|
||||||
ecache_flush_physbase = sp_banks[node].base_addr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Note: Zero would be a valid value of ecache_flush_physbase so
|
if (ecache_flush_physbase == ~0UL) {
|
||||||
* don't use that as the success test. :-)
|
|
||||||
*/
|
|
||||||
if (sp_banks[node].num_bytes == 0) {
|
|
||||||
prom_printf("cheetah_ecache_flush_init: Cannot find %d byte "
|
prom_printf("cheetah_ecache_flush_init: Cannot find %d byte "
|
||||||
"contiguous physical memory.\n", ecache_flush_size);
|
"contiguous physical memory.\n",
|
||||||
|
ecache_flush_size);
|
||||||
prom_halt();
|
prom_halt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1346,16 +1331,12 @@ static int cheetah_fix_ce(unsigned long physaddr)
|
||||||
/* Return non-zero if PADDR is a valid physical memory address. */
|
/* Return non-zero if PADDR is a valid physical memory address. */
|
||||||
static int cheetah_check_main_memory(unsigned long paddr)
|
static int cheetah_check_main_memory(unsigned long paddr)
|
||||||
{
|
{
|
||||||
int i;
|
unsigned long vaddr = PAGE_OFFSET + paddr;
|
||||||
|
|
||||||
for (i = 0; ; i++) {
|
if (vaddr > (unsigned long) high_memory)
|
||||||
if (sp_banks[i].num_bytes == 0)
|
return 0;
|
||||||
break;
|
|
||||||
if (paddr >= sp_banks[i].base_addr &&
|
return kern_addr_valid(vaddr);
|
||||||
paddr < (sp_banks[i].base_addr + sp_banks[i].num_bytes))
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cheetah_cee_handler(struct pt_regs *regs, unsigned long afsr, unsigned long afar)
|
void cheetah_cee_handler(struct pt_regs *regs, unsigned long afsr, unsigned long afar)
|
||||||
|
@ -1610,10 +1591,10 @@ void cheetah_deferred_handler(struct pt_regs *regs, unsigned long afsr, unsigned
|
||||||
/* OK, usermode access. */
|
/* OK, usermode access. */
|
||||||
recoverable = 1;
|
recoverable = 1;
|
||||||
} else {
|
} else {
|
||||||
unsigned long g2 = regs->u_regs[UREG_G2];
|
const struct exception_table_entry *entry;
|
||||||
unsigned long fixup = search_extables_range(regs->tpc, &g2);
|
|
||||||
|
|
||||||
if (fixup != 0UL) {
|
entry = search_exception_tables(regs->tpc);
|
||||||
|
if (entry) {
|
||||||
/* OK, kernel access to userspace. */
|
/* OK, kernel access to userspace. */
|
||||||
recoverable = 1;
|
recoverable = 1;
|
||||||
|
|
||||||
|
@ -1632,9 +1613,8 @@ void cheetah_deferred_handler(struct pt_regs *regs, unsigned long afsr, unsigned
|
||||||
* recoverable condition.
|
* recoverable condition.
|
||||||
*/
|
*/
|
||||||
if (recoverable) {
|
if (recoverable) {
|
||||||
regs->tpc = fixup;
|
regs->tpc = entry->fixup;
|
||||||
regs->tnpc = regs->tpc + 4;
|
regs->tnpc = regs->tpc + 4;
|
||||||
regs->u_regs[UREG_G2] = g2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,6 @@
|
||||||
|
|
||||||
.text
|
.text
|
||||||
|
|
||||||
kernel_unaligned_trap_fault:
|
|
||||||
call kernel_mna_trap_fault
|
|
||||||
nop
|
|
||||||
retl
|
|
||||||
nop
|
|
||||||
.size kern_unaligned_trap_fault, .-kern_unaligned_trap_fault
|
|
||||||
|
|
||||||
.globl __do_int_store
|
.globl __do_int_store
|
||||||
__do_int_store:
|
__do_int_store:
|
||||||
rd %asi, %o4
|
rd %asi, %o4
|
||||||
|
@ -51,24 +44,24 @@ __do_int_store:
|
||||||
0:
|
0:
|
||||||
wr %o4, 0x0, %asi
|
wr %o4, 0x0, %asi
|
||||||
retl
|
retl
|
||||||
nop
|
mov 0, %o0
|
||||||
.size __do_int_store, .-__do_int_store
|
.size __do_int_store, .-__do_int_store
|
||||||
|
|
||||||
.section __ex_table
|
.section __ex_table
|
||||||
.word 4b, kernel_unaligned_trap_fault
|
.word 4b, __retl_efault
|
||||||
.word 5b, kernel_unaligned_trap_fault
|
.word 5b, __retl_efault
|
||||||
.word 6b, kernel_unaligned_trap_fault
|
.word 6b, __retl_efault
|
||||||
.word 7b, kernel_unaligned_trap_fault
|
.word 7b, __retl_efault
|
||||||
.word 8b, kernel_unaligned_trap_fault
|
.word 8b, __retl_efault
|
||||||
.word 9b, kernel_unaligned_trap_fault
|
.word 9b, __retl_efault
|
||||||
.word 10b, kernel_unaligned_trap_fault
|
.word 10b, __retl_efault
|
||||||
.word 11b, kernel_unaligned_trap_fault
|
.word 11b, __retl_efault
|
||||||
.word 12b, kernel_unaligned_trap_fault
|
.word 12b, __retl_efault
|
||||||
.word 13b, kernel_unaligned_trap_fault
|
.word 13b, __retl_efault
|
||||||
.word 14b, kernel_unaligned_trap_fault
|
.word 14b, __retl_efault
|
||||||
.word 15b, kernel_unaligned_trap_fault
|
.word 15b, __retl_efault
|
||||||
.word 16b, kernel_unaligned_trap_fault
|
.word 16b, __retl_efault
|
||||||
.word 17b, kernel_unaligned_trap_fault
|
.word 17b, __retl_efault
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
.globl do_int_load
|
.globl do_int_load
|
||||||
|
@ -133,21 +126,21 @@ do_int_load:
|
||||||
0:
|
0:
|
||||||
wr %o5, 0x0, %asi
|
wr %o5, 0x0, %asi
|
||||||
retl
|
retl
|
||||||
nop
|
mov 0, %o0
|
||||||
.size __do_int_load, .-__do_int_load
|
.size __do_int_load, .-__do_int_load
|
||||||
|
|
||||||
.section __ex_table
|
.section __ex_table
|
||||||
.word 4b, kernel_unaligned_trap_fault
|
.word 4b, __retl_efault
|
||||||
.word 5b, kernel_unaligned_trap_fault
|
.word 5b, __retl_efault
|
||||||
.word 6b, kernel_unaligned_trap_fault
|
.word 6b, __retl_efault
|
||||||
.word 7b, kernel_unaligned_trap_fault
|
.word 7b, __retl_efault
|
||||||
.word 8b, kernel_unaligned_trap_fault
|
.word 8b, __retl_efault
|
||||||
.word 9b, kernel_unaligned_trap_fault
|
.word 9b, __retl_efault
|
||||||
.word 10b, kernel_unaligned_trap_fault
|
.word 10b, __retl_efault
|
||||||
.word 11b, kernel_unaligned_trap_fault
|
.word 11b, __retl_efault
|
||||||
.word 12b, kernel_unaligned_trap_fault
|
.word 12b, __retl_efault
|
||||||
.word 13b, kernel_unaligned_trap_fault
|
.word 13b, __retl_efault
|
||||||
.word 14b, kernel_unaligned_trap_fault
|
.word 14b, __retl_efault
|
||||||
.word 15b, kernel_unaligned_trap_fault
|
.word 15b, __retl_efault
|
||||||
.word 16b, kernel_unaligned_trap_fault
|
.word 16b, __retl_efault
|
||||||
.previous
|
.previous
|
||||||
|
|
|
@ -180,14 +180,14 @@ static void __attribute_used__ unaligned_panic(char *str, struct pt_regs *regs)
|
||||||
die_if_kernel(str, regs);
|
die_if_kernel(str, regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void do_int_load(unsigned long *dest_reg, int size,
|
extern int do_int_load(unsigned long *dest_reg, int size,
|
||||||
unsigned long *saddr, int is_signed, int asi);
|
unsigned long *saddr, int is_signed, int asi);
|
||||||
|
|
||||||
extern void __do_int_store(unsigned long *dst_addr, int size,
|
extern int __do_int_store(unsigned long *dst_addr, int size,
|
||||||
unsigned long src_val, int asi);
|
unsigned long src_val, int asi);
|
||||||
|
|
||||||
static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr,
|
static inline int do_int_store(int reg_num, int size, unsigned long *dst_addr,
|
||||||
struct pt_regs *regs, int asi, int orig_asi)
|
struct pt_regs *regs, int asi, int orig_asi)
|
||||||
{
|
{
|
||||||
unsigned long zero = 0;
|
unsigned long zero = 0;
|
||||||
unsigned long *src_val_p = &zero;
|
unsigned long *src_val_p = &zero;
|
||||||
|
@ -219,7 +219,7 @@ static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr,
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
__do_int_store(dst_addr, size, src_val, asi);
|
return __do_int_store(dst_addr, size, src_val, asi);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void advance(struct pt_regs *regs)
|
static inline void advance(struct pt_regs *regs)
|
||||||
|
@ -242,14 +242,14 @@ static inline int ok_for_kernel(unsigned int insn)
|
||||||
return !floating_point_load_or_store_p(insn);
|
return !floating_point_load_or_store_p(insn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kernel_mna_trap_fault(void)
|
static void kernel_mna_trap_fault(void)
|
||||||
{
|
{
|
||||||
struct pt_regs *regs = current_thread_info()->kern_una_regs;
|
struct pt_regs *regs = current_thread_info()->kern_una_regs;
|
||||||
unsigned int insn = current_thread_info()->kern_una_insn;
|
unsigned int insn = current_thread_info()->kern_una_insn;
|
||||||
unsigned long g2 = regs->u_regs[UREG_G2];
|
const struct exception_table_entry *entry;
|
||||||
unsigned long fixup = search_extables_range(regs->tpc, &g2);
|
|
||||||
|
|
||||||
if (!fixup) {
|
entry = search_exception_tables(regs->tpc);
|
||||||
|
if (!entry) {
|
||||||
unsigned long address;
|
unsigned long address;
|
||||||
|
|
||||||
address = compute_effective_address(regs, insn,
|
address = compute_effective_address(regs, insn,
|
||||||
|
@ -270,9 +270,8 @@ void kernel_mna_trap_fault(void)
|
||||||
die_if_kernel("Oops", regs);
|
die_if_kernel("Oops", regs);
|
||||||
/* Not reached */
|
/* Not reached */
|
||||||
}
|
}
|
||||||
regs->tpc = fixup;
|
regs->tpc = entry->fixup;
|
||||||
regs->tnpc = regs->tpc + 4;
|
regs->tnpc = regs->tpc + 4;
|
||||||
regs->u_regs [UREG_G2] = g2;
|
|
||||||
|
|
||||||
regs->tstate &= ~TSTATE_ASI;
|
regs->tstate &= ~TSTATE_ASI;
|
||||||
regs->tstate |= (ASI_AIUS << 24UL);
|
regs->tstate |= (ASI_AIUS << 24UL);
|
||||||
|
@ -295,7 +294,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u
|
||||||
kernel_mna_trap_fault();
|
kernel_mna_trap_fault();
|
||||||
} else {
|
} else {
|
||||||
unsigned long addr, *reg_addr;
|
unsigned long addr, *reg_addr;
|
||||||
int orig_asi, asi;
|
int orig_asi, asi, err;
|
||||||
|
|
||||||
addr = compute_effective_address(regs, insn,
|
addr = compute_effective_address(regs, insn,
|
||||||
((insn >> 25) & 0x1f));
|
((insn >> 25) & 0x1f));
|
||||||
|
@ -320,9 +319,10 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u
|
||||||
switch (dir) {
|
switch (dir) {
|
||||||
case load:
|
case load:
|
||||||
reg_addr = fetch_reg_addr(((insn>>25)&0x1f), regs);
|
reg_addr = fetch_reg_addr(((insn>>25)&0x1f), regs);
|
||||||
do_int_load(reg_addr, size, (unsigned long *) addr,
|
err = do_int_load(reg_addr, size,
|
||||||
decode_signedness(insn), asi);
|
(unsigned long *) addr,
|
||||||
if (unlikely(asi != orig_asi)) {
|
decode_signedness(insn), asi);
|
||||||
|
if (likely(!err) && unlikely(asi != orig_asi)) {
|
||||||
unsigned long val_in = *reg_addr;
|
unsigned long val_in = *reg_addr;
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 2:
|
case 2:
|
||||||
|
@ -344,16 +344,19 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case store:
|
case store:
|
||||||
do_int_store(((insn>>25)&0x1f), size,
|
err = do_int_store(((insn>>25)&0x1f), size,
|
||||||
(unsigned long *) addr, regs,
|
(unsigned long *) addr, regs,
|
||||||
asi, orig_asi);
|
asi, orig_asi);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic("Impossible kernel unaligned trap.");
|
panic("Impossible kernel unaligned trap.");
|
||||||
/* Not reached... */
|
/* Not reached... */
|
||||||
}
|
}
|
||||||
advance(regs);
|
if (unlikely(err))
|
||||||
|
kernel_mna_trap_fault();
|
||||||
|
else
|
||||||
|
advance(regs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -125,15 +125,11 @@ __strncpy_from_user:
|
||||||
add %o2, %o3, %o0
|
add %o2, %o3, %o0
|
||||||
.size __strncpy_from_user, .-__strncpy_from_user
|
.size __strncpy_from_user, .-__strncpy_from_user
|
||||||
|
|
||||||
.section .fixup,#alloc,#execinstr
|
|
||||||
.align 4
|
|
||||||
4: retl
|
|
||||||
mov -EFAULT, %o0
|
|
||||||
|
|
||||||
.section __ex_table,#alloc
|
.section __ex_table,#alloc
|
||||||
.align 4
|
.align 4
|
||||||
.word 60b, 4b
|
.word 60b, __retl_efault
|
||||||
.word 61b, 4b
|
.word 61b, __retl_efault
|
||||||
.word 62b, 4b
|
.word 62b, __retl_efault
|
||||||
.word 63b, 4b
|
.word 63b, __retl_efault
|
||||||
.word 64b, 4b
|
.word 64b, __retl_efault
|
||||||
|
.previous
|
||||||
|
|
|
@ -11,61 +11,56 @@
|
||||||
|
|
||||||
/* Calculating the exact fault address when using
|
/* Calculating the exact fault address when using
|
||||||
* block loads and stores can be very complicated.
|
* block loads and stores can be very complicated.
|
||||||
|
*
|
||||||
* Instead of trying to be clever and handling all
|
* Instead of trying to be clever and handling all
|
||||||
* of the cases, just fix things up simply here.
|
* of the cases, just fix things up simply here.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static unsigned long compute_size(unsigned long start, unsigned long size, unsigned long *offset)
|
||||||
|
{
|
||||||
|
unsigned long fault_addr = current_thread_info()->fault_address;
|
||||||
|
unsigned long end = start + size;
|
||||||
|
|
||||||
|
if (fault_addr < start || fault_addr >= end) {
|
||||||
|
*offset = 0;
|
||||||
|
} else {
|
||||||
|
*offset = start - fault_addr;
|
||||||
|
size = end - fault_addr;
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned long copy_from_user_fixup(void *to, const void __user *from, unsigned long size)
|
unsigned long copy_from_user_fixup(void *to, const void __user *from, unsigned long size)
|
||||||
{
|
{
|
||||||
char *dst = to;
|
unsigned long offset;
|
||||||
const char __user *src = from;
|
|
||||||
|
|
||||||
while (size) {
|
size = compute_size((unsigned long) from, size, &offset);
|
||||||
if (__get_user(*dst, src))
|
if (likely(size))
|
||||||
break;
|
memset(to + offset, 0, size);
|
||||||
dst++;
|
|
||||||
src++;
|
|
||||||
size--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size)
|
|
||||||
memset(dst, 0, size);
|
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long copy_to_user_fixup(void __user *to, const void *from, unsigned long size)
|
unsigned long copy_to_user_fixup(void __user *to, const void *from, unsigned long size)
|
||||||
{
|
{
|
||||||
char __user *dst = to;
|
unsigned long offset;
|
||||||
const char *src = from;
|
|
||||||
|
|
||||||
while (size) {
|
return compute_size((unsigned long) to, size, &offset);
|
||||||
if (__put_user(*src, dst))
|
|
||||||
break;
|
|
||||||
dst++;
|
|
||||||
src++;
|
|
||||||
size--;
|
|
||||||
}
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long copy_in_user_fixup(void __user *to, void __user *from, unsigned long size)
|
unsigned long copy_in_user_fixup(void __user *to, void __user *from, unsigned long size)
|
||||||
{
|
{
|
||||||
char __user *dst = to;
|
unsigned long fault_addr = current_thread_info()->fault_address;
|
||||||
char __user *src = from;
|
unsigned long start = (unsigned long) to;
|
||||||
|
unsigned long end = start + size;
|
||||||
|
|
||||||
while (size) {
|
if (fault_addr >= start && fault_addr < end)
|
||||||
char tmp;
|
return end - fault_addr;
|
||||||
|
|
||||||
if (__get_user(tmp, src))
|
start = (unsigned long) from;
|
||||||
break;
|
end = start + size;
|
||||||
if (__put_user(tmp, dst))
|
if (fault_addr >= start && fault_addr < end)
|
||||||
break;
|
return end - fault_addr;
|
||||||
dst++;
|
|
||||||
src++;
|
|
||||||
size--;
|
|
||||||
}
|
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,6 @@
|
||||||
EXTRA_AFLAGS := -ansi
|
EXTRA_AFLAGS := -ansi
|
||||||
EXTRA_CFLAGS := -Werror
|
EXTRA_CFLAGS := -Werror
|
||||||
|
|
||||||
obj-y := ultra.o tlb.o fault.o init.o generic.o extable.o
|
obj-y := ultra.o tlb.o fault.o init.o generic.o
|
||||||
|
|
||||||
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
|
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
|
||||||
|
|
|
@ -1,80 +0,0 @@
|
||||||
/*
|
|
||||||
* linux/arch/sparc64/mm/extable.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/config.h>
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include <asm/uaccess.h>
|
|
||||||
|
|
||||||
extern const struct exception_table_entry __start___ex_table[];
|
|
||||||
extern const struct exception_table_entry __stop___ex_table[];
|
|
||||||
|
|
||||||
void sort_extable(struct exception_table_entry *start,
|
|
||||||
struct exception_table_entry *finish)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Caller knows they are in a range if ret->fixup == 0 */
|
|
||||||
const struct exception_table_entry *
|
|
||||||
search_extable(const struct exception_table_entry *start,
|
|
||||||
const struct exception_table_entry *last,
|
|
||||||
unsigned long value)
|
|
||||||
{
|
|
||||||
const struct exception_table_entry *walk;
|
|
||||||
|
|
||||||
/* Single insn entries are encoded as:
|
|
||||||
* word 1: insn address
|
|
||||||
* word 2: fixup code address
|
|
||||||
*
|
|
||||||
* Range entries are encoded as:
|
|
||||||
* word 1: first insn address
|
|
||||||
* word 2: 0
|
|
||||||
* word 3: last insn address + 4 bytes
|
|
||||||
* word 4: fixup code address
|
|
||||||
*
|
|
||||||
* See asm/uaccess.h for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* 1. Try to find an exact match. */
|
|
||||||
for (walk = start; walk <= last; walk++) {
|
|
||||||
if (walk->fixup == 0) {
|
|
||||||
/* A range entry, skip both parts. */
|
|
||||||
walk++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (walk->insn == value)
|
|
||||||
return walk;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 2. Try to find a range match. */
|
|
||||||
for (walk = start; walk <= (last - 1); walk++) {
|
|
||||||
if (walk->fixup)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (walk[0].insn <= value && walk[1].insn > value)
|
|
||||||
return walk;
|
|
||||||
|
|
||||||
walk++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Special extable search, which handles ranges. Returns fixup */
|
|
||||||
unsigned long search_extables_range(unsigned long addr, unsigned long *g2)
|
|
||||||
{
|
|
||||||
const struct exception_table_entry *entry;
|
|
||||||
|
|
||||||
entry = search_exception_tables(addr);
|
|
||||||
if (!entry)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Inside range? Fix g2 and return correct fixup */
|
|
||||||
if (!entry->fixup) {
|
|
||||||
*g2 = (addr - entry->insn) / 4;
|
|
||||||
return (entry + 1)->fixup;
|
|
||||||
}
|
|
||||||
|
|
||||||
return entry->fixup;
|
|
||||||
}
|
|
|
@ -32,8 +32,6 @@
|
||||||
|
|
||||||
#define ELEMENTS(arr) (sizeof (arr)/sizeof (arr[0]))
|
#define ELEMENTS(arr) (sizeof (arr)/sizeof (arr[0]))
|
||||||
|
|
||||||
extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* To debug kernel to catch accesses to certain virtual/physical addresses.
|
* To debug kernel to catch accesses to certain virtual/physical addresses.
|
||||||
* Mode = 0 selects physical watchpoints, mode = 1 selects virtual watchpoints.
|
* Mode = 0 selects physical watchpoints, mode = 1 selects virtual watchpoints.
|
||||||
|
@ -71,53 +69,6 @@ void set_brkpt(unsigned long addr, unsigned char mask, int flags, int mode)
|
||||||
: "memory");
|
: "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Nice, simple, prom library does all the sweating for us. ;) */
|
|
||||||
unsigned long __init prom_probe_memory (void)
|
|
||||||
{
|
|
||||||
register struct linux_mlist_p1275 *mlist;
|
|
||||||
register unsigned long bytes, base_paddr, tally;
|
|
||||||
register int i;
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
mlist = *prom_meminfo()->p1275_available;
|
|
||||||
bytes = tally = mlist->num_bytes;
|
|
||||||
base_paddr = mlist->start_adr;
|
|
||||||
|
|
||||||
sp_banks[0].base_addr = base_paddr;
|
|
||||||
sp_banks[0].num_bytes = bytes;
|
|
||||||
|
|
||||||
while (mlist->theres_more != (void *) 0) {
|
|
||||||
i++;
|
|
||||||
mlist = mlist->theres_more;
|
|
||||||
bytes = mlist->num_bytes;
|
|
||||||
tally += bytes;
|
|
||||||
if (i >= SPARC_PHYS_BANKS-1) {
|
|
||||||
printk ("The machine has more banks than "
|
|
||||||
"this kernel can support\n"
|
|
||||||
"Increase the SPARC_PHYS_BANKS "
|
|
||||||
"setting (currently %d)\n",
|
|
||||||
SPARC_PHYS_BANKS);
|
|
||||||
i = SPARC_PHYS_BANKS-1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
sp_banks[i].base_addr = mlist->start_adr;
|
|
||||||
sp_banks[i].num_bytes = mlist->num_bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
i++;
|
|
||||||
sp_banks[i].base_addr = 0xdeadbeefbeefdeadUL;
|
|
||||||
sp_banks[i].num_bytes = 0;
|
|
||||||
|
|
||||||
/* Now mask all bank sizes on a page boundary, it is all we can
|
|
||||||
* use anyways.
|
|
||||||
*/
|
|
||||||
for (i = 0; sp_banks[i].num_bytes != 0; i++)
|
|
||||||
sp_banks[i].num_bytes &= PAGE_MASK;
|
|
||||||
|
|
||||||
return tally;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __kprobes unhandled_fault(unsigned long address,
|
static void __kprobes unhandled_fault(unsigned long address,
|
||||||
struct task_struct *tsk,
|
struct task_struct *tsk,
|
||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
|
@ -242,7 +193,6 @@ static unsigned int get_fault_insn(struct pt_regs *regs, unsigned int insn)
|
||||||
static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code,
|
static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code,
|
||||||
unsigned int insn, unsigned long address)
|
unsigned int insn, unsigned long address)
|
||||||
{
|
{
|
||||||
unsigned long g2;
|
|
||||||
unsigned char asi = ASI_P;
|
unsigned char asi = ASI_P;
|
||||||
|
|
||||||
if ((!insn) && (regs->tstate & TSTATE_PRIV))
|
if ((!insn) && (regs->tstate & TSTATE_PRIV))
|
||||||
|
@ -273,11 +223,9 @@ static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g2 = regs->u_regs[UREG_G2];
|
|
||||||
|
|
||||||
/* Is this in ex_table? */
|
/* Is this in ex_table? */
|
||||||
if (regs->tstate & TSTATE_PRIV) {
|
if (regs->tstate & TSTATE_PRIV) {
|
||||||
unsigned long fixup;
|
const struct exception_table_entry *entry;
|
||||||
|
|
||||||
if (asi == ASI_P && (insn & 0xc0800000) == 0xc0800000) {
|
if (asi == ASI_P && (insn & 0xc0800000) == 0xc0800000) {
|
||||||
if (insn & 0x2000)
|
if (insn & 0x2000)
|
||||||
|
@ -288,10 +236,9 @@ static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code,
|
||||||
|
|
||||||
/* Look in asi.h: All _S asis have LS bit set */
|
/* Look in asi.h: All _S asis have LS bit set */
|
||||||
if ((asi & 0x1) &&
|
if ((asi & 0x1) &&
|
||||||
(fixup = search_extables_range(regs->tpc, &g2))) {
|
(entry = search_exception_tables(regs->tpc))) {
|
||||||
regs->tpc = fixup;
|
regs->tpc = entry->fixup;
|
||||||
regs->tnpc = regs->tpc + 4;
|
regs->tnpc = regs->tpc + 4;
|
||||||
regs->u_regs[UREG_G2] = g2;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -461,7 +408,7 @@ good_area:
|
||||||
}
|
}
|
||||||
|
|
||||||
up_read(&mm->mmap_sem);
|
up_read(&mm->mmap_sem);
|
||||||
goto fault_done;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Something tried to access memory that isn't in our memory map..
|
* Something tried to access memory that isn't in our memory map..
|
||||||
|
@ -473,8 +420,7 @@ bad_area:
|
||||||
|
|
||||||
handle_kernel_fault:
|
handle_kernel_fault:
|
||||||
do_kernel_fault(regs, si_code, fault_code, insn, address);
|
do_kernel_fault(regs, si_code, fault_code, insn, address);
|
||||||
|
return;
|
||||||
goto fault_done;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We ran out of memory, or some other thing happened to us that made
|
* We ran out of memory, or some other thing happened to us that made
|
||||||
|
@ -505,9 +451,4 @@ do_sigbus:
|
||||||
/* Kernel mode? Handle exceptions or die */
|
/* Kernel mode? Handle exceptions or die */
|
||||||
if (regs->tstate & TSTATE_PRIV)
|
if (regs->tstate & TSTATE_PRIV)
|
||||||
goto handle_kernel_fault;
|
goto handle_kernel_fault;
|
||||||
|
|
||||||
fault_done:
|
|
||||||
/* These values are no longer needed, clear them. */
|
|
||||||
set_thread_fault_code(0);
|
|
||||||
current_thread_info()->fault_address = 0;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
#include <linux/kprobes.h>
|
#include <linux/kprobes.h>
|
||||||
#include <linux/cache.h>
|
#include <linux/cache.h>
|
||||||
|
#include <linux/sort.h>
|
||||||
|
|
||||||
#include <asm/head.h>
|
#include <asm/head.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
|
@ -41,7 +42,72 @@
|
||||||
|
|
||||||
extern void device_scan(void);
|
extern void device_scan(void);
|
||||||
|
|
||||||
struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
|
#define MAX_BANKS 32
|
||||||
|
|
||||||
|
static struct linux_prom64_registers pavail[MAX_BANKS] __initdata;
|
||||||
|
static struct linux_prom64_registers pavail_rescan[MAX_BANKS] __initdata;
|
||||||
|
static int pavail_ents __initdata;
|
||||||
|
static int pavail_rescan_ents __initdata;
|
||||||
|
|
||||||
|
static int cmp_p64(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const struct linux_prom64_registers *x = a, *y = b;
|
||||||
|
|
||||||
|
if (x->phys_addr > y->phys_addr)
|
||||||
|
return 1;
|
||||||
|
if (x->phys_addr < y->phys_addr)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __init read_obp_memory(const char *property,
|
||||||
|
struct linux_prom64_registers *regs,
|
||||||
|
int *num_ents)
|
||||||
|
{
|
||||||
|
int node = prom_finddevice("/memory");
|
||||||
|
int prop_size = prom_getproplen(node, property);
|
||||||
|
int ents, ret, i;
|
||||||
|
|
||||||
|
ents = prop_size / sizeof(struct linux_prom64_registers);
|
||||||
|
if (ents > MAX_BANKS) {
|
||||||
|
prom_printf("The machine has more %s property entries than "
|
||||||
|
"this kernel can support (%d).\n",
|
||||||
|
property, MAX_BANKS);
|
||||||
|
prom_halt();
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = prom_getproperty(node, property, (char *) regs, prop_size);
|
||||||
|
if (ret == -1) {
|
||||||
|
prom_printf("Couldn't get %s property from /memory.\n");
|
||||||
|
prom_halt();
|
||||||
|
}
|
||||||
|
|
||||||
|
*num_ents = ents;
|
||||||
|
|
||||||
|
/* Sanitize what we got from the firmware, by page aligning
|
||||||
|
* everything.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < ents; i++) {
|
||||||
|
unsigned long base, size;
|
||||||
|
|
||||||
|
base = regs[i].phys_addr;
|
||||||
|
size = regs[i].reg_size;
|
||||||
|
|
||||||
|
size &= PAGE_MASK;
|
||||||
|
if (base & ~PAGE_MASK) {
|
||||||
|
unsigned long new_base = PAGE_ALIGN(base);
|
||||||
|
|
||||||
|
size -= new_base - base;
|
||||||
|
if ((long) size < 0L)
|
||||||
|
size = 0UL;
|
||||||
|
base = new_base;
|
||||||
|
}
|
||||||
|
regs[i].phys_addr = base;
|
||||||
|
regs[i].reg_size = size;
|
||||||
|
}
|
||||||
|
sort(regs, ents, sizeof(struct linux_prom64_registers),
|
||||||
|
cmp_p64, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
unsigned long *sparc64_valid_addr_bitmap __read_mostly;
|
unsigned long *sparc64_valid_addr_bitmap __read_mostly;
|
||||||
|
|
||||||
|
@ -1206,14 +1272,14 @@ unsigned long __init bootmem_init(unsigned long *pages_avail)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_BOOTMEM
|
#ifdef CONFIG_DEBUG_BOOTMEM
|
||||||
prom_printf("bootmem_init: Scan sp_banks, ");
|
prom_printf("bootmem_init: Scan pavail, ");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bytes_avail = 0UL;
|
bytes_avail = 0UL;
|
||||||
for (i = 0; sp_banks[i].num_bytes != 0; i++) {
|
for (i = 0; i < pavail_ents; i++) {
|
||||||
end_of_phys_memory = sp_banks[i].base_addr +
|
end_of_phys_memory = pavail[i].phys_addr +
|
||||||
sp_banks[i].num_bytes;
|
pavail[i].reg_size;
|
||||||
bytes_avail += sp_banks[i].num_bytes;
|
bytes_avail += pavail[i].reg_size;
|
||||||
if (cmdline_memory_size) {
|
if (cmdline_memory_size) {
|
||||||
if (bytes_avail > cmdline_memory_size) {
|
if (bytes_avail > cmdline_memory_size) {
|
||||||
unsigned long slack = bytes_avail - cmdline_memory_size;
|
unsigned long slack = bytes_avail - cmdline_memory_size;
|
||||||
|
@ -1221,12 +1287,15 @@ unsigned long __init bootmem_init(unsigned long *pages_avail)
|
||||||
bytes_avail -= slack;
|
bytes_avail -= slack;
|
||||||
end_of_phys_memory -= slack;
|
end_of_phys_memory -= slack;
|
||||||
|
|
||||||
sp_banks[i].num_bytes -= slack;
|
pavail[i].reg_size -= slack;
|
||||||
if (sp_banks[i].num_bytes == 0) {
|
if ((long)pavail[i].reg_size <= 0L) {
|
||||||
sp_banks[i].base_addr = 0xdeadbeef;
|
pavail[i].phys_addr = 0xdeadbeefUL;
|
||||||
|
pavail[i].reg_size = 0UL;
|
||||||
|
pavail_ents = i;
|
||||||
} else {
|
} else {
|
||||||
sp_banks[i+1].num_bytes = 0;
|
pavail[i+1].reg_size = 0Ul;
|
||||||
sp_banks[i+1].base_addr = 0xdeadbeef;
|
pavail[i+1].phys_addr = 0xdeadbeefUL;
|
||||||
|
pavail_ents = i + 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1280,12 +1349,12 @@ unsigned long __init bootmem_init(unsigned long *pages_avail)
|
||||||
/* Now register the available physical memory with the
|
/* Now register the available physical memory with the
|
||||||
* allocator.
|
* allocator.
|
||||||
*/
|
*/
|
||||||
for (i = 0; sp_banks[i].num_bytes != 0; i++) {
|
for (i = 0; i < pavail_ents; i++) {
|
||||||
#ifdef CONFIG_DEBUG_BOOTMEM
|
#ifdef CONFIG_DEBUG_BOOTMEM
|
||||||
prom_printf("free_bootmem(sp_banks:%d): base[%lx] size[%lx]\n",
|
prom_printf("free_bootmem(pavail:%d): base[%lx] size[%lx]\n",
|
||||||
i, sp_banks[i].base_addr, sp_banks[i].num_bytes);
|
i, pavail[i].phys_addr, pavail[i].reg_size);
|
||||||
#endif
|
#endif
|
||||||
free_bootmem(sp_banks[i].base_addr, sp_banks[i].num_bytes);
|
free_bootmem(pavail[i].phys_addr, pavail[i].reg_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_BLK_DEV_INITRD
|
#ifdef CONFIG_BLK_DEV_INITRD
|
||||||
|
@ -1334,7 +1403,7 @@ static unsigned long kernel_map_range(unsigned long pstart, unsigned long pend,
|
||||||
unsigned long alloc_bytes = 0UL;
|
unsigned long alloc_bytes = 0UL;
|
||||||
|
|
||||||
if ((vstart & ~PAGE_MASK) || (vend & ~PAGE_MASK)) {
|
if ((vstart & ~PAGE_MASK) || (vend & ~PAGE_MASK)) {
|
||||||
prom_printf("kernel_map: Unaligned sp_banks[%lx:%lx]\n",
|
prom_printf("kernel_map: Unaligned physmem[%lx:%lx]\n",
|
||||||
vstart, vend);
|
vstart, vend);
|
||||||
prom_halt();
|
prom_halt();
|
||||||
}
|
}
|
||||||
|
@ -1381,23 +1450,24 @@ static unsigned long kernel_map_range(unsigned long pstart, unsigned long pend,
|
||||||
return alloc_bytes;
|
return alloc_bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern struct linux_mlist_p1275 *prom_ptot_ptr;
|
static struct linux_prom64_registers pall[MAX_BANKS] __initdata;
|
||||||
|
static int pall_ents __initdata;
|
||||||
|
|
||||||
extern unsigned int kvmap_linear_patch[1];
|
extern unsigned int kvmap_linear_patch[1];
|
||||||
|
|
||||||
static void __init kernel_physical_mapping_init(void)
|
static void __init kernel_physical_mapping_init(void)
|
||||||
{
|
{
|
||||||
struct linux_mlist_p1275 *p = prom_ptot_ptr;
|
unsigned long i, mem_alloced = 0UL;
|
||||||
unsigned long mem_alloced = 0UL;
|
|
||||||
|
|
||||||
while (p) {
|
read_obp_memory("reg", &pall[0], &pall_ents);
|
||||||
|
|
||||||
|
for (i = 0; i < pall_ents; i++) {
|
||||||
unsigned long phys_start, phys_end;
|
unsigned long phys_start, phys_end;
|
||||||
|
|
||||||
phys_start = p->start_adr;
|
phys_start = pall[i].phys_addr;
|
||||||
phys_end = phys_start + p->num_bytes;
|
phys_end = phys_start + pall[i].reg_size;
|
||||||
mem_alloced += kernel_map_range(phys_start, phys_end,
|
mem_alloced += kernel_map_range(phys_start, phys_end,
|
||||||
PAGE_KERNEL);
|
PAGE_KERNEL);
|
||||||
|
|
||||||
p = p->theres_more;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printk("Allocated %ld bytes for kernel page tables.\n",
|
printk("Allocated %ld bytes for kernel page tables.\n",
|
||||||
|
@ -1425,6 +1495,18 @@ void kernel_map_pages(struct page *page, int numpages, int enable)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
unsigned long __init find_ecache_flush_span(unsigned long size)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < pavail_ents; i++) {
|
||||||
|
if (pavail[i].reg_size >= size)
|
||||||
|
return pavail[i].phys_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ~0UL;
|
||||||
|
}
|
||||||
|
|
||||||
/* paging_init() sets up the page tables */
|
/* paging_init() sets up the page tables */
|
||||||
|
|
||||||
extern void cheetah_ecache_flush_init(void);
|
extern void cheetah_ecache_flush_init(void);
|
||||||
|
@ -1435,7 +1517,19 @@ pgd_t swapper_pg_dir[2048];
|
||||||
void __init paging_init(void)
|
void __init paging_init(void)
|
||||||
{
|
{
|
||||||
unsigned long end_pfn, pages_avail, shift;
|
unsigned long end_pfn, pages_avail, shift;
|
||||||
unsigned long real_end;
|
unsigned long real_end, i;
|
||||||
|
|
||||||
|
/* Find available physical memory... */
|
||||||
|
read_obp_memory("available", &pavail[0], &pavail_ents);
|
||||||
|
|
||||||
|
phys_base = 0xffffffffffffffffUL;
|
||||||
|
for (i = 0; i < pavail_ents; i++)
|
||||||
|
phys_base = min(phys_base, pavail[i].phys_addr);
|
||||||
|
|
||||||
|
pfn_base = phys_base >> PAGE_SHIFT;
|
||||||
|
|
||||||
|
kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL;
|
||||||
|
kern_size = (unsigned long)&_end - (unsigned long)KERNBASE;
|
||||||
|
|
||||||
set_bit(0, mmu_context_bmap);
|
set_bit(0, mmu_context_bmap);
|
||||||
|
|
||||||
|
@ -1507,128 +1601,35 @@ void __init paging_init(void)
|
||||||
device_scan();
|
device_scan();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ok, it seems that the prom can allocate some more memory chunks
|
|
||||||
* as a side effect of some prom calls we perform during the
|
|
||||||
* boot sequence. My most likely theory is that it is from the
|
|
||||||
* prom_set_traptable() call, and OBP is allocating a scratchpad
|
|
||||||
* for saving client program register state etc.
|
|
||||||
*/
|
|
||||||
static void __init sort_memlist(struct linux_mlist_p1275 *thislist)
|
|
||||||
{
|
|
||||||
int swapi = 0;
|
|
||||||
int i, mitr;
|
|
||||||
unsigned long tmpaddr, tmpsize;
|
|
||||||
unsigned long lowest;
|
|
||||||
|
|
||||||
for (i = 0; thislist[i].theres_more != 0; i++) {
|
|
||||||
lowest = thislist[i].start_adr;
|
|
||||||
for (mitr = i+1; thislist[mitr-1].theres_more != 0; mitr++)
|
|
||||||
if (thislist[mitr].start_adr < lowest) {
|
|
||||||
lowest = thislist[mitr].start_adr;
|
|
||||||
swapi = mitr;
|
|
||||||
}
|
|
||||||
if (lowest == thislist[i].start_adr)
|
|
||||||
continue;
|
|
||||||
tmpaddr = thislist[swapi].start_adr;
|
|
||||||
tmpsize = thislist[swapi].num_bytes;
|
|
||||||
for (mitr = swapi; mitr > i; mitr--) {
|
|
||||||
thislist[mitr].start_adr = thislist[mitr-1].start_adr;
|
|
||||||
thislist[mitr].num_bytes = thislist[mitr-1].num_bytes;
|
|
||||||
}
|
|
||||||
thislist[i].start_adr = tmpaddr;
|
|
||||||
thislist[i].num_bytes = tmpsize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void __init rescan_sp_banks(void)
|
|
||||||
{
|
|
||||||
struct linux_prom64_registers memlist[64];
|
|
||||||
struct linux_mlist_p1275 avail[64], *mlist;
|
|
||||||
unsigned long bytes, base_paddr;
|
|
||||||
int num_regs, node = prom_finddevice("/memory");
|
|
||||||
int i;
|
|
||||||
|
|
||||||
num_regs = prom_getproperty(node, "available",
|
|
||||||
(char *) memlist, sizeof(memlist));
|
|
||||||
num_regs = (num_regs / sizeof(struct linux_prom64_registers));
|
|
||||||
for (i = 0; i < num_regs; i++) {
|
|
||||||
avail[i].start_adr = memlist[i].phys_addr;
|
|
||||||
avail[i].num_bytes = memlist[i].reg_size;
|
|
||||||
avail[i].theres_more = &avail[i + 1];
|
|
||||||
}
|
|
||||||
avail[i - 1].theres_more = NULL;
|
|
||||||
sort_memlist(avail);
|
|
||||||
|
|
||||||
mlist = &avail[0];
|
|
||||||
i = 0;
|
|
||||||
bytes = mlist->num_bytes;
|
|
||||||
base_paddr = mlist->start_adr;
|
|
||||||
|
|
||||||
sp_banks[0].base_addr = base_paddr;
|
|
||||||
sp_banks[0].num_bytes = bytes;
|
|
||||||
|
|
||||||
while (mlist->theres_more != NULL){
|
|
||||||
i++;
|
|
||||||
mlist = mlist->theres_more;
|
|
||||||
bytes = mlist->num_bytes;
|
|
||||||
if (i >= SPARC_PHYS_BANKS-1) {
|
|
||||||
printk ("The machine has more banks than "
|
|
||||||
"this kernel can support\n"
|
|
||||||
"Increase the SPARC_PHYS_BANKS "
|
|
||||||
"setting (currently %d)\n",
|
|
||||||
SPARC_PHYS_BANKS);
|
|
||||||
i = SPARC_PHYS_BANKS-1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
sp_banks[i].base_addr = mlist->start_adr;
|
|
||||||
sp_banks[i].num_bytes = mlist->num_bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
i++;
|
|
||||||
sp_banks[i].base_addr = 0xdeadbeefbeefdeadUL;
|
|
||||||
sp_banks[i].num_bytes = 0;
|
|
||||||
|
|
||||||
for (i = 0; sp_banks[i].num_bytes != 0; i++)
|
|
||||||
sp_banks[i].num_bytes &= PAGE_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __init taint_real_pages(void)
|
static void __init taint_real_pages(void)
|
||||||
{
|
{
|
||||||
struct sparc_phys_banks saved_sp_banks[SPARC_PHYS_BANKS];
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < SPARC_PHYS_BANKS; i++) {
|
read_obp_memory("available", &pavail_rescan[0], &pavail_rescan_ents);
|
||||||
saved_sp_banks[i].base_addr =
|
|
||||||
sp_banks[i].base_addr;
|
|
||||||
saved_sp_banks[i].num_bytes =
|
|
||||||
sp_banks[i].num_bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
rescan_sp_banks();
|
/* Find changes discovered in the physmem available rescan and
|
||||||
|
|
||||||
/* Find changes discovered in the sp_bank rescan and
|
|
||||||
* reserve the lost portions in the bootmem maps.
|
* reserve the lost portions in the bootmem maps.
|
||||||
*/
|
*/
|
||||||
for (i = 0; saved_sp_banks[i].num_bytes; i++) {
|
for (i = 0; i < pavail_ents; i++) {
|
||||||
unsigned long old_start, old_end;
|
unsigned long old_start, old_end;
|
||||||
|
|
||||||
old_start = saved_sp_banks[i].base_addr;
|
old_start = pavail[i].phys_addr;
|
||||||
old_end = old_start +
|
old_end = old_start +
|
||||||
saved_sp_banks[i].num_bytes;
|
pavail[i].reg_size;
|
||||||
while (old_start < old_end) {
|
while (old_start < old_end) {
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
for (n = 0; sp_banks[n].num_bytes; n++) {
|
for (n = 0; pavail_rescan_ents; n++) {
|
||||||
unsigned long new_start, new_end;
|
unsigned long new_start, new_end;
|
||||||
|
|
||||||
new_start = sp_banks[n].base_addr;
|
new_start = pavail_rescan[n].phys_addr;
|
||||||
new_end = new_start + sp_banks[n].num_bytes;
|
new_end = new_start +
|
||||||
|
pavail_rescan[n].reg_size;
|
||||||
|
|
||||||
if (new_start <= old_start &&
|
if (new_start <= old_start &&
|
||||||
new_end >= (old_start + PAGE_SIZE)) {
|
new_end >= (old_start + PAGE_SIZE)) {
|
||||||
set_bit (old_start >> 22,
|
set_bit(old_start >> 22,
|
||||||
sparc64_valid_addr_bitmap);
|
sparc64_valid_addr_bitmap);
|
||||||
goto do_next_page;
|
goto do_next_page;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,5 +6,5 @@
|
||||||
EXTRA_AFLAGS := -ansi
|
EXTRA_AFLAGS := -ansi
|
||||||
EXTRA_CFLAGS := -Werror
|
EXTRA_CFLAGS := -Werror
|
||||||
|
|
||||||
lib-y := bootstr.o devops.o init.o memory.o misc.o \
|
lib-y := bootstr.o devops.o init.o misc.o \
|
||||||
tree.o console.o printf.o p1275.o cif.o
|
tree.o console.o printf.o p1275.o cif.o
|
||||||
|
|
|
@ -27,7 +27,6 @@ int prom_chosen_node;
|
||||||
* failure. It gets passed the pointer to the PROM vector.
|
* failure. It gets passed the pointer to the PROM vector.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern void prom_meminit(void);
|
|
||||||
extern void prom_cif_init(void *, void *);
|
extern void prom_cif_init(void *, void *);
|
||||||
|
|
||||||
void __init prom_init(void *cif_handler, void *cif_stack)
|
void __init prom_init(void *cif_handler, void *cif_stack)
|
||||||
|
@ -90,8 +89,6 @@ void __init prom_init(void *cif_handler, void *cif_stack)
|
||||||
|
|
||||||
printk ("PROMLIB: Sun IEEE Boot Prom %s\n", buffer + bufadjust);
|
printk ("PROMLIB: Sun IEEE Boot Prom %s\n", buffer + bufadjust);
|
||||||
|
|
||||||
prom_meminit();
|
|
||||||
|
|
||||||
/* Initialization successful. */
|
/* Initialization successful. */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -1,152 +0,0 @@
|
||||||
/* $Id: memory.c,v 1.5 1999/08/31 06:55:04 davem Exp $
|
|
||||||
* memory.c: Prom routine for acquiring various bits of information
|
|
||||||
* about RAM on the machine, both virtual and physical.
|
|
||||||
*
|
|
||||||
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
|
|
||||||
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
|
||||||
#include <linux/init.h>
|
|
||||||
|
|
||||||
#include <asm/openprom.h>
|
|
||||||
#include <asm/oplib.h>
|
|
||||||
|
|
||||||
/* This routine, for consistency, returns the ram parameters in the
|
|
||||||
* V0 prom memory descriptor format. I choose this format because I
|
|
||||||
* think it was the easiest to work with. I feel the religious
|
|
||||||
* arguments now... ;) Also, I return the linked lists sorted to
|
|
||||||
* prevent paging_init() upset stomach as I have not yet written
|
|
||||||
* the pepto-bismol kernel module yet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct linux_prom64_registers prom_reg_memlist[64];
|
|
||||||
struct linux_prom64_registers prom_reg_tmp[64];
|
|
||||||
|
|
||||||
struct linux_mlist_p1275 prom_phys_total[64];
|
|
||||||
struct linux_mlist_p1275 prom_prom_taken[64];
|
|
||||||
struct linux_mlist_p1275 prom_phys_avail[64];
|
|
||||||
|
|
||||||
struct linux_mlist_p1275 *prom_ptot_ptr = prom_phys_total;
|
|
||||||
struct linux_mlist_p1275 *prom_ptak_ptr = prom_prom_taken;
|
|
||||||
struct linux_mlist_p1275 *prom_pavl_ptr = prom_phys_avail;
|
|
||||||
|
|
||||||
struct linux_mem_p1275 prom_memlist;
|
|
||||||
|
|
||||||
|
|
||||||
/* Internal Prom library routine to sort a linux_mlist_p1275 memory
|
|
||||||
* list. Used below in initialization.
|
|
||||||
*/
|
|
||||||
static void __init
|
|
||||||
prom_sortmemlist(struct linux_mlist_p1275 *thislist)
|
|
||||||
{
|
|
||||||
int swapi = 0;
|
|
||||||
int i, mitr;
|
|
||||||
unsigned long tmpaddr, tmpsize;
|
|
||||||
unsigned long lowest;
|
|
||||||
|
|
||||||
for(i=0; thislist[i].theres_more; i++) {
|
|
||||||
lowest = thislist[i].start_adr;
|
|
||||||
for(mitr = i+1; thislist[mitr-1].theres_more; mitr++)
|
|
||||||
if(thislist[mitr].start_adr < lowest) {
|
|
||||||
lowest = thislist[mitr].start_adr;
|
|
||||||
swapi = mitr;
|
|
||||||
}
|
|
||||||
if(lowest == thislist[i].start_adr) continue;
|
|
||||||
tmpaddr = thislist[swapi].start_adr;
|
|
||||||
tmpsize = thislist[swapi].num_bytes;
|
|
||||||
for(mitr = swapi; mitr > i; mitr--) {
|
|
||||||
thislist[mitr].start_adr = thislist[mitr-1].start_adr;
|
|
||||||
thislist[mitr].num_bytes = thislist[mitr-1].num_bytes;
|
|
||||||
}
|
|
||||||
thislist[i].start_adr = tmpaddr;
|
|
||||||
thislist[i].num_bytes = tmpsize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize the memory lists based upon the prom version. */
|
|
||||||
void __init prom_meminit(void)
|
|
||||||
{
|
|
||||||
int node = 0;
|
|
||||||
unsigned int iter, num_regs;
|
|
||||||
|
|
||||||
node = prom_finddevice("/memory");
|
|
||||||
num_regs = prom_getproperty(node, "available",
|
|
||||||
(char *) prom_reg_memlist,
|
|
||||||
sizeof(prom_reg_memlist));
|
|
||||||
num_regs = (num_regs/sizeof(struct linux_prom64_registers));
|
|
||||||
for(iter=0; iter<num_regs; iter++) {
|
|
||||||
prom_phys_avail[iter].start_adr =
|
|
||||||
prom_reg_memlist[iter].phys_addr;
|
|
||||||
prom_phys_avail[iter].num_bytes =
|
|
||||||
prom_reg_memlist[iter].reg_size;
|
|
||||||
prom_phys_avail[iter].theres_more =
|
|
||||||
&prom_phys_avail[iter+1];
|
|
||||||
}
|
|
||||||
prom_phys_avail[iter-1].theres_more = NULL;
|
|
||||||
|
|
||||||
num_regs = prom_getproperty(node, "reg",
|
|
||||||
(char *) prom_reg_memlist,
|
|
||||||
sizeof(prom_reg_memlist));
|
|
||||||
num_regs = (num_regs/sizeof(struct linux_prom64_registers));
|
|
||||||
for(iter=0; iter<num_regs; iter++) {
|
|
||||||
prom_phys_total[iter].start_adr =
|
|
||||||
prom_reg_memlist[iter].phys_addr;
|
|
||||||
prom_phys_total[iter].num_bytes =
|
|
||||||
prom_reg_memlist[iter].reg_size;
|
|
||||||
prom_phys_total[iter].theres_more =
|
|
||||||
&prom_phys_total[iter+1];
|
|
||||||
}
|
|
||||||
prom_phys_total[iter-1].theres_more = NULL;
|
|
||||||
|
|
||||||
node = prom_finddevice("/virtual-memory");
|
|
||||||
num_regs = prom_getproperty(node, "available",
|
|
||||||
(char *) prom_reg_memlist,
|
|
||||||
sizeof(prom_reg_memlist));
|
|
||||||
num_regs = (num_regs/sizeof(struct linux_prom64_registers));
|
|
||||||
|
|
||||||
/* Convert available virtual areas to taken virtual
|
|
||||||
* areas. First sort, then convert.
|
|
||||||
*/
|
|
||||||
for(iter=0; iter<num_regs; iter++) {
|
|
||||||
prom_prom_taken[iter].start_adr =
|
|
||||||
prom_reg_memlist[iter].phys_addr;
|
|
||||||
prom_prom_taken[iter].num_bytes =
|
|
||||||
prom_reg_memlist[iter].reg_size;
|
|
||||||
prom_prom_taken[iter].theres_more =
|
|
||||||
&prom_prom_taken[iter+1];
|
|
||||||
}
|
|
||||||
prom_prom_taken[iter-1].theres_more = NULL;
|
|
||||||
|
|
||||||
prom_sortmemlist(prom_prom_taken);
|
|
||||||
|
|
||||||
/* Finally, convert. */
|
|
||||||
for(iter=0; iter<num_regs; iter++) {
|
|
||||||
prom_prom_taken[iter].start_adr =
|
|
||||||
prom_prom_taken[iter].start_adr +
|
|
||||||
prom_prom_taken[iter].num_bytes;
|
|
||||||
prom_prom_taken[iter].num_bytes =
|
|
||||||
prom_prom_taken[iter+1].start_adr -
|
|
||||||
prom_prom_taken[iter].start_adr;
|
|
||||||
}
|
|
||||||
prom_prom_taken[iter-1].num_bytes =
|
|
||||||
-1UL - prom_prom_taken[iter-1].start_adr;
|
|
||||||
|
|
||||||
/* Sort the other two lists. */
|
|
||||||
prom_sortmemlist(prom_phys_total);
|
|
||||||
prom_sortmemlist(prom_phys_avail);
|
|
||||||
|
|
||||||
/* Link all the lists into the top-level descriptor. */
|
|
||||||
prom_memlist.p1275_totphys=&prom_ptot_ptr;
|
|
||||||
prom_memlist.p1275_prommap=&prom_ptak_ptr;
|
|
||||||
prom_memlist.p1275_available=&prom_pavl_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This returns a pointer to our libraries internal p1275 format
|
|
||||||
* memory descriptor.
|
|
||||||
*/
|
|
||||||
struct linux_mem_p1275 *
|
|
||||||
prom_meminfo(void)
|
|
||||||
{
|
|
||||||
return &prom_memlist;
|
|
||||||
}
|
|
|
@ -475,7 +475,7 @@ static int __devinit radeon_probe_pll_params(struct radeonfb_info *rinfo)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Flush PCI buffers ? */
|
/* Flush PCI buffers ? */
|
||||||
tmp = INREG(DEVICE_ID);
|
tmp = INREG16(DEVICE_ID);
|
||||||
|
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
|
|
||||||
|
|
|
@ -395,6 +395,8 @@ static inline void _radeon_msleep(struct radeonfb_info *rinfo, unsigned long ms)
|
||||||
|
|
||||||
#define INREG8(addr) readb((rinfo->mmio_base)+addr)
|
#define INREG8(addr) readb((rinfo->mmio_base)+addr)
|
||||||
#define OUTREG8(addr,val) writeb(val, (rinfo->mmio_base)+addr)
|
#define OUTREG8(addr,val) writeb(val, (rinfo->mmio_base)+addr)
|
||||||
|
#define INREG16(addr) readw((rinfo->mmio_base)+addr)
|
||||||
|
#define OUTREG16(addr,val) writew(val, (rinfo->mmio_base)+addr)
|
||||||
#define INREG(addr) readl((rinfo->mmio_base)+addr)
|
#define INREG(addr) readl((rinfo->mmio_base)+addr)
|
||||||
#define OUTREG(addr,val) writel(val, (rinfo->mmio_base)+addr)
|
#define OUTREG(addr,val) writel(val, (rinfo->mmio_base)+addr)
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,8 @@ extern unsigned long page_kernel;
|
||||||
/* Top-level page directory */
|
/* Top-level page directory */
|
||||||
extern pgd_t swapper_pg_dir[1024];
|
extern pgd_t swapper_pg_dir[1024];
|
||||||
|
|
||||||
|
extern void paging_init(void);
|
||||||
|
|
||||||
/* Page table for 0-4MB for everybody, on the Sparc this
|
/* Page table for 0-4MB for everybody, on the Sparc this
|
||||||
* holds the same as on the i386.
|
* holds the same as on the i386.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -186,8 +186,8 @@ struct linux_prom_registers {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct linux_prom64_registers {
|
struct linux_prom64_registers {
|
||||||
long phys_addr;
|
unsigned long phys_addr;
|
||||||
long reg_size;
|
unsigned long reg_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct linux_prom_irqs {
|
struct linux_prom_irqs {
|
||||||
|
|
|
@ -95,20 +95,6 @@ extern int prom_devclose(int device_handle);
|
||||||
extern void prom_seek(int device_handle, unsigned int seek_hival,
|
extern void prom_seek(int device_handle, unsigned int seek_hival,
|
||||||
unsigned int seek_lowval);
|
unsigned int seek_lowval);
|
||||||
|
|
||||||
/* Machine memory configuration routine. */
|
|
||||||
|
|
||||||
/* This function returns a V0 format memory descriptor table, it has three
|
|
||||||
* entries. One for the total amount of physical ram on the machine, one
|
|
||||||
* for the amount of physical ram available, and one describing the virtual
|
|
||||||
* areas which are allocated by the prom. So, in a sense the physical
|
|
||||||
* available is a calculation of the total physical minus the physical mapped
|
|
||||||
* by the prom with virtual mappings.
|
|
||||||
*
|
|
||||||
* These lists are returned pre-sorted, this should make your life easier
|
|
||||||
* since the prom itself is way too lazy to do such nice things.
|
|
||||||
*/
|
|
||||||
extern struct linux_mem_p1275 *prom_meminfo(void);
|
|
||||||
|
|
||||||
/* Miscellaneous routines, don't really fit in any category per se. */
|
/* Miscellaneous routines, don't really fit in any category per se. */
|
||||||
|
|
||||||
/* Reboot the machine with the command line passed. */
|
/* Reboot the machine with the command line passed. */
|
||||||
|
|
|
@ -140,23 +140,6 @@ extern unsigned long page_to_pfn(struct page *);
|
||||||
#define virt_to_phys __pa
|
#define virt_to_phys __pa
|
||||||
#define phys_to_virt __va
|
#define phys_to_virt __va
|
||||||
|
|
||||||
/* The following structure is used to hold the physical
|
|
||||||
* memory configuration of the machine. This is filled in
|
|
||||||
* probe_memory() and is later used by mem_init() to set up
|
|
||||||
* mem_map[]. We statically allocate SPARC_PHYS_BANKS of
|
|
||||||
* these structs, this is arbitrary. The entry after the
|
|
||||||
* last valid one has num_bytes==0.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct sparc_phys_banks {
|
|
||||||
unsigned long base_addr;
|
|
||||||
unsigned long num_bytes;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define SPARC_PHYS_BANKS 32
|
|
||||||
|
|
||||||
extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
|
|
||||||
|
|
||||||
#endif /* !(__ASSEMBLY__) */
|
#endif /* !(__ASSEMBLY__) */
|
||||||
|
|
||||||
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
|
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
|
||||||
|
|
|
@ -341,6 +341,9 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *p
|
||||||
extern pgd_t swapper_pg_dir[2048];
|
extern pgd_t swapper_pg_dir[2048];
|
||||||
extern pmd_t swapper_low_pmd_dir[2048];
|
extern pmd_t swapper_low_pmd_dir[2048];
|
||||||
|
|
||||||
|
extern void paging_init(void);
|
||||||
|
extern unsigned long find_ecache_flush_span(unsigned long size);
|
||||||
|
|
||||||
/* These do nothing with the way I have things setup. */
|
/* These do nothing with the way I have things setup. */
|
||||||
#define mmu_lockarea(vaddr, len) (vaddr)
|
#define mmu_lockarea(vaddr, len) (vaddr)
|
||||||
#define mmu_unlockarea(vaddr, len) do { } while(0)
|
#define mmu_unlockarea(vaddr, len) do { } while(0)
|
||||||
|
|
|
@ -70,26 +70,14 @@ static inline int access_ok(int type, const void __user * addr, unsigned long si
|
||||||
* with the main instruction path. This means when everything is well,
|
* with the main instruction path. This means when everything is well,
|
||||||
* we don't even have to jump over them. Further, they do not intrude
|
* we don't even have to jump over them. Further, they do not intrude
|
||||||
* on our cache or tlb entries.
|
* on our cache or tlb entries.
|
||||||
*
|
|
||||||
* There is a special way how to put a range of potentially faulting
|
|
||||||
* insns (like twenty ldd/std's with now intervening other instructions)
|
|
||||||
* You specify address of first in insn and 0 in fixup and in the next
|
|
||||||
* exception_table_entry you specify last potentially faulting insn + 1
|
|
||||||
* and in fixup the routine which should handle the fault.
|
|
||||||
* That fixup code will get
|
|
||||||
* (faulting_insn_address - first_insn_in_the_range_address)/4
|
|
||||||
* in %g2 (ie. index of the faulting instruction in the range).
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct exception_table_entry
|
struct exception_table_entry {
|
||||||
{
|
unsigned int insn, fixup;
|
||||||
unsigned insn, fixup;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Special exable search, which handles ranges. Returns fixup */
|
|
||||||
unsigned long search_extables_range(unsigned long addr, unsigned long *g2);
|
|
||||||
|
|
||||||
extern void __ret_efault(void);
|
extern void __ret_efault(void);
|
||||||
|
extern void __retl_efault(void);
|
||||||
|
|
||||||
/* Uh, these should become the main single-value transfer routines..
|
/* Uh, these should become the main single-value transfer routines..
|
||||||
* They automatically use the right size if we just have the right
|
* They automatically use the right size if we just have the right
|
||||||
|
@ -263,7 +251,7 @@ copy_from_user(void *to, const void __user *from, unsigned long size)
|
||||||
{
|
{
|
||||||
unsigned long ret = ___copy_from_user(to, from, size);
|
unsigned long ret = ___copy_from_user(to, from, size);
|
||||||
|
|
||||||
if (ret)
|
if (unlikely(ret))
|
||||||
ret = copy_from_user_fixup(to, from, size);
|
ret = copy_from_user_fixup(to, from, size);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -279,7 +267,7 @@ copy_to_user(void __user *to, const void *from, unsigned long size)
|
||||||
{
|
{
|
||||||
unsigned long ret = ___copy_to_user(to, from, size);
|
unsigned long ret = ___copy_to_user(to, from, size);
|
||||||
|
|
||||||
if (ret)
|
if (unlikely(ret))
|
||||||
ret = copy_to_user_fixup(to, from, size);
|
ret = copy_to_user_fixup(to, from, size);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -295,7 +283,7 @@ copy_in_user(void __user *to, void __user *from, unsigned long size)
|
||||||
{
|
{
|
||||||
unsigned long ret = ___copy_in_user(to, from, size);
|
unsigned long ret = ___copy_in_user(to, from, size);
|
||||||
|
|
||||||
if (ret)
|
if (unlikely(ret))
|
||||||
ret = copy_in_user_fixup(to, from, size);
|
ret = copy_in_user_fixup(to, from, size);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue