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
This commit is contained in:
parent
b505f47bef
commit
4da47b2fec
@ -106,6 +106,13 @@ SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
|
||||
&freebsd_brand_oinfo);
|
||||
|
||||
|
||||
void
|
||||
elf64_dump_thread(struct thread *td __unused, void *dst __unused,
|
||||
size_t *off __unused)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* Process one elf relocation with addend. */
|
||||
static int
|
||||
elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
|
||||
|
@ -102,6 +102,14 @@ SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
|
||||
(sysinit_cfunc_t) elf64_insert_brand_entry,
|
||||
&freebsd_brand_oinfo);
|
||||
|
||||
|
||||
void
|
||||
elf64_dump_thread(struct thread *td __unused, void *dst __unused,
|
||||
size_t *off __unused)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* Process one elf relocation with addend. */
|
||||
static int
|
||||
elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
|
||||
|
@ -102,6 +102,14 @@ SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
|
||||
(sysinit_cfunc_t) elf32_insert_brand_entry,
|
||||
&freebsd_brand_oinfo);
|
||||
|
||||
|
||||
void
|
||||
elf32_dump_thread(struct thread *td __unused, void *dst __unused,
|
||||
size_t *off __unused)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* Process one elf relocation with addend. */
|
||||
static int
|
||||
elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
|
||||
|
@ -157,6 +157,14 @@ SYSINIT(oia32, SI_SUB_EXEC, SI_ORDER_ANY,
|
||||
(sysinit_cfunc_t) elf32_insert_brand_entry,
|
||||
&ia32_brand_oinfo);
|
||||
|
||||
|
||||
void
|
||||
elf32_dump_thread(struct thread *td __unused, void *dst __unused,
|
||||
size_t *off __unused)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* XXX may be freebsd32 MI */
|
||||
static register_t *
|
||||
ia32_copyout_strings(struct image_params *imgp)
|
||||
|
@ -102,6 +102,14 @@ SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
|
||||
(sysinit_cfunc_t) elf32_insert_brand_entry,
|
||||
&freebsd_brand_oinfo);
|
||||
|
||||
|
||||
void
|
||||
elf32_dump_thread(struct thread *td __unused, void *dst __unused,
|
||||
size_t *off __unused)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* Process one elf relocation with addend. */
|
||||
static int
|
||||
elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -1204,8 +1204,11 @@ __elfN(puthdr)(struct thread *td, void *dst, size_t *off, int numsegs)
|
||||
sizeof *status);
|
||||
__elfN(putnote)(dst, off, "FreeBSD", NT_FPREGSET, fpregset,
|
||||
sizeof *fpregset);
|
||||
|
||||
/* XXX allow for MD specific notes. */
|
||||
/*
|
||||
* Allow for MD specific notes, as well as any MD
|
||||
* specific preparations for writing MI notes.
|
||||
*/
|
||||
__elfN(dump_thread)(thr, dst, off);
|
||||
|
||||
thr = (thr == td) ? TAILQ_FIRST(&p->p_threads) :
|
||||
TAILQ_NEXT(thr, td_plist);
|
||||
|
@ -105,6 +105,14 @@ SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
|
||||
(sysinit_cfunc_t) elf32_insert_brand_entry,
|
||||
&freebsd_brand_oinfo);
|
||||
|
||||
|
||||
void
|
||||
elf32_dump_thread(struct thread *td __unused, void *dst __unused,
|
||||
size_t *off __unused)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* Process one elf relocation with addend. */
|
||||
static int
|
||||
elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
|
||||
|
@ -115,6 +115,14 @@ SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
|
||||
(sysinit_cfunc_t) elf64_insert_brand_entry,
|
||||
&freebsd_brand_oinfo);
|
||||
|
||||
|
||||
void
|
||||
elf64_dump_thread(struct thread *td __unused, void *dst __unused,
|
||||
size_t *off __unused)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The following table holds for each relocation type:
|
||||
* - the width in bits of the memory location the relocation
|
||||
|
@ -76,6 +76,9 @@ int __elfN(remove_brand_entry)(Elf_Brandinfo *entry);
|
||||
int __elfN(freebsd_fixup)(register_t **, struct image_params *);
|
||||
int __elfN(coredump)(struct thread *, struct vnode *, off_t);
|
||||
|
||||
/* Machine specific function to dump per-thread information. */
|
||||
void __elfN(dump_thread)(struct thread *, void *, size_t *);
|
||||
|
||||
extern int __elfN(fallback_brand);
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
Loading…
x
Reference in New Issue
Block a user