Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F131866357
D25129.id72763.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
26 KB
Referenced Files
None
Subscribers
None
D25129.id72763.diff
View Options
Index: head/sys/conf/files.powerpc
===================================================================
--- head/sys/conf/files.powerpc
+++ head/sys/conf/files.powerpc
@@ -239,7 +239,7 @@
powerpc/powerpc/bus_machdep.c standard
powerpc/powerpc/busdma_machdep.c standard
powerpc/powerpc/clock.c standard
-powerpc/powerpc/copyinout.c standard
+powerpc/powerpc/copyinout.c optional aim
powerpc/powerpc/cpu.c standard
powerpc/powerpc/cpu_subr64.S optional powerpc64
powerpc/powerpc/db_disasm.c optional ddb
@@ -274,6 +274,7 @@
powerpc/powerpc/swtch32.S optional powerpc | powerpcspe
powerpc/powerpc/swtch64.S optional powerpc64
powerpc/powerpc/stack_machdep.c optional ddb | stack
+powerpc/powerpc/support.S optional powerpc64 | booke
powerpc/powerpc/syncicache.c standard
powerpc/powerpc/sys_machdep.c standard
powerpc/powerpc/trap.c standard
Index: head/sys/powerpc/aim/mmu_radix.c
===================================================================
--- head/sys/powerpc/aim/mmu_radix.c
+++ head/sys/powerpc/aim/mmu_radix.c
@@ -412,8 +412,6 @@
vm_size_t);
void mmu_radix_clear_modify(vm_page_t);
void mmu_radix_copy(pmap_t, pmap_t, vm_offset_t, vm_size_t, vm_offset_t);
-int mmu_radix_map_user_ptr(pmap_t pm,
- volatile const void *uaddr, void **kaddr, size_t ulen, size_t *klen);
int mmu_radix_decode_kernel_ptr(vm_offset_t, int *, vm_offset_t *);
int mmu_radix_enter(pmap_t, vm_offset_t, vm_page_t, vm_prot_t, u_int, int8_t);
void mmu_radix_enter_object(pmap_t, vm_offset_t, vm_offset_t, vm_page_t,
@@ -538,7 +536,6 @@
.kextract = mmu_radix_kextract,
.kremove = mmu_radix_kremove,
.change_attr = mmu_radix_change_attr,
- .map_user_ptr = mmu_radix_map_user_ptr,
.decode_kernel_ptr = mmu_radix_decode_kernel_ptr,
.tlbie_all = mmu_radix_tlbie_all,
@@ -5996,20 +5993,6 @@
pte = kvtopte(va);
pte_clear(pte);
-}
-
-int mmu_radix_map_user_ptr(pmap_t pm,
- volatile const void *uaddr, void **kaddr, size_t ulen, size_t *klen)
-{
- if ((uintptr_t)uaddr + ulen >= VM_MAXUSER_ADDRESS ||
- (uintptr_t)uaddr + ulen < (uintptr_t)uaddr)
- return (EFAULT);
-
- *kaddr = (void *)(uintptr_t)uaddr;
- if (klen)
- *klen = ulen;
-
- return (0);
}
int
Index: head/sys/powerpc/booke/pmap.c
===================================================================
--- head/sys/powerpc/booke/pmap.c
+++ head/sys/powerpc/booke/pmap.c
@@ -349,8 +349,6 @@
static void mmu_booke_quick_remove_page(vm_offset_t addr);
static int mmu_booke_change_attr(vm_offset_t addr,
vm_size_t sz, vm_memattr_t mode);
-static int mmu_booke_map_user_ptr(pmap_t pm,
- volatile const void *uaddr, void **kaddr, size_t ulen, size_t *klen);
static int mmu_booke_decode_kernel_ptr(vm_offset_t addr,
int *is_user, vm_offset_t *decoded_addr);
static void mmu_booke_page_array_startup(long);
@@ -410,7 +408,6 @@
.kremove = mmu_booke_kremove,
.unmapdev = mmu_booke_unmapdev,
.change_attr = mmu_booke_change_attr,
- .map_user_ptr = mmu_booke_map_user_ptr,
.decode_kernel_ptr = mmu_booke_decode_kernel_ptr,
/* dumpsys() support */
@@ -1206,26 +1203,6 @@
tlb_miss_unlock();
mtx_unlock_spin(&tlbivax_mutex);
-}
-
-/*
- * Provide a kernel pointer corresponding to a given userland pointer.
- * The returned pointer is valid until the next time this function is
- * called in this thread. This is used internally in copyin/copyout.
- */
-int
-mmu_booke_map_user_ptr(pmap_t pm, volatile const void *uaddr,
- void **kaddr, size_t ulen, size_t *klen)
-{
-
- if (trunc_page((uintptr_t)uaddr + ulen) > VM_MAXUSER_ADDRESS)
- return (EFAULT);
-
- *kaddr = (void *)(uintptr_t)uaddr;
- if (klen)
- *klen = ulen;
-
- return (0);
}
/*
Index: head/sys/powerpc/include/asm.h
===================================================================
--- head/sys/powerpc/include/asm.h
+++ head/sys/powerpc/include/asm.h
@@ -114,6 +114,7 @@
.p2align 4; \
TYPE_ENTRY(name) \
DOT_LABEL(name):
+#define _NAKED_ENTRY(name) _ENTRY(name)
#else
#define _ENTRY(name) \
.text; \
@@ -124,6 +125,15 @@
addis %r2, %r12, (.TOC.-name)@ha; \
addi %r2, %r2, (.TOC.-name)@l; \
.localentry name, .-name;
+
+/* "Naked" function entry. No TOC prologue for ELFv2. */
+#define _NAKED_ENTRY(name) \
+ .text; \
+ .p2align 4; \
+ .globl name; \
+ .type name,@function; \
+name: \
+ .localentry name, .-name;
#endif
#define _END(name) \
@@ -145,6 +155,8 @@
.type name,@function; \
name:
#define _END(name)
+
+#define _NAKED_ENTRY(name) _ENTRY(name)
#define LOAD_ADDR(reg, var) \
lis reg, var@ha; \
Index: head/sys/powerpc/include/mmuvar.h
===================================================================
--- head/sys/powerpc/include/mmuvar.h
+++ head/sys/powerpc/include/mmuvar.h
@@ -182,6 +182,25 @@
typedef struct mmu_kobj *mmu_t;
+/* The currently installed pmap object. */
+extern mmu_t mmu_obj;
+
+/*
+ * Resolve a given pmap function.
+ * 'func' is the function name less the 'pmap_' * prefix.
+ */
+#define PMAP_RESOLVE_FUNC(func) \
+ ({ \
+ pmap_##func##_t f; \
+ const struct mmu_kobj *mmu = mmu_obj; \
+ do { \
+ f = mmu->funcs->func; \
+ if (f != NULL) break; \
+ mmu = mmu->base; \
+ } while (mmu != NULL); \
+ f;})
+
+
#define MMU_DEF(name, ident, methods) \
\
const struct mmu_kobj name = { \
Index: head/sys/powerpc/include/param.h
===================================================================
--- head/sys/powerpc/include/param.h
+++ head/sys/powerpc/include/param.h
@@ -134,6 +134,9 @@
#define KSTACK_GUARD_PAGES 1 /* pages of kstack guard; 0 disables */
#define USPACE (kstack_pages * PAGE_SIZE) /* total size of pcb */
+#define COPYFAULT 0x1
+#define FUSUFAULT 0x2
+
/*
* Mach derived conversion macros
*/
Index: head/sys/powerpc/powerpc/copyinout.c
===================================================================
--- head/sys/powerpc/powerpc/copyinout.c
+++ head/sys/powerpc/powerpc/copyinout.c
@@ -66,13 +66,102 @@
#include <vm/vm.h>
#include <vm/pmap.h>
+#include <vm/vm_extern.h>
#include <vm/vm_map.h>
+#include <machine/mmuvar.h>
#include <machine/pcb.h>
#include <machine/vmparam.h>
+#include <machine/ifunc.h>
+/*
+ * On powerpc64 (AIM only) the copy functions are IFUNcs, selecting the best
+ * option based on the PMAP in use.
+ *
+ * There are two options for copy functions on powerpc64:
+ * - 'remap' copies, which remap userspace segments into kernel space for
+ * copying. This is used by the 'oea64' pmap.
+ * - 'direct' copies, which copy directly from userspace. This does not require
+ * remapping user segments into kernel. This is used by the 'radix' pmap for
+ * performance.
+ *
+ * Book-E does not use the C functions, opting instead to use the 'direct'
+ * copies, directly, avoiding the IFUNC overhead.
+ *
+ * On 32-bit AIM these functions are direct, not IFUNCs, for performance.
+ */
+#ifdef __powerpc64__
+int subyte_remap(volatile void *addr, int byte);
+int subyte_direct(volatile void *addr, int byte);
+int copyinstr_remap(const void *udaddr, void *kaddr, size_t len, size_t *done);
+int copyinstr_direct(const void *udaddr, void *kaddr, size_t len, size_t *done);
+int copyout_remap(const void *kaddr, void *udaddr, size_t len);
+int copyout_direct(const void *kaddr, void *udaddr, size_t len);
+int copyin_remap(const void *uaddr, void *kaddr, size_t len);
+int copyin_direct(const void *uaddr, void *kaddr, size_t len);
+int suword32_remap(volatile void *addr, int word);
+int suword32_direct(volatile void *addr, int word);
+int suword_remap(volatile void *addr, long word);
+int suword_direct(volatile void *addr, long word);
+int suword64_remap(volatile void *addr, int64_t word);
+int suword64_direct(volatile void *addr, int64_t word);
+int fubyte_remap(volatile const void *addr);
+int fubyte_direct(volatile const void *addr);
+int fuword16_remap(volatile const void *addr);
+int fuword16_direct(volatile const void *addr);
+int fueword32_remap(volatile const void *addr, int32_t *val);
+int fueword32_direct(volatile const void *addr, int32_t *val);
+int fueword64_remap(volatile const void *addr, int64_t *val);
+int fueword64_direct(volatile const void *addr, int64_t *val);
+int fueword_remap(volatile const void *addr, long *val);
+int fueword_direct(volatile const void *addr, long *val);
+int casueword32_remap(volatile uint32_t *addr, uint32_t old, uint32_t *oldvalp,
+ uint32_t new);
+int casueword32_direct(volatile uint32_t *addr, uint32_t old, uint32_t *oldvalp,
+ uint32_t new);
+int casueword_remap(volatile u_long *addr, u_long old, u_long *oldvalp,
+ u_long new);
+int casueword_direct(volatile u_long *addr, u_long old, u_long *oldvalp,
+ u_long new);
+
+/*
+ * The IFUNC resolver determines the copy based on if the PMAP implementation
+ * includes a pmap_map_user_ptr function.
+ */
+#define DEFINE_COPY_FUNC(ret, func, args) \
+ DEFINE_IFUNC(, ret, func, args) \
+ { \
+ return (PMAP_RESOLVE_FUNC(map_user_ptr) ? \
+ func##_remap : func##_direct); \
+ }
+DEFINE_COPY_FUNC(int, subyte, (volatile void *, int))
+DEFINE_COPY_FUNC(int, copyinstr, (const void *, void *, size_t, size_t *))
+DEFINE_COPY_FUNC(int, copyin, (const void *, void *, size_t))
+DEFINE_COPY_FUNC(int, copyout, (const void *, void *, size_t))
+DEFINE_COPY_FUNC(int, suword, (volatile void *, long))
+DEFINE_COPY_FUNC(int, suword32, (volatile void *, int))
+#ifdef __powerpc64__
+DEFINE_COPY_FUNC(int, suword64, (volatile void *, int64_t))
+#endif
+DEFINE_COPY_FUNC(int, fubyte, (volatile const void *))
+DEFINE_COPY_FUNC(int, fuword16, (volatile const void *))
+DEFINE_COPY_FUNC(int, fueword32, (volatile const void *, int32_t *))
+#ifdef __powerpc64__
+DEFINE_COPY_FUNC(int, fueword64, (volatile const void *, int64_t *))
+#endif
+DEFINE_COPY_FUNC(int, fueword, (volatile const void *, long *))
+DEFINE_COPY_FUNC(int, casueword32,
+ (volatile uint32_t *, uint32_t, uint32_t *, uint32_t))
+DEFINE_COPY_FUNC(int, casueword, (volatile u_long *, u_long, u_long *, u_long))
+
+#define REMAP(x) x##_remap
+#else
+#define REMAP(x) x
+#endif
+
+
int
-copyout(const void *kaddr, void *udaddr, size_t len)
+REMAP(copyout)(const void *kaddr, void *udaddr, size_t len)
{
struct thread *td;
pmap_t pm;
@@ -111,7 +200,7 @@
}
int
-copyin(const void *udaddr, void *kaddr, size_t len)
+REMAP(copyin)(const void *udaddr, void *kaddr, size_t len)
{
struct thread *td;
pmap_t pm;
@@ -150,7 +239,7 @@
}
int
-copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done)
+REMAP(copyinstr)(const void *udaddr, void *kaddr, size_t len, size_t *done)
{
const char *up;
char *kp;
@@ -183,7 +272,7 @@
}
int
-subyte(volatile void *addr, int byte)
+REMAP(subyte)(volatile void *addr, int byte)
{
struct thread *td;
pmap_t pm;
@@ -212,7 +301,7 @@
#ifdef __powerpc64__
int
-suword32(volatile void *addr, int word)
+REMAP(suword32)(volatile void *addr, int word)
{
struct thread *td;
pmap_t pm;
@@ -238,10 +327,16 @@
td->td_pcb->pcb_onfault = NULL;
return (0);
}
+#else
+int
+REMAP(suword32)(volatile void *addr, int32_t word)
+{
+REMAP( return (suword)(addr, (long)word));
+}
#endif
int
-suword(volatile void *addr, long word)
+REMAP(suword)(volatile void *addr, long word)
{
struct thread *td;
pmap_t pm;
@@ -270,20 +365,14 @@
#ifdef __powerpc64__
int
-suword64(volatile void *addr, int64_t word)
+REMAP(suword64)(volatile void *addr, int64_t word)
{
- return (suword(addr, (long)word));
+ return (REMAP(suword)(addr, (long)word));
}
-#else
-int
-suword32(volatile void *addr, int32_t word)
-{
- return (suword(addr, (long)word));
-}
#endif
int
-fubyte(volatile const void *addr)
+REMAP(fubyte)(volatile const void *addr)
{
struct thread *td;
pmap_t pm;
@@ -312,7 +401,7 @@
}
int
-fuword16(volatile const void *addr)
+REMAP(fuword16)(volatile const void *addr)
{
struct thread *td;
pmap_t pm;
@@ -340,7 +429,7 @@
}
int
-fueword32(volatile const void *addr, int32_t *val)
+REMAP(fueword32)(volatile const void *addr, int32_t *val)
{
struct thread *td;
pmap_t pm;
@@ -369,7 +458,7 @@
#ifdef __powerpc64__
int
-fueword64(volatile const void *addr, int64_t *val)
+REMAP(fueword64)(volatile const void *addr, int64_t *val)
{
struct thread *td;
pmap_t pm;
@@ -398,7 +487,7 @@
#endif
int
-fueword(volatile const void *addr, long *val)
+REMAP(fueword)(volatile const void *addr, long *val)
{
struct thread *td;
pmap_t pm;
@@ -426,7 +515,7 @@
}
int
-casueword32(volatile uint32_t *addr, uint32_t old, uint32_t *oldvalp,
+REMAP(casueword32)(volatile uint32_t *addr, uint32_t old, uint32_t *oldvalp,
uint32_t new)
{
struct thread *td;
@@ -474,7 +563,7 @@
#ifndef __powerpc64__
int
-casueword(volatile u_long *addr, u_long old, u_long *oldvalp, u_long new)
+REMAP(casueword)(volatile u_long *addr, u_long old, u_long *oldvalp, u_long new)
{
return (casueword32((volatile uint32_t *)addr, old,
@@ -482,7 +571,7 @@
}
#else
int
-casueword(volatile u_long *addr, u_long old, u_long *oldvalp, u_long new)
+REMAP(casueword)(volatile u_long *addr, u_long old, u_long *oldvalp, u_long new)
{
struct thread *td;
pmap_t pm;
Index: head/sys/powerpc/powerpc/pmap_dispatch.c
===================================================================
--- head/sys/powerpc/powerpc/pmap_dispatch.c
+++ head/sys/powerpc/powerpc/pmap_dispatch.c
@@ -62,7 +62,7 @@
#include <machine/mmuvar.h>
#include <machine/smp.h>
-static mmu_t mmu_obj;
+mmu_t mmu_obj;
/*
* pmap globals
@@ -99,24 +99,14 @@
#define DEFINE_PMAP_IFUNC(ret, func, args) \
DEFINE_IFUNC(, ret, pmap_##func, args) { \
- const struct mmu_kobj *mmu = mmu_obj; \
pmap_##func##_t f; \
- do { \
- f = mmu->funcs->func; \
- if (f != NULL) break; \
- mmu = mmu->base; \
- } while (mmu != NULL); \
+ f = PMAP_RESOLVE_FUNC(func); \
return (f != NULL ? f : (pmap_##func##_t)pmap_nomethod);\
}
#define DEFINE_DUMPSYS_IFUNC(ret, func, args) \
DEFINE_IFUNC(, ret, dumpsys_##func, args) { \
- const struct mmu_kobj *mmu = mmu_obj; \
pmap_dumpsys_##func##_t f; \
- do { \
- f = mmu->funcs->dumpsys_##func; \
- if (f != NULL) break; \
- mmu = mmu->base; \
- } while (mmu != NULL); \
+ f = PMAP_RESOLVE_FUNC(dumpsys_##func); \
return (f != NULL ? f : (pmap_dumpsys_##func##_t)pmap_nomethod);\
}
Index: head/sys/powerpc/powerpc/support.S
===================================================================
--- head/sys/powerpc/powerpc/support.S
+++ head/sys/powerpc/powerpc/support.S
@@ -0,0 +1,539 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2018, Matthew Macy <mmacy@freebsd.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Assembly variants of various functions, for those that don't need generic C
+ * implementations. Currently this includes:
+ *
+ * - Direct-access versions of copyin/copyout methods.
+ * - These are used by Radix AIM pmap (ISA 3.0), and Book-E, to avoid
+ * unnecessary pmap_map_usr_ptr() calls.
+ */
+
+#include "assym.inc"
+#include "opt_sched.h"
+
+#include <sys/syscall.h>
+#include <sys/errno.h>
+
+#include <machine/param.h>
+#include <machine/asm.h>
+#include <machine/spr.h>
+#include <machine/trap.h>
+#include <machine/vmparam.h>
+
+#ifdef _CALL_ELF
+.abiversion _CALL_ELF
+#endif
+
+#ifdef __powerpc64__
+#define LOAD ld
+#define STORE std
+#define WORD 8
+#define CMPI cmpdi
+#define CMPLI cmpldi
+/* log_2(8 * WORD) */
+#define LOOP_LOG 6
+#define LOG_WORD 3
+#else
+#define LOAD lwz
+#define STORE stw
+#define WORD 4
+#define CMPI cmpwi
+#define CMPLI cmplwi
+/* log_2(8 * WORD) */
+#define LOOP_LOG 5
+#define LOG_WORD 2
+#endif
+
+#ifdef AIM
+#define ENTRY_DIRECT(x) ENTRY(x ## _direct)
+#else
+#define ENTRY_DIRECT(x) ENTRY(x)
+#endif
+
+#ifdef __powerpc64__
+#define PROLOGUE ;\
+ mflr %r0 ;\
+ std %r0, 16(%r1) ;\
+
+#define EPILOGUE ;\
+ ld %r0, 16(%r1) ;\
+ mtlr %r0 ;\
+ blr ;\
+ nop
+
+#define VALIDATE_TRUNCATE_ADDR_COPY VALIDATE_ADDR_COPY
+#define VALIDATE_ADDR_COPY(raddr, len) \
+ srdi %r0, raddr, 52 ;\
+ cmpwi %r0, 1 ;\
+ bge- copy_fault ;\
+ nop
+
+#define VALIDATE_ADDR_FUSU(raddr) ;\
+ srdi %r0, raddr, 52 ;\
+ cmpwi %r0, 1 ;\
+ bge- fusufault ;\
+ nop
+
+#else
+#define PROLOGUE ;\
+ mflr %r0 ;\
+ stw %r0, 4(%r1) ;\
+
+#define EPILOGUE ;\
+ lwz %r0, 4(%r1) ;\
+ mtlr %r0 ;\
+ blr ;\
+ nop
+
+/* %r0 is temporary */
+/*
+ * Validate address and length are valid.
+ * For VALIDATE_ADDR_COPY() have to account for wraparound.
+ */
+#define VALIDATE_ADDR_COPY(raddr, len) \
+ lis %r0, VM_MAXUSER_ADDRESS@h ;\
+ ori %r0, %r0, VM_MAXUSER_ADDRESS@l ;\
+ cmplw %r0, raddr ;\
+ blt- copy_fault ;\
+ add %r0, raddr, len ;\
+ cmplw 7, %r0, raddr ;\
+ blt- 7, copy_fault ;\
+ mtcrf 0x80, %r0 ;\
+ bt- 0, copy_fault ;\
+ nop
+
+#define VALIDATE_TRUNCATE_ADDR_COPY(raddr, len) \
+ lis %r0, VM_MAXUSER_ADDRESS@h ;\
+ ori %r0, %r0, VM_MAXUSER_ADDRESS@l ;\
+ cmplw %r0, raddr ;\
+ blt- copy_fault ;\
+ sub %r0, %r0, raddr ;\
+ cmplw len, %r0 ;\
+ isel len, len, %r0, 0 ;\
+
+#define VALIDATE_ADDR_FUSU(raddr) \
+ lis %r0, VM_MAXUSER_ADDRESS@h ;\
+ ori %r0, %r0, VM_MAXUSER_ADDRESS@l ;\
+ cmplw %r0, raddr ;\
+ ble- fusufault
+
+#endif
+
+#define PCPU(reg) mfsprg reg, 0
+
+#define SET_COPYFAULT(raddr, rpcb, len) \
+ VALIDATE_ADDR_COPY(raddr, len) ;\
+ PCPU(%r9) ;\
+ li %r0, COPYFAULT ;\
+ LOAD rpcb, PC_CURPCB(%r9) ;\
+ STORE %r0, PCB_ONFAULT(rpcb) ;\
+
+#define SET_COPYFAULT_TRUNCATE(raddr, rpcb, len)\
+ VALIDATE_TRUNCATE_ADDR_COPY(raddr, len) ;\
+ PCPU(%r9) ;\
+ li %r0, COPYFAULT ;\
+ LOAD rpcb, PC_CURPCB(%r9) ;\
+ STORE %r0, PCB_ONFAULT(rpcb)
+
+#define SET_FUSUFAULT(raddr, rpcb) \
+ VALIDATE_ADDR_FUSU(raddr) ;\
+ PCPU(%r9) ;\
+ li %r0, FUSUFAULT ;\
+ LOAD rpcb, PC_CURPCB(%r9) ;\
+ STORE %r0, PCB_ONFAULT(rpcb)
+
+#define CLEAR_FAULT_NO_CLOBBER(rpcb) \
+ PCPU(%r9) ;\
+ LOAD rpcb, PC_CURPCB(%r9) ;\
+ li %r0, 0 ;\
+ STORE %r0, PCB_ONFAULT(rpcb)
+
+#define CLEAR_FAULT(rpcb) \
+ CLEAR_FAULT_NO_CLOBBER(rpcb) ;\
+ li %r3, 0
+
+/*
+ * bcopy(src, dst, len)
+ * %r3 %r4 %r5
+ *
+ * %r7 is the pcb pointer
+ *
+ * %r0 and %r8-%r10 are volatile
+ * %r11 and %r12 are generally volatile, used in linking and exception
+ * handling. Can be clobbered here.
+ *
+ * Does not allocate or use stack space, but clobbers all volatile registers.
+ */
+
+#define rs %r3
+#define rd %r4
+#define rl %r5
+
+#define t1 %r6
+#define t2 %r7
+#define t3 %r8
+#define t4 %r9
+#define t5 %r10
+#define t6 %r11
+#define t7 %r12
+#define t8 %r0
+
+#define Thresh WORD * 8
+#define W4 3
+#define W2 2
+#define W1 1
+#define WORDS(n) (32 - LOG_WORD - W##n)
+.text
+ENTRY(bcopy_generic)
+ CMPLI 0, %r5, 0
+ beq .Lend
+ dcbtst 0, rd
+ dcbt 0, rs
+ CMPLI rl, Thresh
+ blt .Lsmall
+ b .Llarge
+/* memcpy */
+/* ... */
+.Lsmall: /* < 8 words remaining */
+ mtcrf 0x3, rl
+.Lsmall_start:
+ bf WORDS(4), 0f
+ LOAD t1, 0(rs)
+ LOAD t2, WORD*1(rs)
+ LOAD t3, WORD*2(rs)
+ LOAD t4, WORD*3(rs)
+ addi rs, rs, WORD*4
+ STORE t1, 0(rd)
+ STORE t2, WORD*1(rd)
+ STORE t3, WORD*2(rd)
+ STORE t4, WORD*3(rd)
+ addi rd, rd, WORD*4
+0: /* < 4 words remaining */
+ bf WORDS(2), 1f
+ LOAD t1, 0(rs)
+ LOAD t2, WORD*1(rs)
+ addi rs, rs, WORD*2
+ STORE t1, 0(rd)
+ STORE t2, WORD*1(rd)
+ addi rd, rd, WORD*2
+1: /* < 2 words remaining */
+ bf WORDS(1), 2f
+ LOAD t1, 0(rs)
+ addi rs, rs, WORD
+ STORE t1, 0(rd)
+ addi rd, rd, WORD
+2: /* < 1 word remaining */
+#ifdef __powerpc64__
+ bf 29, 3f
+ lwz t1, 0(rs)
+ addi rs, rs, 4
+ stw t1, 0(rd)
+ addi rd, rd, 4
+3: /* < 4 bytes remaining */
+#endif
+ bf 30, 4f
+ lhz t1, 0(rs)
+ addi rs, rs, 2
+ sth t1, 0(rd)
+ addi rd, rd, 2
+4: /* < 2 bytes remaining */
+ bf 31, .Lout
+ lbz t1, 0(rs)
+ addi rs, rs, 1
+ stb t1, 0(rd)
+ addi rd, rd, 1
+ b .Lout
+
+ .align 4
+.Llarge:
+ neg t3, rd
+ andi. t6, t3, WORD-1 /* Align rd to word size */
+ mtctr t6
+ sub rl, rl, t6
+ beq+ .Llargealigned
+1:
+ lbz t1, 0(rs)
+ addi rs, rs, 1
+ stb t1, 0(rd)
+ addi rd, rd, 1
+ bdnz 1b
+
+.Llargealigned:
+ srwi. t2, rl, LOOP_LOG /* length >> log_2(loop_size) => 8W iterations */
+ mtcrf 0x3, rl
+ beq .Lsmall_start
+ mtctr t2
+ b 1f
+
+ .align 5
+1:
+ LOAD t1, 0(rs)
+ LOAD t2, WORD(rs)
+ LOAD t3, WORD*2(rs)
+ LOAD t4, WORD*3(rs)
+ LOAD t5, WORD*4(rs)
+ LOAD t6, WORD*5(rs)
+ LOAD t7, WORD*6(rs)
+ LOAD t8, WORD*7(rs)
+ addi rs, rs, WORD*8
+ STORE t1, 0(rd)
+ STORE t2, WORD*1(rd)
+ STORE t3, WORD*2(rd)
+ STORE t4, WORD*3(rd)
+ STORE t5, WORD*4(rd)
+ STORE t6, WORD*5(rd)
+ STORE t7, WORD*6(rd)
+ STORE t8, WORD*7(rd)
+ addi rd, rd, WORD*8
+ bdnz 1b
+
+ b .Lsmall_start
+.Lout:
+/* done */
+.Lend:
+ blr
+
+/*
+ * copyout(from_kernel, to_user, len)
+ * %r3, %r4, %r5
+ */
+ENTRY_DIRECT(copyout)
+ PROLOGUE
+ SET_COPYFAULT(%r4, %r7, %r5)
+ bl bcopy_generic
+ nop
+ CLEAR_FAULT(%r7)
+ EPILOGUE
+
+/*
+ * copyin(from_user, to_kernel, len)
+ * %r3, %r4, %r5
+ */
+ENTRY_DIRECT(copyin)
+ PROLOGUE
+ SET_COPYFAULT(%r3, %r7, %r5)
+ bl bcopy_generic
+ nop
+ CLEAR_FAULT(%r7)
+ EPILOGUE
+/*
+ * copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done)
+ * %r3 %r4 %r5 %r6
+ */
+
+ENTRY_DIRECT(copyinstr)
+ PROLOGUE
+ SET_COPYFAULT_TRUNCATE(%r3, %r7, %r5)
+ addi %r9, %r5, 1
+ mtctr %r9
+ mr %r8, %r3
+ addi %r8, %r8, -1
+ addi %r4, %r4, -1
+ li %r3, ENAMETOOLONG
+0:
+ bdz- 2f
+ lbzu %r0, 1(%r8)
+ stbu %r0, 1(%r4)
+
+ // NULL byte reached ?
+ CMPI %r0, 0
+ beq- 1f
+ b 0b
+1:
+ li %r3, 0
+2:
+ /* skip storing length if done is NULL */
+ CMPI %r6, 0
+ beq- 3f
+ mfctr %r0
+ sub %r0, %r9, %r0
+ STORE %r0, 0(%r6)
+3:
+ CLEAR_FAULT_NO_CLOBBER(%r7)
+ EPILOGUE
+
+ENTRY_DIRECT(subyte)
+ PROLOGUE
+ SET_FUSUFAULT(%r3, %r7)
+ stb %r4, 0(%r3)
+ CLEAR_FAULT(%r7)
+ EPILOGUE
+
+#ifndef __powerpc64__
+ENTRY_DIRECT(suword)
+ PROLOGUE
+ SET_FUSUFAULT(%r3, %r7)
+ stw %r4, 0(%r3)
+ CLEAR_FAULT(%r7)
+ EPILOGUE
+#endif
+
+ENTRY_DIRECT(suword32)
+ PROLOGUE
+ SET_FUSUFAULT(%r3, %r7)
+ stw %r4, 0(%r3)
+ CLEAR_FAULT(%r7)
+ EPILOGUE
+
+#ifdef __powerpc64__
+ENTRY_DIRECT(suword64)
+ PROLOGUE
+ SET_FUSUFAULT(%r3, %r7)
+ std %r4, 0(%r3)
+ CLEAR_FAULT(%r7)
+ EPILOGUE
+ENTRY_DIRECT(suword)
+ PROLOGUE
+ SET_FUSUFAULT(%r3, %r7)
+ std %r4, 0(%r3)
+ CLEAR_FAULT(%r7)
+ EPILOGUE
+#endif
+
+ENTRY_DIRECT(fubyte)
+ PROLOGUE
+ SET_FUSUFAULT(%r3, %r7)
+ lbz %r3, 0(%r3)
+ CLEAR_FAULT_NO_CLOBBER(%r7)
+ EPILOGUE
+
+ENTRY_DIRECT(fuword16)
+ PROLOGUE
+ SET_FUSUFAULT(%r3, %r7)
+ lhz %r3, 0(%r3)
+ CLEAR_FAULT_NO_CLOBBER(%r7)
+ EPILOGUE
+
+#ifndef __powerpc64__
+ENTRY_DIRECT(fueword)
+ PROLOGUE
+ SET_FUSUFAULT(%r3, %r7)
+ lwz %r0, 0(%r3)
+ stw %r0, 0(%r4)
+ CLEAR_FAULT(%r7)
+ EPILOGUE
+#endif
+ENTRY_DIRECT(fueword32)
+ PROLOGUE
+ SET_FUSUFAULT(%r3, %r7)
+ lwz %r0, 0(%r3)
+ stw %r0, 0(%r4)
+ CLEAR_FAULT(%r7)
+ EPILOGUE
+
+#ifdef __powerpc64__
+ENTRY_DIRECT(fueword)
+ PROLOGUE
+ SET_FUSUFAULT(%r3, %r7)
+ ld %r0, 0(%r3)
+ std %r0, 0(%r4)
+ CLEAR_FAULT(%r7)
+ EPILOGUE
+
+ENTRY_DIRECT(fueword64)
+ PROLOGUE
+ SET_FUSUFAULT(%r3, %r7)
+ ld %r0, 0(%r3)
+ std %r0, 0(%r4)
+ CLEAR_FAULT(%r7)
+ EPILOGUE
+#endif
+
+/*
+ * casueword(volatile u_long *base, u_long old, u_long *oldp, u_long new)
+ * %r3 %r4 %r5 %r6
+ */
+
+#define CASUEWORD32(raddr, rpcb) ;\
+ PROLOGUE ;\
+ SET_FUSUFAULT(raddr, rpcb) ;\
+ li %r8, 0 ;\
+1: ;\
+ lwarx %r0, 0, %r3 ;\
+ cmplw %r4, %r0 ;\
+ bne 2f ;\
+ stwcx. %r6, 0, %r3 ;\
+ bne- 3f ;\
+ b 4f ;\
+2: ;\
+ stwcx. %r0, 0, %r3 /* clear reservation (74xx) */ ;\
+3: ;\
+ li %r8, 1 ;\
+4: ;\
+ stw %r0, 0(%r5) ;\
+ CLEAR_FAULT_NO_CLOBBER(rpcb) ;\
+ mr %r3, %r8 ;\
+ EPILOGUE
+
+ENTRY_DIRECT(casueword32)
+ CASUEWORD32(%r3, %r7)
+
+#ifdef __powerpc64__
+#define CASUEWORD64(raddr, rpcb) ;\
+ PROLOGUE ;\
+ SET_FUSUFAULT(raddr, rpcb) ;\
+ li %r8, 0 ;\
+1: ;\
+ ldarx %r0, 0, %r3 ;\
+ cmpld %r4, %r0 ;\
+ bne 2f ;\
+ stdcx. %r6, 0, %r3 ;\
+ bne- 3f ;\
+ b 4f ;\
+2: ;\
+ stdcx. %r0, 0, %r3 /* clear reservation (74xx) */ ;\
+3: ;\
+ li %r8, 1 ;\
+4: ;\
+ std %r0, 0(%r5) ;\
+ CLEAR_FAULT_NO_CLOBBER(rpcb) ;\
+ mr %r3, %r8 ;\
+ EPILOGUE
+
+ENTRY_DIRECT(casueword)
+ CASUEWORD64(%r3, %r7)
+
+ENTRY_DIRECT(casueword64)
+ CASUEWORD64(%r3, %r7)
+#else
+ENTRY_DIRECT(casueword)
+ CASUEWORD32(%r3, %r7)
+#endif
+
+_NAKED_ENTRY(fusufault)
+ CLEAR_FAULT_NO_CLOBBER(%r7)
+ li %r3, -1
+ EPILOGUE
+
+_NAKED_ENTRY(copy_fault)
+ CLEAR_FAULT_NO_CLOBBER(%r7)
+ li %r3, EFAULT
+ EPILOGUE
Index: head/sys/powerpc/powerpc/trap.c
===================================================================
--- head/sys/powerpc/powerpc/trap.c
+++ head/sys/powerpc/powerpc/trap.c
@@ -98,6 +98,9 @@
extern vm_offset_t __startkernel;
+extern int copy_fault(void);
+extern int fusufault(void);
+
#ifdef KDB
int db_trap_glue(struct trapframe *); /* Called from trap_subr.S */
#endif
@@ -590,6 +593,23 @@
jmp_buf *fb;
td = curthread;
+#if defined(__powerpc64__) || defined(BOOKE)
+ uintptr_t dispatch = (uintptr_t)td->td_pcb->pcb_onfault;
+
+ if (dispatch == 0)
+ return (0);
+ /* Short-circuit radix and Book-E paths. */
+ switch (dispatch) {
+ case COPYFAULT:
+ frame->srr0 = (uintptr_t)copy_fault;
+ return (1);
+ case FUSUFAULT:
+ frame->srr0 = (uintptr_t)fusufault;
+ return (1);
+ default:
+ break;
+ }
+#endif
fb = td->td_pcb->pcb_onfault;
if (fb != NULL) {
frame->srr0 = (*fb)->_jb[FAULTBUF_LR];
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Oct 12, 7:49 PM (14 h, 37 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
23638502
Default Alt Text
D25129.id72763.diff (26 KB)
Attached To
Mode
D25129: powerpc: Use IFUNCs for copyin/copyout/etc
Attached
Detach File
Event Timeline
Log In to Comment