summaryrefslogtreecommitdiffstats
path: root/sys/ia64
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2004-08-11 02:35:06 +0000
committermarcel <marcel@FreeBSD.org>2004-08-11 02:35:06 +0000
commitfbbaea5f906ae98c3b2fe400a10aa7f73d292697 (patch)
tree6873386d3adcd9d8f724266b497cb4615a353766 /sys/ia64
parent36e89f928c8909ce943566776b5922f293e7dcd5 (diff)
downloadFreeBSD-src-fbbaea5f906ae98c3b2fe400a10aa7f73d292697.zip
FreeBSD-src-fbbaea5f906ae98c3b2fe400a10aa7f73d292697.tar.gz
Add __elfN(dump_thread). This function is called from __elfN(coredump)
to allow dumping per-thread machine specific notes. On ia64 we use this function to flush the dirty registers onto the backingstore before we write out the PRSTATUS notes. Tested on: alpha, amd64, i386, ia64 & sparc64 Not tested on: arm, powerpc
Diffstat (limited to 'sys/ia64')
-rw-r--r--sys/ia64/ia64/elf_machdep.c83
-rw-r--r--sys/ia64/ia64/machdep.c51
-rw-r--r--sys/ia64/include/md_var.h2
3 files changed, 59 insertions, 77 deletions
diff --git a/sys/ia64/ia64/elf_machdep.c b/sys/ia64/ia64/elf_machdep.c
index 92a609f..8588815 100644
--- a/sys/ia64/ia64/elf_machdep.c
+++ b/sys/ia64/ia64/elf_machdep.c
@@ -49,7 +49,9 @@
#include <machine/md_var.h>
#include <machine/unwind.h>
-static int ia64_coredump(struct thread *, struct vnode *, off_t);
+Elf_Addr link_elf_get_gp(linker_file_t);
+
+extern Elf_Addr fptr_storage[];
struct sysentvec elf64_freebsd_sysvec = {
SYS_MAXSYSCALL,
@@ -66,7 +68,7 @@ struct sysentvec elf64_freebsd_sysvec = {
NULL, /* &szsigcode */
NULL,
"FreeBSD ELF64",
- ia64_coredump,
+ __elfN(coredump),
NULL,
MINSIGSTKSZ,
PAGE_SIZE,
@@ -81,67 +83,40 @@ struct sysentvec elf64_freebsd_sysvec = {
};
static Elf64_Brandinfo freebsd_brand_info = {
- ELFOSABI_FREEBSD,
- EM_IA_64,
- "FreeBSD",
- NULL,
- "/libexec/ld-elf.so.1",
- &elf64_freebsd_sysvec,
- NULL,
- };
-
+ ELFOSABI_FREEBSD,
+ EM_IA_64,
+ "FreeBSD",
+ NULL,
+ "/libexec/ld-elf.so.1",
+ &elf64_freebsd_sysvec,
+ NULL,
+};
SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_ANY,
- (sysinit_cfunc_t) elf64_insert_brand_entry,
- &freebsd_brand_info);
+ (sysinit_cfunc_t)elf64_insert_brand_entry, &freebsd_brand_info);
static Elf64_Brandinfo freebsd_brand_oinfo = {
- ELFOSABI_FREEBSD,
- EM_IA_64,
- "FreeBSD",
- NULL,
- "/usr/libexec/ld-elf.so.1",
- &elf64_freebsd_sysvec,
- NULL,
- };
-
+ ELFOSABI_FREEBSD,
+ EM_IA_64,
+ "FreeBSD",
+ NULL,
+ "/usr/libexec/ld-elf.so.1",
+ &elf64_freebsd_sysvec,
+ NULL,
+};
SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
- (sysinit_cfunc_t) elf64_insert_brand_entry,
- &freebsd_brand_oinfo);
+ (sysinit_cfunc_t)elf64_insert_brand_entry, &freebsd_brand_oinfo);
-Elf_Addr link_elf_get_gp(linker_file_t);
-extern Elf_Addr fptr_storage[];
-
-static int
-ia64_coredump(struct thread *td, struct vnode *vp, off_t limit)
+void
+elf64_dump_thread(struct thread *td, void *dst, size_t *off __unused)
{
- struct trapframe *tf;
- uint64_t bspst, kstk, ndirty, rnat;
-
- tf = td->td_frame;
- ndirty = tf->tf_special.ndirty;
- if (ndirty != 0) {
- kstk = td->td_kstack + (tf->tf_special.bspstore & 0x1ffUL);
- __asm __volatile("mov ar.rsc=0;;");
- __asm __volatile("mov %0=ar.bspstore" : "=r"(bspst));
- /* Make sure we have all the user registers written out. */
- if (bspst - kstk < ndirty) {
- __asm __volatile("flushrs;;");
- __asm __volatile("mov %0=ar.bspstore" : "=r"(bspst));
- }
- __asm __volatile("mov %0=ar.rnat;;" : "=r"(rnat));
- __asm __volatile("mov ar.rsc=3");
- copyout((void*)kstk, (void*)tf->tf_special.bspstore, ndirty);
- kstk += ndirty;
- tf->tf_special.bspstore += ndirty;
- tf->tf_special.ndirty = 0;
- tf->tf_special.rnat =
- (bspst > kstk && (bspst & 0x1ffUL) < (kstk & 0x1ffUL))
- ? *(uint64_t*)(kstk | 0x1f8UL) : rnat;
- }
- return (elf64_coredump(td, vp, limit));
+
+ /* Flush the dirty registers onto the backingstore. */
+ if (dst == NULL)
+ ia64_flush_dirty(td, &td->td_frame->tf_special);
}
+
static Elf_Addr
lookup_fdesc(linker_file_t lf, Elf_Word symidx, elf_lookup_fn lookup)
{
diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c
index 64fc1c0..45cd022 100644
--- a/sys/ia64/ia64/machdep.c
+++ b/sys/ia64/ia64/machdep.c
@@ -1034,36 +1034,41 @@ makectx(struct trapframe *tf, struct pcb *pcb)
save_callee_saved_fp(&pcb->pcb_preserved_fp);
}
+void
+ia64_flush_dirty(struct thread *td, struct _special *r)
+{
+ uint64_t bspst, kstk, rnat;
+
+ if (r->ndirty == 0)
+ return;
+
+ kstk = td->td_kstack + (r->bspstore & 0x1ffUL);
+ __asm __volatile("mov ar.rsc=0;;");
+ __asm __volatile("mov %0=ar.bspstore" : "=r"(bspst));
+ /* Make sure we have all the user registers written out. */
+ if (bspst - kstk < r->ndirty) {
+ __asm __volatile("flushrs;;");
+ __asm __volatile("mov %0=ar.bspstore" : "=r"(bspst));
+ }
+ __asm __volatile("mov %0=ar.rnat;;" : "=r"(rnat));
+ __asm __volatile("mov ar.rsc=3");
+ copyout((void*)kstk, (void*)r->bspstore, r->ndirty);
+ kstk += r->ndirty;
+ r->rnat = (bspst > kstk && (bspst & 0x1ffUL) < (kstk & 0x1ffUL))
+ ? *(uint64_t*)(kstk | 0x1f8UL) : rnat;
+ r->bspstore += r->ndirty;
+ r->ndirty = 0;
+}
+
int
get_mcontext(struct thread *td, mcontext_t *mc, int flags)
{
struct trapframe *tf;
- uint64_t bspst, kstk, rnat;
tf = td->td_frame;
bzero(mc, sizeof(*mc));
- if (tf->tf_special.ndirty != 0) {
- kstk = td->td_kstack + (tf->tf_special.bspstore & 0x1ffUL);
- __asm __volatile("mov ar.rsc=0;;");
- __asm __volatile("mov %0=ar.bspstore" : "=r"(bspst));
- /* Make sure we have all the user registers written out. */
- if (bspst - kstk < tf->tf_special.ndirty) {
- __asm __volatile("flushrs;;");
- __asm __volatile("mov %0=ar.bspstore" : "=r"(bspst));
- }
- __asm __volatile("mov %0=ar.rnat;;" : "=r"(rnat));
- __asm __volatile("mov ar.rsc=3");
- copyout((void*)kstk, (void*)tf->tf_special.bspstore,
- tf->tf_special.ndirty);
- kstk += tf->tf_special.ndirty;
- mc->mc_special = tf->tf_special;
- mc->mc_special.rnat =
- (bspst > kstk && (bspst & 0x1ffUL) < (kstk & 0x1ffUL))
- ? *(uint64_t*)(kstk | 0x1f8UL) : rnat;
- mc->mc_special.bspstore += mc->mc_special.ndirty;
- mc->mc_special.ndirty = 0;
- } else
- mc->mc_special = tf->tf_special;
+ mc->mc_special = tf->tf_special;
+ ia64_flush_dirty(td, &mc->mc_special);
if (tf->tf_flags & FRAME_SYSCALL) {
mc->mc_flags |= _MC_FLAGS_SYSCALL_CONTEXT;
mc->mc_scratch = tf->tf_scratch;
diff --git a/sys/ia64/include/md_var.h b/sys/ia64/include/md_var.h
index 99d03dd42..d1a206e 100644
--- a/sys/ia64/include/md_var.h
+++ b/sys/ia64/include/md_var.h
@@ -65,6 +65,7 @@ extern char esigcode[];
extern int szsigcode;
extern long Maxmem;
+struct _special;
struct fpreg;
struct reg;
struct thread;
@@ -75,6 +76,7 @@ int copyout_regstack(struct thread *, uint64_t *, uint64_t *);
void cpu_mp_add(u_int, u_int, u_int);
int do_ast(struct trapframe *);
int ia64_count_cpus(void);
+void ia64_flush_dirty(struct thread *, struct _special *);
int ia64_highfp_drop(struct thread *);
int ia64_highfp_save(struct thread *);
void ia64_init(void);
OpenPOWER on IntegriCloud