NLKD - Novell Linux Kernel Debugger
Subsystems (22)
cover NLKD - Novell Linux Kernel Debugger
The following patch set represents the Novell Linux Kernel Debugger, stripped off of its original low-level exception handling framework.
Jan
PATCH 1/39 NLKD - an alternative kallsyms approach
This patch provides an alternative to the pre-exisiting kallsyms code. That code, from a kernel debugger perspective at least, suffers from incomplete information, making it impossible to
(a) disambiguate multiple static functions of the same name (in different source files),
(b) determine a complete set of attributes for a symbol (namely, the symbol's size, but also its type, which gets converted to an nm-like one-character representation), and
(c) retain full section information
This new approach basically makes handling core kernel and module symbols the same, by retrieving the kernel's section, symbol, and string tables rather than parsing the system map.
At once it adds the functionality to strip unneeded symbols from modules, which results in non-neglectable space savings for typical distributions (which large amounts of modules). Note that with certain recent, but broken binutils versions (2.16.90*, 2.16.91* up to and including 2.16.91.0.3) this can only be built without CONFIG_MODVERSIONS.
(actual patch attached)
This patch provides an alternative to the pre-exisiting kallsyms code. That code, from a kernel debugger perspective at least, suffers from incomplete information, making it impossible to
(a) disambiguate multiple static functions of the same name (in different source files),
(b) determine a complete set of attributes for a symbol (namely, the symbol's size, but also its type, which gets converted to an nm-like one-character representation), and
(c) retain full section information
This new approach basically makes handling core kernel and module symbols the same, by retrieving the kernel's section, symbol, and string tables rather than parsing the system map.
At once it adds the functionality to strip unneeded symbols from modules, which results in non-neglectable space savings for typical distributions (which large amounts of modules). Note that with certain recent, but broken binutils versions (2.16.90*, 2.16.91* up to and including 2.16.91.0.3) this can only be built without CONFIG_MODVERSIONS.
Makefile +104 -15
@@ -160,15 +160,19 @@ LOCALVERSION = $(subst $(space),, \ KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)$(LOCALVERSION) +HOSTARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ + -e s/arm.*/arm/ -e s/sa110/arm/ \ + -e s/s390x/s390/ -e s/parisc64/parisc/ ) + # SUBARCH tells the usermode build what the underlying arch is. That is set # first, and if a usermode build is happening, the "ARCH=um" on the command # line overrides the setting of ARCH below. If a native build is happening, # then ARCH is assigned, getting whatever value it gets normally, and # SUBARCH is subsequently ignored. -SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ - -e s/arm.*/arm/ -e s/sa110/arm/ \ - -e s/s390x/s390/ -e s/parisc64/parisc/ ) +ifeq ($(SUBARCH),) +SUBARCH := $(if $(filter-out um,$(ARCH)),$(ARCH),$(HOSTARCH)) +endif # Cross compiling and selecting different set of gcc/bin-utils # ---------------------------------------------------------------------------
@@ -327,6 +331,7 @@ NM = $(CROSS_COMPILE)nm STRIP = $(CROSS_COMPILE)strip OBJCOPY = $(CROSS_COMPILE)objcopy OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf AWK = awk GENKSYMS = scripts/genksyms/genksyms DEPMOD = /sbin/depmod
@@ -729,24 +734,108 @@ endef # Generate .S file with all kernel symbols quiet_cmd_kallsyms = KSYM $@ - cmd_kallsyms = $(NM) -n $< | $(KALLSYMS) \ - $(if $(CONFIG_KALLSYMS_ALL),--all-symbols) > $@ -.tmp_kallsyms1.o .tmp_kallsyms2.o .tmp_kallsyms3.o: %.o: %.S scripts FORCE +ifdef CONFIG_KALLSYMS_TRADITIONAL + +cmd_kallsyms = { test $* -eq 0 || $(NM) -n $<; } | $(KALLSYMS) $(if $(CONFIG_KALLSYMS_ALL),--all-symbols) >$@ + +kallsyms-strip-ext := + +else + +cmd_kallsyms = { test $* -eq 0 || $(NM) -n $<; } | $(KALLSYMS) -$$(expr $* + 1) >$@ + +kallsyms-strip-src := $(if $(CONFIG_KALLSYMS_STRIP_GENERATED),$(srctree)/$(KALLSYMS)) +kallsyms-strip-src += $(if $(CONFIG_KALLSYMS_STRIP_GENERATED),$(wildcard $(srctree)/arch/$(ARCH)/kallsyms)) +kallsyms-strip-src += $(if $(CONFIG_KALLSYMS_ALL),,.tmp_data) +kallsyms-strip-src := $(strip $(kallsyms-strip-src)) +kallsyms-strip-ext := $(if $(kallsyms-strip-src),.stripped) + +quiet_cmd_ktab = KTAB $@ +define cmd_ktab + if [ $* -eq 0 ]; then \ + echo "placeholder" >$@; \ + else \ + rm -f $@; \ + $(READELF) -SW $< | while read idx name type addr offs size more; do \ + if [ "$(suffix $@)" = "$$name" ]; then \ + tail -c+$$((0x$$offs+1)) <$< | head -c $$((0x$$size)) >$@; \ + break; \ + fi; \ + done; \ + test -s $@; \ + fi +endef + +quiet_cmd_kshdr = KSHDR $@ +define cmd_kshdr + if [ $* -eq 0 ]; then \ + echo "placeholder" >$@; \ + else \ + nsect= ;: grab this from the first decimal number; \ + osect= ;: grab this from the first hexadecimal number; \ + for i in $$($(READELF) -S $< | egrep '^[^]\[()]*$$'); \ + do \ + test -z "$$nsect" && nsect=$$(echo $${i%:*} | egrep '^[[:digit:]]+$$'); \ + test -z "$$osect" && osect=$$(echo $${i%:*} | egrep '^0[xX][[:xdigit:]]+$$'); \ + done; \ + zsect= ;: grab this from the last number that is followed by a unit specification; \ + for i in $$($(READELF) -h $< | egrep ':[[:space:]]+[[:digit:]]+[[:space:]]+\(.*\)'); \ + do \ + val=$$(echo $$i | egrep '^([[:digit:]]+|0[xX][[:xdigit:]]+)$$'); \ + test -n "$$val" && zsect=$$val; \ + done; \ + tail -c+$$((osect+1)) <$< | head -c $$((nsect*zsect)) >$@; \ + fi +endef + +quiet_cmd_kstrip = STRIP $< +cmd_kstrip = $(OBJCOPY) $(addprefix --strip-symbols ,$(filter %.strip,$^)) -w $< $@ + +.tmp_kallsyms%.symtab: .tmp_vmlinux%$(kallsyms-strip-ext) + $(call cmd,ktab) + +.tmp_kallsyms%.strtab: .tmp_vmlinux%$(kallsyms-strip-ext) + $(call cmd,ktab) + +.tmp_kallsyms%.sections: .tmp_vmlinux%$(kallsyms-strip-ext) + $(call cmd,kshdr) + +.tmp_kallsyms%.shstrtab: .tmp_vmlinux%$(kallsyms-strip-ext) + $(call cmd,ktab) + +.tmp_vmlinux%.stripped: .tmp_vmlinux% $(addsuffix .strip,$(kallsyms-strip-src)) $(objtree)/include/linux/autoconf.h + $(call cmd,kstrip) + +.tmp_data.strip: .tmp_vmlinux1 $(objtree)/include/linux/autoconf.h + $(Q)$(NM) $< | sed -n 's,[[:xdigit:]]\+[[:space:]]\+[^tT][[:space:]]\+\(.*\),\1,p' \ + | while read i; do case $$i in \ + $(addsuffix $(close);;, \ + $(shell cat $(addsuffix .strip,$(filter $(srctree)/%,$(kallsyms-strip-src))) /dev/null \ + | sed 's,\([;|&<>()$$\\]\),\\\1,g')) \ + *) echo $$i;; \ + esac; done >$@ + +endif # CONFIG_KALLSYMS_TRADITIONAL + +$(foreach n,0 1 2 3,.tmp_kallsyms$(n).o): AFLAGS+=-Wa,--strip-local-absolute +$(foreach n,0 1 2 3,.tmp_kallsyms$(n).o): %.o: %.S $(if $(CONFIG_KALLSYMS_TRADITIONAL),,%.symtab %.strtab %.sections %.shstrtab) scripts FORCE $(call if_changed_dep,as_o_S) -.tmp_kallsyms%.S: .tmp_vmlinux% $(KALLSYMS) +.tmp_kallsyms%.S: .tmp_vmlinux%$(kallsyms-strip-ext) $(KALLSYMS) $(objtree)/include/linux/autoconf.h $(call cmd,kallsyms) -# .tmp_vmlinux1 must be complete except kallsyms, so update vmlinux version -.tmp_vmlinux1: $(vmlinux-lds) $(vmlinux-all) FORCE - $(call if_changed_rule,ksym_ld) +.tmp_vmlinux0$(kallsyms-strip-ext): + $(Q)echo "placeholder" >$@ -.tmp_vmlinux2: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms1.o FORCE - $(call if_changed,vmlinux__) +.tmp_vmlinux1: .tmp_kallsyms0.o +.tmp_vmlinux2: .tmp_kallsyms1.o +.tmp_vmlinux3: .tmp_kallsyms2.o -.tmp_vmlinux3: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms2.o FORCE - $(call if_changed,vmlinux__) +.tmp_vmlinux%: LDFLAGS_vmlinux += -S +# .tmp_vmlinux1 must be complete except kallsyms, so update vmlinux version +.tmp_vmlinux%: $(vmlinux-lds) $(vmlinux-all) FORCE + $(if $(filter 1,$*),$(call if_changed_rule,ksym_ld),$(call if_changed,vmlinux__)) # Needs to visit scripts/ before $(KALLSYMS) can be used. $(KALLSYMS): scripts ;
@@ -980,7 +1069,7 @@ endif # CONFIG_MODULES # Directories & files removed with 'make clean' CLEAN_DIRS += $(MODVERDIR) CLEAN_FILES += vmlinux System.map \ - .tmp_kallsyms* .tmp_version .tmp_vmlinux* .tmp_System.map + .tmp_data* .tmp_kallsyms* .tmp_version .tmp_vmlinux* .tmp_System.map # Directories & files removed with 'make mrproper' MRPROPER_DIRS += include/config include2
arch/alpha/defconfig +1 -0
@@ -32,6 +32,7 @@ CONFIG_LOG_BUF_SHIFT=14 # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_TRADITIONAL=y CONFIG_KALLSYMS_ALL=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y
arch/frv/defconfig +1 -0
@@ -33,6 +33,7 @@ CONFIG_SYSCTL=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_TRADITIONAL=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_PRINTK=y
arch/i386/defconfig +2 -0
@@ -28,6 +28,8 @@ CONFIG_HOTPLUG=y # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_TRADITIONAL=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y
arch/i386/kernel/entry.S +43 -6
238 lines not on this page · raw message
arch/ia64/Makefile +0 -1
@@ -9,7 +9,6 @@ # NM := $(CROSS_COMPILE)nm -B -READELF := $(CROSS_COMPILE)readelf export AWK
arch/ia64/defconfig +1 -0
@@ -29,6 +29,7 @@ CONFIG_IKCONFIG_PROC=y # CONFIG_CPUSETS is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_TRADITIONAL=y CONFIG_KALLSYMS_ALL=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_PRINTK=y
arch/m68k/defconfig +1 -0
@@ -32,6 +32,7 @@ CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_TRADITIONAL=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_PRINTK=y CONFIG_BUG=y
arch/mips/defconfig +1 -0
@@ -32,6 +32,7 @@ CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_TRADITIONAL=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y
arch/ppc64/defconfig +1 -0
@@ -41,6 +41,7 @@ CONFIG_CPUSETS=y CONFIG_INITRAMFS_SOURCE="" # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_TRADITIONAL=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_PRINTK=y
arch/s390/defconfig +1 -0
@@ -37,6 +37,7 @@ CONFIG_IKCONFIG_PROC=y CONFIG_INITRAMFS_SOURCE="" # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_TRADITIONAL=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_PRINTK=y
arch/sparc/defconfig +2 -0
@@ -28,7 +28,9 @@ CONFIG_LOG_BUF_SHIFT=14 # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_TRADITIONAL=y # CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y
arch/sparc64/defconfig +1 -0
@@ -30,6 +30,7 @@ CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_TRADITIONAL=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y
arch/um/defconfig +1 -0
@@ -70,6 +70,7 @@ CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_TRADITIONAL=y # CONFIG_KALLSYMS_ALL is not set CONFIG_KALLSYMS_EXTRA_PASS=y CONFIG_PRINTK=y
arch/x86_64/defconfig +1 -0
@@ -43,6 +43,7 @@ CONFIG_IKCONFIG_PROC=y CONFIG_INITRAMFS_SOURCE="" # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_TRADITIONAL=y CONFIG_KALLSYMS_ALL=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_PRINTK=y
arch/x86_64/kernel/entry.S +43 -1
241 lines not on this page · raw message
include/linux/kallsyms.h +27 -0
@@ -19,6 +19,25 @@ const char *kallsyms_lookup(unsigned lonunsigned long *offset, char **modname, char *namebuf); +#ifdef CONFIG_MODULES + +#if defined(Elf_Shdr) && defined(Elf_Sym) +char kallsyms_elf_type (const Elf_Sym *sym, +const Elf_Shdr *sechdrs, +const char *secstrings); +#endif + +struct module ; +void module_init_done (struct module *); + +unsigned long kallsyms_find_symname (struct module *,const char *); + +const char *kallsyms_get_ksymbol (struct module *, +unsigned long addr, +unsigned long *size, +unsigned long *offset); +#endif +/* Replace "%s" in format with address, if found */ extern void __print_symbol (const char *fmt,unsigned long address);
@@ -64,4 +83,12 @@ do { \__print_symbol (fmt, addr); \ } while(0) +#if defined(CONFIG_KALLSYMS ) && !defined(CONFIG_KALLSYMS_TRADITIONAL ) +void kallsyms_early_init (void ); +void kallsyms_init_done (void ); +#else +#define kallsyms_early_init () ((void)0) +#define kallsyms_init_done () ((void)0) +#endif +#endif /*_LINUX_KALLSYMS_H*/
include/linux/linkage.h +10 -0
@@ -39,6 +39,16 @@ALIGN ; \ name: +#ifdef CONFIG_KALLSYMS +#define ENDPROC (name) \ + .type name, @function; \ + END(name) +#define END (name) \ + .size name, .-name +#else +#define ENDPROC (name) +#define END (name) +#endif #endif
include/linux/module.h +8 -1
@@ -301,7 +301,14 @@ struct module/* We keep the symbol and string tables for kallsyms. */ Elf_Sym *symtab;unsigned long num_symtab; -char *strtab; +const char *strtab; + +# ifndef CONFIG_KALLSYMS_TRADITIONAL +/* And also the sections and their string table. */ +Elf_Shdr *sections; +unsigned long num_sections; +const char *shstrtab; +# endif /* Section attributes */ struct module_sect_attrs *sect_attrs;
init/Kconfig +17 -0
@@ -272,9 +272,19 @@ config KALLSYMS symbolic stack backtraces. This increases the size of the kernel somewhat, as all symbols have to be loaded into the kernel image. +config KALLSYMS_TRADITIONAL + bool "Traditional kallsyms symbol table format" + depends on KALLSYMS + default !MODULES + help + Say N here if you want the kernel symbol table to be consistent with + that loadable modules use (i.e. the ELF symbol table extracted from + the kernel binary). + config KALLSYMS_ALL bool "Include all symbols in kallsyms" depends on DEBUG_KERNEL && KALLSYMS + default DEBUG_KERNEL help Normally kallsyms only contains the symbols of functions, for nicer OOPS messages. Some debuggers can use kallsyms for other
@@ -283,6 +293,13 @@ config KALLSYMS_ALL Say N. +config KALLSYMS_STRIP_GENERATED + bool "Strip machine generated symbols from kallsyms" if KALLSYMS_ALL + depends on KALLSYMS && !KALLSYMS_TRADITIONAL + default y + help + Say N if you want kallsyms to retain even machine generated symbols. + config KALLSYMS_EXTRA_PASS bool "Do an extra kallsyms pass" depends on KALLSYMS
init/main.c +2 -0
@@ -481,6 +481,7 @@ asmlinkage void __init start_kernel(void &unknown_bootoption);sort_main_extable ();trap_init (); +kallsyms_early_init ();rcu_init ();init_IRQ ();pidhash_init ();
@@ -708,6 +709,7 @@ static int init(void * unused)* we're essentially up and running. Get rid of the * initmem segments and start the user-mode stuff.. */ +kallsyms_init_done ();free_initmem ();unlock_kernel (); system_state =SYSTEM_RUNNING ;
kernel/kallsyms.c +306 -34
467 lines not on this page · raw message
kernel/module.c +138 -119
377 lines not on this page · raw message
scripts/Kbuild.include +2 -0
@@ -5,6 +5,8 @@ comma := , empty := space := $(empty) $(empty) +open := ( +close := ) ### # The temporary file to save gcc -MD generated dependencies must not
scripts/Makefile +1 -0
@@ -8,6 +8,7 @@ # conmakehash: Create arrays for initializing the kernel console tables hostprogs-$(CONFIG_KALLSYMS) += kallsyms +HOSTCFLAGS_kallsyms.o := -D ARCH_$(SUBARCH) hostprogs-$(CONFIG_LOGO) += pnmtologo hostprogs-$(CONFIG_VT) += conmakehash hostprogs-$(CONFIG_PROM_CONSOLE) += conmakehash
scripts/Makefile.build +20 -11
@@ -156,23 +156,26 @@ else # are done. # o otherwise, we calculate symbol versions using the good old # genksyms on the preprocessed source and postprocess them in a way -# that they are usable as a linker script -# o generate <file>.o from .tmp_<file>.o using the linker to -# replace the unresolved symbols __crc_exported_symbol with -# the actual value of the checksum generated by genksyms +# that they are usable as assembly source +# o recompile <file>.o from <file>.c forcing inclusion of assembler +# directives defining the actual values of __crc_*, followed by +# objcopy-ing them to force these symbols to be local to permit +# stripping them during the final module linking stage. cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $< cmd_modversions = \ if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \ - $(CPP) -D__GENKSYMS__ $(c_flags) $< \ - | $(GENKSYMS) \ - > $(@D)/.tmp_$(@F:.o=.ver); \ - \ - $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \ - -T $(@D)/.tmp_$(@F:.o=.ver); \ - rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver); \ + if $(CPP) -D__GENKSYMS__ $(c_flags) $< \ + | $(GENKSYMS) -a > $(@D)/.tmp_$(@F:.o=.ver) \ + && $(CC) $(c_flags) -c -w -include $(@D)/.tmp_$(@F:.o=.ver) -o $@ $< \ + && $(OBJCOPY) -L '__crc_*' -w $@; then \ + rm -f $(@D)/.tmp_$(@F); \ + else \ + rm -f $@; exit 1; \ + fi; \ else \ mv -f $(@D)/.tmp_$(@F) $@; \ + rm -f $(@D)/.tmp_$(@F:.o=.ver); \ fi; endif
@@ -183,6 +186,12 @@ define rule_cc_o_c $(cmd_cc_o_c); \ $(cmd_modversions) \ scripts/basic/fixdep $(depfile) $@ '$(subst ','\'',$(cmd_cc_o_c))' > $(@D)/.$(@F).tmp; \ + if [ -r $(@D)/.tmp_$(@F:.o=.ver) ]; then \ + echo >> $(@D)/.$(@F).tmp; \ + echo '$@: $(GENKSYMS)' >> $(@D)/.$(@F).tmp; \ + echo '$(GENKSYMS):: ;' >> $(@D)/.$(@F).tmp; \ + rm $(@D)/.tmp_$(@F:.o=.ver); \ + fi; \ rm -f $(depfile); \ mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd endef
scripts/Makefile.modinst +2 -1
@@ -17,7 +17,8 @@ __modinst: $(modules) @: quiet_cmd_modules_install = INSTALL $@ - cmd_modules_install = mkdir -p $(2); cp $@ $(2) + cmd_modules_install = mkdir -p $(2); \ + cp $(firstword $(wildcard $@s) $@) $(2)/$(basename $(@F)).ko # Modules built outside the kernel source tree go into extra by default INSTALL_MOD_DIR ?= extra
scripts/Makefile.modpost +62 -6
102 lines not on this page · raw message
scripts/genksyms/genksyms.c +17 -5
@@ -43,7 +43,7 @@ FILE *debugfile;int cur_line =1 ;char *cur_filename, *output_directory; -int flag_debug, flag_dump_defs, flag_warnings; +int flag_debug, flag_dump_defs, flag_warnings, flag_inline_asm;static int errors;static int nsyms;
@@ -457,8 +457,16 @@ export_symbol(const char *name)if (flag_dump_defs)fputs (">\n" , debugfile); -/* Used as a linker script. */ -printf ("__crc_%s = 0x%08lx ;\n" , name, crc); +if (!flag_inline_asm) + { +/* Used as a linker script. */ +printf ("__crc_%s = 0x%08lx ;\n" , name, crc); + } +else + { +/* Used as inline assembly. */ +printf ("__asm__(\".equiv __crc_%s, 0x%08lx\");\n" , name, crc); + } } }
@@ -529,6 +537,7 @@ main(int argc, char **argv)#ifdef __GNU_LIBRARY__struct option long_opts[] = { + {"asm" ,0 ,0 ,'a' }, {"debug" ,0 ,0 ,'d' }, {"warnings" ,0 ,0 ,'w' }, {"quiet", 0, 0, 'q'},
@@ -538,13 +547,16 @@ main(int argc, char **argv) {0, 0, 0, 0} }; -while ((o =getopt_long (argc, argv,"dwqVDk:p:" , +while ((o =getopt_long (argc, argv,"adwqVDk:p:" , &long_opts[0 ],NULL )) !=EOF ) #else /* __GNU_LIBRARY__ */ - while ((o = getopt(argc, argv, "dwqVDk:p:")) != EOF) + while ((o = getopt(argc, argv, "adwqVDk:p:")) != EOF)#endif /* __GNU_LIBRARY__ */ switch (o) { +case 'a' : + flag_inline_asm =1 ; +break ;case 'd' : flag_debug++;break ;
scripts/kallsyms.c +65 -27
144 lines not on this page · raw message
scripts/kallsyms.strip +18 -0
@@ -0,0 +1,18 @@ +<*> +__compound_literal[$.][0-9]* +__crc_[a-zA-Z_]* +__exitcall_[a-zA-Z_]* +__func__[$.][0-9]* +__FUNCTION__[$.][0-9]* +gcc[0-9]_compiled[$.] +__initcall_[a-zA-Z_]* +__kcrctab_[a-zA-Z_]* +__kstrtab_[a-zA-Z_]* +__ksymtab_[a-zA-Z_]* +__mod_[a-zA-Z_]*[0-9] +__module_depends +__param_[a-zA-Z_]* +__pci_fixup_[A-Z]* +__PRETTY_FUNCTION__[$.][0-9]* +__setup_[a-zA-Z_0-9]* +____versions
PATCH 2/39 NLKD - an alternative early ioremap approach
An alternative to (on i386) boot-time ioremap approaches, which is more architecture independent (though arch dependent code needs adjustments if this is to be made use of, which with this patch only happens for i386 and x86_64) and doesn't require alternative boot-time interfaces.
(actual patch attached)
An alternative to (on i386) boot-time ioremap approaches, which is more architecture independent (though arch dependent code needs adjustments if this is to be made use of, which with this patch only happens for i386 and x86_64) and doesn't require alternative boot-time interfaces.
arch/i386/kernel/setup.c +3 -0
@@ -1127,6 +1127,9 @@ static unsigned long __init setup_memory }printk (KERN_NOTICE "%ldMB HIGHMEM available.\n" ,pages_to_mb (highend_pfn - highstart_pfn)); + high_memory = (void *)__va (highstart_pfn *PAGE_SIZE -1 ) +1 ; +#else + high_memory = (void *)__va (max_low_pfn *PAGE_SIZE -1 ) +1 ;#endif printk (KERN_NOTICE "%ldMB LOWMEM available.\n" ,pages_to_mb (max_low_pfn));
arch/i386/mm/init.c +0 -6
@@ -560,12 +560,6 @@ void __init mem_init(void)set_max_mapnr_init (); -#ifdef CONFIG_HIGHMEM - high_memory = (void *)__va (highstart_pfn *PAGE_SIZE -1 ) +1 ; -#else - high_memory = (void *)__va (max_low_pfn *PAGE_SIZE -1 ) +1 ; -#endif -/* this will put all low memory onto the freelists */ totalram_pages +=free_all_bootmem ();
arch/i386/mm/ioremap.c +2 -1
@@ -257,7 +257,8 @@ void iounmap(volatile void __iomem *addr } out_unlock:write_unlock (&vmlist_lock); -kfree (p); +if (p) +free_vm_area (p); }EXPORT_SYMBOL (iounmap);
arch/i386/mm/pgtable.c +4 -1
@@ -11,6 +11,7 @@#include <linux/smp.h> #include <linux/highmem.h> #include <linux/slab.h> +#include <linux/bootmem.h> #include <linux/pagemap.h> #include <linux/spinlock.h>
@@ -148,7 +149,9 @@ void __set_fixmap (enum fixed_addressespte_t *pte_alloc_one_kernel (struct mm_struct *mm,unsigned long address) { -return (pte_t *)__get_free_page (GFP_KERNEL |__GFP_REPEAT|__GFP_ZERO); +if (likely (totalram_pages)) +return (pte_t *)__get_free_page (GFP_KERNEL |__GFP_REPEAT|__GFP_ZERO); +return alloc_bootmem_pages (PAGE_SIZE ); }struct page *pte_alloc_one (struct mm_struct *mm,unsigned long address)
arch/x86_64/kernel/setup.c +1 -0
@@ -566,6 +566,7 @@ void __init setup_arch(char **cmdline_p)* we are rounding upwards: */ end_pfn =e820_end_of_ram (); + high_memory = (void *)__va (end_pfn *PAGE_SIZE -1 ) +1 ;check_efer ();
arch/x86_64/mm/init.c +0 -1
@@ -400,7 +400,6 @@ void __init mem_init(void) max_low_pfn = end_pfn; max_pfn = end_pfn; num_physpages = end_pfn; - high_memory = (void *)__va (end_pfn *PAGE_SIZE );/* clear the zero-page */ memset (empty_zero_page,0 ,PAGE_SIZE );
arch/x86_64/mm/ioremap.c +2 -1
@@ -266,5 +266,6 @@ void iounmap(volatile void __iomem *addrelse if (p->flags >>20 )ioremap_change_attr (p->phys_addr, p->size,0 );write_unlock (&vmlist_lock); -kfree (p); +if (p) +free_vm_area (p); }
include/linux/vmalloc.h +2 -0
@@ -8,6 +8,7 @@#define VM_IOREMAP 0x00000001/* ioremap() and friends */ #define VM_ALLOC 0x00000002/* vmalloc() */ #define VM_MAP 0x00000004/* vmap()ed pages */ +#define VM_BOOTMEM 0x00000008/* allocated from bootmem */ /* bits [20..32] reserved for arch specific ioremap internals */ /*
@@ -50,6 +51,7 @@ extern struct vm_struct *__get_vm_area(u unsigned long start, unsigned long end);extern struct vm_struct *remove_vm_area (void *addr);extern struct vm_struct *__remove_vm_area (void *addr); +extern void free_vm_area (struct vm_struct *area);extern int map_vm_area (struct vm_struct *area,pgprot_t prot,struct page ***pages);extern void unmap_vm_area (struct vm_struct *area);
mm/page_alloc.c +9 -0
@@ -992,6 +992,15 @@ fastcall unsigned long get_zeroed_page(g {struct page * page; +if (unlikely (!totalram_pages)) { +/* This exists solely for page table allocation; pages +allocated this way must never be freed! */ +void *address =alloc_bootmem_pages (PAGE_SIZE ); + +clear_page (address); +return (unsigned long ) address; + } +/* * get_zeroed_page() returns a 32-bit address, which cannot represent * a highmem page
mm/vmalloc.c +25 -12
@@ -11,6 +11,7 @@#include <linux/module.h> #include <linux/highmem.h> #include <linux/slab.h> +#include <linux/bootmem.h> #include <linux/spinlock.h> #include <linux/interrupt.h>
@@ -177,20 +178,24 @@ struct vm_struct *__get_vm_area(unsigned } addr =ALIGN (start, align); size =PAGE_ALIGN (size); - - area =kmalloc (sizeof (*area),GFP_KERNEL ); -if (unlikely (!area)) -return NULL ; - -if (unlikely (!size)) { -kfree (area); +if (unlikely (!size))return NULL ; - } -/* * We always allocate a guard page. */ size +=PAGE_SIZE ; +if (unlikely (!size)) +return NULL ; + +BUG_ON (flags &VM_BOOTMEM ); +if (likely (malloc_sizes->cs_cachep)) + area =kmalloc (sizeof (*area),GFP_KERNEL ); +else { + area =alloc_bootmem (sizeof (*area)); + flags |=VM_BOOTMEM ; + } +if (unlikely (!area)) +return NULL ;write_lock (&vmlist_lock);for (p = &vmlist; (tmp = *p) !=NULL ;p = &tmp->next) {
@@ -225,7 +230,7 @@ found: out:write_unlock (&vmlist_lock); -kfree (area); +free_vm_area (area);if (printk_ratelimit ())printk (KERN_WARNING "allocation failed: out of vmalloc space - use vmalloc=<size> to increase size.\n" );return NULL ;
@@ -286,6 +291,14 @@ struct vm_struct *remove_vm_area(void *areturn v; } +void free_vm_area (struct vm_struct *area) +{ +if (likely (!(area->flags &VM_BOOTMEM ))) +kfree (area); +else if (!malloc_sizes->cs_cachep) +free_bootmem (virt_to_phys (area),sizeof (*area)); +} +void __vunmap (void *addr,int deallocate_pages) {struct vm_struct *area;
@@ -322,7 +335,7 @@ void __vunmap(void *addr, int deallocatekfree (area->pages); } -kfree (area); +free_vm_area (area);return ; }
@@ -412,7 +425,7 @@ void *__vmalloc_area(struct vm_struct *a area->pages = pages;if (!area->pages) {remove_vm_area (area->addr); -kfree (area); +free_vm_area (area);return NULL ; }memset (area->pages,0 , array_size);
PATCH 3/39 NLKD - early/late CPU up/down notification
A mechanism to allow debuggers to learn about starting/dying CPUs as early/late as possible. Arch-dependent changes for i386 and x86_64 will follow.
(actual patch attached)
A mechanism to allow debuggers to learn about starting/dying CPUs as early/late as possible. Arch-dependent changes for i386 and x86_64 will follow.
include/linux/cpu.h +4 -0
@@ -42,6 +42,10 @@ struct notifier_block;extern int register_cpu_notifier (struct notifier_block *nb);extern void unregister_cpu_notifier (struct notifier_block *nb); +#ifndef MODULE +extern int cpu_notify (unsigned long ); +#endif +int cpu_up (unsigned int cpu);#else
include/linux/notifier.h +2 -0
@@ -65,12 +65,14 @@ extern int notifier_call_chain(struct no#define NETLINK_URELEASE 0x0001/* Unicast netlink socket released */ +#define CPU_ALIVE 0x0001/* current CPU is alive */ #define CPU_ONLINE 0x0002/* CPU (unsigned)v is up */ #define CPU_UP_PREPARE 0x0003/* CPU (unsigned)v coming up */ #define CPU_UP_CANCELED 0x0004/* CPU (unsigned)v NOT coming up */ #define CPU_DOWN_PREPARE 0x0005/* CPU (unsigned)v going down */ #define CPU_DOWN_FAILED 0x0006/* CPU (unsigned)v NOT going down */ #define CPU_DEAD 0x0007/* CPU (unsigned)v dead */ +#define CPU_DYING 0x0008/* current CPU dying */ #endif /* __KERNEL__ */ #endif /* _LINUX_NOTIFIER_H */
kernel/cpu.c +6 -0
@@ -41,6 +41,12 @@ void unregister_cpu_notifier(struct noti }EXPORT_SYMBOL (unregister_cpu_notifier); +int cpu_notify (unsigned long event) +{ +return notifier_call_chain (&cpu_chain, event, + (void *)(long )smp_processor_id ()); +} +#ifdef CONFIG_HOTPLUG_CPU static inline void check_for_tasks (int cpu) {
PATCH 4/39 NLKD/i386 - early/late CPU up/down notification
i386-specific part of the new mechanism to allow debuggers to learn about starting/dying CPUs as early/late as possible.
(actual patch attached)
i386-specific part of the new mechanism to allow debuggers to learn about starting/dying CPUs as early/late as possible.
arch/i386/kernel/smpboot.c +2 -0
@@ -486,6 +486,7 @@ static void __devinit start_secondary(vosmp_callin ();while (!cpu_isset (smp_processor_id (), smp_commenced_mask))rep_nop (); +cpu_notify (CPU_ALIVE );setup_secondary_APIC_clock ();if (nmi_watchdog ==NMI_IO_APIC ) {disable_8259A_irq (0 );
@@ -970,6 +971,7 @@ void cpu_exit_clear(void)int cpu =raw_smp_processor_id ();idle_task_exit (); +cpu_notify (CPU_DYING ); cpucount --;cpu_uninit ();
PATCH 5/39 NLKD/x86-64 - early/late CPU up/down notification
In reply to Jan Beulichx86_64-specific part of the new mechanism to allow debuggers to learn about starting/dying CPUs as early/late as possible.
From: Jan Beulich <[email protected]>
(actual patch attached)
x86_64-specific part of the new mechanism to allow debuggers to learn about starting/dying CPUs as early/late as possible.
From: Jan Beulich <[email protected]>
arch/x86_64/kernel/process.c +1 -0
@@ -164,6 +164,7 @@ DECLARE_PER_CPU(int, cpu_state);static inline void play_dead (void ) {idle_task_exit (); +cpu_notify (CPU_DYING );wbinvd ();mb ();/* Ack it */
arch/x86_64/kernel/smpboot.c +3 -1
@@ -40,7 +40,7 @@#include <linux/config.h> #include <linux/init.h> - +#include <linux/cpu.h> #include <linux/mm.h> #include <linux/kernel_stat.h> #include <linux/smp_lock.h>
@@ -479,6 +479,8 @@ void __cpuinit start_secondary(void)/* otherwise gcc will move up the smp_processor_id before the cpu_init */ barrier (); +cpu_notify (CPU_ALIVE ); +Dprintk ("cpu %d: setting up apic clock\n" ,smp_processor_id ());setup_secondary_APIC_clock ();
Re: [PATCH 5/39] NLKD/x86-64 - early/late CPU up/down notification
Quoted 2 lines · Jan Beulich
x86_64-specific part of the new mechanism to allow debuggers to learn about starting/dying CPUs as early/late as possible.
Please just use the normal notifier chains instead (CPU_UP, CPU_DOWN, register_cpu_notifier). I don't see much sense to have two different mechanisms to do the same thing. While they might be not as early/late as your mechanism I think the users of your debugger can tolerate that.
-Andi
[discuss] Re: [PATCH 5/39] NLKD/x86-64 - early/late CPU up/down notification
Quoted 3 lines
Quoted 1 line
Quoted 1 line
Andi Kleen <[email protected]> 10.11.05 14:10:16 >>>
Quoted 1 line · Jan Beulich
x86_64-specific part of the new mechanism to allow debuggers to
learn
Quoted 6 lines
Quoted 1 line
about starting/dying CPUs as early/late as possible.
Please just use the normal notifier chains instead (
CPU_UP,CPU_DOWN,
register_cpu_notifier). I don't see much sense to have two different mechanisms to do the same thing. While they might be not as
early/late
Quoted 1 line
as your mechanism I think the users of your debugger can tolerate
that.
Assuming you mean CPU_ONLINE and CPU_DEAD. But no, I don't really like this. The most significant difference is that the existing notifications are not sent on the starting CPU, but on the one it got started from. The point in time is only the second reason for not using these.
Jan
Re: [discuss] Re: [PATCH 5/39] NLKD/x86-64 - early/late CPU up/down notification
Quoted 1 line · Jan Beulich
Assuming you mean
CPU_ONLINEandCPU_DEAD.
Yes
Quoted 4 lines
But no, I don't really like
this. The most significant difference is that the existing notifications are not sent on the starting CPU, but on the one it got started from. The point in time is only the second reason for not using these.
Ok, I can see your point. Let's say a new notifier for that would be ok if you can find at least one other existing in tree user and convert it to it. Does that sound fair?
Note I'm about to remove the IO apic watchdog setup, so that one doesn't count.
-Andi
PATCH 6/39 NLKD - early panic notification
In reply to Jan BeulichA mechanism to allow debuggers to intercept panic events early.
(actual patch attached)
A mechanism to allow debuggers to intercept panic events early.
include/linux/kernel.h +1 -0
@@ -86,6 +86,7 @@ extern int cond_resched(void); })extern struct notifier_block *panic_notifier_list; +extern struct notifier_block *prepanic_notifier_list;extern long (*panic_blink)(long time); NORET_TYPE void panic(const char * fmt, ...) __attribute__ ((NORET_AND format (printf, 1, 2)));
kernel/panic.c +3 -0
@@ -27,8 +27,10 @@ int tainted;EXPORT_SYMBOL (panic_timeout);struct notifier_block *panic_notifier_list; +struct notifier_block *prepanic_notifier_list;EXPORT_SYMBOL (panic_notifier_list); +EXPORT_SYMBOL (prepanic_notifier_list);static int __init panic_setup (char *str) {
@@ -76,6 +78,7 @@ NORET_TYPE void panic(const char * fmt,vsnprintf (buf,sizeof (buf), fmt, args);va_end (args);printk (KERN_EMERG "Kernel panic - not syncing: %s\n" ,buf); +notifier_call_chain (&prepanic_notifier_list,0 , buf);bust_spinlocks (0 );/*
PATCH 7/39 NLKD - task create/destroy notification
A mechanism to allow debuggers to learn about starting/dying tasks.
(actual patch attached)
A mechanism to allow debuggers to learn about starting/dying tasks.
include/linux/sched.h +6 -0
@@ -34,6 +34,7 @@#include <linux/percpu.h> #include <linux/topology.h> #include <linux/seccomp.h> +#include <linux/notifier.h> #include <linux/auxvec.h> /* For AT_VECTOR_SIZE */
@@ -1109,6 +1110,11 @@ extern int do_execve(char *, char __userextern long do_fork (unsigned long ,unsigned long ,struct pt_regs *,unsigned long ,int __user *,int __user *);task_t *fork_idle (int ); +#define TASK_NEW 1 +#define TASK_DELETE 2 + +extern struct notifier_block *task_notifier_list; +extern void set_task_comm (struct task_struct *tsk,char *from);extern void get_task_comm (char *to,struct task_struct *tsk);
kernel/fork.c +7 -0
@@ -64,6 +64,9 @@ DEFINE_PER_CPU(unsigned long, process_coEXPORT_SYMBOL (tasklist_lock); +struct notifier_block *task_notifier_list =NULL ; +EXPORT_SYMBOL (task_notifier_list); +int nr_processes (void ) {int cpu;
@@ -108,6 +111,8 @@ EXPORT_SYMBOL(free_task);void __put_task_struct (struct task_struct *tsk) { +notifier_call_chain (&task_notifier_list,TASK_DELETE , tsk); +WARN_ON (!(tsk->exit_state & (EXIT_DEAD |EXIT_ZOMBIE )));WARN_ON (atomic_read (&tsk->usage));WARN_ON (tsk == current);
@@ -1279,6 +1284,8 @@ long do_fork(unsigned long clone_flags,set_tsk_thread_flag (p,TIF_SIGPENDING ); } +notifier_call_chain (&task_notifier_list,TASK_NEW , p); +if (!(clone_flags &CLONE_STOPPED ))wake_up_new_task (p, clone_flags);else
PATCH 8/39 NLKD - rmmod notification
Debugging and maintenance support code occasionally needs to know not only of module insertions, but also module removals.
(actual patch attached)
Debugging and maintenance support code occasionally needs to know not only of module insertions, but also module removals.
kernel/module.c +9 -1
@@ -1169,6 +1169,10 @@ static void cleanup_kallsyms(struct modu/* Free a module, remove from lists, etc (must hold module mutex). */ static void free_module (struct module *mod) { +down (¬ify_mutex); +notifier_call_chain (&module_notify_list,MODULE_STATE_GOING , mod); +up (¬ify_mutex); +/* Delete from various lists */ stop_machine_run (__unlink_module, mod,NR_CPUS );remove_sect_attrs (mod);
@@ -1999,9 +2003,13 @@ sys_init_module(void __user *umod,buggy refcounters. */ mod->state =MODULE_STATE_GOING ;synchronize_sched (); -if (mod->unsafe) +if (mod->unsafe) {printk (KERN_ERR "%s: module is now stuck!\n" , mod->name); +down (¬ify_mutex); +notifier_call_chain (&module_notify_list,MODULE_STATE_GOING , mod); +up (¬ify_mutex); + }else {module_put (mod);down (&module_mutex);
PATCH 9/39 NLKD - hotkey notification
A mechanism to allow debuggers to trigger on a certain hotkey (combination). Derived (generalized) from similar KDB work.
(actual patch attached)
A mechanism to allow debuggers to trigger on a certain hotkey (combination). Derived (generalized) from similar KDB work.
drivers/char/keyboard.c +9 -0
@@ -39,6 +39,7 @@#include <linux/vt_kern.h> #include <linux/sysrq.h> #include <linux/input.h> +#include <linux/kdebug.h> static void kbd_disconnect (struct input_handle *handle);extern void ctrl_alt_del (void );
@@ -153,6 +154,9 @@ static int sysrq_down;#endif static int sysrq_alt; +struct notifier_block *kdebug_chain =NULL ; +EXPORT_SYMBOL (kdebug_chain); +/* * Translation of scancodes to keycodes. We set them on only the first attached * keyboard - for per-keyboard setting, /dev/input/event is more useful.
@@ -1052,6 +1056,11 @@ static void kbd_keycode(unsigned int key rep = (down ==2 ); +if (notify_kdebug (KDEBUG_KEYBOARD , + keycode | ((long )!down << (BITS_PER_LONG -1 )), + regs) ==NOTIFY_STOP ) +return ; +#ifdef CONFIG_MAC_EMUMOUSEBTN if (mac_hid_mouse_emulate_buttons (1 , keycode, down))return ;
include/linux/kdebug.h new file +27 -0
@@ -0,0 +1,27 @@ +#ifndef _KDEBUG_H +#define _KDEBUG_H + +/* +* This notifier is to replace hardcoded entries in e.g. the keyboard +* driver used by kernel debuggers. +*/ +#include <linux/notifier.h> + +struct pt_regs ; + +struct kdebug_args { +struct pt_regs *regs; +long data; +}; + +extern struct notifier_block *kdebug_chain; + +#define KDEBUG_KEYBOARD 1 + +static inline int notify_kdebug (unsigned long event,long data,struct pt_regs *regs) +{ +struct kdebug_args args = { .regs=regs, .data = data }; +return notifier_call_chain (&kdebug_chain, event, &args); +} + +#endif
PATCH 10/39 NLKD - console layout change notification
A mechanism to allow (local) debuggers to learn about changes to the console layout, to adapt their internal state.
(actual patch attached)
A mechanism to allow (local) debuggers to learn about changes to the console layout, to adapt their internal state.
drivers/video/console/fbcon.c +32 -10
@@ -107,7 +107,7 @@ enum { };struct display fb_display[MAX_NR_CONSOLES ]; -static signed char con2fb_map[MAX_NR_CONSOLES ]; +signed char con2fb_map[MAX_NR_CONSOLES ];static signed char con2fb_map_boot[MAX_NR_CONSOLES ];static int logo_height;static int logo_lines;
@@ -211,6 +211,16 @@ static inline int fbcon_is_inactive(stru vc->vc_mode != KD_TEXT || ops->graphics); } +static inline int fbcon_set_par (struct fb_info *info) +{ +if (info->fbops->fb_set_par) { +if (fb_notify_clients (FB_EVENT_PRE_MODE_CHANGE , info, &info->var) ==NOTIFY_BAD ) +return -EINVAL ; + info->fbops->fb_set_par (info); + } +return 0 ; +} +static inline int get_color (struct vc_data *vc,struct fb_info *info,u16 c,int is_fg) {
@@ -623,15 +633,19 @@ static int con2fb_release_oldinfo(structreturn err; } -static void con2fb_init_display (struct vc_data *vc,struct fb_info *info, +static int con2fb_init_display (struct vc_data *vc,struct fb_info *info,int unit,int show_logo) {struct fbcon_ops *ops = info->fbcon_par; ops->currcon = fg_console; -if (info->fbops->fb_set_par && !(ops->flags &FBCON_FLAGS_INIT )) - info->fbops->fb_set_par (info); +if (!(ops->flags &FBCON_FLAGS_INIT )) { +int err =fbcon_set_par (info); + +if (err) +return err; + } ops->flags |=FBCON_FLAGS_INIT ; ops->graphics =0 ;
@@ -652,6 +666,7 @@ static void con2fb_init_display(struct v }update_screen (vc_cons[fg_console].d); +return 0 ; }/**
@@ -708,7 +723,7 @@ static int set_con2fb_map(int unit, intif (!found)fbcon_add_cursor_timer (info); con2fb_map_boot[unit] = newidx; -con2fb_init_display (vc, info, unit, show_logo); + err =con2fb_init_display (vc, info, unit, show_logo); }release_console_sem ();
@@ -980,9 +995,8 @@ static void fbcon_init(struct vc_data *v* We need to do it in fbcon_init() to prevent screen corruption. */ if (CON_IS_VISIBLE (vc)) { -if (info->fbops->fb_set_par && - !(ops->flags &FBCON_FLAGS_INIT )) - info->fbops->fb_set_par (info); +if (!(ops->flags &FBCON_FLAGS_INIT ) &&fbcon_set_par (info) !=0 ) +return ; ops->flags |=FBCON_FLAGS_INIT ; }
@@ -1988,8 +2002,8 @@ static int fbcon_switch(struct vc_data *fb_set_var (info, &var);if (old_info !=NULL && old_info != info) { -if (info->fbops->fb_set_par) - info->fbops->fb_set_par (info); +if (fbcon_set_par (info) !=0 ) +return 0 ;fbcon_del_cursor_timer (old_info);fbcon_add_cursor_timer (info); }
@@ -2848,6 +2862,12 @@ static const struct consw fb_con = { .con_resize = fbcon_resize, }; +int is_fb_con (const struct consw *con) +{ +return con == &fb_con; +} +EXPORT_SYMBOL (is_fb_con); +static struct notifier_block fbcon_event_notifier = { .notifier_call = fbcon_event_notify, };
@@ -2892,4 +2912,6 @@ module_exit(fb_console_exit);#endif +EXPORT_SYMBOL (con2fb_map); +MODULE_LICENSE ("GPL" );
drivers/video/console/fbcon.h +3 -0
@@ -168,4 +168,7 @@ extern void fbcon_set_tileops(struct vc_#endif extern void fbcon_set_bitops (struct fbcon_ops *ops); +extern int is_fb_con (const struct consw *); +extern signed char con2fb_map[]; +#endif /* _VIDEO_FBCON_H */
drivers/video/console/vgacon.c +17 -0
@@ -114,6 +114,8 @@ static int vga_video_font_height;static int vga_scan_lines;static unsigned int vga_rolled_over =0 ; +static struct notifier_block *vga_notifier_list; +static int __init no_scroll (char *str) {/*
@@ -962,6 +964,9 @@ static int vgacon_adjust_height(struct voutb_p (fsr, vga_video_port_val);outb_p (0x12 , vga_video_port_reg);/* Vertical display limit */ outb_p (vde, vga_video_port_val); +notifier_call_chain (&vga_notifier_list, +VGACON_EVENT_PRE_ADJUST_HEIGHT | (vga_font_is_default ?VGACON_MC_DEFAULT_FONT :0 ), + (void *)(long )rows);spin_unlock_irq (&vga_lock);for (i =0 ; i <MAX_NR_CONSOLES ; i++) {
@@ -1185,4 +1190,16 @@ const struct consw vga_con = { .con_invert_region = vgacon_invert_region, }; +int vgacon_register_client (struct notifier_block *nb) +{ +return notifier_chain_register (&vga_notifier_list, nb); +} +EXPORT_SYMBOL (vgacon_register_client); + +int vgacon_unregister_client (struct notifier_block *nb) +{ +return notifier_chain_unregister (&vga_notifier_list, nb); +} +EXPORT_SYMBOL (vgacon_unregister_client); +MODULE_LICENSE ("GPL" );
drivers/video/fbmem.c +25 -1
@@ -673,8 +673,17 @@ fb_set_var(struct fb_info *info, structif ((var->activate &FB_ACTIVATE_MASK ) ==FB_ACTIVATE_NOW ) {struct fb_videomode mode; +struct fb_event event;int err =0 ; + event.info = info; + event.data = var; +if (notifier_call_chain (&fb_notifier_list, +FB_EVENT_PRE_MODE_CHANGE , + &event) ==NOTIFY_BAD ) +return -EINVAL ; + + info->var = *var;if (info->fbops->fb_set_par) info->fbops->fb_set_par (info);
@@ -690,7 +699,6 @@ fb_set_var(struct fb_info *info, struct err =fb_add_videomode (&mode, &info->modelist);if (!err && (flags &FBINFO_MISC_USEREVENT )) { -struct fb_event event;int evnt = (var->activate &FB_ACTIVATE_ALL ) ?FB_EVENT_MODE_CHANGE_ALL :FB_EVENT_MODE_CHANGE ;
@@ -1117,6 +1125,21 @@ int fb_unregister_client(struct notifier }/** +* fb_notify_clients - notify all clients +* @what: event type +* @info: framebuffer affected +* @data: event specific data +*/ +int fb_notify_clients (unsigned long what,struct fb_info *info,void *data) +{ +struct fb_event event; + + event.info = info; + event.data = data; +return notifier_call_chain (&fb_notifier_list, what, &event); +} + +/** * fb_set_suspend - low level driver signals suspend * @info: framebuffer affected * @state: 0 = resuming, !=0 = suspending
@@ -1321,6 +1344,7 @@ EXPORT_SYMBOL(fb_get_buffer_offset);EXPORT_SYMBOL (fb_set_suspend);EXPORT_SYMBOL (fb_register_client);EXPORT_SYMBOL (fb_unregister_client); +EXPORT_SYMBOL (fb_notify_clients);EXPORT_SYMBOL (fb_get_options);EXPORT_SYMBOL (fb_new_modelist);
include/linux/fb.h +3 -0
@@ -475,6 +475,8 @@ struct fb_cursor_user {* Register/unregister for framebuffer events */ +/* The resolution of the passed in fb_info is about to change */ +#define FB_EVENT_PRE_MODE_CHANGE 0x00/* The resolution of the passed in fb_info about to change */ #define FB_EVENT_MODE_CHANGE 0x01/* The display on this fb_info is beeing suspended, no access to the
@@ -509,6 +511,7 @@ struct fb_event {extern int fb_register_client (struct notifier_block *nb);extern int fb_unregister_client (struct notifier_block *nb); +extern int fb_notify_clients (unsigned long ,struct fb_info *,void *);/* * Pixmap structure definition
include/video/vga.h +9 -0
@@ -19,6 +19,7 @@#include <linux/config.h> #include <linux/types.h> +#include <linux/notifier.h> #include <asm/io.h> #ifndef CONFIG_AMIGA #include <asm/vga.h>
@@ -479,4 +480,12 @@ static inline void vga_mm_wattr (void __ vga_mm_w (regbase, VGA_ATT_W, val); } +#define VGACON_EVENT_PRE_ADJUST_HEIGHT 0x01 + +#define VGACON_EVENT_FLAGS_MASK 0xff000000 +#define VGACON_MC_DEFAULT_FONT 0x80000000 + +int vgacon_register_client (struct notifier_block *); +int vgacon_unregister_client (struct notifier_block *); +#endif /* __linux_video_vga_h__ */
PATCH 11/39 NLKD - time adjustment
Generic part of an interface to allow debuggers to update time after having halted the system for perhaps extended periods of time. This generally requires arch-dependent changes, too, unless the arch- dependent time handling is already overflow-safe.
(actual patch attached)
Generic part of an interface to allow debuggers to update time after having halted the system for perhaps extended periods of time. This generally requires arch-dependent changes, too, unless the arch- dependent time handling is already overflow-safe.
include/linux/jiffies.h +5 -0
@@ -83,6 +83,11 @@*/ extern u64 __jiffy_data jiffies_64;extern unsigned long volatile __jiffy_data jiffies; +#ifndef CONFIG_DEBUG_KERNEL +# define debugger_jiffies 0 +#else +extern u64 debugger_jiffies; +#endif #if (BITS_PER_LONG <64 )u64 get_jiffies_64 (void );
kernel/timer.c +26 -0
@@ -46,6 +46,10 @@ static void time_interpolator_update(lon#define time_interpolator_update (x)#endif +#ifdef CONFIG_DEBUG_KERNEL +u64 debugger_jiffies; +#endif +/* * per-CPU timer vector definitions: */
@@ -935,6 +939,28 @@ static inline void update_times(void) ticks = jiffies - wall_jiffies;if (ticks) { wall_jiffies += ticks; +#ifndef debugger_jiffies +if (ticks >1 + && debugger_jiffies + && jiffies_64 - debugger_jiffies >1 ) { +u64 nsec64 = (u64)(ticks -1 ) * tick_nsec; +unsigned long nsec =do_div (nsec64,NSEC_PER_SEC ); +unsigned long sec = nsec64; + +if (sec >0 + && xtime.tv_nsec + nsec + tick_nsec <NSEC_PER_SEC ) { +/* Make sure xtime.tv_nsec exceeds a second when +checked (in update_wall_time). */ + sec--; + nsec +=NSEC_PER_SEC ; + } + xtime.tv_sec += sec; + xtime.tv_nsec += nsec; +touch_softlockup_watchdog (); + ticks =1 ; + } + debugger_jiffies =0 ; +#endif update_wall_time (ticks); }calc_load (ticks);
PATCH 12/39 NLKD/i386 - time adjustment
Since i386 time handling is not overflow-safe, these are the adjustments needed for allowing debuggers to update time after having halted the system for perhaps extended periods of time.
(actual patch attached)
Since i386 time handling is not overflow-safe, these are the adjustments needed for allowing debuggers to update time after having halted the system for perhaps extended periods of time.
arch/i386/kernel/timers/common.c +3 -1
@@ -149,7 +149,7 @@ unsigned long read_timer_tsc(void)/* calculate cpu_khz */ -void init_cpu_khz (void ) +unsigned long init_cpu_khz (void ) {if (cpu_has_tsc) {unsigned long tsc_quotient =calibrate_tsc ();
@@ -166,7 +166,9 @@ void init_cpu_khz(void)printk ("Detected %u.%03u MHz processor.\n" , cpu_khz /1000 , cpu_khz %1000 ); } +return tsc_quotient; } } +return 0 ; }
arch/i386/kernel/timers/timer_hpet.c +25 -5
@@ -99,7 +99,7 @@ static unsigned long get_offset_hpet(voistatic void mark_offset_hpet (void ) {unsigned long long this_offset, last_offset; -unsigned long offset; +unsigned long offset, lost_ticks =0 ;write_seqlock (&monotonic_lock); last_offset = ((unsigned long long )last_tsc_high<<32 )|last_tsc_low;
@@ -109,14 +109,34 @@ static void mark_offset_hpet(void) offset =hpet_readl (HPET_T0_CMP ) - hpet_tick; else offset =hpet_readl (HPET_COUNTER ); -if (unlikely (((offset - hpet_last) >= (2 *hpet_tick)) && (hpet_last !=0 ))) { -int lost_ticks = ((offset - hpet_last) / hpet_tick) -1 ; - jiffies_64 += lost_ticks; + this_offset = ((unsigned long long )last_tsc_high<<32 )|last_tsc_low; +if (unlikely (debugger_jiffies)) { +unsigned long long delta = this_offset - last_offset; +unsigned long lo, hi, lo1; + +#ifndef CONFIG_SMP +/* When the TSC gets reset during AP startup, the code below would +incorrectly think we lost a huge amount of ticks. */ +if (unlikely ((long long )delta <0 )) + delta = this_offset; +#endif +ASM_MUL64_REG (hi/* dummy */ , lo1, tsc_hpet_quotient, (unsigned long )delta); +ASM_MUL64_REG (lo, hi, tsc_hpet_quotient, (unsigned long )(delta >>32 )); + __asm__("addl %3, %1\n\t" +"adcl $0, %2" + :"=A" (delta) + :"a" (lo),"d" (hi),"rm" (lo1) + :"flags" ); +do_div (delta, hpet_tick); + lost_ticks = delta; } +else if (unlikely (((offset - hpet_last) >= (2 *hpet_tick)) && (hpet_last !=0 ))) + lost_ticks = ((offset - hpet_last) / hpet_tick); +if (lost_ticks) + jiffies_64 += lost_ticks -1 ; hpet_last = offset;/* update the monotonic base value */ - this_offset = ((unsigned long long )last_tsc_high<<32 )|last_tsc_low; monotonic_base +=cycles_2_ns (this_offset - last_offset);write_sequnlock (&monotonic_lock); }
arch/i386/kernel/timers/timer_pm.c +59 -8
98 lines not on this page · raw message
arch/i386/kernel/timers/timer_tsc.c +71 -15
150 lines not on this page · raw message
include/asm-i386/timer.h +1 -1
@@ -57,7 +57,7 @@ extern struct init_timer_opts timer_cyclextern unsigned long calibrate_tsc (void );extern unsigned long read_timer_tsc (void ); -extern void init_cpu_khz (void ); +extern unsigned long init_cpu_khz (void );extern int recalibrate_cpu_khz (void );#ifdef CONFIG_HPET_TIMER extern struct init_timer_opts timer_hpet_init;
Re: [PATCH 12/39] NLKD/i386 - time adjustment
Quoted 7 lines · Jan Beulich
Since i386 time handling is not overflow-safe, these are the adjustments needed for allowing debuggers to update time after having halted the system for perhaps extended periods of time.
Signed-off-by Jan Beulich <[email protected]>(actual patch attached)
The patch includes code that seems to imply that gcc can not do mpy of (long long) variables. It does just fine with these. It also adds (long long) types just fine. The only problem it has is with div, for which we have do_div().
I really do not see the relavence of the run time library patches given the above. The adjust code does not seem to use them. Also, gcc (with the lib code) does all of this stuff. The only need for it would, possibly, be to debug the library code and even then, I suspect you really want to do that in user land and then bring the result into the kernel.
Am I missing something?
Quoted 1 line
Signature · 2 lines
George Anzinger [email protected] HRT (High-res-timers): http://sourceforge.net/projects/high-res-timers/
Re: [PATCH 12/39] NLKD/i386 - time adjustment
Quoted 11 lines
Quoted 1 line
Quoted 1 line
George Anzinger <[email protected]> 09.11.05 20:10:09 >>>
Quoted 7 lines · Jan Beulich
Since i386 time handling is not overflow-safe, these are the adjustments needed for allowing debuggers to update time after having halted the system for perhaps extended periods of time.
Signed-off-by Jan Beulich <[email protected]>(actual patch attached)
The patch includes code that seems to imply that gcc can not do mpy of
(long long) variables. It
Quoted 1 line
does just fine with these. It also adds (long long) types just fine.
The only problem it has is
Quoted 1 line
with div, for which we have
do_div().
gcc can do long long multiplies fine, but only with a long long result. The code presented, however, needs (at least) 96 bits of the result, which expressing in C would be far more complicated than doing it with a couple of assembly statements.
Quoted 1 line
I really do not see the relavence of the run time library patches
given the above. The adjust code
Quoted 1 line
does not seem to use them. Also, gcc (with the lib code) does all of
this stuff. The only need for
Quoted 1 line
it would, possibly, be to debug the library code and even then, I
suspect you really want to do that
Quoted 1 line
in user land and then bring the result into the kernel.
Which run time library patches are you referring to? NLKD's? If so, these routines must not be used by code outside of the debugger (and the opposite is true, too: debugger code must not use common code routines where ever possible).
Further, it is my understanding that it is for a (unknown to me) reason that the linux kernel doesn't have the full set of libgcc support routines. Since the debugger in various places relies on being able to do 64-bit math on 32-bit systems, I had to add these in a way so that they'd be hidden from the rest of the kernel (and also so that they'd satisfy the isolation rules outlined above).
Jan
Re: [PATCH 12/39] NLKD/i386 - time adjustment
Jan Beulich wrote:
~
Quoted 6 lines
gcc can do long long multiplies fine, but only with a long long result. The code presented, however, needs (at least) 96 bits of the result, which expressing in C would be far more complicated than doing it with a couple of assembly statements.
Well, if you need that many bits... guess I would need to study the code (hard with binary attachments) to understand why you need so many bits.
Quoted 3 lines
Quoted 2 lines
I really do not see the relavence of the run time library patches
~
Quoted 5 lines
Which run time library patches are you referring to? NLKD's? If so, these routines must not be used by code outside of the debugger (and the opposite is true, too: debugger code must not use common code routines where ever possible).
Just what is your argument here? As I understand it this is only a problem (i.e. sharing the code) if you are trying to single step or set breakpoints in the library code.
Quoted 7 lines
Further, it is my understanding that it is for a (unknown to me) reason that the linux kernel doesn't have the full set of libgcc support routines. Since the debugger in various places relies on being able to do 64-bit math on 32-bit systems, I had to add these in a way so that they'd be hidden from the rest of the kernel (and also so that they'd satisfy the isolation rules outlined above).
Well, the powers that be, decided that the kernel did not need the "missing" routines and that they just added bloat. One then wonders why a debugger needs them. Could you enlighten us on this?
Signature · 2 lines
George Anzinger [email protected] HRT (High-res-timers): http://sourceforge.net/projects/high-res-timers/
PATCH 13/39 NLKD/x86-64 - time adjustment
In reply to Jan BeulichSince x86-64 time handling is not overflow-safe, these are the adjustments needed for allowing debuggers to update time after having halted the system for perhaps extended periods of time.
Note that this depends on the HPET definitions adjustments, which aren't in 2.6.14, but have supposedly been merged already into 2.6.15.
From: Jan Beulich <[email protected]>
(actual patch attached)
Since x86-64 time handling is not overflow-safe, these are the adjustments needed for allowing debuggers to update time after having halted the system for perhaps extended periods of time.
Note that this depends on the HPET definitions adjustments, which aren't in 2.6.14, but have supposedly been merged already into 2.6.15.
From: Jan Beulich <[email protected]>
arch/x86_64/kernel/pmtimer.c +40 -9
@@ -52,22 +52,53 @@ int pmtimer_mark_offset(void) {static int first_run =1 ;unsigned long tsc; -u32 lost; - +u32 lost, delta;u32 tick =inl (pmtmr_ioport); -u32 delta; +#ifdef debugger_jiffies +# define delta64 delta +#else +u64 delta64; +#endif + +rdtscll (tsc); - delta =cyc2us ((tick - last_pmtmr_tick) &ACPI_PM_MASK ); +if (likely (!debugger_jiffies)) { + delta =cyc2us ((tick - last_pmtmr_tick) &ACPI_PM_MASK ); +#ifndef delta64 + delta64 = delta; + } +else { +# ifdef CONFIG_SMP +/* When the TSC gets reset during AP startup, the code below would +incorrectly think we lost a huge amount of ticks. */ +if (unlikely ((long long )(tsc - vxtime.last_tsc) <0 )) + delta64 = tsc; + else +# endif + delta64 = tsc - vxtime.last_tsc; + __asm__("mulq %1\n\t" +"shrdq $32, %%rdx, %0" + :"+a" (delta64) + :"rm" (vxtime.tsc_quot) + :"rdx" ); + delta = (u32 )delta64 ? (u32 )delta64 -1 : (offset_delay =0 ); +#endif + } last_pmtmr_tick = tick; monotonic_base += delta *NSEC_PER_USEC ; - delta += offset_delay; - - lost = delta / (USEC_PER_SEC /HZ ); - offset_delay = delta % (USEC_PER_SEC /HZ ); +if (likely (delta == delta64)) { + delta += offset_delay; + lost = delta / (USEC_PER_SEC /HZ ); + offset_delay = delta % (USEC_PER_SEC /HZ ); + } +else { + lost = (u32)(delta64 / (USEC_PER_SEC /HZ )); + offset_delay =0 ; + } +#undef delta64 -rdtscll (tsc); vxtime.last_tsc = tsc - offset_delay * cpu_khz;/* don't calculate delay for first run,
arch/x86_64/kernel/time.c +210 -42
372 lines not on this page · raw message
include/asm-x86_64/vsyscall.h +6 -1
@@ -29,7 +29,10 @@ enum vsyscall_num {struct vxtime_data {long hpet_address;/* HPET base address */ -int last; +union { +int last; +long last64; + };unsigned long last_tsc;long quot;long tsc_quot;
@@ -37,7 +40,9 @@ struct vxtime_data { };#define hpet_readl (a) readl((void *)fix_to_virt(FIX_HPET_BASE) + a) +#define hpet_readq (a) readq((void *)fix_to_virt(FIX_HPET_BASE) + a)#define hpet_writel (d,a) writel(d, (void *)fix_to_virt(FIX_HPET_BASE) + a) +#define hpet_writeq (d,a) writeq(d, (void *)fix_to_virt(FIX_HPET_BASE) + a)/* vsyscall space (readonly) */ extern struct vxtime_data __vxtime;
PATCH 18/39 NLKD/x86-64 - INT1/INT3 handling changes
This
- switches the INT3 handler to run on an IST stack (to cope with breakpoints set by a kernel debugger on places where the kernel's %gs base hasn't been set up, yet); the IST stack used is shared with the INT1 handler's
- allows nesting of INT1/INT3 handlers so that one can, with a kernel debugger, debug (at least) the user-mode portions of the INT1/INT3 handling; the nesting isn't actively enabled here since a kernel- debugger-free kernel doesn't need it
From: Jan Beulich <[email protected]>
(actual patch attached)
This
- switches the INT3 handler to run on an IST stack (to cope with breakpoints set by a kernel debugger on places where the kernel's %gs base hasn't been set up, yet); the IST stack used is shared with the INT1 handler's
- allows nesting of INT1/INT3 handlers so that one can, with a kernel debugger, debug (at least) the user-mode portions of the INT1/INT3 handling; the nesting isn't actively enabled here since a kernel- debugger-free kernel doesn't need it
From: Jan Beulich <[email protected]>
arch/x86_64/kernel/asm-offsets.c +5 -0
@@ -64,5 +64,10 @@ int main(void)DEFINE (pbe_address, offsetof(struct pbe , address));DEFINE (pbe_orig_address, offsetof(struct pbe , orig_address));DEFINE (pbe_next, offsetof(struct pbe , next)); +BLANK (); +DEFINE (EXCEPTION_STACK_SIZE ,EXCEPTION_STKSZ ); +#if DEBUG_STKSZ >EXCEPTION_STKSZ +DEFINE (DEBUG_IST ,DEBUG_STACK ); +#endif return 0 ; }
arch/x86_64/kernel/entry.S +22 -4
@@ -685,7 +685,10 @@ END(spurious_interrupt) /* error code is on the stack already */ /* handle NMI like exceptions that can happen everywhere */ - .macro paranoidentry sym +#ifndef DEBUG_IST +# define DEBUG_IST 0 +#endif + .macro paranoidentry sym, ist=0 SAVE_ALL cld movl $1,%ebx
@@ -695,10 +698,20 @@ END(spurious_interrupt) js 1f swapgs xorl %ebx,%ebx -1: movq %rsp,%rdi +1: + .if \ist + movq %gs:pda_data_offset, %rbp + .endif + movq %rsp,%rdi movq ORIG_RAX(%rsp),%rsi movq $-1,ORIG_RAX(%rsp) + .if \ist + subq $EXCEPTION_STACK_SIZE, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp) + .endif call \sym + .if \ist + addq $EXCEPTION_STACK_SIZE, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp) + .endif cli .endm
@@ -924,7 +937,7 @@ KPROBE_ENTRY(debug) INTR_FRAME pushq $0 CFI_ADJUST_CFA_OFFSET 8 - paranoidentry do_debug + paranoidentry do_debug, DEBUG_IST jmp paranoid_exit CFI_ENDPROC END(debug)
@@ -981,7 +994,12 @@ paranoid_schedule: END(nmi) KPROBE_ENTRY(int3) - zeroentry do_int3 + INTR_FRAME + pushq $0 + CFI_ADJUST_CFA_OFFSET 8 + paranoidentry do_int3, DEBUG_IST + jmp paranoid_exit + CFI_ENDPROC END(int3) .previous .text
arch/x86_64/kernel/setup64.c +18 -4
@@ -146,7 +146,7 @@ void pda_init(int cpu) pda->irqstackptr +=IRQSTACKSIZE -64 ; } -char boot_exception_stacks[N_EXCEPTION_STACKS * EXCEPTION_STKSZ] +char boot_exception_stacks[(N_EXCEPTION_STACKS - 2) * EXCEPTION_STKSZ + DEBUG_STKSZ] __attribute__((section(".bss.page_aligned")));/* May not be marked __init: used by software suspend */
@@ -243,13 +243,27 @@ void __cpuinit cpu_init (void)*/ for (v =0 ; v <N_EXCEPTION_STACKS ; v++) {if (cpu) { - estacks = (char *)__get_free_pages (GFP_ATOMIC , -EXCEPTION_STACK_ORDER ); +static const unsigned int order[N_EXCEPTION_STACKS ] = { + [0 ...N_EXCEPTION_STACKS -1 ] =EXCEPTION_STACK_ORDER , + [DEBUG_STACK -1 ] =DEBUG_STACK_ORDER + }; + + estacks = (char *)__get_free_pages (GFP_ATOMIC , order[v]);if (!estacks)panic ("Cannot allocate exception stack %ld %d\n" , v, cpu); } - estacks +=EXCEPTION_STKSZ ; +switch (v +1 ) { +#if DEBUG_STKSZ >EXCEPTION_STKSZ +case DEBUG_STACK : + cpu_pda[cpu].debugstack = (unsigned long )estacks; + estacks +=DEBUG_STKSZ ; +break ; +#endif +default : + estacks +=EXCEPTION_STKSZ ; +break ; + } t->ist[v] = (unsigned long )estacks; }
arch/x86_64/kernel/traps.c +32 -3
@@ -121,19 +121,31 @@ int printk_address(unsigned long addressstatic unsigned long *in_exception_stack (unsigned cpu,unsigned long stack,unsigned *usedp,const char **idp) { -static const char ids[N_EXCEPTION_STACKS ][8 ] = { +static char ids[][8 ] = { [DEBUG_STACK -1 ] ="#DB" , [NMI_STACK -1 ] ="NMI" , [DOUBLEFAULT_STACK -1 ] ="#DF" , [STACKFAULT_STACK -1 ] ="#SS" , [MCE_STACK -1 ] ="#MC" , +#if DEBUG_STKSZ > EXCEPTION_STKSZ + [N_EXCEPTION_STACKS ... N_EXCEPTION_STACKS + DEBUG_STKSZ / EXCEPTION_STKSZ - 2] = "#DB[?]" +#endif };unsigned k;for (k =0 ; k <N_EXCEPTION_STACKS ; k++) {unsigned long end; - end =per_cpu (init_tss, cpu).ist[k]; +switch (k +1 ) { +#if DEBUG_STKSZ >EXCEPTION_STKSZ +case DEBUG_STACK : + end = cpu_pda[cpu].debugstack +DEBUG_STKSZ ; +break ; +#endif +default : + end =per_cpu (init_tss, cpu).ist[k]; +break ; + }if (stack >= end)continue ;if (stack >= end -EXCEPTION_STKSZ ) {
@@ -143,6 +155,22 @@ static unsigned long *in_exception_stack *idp = ids[k];return (unsigned long *)end; } +#if DEBUG_STKSZ >EXCEPTION_STKSZ +if (k ==DEBUG_STACK -1 && stack >= end -DEBUG_STKSZ ) { +unsigned j =N_EXCEPTION_STACKS -1 ; + +do { + ++j; + end -=EXCEPTION_STKSZ ; + ids[j][4 ] ='1' + (j -N_EXCEPTION_STACKS ); + }while (stack < end -EXCEPTION_STKSZ ); +if (*usedp & (1U << j)) +break ; + *usedp |=1U << j; + *idp = ids[j]; +return (unsigned long *)end; + } +#endif }return NULL ; }
@@ -652,6 +680,7 @@ asmlinkage void default_do_nmi(struct ptio_check_error (reason, regs); } +/* runs on IST stack. */ asmlinkage void __kprobes do_int3(struct pt_regs * regs, long error_code) {if (notify_die (DIE_INT3 ,"int3" , regs, error_code,3 ,SIGTRAP ) ==NOTIFY_STOP ) {
@@ -942,7 +971,7 @@ void __init trap_init(void)set_intr_gate (0 ,÷_error);set_intr_gate_ist (1 ,&debug,DEBUG_STACK );set_intr_gate_ist (2 ,&nmi,NMI_STACK ); -set_system_gate (3 ,&int3); +set_system_gate_ist (3 ,&int3,DEBUG_STACK );/* int3 can be called from all */ set_system_gate (4 ,&overflow);/* int4 can be called from all */ set_intr_gate (5 ,&bounds);set_intr_gate (6 ,&invalid_op);
include/asm-x86_64/desc.h +5 -0
@@ -111,6 +111,11 @@ static inline void set_system_gate(int n_set_gate (&idt_table[nr],GATE_INTERRUPT , (unsigned long ) func,3 ,0 ); } +static inline void set_system_gate_ist (int nr,void *func,unsigned ist) +{ +_set_gate (&idt_table[nr],GATE_INTERRUPT , (unsigned long ) func,3 , ist); +} +static inline void set_tssldt_descriptor (void *ptr,unsigned long tss,unsigned type,unsigned size) {
include/asm-x86_64/pda.h +4 -0
@@ -12,6 +12,10 @@ struct x8664_pda {unsigned long data_offset;/* Per cpu data offset from linker address */ unsigned long kernelstack;/* top of kernel stack for current */ unsigned long oldrsp;/* user rsp for system call */ +#ifdef CONFIG_NLKD /* Better would be DEBUG_STKSZ > EXCEPTION_STKSZ, but +this file can't include processor.h. */ +unsigned long debugstack;/* #DB/#BP stack. */ +#endif int irqcount;/* Irq nesting counter. Starts with -1 */ int cpunumber;/* Logical CPU number */ char *irqstackptr;/* top of irqstack */
include/asm-x86_64/processor.h +3 -1
@@ -271,8 +271,10 @@ struct thread_struct {#define DEBUG_STACK 4#define MCE_STACK 5#define N_EXCEPTION_STACKS 5/* hw limit: 7 */ -#define EXCEPTION_STKSZ (PAGE_SIZE << EXCEPTION_STACK_ORDER)#define EXCEPTION_STACK_ORDER 0 +#define EXCEPTION_STKSZ (PAGE_SIZE << EXCEPTION_STACK_ORDER) +#define DEBUG_STACK_ORDER EXCEPTION_STACK_ORDER +#define DEBUG_STKSZ (PAGE_SIZE << DEBUG_STACK_ORDER)#define start_thread (regs,new_rip,new_rsp) do { \ asm volatile("movl %0,%%fs; movl %0,%%es; movl %0,%%ds": :"r" (0)); \
PATCH 19/39 NLKD/x86-64 - stack-pointer-invalid markers
This adds static information about the code regions where the stack pointer cannot be relied upon. Kernel debuggers may then use this information to determine which stack to switch to when having a need to switch off of namely the NMI stack.
From: Jan Beulich <[email protected]>
(actual patch attached)
This adds static information about the code regions where the stack pointer cannot be relied upon. Kernel debuggers may then use this information to determine which stack to switch to when having a need to switch off of namely the NMI stack.
From: Jan Beulich <[email protected]>
arch/x86_64/ia32/ia32entry.S +4 -0
@@ -60,6 +60,7 @@ ENTRY(ia32_sysenter_target) CFI_REGISTER rsp,rbp swapgs movq %gs:pda_kernelstack, %rsp +0: STACK_INVALID ia32_sysenter_target, 0b addq $(PDA_STACKOFFSET),%rsp sti movl %ebp,%ebp /* zero extension */
@@ -169,6 +170,7 @@ ENTRY(ia32_cstar_target) movl %esp,%r8d CFI_REGISTER rsp,r8 movq %gs:pda_kernelstack,%rsp +0: STACK_INVALID ia32_cstar_target, 0b sti SAVE_ARGS 8,1,1 movl %eax,%eax /* zero extension */
@@ -211,8 +213,10 @@ cstar_do_call: /*CFI_REGISTER rflags,r11*/ movl RSP-ARGOFFSET(%rsp),%esp CFI_RESTORE rsp +0: STACK_INVALID 0b, 1f swapgs sysretl +1: cstar_tracesys: CFI_RESTORE_STATE
arch/x86_64/kernel/entry.S +3 -0
@@ -190,6 +190,7 @@ ENTRY(system_call) swapgs movq %rsp,%gs:pda_oldrsp movq %gs:pda_kernelstack,%rsp +0: STACK_INVALID system_call, 0b sti SAVE_ARGS 8,1 movq %rax,ORIG_RAX-ARGOFFSET(%rsp)
@@ -224,8 +225,10 @@ sysret_check: RESTORE_ARGS 0,-ARG_SKIP,1 /*CFI_REGISTER rflags,r11*/ movq %gs:pda_oldrsp,%rsp +0: STACK_INVALID 0b, 1f swapgs sysretq +1: /* Handle reschedules */ /* edx: work, edi: workmask */
arch/x86_64/kernel/vmlinux.lds.S +7 -0
@@ -30,6 +30,13 @@ SECTIONS _etext = .; /* End of text section */ +#ifdef CONFIG_NLKD + . = ALIGN(8); /* RSP invalid table */ + __start___stack_invalid = .; + __stack_invalid : AT(ADDR(__stack_invalid) - LOAD_OFFSET) { *(__stack_invalid) } + __stop___stack_invalid = .; +#endif + . = ALIGN(16); /* Exception table */ __start___ex_table = .; __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { *(__ex_table) }
include/asm-x86_64/calling.h +11 -0
@@ -158,6 +158,17 @@ RESTORE_ARGS 0,\addskip .endm +#ifndef MODULE + .macro STACK_INVALID from, to +# ifdef CONFIG_NLKD + .section __stack_invalid, "a", @progbits + .align 8 + .quad \from, \to + .previous +# endif + .endm +#endif + .macro icebp .byte 0xf1 .endm
PATCH 20/39 NLKD/x86-64 - switch_to() floating point adjustment
Touching of the floating point state in a kernel debugger must be NMI-safe, specifically math_state_restore() must be able to deal with being called out of an NMI context. In order to do that reliably, the context switch code must take care to not leave a window open where the current task's TS_USEDFPU flag and CR0.TS could get out of sync.
From: Jan Beulich <[email protected]>
(actual patch attached)
Touching of the floating point state in a kernel debugger must be NMI-safe, specifically math_state_restore() must be able to deal with being called out of an NMI context. In order to do that reliably, the context switch code must take care to not leave a window open where the current task's TS_USEDFPU flag and CR0.TS could get out of sync.
From: Jan Beulich <[email protected]>
arch/x86_64/kernel/process.c +5 -2
@@ -505,6 +505,10 @@ struct task_struct *__switch_to(struct tint cpu =smp_processor_id ();struct tss_struct *tss = &per_cpu (init_tss, cpu); +/* This must be done prior to examining TS_USEDFPU in the outgoing +task (and perhaps setting CR0.TS), so that math_state_restore() +will set TS_USEDFPU in the correct (new) task afterwards. */ +write_pda (pcurrent, next_p);unlazy_fpu (prev_p);/*
@@ -564,11 +568,10 @@ struct task_struct *__switch_to(struct t }/* -* Switch the PDA context. +* Switch the remaining PDA context. */ prev->userrsp =read_pda (oldrsp);write_pda (oldrsp, next->userrsp); -write_pda (pcurrent, next_p);write_pda (kernelstack, (unsigned long )next_p->thread_info +THREAD_SIZE -PDA_STACKOFFSET );/*
PATCH 21/39 NLKD/x86-64 - core adjustments
The core x86-64 NLKD adjustments to pre-existing code.
From: Jan Beulich <[email protected]>
(actual patch attached)
The core x86-64 NLKD adjustments to pre-existing code.
From: Jan Beulich <[email protected]>
arch/x86_64/ia32/ptrace32.c +13 -1
@@ -88,22 +88,32 @@ static int putreg32(struct task_struct *return -EIO ; case offsetof(struct user32, u_debugreg[0]): +if (enable_debugreg (child,0 , val) <0 ) +return -EBUSY ; child->thread.debugreg0 = val;break ; case offsetof(struct user32, u_debugreg[1]): +if (enable_debugreg (child,1 , val) <0 ) +return -EBUSY ; child->thread.debugreg1 = val;break ; case offsetof(struct user32, u_debugreg[2]): +if (enable_debugreg (child,2 , val) <0 ) +return -EBUSY ; child->thread.debugreg2 = val;break ; case offsetof(struct user32, u_debugreg[3]): +if (enable_debugreg (child,3 , val) <0 ) +return -EBUSY ; child->thread.debugreg3 = val;break ; case offsetof(struct user32, u_debugreg[6]): +if (enable_debugreg (child,6 , val) <0 ) +return -EBUSY ; child->thread.debugreg6 = val;break ;
@@ -112,8 +122,10 @@ static int putreg32(struct task_struct */* See arch/i386/kernel/ptrace.c for an explanation of * this awkward check.*/ for (i=0 ; i<4 ; i++) -if ((0x5454 >> ((val >> (16 +4 *i)) &0xf )) &1 ) +if ((0x5554 >> ((val >> (16 +4 *i)) &0xf )) &1 )return -EIO ; +if (enable_debugreg (child,7 , val) <0 ) +return -EBUSY ; child->thread.debugreg7 = val;break ;
arch/x86_64/kernel/process.c +15 -1
@@ -50,6 +50,7 @@#include <asm/desc.h> #include <asm/proto.h> #include <asm/ia32.h> +#include <asm/debugreg.h> asmlinkage extern void ret_from_fork(void);
@@ -346,6 +347,10 @@ void exit_thread(void) t->io_bitmap_max =0 ;put_cpu (); } +if (me->thread.debugreg7) { +enable_debugreg (me,7 ,0 ); + me->thread.debugreg7 =0 ; + } }void flush_thread (void )
@@ -363,6 +368,8 @@ void flush_thread(void)if (t->flags & _TIF_ABI_PENDING) t->flags ^= (_TIF_ABI_PENDING | _TIF_IA32); +if (tsk->thread.debugreg7) +enable_debugreg (tsk,7 ,0 ); tsk->thread.debugreg0 =0 ; tsk->thread.debugreg1 =0 ; tsk->thread.debugreg2 =0 ;
@@ -477,6 +484,13 @@ int copy_thread(int nr, unsigned long clif (err) goto out; } + +if (me->thread.debugreg7) { + p->thread.debugreg7 =0 ; +enable_debugreg (p,7 , me->thread.debugreg7); + p->thread.debugreg7 = me->thread.debugreg7; + } + err =0 ; out:if (err && p->thread.io_bitmap_ptr) {
@@ -489,7 +503,7 @@ out:/* * This special macro can be used to load a debugging register */ -#define loaddebug (thread,r) set_debug(thread->debugreg ## r, r) +#define loaddebug (thread,r) set_debugreg(thread->debugreg ## r, r)/* * switch_to(x,y) should switch tasks from x to y.
arch/x86_64/kernel/ptrace.c +31 -7
@@ -433,42 +433,66 @@ asmlinkage long sys_ptrace(long request,/* Disallows to set a breakpoint into the vsyscall */ case offsetof(struct user, u_debugreg[0]):if (data >=TASK_SIZE_OF (child) - dsize)break ; +if (enable_debugreg (child,0 , data) <0 ) { + ret = -EBUSY ; +break ; + } child->thread.debugreg0 = data; ret =0 ;break ; case offsetof(struct user, u_debugreg[1]):if (data >=TASK_SIZE_OF (child) - dsize)break ; +if (enable_debugreg (child,1 , data) <0 ) { + ret = -EBUSY ; +break ; + } child->thread.debugreg1 = data; ret =0 ;break ; case offsetof(struct user, u_debugreg[2]):if (data >=TASK_SIZE_OF (child) - dsize)break ; +if (enable_debugreg (child,2 , data) <0 ) { + ret = -EBUSY ; +break ; + } child->thread.debugreg2 = data; ret =0 ;break ; case offsetof(struct user, u_debugreg[3]):if (data >=TASK_SIZE_OF (child) - dsize)break ; +if (enable_debugreg (child,3 , data) <0 ) { + ret = -EBUSY ; +break ; + } child->thread.debugreg3 = data; ret =0 ;break ; case offsetof(struct user, u_debugreg[6]): -if (data >>32 ) +if (data >>32 )break ; +if (enable_debugreg (child,6 , data) <0 ) { + ret = -EBUSY ; +break ; + } child->thread.debugreg6 = data; ret =0 ;break ; case offsetof(struct user, u_debugreg[7]):/* See arch/i386/kernel/ptrace.c for an explanation of * this awkward check.*/ - data &= ~DR_CONTROL_RESERVED ; -for (i=0 ; i<4 ; i++) -if ((0x5454 >> ((data >> (16 +4 *i)) &0xf )) &1 ) + data &= ~DR_CONTROL_RESERVED ; +for (i=0 ; i<4 ; i++) +if ((0x5554 >> ((data >> (16 +4 *i)) &0xf )) &1 )break ;if (i ==4 ) { +if (enable_debugreg (child,7 , data) <0 ) { + ret = -EBUSY ; +break ; + } child->thread.debugreg7 = data; - ret =0 ; - } -break ; + ret =0 ; + } +break ; }break ; }
arch/x86_64/kernel/setup64.c +7 -6
@@ -25,6 +25,7 @@#include <asm/percpu.h> #include <asm/proto.h> #include <asm/sections.h> +#include <asm/debugreg.h> char x86_boot_params[BOOT_PARAM_SIZE ]__initdata = {0 ,};
@@ -289,12 +290,12 @@ void __cpuinit cpu_init (void)* Clear all 6 debug registers: */ -set_debug (0UL ,0 ); -set_debug (0UL ,1 ); -set_debug (0UL ,2 ); -set_debug (0UL ,3 ); -set_debug (0UL ,6 ); -set_debug (0UL ,7 ); +set_debugreg (0UL ,0 ); +set_debugreg (0UL ,1 ); +set_debugreg (0UL ,2 ); +set_debugreg (0UL ,3 ); +set_debugreg (0UL ,6 ); +set_debugreg (0UL ,7 );fpu_init (); }
arch/x86_64/kernel/signal.c +3 -2
@@ -29,6 +29,7 @@#include <asm/i387.h> #include <asm/proto.h> #include <asm/ia32_unistd.h> +#include <asm/debugreg.h> /* #define DEBUG_SIG 1 */
@@ -439,8 +440,8 @@ int do_signal(struct pt_regs *regs, sigs* have been cleared if the watchpoint triggered * inside the kernel. */ -if (current->thread.debugreg7) -set_debugreg (current->thread.debugreg7,7 ); +if (unlikely (current->thread.debugreg7)) +restore_debugreg ();/* Whee! Actually deliver the signal. */ return handle_signal (signr, &info, &ka, oldset, regs);
arch/x86_64/kernel/suspend.c +1 -0
@@ -13,6 +13,7 @@#include <asm/proto.h> #include <asm/page.h> #include <asm/pgtable.h> +#include <asm/debugreg.h> struct saved_context saved_context;
arch/x86_64/kernel/traps.c +1 -1
@@ -784,7 +784,7 @@ asmlinkage void __kprobes do_debug(struc info.si_addr = (void __user *)regs->rip;force_sig_info (SIGTRAP , &info, tsk); clear_dr7: -set_debugreg (0UL ,7 ); +disable_debugreg (regs,7 );return ; clear_TF_reenable:
arch/x86_64/kernel/vmlinux.lds.S +6 -0
@@ -144,6 +144,12 @@ SECTIONS __setup_start = .; .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) { *(.init.setup) } __setup_end = .; +#ifdef CONFIG_NLKD + . = ALIGN(8); + __start_nlkd_ext = .; + .nlkd.ext : AT(ADDR(.nlkd.ext) - LOAD_OFFSET) { *(.nlkd.ext) } + __stop_nlkd_ext = .; +#endif __initcall_start = .; .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) { *(.initcall1.init)
include/asm-x86_64/debugreg.h +50 -0
54 lines not on this page · raw message
include/asm-x86_64/processor.h +13 -8
@@ -271,9 +271,22 @@ struct thread_struct {#define DEBUG_STACK 4#define MCE_STACK 5#define N_EXCEPTION_STACKS 5/* hw limit: 7 */ + +#ifndef CONFIG_NLKD #define EXCEPTION_STACK_ORDER 0 +#else +#define EXCEPTION_STACK_ORDER 1 +#endif #define EXCEPTION_STKSZ (PAGE_SIZE << EXCEPTION_STACK_ORDER) + +#ifndef CONFIG_NLKD #define DEBUG_STACK_ORDER EXCEPTION_STACK_ORDER +#else +/* debug and breakpoint exceptions may nest 4 levels deep (minimum +requirement is 3 levels if handling exceptions from the debugger +should be possible, else 2 levels) */ +#define DEBUG_STACK_ORDER (EXCEPTION_STACK_ORDER + 2) +#endif #define DEBUG_STKSZ (PAGE_SIZE << DEBUG_STACK_ORDER)#define start_thread (regs,new_rip,new_rsp) do { \
@@ -288,14 +301,6 @@ struct thread_struct {set_fs (USER_DS ); \ }while (0 ) -#define get_debugreg (var, register) \ - __asm__("movq %%db" #register ", %0" \ - :"=r" (var)) -#define set_debugreg(value, register) \ - __asm__("movq %0,%%db" #register \ - : /* no output */ \ - :"r" (value)) - struct task_struct;struct mm_struct ;
include/asm-x86_64/suspend.h +1 -3
@@ -39,9 +39,7 @@ extern unsigned long saved_context_r12,extern unsigned long saved_context_eflags;#define loaddebug (thread,register) \ - __asm__("movq %0,%%db" #register \ - : /* no output */ \ - :"r" ((thread)->debugreg##register)) + set_debugreg((thread)->debugreg##register, register)extern void fix_processor_context (void );
include/asm-x86_64/system.h +0 -6
@@ -70,12 +70,6 @@ extern void load_gs_index(unsigned); ".previous" \ : :"r" (value), "r" (0)) -#define set_debug(value,register) \ - __asm__("movq %0,%%db" #register \ - : /* no output */ \ - :"r" ((unsigned long) value)) - - #ifdef __KERNEL__ struct alt_instr { __u8 *instr; /* original instruction */
Re: [PATCH 20/39] NLKD/x86-64 - switch_to() floating point adjustment
In reply to Jan BeulichQuoted 5 lines · Jan Beulich
Touching of the floating point state in a kernel debugger must be NMI-safe, specifically
math_state_restore()must be able to deal with being called out of an NMI context. In order to do that reliably, the context switch code must take care to not leave a window open where the current task'sTS_USEDFPUflag and CR0.TS could get out of sync.
Didn't we agree earlier on moving unlazy_fpu() down instead?
-Andi
Re: [PATCH 20/39] NLKD/x86-64 - switch_to() floating point adjustment
Quoted 9 lines
Quoted 1 line
Quoted 1 line
Andi Kleen <[email protected]> 10.11.05 14:24:53 >>>
Quoted 5 lines · Jan Beulich
Touching of the floating point state in a kernel debugger must be NMI-safe, specifically
math_state_restore()must be able to deal with being called out of an NMI context. In order to do that reliably, the context switch code must take care to not leave a window open where the current task'sTS_USEDFPUflag and CR0.TS could get out of sync.Didn't we agree earlier on moving
unlazy_fpu()down instead?
I wasn't sure about that, and hence I submitted it the way I had coded it.
Jan
Re: [PATCH 19/39] NLKD/x86-64 - stack-pointer-invalid markers
In reply to Jan BeulichQuoted 4 lines · Jan Beulich
This adds static information about the code regions where the stack pointer cannot be relied upon. Kernel debuggers may then use this information to determine which stack to switch to when having a need to switch off of namely the NMI stack.
Hmm - can't this be expressed in CFI somehow?
-Andi
Re: [PATCH 19/39] NLKD/x86-64 - stack-pointer-invalid markers
Quoted 8 lines
Quoted 1 line
Quoted 1 line
Andi Kleen <[email protected]> 10.11.05 14:23:55 >>>
Quoted 4 lines · Jan Beulich
This adds static information about the code regions where the stack pointer cannot be relied upon. Kernel debuggers may then use this information to determine which stack to switch to when having a need to switch off of namely the NMI stack.
Hmm - can't this be expressed in CFI somehow?
Probably one could use .cfi_undefined, but the code needing the information (switching away from the NMI stack) shouldn't have to go through parsing the .eh_frame section contents in order to obtain that information.
Jan
Re: [PATCH 18/39] NLKD/x86-64 - INT1/INT3 handling changes
In reply to Jan BeulichQuoted 9 lines · Jan Beulich
This
- switches the INT3 handler to run on an IST stack (to cope with breakpoints set by a kernel debugger on places where the kernel's %gs base hasn't been set up, yet); the IST stack used is shared with the INT1 handler's
- allows nesting of INT1/INT3 handlers so that one can, with a kernel debugger, debug (at least) the user-mode portions of the INT1/INT3 handling; the nesting isn't actively enabled here since a kernel- debugger-free kernel doesn't need it
Looks reasonable except for the CONFIG_NLKD hunk, which doesn't seem to be related. I think I'll apply it without that.
-Andi
Re: [PATCH 18/39] NLKD/x86-64 - INT1/INT3 handling changes
Quoted 12 lines
Quoted 1 line
Quoted 1 line
Andi Kleen <[email protected]> 10.11.05 14:21:48 >>>
Quoted 9 lines · Jan Beulich
This
- switches the INT3 handler to run on an IST stack (to cope with breakpoints set by a kernel debugger on places where the kernel's %gs base hasn't been set up, yet); the IST stack used is shared with the INT1 handler's
- allows nesting of INT1/INT3 handlers so that one can, with a kernel debugger, debug (at least) the user-mode portions of the INT1/INT3 handling; the nesting isn't actively enabled here since a kernel- debugger-free kernel doesn't need it
Quoted 2 lines
Looks reasonable except for the
CONFIG_NLKDhunk, which doesn't seem to be related. I think I'll apply it without that.
As the comment in that hunk says - this is not the correct test, but the correct test cannot be used. Omitting the hunk altogether will leave orphan references to the pda field (even though these won't cause build problems) in setup64.c and traps.c.
Jan
Re: [PATCH 18/39] NLKD/x86-64 - INT1/INT3 handling changes
Quoted 13 lines · Jan Beulich
Quoted 13 lines
Quoted 1 line
Quoted 1 line
Andi Kleen <[email protected]> 10.11.05 14:21:48 >>>
Quoted 9 lines · Jan Beulich
This
- switches the INT3 handler to run on an IST stack (to cope with breakpoints set by a kernel debugger on places where the kernel's %gs base hasn't been set up, yet); the IST stack used is shared with the INT1 handler's
- allows nesting of INT1/INT3 handlers so that one can, with a kernel debugger, debug (at least) the user-mode portions of the INT1/INT3 handling; the nesting isn't actively enabled here since a kernel- debugger-free kernel doesn't need it
Quoted 7 lines
Quoted 2 lines
Looks reasonable except for the
CONFIG_NLKDhunk, which doesn't seem to be related. I think I'll apply it without that.As the comment in that hunk says - this is not the correct test, but the correct test cannot be used. Omitting the hunk altogether will leave orphan references to the pda field (even though these won't cause build problems) in
setup64.candtraps.c.
!NLKD code relying on CONFIG_NLKD code? That sounds wrong. I won't apply it then. Please clean up first.
-Andi
Re: [PATCH 18/39] NLKD/x86-64 - INT1/INT3 handling changes
Quoted 4 lines
Quoted 4 lines
Quoted 2 lines
Looks reasonable except for the
CONFIG_NLKDhunk, which doesn't seem to be related. I think I'll apply it without that.As the comment in that hunk says - this is not the correct test, but
the
Quoted 1 line
Quoted 1 line
correct test cannot be used. Omitting the hunk altogether will leave
orphan
Quoted 1 line
Quoted 1 line
references to the pda field (even though these won't cause build
problems)
Quoted 3 lines
Quoted 1 line
in
setup64.candtraps.c.!NLKD code relying on
CONFIG_NLKDcode? That sounds wrong. I won't
apply
Quoted 1 line
it then. Please clean up first.
Since the exception stack size doesn't get set to other than 4k, this isn't by itself wrong (the NLKD patch later conditionally sets this to more than 4k). The problem, as said in the patch, is that pda.h cannot include processor.h, and I see no solution for that (other than breaking up processor.h).
Jan
Re: [discuss] Re: [PATCH 18/39] NLKD/x86-64 - INT1/INT3 handling changes
Quoted 5 lines · Jan Beulich
Since the exception stack size doesn't get set to other than 4k, this isn't by itself wrong (the NLKD patch later conditionally sets this to more than 4k). The problem, as said in the patch, is that
pda.hcannot includeprocessor.h, and I see no solution for that (other than breaking upprocessor.h).
You mean for the exception stack size defines? Feel free to put them into a different header then. processor.h has too much stuff anyways.
-Andi
Re: [PATCH 13/39] NLKD/x86-64 - time adjustment
In reply to Jan BeulichQuoted 8 lines · Jan Beulich
Since x86-64 time handling is not overflow-safe, these are the adjustments needed for allowing debuggers to update time after having halted the system for perhaps extended periods of time.
Note that this depends on the HPET definitions adjustments, which aren't in 2.6.14, but have supposedly been merged already into 2.6.15.
From: Jan Beulich <[email protected]>
<no code quoting because that is hard with your attachments>
In general thanks for the overflow fixes. I understand the code had generic problems in this area and it's good someone tackling them.
But many details should be changed.
The magic ICH6 HPET enable code has to go. It looks far too fragile and might break something else. I also don't want direct PCI config space accesses like this. We'll have to wait for ACPI HPET support I think. I think I'll remove the original hack for AMD 8111 too - it was only for testing anyways. If you still want to use it you have to keep it as a private patch.
Please remove the ifdefs too. 64bit HPET support would be fine, but only as a runtime mechanism, not compile time.
Can you remove debugger_jiffies please?
The code has to handle long delays anyways (e.g. if someone uses a target probe), so we cannot rely on such hacks anyways.
I don't quite understand why the SMP case should be different from UP in that ifdef. Can you explain? It shouldn't in theory.
/* When the TSC gets reset during AP startup, the code below would
+ incorrectly think we lost a huge amount of ticks. */
That is outdated - the TSCs are not reset anymore since 2.6.12. Please remove code for handling that.
The union in vxtime_data is ugly - can it be avoided?
Vojtech should probably review that one too when you repost.
-Andi
Re: [PATCH 13/39] NLKD/x86-64 - time adjustment
Quoted 5 lines
The magic ICH6 HPET enable code has to go. It looks far too fragile and might break something else. I also don't want direct PCI config space accesses like this. We'll have to wait for ACPI HPET support I think. I think I'll remove the original hack for AMD 8111 too - it was only for testing anyways. If you still want to use it you have to keep it as a private patch.
That's fine with me. However, it was the only way for me to test the HPET code... It's not enabled anyway by default, but if you want the whole hack go away that's fine with me.
Quoted 2 lines
Please remove the ifdefs too. 64bit HPET support would be fine, but only as a runtime mechanism, not compile time.
This I added only for the purpose of not affecting existing code in existing configurations. If the code is generally acceptable, then I'll be more than happy to convert it.
Quoted 3 lines
Can you remove
debugger_jiffiesplease?
The code has to handle long delays anyways (e.g. if someone uses a target probe), so we cannot rely on such hacks anyways.
As above, I introduced this only to not affect existing code. If the added latency is no problem, then of course only the overflow safe code path should be kept, and then debugger_jiffies is completely unnecessary.
Quoted 8 lines
I don't quite understand why the SMP case should be different from UP in that ifdef. Can you explain? It shouldn't in theory.
/* When the TSC gets reset during AP startup, the code below would
(quoted diff) +1
-0+ incorrectly think we lost a huge amount of ticks. */That is outdated - the TSCs are not reset anymore since 2.6.12. Please remove code for handling that.
Good to know, I didn't notice that. The conditional was so that the reset TSC would be considered a rolled-over one, resulting in a huge number of lost ticks.
Quoted 1 line
The union in
vxtime_datais ugly - can it be avoided?
Yes, if the whole code is to become overflow-safe, then it'll just need to be a 64-bit field.
Jan
Re: [PATCH 13/39] NLKD/x86-64 - time adjustment
Quoted 7 lines · Jan Beulich
Quoted 3 lines
Please remove the ifdefs too. 64bit HPET support would be fine, but only as a runtime mechanism, not compile time.
This I added only for the purpose of not affecting existing code in existing configurations. If the code is generally acceptable, then I'll be more than happy to convert it.
We can't use 64bit HPET everywhere because quite some chipsets only support 32bit HPET. So it has to be a runtime switch depending on the capabilities of the hardware.
Quoted 8 lines
Quoted 4 lines
Can you remove
debugger_jiffiesplease?
The code has to handle long delays anyways (e.g. if someone uses a target probe), so we cannot rely on such hacks anyways.As above, I introduced this only to not affect existing code. If the added latency is no problem, then of course only the overflow safe code path should be kept, and then
debugger_jiffiesis completely unnecessary.
Hmm - didn't notice anything particularly slow. Or what were you thinking about regarding the latency? And it should only run at each timer interrupt, so it isn't a fast path. So I guess it's best to run it always.
-Andi
Re: [PATCH 13/39] NLKD/x86-64 - time adjustment
Quoted 6 lines · Andi Kleen
Quoted 4 lines · Jan Beulich
Quoted 3 lines
Please remove the ifdefs too. 64bit HPET support would be fine, but only as a runtime mechanism, not compile time.
Quoted 7 lines
Quoted 3 lines
This I added only for the purpose of not affecting existing code in existing configurations. If the code is generally acceptable, then I'll be more than happy to convert it.
We can't use 64bit HPET everywhere because quite some chipsets only support 32bit HPET. So it has to be a runtime switch depending on the capabilities of the hardware.
Is there any advantage to using 64-bit HPET? It's read is even slower (and thus even more unusable in a vsyscall than a 32-bit HPET read), and the missing 32 bits can be quite easily added should we need them for computations, which I doubt.
Quoted 11 lines
Quoted 7 lines
Quoted 3 lines
Can you remove
debugger_jiffiesplease?
The code has to handle long delays anyways (e.g. if someone uses a target probe), so we cannot rely on such hacks anyways.As above, I introduced this only to not affect existing code. If the added latency is no problem, then of course only the overflow safe code path should be kept, and then
debugger_jiffiesis completely unnecessary.Hmm - didn't notice anything particularly slow. Or what were you thinking about regarding the latency? And it should only run at each timer interrupt, so it isn't a fast path. So I guess it's best to run it always.
Signature · 2 lines
Vojtech Pavlik SuSE Labs, SuSE CR
Re: [PATCH 13/39] NLKD/x86-64 - time adjustment
Quoted 1 line · Vojtech Pavlik
Is there any advantage to using 64-bit HPET?
Yes - it can tolerate long delays between ticks, e.g. caused by noidletick / debuggers / target probes / smm etc. At least the first case will be fairly important soon.
Quoted 1 line
It's read is even slower
Why? The read should be on cache line granuality and there shouldn't be any difference in theory.
-Andi
Re: [PATCH 13/39] NLKD/x86-64 - time adjustment
Quoted 7 lines · Andi Kleen
Quoted 1 line · Vojtech Pavlik
Is there any advantage to using 64-bit HPET?
Yes - it can tolerate long delays between ticks, e.g. caused by noidletick / debuggers / target probes / smm etc. At least the first case will be fairly important soon.
A 32-bit 14 MHz HPET counter will overflow in approximately 5 minutes. I don't think going 64-bit makes sense for noidletick, but for debuggers, etc, it could make a good sense indeed.
Quoted 4 lines
Quoted 1 line
It's read is even slower
Why? The read should be on cache line granuality and there shouldn't be any difference in theory.
I'll try to measure this. Indeed, in theory there shouldn't be a significant difference.
Signature · 2 lines
Vojtech Pavlik SuSE Labs, SuSE CR
Re: [PATCH 13/39] NLKD/x86-64 - time adjustment
Quoted 16 lines · Vojtech Pavlik
Quoted 7 lines · Andi Kleen
Quoted 1 line · Vojtech Pavlik
Is there any advantage to using 64-bit HPET?
Yes - it can tolerate long delays between ticks, e.g. caused by noidletick / debuggers / target probes / smm etc. At least the first case will be fairly important soon.
A 32-bit 14 MHz HPET counter will overflow in approximately 5 minutes. I don't think going 64-bit makes sense for noidletick, but for debuggers, etc, it could make a good sense indeed.
Quoted 9 lines
Quoted 4 lines
Quoted 1 line
It's read is even slower
Why? The read should be on cache line granuality and there shouldn't be any difference in theory.
I'll try to measure this. Indeed, in theory there shouldn't be a significant difference.
Doesn't this depend on the atomic nature of the 64-bit read? If it is really two 32-bit reads one would need to do extra work to make sure the two parts belong together.
Signature · 2 lines
George Anzinger [email protected] HRT (High-res-timers): http://sourceforge.net/projects/high-res-timers/
Re: [discuss] Re: [PATCH 13/39] NLKD/x86-64 - time adjustment
Quoted 2 lines · George Anzinger
Doesn't this depend on the atomic nature of the 64-bit read? If it is really two 32-bit reads one would need to do extra work to make sure the two parts belong together.
Please take a look at the Subject.
-Andi
Re: [discuss] Re: [PATCH 13/39] NLKD/x86-64 - time adjustment
Quoted 7 lines · Andi Kleen
Quoted 3 lines · George Anzinger
Doesn't this depend on the atomic nature of the 64-bit read? If it is really two 32-bit reads one would need to do extra work to make sure the two parts belong together.
Please take a look at the Subject.
Still, the HPET doesn't necessarily have to be a 64-bit device. At least on AMD systems, where it's implemented in AMD8111 Thor, it's bundled together with other, 32-bit PCI devices like USB. On the other hand, the 8111 HPET doesn't implement a 64-bit conter, and it's likely that the Intel implementation in the northbridges (or *CH, as Intel prefers calling the things) is likely native 64-bit.
Signature · 2 lines
Vojtech Pavlik SuSE Labs, SuSE CR
Re: [discuss] Re: [PATCH 13/39] NLKD/x86-64 - time adjustment
Quoted 6 lines
Quoted 1 line
Quoted 1 line
Vojtech Pavlik <[email protected]> 15.11.05 08:50:26 >>>
Quoted 3 lines · Andi Kleen
Quoted 1 line · George Anzinger
Doesn't this depend on the atomic nature of the 64-bit read? If
it
Quoted 1 line
Quoted 1 line
Quoted 1 line
is really two 32-bit reads one would need to do extra work to
make
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
sure the two parts belong together.
Please take a look at the Subject.
Still, the HPET doesn't necessarily have to be a 64-bit device. At
least
Quoted 2 lines
on AMD systems, where it's implemented in AMD8111 Thor, it's bundled together with other, 32-bit PCI devices like USB. On the other hand,
the
Quoted 3 lines
8111 HPET doesn't implement a 64-bit conter, and it's likely that the Intel implementation in the northbridges (or *CH, as Intel prefers calling the things) is likely native 64-bit.
And even then there is no guarantee there isn't something somewhere converting the 64-bit to pairs of 32-bit accesses. Thus one would in fact need extra information about the platform to know whether the entire bus path is 64-bit in order to safely do 64-bit accesses.
However, the changes as I proposed them (and will resubmit hopefully later today with the adjustments requested by Andi) do intentionally not do any 64-bit reads, they only use 64-bit writes when resetting counter or comparator (where all that's needed from the platform is that the writes to the low 32 bits are done first, which x86 architecturally guarantees).
Jan
Re: [PATCH 13/39] NLKD/x86-64 - time adjustment
In reply to Andi KleenQuoted 16 lines · Andi Kleen
Please remove the ifdefs too. 64bit HPET support would be fine, but only as a runtime mechanism, not compile time.
Can you remove
debugger_jiffiesplease?
The code has to handle long delays anyways (e.g. if someone uses a target probe), so we cannot rely on such hacks anyways.I don't quite understand why the SMP case should be different from UP in that ifdef. Can you explain? It shouldn't in theory.
/* When the TSC gets reset during AP startup, the code below would
(quoted diff) +1
-0+ incorrectly think we lost a huge amount of ticks. */That is outdated - the TSCs are not reset anymore since 2.6.12. Please remove code for handling that.
Quoted 3 lines
The union in
vxtime_datais ugly - can it be avoided?Vojtech should probably review that one too when you repost.
I'd like to take a look at the patch as it is, but it seems my spam filter ate it, and LKML.org doesn't archive binary attachments.
I've done some work on making x86-64 time handling overflow save in the last few days, so I'm quite interested in what you needed to change.
Signature · 2 lines
Vojtech Pavlik SuSE Labs, SuSE CR
PATCH 14/39 NLKD - kernel trace buffer access
In reply to Jan BeulichDebug extension implementation for NLKD to access the kernel trace buffer.
(actual patch attached)
Debug extension implementation for NLKD to access the kernel trace buffer.
kernel/printk.c +187 -0
@@ -1032,3 +1032,190 @@ int printk_ratelimit(void) printk_ratelimit_burst); }EXPORT_SYMBOL (printk_ratelimit); + +#if defined(CONFIG_PRINTK ) && defined(CONFIG_NLKD ) +# include <linux/ctype.h> +# include <linux/nlkd.h> + +static int match (unsigned long start,unsigned long end,const char *pattern,size_t len) +{ +unsigned long stop; + + start &=LOG_BUF_MASK ; + stop = end &=LOG_BUF_MASK ; +if (stop < start) + stop = log_buf_len; +for (;;) { +const char *p; + +while (((end - start) &LOG_BUF_MASK ) >= len + && (p =memchr (log_buf + start, *pattern, stop - start)) !=NULL ) { +unsigned long where = p - log_buf; + +if (len > stop - where + ? !memcmp (p, pattern, stop - where) + && !memcmp (p + (stop - where), + pattern + (stop - where), + len - (stop - where)) + : !memcmp (p, pattern, len)) +return 1 ; + start = where +1 ; + } +if (end >= start) +return 0 ; + start =0 ; + stop = end; + } +} + +static void do_mgrep (const char *pattern,long skip,long count) +{ +int backward =1 ; +unsigned long line, cur; +size_t len = pattern ?strlen (pattern) :0 ; + +if (count ==0 ) + count =5 ; +else if (count <0 ) { + count = -count; + backward =0 ; + } +if (skip <0 ) { + skip = -skip; + backward =0 ; + } +#define LOG_IDX_MATCH (idx1, idx2) (!(((idx1) ^ (idx2)) & LOG_BUF_MASK)) +if (backward) { +/* Search from end. */ +int end; + + skip += count -1 ; + line = log_end; +do { +for (cur = line -1 ; !LOG_IDX_MATCH (cur, log_end) &&LOG_BUF (cur) &&LOG_BUF (cur) =='\n' ; --cur) + ; +for (; !(end =LOG_IDX_MATCH (cur, log_end) || !LOG_BUF (cur)) &&LOG_BUF (cur) !='\n' ; --cur) + ; +if (len && !match (cur +1 , line, pattern, len)) + ++skip; + line = cur +1 ; + }while (skip-- && !end); +if (++skip < count) + count -= skip; +else + count =0 ; + } +else { +/* Search from start. */ +for (cur =LOG_BUF (log_end) ? log_end :0 ; line = cur, skip; --skip) { +while (LOG_BUF (cur) !='\n' ) +if (!LOG_BUF (cur) ||LOG_IDX_MATCH (++cur, log_end)) +return ; +while (LOG_BUF (cur) =='\n' ) +if (!LOG_BUF (cur) ||LOG_IDX_MATCH (++cur, log_end)) +return ; +if (len && !match (line, cur, pattern, len)) + ++skip; + } + } +while (count) { +for (cur = line;LOG_BUF (cur) &&LOG_BUF (cur) !='\n' ; ++cur) +if (LOG_IDX_MATCH (cur +1 ,0 )) { +for (cur =0 ;LOG_BUF (cur) &&LOG_BUF (cur) !='\n' ; ++cur) +if (LOG_IDX_MATCH (cur +1 , line)) +break ; +break ; + } +if (!len ||match (line, cur, pattern, len)) { +if (cur < line) { +nlkdExtPrintf ("%.*s" , log_buf_len - (int )(line &LOG_BUF_MASK ), &LOG_BUF (line)); +nlkdExtPrintf ("%.*s\n" , (int )cur, log_buf); + } +else +nlkdExtPrintf ("%.*s\n" , (int )(cur - line), &LOG_BUF (line)); + --count; + } +if (LOG_BUF (cur) !='\n' ) +break ; +for (line = cur +1 ;LOG_BUF (line) =='\n' ; ++line) + ; + } +#undef LOG_IDX_MATCH +} + +static char *skipComma (char *s) { +while (*s &&isspace (*s)) + ++s; +if (*s ==';' || *s ==',' ) + ++s; +while (*s &&isspace (*s)) + ++s; +return s; +} + +/* +* !dmesg [[<# to skip>;]<# of lines>] +*/ +static void dbgxt_dmesg (void *pattern,const char *command) { +long skip =0 , count =0 ; + +if (!command) +return ; +if (!pattern && *command =='?' ) { +nlkdExtOutputString ("dmesg [[<# to skip>] <# of entries>]" ); +return ; + } +if (*command) { +char *tail; + + skip =simple_strtol (command, &tail,0 ); +if (*(tail =skipComma (tail))) + count =simple_strtol (tail,NULL ,0 ); +else { + count = skip; + skip =0 ; + } + } +do_mgrep (pattern, skip, count); +} + +/* +* !mgrep <match string> [[<# to skip>];<# of lines>] +*/ +static void dbgxt_mgrep (void *unused,const char *command) { +if (!command) +return ; +if (!strcmp (command,"?" )) { +nlkdExtOutputString ("mgrep <match> [[<# to skip>] <# of entries>]" ); +return ; + } +if (*command) { +char pattern[256 ], *dst; +char quote =strchr ("\"\'" , *command) !=NULL ? *command++ :0 ; + +for (dst = pattern; *command && (quote ? *command != quote : !isspace (*command)); ++command) +if (dst < pattern +ARRAY_SIZE (pattern) -1 ) + *dst++ = *command; + *dst =0 ; +if (*command) + ++command; +while (*command &&isspace (*command)) + ++command; +dbgxt_dmesg ((void *)pattern, command); + } +} + +static THIS_MODULE_ID (printkModuleId); +NLKD_EXTENSION (dmesg, + dbgxt_dmesg, +NULL , + printkModuleId, +"Display trace buffer records" , +0 ); +NLKD_EXTENSION (mgrep, + dbgxt_mgrep, +NULL , + printkModuleId, +"Grep trace buffer records" , +0 ); +#endif
PATCH 15/39 NLKD - early pseudo-fs
While for limited amounts of configuration information the kernel command line may be suitable, it isn't when it comes to significant amounts of configurable entities that need to be set before the full kernel infrastructure is available. This patch adds functionality to pass one or more configuration files through the initrd, but without requiring knowledge of the actual structure (including compression) of it; the file(s) is/are attached to the end of the already built initrd (which obviously depends on external scripts not provided here).
(actual patch attached)
While for limited amounts of configuration information the kernel command line may be suitable, it isn't when it comes to significant amounts of configurable entities that need to be set before the full kernel infrastructure is available. This patch adds functionality to pass one or more configuration files through the initrd, but without requiring knowledge of the actual structure (including compression) of it; the file(s) is/are attached to the end of the already built initrd (which obviously depends on external scripts not provided here).
include/linux/epfs.h new file +56 -0
@@ -0,0 +1,56 @@ +/***************************************************************************** +* +* File Name: epfs.h +* Created by: Jan Beulich +* Date created: 28Apr2005 +* +* %version: 2 % +* %derived_by: jbeulich % +* %date_modified: Mon Jun 27 04:48:22 2005 % +* +*****************************************************************************/ +/***************************************************************************** +* * +* Copyright (c) 2005 Novell, Inc. All Rights Reserved. * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of version 2 of the GNU General Public License * +* as published by the Free Software Foundation. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, contact Novell, Inc. * +* * +* To contact Novell about this file by physical or electronic mail, * +* you may find current contact information at www.novell.com. * +* * +*****************************************************************************/ +/***************************************************************************** +* +* File Description: +* +*****************************************************************************/ +#ifndef _LINUX_EPFS_H + +#include <linux/config.h> +#include <linux/errno.h> +#include <linux/types.h> + +#if defined(CONFIG_EARLY_PSEUDO_FS ) && !defined(MODULE ) +# define EPFS_DECLARE (proto, retval) proto; +#else +# define EPFS_DECLARE (proto, retval) static inline proto { return retval; } +#endif + +EPFS_DECLARE(int epfs_open(const char *name), -ENOSYS) +EPFS_DECLARE(size_t epfs_get_size(int fd), ~(size_t)0) +EPFS_DECLARE(size_t epfs_read(int fd, size_t pos, void *buf, size_t size), ~(size_t)0) +EPFS_DECLARE(int epfs_close(int fd), -ENOSYS) + +#undef EPFS_DECLARE + +#endif /* _LINUX_EPFS_H */
init/Kconfig +10 -0
@@ -340,6 +340,16 @@ config BASE_FULL kernel data structures. This saves memory on small machines, but may reduce performance. +config EARLY_PSEUDO_FS + bool "Early pseudo file system support" + depends on BLK_DEV_INITRD + ---help--- + This pseudo file system allows access to certain (configuration) + files before any real file system is available. A matching mkinitrd + or similar script is required to actually make use of this. + + If unsure, say N. + config FUTEX bool "Enable futex support" if EMBEDDED default y
init/Makefile +1 -0
@@ -4,6 +4,7 @@ obj-y := main.o version.o mounts.o initramfs.o obj-$(CONFIG_GENERIC_CALIBRATE_DELAY) += calibrate.o +obj-$(CONFIG_EARLY_PSEUDO_FS) += epfs.o mounts-y := do_mounts.o mounts-$(CONFIG_DEVFS_FS) += do_mounts_devfs.o
init/epfs.c new file +151 -0
151 lines not on this page · raw message
PATCH 16/39 NLKD - core adjustments
The core NLKD adjustments to pre-existing code.
(actual patch attached)
The core NLKD adjustments to pre-existing code.
include/asm-generic/bug.h +38 -0
@@ -5,6 +5,44 @@#include <linux/config.h> #ifdef CONFIG_BUG + +# ifdef CONFIG_NLKD + +# ifndef _LINUX_NLKD_H +# define _LINUX_NLKD_H +# include <linux/nlkd.h> +# undef _LINUX_NLKD_H +# endif + +# ifdef HAVE_ARCH_BUG +# undef BUG +# else +# define HAVE_ARCH_BUG +# endif +# define BUG () nlkdAssert("BUG", __FILE__, __PRETTY_FUNCTION__, __LINE__) + +# ifdef HAVE_ARCH_BUG_ON +# undef BUG_ON +# else +# define HAVE_ARCH_BUG_ON +# endif +# define BUG_ON (condition) (unlikely(condition) \ + ? nlkdAssert("!(" #condition ")", __FILE__, __PRETTY_FUNCTION__, __LINE__) \ + : (void)0) + +# ifdef HAVE_ARCH_WARN_ON +# undef WARN_ON +# else +# define HAVE_ARCH_WARN_ON +# endif +# define WARN_ON (condition) (unlikely(condition) \ + ? printk("Badness in %s at %s:%d\n", __PRETTY_FUNCTION__, __FILE__, __LINE__), \ + dump_stack(), \ + nlkdDebugEvent(DEBUG_EVENT_MESSAGE, #condition) \ + : (void)0) + +# endif /* CONFIG_NLKD */ +#ifndef HAVE_ARCH_BUG #define BUG () do { \ printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
include/linux/sched.h +11 -0
@@ -298,6 +298,10 @@ struct mm_struct {/* Architecture-specific MM context */ mm_context_t context; +#ifdef CONFIG_NLKD +struct cdeBPStruct_s *bpList; +#endif +/* Token based thrashing protection. */ unsigned long swap_token_time;char recent_pagein;
@@ -681,6 +685,10 @@ struct task_struct {struct mm_struct *mm, *active_mm; +#ifdef CONFIG_NLKD +struct cdeBPStruct_s *bpList; +#endif +/* task state */ struct linux_binfmt *binfmt;long exit_state;
@@ -689,6 +697,9 @@ struct task_struct {/* ??? */ unsigned long personality; unsigned did_exec:1; +#ifdef CONFIG_NLKD + unsigned kstep:1; /* kernel-debugger single stepping this task */ +#endif pid_t pid;pid_t tgid;/*
init/Kconfig +1 -1
@@ -275,7 +275,7 @@ config KALLSYMS config KALLSYMS_TRADITIONAL bool "Traditional kallsyms symbol table format" depends on KALLSYMS - default !MODULES + default !MODULES && !NLKD help Say N here if you want the kernel symbol table to be consistent with that loadable modules use (i.e. the ELF symbol table extracted from
init/main.c +3 -0
@@ -47,6 +47,7 @@#include <linux/rmap.h> #include <linux/mempolicy.h> #include <linux/key.h> +#include <linux/nlkd.h> #include <net/sock.h> #include <asm/io.h>
@@ -482,6 +483,7 @@ asmlinkage void __init start_kernel(voidsort_main_extable ();trap_init ();kallsyms_early_init (); +nlkd_init ();rcu_init ();init_IRQ ();pidhash_init ();
@@ -709,6 +711,7 @@ static int init(void * unused)* we're essentially up and running. Get rid of the * initmem segments and start the user-mode stuff.. */ +nlkd_init_done ();kallsyms_init_done ();free_initmem ();unlock_kernel ();
kernel/exit.c +2 -0
@@ -28,6 +28,7 @@#include <linux/cpuset.h> #include <linux/syscalls.h> #include <linux/signal.h> +#include <linux/nlkd.h> #include <asm/uaccess.h> #include <asm/unistd.h>
@@ -794,6 +795,7 @@ fastcall NORET_TYPE void do_exit(long costruct task_struct *tsk = current;int group_dead; +bp_list_clear (tsk);profile_task_exit (tsk);WARN_ON (atomic_read (&tsk->fs_excl));
kernel/fork.c +5 -0
@@ -42,6 +42,7 @@#include <linux/profile.h> #include <linux/rmap.h> #include <linux/acct.h> +#include <linux/nlkd.h> #include <asm/pgtable.h> #include <asm/pgalloc.h>
@@ -337,6 +338,9 @@ static struct mm_struct * mm_init(structif (likely (!mm_alloc_pgd (mm))) { mm->def_flags =0 ; +#if defined(CONFIG_CDE ) || defined(CONFIG_CDE_MODULE ) + mm->bpList =NULL ; +#endif return mm; }free_mm (mm);
@@ -377,6 +381,7 @@ void fastcall __mmdrop(struct mm_structvoid mmput (struct mm_struct *mm) {if (atomic_dec_and_test (&mm->mm_users)) { +bp_list_clear (mm);exit_aio (mm);exit_mmap (mm);if (!list_empty (&mm->mmlist)) {
kernel/power/swsusp.c +3 -0
@@ -67,6 +67,7 @@#include <linux/highmem.h> #include <linux/bio.h> #include <linux/mount.h> +#include <linux/nlkd.h> #include <asm/uaccess.h> #include <asm/mmu_context.h>
@@ -1044,6 +1045,7 @@ int swsusp_suspend(void)/* Restore control flow magically appears here */ restore_processor_state ();BUG_ON (nr_copy_pages_check != nr_copy_pages); +bp_load ();restore_highmem ();device_power_up ();local_irq_enable ();
@@ -1064,6 +1066,7 @@ int swsusp_resume(void)*/ BUG_ON (!error);restore_processor_state (); +bp_load ();restore_highmem ();touch_softlockup_watchdog ();device_power_up ();
kernel/sched.c +9 -1
@@ -47,6 +47,7 @@#include <linux/syscalls.h> #include <linux/times.h> #include <linux/acct.h> +#include <linux/nlkd.h> #include <asm/tlb.h> #include <asm/unistd.h>
@@ -1568,12 +1569,17 @@ task_t * context_switch(runqueue_t *rq,struct mm_struct *mm = next->mm;struct mm_struct *oldmm = prev->active_mm; +bp_list_disable (1 , prev); +if (unlikely (!mm)) { next->active_mm = oldmm;atomic_inc (&oldmm->mm_count);enter_lazy_tlb (oldmm, next); - }else + }else { +bp_list_disable (oldmm && oldmm != mm, oldmm);switch_mm (oldmm, mm, next); +bp_list_enable (oldmm != mm, mm); + }if (unlikely (!prev->mm)) { prev->active_mm =NULL ;
@@ -1584,6 +1590,8 @@ task_t * context_switch(runqueue_t *rq,/* Here we just switch the register state and the stack. */ switch_to (prev, next, prev); +bp_list_enable (1 , current); +return prev; }
PATCH 17/39 NLKD/i386 - core adjustments
The core i386 NLKD adjustments to pre-existing code.
(actual patch attached)
The core i386 NLKD adjustments to pre-existing code.
arch/i386/Kconfig +5 -0
@@ -425,6 +425,11 @@ config X86_CMPXCHG64 depends on !M386 && !M486 default y +config X86_CMOVE + bool + depends on !M386 && !M486 && !MCYRIXIII && !M586 && !M586TSC && !M586MMX && !MWINCHIPC6 && !MWINCHIP2 && !MWINCHIP3D && !MGEODEGX1 + default y + config X86_ALIGNMENT_16 bool depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1
arch/i386/Kconfig.debug +1 -1
@@ -54,7 +54,7 @@ config DEBUG_PAGEALLOC config 4KSTACKS bool "Use 4Kb for kernel stacks instead of 8Kb" - depends on DEBUG_KERNEL + depends on DEBUG_KERNEL && !NLKD help If you say Y here the kernel will use a 4Kb stacksize for the kernel stack attached to each process/thread. This facilitates
arch/i386/kernel/cpu/common.c +1 -0
@@ -7,6 +7,7 @@#include <linux/bootmem.h> #include <asm/semaphore.h> #include <asm/processor.h> +#include <asm/debugreg.h> #include <asm/i387.h> #include <asm/msr.h> #include <asm/io.h>
arch/i386/kernel/process.c +13 -0
@@ -46,6 +46,7 @@#include <asm/io.h> #include <asm/ldt.h> #include <asm/processor.h> +#include <asm/debugreg.h> #include <asm/i387.h> #include <asm/desc.h> #ifdef CONFIG_MATH_EMULATION
@@ -393,6 +394,10 @@ void exit_thread(void) tss->io_bitmap_base =INVALID_IO_BITMAP_OFFSET ;put_cpu (); } +if (tsk->thread.debugreg[7 ]) { +enable_debugreg (tsk,7 ,0 ); + tsk->thread.debugreg[7 ] =0 ; + } }void flush_thread (void )
@@ -406,6 +411,8 @@ void flush_thread(void)*/ kprobe_flush_task (tsk); +if (tsk->thread.debugreg[7 ]) +enable_debugreg (tsk,7 ,0 );memset (tsk->thread.debugreg,0 ,sizeof (unsigned long )*8 );memset (tsk->thread.tls_array,0 ,sizeof (tsk->thread.tls_array));/*
@@ -507,6 +514,12 @@ int copy_thread(int nr, unsigned long cl desc->b =LDT_entry_b (&info); } +if (tsk->thread.debugreg[7 ]) { + p->thread.debugreg[7 ] =0 ; +enable_debugreg (p,7 , tsk->thread.debugreg[7 ]); + p->thread.debugreg[7 ] = tsk->thread.debugreg[7 ]; + } + err =0 ; out:if (err && p->thread.io_bitmap_ptr) {
arch/i386/kernel/ptrace.c +6 -1
@@ -493,7 +493,7 @@ asmlinkage int sys_ptrace(long request,* * Note that LENi == 0x10 is defined on x86_64 in long * mode (i.e. even for 32-bit userspace software, but -* 64-bit kernel), so the x86_64 mask value is 0x5454. +* 64-bit kernel), so the x86_64 mask value is 0x5554. * See the AMD manual no. 24593 (AMD64 System * Programming)*/
@@ -506,6 +506,11 @@ asmlinkage int sys_ptrace(long request, addr -= (long ) &dummy->u_debugreg; addr = addr >>2 ; + +if (enable_debugreg (child, addr, data) <0 ) { + ret = -EBUSY ; +break ; + } child->thread.debugreg[addr] = data; ret =0 ; }
arch/i386/kernel/signal.c +2 -1
@@ -25,6 +25,7 @@#include <asm/ucontext.h> #include <asm/uaccess.h> #include <asm/i387.h> +#include <asm/debugreg.h> #include "sigframe.h" #define DEBUG_SIG 0
@@ -629,7 +630,7 @@ int fastcall do_signal(struct pt_regs *r* inside the kernel. */ if (unlikely (current->thread.debugreg[7 ])) { -set_debugreg (current->thread.debugreg[7 ],7 ); +restore_debugreg (); }/* Whee! Actually deliver the signal. */
arch/i386/kernel/traps.c +1 -1
@@ -774,7 +774,7 @@ fastcall void __kprobes do_debug(struct* the signal is delivered. */ clear_dr7: -set_debugreg (0 ,7 ); +disable_debugreg (regs,7 );return ; debug_vm86:
arch/i386/kernel/vmlinux.lds.S +6 -0
@@ -82,6 +82,12 @@ SECTIONS __setup_start = .; .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) { *(.init.setup) } __setup_end = .; +#ifdef CONFIG_NLKD + . = ALIGN(4); + __start_nlkd_ext = .; + .nlkd.ext : AT(ADDR(.nlkd.ext) - LOAD_OFFSET) { *(.nlkd.ext) } + __stop_nlkd_ext = .; +#endif __initcall_start = .; .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) { *(.initcall1.init)
arch/i386/power/cpu.c +1 -0
@@ -10,6 +10,7 @@#include <linux/config.h> #include <linux/module.h> #include <linux/suspend.h> +#include <asm/debugreg.h> static struct saved_context saved_context;
include/asm-i386/debugreg.h +50 -0
54 lines not on this page · raw message
include/asm-i386/processor.h +1 -11
@@ -461,6 +461,7 @@ struct thread_struct {#define INIT_THREAD { \ .vm86_info = NULL, \ + .esp0 = sizeof(init_stack) + (long)&init_stack, \ .sysenter_cs = __KERNEL_CS, \ .io_bitmap_ptr = NULL, \ }
@@ -507,17 +508,6 @@ static inline void load_esp0(struct tss_ }while (0 )/* -* These special macros can be used to get or set a debugging register - */ -#define get_debugreg (var, register) \ - __asm__("movl %%db" #register ", %0" \ - :"=r" (var)) -#define set_debugreg(value, register) \ - __asm__("movl %0,%%db" #register \ - : /* no output */ \ - :"r" (value)) - -/* * Set IOPL bits in EFLAGS from given mask */ static inline void set_iopl_mask(unsigned mask)
Re: [PATCH 17/39] NLKD/i386 - core adjustments
Quoted 5 lines · Jan Beulich
The core i386 NLKD adjustments to pre-existing code.
Signed-off-by Jan Beulich <[email protected]>(actual patch attached)
If your code doesn't work with 4k stacks you have a problem because 8k stacks will soon be removed (my goal is 2.6.16, perhaps one or two releases later).
cu
Adrian
Signature · 4 lines
"Is there not promise of rain?" Ling Tan asked suddenly out
of the darkness. There had been need of rain for many days.
"Only a promise," Lao Er said.
Pearl S. Buck - Dragon SeedRe: [PATCH 17/39] NLKD/i386 - core adjustments
Quoted 4 lines
Quoted 1 line
Quoted 1 line
Adrian Bunk <[email protected]> 09.11.05 20:00:17 >>>
Quoted 2 lines · Jan Beulich
The core i386 NLKD adjustments to pre-existing code.
Quoted 8 lines
Quoted 3 lines
Signed-off-by Jan Beulich <[email protected]>(actual patch attached)
If your code doesn't work with 4k stacks you have a problem because 8k stacks will soon be removed (my goal is 2.6.16, perhaps one or two
releases later).
It's not that it doesn't work with them, but chances of stack overflow are too high for my taste.
Jan
Re: [PATCH 17/39] NLKD/i386 - core adjustments
Quoted 8 lines · Jan Beulich
Quoted 8 lines
Quoted 1 line
Quoted 1 line
Adrian Bunk <[email protected]> 09.11.05 20:00:17 >>>
Quoted 5 lines · Jan Beulich
The core i386 NLKD adjustments to pre-existing code.
Signed-off-by Jan Beulich <[email protected]>(actual patch attached)
Quoted 7 lines
Quoted 4 lines
If your code doesn't work with 4k stacks you have a problem because 8k stacks will soon be removed (my goal is 2.6.16, perhaps one or two
releases later).
It's not that it doesn't work with them, but chances of stack overflow are too high for my taste.
If there's a chance of a stack overflow the stack usage has to be reduced until the chance goes down to 0.
Quoted 1 line
Jan
cu
Adrian
Signature · 4 lines
"Is there not promise of rain?" Ling Tan asked suddenly out
of the darkness. There had been need of rain for many days.
"Only a promise," Lao Er said.
Pearl S. Buck - Dragon SeedRe: [PATCH 17/39] NLKD/i386 - core adjustments
Quoted 2 lines
If there's a chance of a stack overflow the stack usage has to be reduced until the chance goes down to 0.
How does one reduce stack usage in the presence of recursion driven by user input (referring to expression evaluation)?
Also, NLKD has an extension to the (simplistic) pt_regs frame (including e.g. floating point state) and may be used to debug itself (i.e. there may be more than one frame on the stack at a time).
Jan
Re: [PATCH 17/39] NLKD/i386 - core adjustments
Quoted 4 lines · Jan Beulich
Quoted 2 lines
If there's a chance of a stack overflow the stack usage has to be reduced until the chance goes down to 0.
How does one reduce stack usage in the presence of recursion driven by user input (referring to expression evaluation)?
Recursion removal is a pretty standard technique and featured in almost all introductionary computer science texts. A quick google query finds
http://portal.acm.org/citation.cfm?id=359344
All recursive algorithms can be expressed non-recursively, although it might not always be as nice. Or you can put an upper limit on the allowed complexity of queries.
Sincerely,
Lars Marowsky-Brée <[email protected]>
Signature · 4 lines
High Availability & Clustering SUSE Labs, Research and Development SUSE LINUX Products GmbH - A Novell Business -- Charles Darwin "Ignorance more frequently begets confidence than does knowledge"
PATCH 22/39 NLKD - core
In reply to Jan BeulichThe core NLKD additions.
With other debugging code living scattered across the (official or external) tree(s), this tries to atb once establish a common place for debugging code in a new debug/ directory.
Note that this depends on the i386 cmpxchg adjustments patch, which isn't in 2.6.14, but has supposedly been merged already into 2.6.15.
(actual patch attached)
The core NLKD additions.
With other debugging code living scattered across the (official or external) tree(s), this tries to atb once establish a common place for debugging code in a new debug/ directory.
Note that this depends on the i386 cmpxchg adjustments patch, which isn't in 2.6.14, but has supposedly been merged already into 2.6.15.
Makefile +1 -0
@@ -592,6 +592,7 @@ export MODLIB ifeq ($(KBUILD_EXTMOD),) core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ +core-$(CONFIG_DEBUG_KERNEL) += debug/ vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \ $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
debug/Kconfig new file +22 -0
@@ -0,0 +1,22 @@ +choice + prompt "Kernel debugger" + optional + depends on DEBUG_KERNEL + ---help--- + Kernel debuggers contain commands which allow memory to be examined, + instructions to be disassembled and breakpoints to be set. + + If unsure, say N. + +config NLKD + bool "Novell Linux Kernel Debugger" + depends on DEBUG_KERNEL + depends on (X86_CMOVE && X86_CMPXCHG64 && X86_TSC) || X86_64 + depends on !X86 || !OPROFILE + ---help--- + This option provides a kernel debugger framework. Sub-component + selection will follow later. + +endchoice + +source "debug/nlkd/Kconfig"
debug/Makefile new file +1 -0
@@ -0,0 +1 @@ +obj-$(CONFIG_NLKD) += nlkd/
debug/nlkd/Kconfig new file +71 -0
71 lines not on this page · raw message
debug/nlkd/Makefile new file +108 -0
108 lines not on this page · raw message
debug/nlkd/nlkd.c new file +161 -0
161 lines not on this page · raw message
debug/nlkd/nlkd.h new file +48 -0
48 lines not on this page · raw message
include/linux/fta.h new file +261 -0
261 lines not on this page · raw message
include/linux/lstatus.h new file +241 -0
241 lines not on this page · raw message
include/linux/module-id.h new file +53 -0
53 lines not on this page · raw message
include/linux/nint.h new file +240 -0
240 lines not on this page · raw message
include/linux/nlkd.h new file +241 -0
241 lines not on this page · raw message
PATCH 23/39 NLKD/x86 - core
The core x86 (32- and 64-bit) NLKD additions.
(actual patch attached)
The core x86 (32- and 64-bit) NLKD additions.
debug/nlkd/asm-x86.h new file +290 -0
@@ -0,0 +1,290 @@ +/***************************************************************************** +* +* File Name: asm-x86.h +* Created by: Jan Beulich +* %version: 2 % +* %derived_by: jbeulich % +* %date_modified: Thu Nov 03 04:14:19 2005 % +* +*****************************************************************************/ +/***************************************************************************** +* * +* Copyright (c) 2002-2005 Novell, Inc. All Rights Reserved. * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of version 2 of the GNU General Public License * +* as published by the Free Software Foundation. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, contact Novell, Inc. * +* * +* To contact Novell about this file by physical or electronic mail, * +* you may find current contact information at www.novell.com. * +* * +*****************************************************************************/ +/***************************************************************************** +* +* File Description: +* +*****************************************************************************/ + +.intel_syntax noprefix +.altmacro + +.equiv TRUE, 1 +.equiv FALSE, 0 + +.equiv byte, 1 +.equiv word, 2 +.equiv dword, 4 +.equiv fword, 6 +.equiv qword, 8 +.equiv tbyte, 10 +.equiv oword, 16 +.equiv xmmword, 16 + +.macro .extproc name + .global name + .type name, @function +.endm + +.macro .locproc name + .type name, @function + .align PROCEDURE_ALIGN, 0xCC +name: +#ifdef CONFIG_UNWIND_INFO + .cfi_startproc + .equ .eh.framereg, eh.SP + .equ .eh.frameptr,SP +#endif +.endm + +.macro .pubproc name + .locproc name + .global name +.endm + +.macro .hidproc name + .pubproc name + .hidden name +.endm + +.macro .endp name + .size name, .-name +#ifdef CONFIG_UNWIND_INFO + .cfi_endproc + .equ .eh.framereg,-1 + .equ .eh.frameptr,-1 +#endif +.endm + +.macro .locentry name, type=@notype + .type name, type +name: +.endm + +.macro .pubentry name, type + .locentry name, type + .global name +.endm + +.macro .hidentry name, type + .pubentry name, type + .hidden name +.endm + +.macro .rodata + .section .rodata, "a", @progbits +.endm + +// frame unwind info generation support + +.macro EHpush item:req, spill=TRUE + push item +#ifdef CONFIG_UNWIND_INFO + .if .eh.framereg == eh.SP + .cfi_adjust_cfa_offset .eh.stkword + .endif + .if spill + .ifdef eh.&item + .if .eh.preserved && (1 << eh.&item) + .cfi_rel_offset item, 0 + .endif + .endif + .endif +#endif +.endm + +.macro EHpushC item:req + .if 1 | item // just to make sure this is a constant + push item + .endif +#ifdef CONFIG_UNWIND_INFO + .if .eh.framereg == eh.SP + .cfi_adjust_cfa_offset .eh.stkword + .endif +#endif +.endm + +.macro EHpushO item:req + push offset item +#ifdef CONFIG_UNWIND_INFO + .if .eh.framereg == eh.SP + .cfi_adjust_cfa_offset .eh.stkword + .endif +#endif +.endm + +.macro EHpushV item:req + push [item] +#ifdef CONFIG_UNWIND_INFO + .if .eh.framereg == eh.SP + .cfi_adjust_cfa_offset .eh.stkword + .endif +#endif +.endm + +.macro EHpop item:req, fill=TRUE + pop item +#ifdef CONFIG_UNWIND_INFO + .if fill + .ifdef eh.&item + .if .eh.preserved && (1 << eh.&item) + .cfi_restore item + .endif + .endif + .endif + .if .eh.framereg == eh.SP + .cfi_adjust_cfa_offset -.eh.stkword + .endif +#endif +.endm + +.macro EHpopV item:req + pop [item] +#ifdef CONFIG_UNWIND_INFO + .if .eh.framereg == eh.SP + .cfi_adjust_cfa_offset -.eh.stkword + .endif +#endif +.endm + +.macro EHsetfr dst, src, offs=0 + .if eh.&dst <> eh.&src + .if offs == 0 + mov dst, src +#ifdef CONFIG_UNWIND_INFO + .cfi_def_cfa_register dst +#endif + .else + lea dst, [src + (offs) * .eh.stkword] +#ifdef CONFIG_UNWIND_INFO + .cfi_adjust_cfa_offset -(offs) * .eh.stkword + .cfi_def_cfa_register dst +#endif + .endif + .else + add dst, (offs) * .eh.stkword +#ifdef CONFIG_UNWIND_INFO + .cfi_adjust_cfa_offset -(offs) * .eh.stkword +#endif + .endif +#ifdef CONFIG_UNWIND_INFO + .equ .eh.framereg, eh.&dst + .equ .eh.frameptr, dst +#endif +.endm + +.macro EHenter frsz, level + enter frsz, level +#ifdef CONFIG_UNWIND_INFO + .if .eh.framereg <> eh.SP + .error "'enter' without SP-based frame is not supported." + .endif + .cfi_adjust_cfa_offset .eh.stkword + .cfi_rel_offset BP, 0 + .cfi_def_cfa_register BP + .equ .eh.framereg, eh.BP + .equ .eh.frameptr, BP +#endif +.endm + +.macro EHleave + leave +#ifdef CONFIG_UNWIND_INFO + .if .eh.framereg <> eh.BP + .error "'leave' without BP-based frame is not supported." + .endif + .cfi_def_cfa_register SP + .cfi_restore BP + .cfi_adjust_cfa_offset -.eh.stkword + .equ .eh.framereg, eh.SP + .equ .eh.frameptr, SP +#endif +.endm + +.macro EHspill offs:req, reg:req + mov [.eh.frameptr+(offs)*.eh.stkword], reg +#ifdef CONFIG_UNWIND_INFO + .if .eh.framereg == eh.SP &&&&& (offs) < 0 + .warning "Spill offset into SP-relative frame should be positive." + .endif + .cfi_offset reg, (offs)*.eh.stkword +#endif +.endm + +.macro EHfill reg:req, offs:req + mov reg, [.eh.frameptr+(offs)*.eh.stkword] +#ifdef CONFIG_UNWIND_INFO + .if .eh.framereg == eh.SP &&&&& (offs) < 0 + .warning "Fill offset into SP-relative frame should be positive." + .endif + .cfi_restore reg +#endif +.endm + +.macro EHpushf spill=TRUE + pushf +#ifdef CONFIG_UNWIND_INFO + .if .eh.framereg == eh.SP + .cfi_adjust_cfa_offset .eh.stkword + .endif + .if spill + .cfi_rel_offset FLAGS, 0 + .endif +#endif +.endm + +.macro EHpopf fill=TRUE + popf +#ifdef CONFIG_UNWIND_INFO + .if fill + .cfi_restore FLAGS + .endif + .if .eh.framereg == eh.SP + .cfi_adjust_cfa_offset -.eh.stkword + .endif +#endif +.endm + +.macro EHpushState +#ifdef CONFIG_UNWIND_INFO + .cfi_remember_state +#endif +.endm + +.macro EHpopState +#ifdef CONFIG_UNWIND_INFO + .cfi_restore_state +#endif +.endm + +#ifdef CONFIG_UNWIND_INFO +.equ .eh.framereg, -1 +.equ .eh.frameptr, -1 +#endif
PATCH 24/39 NLKD/i386 - core
The core i386 NLKD additions.
(actual patch attached)
The core i386 NLKD additions.
arch/i386/Kconfig.debug +1 -0
@@ -1,6 +1,7 @@ menu "Kernel hacking" source "lib/Kconfig.debug" +source "debug/Kconfig" config EARLY_PRINTK bool "Early printk" if EMBEDDED && DEBUG_KERNEL
arch/i386/kernel/asm-offsets.c +92 -0
108 lines not on this page · raw message
debug/nlkd/asm-ia32.h new file +121 -0
121 lines not on this page · raw message
debug/nlkd/nlkdIA32.S new file +86 -0
86 lines not on this page · raw message
debug/nlkd/nlkdIA32.h new file +55 -0
55 lines not on this page · raw message
include/asm-i386/fta-frame.h new file +177 -0
177 lines not on this page · raw message
include/asm-i386/fta-type.h new file +89 -0
89 lines not on this page · raw message
include/asm-i386/ia_32.h new file +907 -0
907 lines not on this page · raw message
PATCH 25/39 NLKD/x86-64 - core
In reply to Jan BeulichThe core x86-64 NLKD additions.
(actual patch attached)
The core x86-64 NLKD additions.
arch/x86_64/Kconfig.debug +1 -0
@@ -1,6 +1,7 @@ menu "Kernel hacking" source "lib/Kconfig.debug" +source "debug/Kconfig" # !SMP for now because the context switch early causes GPF in segment reloading # and the GS base checking does the wrong thing then, causing a hang.
arch/x86_64/kernel/asm-offsets.c +70 -0
91 lines not on this page · raw message
debug/nlkd/asm-amd64.h new file +100 -0
100 lines not on this page · raw message
debug/nlkd/nlkdAMD64.S new file +75 -0
75 lines not on this page · raw message
debug/nlkd/nlkdAMD64.h new file +55 -0
55 lines not on this page · raw message
include/asm-x86_64/fta-frame.h new file +216 -0
216 lines not on this page · raw message
include/asm-x86_64/fta-type.h new file +89 -0
89 lines not on this page · raw message
include/asm-x86_64/x86_64.h new file +934 -0
934 lines not on this page · raw message
Re: [PATCH 25/39] NLKD/x86-64 - core
Quoted 1 line · Jan Beulich
The core x86-64 NLKD additions.
I probably won't merge that unless the full NLKD somehow manages to get into mainline. Shouldn't be that hard to maintain out of tree or even build the debugger in a fully separate directory.
My general suggestion would be to move away from using your own defines for all the architecture state (MSRs etc) but instead use the ones from the Linux headers instead which should be largely equivalent (if there are some missing we can probably add them) And getting of that Intel style assembly would be good too.
I would move the asm-offset bits into a separate file, perhaps run from the NLKD Makefile, that should reduce later merging pain.
-Andi
PATCH 26/39 NLKD - run time library
In reply to Jan BeulichSome support definitions and routines of NLKD, the latter primarily to isolate the debugger code from the rest of the kernel.
(actual patch attached)
Some support definitions and routines of NLKD, the latter primarily to isolate the debugger code from the rest of the kernel.
debug/nlkd/dbgutil.c new file +89 -0
@@ -0,0 +1,89 @@ +/***************************************************************************** +* +* File Name: dbgutil.c +* Created by: Jan Beulich +* Date created: 21Jul1999 +* +* %version: 5 % +* %derived_by: jbeulich % +* %date_modified: Mon Jun 27 03:57:44 2005 % +* +*****************************************************************************/ +/***************************************************************************** +* * +* Copyright (c) 1999-2005 Novell, Inc. All Rights Reserved. * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of version 2 of the GNU General Public License * +* as published by the Free Software Foundation. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, contact Novell, Inc. * +* * +* To contact Novell about this file by physical or electronic mail, * +* you may find current contact information at www.novell.com. * +* * +*****************************************************************************/ +/***************************************************************************** +* +* File Description: +* +*****************************************************************************/ + +#include <linux/debugrtl.h> + +#if !defined(_M_IA64) && !defined(__ia64__) \ + && !defined(_M_IX86) && !defined(__i386__) \ + && !defined(_M_AMD64) && !defined(__x86_64__) +asmlinkage DbgQuotRemS dbgDivideS(nint_t numer, nint_t denom) { +DbgQuotRemS sd; + +if (denom ==1 ) + { + sd.quot = numer; + sd.rem =0 ; + } +else if (denom ==-1 ) + { + sd.quot = -numer; + sd.rem =0 ; + } +else + { + sd.quot = numer / denom; + sd.rem = numer % denom; + } + +return sd; +} + +asmlinkage DbgQuotRemU dbgDivideU(nuint_t numer, nuint_t denom) { +DbgQuotRemU ud; + +if (denom ==1 ) + { + ud.quot = numer; + ud.rem =0 ; + } +else + { + ud.quot = numer / denom; + ud.rem = numer % denom; + } +return ud; +} +#endif + +asmlinkage char*dbgCatStr(char*dst, const char*src) { +dbgCopyStr (dst +dbgCountStr (dst), src); +return dst; +} + +#include <linux/module.h> +#define DEBUGRTL_EXPORT (type, name, ...) EXPORT_SYMBOL(name) +#include <linux/debugrtl.h>
include/linux/debugrtl.h new file +170 -0
170 lines not on this page · raw message
PATCH 27/39 NLKD/i386 - run time library
i386-specific implementation of the support routines of NLKD.
(actual patch attached)
i386-specific implementation of the support routines of NLKD.
debug/nlkd/dbgIA32.S new file +721 -0
@@ -0,0 +1,721 @@ +/***************************************************************************** + * + * File Name: dbgIA32.S + * Created by: jbeulich + * %version: 10 % + * %derived_by: jbeulich % + * %date_modified: Wed Oct 05 01:10:16 2005 % + * + ****************************************************************************/ +/***************************************************************************** + * * + * Copyright (c) 2001-2005 Novell, Inc. All Rights Reserved. * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of version 2 of the GNU General Public License * + * as published by the Free Software Foundation. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, contact Novell, Inc. * + * * + * To contact Novell about this file by physical or electronic mail, * + * you may find current contact information at www.novell.com. * + * * + *****************************************************************************/ +/***************************************************************************** + * + * File Description: + * + ****************************************************************************/ + +#include <linux/config.h> +.equiv PROCEDURE_ALIGN, 1 +#include "asm-ia32.h" + +//todo .file "dbgutil" +.text + +// int dbgCompareMem(const void*, const void*, size_t); +.pubproc dbgCompareMem + mov ecx, [esp+3*dword] + EHpush esi + xor eax, eax + EHpush edi + xor edx, edx + mov esi, [esp+3*dword] + mov edi, [esp+4*dword] + repe cmpsb + seta al + EHpop edi + setb dl + EHpop esi + sub eax, edx + ret +.endp dbgCompareMem + +// int dbgCompareStr(const char*, const char*); +.pubproc dbgCompareStr + xor eax, eax + mov ecx, [esp+dword] + mov edx, [esp+2*dword] +0: + mov al, [ecx] + inc ecx + test al, al + jz 1f + cmp al, [edx] + jne 1f + inc edx + jmp 0b +1: + movzx edx, byte ptr [edx] + sub eax, edx + ret +.endp dbgCompareStr + +// void*dbgCopyMem(void*, const void*, size_t); +// Note: The minimum requirements to this routine are that copying between properly +// aligned buffers with a suitable size will be carried out with the maximum +// access granularity possible. +.pubproc dbgCopyMem +#if !defined(CONFIG_REGPARM) || __GNUC__ < 3 + mov ecx, [esp+3*dword] +#endif + EHpush esi + EHpush edi + test cl, byte +#if !defined(CONFIG_REGPARM) || __GNUC__ < 3 + mov edi, [esp+3*dword] + mov esi, [esp+4*dword] + mov eax, edi +#else + mov edi, eax + mov esi, edx +#endif + jz 0f + rep movsb + EHpushState + EHpop edi + EHpop esi + ret +0: + EHpopState + shr ecx, 2 + jnc 1f + adc ecx, ecx + .byte 0x66 +1: + rep movsd + EHpop edi + EHpop esi + ret +.endp dbgCopyMem + +// char*dbgCopyStr(char*, const char*); +.pubproc dbgCopyStr + mov ecx, [esp+2*dword] + mov edx, [esp+dword] + EHpush ecx +0: + mov al, [ecx] + inc ecx + mov [edx], al + inc edx + test al, al + jnz 0b + EHpop eax + ret +.endp dbgCopyStr + +// char*dbgCopyStrP(char*, const char*); +.pubproc dbgCopyStrP + mov ecx, [esp+2*dword] + mov edx, [esp+dword] +0: + mov al, [ecx] + inc ecx + mov [edx], al + inc edx + test al, al + jnz 0b + lea eax, [edx-byte] + ret +.endp dbgCopyStrP + +// unsigned dbgCountBits(uint64_t); +.pubproc dbgCountBits + mov ecx, [esp+dword] + mov edx, [esp+2*dword] + xor eax, eax +0: + shr ecx, 1 + adc eax, 0 + shr edx, 1 + adc eax, 0 + test ecx, ecx + jnz 0b + test edx, edx + jnz 0b + ret +.endp dbgCountBits + +// size_t dbgCountStr(const char*); +.pubproc dbgCountStr + EHpush edi + or ecx, not 0 + xor eax, eax + mov edi, [esp+2*dword] + repne scasb + add ecx, 2 + EHpop edi + sub eax, ecx + ret +.endp dbgCountStr + +// size_t dbgCountWstr(const wchar_t*); +.pubproc dbgCountWstr + EHpush edi + or ecx, not 0 + xor eax, eax + mov edi, [esp+2*dword] + repne scasw + add ecx, 2 + EHpop edi + sub eax, ecx + ret +.endp dbgCountWstr + +// char*dbgFindChar(const char*, char); +.pubproc dbgFindChar + mov eax, [esp+dword] + movzx ecx, byte ptr [esp+2*dword] +0: + movzx edx, byte ptr [eax] + cmp ecx, edx + je 1f + inc eax + test edx, edx + jnz 0b + xor eax, eax +0: + ret +.endp dbgFindChar + +// wchar_t*dbgFindWchar(const wchar_t*, wchar_t); +.pubproc dbgFindWchar + mov eax, [esp+dword] + movzx ecx, word ptr [esp+2*dword] +0: + movzx edx, word ptr [eax] + cmp ecx, edx + je 1f + add eax, word + test edx, edx + jnz 0b + xor eax, eax +1: + ret +.endp dbgFindWchar + +// char*dbgWstr2Str(char*, const wchar_t*); +.pubproc dbgWstr2Str + EHpush ebx + mov bl, '?' + mov ecx, [esp+3*dword] + mov edx, [esp+2*dword] + EHpush ecx +0: + movzx eax, word ptr [ecx] + add ecx, word + cmp eax, 0x7f + cmova eax, ebx + mov [edx], al + inc edx + test eax, eax + jnz 0b + EHpop eax + EHpop ebx + ret +.endp dbgWstr2Str + +// int dbgLower(int); +.pubproc dbgLower + mov eax, [esp+dword] + cmp eax, 'A' + jb 0f + cmp eax, 'Z' + ja 0f + add al, 'a' - 'A' +0: + ret +.endp dbgLower + +// int dbgUpper(int); +.pubproc dbgUpper + mov eax, [esp+dword] + cmp eax, 'a' + jb 0f + cmp eax, 'z' + ja 0f + add al, 'A' - 'a' +0: + ret +.endp dbgUpper + +// void*dbgFillMem(void*, int, size_t); +.pubproc dbgFillMem +#if !defined(CONFIG_REGPARM) || __GNUC__ < 3 + mov ecx, [esp+3*dword] + mov eax, [esp+2*dword] +#else + xchg eax, edx +#endif + jmp 0f +// void*dbgZeroMem(void*, size_t); +.pubentry dbgZeroMem +#if !defined(CONFIG_REGPARM) || __GNUC__ < 3 + mov ecx, [esp+2*dword] +#else + mov ecx, edx + mov edx, eax +#endif + xor eax, eax +0: + EHpush edi +#if !defined(CONFIG_REGPARM) || __GNUC__ < 3 + mov edi, [esp+2*dword] + EHpush edi, FALSE +#else + mov edi, edx +#endif + rep stosb +#if !defined(CONFIG_REGPARM) || __GNUC__ < 3 + EHpop eax +#else + mov eax, edx +#endif + EHpop edi + ret +.endp dbgFillMem + +// uint8_t*dbgFindInt8(const uint8_t*, uint8_t, size_t); +// void*dbgFindByte(const void*, int, size_t); +.pubproc dbgFindInt8 +.pubentry dbgFindByte + mov ecx, [esp+3*dword] + EHpush edi + jecxz 0f + mov edi, [esp+2*dword] + mov al, [esp+3*dword] + repne scasb + lea eax, [edi-byte] + je 1f +0: + xor eax, eax +1: + EHpop edi + ret +.endp dbgFindInt8 + +// uint16_t*dbgFindInt16(const uint16_t*, uint16_t, size_t); +.pubproc dbgFindInt16 + mov ecx, [esp+3*dword] + EHpush edi + jecxz 0f + mov edi, [esp+2*dword] + mov eax, [esp+3*dword] + repne scasw + lea eax, [edi-word] + je 1f +0: + xor eax, eax +1: + EHpop edi + ret +.endp dbgFindInt16 + +// uint32_t*dbgFindInt32(const uint32_t*, uint32_t, size_t); +// nuint_t*dbgFindIntN(const nuint_t*, nuint_t, size_t); +// void**dbgFindPtr(const void**, const void*, size_t); +.pubproc dbgFindInt32 +.pubentry dbgFindIntN +.pubentry dbgFindPtr + mov ecx, [esp+3*dword] + EHpush edi + jecxz 0f + mov edi, [esp+2*dword] + mov eax, [esp+3*dword] + repne scasd + lea eax, [edi-dword] + je 1f +0: + xor eax, eax +1: + EHpop edi + ret +.endp dbgFindInt32 + +// uint64_t dbgMultiply(uint64_t, uint64_t, uint64_t*overflow); +.pubproc dbgMultiply + mov eax, [esp+2*dword] + EHpush edi + mov edi, [esp+6*dword] + mul dword ptr [esp+5*dword] + mov [edi], eax + mov eax, [esp+2*dword] + mov [edi+dword], edx + mul dword ptr [esp+5*dword] + mov ecx, eax + add [edi], edx + mov eax, [esp+3*dword] + adc dword ptr [edi+dword], 0 + mul dword ptr [esp+4*dword] + add ecx, eax + adc [edi], edx + mov eax, [esp+2*dword] + adc dword ptr [edi+dword], 0 + mul dword ptr [esp+4*dword] + add edx, ecx + adc dword ptr [edi], 0 + add dword ptr [edi+dword], 0 + EHpop edi + ret +.endp dbgMultiply + +// nint_t dbgLog2(uint64_t) +.pubproc dbgLog2 + bsr eax, [esp+2*dword] + lea eax, [eax+32] + jnz 0f + bsr eax, [esp+1*dword] + jnz 0f + or eax, not 0 +0: + ret +.endp dbgLog2 + +// uint8_t dbgRotl8(uint8_t, nuint_t); +.pubproc dbgRotl8 + mov cl, [esp+2*dword] + mov al, [esp+dword] + rol al, cl + ret +.endp dbgRotl8 + +// uint8_t dbgRotr8(uint8_t, nuint_t); +.pubproc dbgRotr8 + mov cl, [esp+2*dword] + mov al, [esp+dword] + ror al, cl + ret +.endp dbgRotr8 + +// uint16_t dbgRotl16(uint16_t, nuint_t); +.pubproc dbgRotl16 + mov cl, [esp+2*dword] + mov eax, [esp+dword] + rol ax, cl + ret +.endp dbgRotl16 + +// uint16_t dbgRotr16(uint16_t, nuint_t); +.pubproc dbgRotr16 + mov cl, [esp+2*dword] + mov eax, [esp+dword] + ror ax, cl + ret +.endp dbgRotr16 + +// uint32_t dbgRotl32(uint32_t, nuint_t); +.pubproc dbgRotl32 + mov cl, [esp+2*dword] + mov eax, [esp+dword] + rol eax, cl + ret +.endp dbgRotl32 + +// uint32_t dbgRotr32(uint32_t, nuint_t); +.pubproc dbgRotr32 + mov cl, [esp+2*dword] + mov eax, [esp+dword] + ror eax, cl + ret +.endp dbgRotr32 + +// uint64_t dbgRotl64(uint64_t, nuint_t); +.pubproc dbgRotl64 + mov cl, [esp+3*dword] + mov eax, [esp+dword] + test cl, 0x20 + mov edx, [esp+2*dword] + EHpush ebx + jz 0f + xchg eax, edx +0: + mov ebx, edx + shld edx, eax, cl + shld eax, ebx, cl + EHpop ebx + ret +.endp dbgRotl64 + +// uint64_t dbgRotr64(uint64_t, nuint_t); +.pubproc dbgRotr64 + mov cl, [esp+3*dword] + mov eax, [esp+dword] + test cl, 0x20 + mov edx, [esp+2*dword] + EHpush ebx + jz 0f + xchg eax, edx +0: + mov ebx, eax + shrd eax, edx, cl + shrd edx, ebx, cl + EHpop ebx + ret +.endp dbgRotr64 + +.pubproc dbgDivideU + mov eax, [esp+2*dword] + xor edx, edx + mov ecx, [esp+1*dword] + div dword ptr [esp+3*dword] + mov [ecx], eax + mov [ecx+dword], edx + mov eax, ecx + ret dword +.endp dbgDivideU + +.pubproc dbgDivideS + mov eax, [esp+2*dword] + mov ecx, [esp+1*dword] + cdq + idiv dword ptr [esp+3*dword] + mov [ecx], eax + mov [ecx+dword], edx + mov eax, ecx + ret dword +.endp dbgDivideS + +.pubproc dbg__divdi3 +#if !defined(CONFIG_REGPARM) || __GNUC__ < 3 + mov eax, [esp+1*dword] + mov edx, [esp+2*dword] +# define ARG2_SLOT 3 +#else +# define ARG2_SLOT 1 +#endif + EHpushState + EHpush ebp + EHpush ebx + mov ebp, [esp+(ARG2_SLOT+3)*dword] + mov ebx, [esp+(ARG2_SLOT+2)*dword] + EHpush esi + mov ecx, edx + mov esi, ebp + sar ecx, 31 + sar esi, 31 + xor eax, ecx + xor edx, ecx + xor ebx, esi + xor ebp, esi + sub eax, ecx + sbb edx, ecx + xor ecx, esi + sub ebx, esi + sbb ebp, esi + EHpop esi + jz .LquickDIV + jns .LscaleDIV + // EDX:EAX <= 80000000:00000000, EBP:EBX == 80000000:00000000 + mov eax, edx + xor edx, edx + shr eax, 31 + jmp .LreturnDIV + EHpopState +.pubentry dbg__udivdi3 +#if !defined(CONFIG_REGPARM) || __GNUC__ < 3 + mov eax, [esp+1*dword] + mov edx, [esp+2*dword] +#endif + EHpush ebp + EHpush ebx + xor ecx, ecx + mov ebp, [esp+(ARG2_SLOT+3)*dword] + mov ebx, [esp+(ARG2_SLOT+2)*dword] + test ebp, ebp + jz .LquickDIV + js .LcompareDIV +.LscaleDIV: + EHpush ecx + bsr ecx, ebp + EHpush edx + EHpush eax + inc ecx // number of bits to shift (at most 31) + EHpush ebx, FALSE + shrd ebx, ebp, cl + shrd eax, edx, cl + shr edx, cl + div ebx + EHpop ebx, FALSE + imul ebp, eax // lo(quotient * hi(divisor)) + mov ecx, eax + mul ebx // quotient * lo(divisor) + EHpop ebx, FALSE + add ebp, edx // EBP:EAX = quotient * divisor + sbb ecx, 0 // adjust quotient (if overflow) + xor edx, edx + sub ebx, eax + EHpop ebx, FALSE + mov eax, ecx + sbb ebx, ebp + EHpop ecx + sbb eax, edx // adjust quotient + jmp .LreturnDIV +.LcompareDIV: + sub eax, ebx + mov eax, 0 + sbb edx, ebp + mov edx, eax + sbb eax, -1 + jmp .LreturnDIV +.LquickDIV: + cmp edx, ebx + jb 0f + mov ebp, eax + mov eax, edx + xor edx, edx + div ebx + xchg eax, ebp +0: + div ebx + mov edx, ebp +.LreturnDIV: + xor eax, ecx + EHpop ebx + xor edx, ecx + sub eax, ecx + EHpop ebp + sbb edx, ecx + ret +#undef ARG2_SLOT +.endp dbg__divdi3 + +.pubproc dbg__moddi3 +#if !defined(CONFIG_REGPARM) || __GNUC__ < 3 + mov eax, [esp+1*dword] + mov edx, [esp+2*dword] +# define ARG2_SLOT 3 +#else +# define ARG2_SLOT 1 +#endif + EHpushState + EHpush ebp + EHpush ebx + mov ebp, [esp+(ARG2_SLOT+3)*dword] + mov ebx, [esp+(ARG2_SLOT+2)*dword] + EHpush esi + mov ecx, edx + mov esi, ebp + sar ecx, 31 + sar esi, 31 + xor eax, ecx + xor edx, ecx + xor ebx, esi + xor ebp, esi + sub eax, ecx + sbb edx, ecx + sub ebx, esi + sbb ebp, esi + EHpop esi + jz .LquickMOD + jns .LscaleMOD + // EDX:EAX <= 80000000:00000000, EBP:EBX == 80000000:00000000 + not ebp + and edx, ebp + jmp .LreturnMOD + EHpopState +.pubentry dbg__umoddi3 +#if !defined(CONFIG_REGPARM) || __GNUC__ < 3 + mov eax, [esp+1*dword] + mov edx, [esp+2*dword] +#endif + EHpush ebp + EHpush ebx + xor ecx, ecx + mov ebp, [esp+(ARG2_SLOT+3)*dword] + mov ebx, [esp+(ARG2_SLOT+2)*dword] + test ebp, ebp + jz .LquickMOD + js .LcompareMOD +.LscaleMOD: + EHpush ecx + bsr ecx, ebp + EHpush esi + mov esi, edx + EHpush edi + inc ecx // number of bits to shift (at most 31) + mov edi, eax + EHpush ebx, FALSE + shrd ebx, ebp, cl + shrd eax, edx, cl + shr edx, cl + mov ecx, [esp] + div ebx + mov [esp], ebp + imul ebp, eax // lo(quotient * hi(divisor)) + mul ecx // quotient * lo(divisor) + add edx, ebp // EDX:EAX = quotient * divisor + sbb ebp, ebp // record overflow + sub edi, eax + sbb esi, edx + mov eax, ecx + sbb ebp, 0 // accumulate overflow + EHpop edx + and eax, ebp + and edx, ebp + add eax, edi + EHpop edi + adc edx, esi + EHpop esi + EHpop ecx + jmp .LreturnMOD +.LcompareMOD: + sub eax, ebx + EHpush esi + sbb edx, ebp + sbb esi, esi + and ebx, esi + and ebp, esi + add eax, ebx + EHpop esi + adc edx, ebp + jmp .LreturnMOD +.LquickMOD: + cmp edx, ebx + jb 0f + mov ebp, eax + mov eax, edx + xor edx, edx + div ebx + xchg eax, ebp +0: + div ebx + mov eax, edx + xor edx, edx +.LreturnMOD: + xor eax, ecx + EHpop ebx + xor edx, ecx + sub eax, ecx + EHpop ebp + sbb edx, ecx + ret +#undef ARG2_SLOT +.endp dbg__moddi3
PATCH 28/39 NLKD/x86-64 - run time library
x86_64-specific implementation of the support routines of NLKD.
(actual patch attached)
x86_64-specific implementation of the support routines of NLKD.
debug/nlkd/dbgAMD64.S new file +403 -0
@@ -0,0 +1,403 @@ +/***************************************************************************** + * + * File Name: dbgAMD64.S + * Created by: jbeulich + * %version: 8 % + * %derived_by: jbeulich % + * %date_modified: Wed Oct 05 01:08:52 2005 % + * + ****************************************************************************/ +/***************************************************************************** + * * + * Copyright (c) 2002-2005 Novell, Inc. All Rights Reserved. * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of version 2 of the GNU General Public License * + * as published by the Free Software Foundation. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, contact Novell, Inc. * + * * + * To contact Novell about this file by physical or electronic mail, * + * you may find current contact information at www.novell.com. * + * * + *****************************************************************************/ +/***************************************************************************** + * + * File Description: + * + ****************************************************************************/ + +#include <linux/config.h> +.equiv PROCEDURE_ALIGN, 1 +#include "asm-amd64.h" + +// int dbgCompareMem(const void*, const void*, size_t); +.pubproc dbgCompareMem + mov rcx, rdx + xchg rsi, rdi + xor eax, eax + xor edx, edx + repe cmpsb + seta al + setb dl + sub eax, edx + ret +.endp dbgCompareMem + +// int dbgCompareStr(const char*, const char*); +.pubproc dbgCompareStr + xor eax, eax +0: + mov al, [rdi] + inc rdi + test al, al + jz 1f + cmp al, [rsi] + jne 1f + inc rsi + jmp 0b +1: + movzx edx, byte ptr [rsi] + sub eax, edx + ret +.endp dbgCompareStr + +// void*dbgCopyMem(void*, const void*, size_t); +// Note: The minimum requirements to this routine are that copying between properly +// aligned buffers with a suitable size will be carried out with the maximum +// access granularity possible. +.pubproc dbgCopyMem + mov rcx, rdx + test dl, byte + mov rax, rdi + jz 0f + rep movsb + ret +0: + test dl, word or dword + jz 2f + shr rcx, 2 + jnc 1f + adc rcx, rcx + .byte 0x66 +1: + rep movsd + ret +2: + shr rcx, 3 + rep movsq + ret +.endp dbgCopyMem + +// char*dbgCopyStr(char*, const char*); +.pubproc dbgCopyStr + mov rax, rdi +0: + cmp byte ptr [rsi], 0 + movsb + jne 0b + ret +.endp dbgCopyStr + +// char*dbgCopyStrP(char*, const char*); +.pubproc dbgCopyStrP +0: + lodsb + stosb + test al, al + jnz 0b + lea rax, [rdi-byte] + ret +.endp dbgCopyStrP + +// unsigned dbgCountBits(uint64_t); +.pubproc dbgCountBits + shld rsi, rdi, 32 + xor eax, eax +0: + shr edi, 1 + adc eax, 0 + shr esi, 1 + adc eax, 0 + test edi, edi + jnz 0b + test esi, esi + jnz 0b + ret +.endp dbgCountBits + +// size_t dbgCountStr(const char*); +.pubproc dbgCountStr + or rcx, not 0 + xor eax, eax + repne scasb + add rcx, 2 + sub rax, rcx + ret +.endp dbgCountStr + +// size_t dbgCountWstr(const wchar_t*); +.pubproc dbgCountWstr + or rcx, not 0 + xor eax, eax + repne scasw + add rcx, 2 + sub rax, rcx + ret +.endp dbgCountWstr + +// char*dbgFindChar(const char*, char); +.pubproc dbgFindChar +0: + mov dl, [rdi] + cmp sil, dl + je 1f + inc rdi + test dl, dl + jnz 0b + xor eax, eax + ret +1: + mov rax, rdi + ret +.endp dbgFindChar + +// wchar_t*dbgFindWchar(const wchar_t*, wchar_t); +.pubproc dbgFindWchar +0: + mov dx, [rdi] + cmp si, dx + je 1f + add rdi, word + test dx, dx + jnz 0b + xor eax, eax + ret +1: + mov rax, rdi + ret +.endp dbgFindWchar + +// char*dbgWstr2Str(char*, const wchar_t*); +.pubproc dbgWstr2Str + mov rax, rdi + mov cl, '?' +0: + movzx edx, word ptr [rsi] + add rsi, word + cmp edx, 0x7f + cmova edx, ecx + mov [rdi], dl + inc rdi + test edx, edx + jnz 0b + ret +.endp dbgWstr2Str + +// int dbgLower(int); +.pubproc dbgLower + mov eax, edi + cmp edi, 'A' + jb 0f + cmp edi, 'Z' + ja 0f + add al, 'a' - 'A' +0: + ret +.endp dbgLower + +// int dbgUpper(int); +.pubproc dbgUpper + mov eax, edi + cmp edi, 'a' + jb 0f + cmp edi, 'z' + ja 0f + add al, 'A' - 'a' +0: + ret +.endp dbgUpper + +// void*dbgFillMem(void*, int, size_t); +.pubproc dbgFillMem + mov rcx, rdx + mov eax, esi + jmp 0f +// void*dbgZeroMem(void*, size_t); +.pubentry dbgZeroMem + mov ecx, esi + xor eax, eax +0: + mov rdx, rdi + rep stosb + mov rax, rdx + ret +.endp dbgFillMem + +// uint8_t*dbgFindInt8(const uint8_t*, uint8_t, size_t); +// void*dbgFindByte(const void*, int, size_t); +.pubproc dbgFindInt8 +.pubentry dbgFindByte + mov rcx, rdx + jrcxz 0f + mov eax, esi + repne scasb + lea rax, [rdi-byte] + je 1f +0: + xor eax, eax +1: + ret +.endp dbgFindInt8 + +// uint16_t*dbgFindInt16(const uint16_t*, uint16_t, size_t); +.pubproc dbgFindInt16 + mov rcx, rdx + jrcxz 0f + mov eax, esi + repne scasw + lea rax, [rdi-word] + je 1f +0: + xor eax, eax +1: + ret +.endp dbgFindInt16 + +// uint32_t*dbgFindInt32(const uint32_t*, uint32_t, size_t); +// nuint_t*dbgFindIntN(const nuint_t*, nuint_t, size_t); +.pubproc dbgFindInt32 +.pubentry dbgFindIntN + mov rcx, rdx + jrcxz 0f + mov eax, esi + repne scasd + lea rax, [rdi-dword] + je 1f +0: + xor eax, eax +1: + ret +.endp dbgFindInt32 + +// uint64_t*dbgFindInt64(const uint64_t*, uint64_t, size_t); +// void**dbgFindPtr(const void**, const void*, size_t); +.pubproc dbgFindInt64 +.pubentry dbgFindPtr + mov rcx, rdx + jrcxz 0f + mov rax, rsi + repne scasq + lea rax, [rdi-qword] + je 1f +0: + xor eax, eax +1: + ret +.endp dbgFindInt64 + +// uint64_t dbgMultiply(uint64_t, uint64_t, uint64_t*overflow); +.pubproc dbgMultiply + mov rax, rdi + mov rcx, rdx + mul rsi + mov [rcx], rdx + ret +.endp dbgMultiply + +// nint_t dbgLog2(uint64_t) +.pubproc dbgLog2 + bsr rax, rdi + jnz 0f + or eax, not 0 +0: + ret +.endp dbgLog2 + +// uint8_t dbgRotl8(uint8_t, nuint_t); +.pubproc dbgRotl8 + mov eax, edi + mov ecx, esi + rol al, cl + ret +.endp dbgRotl8 + +// uint8_t dbgRotr8(uint8_t, nuint_t); +.pubproc dbgRotr8 + mov eax, edi + mov ecx, esi + ror al, cl + ret +.endp dbgRotr8 + +// uint16_t dbgRotl16(uint16_t, nuint_t); +.pubproc dbgRotl16 + mov eax, edi + mov ecx, esi + rol ax, cl + ret +.endp dbgRotl16 + +// uint16_t dbgRotr16(uint16_t, nuint_t); +.pubproc dbgRotr16 + mov eax, edi + mov ecx, esi + ror ax, cl + ret +.endp dbgRotr16 + +// uint32_t dbgRotl32(uint32_t, nuint_t); +.pubproc dbgRotl32 + mov eax, edi + mov ecx, esi + rol eax, cl + ret +.endp dbgRotl32 + +// uint32_t dbgRotr32(uint32_t, nuint_t); +.pubproc dbgRotr32 + mov eax, edi + mov ecx, esi + ror eax, cl + ret +.endp dbgRotr32 + +// uint64_t dbgRotl64(uint64_t, nuint_t); +.pubproc dbgRotl64 + mov rax, rdi + mov ecx, esi + rol rax, cl + ret +.endp dbgRotl64 + +// uint64_t dbgRotr64(uint64_t, nuint_t); +.pubproc dbgRotr64 + mov rax, rdi + mov ecx, esi + ror rax, cl + ret +.endp dbgRotr64 + +.pubproc dbgDivideU + mov eax, edi + xor edx, edx + div esi + shl rdx, 32 + or rax, rdx + ret +.endp dbgDivideU + +.pubproc dbgDivideS + mov eax, edi + cdq + idiv esi + shl rdx, 32 + or rax, rdx + ret +.endp dbgDivideS
Re: [PATCH 28/39] NLKD/x86-64 - run time library
Quoted 1 line · Jan Beulich
x86_64-specific implementation of the support routines of NLKD.
Same comment as for patch 25.
-Andi
A message that is not in the archive (sent off-list or not yet received): [email protected]
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 34/39 NLKD/x86 - Console Debug Agent
The x86-dependent (32- and 64-bit) part of the Console Debug Agent of NLKD.
(actual patch attached)
The x86-dependent (32- and 64-bit) part of the Console Debug Agent of NLKD.
debug/nlkd/cda/x86_1.c new file +535 -0
@@ -0,0 +1,535 @@ +/***************************************************************************** +* +* File Name: x86_1.c +* Created by: Jan Beulich +* Date created: 08Mar2001 +* +* %version: 7 % +* %derived_by: jbeulich % +* %date_modified: Thu Sep 01 00:37:12 2005 % +* +*****************************************************************************/ +/***************************************************************************** +* * +* Copyright (c) 2001-2005 Novell, Inc. All Rights Reserved. * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of version 2 of the GNU General Public License * +* as published by the Free Software Foundation. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, contact Novell, Inc. * +* * +* To contact Novell about this file by physical or electronic mail, * +* you may find current contact information at www.novell.com. * +* * +*****************************************************************************/ +/***************************************************************************** +* +* File Description: +* +*****************************************************************************/ + +NAME_TABLE(80_, "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp"); +#define names_81_ names_80_ +#define names_82_ names_80_ +#define names_83_ names_80_ +NAME_TABLE(8F_, "pop", NULL, NULL, NULL, NULL, NULL, NULL, NULL); +NAME_TABLE (C0_ ,"rol" ,"ror" ,"rcl" ,"rcr" ,"shl" ,"shr" ,"sal" ,"sar" ); +#define names_C1_ names_C0_ +NAME_TABLE (C6_ ,"mov" ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ); +#define names_C7_ names_C6_ +#define names_D0_ names_C0_ +#define names_D1_ names_C0_ +#define names_D2_ names_C0_ +#define names_D3_ names_C0_ +NAME_TABLE (D8m,"fadd" ,"fmul" ,"fcom" ,"fcomp" ,"fsub" ,"fsubr" ,"fdiv" ,"fdivr" ); +NAME_TABLE (D9r2,"fnop" ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ); +NAME_TABLE (D9r4,"fchs" ,"fabs" ,NULL ,NULL ,"ftst" ,"fxam" ,NULL ,NULL ); +NAME_TABLE (D9r5,"fld1" ,"fldl2t" ,"fldl2e" ,"fldpi" ,"fldlg2" ,"fldln2" ,"fldz" ,NULL ); +NAME_TABLE (D9r6,"f2xm1" ,"fyl2x" ,"fptan" ,"fpatan" ,"fxtract" ,"fprem1" ,"fdecstp" ,"fincstp" ); +NAME_TABLE (D9r7,"fprem" ,"fyl2xp1" ,"fsqrt" ,"fsincos" ,"frndint" ,"fscale" ,"fsin" ,"fcos" ); +NAME_TABLE (DAm,"fiadd" ,"fimul" ,"ficom" ,"ficomp" ,"fisub" ,"fisubr" ,"fidiv" ,"fidivr" ); +NAME_TABLE (DAr5,NULL ,"fucompp" ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ); +NAME_TABLE (DBr4,"fneni" ,"fndisi" ,"fnclex" ,"fninit" ,"fsetpm" ,"frstpm" ,NULL ,NULL ); +#define names_DCm names_D8m +NAME_TABLE (DCr,"fadd" ,"fmul" ,NULL ,NULL ,"fsubr" ,"fsub" ,"fdivr" ,"fdiv" ); +NAME_TABLE (DEr3,NULL ,"fcompp" ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ); +#define names_DEm names_DAm +NAME_TABLE (DFr4,"fnstsw" ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ); +NAME_TABLE (FE_ ,"inc" ,"dec" ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ); + +static const OpcodeInfo branch_00[8 ] = { +LEAF_NORMAL (00 ,"add" , rm_r, byte, none, none, sflags, none, none, none), +LEAF_NORMAL (01 ,"add" , rm_r, offset, none, none, sflags, none, none, none), +LEAF_NORMAL (02 ,"add" , r_rm, byte, none, none, sflags, none, none, none), +LEAF_NORMAL (03 ,"add" , r_rm, offset, none, none, sflags, none, none, none), +LEAF_NORMAL (04 ,"add" , accum, byte, imm, byte, sflags, none, none, none), +LEAF_NORMAL (05 ,"add" , accum, offset, imm, offset32, sflags, none, none, none), +#ifndef X86_64 +LEAF_NORMAL (06 ,"push" , reg, ptr, none, none,SP , none, none, none), +LEAF_NORMAL (07 ,"pop" , reg, ptr, none, word, tos, none, none, none)}, +#else + LEAF_NORMAL(06, NULL, none, none, none, none, none, none, none, none), + LEAF_NORMAL(07, NULL, none, none, none, none, none, none, none, none)}, +#endif +branch_08[8 ] = { +LEAF_NORMAL (08 ,"or" , rm_r, byte, none, none, sflags, none, none, none), +LEAF_NORMAL (09 ,"or" , rm_r, offset, none, none, sflags, none, none, none), + LEAF_NORMAL(0A, "or", r_rm, byte, none, none, sflags, none, none, none), +LEAF_NORMAL (0B ,"or" , r_rm, offset, none, none, sflags, none, none, none), + LEAF_NORMAL(0C, "or", accum, byte, imm, byte, sflags, none, none, none), +LEAF_NORMAL (0D ,"or" , accum, offset, imm, offset32, sflags, none, none, none), +#ifndef X86_64 +LEAF_NORMAL (0E ,"push" , reg, ptr, none, none,SP , none, none, none), +#else +LEAF_NORMAL (0E ,NULL , none, none, none, none, none, none, none, none), +#endif +LEAF_NORMAL (0F ,NULL , none, none, none, none, none, none, none, none)}, +branch_10[8 ] = { +LEAF_NORMAL (10 ,"adc" , rm_r, byte, none, none, sflags, none, none, none), +LEAF_NORMAL (11 ,"adc" , rm_r, offset, none, none, sflags, none, none, none), +LEAF_NORMAL (12 ,"adc" , r_rm, byte, none, none, sflags, none, none, none), +LEAF_NORMAL (13 ,"adc" , r_rm, offset, none, none, sflags, none, none, none), +LEAF_NORMAL (14 ,"adc" , accum, byte, imm, byte, sflags, none, none, none), +LEAF_NORMAL (15 ,"adc" , accum, offset, imm, offset32, sflags, none, none, none), +#ifndef X86_64 +LEAF_NORMAL (16 ,"push" , reg, ptr, none, none,SP , none, none, none), +LEAF_NORMAL (17 ,"pop" , reg, ptr, none, word, tos, none, none, none)}, +#else + LEAF_NORMAL(16, NULL, none, none, none, none, none, none, none, none), + LEAF_NORMAL(17, NULL, none, none, none, none, none, none, none, none)}, +#endif +branch_18[8 ] = { +LEAF_NORMAL (18 ,"sbb" , rm_r, byte, none, none, sflags, none, none, none), +LEAF_NORMAL (19 ,"sbb" , rm_r, offset, none, none, sflags, none, none, none), + LEAF_NORMAL(1A, "sbb", r_rm, byte, none, none, sflags, none, none, none), +LEAF_NORMAL (1B ,"sbb" , r_rm, offset, none, none, sflags, none, none, none), + LEAF_NORMAL(1C, "sbb", accum, byte, imm, byte, sflags, none, none, none), +LEAF_NORMAL (1D ,"sbb" , accum, offset, imm, offset32, sflags, none, none, none), +#ifndef X86_64 +LEAF_NORMAL (1E ,"push" , reg, ptr, none, none,SP , none, none, none), +LEAF_NORMAL (1F ,"pop" , reg, ptr, none, word, tos, none, none, none)}, +#else + LEAF_NORMAL(1E, NULL, none, none, none, none, none, none, none, none), + LEAF_NORMAL(1F, NULL, none, none, none, none, none, none, none, none)}, +#endif +branch_20[8 ] = { +LEAF_NORMAL (20 ,"and" , rm_r, byte, none, none, sflags, none, none, none), +LEAF_NORMAL (21 ,"and" , rm_r, offset, none, none, sflags, none, none, none), +LEAF_NORMAL (22 ,"and" , r_rm, byte, none, none, sflags, none, none, none), +LEAF_NORMAL (23 ,"and" , r_rm, offset, none, none, sflags, none, none, none), +LEAF_NORMAL (24 ,"and" , accum, byte, imm, byte, sflags, none, none, none), +LEAF_NORMAL (25 ,"and" , accum, offset, imm, offset32, sflags, none, none, none), +LEAF_NORMAL (26 ,NULL , none, none, none, none, none, none, none, none), +#ifndef X86_64 +LEAF_NORMAL (27 ,"daa" , none, none, none, none,AX , sflags, none, none)}, +#else + LEAF_NORMAL(27, NULL, none, none, none, none, none, none, none, none)}, +#endif +branch_28[8 ] = { +LEAF_NORMAL (28 ,"sub" , rm_r, byte, none, none, sflags, none, none, none), +LEAF_NORMAL (29 ,"sub" , rm_r, offset, none, none, sflags, none, none, none), + LEAF_NORMAL(2A, "sub", r_rm, byte, none, none, sflags, none, none, none), +LEAF_NORMAL (2B ,"sub" , r_rm, offset, none, none, sflags, none, none, none), + LEAF_NORMAL(2C, "sub", accum, byte, imm, byte, sflags, none, none, none), +LEAF_NORMAL (2D ,"sub" , accum, offset, imm, offset32, sflags, none, none, none), +LEAF_NORMAL (2E ,NULL , none, none, none, none, none, none, none, none), +#ifndef X86_64 +LEAF_NORMAL (2F ,"das" , none, none, none, none,AX , sflags, none, none)}, +#else + LEAF_NORMAL(2F, NULL, none, none, none, none, none, none, none, none)}, +#endif +branch_30[8 ] = { +LEAF_NORMAL (30 ,"xor" , rm_r, byte, none, none, sflags, none, none, none), +LEAF_NORMAL (31 ,"xor" , rm_r, offset, none, none, sflags, none, none, none), +LEAF_NORMAL (32 ,"xor" , r_rm, byte, none, none, sflags, none, none, none), +LEAF_NORMAL (33 ,"xor" , r_rm, offset, none, none, sflags, none, none, none), +LEAF_NORMAL (34 ,"xor" , accum, byte, imm, byte, sflags, none, none, none), +LEAF_NORMAL (35 ,"xor" , accum, offset, imm, offset32, sflags, none, none, none), +LEAF_NORMAL (36 ,NULL , none, none, none, none, none, none, none, none), +#ifndef X86_64 +LEAF_NORMAL (37 ,"aaa" , none, none, none, none,AX , sflags, none, none)}, +#else + LEAF_NORMAL(37, NULL, none, none, none, none, none, none, none, none)}, +#endif +branch_38[8 ] = { +LEAF_NORMAL (38 ,"cmp" , rm_r, byte, none, none, sflags, none, none, none), +LEAF_NORMAL (39 ,"cmp" , rm_r, offset, none, none, sflags, none, none, none), + LEAF_NORMAL(3A, "cmp", r_rm, byte, none, none, sflags, none, none, none), +LEAF_NORMAL (3B ,"cmp" , r_rm, offset, none, none, sflags, none, none, none), + LEAF_NORMAL(3C, "cmp", accum, byte, imm, byte, sflags, none, none, none), +LEAF_NORMAL (3D ,"cmp" , accum, offset, imm, offset32, sflags, none, none, none), +LEAF_NORMAL (3E ,NULL , none, none, none, none, none, none, none, none), +#ifndef X86_64 +LEAF_NORMAL (3F ,"aas" , none, none, none, none,AX , sflags, none, none)}, +#else + LEAF_NORMAL(3F, NULL, none, none, none, none, none, none, none, none)}, +#endif +branch_60[8 ] = { +#ifndef X86_64 +LEAF_NORMAL (60 ,"pusha" , none, none, none, none, GRs, none, none, opsz), +LEAF_NORMAL (61 ,"popa" , none, none, none, none, GRs, none, none, opsz), + LEAF_NORMAL(62, "bound", r, offset, mm, 2offsets, none, none, none, none), +LEAF_NORMAL (63 ,"arpl" , rm_r, offset, none, none, none, none, none, none), +#else +LEAF_NORMAL (60 ,NULL , none, none, none, none, none, none, none, none), +LEAF_NORMAL (61 ,NULL , none, none, none, none, none, none, none, none), +LEAF_NORMAL (62 ,NULL , none, none, none, none, none, none, none, none), +LEAF_NORMAL (63 ,"movsx" , r, offset, rm, dword, none, none, none, none), +#endif +LEAF_NORMAL (64 ,NULL , none, none, none, none, none, none, none, none), +LEAF_NORMAL (65 ,NULL , none, none, none, none, none, none, none, none), +LEAF_NORMAL (66 ,NULL , none, none, none, none, none, none, none, none), +LEAF_NORMAL (67 ,NULL , none, none, none, none, none, none, none, none)}, +branch_68[8 ] = { +LEAF_NORMAL (68 ,"push" , imm, offset64, none, none,SP , none, none, none), +LEAF_NORMAL (69 ,"imul" , r_rm, offset, imm, offset32, sflags, none, none, imul), + LEAF_NORMAL(6A, "push", simm, offset, none, none, SP, none, none, none), +LEAF_NORMAL (6B ,"imul" , r_rm, offset, simm, offset, sflags, none, none, imul), + LEAF_NORMAL(6C, "ins", str_d, byte, cl_dx, word, none, none, none, string), +LEAF_NORMAL (6D ,"ins" , str_d, offset32, cl_dx, word, none, none, none, string), +LEAF_NORMAL (6E ,"outs" , cl_dx, word, str_s, byte, none, none, none, string), +LEAF_NORMAL (6F ,"outs" , cl_dx, word, str_s, offset32, none, none, none, string)}, +branch_80[8 ] = { + NAME_NORMAL(80_, rm, byte, imm, byte, sflags, none, none), + NAME_NORMAL(81_, rm, offset, imm, offset32, sflags, none, none), +LEAF_NORMAL (82 ,NULL , none, none, none, none, none, none, none, none), + NAME_NORMAL(83_, rm, offset, simm, offset, sflags, none, none), +LEAF_NORMAL (84 ,"test" , rm_r, byte, none, none, sflags, none, none, none), +LEAF_NORMAL (85 ,"test" , rm_r, offset, none, none, sflags, none, none, none), +LEAF_NORMAL (86 ,"xchg" , rm_r, byte, none, none, none, none, none, none), +LEAF_NORMAL (87 ,"xchg" , rm_r, offset, none, none, none, none, none, none)}, +regmem_8C[2 ] = { + LEAF_NORMAL(8Cm, "mov", mm, word, r, ptr, none, none, nowidth, none), + LEAF_NORMAL(8Cr, "mov", rr, offset, r, ptr, none, none, none, none)}, +regmem_8E[2 ] = { + LEAF_NORMAL(8Em, "mov", r, ptr, mm, word, none, none, nowidth, none), + LEAF_NORMAL(8Er, "mov", r, ptr, rr, offset, none, none, none, none)}, +branch_88[8 ] = { +LEAF_NORMAL (88 ,"mov" , rm_r, byte, none, none, none, none, none, none), +LEAF_NORMAL (89 ,"mov" , rm_r, offset, none, none, none, none, none, none), + LEAF_NORMAL(8A, "mov", r_rm, byte, none, none, none, none, none, none), +LEAF_NORMAL (8B ,"mov" , r_rm, offset, none, none, none, none, none, none), + REGMEM_ENTRY(8C, normal), +LEAF_NORMAL (8D ,"lea" , r, offset, mm, none, none, none, none, none), +REGMEM_ENTRY (8E , normal), + NAME_NORMAL(8F_, rm, offset64, none, offset64, tos, none, none)}, +branch_90[8 ] = { +LEAF_NORMAL (90 ,"nop" , none, none, none, none, none, none, none, none), +LEAF_NORMAL (91 ,"xchg" , accum, offset, reg, offset, none, none, none, none), +LEAF_NORMAL (92 ,"xchg" , accum, offset, reg, offset, none, none, none, none), +LEAF_NORMAL (93 ,"xchg" , accum, offset, reg, offset, none, none, none, none), +LEAF_NORMAL (94 ,"xchg" , accum, offset, reg, offset, none, none, none, none), +LEAF_NORMAL (95 ,"xchg" , accum, offset, reg, offset, none, none, none, none), +LEAF_NORMAL (96 ,"xchg" , accum, offset, reg, offset, none, none, none, none), +LEAF_NORMAL (97 ,"xchg" , accum, offset, reg, offset, none, none, none, none)}, +branch_98[8 ] = { +#ifndef X86_64 +LEAF_NORMAL (98 ,"cbw" , none, none, none, none,AX , none, none, none), +LEAF_NORMAL (99 ,"cwd" , none, none, none, none,DX_AX , none, none, none), + LEAF_NORMAL(9A, "call", imm, ptr, none, none, SP, CS, none, none), +#else +LEAF_NORMAL (98 ,"cwde" , none, none, none, none,AX , none, none, none), +LEAF_NORMAL (99 ,"cdq" , none, none, none, none,DX_AX , none, none, none), + LEAF_NORMAL(9A, NULL, none, none, none, none, none, none, none, none), +#endif +LEAF_NORMAL (9B ,"wait" , none, none, none, none, none, none, none, none), + LEAF_NORMAL(9C, "pushf", none, none, none, none, SP, flags, none, opsz), +LEAF_NORMAL (9D ,"popf" , none, none, none, offset64, tos, flags, none, opsz), +LEAF_NORMAL (9E ,"sahf" , none, none, none, none,AX , sflags, none, none), +LEAF_NORMAL (9F ,"lahf" , none, none, none, none, sflags,AX , none, none)}, +branch_A0[8 ] = { +LEAF_NORMAL (A0 ,"mov" , accum, byte, mem, byte, none, none, none, none), +LEAF_NORMAL (A1 ,"mov" , accum, offset, mem, offset, none, none, none, none), +LEAF_NORMAL (A2 ,"mov" , mem, byte, accum, byte, none, none, none, none), +LEAF_NORMAL (A3 ,"mov" , mem, offset, accum, offset, none, none, none, none), +LEAF_NORMAL (A4 ,"movs" , str_d, byte, str_s, byte, none, none, none, string), +LEAF_NORMAL (A5 ,"movs" , str_d, offset, str_s, offset, none, none, none, string), +LEAF_NORMAL (A6 ,"cmps" , str_s, byte, str_d, byte, sflags, none, none, string), +LEAF_NORMAL (A7 ,"cmps" , str_s, offset, str_d, offset, sflags, none, none, string)}, +branch_A8[8 ] = { +LEAF_NORMAL (A8 ,"test" , accum, byte, imm, byte, sflags, none, none, none), +LEAF_NORMAL (A9 ,"test" , accum, offset, imm, offset32, sflags, none, none, none), +LEAF_NORMAL (AA ,"stos" , str_d, byte, none, none, none, none, none, string), +LEAF_NORMAL (AB ,"stos" , str_d, offset, none, none, none, none, none, string), +LEAF_NORMAL (AC ,"lods" , str_s, byte, none, none, none, none, none, string), +LEAF_NORMAL (AD ,"lods" , str_s, offset, none, none, none, none, none, string), +LEAF_NORMAL (AE ,"scas" , str_d, byte, none, none, sflags, none, none, string), +LEAF_NORMAL (AF ,"scas" , str_d, offset, none, none, sflags, none, none, string)}, +branch_C0[8 ] = { +NAME_NORMAL (C0_ , rm, byte, imm, byte, sflags, none, none), +NAME_NORMAL (C1_ , rm, offset, imm, byte, sflags, none, none), +LEAF_NORMAL (C2 ,"ret" , imm, word, none, offset64, tos, none, none, none), +LEAF_NORMAL (C3 ,"ret" , none, none, none, offset64, tos, none, none, none), +#ifndef X86_64 +LEAF_NORMAL (C4 ,"les" , r, offset, mm, ptr,ES , none, nowidth, none), +LEAF_NORMAL (C5 ,"lds" , r, offset, mm, ptr,DS , none, nowidth, none), +#else +LEAF_NORMAL (C4 ,NULL , none, none, none, none, none, none, none, none), +LEAF_NORMAL (C5 ,NULL , none, none, none, none, none, none, none, none), +#endif +NAME_NORMAL (C6_ , rm, byte, imm, byte, none, none, none), +NAME_NORMAL (C7_ , rm, offset, imm, offset32, none, none, none)}, +branch_C8[8 ] = { +LEAF_NORMAL (C8 ,"enter" , imm, word, imm, byte,BP ,SP , none, opsz), +LEAF_NORMAL (C9 ,"leave" , none, none, none, none,SP ,BP , none, opsz), +LEAF_NORMAL (CA ,"retf" , imm, word, none, ptr, tos,CS , none, none), +LEAF_NORMAL (CB ,"retf" , none, none, none, ptr, tos,CS , none, none), +LEAF_NORMAL (CC ,"int3" , none, none, none, none,SP , int, none, none), +LEAF_NORMAL (CD ,"int" , imm, byte, none, none,SP , int, none, none), +#ifndef X86_64 +LEAF_NORMAL (CE ,"into" , none, none, none, none,SP , int, none, none), +#else +LEAF_NORMAL (CE ,NULL , none, none, none, none, none, none, none, none), +#endif +LEAF_NORMAL (CF ,"iret" , none, none, none, ptr, tos, int, none, opsz)}, +branch_D0[8 ] = { +NAME_NORMAL (D0_ , rm, byte, imm, none, sflags, none, none), +NAME_NORMAL (D1_ , rm, offset, imm, none, sflags, none, none), +NAME_NORMAL (D2_ , rm, byte, cl_dx, byte, sflags, none, none), +NAME_NORMAL (D3_ , rm, offset, cl_dx, byte, sflags, none, none), +#ifndef X86_64 +LEAF_NORMAL (D4 ,"aam" , imm, byte, none, none,AX , sflags, none, none), +LEAF_NORMAL (D5 ,"aad" , imm, byte, none, none,AX , sflags, none, none), +LEAF_NORMAL (D6 ,"salc" , none, none, none, none,AX , sflags, none, none), +#else +LEAF_NORMAL (D4 ,NULL , none, none, none, none, none, none, none, none), +LEAF_NORMAL (D5 ,NULL , none, none, none, none, none, none, none, none), +LEAF_NORMAL (D6 ,NULL , none, none, none, none, none, none, none, none), +#endif +LEAF_NORMAL (D7 ,"xlat" , str_s, byte, none, none,AX , none, none, string)}, +branch_D9m[8 ] = { +LEAF_NORMAL (D9m0,"fld" , mm, real4, none, none,ST0 , none, none, none), +LEAF_NORMAL (D9m1,NULL , none, none, none, none, none, none, none, none), +LEAF_NORMAL (D9m2,"fst" , mm, real4, none, none,ST0 , none, none, none), +LEAF_NORMAL (D9m3,"fstp" , mm, real4, none, none,ST0 , none, none, none), +LEAF_NORMAL (D9m4,"fldenv" , mm, none, none, none, none, none, none, none), +LEAF_NORMAL (D9m5,"fldcw" , mm, word, none, none, fcw, none, nowidth, none), +LEAF_NORMAL (D9m6,"fnstenv" , mm, none, none, none, none, none, none, wait), +LEAF_NORMAL (D9m7,"fnstcw" , mm, word, none, none, fcw, none, nowidth, wait)}, +branch_DBm[8 ] = { +LEAF_NORMAL (DBm0,"fild" , mm, dword, none, none,ST0 , none, none, none), +LEAF_NORMAL (DBm1,"fisttp" , mm, dword, none, none,ST0 , none, none, none), +LEAF_NORMAL (DBm2,"fist" , mm, dword, none, none,ST0 , none, none, none), +LEAF_NORMAL (DBm3,"fistp" , mm, dword, none, none,ST0 , none, none, none), +LEAF_NORMAL (DBm4,NULL , none, none, none, none, none, none, none, none), +LEAF_NORMAL (DBm5,"fld" , mm, real10, none, none,ST0 , none, none, none), +LEAF_NORMAL (DBm6,NULL , none, none, none, none, none, none, none, none), +LEAF_NORMAL (DBm7,"fstp" , mm, real10, none, none,ST0 , none, none, none)}, +branch_DDm[8 ] = { +LEAF_NORMAL (DDm0,"fld" , mm, real8, none, none,ST0 , none, none, none), +LEAF_NORMAL (DDm1,"fisttp" , mm, qword, none, none,ST0 , none, none, none), +LEAF_NORMAL (DDm2,"fst" , mm, real8, none, none,ST0 , none, none, none), +LEAF_NORMAL (DDm3,"fstp" , mm, real8, none, none,ST0 , none, none, none), +LEAF_NORMAL (DDm4,"frstor" , mm, none, none, none, none, none, none, none), +LEAF_NORMAL (DDm5,NULL , none, none, none, none, none, none, none, none), +LEAF_NORMAL (DDm6,"fnsave" , mm, none, none, none, none, none, none, wait), +LEAF_NORMAL (DDm7,"fnstsw" , mm, word, none, none, fsw, none, nowidth, wait)}, +branch_DFm[8 ] = { +LEAF_NORMAL (DFm0,"fild" , mm, word, none, none,ST0 , none, none, none), +LEAF_NORMAL (DFm1,"fisttp" , mm, word, none, none,ST0 , none, none, none), +LEAF_NORMAL (DFm2,"fist" , mm, word, none, none,ST0 , none, none, none), +LEAF_NORMAL (DFm3,"fistp" , mm, word, none, none,ST0 , none, none, none), +LEAF_NORMAL (DFm4,"fbld" , mm, bcd, none, none,ST0 , none, none, none), +LEAF_NORMAL (DFm5,"fild" , mm, qword, none, none,ST0 , none, none, none), +LEAF_NORMAL (DFm6,"fbstp" , mm, bcd, none, none,ST0 , none, none, none), +LEAF_NORMAL (DFm7,"fistp" , mm, qword, none, none,ST0 , none, none, none)}, +branch_D8_m[8 ] = { +NAME_NORMAL (D8m, mm, real4, none, none,ST0 , none, none), +BRANCH_ENTRY (D9m), +NAME_NORMAL (DAm, mm, dword, none, none,ST0 , none, none), +BRANCH_ENTRY (DBm), +NAME_NORMAL (DCm, mm, real8, none, none,ST0 , none, none), +BRANCH_ENTRY (DDm), +NAME_NORMAL (DEm, mm, word, none, none,ST0 , none, none), +BRANCH_ENTRY (DFm)}, +branch_D8r[8 ] = { +LEAF_NORMAL (D8r0,"fadd" , accum, real10, rr, real10, fsw, none, none, none), +LEAF_NORMAL (D8r1,"fmul" , accum, real10, rr, real10, fsw, none, none, none), +LEAF_NORMAL (D8r2,"fcom" , rr, real10, none, none,ST0 , none, none, st1), +LEAF_NORMAL (D8r3,"fcomp" , rr, real10, none, none,ST0 , none, none, st1), +LEAF_NORMAL (D8r4,"fsub" , accum, real10, rr, real10, fsw, none, none, none), +LEAF_NORMAL (D8r5,"fsubr" , accum, real10, rr, real10, fsw, none, none, none), +LEAF_NORMAL (D8r6,"fdiv" , accum, real10, rr, real10, fsw, none, none, none), +LEAF_NORMAL (D8r7,"fdivr" , accum, real10, rr, real10, fsw, none, none, none)}, +branch_D9r[8 ] = { +LEAF_NORMAL (D9r0,"fld" , rr, real10, none, none,ST0 , none, none, none), +LEAF_NORMAL (D9r1,"fxch" , rr, real10, none, none,ST0 , none, none, st1), +NAME_NORMAL (D9r2, none, none, none, none, fsw, none, none), +LEAF_NORMAL (D9r3,NULL , none, none, none, none, none, none, none, none), +NAME_NORMAL (D9r4, none, none, none, none,ST0 , none, none), +NAME_NORMAL (D9r5, none, none, none, none,ST0 , none, none), +NAME_NORMAL (D9r6, none, none, none, none,ST0 , none, none), +NAME_NORMAL (D9r7, none, none, none, none,ST0 , none, none)}, +branch_DAr[8 ] = { +LEAF_COND (DAr0,"fcmov" , accum, real10, rr, real10, sflags,ST0 , fpu, none), +LEAF_COND (DAr1,"fcmov" , accum, real10, rr, real10, sflags,ST0 , fpu, none), +LEAF_COND (DAr2,"fcmov" , accum, real10, rr, real10, sflags,ST0 , fpu, none), +LEAF_COND (DAr3,"fcmov" , accum, real10, rr, real10, sflags,ST0 , fpu, none), +LEAF_NORMAL (DAr4,NULL , none, none, none, none, none, none, none, none), +NAME_NORMAL (DAr5, none, none, none, none,ST0_ST1 , none, none), +LEAF_NORMAL (DAr6,NULL , none, none, none, none, none, none, none, none), +LEAF_NORMAL (DAr7,NULL , none, none, none, none, none, none, none, none)}, +branch_DBr[8 ] = { +LEAF_COND (DBr0,"fcmov" , accum, real10, rr, real10, sflags,ST0 , fpu, none), +LEAF_COND (DBr1,"fcmov" , accum, real10, rr, real10, sflags,ST0 , fpu, none), +LEAF_COND (DBr2,"fcmov" , accum, real10, rr, real10, sflags,ST0 , fpu, none), +LEAF_COND (DBr3,"fcmov" , accum, real10, rr, real10, sflags,ST0 , fpu, none), +NAME_NORMAL (DBr4, none, none, none, none, none, none, wait), +LEAF_NORMAL (DBr5,"fucomi" , accum, real10, rr, real10, sflags, none, none, none), +LEAF_NORMAL (DBr6,"fcomi" , accum, real10, rr, real10, sflags, none, none, none), +LEAF_NORMAL (DBr7,NULL , none, none, none, none, none, none, none, none)}, +branch_DDr[8 ] = { +LEAF_NORMAL (DDr0,"ffree" , rr, real10, none, none, none, none, none, none), +LEAF_NORMAL (DDr1,"fxch4" , rr, real10, none, none,ST0 , none, none, st1), +LEAF_NORMAL (DDr2,"fst" , rr, real10, none, none,ST0 , none, none, none), +LEAF_NORMAL (DDr3,"fstp" , rr, real10, none, none,ST0 , none, none, none), +LEAF_NORMAL (DDr4,"fucom" , rr, real10, none, none,ST0 , none, none, st1), +LEAF_NORMAL (DDr5,"fucomp" , rr, real10, none, none,ST0 , none, none, st1), +LEAF_NORMAL (DDr6,NULL , none, none, none, none, none, none, none, none), +LEAF_NORMAL (DDr7,NULL , none, none, none, none, none, none, none, none)}, +branch_DEr[8 ] = { +LEAF_NORMAL (DEr0,"faddp" , rr, real10, none, none,ST0 , none, none, st1), +LEAF_NORMAL (DEr1,"fmulp" , rr, real10, none, none,ST0 , none, none, st1), +LEAF_NORMAL (DEr2,NULL , none, none, none, none, none, none, none, none), +NAME_NORMAL (DEr3, none, none, none, none,ST0_ST1 , none, none), +LEAF_NORMAL (DEr4,"fsubrp" , rr, real10, none, none,ST0 , none, none, st1), +LEAF_NORMAL (DEr5,"fsubp" , rr, real10, none, none,ST0 , none, none, st1), +LEAF_NORMAL (DEr6,"fdivrp" , rr, real10, none, none,ST0 , none, none, st1), +LEAF_NORMAL (DEr7,"fdivp" , rr, real10, none, none,ST0 , none, none, st1)}, +branch_DFr[8 ] = { +LEAF_NORMAL (DFr0,"ffreep" , rr, real10, none, none,ST0 , none, none, none), +LEAF_NORMAL (DFr1,NULL , none, none, none, none, none, none, none, none), +LEAF_NORMAL (DFr2,NULL , none, none, none, none, none, none, none, none), +LEAF_NORMAL (DFr3,NULL , none, none, none, none, none, none, none, none), +NAME_NORMAL (DFr4, accum, word, none, none, fsw, none, wait), +LEAF_NORMAL (DFr5,"fucomip" , accum, real10, rr, real10, sflags, none, none, none), +LEAF_NORMAL (DFr6,"fcomip" , accum, real10, rr, real10, sflags, none, none, none), +LEAF_NORMAL (DFr7,NULL , none, none, none, none, none, none, none, none)}, +branch_D8_r[8 ] = { +BRANCH_ENTRY (D8r), +BRANCH_ENTRY (D9r), +BRANCH_ENTRY (DAr), +BRANCH_ENTRY (DBr), +NAME_NORMAL (DCr, rr, real10, accum, real10, fsw, none, none), +BRANCH_ENTRY (DDr), +BRANCH_ENTRY (DEr), +BRANCH_ENTRY (DFr)}, +regmem_D8[2 ] = { +BRANCH_ENTRY (D8_m), +BRANCH_ENTRY (D8_r)}, +branch_E0[8 ] = { +LEAF_COND (E0 ,"loop" , disp, byte, none, none,CX , sflags, loop, adsz), +LEAF_COND (E1 ,"loop" , disp, byte, none, none,CX , sflags, loop, adsz), +LEAF_COND (E2 ,"loop" , disp, byte, none, none,CX , none, loop, adsz), +#ifndef X86_64 +LEAF_COND (E3 ,"jcxz" , disp, byte, none, none,CX , none, loop, none), +#else +LEAF_COND (E3 ,"jrcxz" , disp, byte, none, none,CX , none, loop, none), +#endif +LEAF_NORMAL (E4 ,"in" , accum, byte, imm, byte, none, none, none, none), +LEAF_NORMAL (E5 ,"in" , accum, offset32, imm, byte, none, none, none, none), +LEAF_NORMAL (E6 ,"out" , imm, byte, accum, byte, none, none, none, none), +LEAF_NORMAL (E7 ,"out" , imm, byte, accum, offset32, none, none, none, none)}, +branch_E8[8 ] = { +LEAF_NORMAL (E8 ,"call" , disp, offset, none, none,SP , none, none, none), +LEAF_NORMAL (E9 ,"jmp" , disp, offset, none, none, none, none, none, none), +#ifndef X86_64 +LEAF_NORMAL (EA ,"jmp" , imm, ptr, none, none,CS , none, none, none), +#else + LEAF_NORMAL(9A, NULL, none, none, none, none, none, none, none, none), +#endif +LEAF_NORMAL (EB ,"jmp" , disp, byte, none, none, none, none, none, none), +LEAF_NORMAL (EC ,"in" , accum, byte, cl_dx, word, none, none, none, none), +LEAF_NORMAL (ED ,"in" , accum, offset32, cl_dx, word, none, none, none, none), +LEAF_NORMAL (EE ,"out" , cl_dx, word, accum, byte, none, none, none, none), +LEAF_NORMAL (EF ,"out" , cl_dx, word, accum, offset32, none, none, none, none)}, +branch_F6_[8 ] = { +LEAF_NORMAL (F6_0 ,"test" , rm, byte, imm, byte, sflags, none, none, none), +LEAF_NORMAL (F6_1 ,NULL , none, none, none, none, none, none, none, none), +LEAF_NORMAL (F6_2 ,"not" , rm, byte, none, none, none, none, none, none), +LEAF_NORMAL (F6_3 ,"neg" , rm, byte, none, none, sflags, none, none, none), +LEAF_NORMAL (F6_4 ,"mul" , rm, byte, none, none,DX_AX , sflags, none, none), +LEAF_NORMAL (F6_5 ,"imul" , rm, byte, none, none,DX_AX , sflags, none, none), +LEAF_NORMAL (F6_6 ,"div" , rm, byte, none, none,DX_AX , sflags, none, none), +LEAF_NORMAL (F6_7 ,"idiv" , rm, byte, none, none,DX_AX , sflags, none, none)}, +branch_F7_[8 ] = { +LEAF_NORMAL (F7_0 ,"test" , rm, offset, imm, offset32, sflags, none, none, none), +LEAF_NORMAL (F7_1 ,NULL , none, none, none, none, none, none, none, none), +LEAF_NORMAL (F7_2 ,"not" , rm, offset, none, none, none, none, none, none), +LEAF_NORMAL (F7_3 ,"neg" , rm, offset, none, none, sflags, none, none, none), +LEAF_NORMAL (F7_4 ,"mul" , rm, offset, none, none,DX_AX , sflags, none, none), +LEAF_NORMAL (F7_5 ,"imul" , rm, offset, none, none,DX_AX , sflags, none, none), +LEAF_NORMAL (F7_6 ,"div" , rm, offset, none, none,DX_AX , sflags, none, none), +LEAF_NORMAL (F7_7 ,"idiv" , rm, offset, none, none,DX_AX , sflags, none, none)}, +branch_F0[8 ] = { +LEAF_NORMAL (F0 ,NULL , none, none, none, none, none, none, none, none), +LEAF_NORMAL (F1 ,"icebp" , none, none, none, none, sflags, none, none, none), +LEAF_NORMAL (F2 ,NULL , none, none, none, none, none, none, none, none), +LEAF_NORMAL (F3 ,NULL , none, none, none, none, none, none, none, none), +LEAF_NORMAL (F4 ,"hlt" , none, none, none, none, none, none, none, none), +LEAF_NORMAL (F5 ,"cmc" , none, none, none, none, sflags, none, none, none), +BRANCH_ENTRY (F6_ ), +BRANCH_ENTRY (F7_ )}, +branch_FF_[8 ] = { +LEAF_NORMAL (FF_0 ,"inc" , rm, offset, none, none, sflags, none, none, none), +LEAF_NORMAL (FF_1 ,"dec" , rm, offset, none, none, sflags, none, none, none), +LEAF_NORMAL (FF_2 ,"call" , rm, offset64, none, none,SP , none, none, none), +LEAF_NORMAL (FF_3 ,"call" , mm, ptr32, none, none,SP ,CS , none, none), +LEAF_NORMAL (FF_4 ,"jmp" , rm, offset64, none, none, none, none, none, none), +LEAF_NORMAL (FF_5 ,"jmp" , mm, ptr32, none, none,CS , none, none, none), +LEAF_NORMAL (FF_6 ,"push" , rm, offset64, none, none,SP , none, none, none), +LEAF_NORMAL (FF_7 ,NULL , none, none, none, none, none, none, none, none)}, +branch_F8[8 ] = { +LEAF_NORMAL (F8 ,"clc" , none, none, none, none, sflags, none, none, none), +LEAF_NORMAL (F9 ,"stc" , none, none, none, none, sflags, none, none, none), +LEAF_NORMAL (FA ,"cli" , none, none, none, none, flags, none, none, none), +LEAF_NORMAL (FB ,"sti" , none, none, none, none, flags, none, none, none), +LEAF_NORMAL (FC ,"cld" , none, none, none, none, flags, none, none, none), +LEAF_NORMAL (FD ,"std" , none, none, none, none, flags, none, none, none), +NAME_NORMAL (FE_ , rm, byte, none, none, sflags, none, none), +BRANCH_ENTRY (FF_ )}, +oneByteTable[256 >>3 ] = { +BRANCH_ENTRY (00 ), +BRANCH_ENTRY (08 ), +BRANCH_ENTRY (10 ), +BRANCH_ENTRY (18 ), +BRANCH_ENTRY (20 ), +BRANCH_ENTRY (28 ), +BRANCH_ENTRY (30 ), +BRANCH_ENTRY (38 ), +#ifndef X86_64 +LEAF_NORMAL (40 ,"inc" , reg, offset, none, none, sflags, none, none, none), +LEAF_NORMAL (48 ,"dec" , reg, offset, none, none, sflags, none, none, none), +#else +LEAF_NORMAL (40 ,NULL , none, none, none, none, none, none, none, none), +LEAF_NORMAL (48 ,NULL , none, none, none, none, none, none, none, none), +#endif +LEAF_NORMAL (50 ,"push" , reg, offset64, none, none,SP , none, none, none), +LEAF_NORMAL (58 ,"pop" , reg, offset64, none, offset, tos, none, none, none), +BRANCH_ENTRY (60 ), +BRANCH_ENTRY (68 ), +LEAF_COND (70 ,"j" , disp, byte, none, none, sflags, none, normal, none), +LEAF_COND (78 ,"j" , disp, byte, none, none, sflags, none, normal, none), +BRANCH_ENTRY (80 ), +BRANCH_ENTRY (88 ), +BRANCH_ENTRY (90 ), +BRANCH_ENTRY (98 ), +BRANCH_ENTRY (A0 ), +BRANCH_ENTRY (A8 ), +LEAF_NORMAL (B0 ,"mov" , reg, byte, imm, byte, none, none, none, none), +LEAF_NORMAL (B8 ,"mov" , reg, offset, imm, offset, none, none, none, none), +BRANCH_ENTRY (C0 ), +BRANCH_ENTRY (C8 ), +BRANCH_ENTRY (D0 ), +REGMEM_ENTRY (D8 , normal), +BRANCH_ENTRY (E0 ), +BRANCH_ENTRY (E8 ), +BRANCH_ENTRY (F0 ), +BRANCH_ENTRY (F8 )};
debug/nlkd/cda/x86_2.c new file +453 -0
453 lines not on this page · raw message
debug/nlkd/cda/x86_3.c new file +159 -0
159 lines not on this page · raw message
debug/nlkd/cda/x86_op.c new file +136 -0
136 lines not on this page · raw message
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 38/39 NLKD/i386 - Remote Debug Agent
The i386-dependent part of the Remote Debug Agent of NLKD.
(actual patch attached)
The i386-dependent part of the Remote Debug Agent of NLKD.
debug/nlkd/rda/rdaIA32.c new file +431 -0
@@ -0,0 +1,431 @@ +/***************************************************************************** +* +* File Name: rdaIA32.c +* Created by: Jan Beulich +* Date created: 23Jan2003 +* +* %version: 7 % +* %derived_by: jbeulich % +* %date_modified: Mon Jun 27 04:00:30 2005 % +* +*****************************************************************************/ +/***************************************************************************** +* * +* Copyright (c) 2003-2005 Novell, Inc. All Rights Reserved. * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of version 2 of the GNU General Public License * +* as published by the Free Software Foundation. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, contact Novell, Inc. * +* * +* To contact Novell about this file by physical or electronic mail, * +* you may find current contact information at www.novell.com. * +* * +*****************************************************************************/ +/***************************************************************************** +* +* File Description: +* +*****************************************************************************/ + +#include <asm/cde.h> + +#include "rda.h" + +#define r_FTW (r_invalid - 1) +#define r_FIP (r_invalid - 2) +#define r_FDP (r_invalid - 3) +#define r_FOP (r_invalid - 4) + +#undef EAX/* colliding with include/asm/ptrace.h */ +#undef ECX +#undef EDX +#undef EBX +#undef EBP +#undef ESP +#undef ESI +#undef EDI +#undef EIP +#undef CS +#undef DS +#undef ES +#undef FS +#undef GS +#undef SS +#define REGINFO (gdb, w, cls, idx) gdb, +enum gdb_registers { +#include "rdaIA32.incl" + gdbCOUNT +}; +#undef REGINFO + +union fpreg_u { +float80_t raw; +struct { +uint32_t mant_lo; +uint32_t mant_hi; +uint16_t sign_exp; + }; +}; + +cdeBool_t rdaSetPC (RdaSessionState *state,uintptr_t address) { +if (!cdeWriteEIP (state->currentFrame, address)) { +rdaError (state,RDA_EINVAL ); +return cdeFalse; + } +return cdeTrue; +} + +void rdaPutFrameInfo (RdaSessionState *state) { +const ftaFullInterruptionCtx_t *frame = state->currentFrame; +int sigval; +uint32_t value; + +switch (cdeGetInterruptionType (frame,NULL )) { +default : + sigval =2 ; +break ; +case IA32_ILLEGAL_OPCODE : + sigval =4 ; +break ; +case IA32_DEBUG : +case IA32_BREAKPOINT : + sigval =5 ; +break ; +case IA32_RSVD_0F : +case IA32_RSVD_14 : +case IA32_RSVD_15 : +case IA32_RSVD_16 : +case IA32_RSVD_17 : +case IA32_RSVD_18 : +case IA32_RSVD_19 : +case IA32_RSVD_1A : +case IA32_RSVD_1B : +case IA32_RSVD_1C : +case IA32_RSVD_1D : +case IA32_RSVD_1E : +case IA32_RSVD_1F : + sigval =6 ; +break ; +case IA32_DOUBLE_FAULT : + sigval =7 ; +break ; +case IA32_DIVIDE_ERROR : +case IA32_DEVICE_NOT_AVAILABLE : +case IA32_FP_ERROR : +case IA32_SIMD_FP_ERROR : + sigval =8 ; +break ; +case IA32_ALIGNMENT_CHECK : + sigval =10 ; +break ; +case IA32_COPROCESSOR_SEGMENT_OVERRUN : +case IA32_INVALID_TSS : +case IA32_SEGMENT_NOT_PRESENT : +case IA32_GENERAL_PROTECTION_FAULT : +case IA32_PAGE_FAULT : + sigval =11 ; +break ; +case IA32_OVERFLOW : +case IA32_BOUNDS_CHECK : +case IA32_STACK_FAULT : + sigval =16 ; +break ; + } +rdaPutHex (state, sigval,1 ); +rdaPutHex (state,EIP ,0 ); +rdaPutChar (state,':' ); +rdaPutHex (state,cdeReadEIP (frame),-4 ); +rdaPutChar (state,';' ); +if (cdeReadGR (reg_esp, frame, &value)) { +rdaPutHex (state,ESP ,0 ); +rdaPutChar (state,':' ); +rdaPutHex (state, value,-4 ); +rdaPutChar (state,';' ); + } +if (cdeReadGR (reg_ebp, frame, &value)) { +rdaPutHex (state,EBP ,0 ); +rdaPutChar (state,':' ); +rdaPutHex (state, value,-4 ); +rdaPutChar (state,';' ); + } +} + +#define REGINFO (gdb, w, cls, idx) {r_##cls, idx}, +static const struct regInfo { +signed char type; +unsigned char index; +} regInfo[] = { +#include "rdaIA32.incl" +}; +#undef REGINFO + +void rdaGetRegisters (RdaSessionState *state, +const char *input, +size_t inputSize) { +unsigned i; + +if (state->currentFrame ==NULL ) { +rdaError (state,RDA_EAGAIN ); +return ; + } +if (inputSize !=0 ) { +rdaError (state,RDA_EINVAL ); +return ; + } +for (i =0 ; i < gdbCOUNT; ++i) { +switch (regInfo[i].type) { +case r_eip: +rdaPutHex (state,cdeReadEIP (state->currentFrame),-4 ); +break ; +case r_eflags: +rdaPutHex (state,cdeReadEFLAGS (state->currentFrame),-4 ); +break ; +case r_general: { +uint32_t value; + +if (!cdeReadGR (regInfo[i].index, state->currentFrame, &value)) + value =0 ; +rdaPutHex (state, value,-4 ); + } +break ; +case r_selector: { +uint16_t value; + +if (!cdeReadSR (regInfo[i].index, state->currentFrame, &value)) + value =0 ; +rdaPutHex (state, value,-4 ); + } +break ; +case r_floating: { +union fpreg_u value; + +if (!cdeReadFR (regInfo[i].index, state->currentFrame, &value.raw)) +dbgZeroMem (&value,sizeof (value)); +rdaPutHex (state, value.mant_lo,-4 ); +rdaPutHex (state, value.mant_hi,-4 ); +rdaPutHex (state, value.sign_exp,-2 ); + } +break ; +case r_fcw: { +uint16_t value; + +if (!cdeReadFpuControlWord (state->currentFrame, &value)) + value =0 ; +rdaPutHex (state, value,-4 ); + } +break ; +case r_fsw: { +uint16_t value; + +if (!cdeReadFpuStatusWord (state->currentFrame, &value)) + value =0 ; +rdaPutHex (state, value,-4 ); + } +break ; +case r_FTW: { +uint16_t value; + +if (!cdeReadFpuTagWord (state->currentFrame, &value)) + value =0 ; +rdaPutHex (state, value,-4 ); + } +break ; +case r_FIP: { +struct CdeAddress address; + +if (!cdeReadFpuCodePointer (state->currentFrame, &address)) +dbgZeroMem (&address,sizeof (address)); +rdaPutHex (state, regInfo[i].index ? address.selector : address.offset,-4 ); + } +break ; +case r_FDP: { +struct CdeAddress address; + +if (!cdeReadFpuDataPointer (state->currentFrame, &address)) +dbgZeroMem (&address,sizeof (address)); +rdaPutHex (state, regInfo[i].index ? address.selector : address.offset,-4 ); + } +break ; +case r_FOP: { +uint16_t value; + +if (!cdeReadFpuOpcode (state->currentFrame, &value)) + value =0 ; +rdaPutHex (state, value,-4 ); + } +break ; +case r_xmm: +if (cdeWriteMXCSR (NULL ,0 )) { +xmmreg_t value; + +if (!cdeReadXMM (regInfo[i].index, state->currentFrame, &value)) +dbgZeroMem (&value,sizeof (value)); +rdaPutHex (state, value.d[0 ],-4 ); +rdaPutHex (state, value.d[1 ],-4 ); +rdaPutHex (state, value.d[2 ],-4 ); +rdaPutHex (state, value.d[3 ],-4 ); + } +break ; +case r_mxcsr: +if (cdeWriteMXCSR (NULL ,0 )) { +uint32_t value; + +if (!cdeReadMXCSR (state->currentFrame, &value)) +dbgZeroMem (&value,sizeof (value)); +rdaPutHex (state, value,-4 ); + } +break ; +default : +RTASSERT (!(regInfo + i)); +break ; + } + } +} + +static cdeBool_t setReg (RdaSessionState *state, +const struct regInfo *info, +const char **pInput) { +cdeBool_t result = cdeFalse; + +switch (info->type) { +uint32_t value; + +case r_eip: + value =rdaGetHex (*pInput, pInput,-4 ); +if (*pInput !=NULL ) + result =cdeWriteEIP (state->currentFrame, value); +break ; +case r_eflags: + value =rdaGetHex (*pInput, pInput,-4 ); +if (*pInput !=NULL ) + result =cdeWriteEFLAGS (state->currentFrame, value); +break ; +case r_general: + value =rdaGetHex (*pInput, pInput,-4 ); +if (*pInput !=NULL ) + result =cdeWriteGR (info->index, state->currentFrame, value); +break ; +case r_selector: + value =rdaGetHex (*pInput, pInput,-4 ); +if (*pInput !=NULL ) + result = (value == (uint16_t )value &&cdeWriteSR (info->index, state->currentFrame, (uint16_t )value)); +break ; +case r_floating: { +union fpreg_u value; + + value.mant_lo =rdaGetHex (*pInput, pInput,-4 ); +if (*pInput !=NULL ) + value.mant_hi =rdaGetHex (*pInput, pInput,-4 ); +if (*pInput !=NULL ) + value.sign_exp = (uint16_t )rdaGetHex (*pInput, pInput,-2 ); +if (*pInput !=NULL ) + result =cdeWriteFR (info->index, state->currentFrame, &value.raw); + } +break ; +case r_fcw: + value =rdaGetHex (*pInput, pInput,-4 ); +if (*pInput !=NULL ) + result = (value == (uint16_t )value &&cdeWriteFpuControlWord (state->currentFrame, (uint16_t )value)); +break ; +case r_fsw: + value =rdaGetHex (*pInput, pInput,-4 ); +if (*pInput !=NULL ) + result = (value == (uint16_t )value &&cdeWriteFpuStatusWord (state->currentFrame, (uint16_t )value)); +break ; +case r_FTW: + value =rdaGetHex (*pInput, pInput,-4 ); +if (*pInput !=NULL ) + result = (value == (uint16_t )value &&cdeWriteFpuTagWord (state->currentFrame, (uint16_t )value)); +break ; +case r_FIP: +case r_FDP: +case r_FOP: + result = cdeFalse; +break ; +case r_xmm: { +xmmreg_t value; + + value.d[0 ] =rdaGetHex (*pInput, pInput,-4 ); +if (*pInput !=NULL ) + value.d[1 ] =rdaGetHex (*pInput, pInput,-4 ); +if (*pInput !=NULL ) + value.d[2 ] =rdaGetHex (*pInput, pInput,-4 ); +if (*pInput !=NULL ) + value.d[3 ] =rdaGetHex (*pInput, pInput,-4 ); +if (*pInput !=NULL ) + result =cdeWriteXMM (info->index, state->currentFrame, &value); + } +break ; +case r_mxcsr: + value =rdaGetHex (*pInput, pInput,-4 ); +if (*pInput !=NULL ) + result =cdeWriteMXCSR (state->currentFrame, value); +break ; +default : +RTASSERT (!info); +break ; + } +if (*pInput ==NULL ) { +rdaError (state,RDA_EFORMAT ); + result = cdeFalse; + } +else if (!result) +rdaError (state,RDA_EINVAL ); +return result; +} + +void rdaSetRegisters (RdaSessionState *state, +const char *input, +size_t inputSize) { +unsigned index; +const char *end; + +if (state->currentFrame ==NULL ) { +rdaError (state,RDA_EAGAIN ); +return ; + } +if (inputSize &1 ) { +rdaError (state,RDA_EINVAL ); +return ; + } +for (index =0 , end = input; index < gdbCOUNT; ++index) { +if (!setReg (state, regInfo + index, &end)) +return ; +if (input + inputSize == end) +break ; + } +if (index == gdbCOUNT) +rdaOK (state); +else +rdaError (state,RDA_EPARTIAL ); +} + +void rdaSetRegister (RdaSessionState *state, +const char *input, +size_t inputSize) { +const char *end; +uintptr_t index =rdaGetHex (input, &end,0 ); + +if (index >= gdbCOUNT) { +rdaError (state,RDA_EINVAL ); +return ; + } +if (state->currentFrame ==NULL ) { +rdaError (state,RDA_EAGAIN ); +return ; + } +if (!setReg (state, regInfo + index, &input)) +return ; +if (input + inputSize == end) +rdaOK (state); +else +rdaError (state,RDA_EFORMAT ); +}
debug/nlkd/rda/rdaIA32.incl new file +78 -0
78 lines not on this page · raw message
PATCH 39/39 NLKD/x86-64 - Remote Debug Agent
In reply to a message not in the archiveThe x86_64-dependent part of the Remote Debug Agent of NLKD.
(actual patch attached)
The x86_64-dependent part of the Remote Debug Agent of NLKD.
debug/nlkd/rda/rdaAMD64.c new file +406 -0
@@ -0,0 +1,406 @@ +/***************************************************************************** +* +* File Name: rdaAMD64.c +* Created by: Jan Beulich +* Date created: 28Jan2003 +* +* %version: 7 % +* %derived_by: jbeulich % +* %date_modified: Mon Jun 27 03:59:40 2005 % +* +*****************************************************************************/ +/***************************************************************************** +* * +* Copyright (c) 2003-2005 Novell, Inc. All Rights Reserved. * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of version 2 of the GNU General Public License * +* as published by the Free Software Foundation. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, contact Novell, Inc. * +* * +* To contact Novell about this file by physical or electronic mail, * +* you may find current contact information at www.novell.com. * +* * +*****************************************************************************/ +/***************************************************************************** +* +* File Description: +* +*****************************************************************************/ + +#include <asm/cde.h> + +#include "rda.h" + +#define r_FTW (r_invalid - 1) +#define r_FIP (r_invalid - 2) +#define r_FDP (r_invalid - 3) +#define r_FOP (r_invalid - 4) + +#define REGINFO (gdb, w, cls, idx) gdb, +enum gdb_registers { +#include "rdaAMD64.incl" + gdbCOUNT +}; +#undef REGINFO + +union fpreg_u { +float80_t raw; +struct { +uint64_t mant; +uint16_t sign_exp; + }; +}; + +cdeBool_t rdaSetPC (RdaSessionState *state,uintptr_t address) { +if (!cdeWriteRIP (state->currentFrame, address)) { +rdaError (state,RDA_EINVAL ); +return cdeFalse; + } +return cdeTrue; +} + +void rdaPutFrameInfo (RdaSessionState *state) { +const ftaFullInterruptionCtx_t *frame = state->currentFrame; +int sigval; +uint64_t value; + +switch (cdeGetInterruptionType (frame,NULL )) { +default : + sigval =2 ; +break ; +case AMD64_ILLEGAL_OPCODE : + sigval =4 ; +break ; +case AMD64_DEBUG : +case AMD64_BREAKPOINT : + sigval =5 ; +break ; +case AMD64_RSVD_09 : +case AMD64_RSVD_0F : +case AMD64_RSVD_14 : +case AMD64_RSVD_15 : +case AMD64_RSVD_16 : +case AMD64_RSVD_17 : +case AMD64_RSVD_18 : +case AMD64_RSVD_19 : +case AMD64_RSVD_1A : +case AMD64_RSVD_1B : +case AMD64_RSVD_1C : +case AMD64_RSVD_1D : +case AMD64_RSVD_1E : +case AMD64_RSVD_1F : + sigval =6 ; +break ; +case AMD64_DOUBLE_FAULT : + sigval =7 ; +break ; +case AMD64_DIVIDE_ERROR : +case AMD64_DEVICE_NOT_AVAILABLE : +case AMD64_FP_ERROR : +case AMD64_SIMD_FP_ERROR : + sigval =8 ; +break ; +case AMD64_ALIGNMENT_CHECK : + sigval =10 ; +break ; +case AMD64_INVALID_TSS : +case AMD64_SEGMENT_NOT_PRESENT : +case AMD64_GENERAL_PROTECTION_FAULT : +case AMD64_PAGE_FAULT : + sigval =11 ; +break ; +case AMD64_OVERFLOW : +case AMD64_BOUNDS_CHECK : +case AMD64_STACK_FAULT : + sigval =16 ; +break ; + } +rdaPutHex (state, sigval,1 ); +rdaPutHex (state,RIP ,0 ); +rdaPutChar (state,':' ); +rdaPutHex (state,cdeReadRIP (frame),-8 ); +rdaPutChar (state,';' ); +if (cdeReadGR (reg_rsp, frame, &value)) { +rdaPutHex (state,RSP ,0 ); +rdaPutChar (state,':' ); +rdaPutHex (state, value,-8 ); +rdaPutChar (state,';' ); + } +if (cdeReadGR (reg_rbp, frame, &value)) { +rdaPutHex (state,RBP ,0 ); +rdaPutChar (state,':' ); +rdaPutHex (state, value,-8 ); +rdaPutChar (state,';' ); + } +} + +#define REGINFO (gdb, w, cls, idx) {r_##cls, idx}, +static const struct regInfo { +signed char type; +unsigned char index; +} regInfo[] = { +#include "rdaAMD64.incl" +}; +#undef REGINFO + +void rdaGetRegisters (RdaSessionState *state, +const char *input, +size_t inputSize) { +unsigned i; + +if (state->currentFrame ==NULL ) { +rdaError (state,RDA_EAGAIN ); +return ; + } +if (inputSize !=0 ) { +rdaError (state,RDA_EINVAL ); +return ; + } +for (i =0 ; i < gdbCOUNT; ++i) { +switch (regInfo[i].type) { +case r_rip: +rdaPutHex (state,cdeReadRIP (state->currentFrame),-8 ); +break ; +case r_rflags: +rdaPutHex (state,cdeReadRFLAGS (state->currentFrame),-4 ); +break ; +case r_general: { +uint64_t value; + +if (!cdeReadGR (regInfo[i].index, state->currentFrame, &value)) + value =0 ; +rdaPutHex (state, value,-8 ); + } +break ; +case r_selector: { +uint16_t value; + +if (!cdeReadSR (regInfo[i].index, state->currentFrame, &value,NULL )) + value =0 ; +rdaPutHex (state, value,-4 ); + } +break ; +case r_floating: { +union fpreg_u value; + +if (!cdeReadFR (regInfo[i].index, state->currentFrame, &value.raw)) +dbgZeroMem (&value,sizeof (value)); +rdaPutHex (state, value.mant,-8 ); +rdaPutHex (state, value.sign_exp,-2 ); + } +break ; +case r_fcw: { +uint16_t value; + +if (!cdeReadFpuControlWord (state->currentFrame, &value)) + value =0 ; +rdaPutHex (state, value,-4 ); + } +break ; +case r_fsw: { +uint16_t value; + +if (!cdeReadFpuStatusWord (state->currentFrame, &value)) + value =0 ; +rdaPutHex (state, value,-4 ); + } +break ; +case r_FTW: { +uint16_t value; + +if (!cdeReadFpuTagWord (state->currentFrame, &value)) + value =0 ; +rdaPutHex (state, value,-4 ); + } +break ; +case r_FIP: { +struct CdeAddress address; + +if (!cdeReadFpuCodePointer (state->currentFrame, &address)) +dbgZeroMem (&address,sizeof (address)); +rdaPutHex (state, regInfo[i].index ? address.selector : address.offset,-4 ); + } +break ; +case r_FDP: { +struct CdeAddress address; + +if (!cdeReadFpuDataPointer (state->currentFrame, &address)) +dbgZeroMem (&address,sizeof (address)); +rdaPutHex (state, regInfo[i].index ? address.selector : address.offset,-4 ); + } +break ; +case r_FOP: { +uint16_t value; + +if (!cdeReadFpuOpcode (state->currentFrame, &value)) + value =0 ; +rdaPutHex (state, value,-4 ); + } +break ; +case r_xmm: +if (cdeWriteMXCSR (NULL ,0 )) { +xmmreg_t value; + +if (!cdeReadXMM (regInfo[i].index, state->currentFrame, &value)) +dbgZeroMem (&value,sizeof (value)); +rdaPutHex (state, value.q[0 ],-8 ); +rdaPutHex (state, value.q[1 ],-8 ); + } +break ; +case r_mxcsr: +if (cdeWriteMXCSR (NULL ,0 )) { +uint32_t value; + +if (!cdeReadMXCSR (state->currentFrame, &value)) +dbgZeroMem (&value,sizeof (value)); +rdaPutHex (state, value,-4 ); + } +break ; +default : +RTASSERT (!(regInfo + i)); +break ; + } + } +} + +static cdeBool_t setReg (RdaSessionState *state, +const struct regInfo *info, +const char **pInput) { +cdeBool_t result = cdeFalse; + +switch (info->type) { +uint64_t value; + +case r_rip: + value =rdaGetHex (*pInput, pInput,-8 ); +if (*pInput !=NULL ) + result =cdeWriteRIP (state->currentFrame, value); +break ; +case r_rflags: + value =rdaGetHex (*pInput, pInput,-4 ); +if (*pInput !=NULL ) + result =cdeWriteRFLAGS (state->currentFrame, value); +break ; +case r_general: + value =rdaGetHex (*pInput, pInput,-8 ); +if (*pInput !=NULL ) + result =cdeWriteGR (info->index, state->currentFrame, value); +break ; +case r_selector: + value =rdaGetHex (*pInput, pInput,-4 ); +if (*pInput !=NULL ) + result = (value == (uint16_t )value &&cdeWriteSR (info->index, state->currentFrame, (uint16_t )value,NULL )); +break ; +case r_floating: { +union fpreg_u value; + + value.mant =rdaGetHex (*pInput, pInput,-8 ); +if (*pInput !=NULL ) + value.sign_exp = (uint16_t )rdaGetHex (*pInput, pInput,-2 ); +if (*pInput !=NULL ) + result =cdeWriteFR (info->index, state->currentFrame, &value.raw); + } +break ; +case r_fcw: + value =rdaGetHex (*pInput, pInput,-4 ); +if (*pInput !=NULL ) + result = (value == (uint16_t )value &&cdeWriteFpuControlWord (state->currentFrame, (uint16_t )value)); +break ; +case r_fsw: + value =rdaGetHex (*pInput, pInput,-4 ); +if (*pInput !=NULL ) + result = (value == (uint16_t )value &&cdeWriteFpuStatusWord (state->currentFrame, (uint16_t )value)); +break ; +case r_FTW: + value =rdaGetHex (*pInput, pInput,-4 ); +if (*pInput !=NULL ) + result = (value == (uint16_t )value &&cdeWriteFpuTagWord (state->currentFrame, (uint16_t )value)); +break ; +case r_FIP: +case r_FDP: +case r_FOP: + result = cdeFalse; +break ; +case r_xmm: { +xmmreg_t value; + + value.q[0 ] =rdaGetHex (*pInput, pInput,-8 ); +if (*pInput !=NULL ) + value.q[1 ] =rdaGetHex (*pInput, pInput,-8 ); +if (*pInput !=NULL ) + result =cdeWriteXMM (info->index, state->currentFrame, &value); + } +break ; +case r_mxcsr: + value =rdaGetHex (*pInput, pInput,-4 ); +if (*pInput !=NULL ) + result =cdeWriteMXCSR (state->currentFrame, (uint32_t )value); +break ; +default : +RTASSERT (!info); +break ; + } +if (*pInput ==NULL ) { +rdaError (state,RDA_EFORMAT ); + result = cdeFalse; + } +else if (!result) +rdaError (state,RDA_EINVAL ); +return result; +} + +void rdaSetRegisters (RdaSessionState *state, +const char *input, +size_t inputSize) { +unsigned index; +const char *end; + +if (state->currentFrame ==NULL ) { +rdaError (state,RDA_EAGAIN ); +return ; + } +if (inputSize &1 ) { +rdaError (state,RDA_EINVAL ); +return ; + } +for (index =0 , end = input; index < gdbCOUNT; ++index) { +if (!setReg (state, regInfo + index, &end)) +return ; +if (input + inputSize == end) +break ; + } +if (index == gdbCOUNT) +rdaOK (state); +else +rdaError (state,RDA_EPARTIAL ); +} + +void rdaSetRegister (RdaSessionState *state, +const char *input, +size_t inputSize) { +const char *end; +uintptr_t index =rdaGetHex (input, &end,0 ); + +if (index >= gdbCOUNT) { +rdaError (state,RDA_EINVAL ); +return ; + } +if (state->currentFrame ==NULL ) { +rdaError (state,RDA_EAGAIN ); +return ; + } +if (!setReg (state, regInfo + index, &input)) +return ; +if (input + inputSize == end) +rdaOK (state); +else +rdaError (state,RDA_EFORMAT ); +}
debug/nlkd/rda/rdaAMD64.incl new file +92 -0
92 lines not on this page · raw message
Al Viro
NAKRe: [PATCH 15/39] NLKD - early pseudo-fs
In reply to Jan BeulichQuoted 9 lines · Jan Beulich
While for limited amounts of configuration information the kernel command line may be suitable, it isn't when it comes to significant amounts of configurable entities that need to be set before the full kernel infrastructure is available. This patch adds functionality to pass one or more configuration files through the initrd, but without requiring knowledge of the actual structure (including compression) of it; the file(s) is/are attached to the end of the already built initrd (which obviously depends on external scripts not provided here).
What the hell for? We _already_ have a way to get any set of files in a filesystem as soon as we have VFS caches set up (and until then you can't open anything anyway).
NAK.
Re: [PATCH 15/39] NLKD - early pseudo-fs
Quoted 5 lines
Quoted 1 line
Quoted 1 line
Al Viro <[email protected]> 09.11.05 15:29:26 >>>
Quoted 3 lines · Jan Beulich
While for limited amounts of configuration information the kernel command line may be suitable, it isn't when it comes to significant amounts of configurable entities that need to be set before the
full
Quoted 1 line
Quoted 1 line
kernel infrastructure is available. This patch adds functionality
to
Quoted 1 line
Quoted 1 line
pass one or more configuration files through the initrd, but
without
Quoted 1 line
Quoted 1 line
requiring knowledge of the actual structure (including compression)
of
Quoted 5 lines
Quoted 3 lines
it; the file(s) is/are attached to the end of the already built initrd (which obviously depends on external scripts not provided here).
What the hell for? We _already_ have a way to get any set of files
in
Quoted 2 lines
a filesystem as soon as we have VFS caches set up (and until then you can't open anything anyway).
That's the whole point - a debugger wants this *before* VFS is set up (and thus obviously without going through VFS in the first place). One may argue that the naming is odd, but that's nothing I really care about.
Quoted 1 line
NAK.
Then suggest an alternative solution.
Jan
Re: [PATCH 15/39] NLKD - early pseudo-fs
Quoted 5 lines · Jan Beulich
Quoted 1 line
What the hell for? We _already_ have a way to get any set of files
in
Quoted 2 lines
a filesystem as soon as we have VFS caches set up (and until then you can't open anything anyway).
Quoted 8 lines
That's the whole point - a debugger wants this *before* VFS is set up (and thus obviously without going through VFS in the first place). One may argue that the naming is odd, but that's nothing I really care about.
Quoted 1 line
NAK.
Then suggest an alternative solution.
"Reduce the parts of your config needed that early on to something saner in size"
Re: [PATCH 15/39] NLKD - early pseudo-fs
Quoted 3 lines
Quoted 1 line
Quoted 1 line
Al Viro <[email protected]> 09.11.05 16:00:57 >>>
Quoted 1 line · Jan Beulich
Quoted 1 line
What the hell for? We _already_ have a way to get any set of
files
Quoted 2 lines
Quoted 2 lines
in
Quoted 1 line
a filesystem as soon as we have VFS caches set up (and until then
you
Quoted 3 lines
Quoted 3 lines
Quoted 1 line
can't open anything anyway).
That's the whole point - a debugger wants this *before* VFS is set
up
Quoted 1 line
Quoted 1 line
(and thus obviously without going through VFS in the first place).
One
Quoted 9 lines
Quoted 6 lines
may argue that the naming is odd, but that's nothing I really care about.
Quoted 1 line
NAK.
Then suggest an alternative solution.
"Reduce the parts of your config needed that early on to something saner in size"
That is no solution. Take a look at what can be configured in NLKD, and tell me what you'd call a 'saner in size' subset. I can't think of anything that can be left out; instead, the amount of configurable things will only grow over time.
Jan
Re: [PATCH 14/39] NLKD - kernel trace buffer access
In reply to Jan BeulichQuoted 2 lines · Jan Beulich
Debug extension implementation for NLKD to access the kernel trace buffer.
printk.c | 187 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 187 insertions(+)
This is complete overkill in printk.c. The only change required to printk is to add a routine which gets the parameters that define the buffer, see below from KDB. The rest of the code in your patch belongs in the debugger, not in printk.
#ifdef CONFIG_KDB
/* kdb dmesg command needs access to the syslog buffer. do_syslog() uses locks
* so it cannot be used during debugging. Just tell kdb where the start and
* end of the physical and logical logs are. This is equivalent to do_syslog(3). */
void kdb_syslog_data(char *syslog_data[4])
{
syslog_data[0] = log_buf;
syslog_data[1] = log_buf + log_buf_len;
syslog_data[2] = log_buf + log_end - (logged_chars < log_buf_len ? logged_chars : log_buf_len);
syslog_data[3] = log_buf + log_end;
}#endif /* CONFIG_KDB */
Re: [PATCH 14/39] NLKD - kernel trace buffer access
Quoted 7 lines
Quoted 1 line
Quoted 1 line
Keith Owens <[email protected]> 10.11.05 06:44:52 >>>
Quoted 2 lines · Jan Beulich
Debug extension implementation for NLKD to access the kernel trace buffer.
printk.c| 187
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Quoted 5 lines
1 files changed, 187 insertions(+)This is complete overkill in
printk.c. The only change required to printk is to add a routine which gets the parameters that define the buffer, see below from KDB. The rest of the code in your patch
belongs
Quoted 1 line
in the debugger, not in printk.
This depends on the perspective...
Quoted 2 lines
#ifdef
CONFIG_KDB
/* kdb dmesg command needs access to the syslog buffer.do_syslog()
uses locks
Quoted 1 line
* so it cannot be used during debugging. Just tell kdb where the
start and
Quoted 1 line
* end of the physical and logical logs are. This is equivalent to
do_syslog(3).
Quoted 6 lines
*/
voidkdb_syslog_data(char *syslog_data[4]){ syslog_data[0] = log_buf; syslog_data[1] = log_buf + log_buf_len; syslog_data[2] = log_buf + log_end - (logged_chars < log_buf_len
? logged_chars : log_buf_len);
Quoted 3 lines
syslog_data[3] = log_buf + log_end; }#endif /*
CONFIG_KDB*/
The publishing of this function allows uncontrolled access to the otherwise (and sure purposefully) static symbols; you could as well globalize the symbols directly. In order for KDB to be a module, this symbol would even need to be exported. By keeping the debugger access code in the same file, nothing gets changed visibility-wise for the outside world.
Further, the design of the debugger extensions of NLKD calls for the extension code to live in the place their data gets controlled at. Consider an extension living in a module - how could the debugger access that information?
Jan
Re: [PATCH 11/39] NLKD - time adjustment
In reply to Jan BeulichQuoted 8 lines · Jan Beulich
Generic part of an interface to allow debuggers to update time after having halted the system for perhaps extended periods of time. This generally requires arch-dependent changes, too, unless the arch- dependent time handling is already overflow-safe.
Signed-off-by Jan Beulich <[email protected]>(actual patch attached)
Perhaps you could teach your mailer how to attach the atachments so that they appear inline to the reader. The problem appears to be that it does not recognize the file type. This is what it says:
Content-Type: application/octet-stream; name="linux-2.6.14-nlkd-time.patch"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="linux-2.6.14-nlkd-time.patch"
where as a correct attachment might look something like:
Content-Type: text/x-diff;
charset="us-ascii";
name="patch_x86_64-kernel-i8259"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="patch_x86_64-kernel-i8259"
This would allow us to comment on the patch with said comments appearing in the body of the patch.
Quoted 1 line
Signature · 2 lines
George Anzinger [email protected] HRT (High-res-timers): http://sourceforge.net/projects/high-res-timers/
Re: [PATCH 6/39] NLKD - early panic notification
In reply to Jan BeulichQuoted 5 lines · Jan Beulich
A mechanism to allow debuggers to intercept panic events early.
Signed-off-by Jan Beulich <[email protected]>(actual patch attached)
EXPORT_SYMBOL_GPL() for any new exports you are adding please.
thanks,
greg k-h
Re: [PATCH 3/39] NLKD - early/late CPU up/down notification
In reply to Jan BeulichQuoted 7 lines · Jan Beulich
A mechanism to allow debuggers to learn about starting/dying CPUs as early/late as possible. Arch-dependent changes for i386 and
x86_64will follow.Signed-off-by Jan Beulich <[email protected]>(actual patch attached)
Ick, but it's in base64 mode, so I can't quote it to say that your #ifdef in the .h file is not needed. Please fix your email client to send patches properly.
thanks,
greg k-h
Re: [PATCH 3/39] NLKD - early/late CPU up/down notification
Quoted 3 lines
Quoted 1 line
Quoted 1 line
Greg KH <[email protected]> 09.11.05 17:45:44 >>>
Quoted 1 line · Jan Beulich
A mechanism to allow debuggers to learn about starting/dying CPUs
as
Quoted 8 lines
Quoted 6 lines
early/late as possible. Arch-dependent changes for i386 and
x86_64will follow.Signed-off-by Jan Beulich <[email protected]>(actual patch attached)
Ick, but it's in base64 mode, so I can't quote it to say that your
That I already was made aware of. Sorry, this worked a few months ago, but they managed to break this again.
Quoted 2 lines
#ifdef in the .h file is not needed. Please fix your email client to send patches properly.
It's not needed, sure, but by having it there I just wanted to make clear that this is something that never can be called from a module (after all, why should one find out at modpost time (and maybe even miss the message since there are so many past eventual symbol resolution warnings) when one can already at compile time.
Jan
Re: [PATCH 3/39] NLKD - early/late CPU up/down notification
Quoted 9 lines · Jan Beulich
Quoted 3 lines
Quoted 1 line
Quoted 1 line
Greg KH <[email protected]> 09.11.05 17:45:44 >>>
#ifdef in the .h file is not needed. Please fix your email client to send patches properly.
It's not needed, sure, but by having it there I just wanted to make clear that this is something that never can be called from a module (after all, why should one find out at modpost time (and maybe even miss the message since there are so many past eventual symbol resolution warnings) when one can already at compile time.
If it isn't present, and you do a build, you will still get the error at build time, just during a different part of it. Adding #ifdef just to move the error to a different part of the build isn't needed. Remember, we want to not use #ifdef at all if we can ever help it.
thanks,
greg k-h
Re: [PATCH 3/39] NLKD - early/late CPU up/down notification
Quoted 4 lines
Quoted 1 line
Quoted 1 line
Greg KH <[email protected]> 09.11.05 18:19:19 >>>
Quoted 2 lines · Jan Beulich
Quoted 2 lines
Quoted 1 line
Quoted 1 line
Greg KH <[email protected]> 09.11.05 17:45:44 >>>
#ifdef in the .h file is not needed. Please fix your email client
to
Quoted 5 lines
Quoted 5 lines
Quoted 1 line
send patches properly.
It's not needed, sure, but by having it there I just wanted to make clear that this is something that never can be called from a module (after all, why should one find out at modpost time (and maybe even
miss
Quoted 4 lines
Quoted 2 lines
the message since there are so many past eventual symbol resolution warnings) when one can already at compile time.
If it isn't present, and you do a build, you will still get the error
at
Quoted 1 line
build time, just during a different part of it. Adding #ifdef just
to
Quoted 1 line
move the error to a different part of the build isn't needed.
Remember,
Quoted 1 line
we want to not use #ifdef at all if we can ever help it.
I understand that. But you don't see my point, so I'll try to explain the background: When discovering the reason for the kallsyms change (also posted with the other NLKD patches) not functioning with CONFIG_MODVERSIONS and binutils between 2.16.90 and 2.16.91.0.3 I realized that the warning messages from the modpost build stage are very easy to overlook (in fact, all reporters of the problem overlooked them as well as I did on the first build attempting to reproduce the problem). This basically means these messages are almost useless, and detection of the problem will likely be deferred to the first attempt to load an offending module (which, as in the case named, may lead to an unusable kernel). Hence, at least until this build problem gets addressed I continue to believe that adding the preprocessor conditional is the better way of dealing with potential issues. Sure I know that hundreds of other symbols possibly causing the same problem aren't protected...
Jan
Re: [PATCH 3/39] NLKD - early/late CPU up/down notification
Quoted 5 lines
I understand that. But you don't see my point, so I'll try to explain the background: When discovering the reason for the kallsyms change (also posted with the other NLKD patches) not functioning with
CONFIG_MODVERSIONSand binutils between 2.16.90 and 2.16.91.0.3 I realized that the warning messages from the modpost build stage are very
Quoted 8 lines
easy to overlook (in fact, all reporters of the problem overlooked them as well as I did on the first build attempting to reproduce the problem). This basically means these messages are almost useless, and detection of the problem will likely be deferred to the first attempt to load an offending module (which, as in the case named, may lead to an unusable kernel). Hence, at least until this build problem gets addressed I continue to believe that adding the preprocessor conditional is the better way of dealing with potential issues.
Can you elaborate a little what you like to have done to the build process.
Sam
Re: [PATCH 3/39] NLKD - early/late CPU up/down notification
Quoted 2 lines
Quoted 2 lines
Quoted 1 line
Sam Ravnborg <[email protected]> 10.11.05 21:59:31 >>>
I understand that. But you don't see my point, so I'll try to
explain
Quoted 4 lines
Quoted 4 lines
the background: When discovering the reason for the kallsyms change (also posted with the other NLKD patches) not functioning with
CONFIG_MODVERSIONSand binutils between 2.16.90 and 2.16.91.0.3 I realized that the warning messages from the modpost build stage are
very
Quoted 1 line
Quoted 1 line
easy to overlook (in fact, all reporters of the problem overlooked
them
Quoted 2 lines
Quoted 2 lines
as well as I did on the first build attempting to reproduce the problem). This basically means these messages are almost useless,
and
Quoted 1 line
Quoted 1 line
detection of the problem will likely be deferred to the first
attempt to
Quoted 1 line
Quoted 1 line
load an offending module (which, as in the case named, may lead to
an
Quoted 2 lines
Quoted 2 lines
unusable kernel). Hence, at least until this build problem gets addressed I continue to believe that adding the preprocessor
conditional
Quoted 4 lines
Quoted 1 line
is the better way of dealing with potential issues.
Can you elaborate a little what you like to have done to the build process.
As said above, I'd like to see the messages from modpost deferred or re-issued at the end of the module building process (i.e. after the perhaps hundreds of *.mod.c files got compiled and the same number of *.ko got linked, which on a typical distribution will easily scroll off the original warnings even with a 1000 line history, as seems to be the default in many cases).
Jan
Re: [PATCH 3/39] NLKD - early/late CPU up/down notification
Quoted 25 lines · On Fri, 11 Nov 2005 08:52:38 +0100 Jan Beulich wrote:
Quoted 2 lines
Quoted 2 lines
Quoted 1 line
Sam Ravnborg <[email protected]> 10.11.05 21:59:31 >>>
I understand that. But you don't see my point, so I'll try to
explain
Quoted 4 lines
Quoted 4 lines
the background: When discovering the reason for the kallsyms change (also posted with the other NLKD patches) not functioning with
CONFIG_MODVERSIONSand binutils between 2.16.90 and 2.16.91.0.3 I realized that the warning messages from the modpost build stage arevery
Quoted 1 line
Quoted 1 line
easy to overlook (in fact, all reporters of the problem overlooked
them
Quoted 2 lines
Quoted 2 lines
as well as I did on the first build attempting to reproduce the problem). This basically means these messages are almost useless,
and
Quoted 1 line
Quoted 1 line
detection of the problem will likely be deferred to the first
attempt to
Quoted 1 line
Quoted 1 line
load an offending module (which, as in the case named, may lead to
an
Quoted 2 lines
Quoted 2 lines
unusable kernel). Hence, at least until this build problem gets addressed I continue to believe that adding the preprocessor
conditional
Quoted 4 lines
Quoted 1 line
is the better way of dealing with potential issues.
Can you elaborate a little what you like to have done to the build process.
Quoted 6 lines
As said above, I'd like to see the messages from modpost deferred or re-issued at the end of the module building process (i.e. after the perhaps hundreds of *.mod.c files got compiled and the same number of *.ko got linked, which on a typical distribution will easily scroll off the original warnings even with a 1000 line history, as seems to be the default in many cases).
Lots of such error or warning messages scroll away. All that it takes is use of egrep "foo|bar" to look for the interesting messages or egrep -v "foo|bar" to discard the uninteresting (normal) messages. I do that all the time and I think that it's the right thing to do, not have the tools regurgitate something that they have already said.
---
~Randy
Re: [PATCH 3/39] NLKD - early/late CPU up/down notification
In reply to Jan BeulichQuoted 22 lines · Jan Beulich
Quoted 4 lines
Quoted 1 line
Quoted 1 line
Greg KH <[email protected]> 09.11.05 18:19:19 >>>
Quoted 2 lines · Jan Beulich
Quoted 2 lines
Quoted 1 line
Quoted 1 line
Greg KH <[email protected]> 09.11.05 17:45:44 >>>
#ifdef in the .h file is not needed. Please fix your email client
to
Quoted 5 lines
Quoted 5 lines
Quoted 1 line
send patches properly.
It's not needed, sure, but by having it there I just wanted to make clear that this is something that never can be called from a module (after all, why should one find out at modpost time (and maybe even
miss
Quoted 4 lines
Quoted 2 lines
the message since there are so many past eventual symbol resolution warnings) when one can already at compile time.
If it isn't present, and you do a build, you will still get the error
at
Quoted 1 line
build time, just during a different part of it. Adding #ifdef just
to
Quoted 1 line
move the error to a different part of the build isn't needed.
Remember,
Quoted 1 line
we want to not use #ifdef at all if we can ever help it.
Quoted 8 lines
I understand that. But you don't see my point, so I'll try to explain the background: When discovering the reason for the kallsyms change (also posted with the other NLKD patches) not functioning with
CONFIG_MODVERSIONSand binutils between 2.16.90 and 2.16.91.0.3 I realized that the warning messages from the modpost build stage are very easy to overlook (in fact, all reporters of the problem overlooked them as well as I did on the first build attempting to reproduce the problem).
When you try to load the module, you will get the error again, right in your kernel/system log, which explicitly shows that you had a problem.
Quoted 8 lines
This basically means these messages are almost useless, and detection of the problem will likely be deferred to the first attempt to load an offending module (which, as in the case named, may lead to an unusable kernel). Hence, at least until this build problem gets addressed I continue to believe that adding the preprocessor conditional is the better way of dealing with potential issues. Sure I know that hundreds of other symbols possibly causing the same problem aren't protected...
Don't try to do things to fix your prior problems in your patch, with changes today so that you don't do it again in the future :)
The build process properly notifies the builder of the problem, if they ignore it, there's really nothing more we can do about it, right?
thanks,
greg k-h
Re: [PATCH 2/39] NLKD - an alternative early ioremap approach
In reply to Jan BeulichHi!
Quoted 8 lines
An alternative to (on i386) boot-time ioremap approaches, which is more architecture independent (though arch dependent code needs adjustments if this is to be made use of, which with this patch only happens for i386 and
x86_64) and doesn't require alternative boot-time interfaces.Signed-off-by Jan Beulich <[email protected]>(actual patch attached)
Can you inline those patches? I do not care what email system you are using, get gmail account if you have to. Or just ask for suse.de/suse.cz account.
Ouch and btw the patch is wrong in first hunk, it adds #else/#endif without #ifdef. Ouch.
Pavel
Signature · 1 line
Thanks, Sharp!
Re: [PATCH 2/39] NLKD - an alternative early ioremap approach
Quoted 2 lines
Ouch and btw the patch is wrong in first hunk, it adds #else/#endif without #ifdef. Ouch.
It only adds #else, #if and #endif already exist...
Jan
Re: [PATCH 1/39] NLKD - an alternative kallsyms approach
In reply to Jan BeulichQuoted 21 lines · Jan Beulich
This patch provides an alternative to the pre-exisiting kallsyms code. That code, from a kernel debugger perspective at least, suffers from incomplete information, making it impossible to
(a) disambiguate multiple static functions of the same name (in different source files),
(b) determine a complete set of attributes for a symbol (namely, the symbol's size, but also its type, which gets converted to an nm-like one-character representation), and
(c) retain full section informationThis new approach basically makes handling core kernel and module symbols the same, by retrieving the kernel's section, symbol, and string tables rather than parsing the system map.
At once it adds the functionality to strip unneeded symbols from modules, which results in non-neglectable space savings for typical distributions (which large amounts of modules). Note that with certain recent, but broken binutils versions (2.16.90*, 2.16.91* up to and including 2.16.91.0.3) this can only be built without
CONFIG_MODVERSIONS.
Quoted 3 lines
Signed-off-by Jan Beulich <[email protected]>(actual patch attached)
It's still not a text-type attachment...
BTW, are you posting these just for comments or did you want someone to apply/merge them? If so, who? You should send them to that someone (unless you have some other arrangements) -- at least that's the normal procedure.
Signature · 1 line
~Randy
Re: [PATCH 1/39] NLKD - an alternative kallsyms approach
Quoted 4 lines · Randy.Dunlap
BTW, are you posting these just for comments or did you want someone to apply/merge them? If so, who? You should send them to that someone (unless you have some other arrangements) -- at least that's the normal procedure.
And the documented one too, see Documentation/SubmittingPatches, section 5.
Why does no one ever read the documentation...
greg k-h
Re: [PATCH 1/39] NLKD - an alternative kallsyms approach
In reply to Randy.DunlapQuoted 4 lines
BTW, are you posting these just for comments or did you want someone to apply/merge them? If so, who? You should send them to that someone (unless you have some other arrangements) -- at least that's the normal procedure.
I don't expect the debugger itself to be merged, but I hope the preparatory pieces could be. And then, if not Andrew (who, as far as I can see, picks up things from the list just as much as stuff directly addressed to him), who would I send this to? There's doesn't seem to be a clear maintainer of i386, for example, and that seems to be the case for many other parts, too.
Jan
Quoted 2 lines · Jan Beulich
The following patch set represents the Novell Linux Kernel Debugger, stripped off of its original low-level exception handling framework.
Honestly, just seeing all these code changes makes me think we really don't need it in the kernel. How many "early" and "alternative" gadgets do we really need just for this thing?
Jeff
Quoted 8 lines · Jeff Garzik
Quoted 2 lines · Jan Beulich
The following patch set represents the Novell Linux Kernel Debugger, stripped off of its original low-level exception handling framework.
Honestly, just seeing all these code changes makes me think we really don't need it in the kernel. How many "early" and "alternative" gadgets do we really need just for this thing?
On the surface I have to agree. However, if Jan wants feedback on the patches, that's a reasonable request IMO.
(but they need to be readable via email so that someone can comment on them)
At a quick blush, I would guess it has as much chance as kdb does (or did) for merging.
Signature · 1 line
~Randy
Quoted 2 lines
On the surface I have to agree. However, if Jan wants feedback on the patches, that's a reasonable request IMO.
Getting feedback is not the only goal.
Quoted 2 lines
(but they need to be readable via email so that someone can comment on them)
Sorry, I hear this quite often, but I also have to play by some company rules, one of which is to use a certain mail system (or otherwise be left alone in case of problems).
Quoted 2 lines
At a quick blush, I would guess it has as much chance as kdb does (or did) for merging.
The intention isn't necessarily to merge the whole debugger, but what we desire is to merge everything to allow the debugger to be built outside of the tree (perhaps as a standalong module).
Jan
Quoted 3 lines · Jan Beulich
Sorry, I hear this quite often, but I also have to play by some company rules, one of which is to use a certain mail system (or otherwise be left alone in case of problems).
Which is more important. Your employers email system or the ability of people to quote and work easily with patches ? Please send patches in a sensible format, even if you use a different mail tool for all your other email.
Other Novell contributors many of them large and important contributors from SuSE don't appear to be having this problem
Quoted 4 lines · Jan Beulich
Quoted 2 lines
On the surface I have to agree. However, if Jan wants feedback on the patches, that's a reasonable request IMO.
Getting feedback is not the only goal.
What is the goal? You never stated it.
Quoted 6 lines
Quoted 2 lines
(but they need to be readable via email so that someone can comment on them)
Sorry, I hear this quite often, but I also have to play by some company rules, one of which is to use a certain mail system (or otherwise be left alone in case of problems).
Please remember, lkml does _not_ care about any company rules. You need to follow the community's rules, not try to get the community to follow yours, if you wish to get them to do anything.
thanks,
greg k-h
Quoted 3 lines · Jan
Sorry, I hear this quite often, but I also have to play by some company rules, one of which is to use a certain mail system (or otherwise be left alone in case of problems).
May I recommend a separate tool for sending patches, instead of using your email client. Consider for example:
http://www.speakeasy.org/~pj99/sgi/sendpatchset
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.925.600.0401Quoted 6 lines · Jan Beulich
Quoted 2 lines
At a quick blush, I would guess it has as much chance as kdb does (or did) for merging.
The intention isn't necessarily to merge the whole debugger, but what we desire is to merge everything to allow the debugger to be built outside of the tree (perhaps as a standalong module).
While you're posted a few actually useful patches that fix or encehance core code we're not going to put in any of your odd hooks or exports. As you might have noticed while reading lkml we are everything but keen on those.
Quoted 11 lines · Randy.Dunlap
Quoted 8 lines · Jeff Garzik
Quoted 2 lines · Jan Beulich
The following patch set represents the Novell Linux Kernel Debugger, stripped off of its original low-level exception handling framework.
Honestly, just seeing all these code changes makes me think we really don't need it in the kernel. How many "early" and "alternative" gadgets do we really need just for this thing?
Quoted 7 lines
On the surface I have to agree. However, if Jan wants feedback on the patches, that's a reasonable request IMO.
(but they need to be readable via email so that someone can comment on them)At a quick blush, I would guess it has as much chance as kdb does (or did) for merging.
I hope we can follow the same strategy as I did for debuggers on x86-64 - which imho worked very well. Get all the (sane) hooks in so that everybody who wants to use their particular flavour of debugger can use it by (ideally) either just loading it or alternatively applying a small core patch and the debugger files elsewhere. The die chains started from that.
Making the debugger work modular is a bit more work, but possible (was done for kdb at least before with some changes). IMHO that's the ideal state for users - they can just compile it externally and load it when they need it, but the core kernel doesn't need to carry it. It conflicts a bit with the usual policy of not exporting stuff that's not used in the core kernel; but I think making an exception here is reasonable because
So I guess it's best to concentrate on merging the hooks needed in a sane way.
I think the many additions for "early" code in the NLKD patchkit comes from Jan's desire to make the debugger work in as many weird corner cases as possible. I must say he found a lot of problems in corner cases during that work in x86-64 and i386, fixing generic bugs and making even the standard oops code and other error handling code (e.g. double faults on i386) more reliable, which I appreciate.
The particular early changes have to be weighted of course in intrusiveness. If it's simple and not too ugly stuff I guess it is reasonable to consider it. If not the debugger will have to live without it.
I already merged all the changes that looked good (and where I was cc'ed) for x86-64 now. Some patches need changes, and I guess with that feedback the i386 part can be similarly adjusted.
-Andi
Quoted 30 lines · Andi Kleen
Quoted 16 lines · Randy.Dunlap
Quoted 12 lines · Jeff Garzik
Quoted 4 lines · Jan Beulich
The following patch set represents the Novell Linux Kernel Debugger, stripped off of its original low-level exception handling framework.
Honestly, just seeing all these code changes makes me think we really don't need it in the kernel. How many "early" and "alternative" gadgets do we really need just for this thing?
Quoted 9 lines
On the surface I have to agree. However, if Jan wants feedback on the patches, that's a reasonable request IMO.
(but they need to be readable via email so that someone can comment on them)At a quick blush, I would guess it has as much chance as kdb does (or did) for merging.
Quoted 6 lines
I hope we can follow the same strategy as I did for debuggers on x86-64 - which imho worked very well. Get all the (sane) hooks in so that everybody who wants to use their particular flavour of debugger can use it by (ideally) either just loading it or alternatively applying a small core patch and the debugger files elsewhere. The die chains started
from that.
Yes. This is the way to go. Use kdb as a base and instrument an alternate debugger interface. You need to also find a good way to allow GDB to work properly with alternate debuggers. At present, the code in traps.c is mutually exclusive since embedded int3 breakpoints trigger in the kernel for gbd. This is busted.
Jeff
Quoted 34 lines
Making the debugger work modular is a bit more work, but possible (was done for kdb at least before with some changes). IMHO that's the ideal state for users - they can just compile it externally and load it when they need it, but the core kernel doesn't need to carry it. It conflicts a bit with the usual policy of not exporting stuff that's not used in the core kernel; but I think making an exception here is reasonable because
So I guess it's best to concentrate on merging the hooks needed in a sane way.
I think the many additions for "early" code in the NLKD patchkit
comes from Jan's desire to make the debugger work in as many weird
corner cases as possible. I must say he found a lot of problems in corner cases during that work in x86-64 and i386, fixing generic bugs and making even the standard oops code and other error handling
code (e.g. double faults on i386) more reliable, which I appreciate.The particular early changes have to be weighted of course in intrusiveness. If it's simple and not too ugly stuff I guess it is reasonable to consider it. If not the debugger will have to live without it.
I already merged all the changes that looked good (and where I was cc'ed) for x86-64 now. Some patches need changes, and I guess with that feedback the i386 part can be similarly adjusted.
(quoted diff) +0
-2-Andi -To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Quoted 5 lines · jmerkey
Yes. This is the way to go. Use kdb as a base and instrument an alternate debugger interface. You need to also find a good way to allow GDB to work properly with alternate debuggers. At present, the code in
traps.cis mutually exclusive since embedded int3 breakpoints trigger in the kernel for gbd. This is busted.
I don't think we'll support stacking multiple kernel debuggers (except for special cases like kprobes+another debugger). It's complicated and probably not worth it.
-Andi
Quoted 11 lines · Andi Kleen
Quoted 5 lines · jmerkey
Yes. This is the way to go. Use kdb as a base and instrument an alternate debugger interface. You need to also find a good way to allow GDB to work properly with alternate debuggers. At present, the code in
traps.cis mutually exclusive since embedded int3 breakpoints trigger in the kernel for gbd. This is busted.
Quoted 9 lines
I don't think we'll support stacking multiple kernel debuggers (except for special cases like kprobes+another debugger). It's complicated and probably not worth it.
-Andi
I already instrumented an alternate debugger interface in MDB. It's not complicated at all. Here's the code. All you
need to do is change two places. Add the alternate interface into kdb, and fix the int3 contention problem with GDB. GDB support with kdb action involves creating a callback into GDB signaling the int3 POST kdb handling. In other words, keep a table of breakpoints for int3 alternate debuggers they must register, compare against this table and divert the int3 on this basis, it is matches the table, send to the registered debugger entry point, if it doesn't match, call the GDB handler and send it to userspace. Seems simple. Here's part one. Someone else can write part 2.
Jeff
linux-2.6.9-mdb/./kdb/kdbmain.c 2004-10-18 11:44:47.000000000 -0600 renamed from kdb/kdbmain.c 2004-10-18 11:46:59.439535288 -0600 +0 -0
@@ -57,7 +57,12 @@
int kdb_seqno = 2; /* how many times kdb has been entered */
volatile int kdb_nextline = 1;
+
+#if defined(CONFIG_MDB)
+volatile int kdb_new_cpu; /* Which cpu to switch to */
+#else
static volatile int kdb_new_cpu; /* Which cpu to switch to */
+#endif
volatile int kdb_state[NR_CPUS]; /* Per cpu state */
@@ -1134,8 +1139,13 @@
extern char kdb_prompt_str[];
+#if defined(CONFIG_MDB)
static intkdb_local(kdb_reason_t reason, int error, struct pt_regs *regs, kdb_dbtrap_t db_result) +#else
+int
+kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs, kdb_dbtrap_t db_result) +#endif
{
char *cmdbuf;
int diag;
@@ -1676,6 +1686,27 @@
int result = 0; /* Default is kdb did not handle it */
int ss_event;
kdb_dbtrap_t db_result=KDB_DB_NOBPT;+
+#if defined(CONFIG_MDB)
+ extern int AlternateDebuggerRoutine(kdb_reason_t reason, int error,
+ struct pt_regs *ef);
+ if (!kdb_on)
+ return 0;
+
+ result = AlternateDebuggerRoutine(reason, error, regs);
+ switch (result)
+ {+ case 1: // alternate debugger handled event
+ return 1;
+
+ case -1: // alternate debugger did not handle event
+ return 0;
+
+ default: // drop into kdb
+ break;
+ }
+#endif
+
atomic_inc(&kdb_event);
switch(reason) {@@ -3016,6 +3047,40 @@
* Remarks:
*/
+#if defined (CONFIG_MDB)
+
+#include <linux/mdbglobals.h>
+
+void
+mdb_ps1(struct task_struct *p)
+{
+ DBGPrint("0x%p %8d %8d %d %4d %c 0x%p %c%s\n",
+ (void *)p, p->pid, p->parent->pid, + kdb_task_has_cpu(p), kdb_process_cpu(p), + (p->state == 0) ? 'R' : + (p->state < 0) ? 'U' : + (p->state & TASK_UNINTERRUPTIBLE) ? 'D' : + (p->state & TASK_STOPPED || p->ptrace & PT_PTRACED) ? 'T' : + (p->state & TASK_ZOMBIE) ? 'Z' : + (p->state & TASK_INTERRUPTIBLE) ? 'S' : '?', + (void *)(&p->thread), + (p == current) ? '*': ' ', + p->comm);
+ if (kdb_task_has_cpu(p)) {
+ struct kdb_running_process *krp = kdb_running_process + kdb_process_cpu(p);
+ if (!krp->seqno || !krp->p)
+ DBGPrint(" Error: no saved data for this cpu\n");
+ else {
+ if (krp->seqno < kdb_seqno - 1)
+ DBGPrint(" Warning: process state is stale\n");
+ if (krp->p != p)
+ DBGPrint(" Error: does not match running process table (0x%p)\n", krp->p);
+ }
+ }
+}
+
+#endif
+
voidkdb_ps1(struct task_struct *p)
{
@@ -3835,6 +3900,10 @@
void __initkdb_init(void)
{
+#if defined(CONFIG_MDB)
+ extern void mdb_init(void); +#endif
+
kdb_initial_cpu = smp_processor_id();
/*
* This must be called before any calls to kdb_printf.@@ -3855,6 +3924,11 @@
kdb_cmd_init(); /* Preset commands from kdb_cmds */
kdb_initial_cpu = -1; /* Avoid recursion problems */
+
+#if defined(CONFIG_MDB)
+ mdb_init(); +#endif
+
kdb(KDB_REASON_SILENT, 0, 0); /* Activate any preset breakpoints
on boot cpu */
kdb_initial_cpu = smp_processor_id();
notifier_chain_register(&panic_notifier_list, &kdb_block);Quoted 154 lines · Jeff V. Merkey
Quoted 11 lines · Andi Kleen
Quoted 4 lines · jmerkey
Yes. This is the way to go. Use kdb as a base and instrument an alternate debugger interface. You need to also find a good way to allow GDB to work properly with alternate debuggers. At present, the code in
traps.cis mutually exclusive since embedded int3 breakpoints trigger in the kernel for gbd. This is busted.Quoted 9 lines
I don't think we'll support stacking multiple kernel debuggers (except for special cases like kprobes+another debugger). It's complicated and probably not worth it.
-Andi
I already instrumented an alternate debugger interface in MDB. It's not complicated at all. Here's the code. All you
need to do is change two places. Add the alternate interface into kdb, and fix the int3 contention problem with GDB. GDB support with kdb action involves creating a callback into GDB signaling the int3 POST kdb handling. In other words, keep a table of breakpoints for int3 alternate debuggers they must register, compare against this table and divert the int3 on this basis, it is matches the table, send to the registered debugger entry point, if it doesn't match, call the GDB handler and send it to userspace. Seems simple. Here's part one. Someone else can write part 2.Jeff
diff -Naur./kdb/kdbmain.c../linux-2.6.9-mdb/./kdb/kdbmain.clinux-2.6.9-mdb/./kdb/kdbmain.c 2004-10-18 renamed from kdb/kdbmain.c 2004-10-18 11:46:59.439535288 -0600 +0
-011:44:47.000000000 -0600
linux-2.6.9-mdb/./kdb/kdbmain.c 2004-10-18 renamed from kdb/kdbmain.c 2004-10-18 11:46:59.439535288 -0600 +0
-0@@ -57,7 +57,12 @@int
kdb_seqno= 2; /* how many times kdb has been entered */volatile int
kdb_nextline= 1;linux-2.6.9-mdb/./kdb/kdbmain.c 2004-10-18 renamed from kdb/kdbmain.c 2004-10-18 11:46:59.439535288 -0600 +4
-0+ +#if defined(CONFIG_MDB) +volatile int kdb_new_cpu; /* Which cpu to switch to */ +#elsestatic volatile int
kdb_new_cpu; /* Which cpu to switch to */
+#endifvolatile int kdb_state[NR_CPUS]; /* Per cpu state */
linux-2.6.9-mdb/./kdb/kdbmain.c 2004-10-18 renamed from kdb/kdbmain.c 2004-10-18 11:46:59.439535288 -0600 +1
-0@@ -1134,8 +1139,13 @@ extern char kdb_prompt_str[]; +#if defined(CONFIG_MDB)static int
kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs, kdb_dbtrap_t db_result)linux-2.6.9-mdb/./kdb/kdbmain.c 2004-10-18 renamed from kdb/kdbmain.c 2004-10-18 11:46:59.439535288 -0600 +3
-0+#else +int +kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs,
kdb_dbtrap_tdb_result)
+#endif{ char *cmdbuf; int diag;linux-2.6.9-mdb/./kdb/kdbmain.c 2004-10-18 renamed from kdb/kdbmain.c 2004-10-18 11:46:59.439535288 -0600 +21
-0@@ -1676,6 +1686,27 @@ int result = 0; /* Default is kdb did not handle it */ int ss_event; kdb_dbtrap_t db_result=KDB_DB_NOBPT; + +#if defined(CONFIG_MDB) + extern int AlternateDebuggerRoutine(kdb_reason_t reason, int error, + struct pt_regs *ef); + if (!kdb_on) + return 0; + + result = AlternateDebuggerRoutine(reason, error, regs); + switch (result) + { + case 1: // alternate debugger handled event + return 1; + + case -1: // alternate debugger did not handle event + return 0; + + default: // drop into kdb + break; + } +#endif + atomic_inc(&kdb_event);switch(reason) {linux-2.6.9-mdb/./kdb/kdbmain.c 2004-10-18 renamed from kdb/kdbmain.c 2004-10-18 11:46:59.439535288 -0600 +34
-0@@ -3016,6 +3047,40 @@ * Remarks: */ +#if defined (CONFIG_MDB) + +#include <linux/mdbglobals.h> + +void +mdb_ps1(struct task_struct *p) +{ + DBGPrint("0x%p %8d %8d %d %4d %c 0x%p %c%s\n", + (void *)p, p->pid, p->parent->pid, + kdb_task_has_cpu(p), kdb_process_cpu(p), + (p->state == 0) ? 'R' : + (p->state < 0) ? 'U' : + (p->state & TASK_UNINTERRUPTIBLE) ? 'D' : + (p->state & TASK_STOPPED || p->ptrace & PT_PTRACED) ? 'T' : + (p->state & TASK_ZOMBIE) ? 'Z' : + (p->state & TASK_INTERRUPTIBLE) ? 'S' : '?', + (void *)(&p->thread), + (p == current) ? '*': ' ', + p->comm); + if (kdb_task_has_cpu(p)) { + struct kdb_running_process *krp = kdb_running_process + kdb_process_cpu(p); + if (!krp->seqno || !krp->p) + DBGPrint(" Error: no saved data for this cpu\n"); + else { + if (krp->seqno < kdb_seqno - 1) + DBGPrint(" Warning: process state is stale\n"); + if (krp->p != p) + DBGPrint(" Error: does not match running process table (0x%p)\n", krp->p); + } + } +} + +#endif +void
kdb_ps1(struct task_struct *p)
{linux-2.6.9-mdb/./kdb/kdbmain.c 2004-10-18 renamed from kdb/kdbmain.c 2004-10-18 11:46:59.439535288 -0600 +0
-0@@ -3835,6 +3900,10 @@void
__initkdb_init(void)
{linux-2.6.9-mdb/./kdb/kdbmain.c 2004-10-18 renamed from kdb/kdbmain.c 2004-10-18 11:46:59.439535288 -0600 +7
-0+#if defined(CONFIG_MDB) + extern void mdb_init(void); +#endif + kdb_initial_cpu = smp_processor_id(); /* * This must be called before any calls to kdb_printf.@@ -3855,6 +3924,11 @@ kdb_cmd_init(); /* Preset commands from kdb_cmds */ kdb_initial_cpu = -1; /* Avoid recursion problems */ + +#if defined(CONFIG_MDB) + mdb_init(); +#endif + kdb(KDB_REASON_SILENT, 0, 0); /* Activate any presetbreakpoints on boot cpu */
Quoted 4 lines
kdb_initial_cpu = smp_processor_id();
notifier_chain_register(&panic_notifier_list, &kdb_block);Alternate Debuggers should register an init function called from kdb_init. Calling AlternateDebuggerInterface should call all registred debuggers
and allow each one to report status. NetWare has had an alternate debugger interface for years. It's easy to instrument. The only thing in Linux that's odd at all is the way GDB int3's are handled. All this other stuff they are making you put in is not the problem of Linux.
Jeff
Jeff
Quoted 3 lines · Jeff Garzik
Honestly, just seeing all these code changes makes me think we really don't need it in the kernel. How many "early" and "alternative" gadgets do we really need just for this thing?
I think it is clearly the case that the design is wrong. The existance of kgdb shows how putting the complex logic remotely on another system is not only a lot cleaner and simpler but can also provide more functionality and higher reliability.
The presence of user mode linux and Xen also provide solutions to the usual concern about needing two systems, as will future hardware features.
Alan
Quoted 7 lines · Alan Cox
Quoted 3 lines · Jeff Garzik
Honestly, just seeing all these code changes makes me think we really don't need it in the kernel. How many "early" and "alternative" gadgets do we really need just for this thing?
Quoted 10 lines
I think it is clearly the case that the design is wrong. The existance of kgdb shows how putting the complex logic remotely on another system is not only a lot cleaner and simpler but can also provide more functionality and higher reliability.
The presence of user mode linux and Xen also provide solutions to the usual concern about needing two systems, as will future hardware features.
Not necessarily true with regard to having the functionality in the kernel, but for Linux, probably better for maintenance based on the social issues. I have MDB fully integrated in the kernel and I don't have all these problems. It's just an update to the kdb hooks, patch, build and go. Novell should probably just fork the kernel and start their own distro and dump the mainstream Linux. They have the people and infrastructure to support drivers and do just as good a job as LKML with the old NetWare group. Novell was presented with MDB two years ago and opted to build their own rather than go with ours. I have been disappointed with the quality of what they have produced to date.
They should fork form Linux and understand that the Linux folks and their culture is totaly alien to Novell's culture. They will never make
progress with the Linux folks and continued interactions will waste both groups time. They have the talent and resources to preempt Linux and do their own thing. They need to just go and do it.
J
Quoted 10 lines
Alan
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Quoted 5 lines · Alan Cox
I think it is clearly the case that the design is wrong. The existance of kgdb shows how putting the complex logic remotely on another system is not only a lot cleaner and simpler but can also provide more functionality and higher reliability.
Unless the target machine is modern (2005+ era) and has no serial ports, nor any way to add them other than via the USB stack.
Cheers
Quoted 9 lines · Mark Lord
Quoted 5 lines · Alan Cox
I think it is clearly the case that the design is wrong. The existance of kgdb shows how putting the complex logic remotely on another system is not only a lot cleaner and simpler but can also provide more functionality and higher reliability.
Unless the target machine is modern (2005+ era) and has no serial ports, nor any way to add them other than via the USB stack.
There's always ethernet. Or, where there is a will, there is a way, as shown by PowerPC's xmon over firewire.
Signature · 2 lines
Tom Rini http://gate.crashing.org/~trini/
Quoted 2 lines · Mark Lord
Unless the target machine is modern (2005+ era) and has no serial ports, nor any way to add them other than via the USB stack.
Debugger USB serial isn't hard. A micro polled USB stack is tiny (see for example the BIOS USB in a PC). You've also get ethernet and firewire. gdb remote has supported ethernet for years along with just about anything else you can get a bitstream in and out of.
Alan
Quoted 9 lines · Mark Lord
Quoted 5 lines · Alan Cox
I think it is clearly the case that the design is wrong. The existance of kgdb shows how putting the complex logic remotely on another system is not only a lot cleaner and simpler but can also provide more functionality and higher reliability.
Unless the target machine is modern (2005+ era) and has no serial ports, nor any way to add them other than via the USB stack.
Firewire looks most promising actually right now, at least for Desktop/Laptop type systems. And servers still have serial ports right now, either in hardware or simulated in some way.
-Andi
A message that is not in the archive (sent off-list or not yet received): [email protected]
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 32/39] NLKD/x86-64 - Core Debug Engine
Quoted 1 line · Jan Beulich
The x86_64-dependent part of the Core Debug Engine of NLKD.
Same comment as #25.
-Andi