svn commit: r276652 - head/sys/powerpc/include

Bruce Evans brde at optusnet.com.au
Sun Jan 4 08:41:15 UTC 2015


On Sun, 4 Jan 2015, Justin Hibbits wrote:

> Log:
>  Truncate DB_SMALL_VALUE_MAX to a much lower value.
>
>  Unlike the other architectures, the PowerPC kernel is loaded under the 2GB
>  boundary.
>
>  MFC after:	2 weeks
>
> Modified:
>  head/sys/powerpc/include/db_machdep.h
>
> Modified: head/sys/powerpc/include/db_machdep.h
> ==============================================================================
> --- head/sys/powerpc/include/db_machdep.h	Sun Jan  4 00:58:30 2015	(r276651)
> +++ head/sys/powerpc/include/db_machdep.h	Sun Jan  4 01:45:26 2015	(r276652)
> @@ -87,7 +87,7 @@ typedef	intptr_t	db_expr_t;	/* expressio
> #define	inst_load(ins)		0
> #define	inst_store(ins)		0
>
> -#define	DB_SMALL_VALUE_MAX	(0x7fffffff)
> +#define	DB_SMALL_VALUE_MAX	(KERNBASE-1)
> #define	DB_SMALL_VALUE_MIN	(-0x40001)
>
> #endif	/* _POWERPC_DB_MACHDEP_H_ */

DB_SMALL_VALUE was broken on all arches AFAIK.  Hopefully it now sort of
works for PowerPC, and you can fix it better for PowerPC and then other
arches.

It was first implemented in:

X RCS file: /home/ncvs/src/sys/ddb/db_sym.c,v
X Working file: db_sym.c
X head: 1.35
X ...
X ----------------------------
X revision 1.17
X date: 1997/01/16 11:27:10;  author: bde;  state: Exp;  lines: +8 -2
X Fixed printing of small offsets.  E.g., -4(%ebp) is now printed
X as -0x4(%ebp) instead of as _APTD+0xffc(%ebp), and if GUPROF is
X defined, 8(%ebp) is now printed as 0x8(%ebp) instead of as
X GMON_PROF_HIRES+0x4(%ebp).
X ----------------------------

This depends on magic symbols like _APTD.  Someone broke this on i386
by removing these magic symbols without updating the definition of
DB_SMALL_VALUE_MAX.  Other arches are even more broken.  They never
had a suitable magic symbol and/or the i386 value was copied without
changing it except to expand to 64 bits.

The brokenness is especially large on 64-bit arches.  It causes small
negative offsets from the stack or frame pointer to be misclassified
as large, so they are printed as huge cryptic unsigned values instead
of as small signed values.  E.g., -24(%ebp) is printed as
0xffffffe8(%ebp) on i386 and -24(%rbp) is printed as
0xffffffffffffffe8(%ebp) on amd64.

I use the following quick fixes for i386:

X Index: db_sym.c
X ===================================================================
X RCS file: /home/ncvs/src/sys/ddb/db_sym.c,v
X retrieving revision 1.35
X diff -u -2 -r1.35 db_sym.c
X --- db_sym.c	24 Feb 2004 22:51:42 -0000	1.35
X +++ db_sym.c	25 Feb 2004 10:11:09 -0000
X @@ -303,5 +303,9 @@
X  	if (name == 0)
X  		value = off;
X +#ifdef magic_large_symbols_unbroken
X  	if (value >= DB_SMALL_VALUE_MIN && value <= DB_SMALL_VALUE_MAX) {
X +#else
X +	if (off >= DB_SMALL_VALUE_MIN && off <= DB_SMALL_VALUE_MAX) {
X +#endif
X  		db_printf("%+#lr", (long)off);
X  		return;
X Index: db_machdep.h
X ===================================================================
X RCS file: /home/ncvs/src/sys/i386/include/db_machdep.h,v
X retrieving revision 1.17
X diff -u -2 -r1.17 db_machdep.h
X --- db_machdep.h	15 Sep 2001 11:06:07 -0000	1.17
X +++ db_machdep.h	9 Nov 2003 15:54:26 -0000
X @@ -87,7 +87,9 @@
X   * _APTmap = 0xffc00000.  Accepting this is OK (unless db_maxoff is
X   * set to >= 0x400000 - (max stack offset)).
X + * XXX _APTD and _APTmap went away.  Now there are SMP_prvspace = 0xffc00000
X + * and lapic = 0xfffff000.
X   */
X  #define	DB_SMALL_VALUE_MAX	0x7fffffff
X -#define	DB_SMALL_VALUE_MIN	(-0x400001)
X +#define	DB_SMALL_VALUE_MIN	(-0x3fffff)
X 
X #endif /* !_MACHINE_DB_MACHDEP_H_ */

I forget why I changed the logic in db_sym.c.  It is only a heuristic.

DB_SMALL_VALUE_MAX should probably be related to KERNBASE on all arches,
or just be much smaller.  0x7fffffff obviously doesn't work on i386 either
if KERNBASE is smaller than that.  Namespace problems prevent defining the
DB* symbols in terms of KERNBASE and even more so for symbols like
_APTD that were only defined in object files.  0x7fffffff allowed reduction
of KERNBASE well below its default value at the time of the original
implementation.  It was only about 32MB or 256MB below the top.  Now its
default is 3GB and 2GB isn't much lower, but it is not very useful on i386 to
change the split to much more for the kernel and much less for applications.

DB_SMALL_VALUE_MIN is related to the memory layout.  There may be symbols
near the top of the address space no matter what KERNBASE is.  This happens
on i386 -- most kernel symbols are near KERNBASE (default 0xc0000000) but
there are some magic symbols related mainly to page tables near the top.
We want to print all of these symbols by name, or at least as large
unsigned values (the latter happens too much for constant literals in
ddb and gdb, and objdump is worse).  So DB_SMALL_VALUE_MIN must be fairly
small.  Also, the address space should be laid out so as to not have any
important symbols near the top, to leave space for DB_SMALL_VALUE_MIN not
needing to be too small.

To avoid the namespace bugs and to de-magic the limits, the definitions
show be something like:

/* Set in locore; currently only used in ldscript: */
extern char kernbase[];
/* If not already defined somwhere: */
extern char end[];

#define	DB_SMALL_VALUE_MAX	kernbase
#define	DB_SMALL_VALUE_MIN	(-(intptr_t)end)	/* does this work? */

Or with less magic:

/* Set these in locore like kernbase: */
extern char db_smallest_ksym[];
extern char db_largest_ksym[];

#define	DB_SMALL_VALUE_MAX	db_smallest_ksym
#define	DB_SMALL_VALUE_MIN	(-(intptr_t)db_largest_ksym)

It is difficult to define the magic symbols with best values to work with
the heuristic even when you control them.  Addresses outside of the
statically known address space may be generated by loading modules and
malloc()ing data.  These shouldn't be printed as signed.  The above
definitions give too wide a range of small values.  So db_largest_ksym
should be set to something more like its current value of a few MB below
the top, perhaps to max(this value, end).  I don't know how to write this
expression in asm.  It could be written in C:

#define	DB_SMALL_VALUE_MIN	MAX(-3xfffff, -(intptr_t)db_largest_ksym)

db_largest_ksym must also be larger than INTPTR_MAX for the sign magic to
work.  That probably won't happen automatically if all static kernel
symbols are in the lower half of the address space.

The i386 kernel address space now looks like:

X 00400000 A kernload
X bfc00000 A PTmap
X bfeff000 A PTD
X bfeffbfc A PTDpde
X c0000000 A kernbase
X c0453fd0 T btext
X c0454039 t begin
X ...
X c092f494 A _end
X c092f494 A end

This hasn't changed for more than 10 years.  Apparently the page table
stuff was moved from the top of the address space to just below kernbase,
so there are no symbols near the top.  DB_SMALL_VALUE_MAX needs to be
below kernbase.  The low kernload symbol might be
a problem.

The amd64 address space now looks like:

X                  w uart_sab82532_class
X                  w uart_z8530_class

No values?

X 0000000000200000 A kernphys
X ffff800000000000 A loc_PTmap
X ffff804000000000 A loc_PDmap
X ffff804020000000 A loc_PDPmap
X ffff804020100000 A loc_PML4map
X ffff804020100800 A loc_PML4pml4e
X fffff80000000000 A dmapbase
X fffffc0000000000 A dmapend
X ffffffff80000000 A kernbase
X ffffffff802baa50 T btext
X ...
X ffffffff8123be08 A _end

Essentially the same.  The smallest symbol of interest is much further
below kernbase, and I think malloced memory is below kernbase too (there
is only 2GB above).

Bruce


More information about the svn-src-all mailing list