Skip to contentSkip to conversation

NLKD - Novell Linux Kernel Debugger

PATCH NAK Jan Beulich 20 participants 105 messages Nov 9, 2005 – Nov 15, 2005 5 messages not in the archive

Subsystems (22)
Memory management Kbuild MIPS MM core +18 more subsystems
lore
Share & tools
lore
#0 lore raw

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

#1 lore raw

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 lon
 			    unsigned 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
#2 lore raw

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
Index: 2.6.14-nlkd/arch/i386/kernel/setup.c
===================================================================
@@ -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
Index: 2.6.14-nlkd/arch/i386/mm/init.c
===================================================================
@@ -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
Index: 2.6.14-nlkd/arch/i386/mm/ioremap.c
===================================================================
@@ -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
Index: 2.6.14-nlkd/arch/i386/mm/pgtable.c
===================================================================
@@ -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_addresses 
 
 pte_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
Index: 2.6.14-nlkd/arch/x86_64/kernel/setup.c
===================================================================
@@ -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
Index: 2.6.14-nlkd/arch/x86_64/mm/init.c
===================================================================
@@ -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
Index: 2.6.14-nlkd/arch/x86_64/mm/ioremap.c
===================================================================
@@ -266,5 +266,6 @@ void iounmap(volatile void __iomem *addr
 	else 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
Index: 2.6.14-nlkd/include/linux/vmalloc.h
===================================================================
@@ -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
Index: 2.6.14-nlkd/mm/page_alloc.c
===================================================================
@@ -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
Index: 2.6.14-nlkd/mm/vmalloc.c
===================================================================
@@ -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 *a
 	return 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 deallocate
 			kfree(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);
#3 lore raw

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
Index: 2.6.14-nlkd/include/linux/cpu.h
===================================================================
@@ -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
Index: 2.6.14-nlkd/include/linux/notifier.h
===================================================================
@@ -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
Index: 2.6.14-nlkd/kernel/cpu.c
===================================================================
@@ -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)
 {
#4 lore raw

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
Index: 2.6.14-nlkd/arch/i386/kernel/smpboot.c
===================================================================
@@ -486,6 +486,7 @@ static void __devinit start_secondary(vo
 	smp_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();
#5 lore raw

PATCH 5/39 NLKD/x86-64 - early/late CPU up/down notification

In reply to Jan Beulich

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]>

(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
Index: 2.6.14-nlkd/arch/x86_64/kernel/process.c
===================================================================
@@ -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
Index: 2.6.14-nlkd/arch/x86_64/kernel/smpboot.c
===================================================================
@@ -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();
 
#6 lore raw

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

#7 lore raw

[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

#8 lore raw

Re: [discuss] Re: [PATCH 5/39] NLKD/x86-64 - early/late CPU up/down notification

Quoted 1 line · Jan Beulich

Assuming you mean CPU_ONLINE and CPU_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

#9 lore raw

PATCH 6/39 NLKD - early panic notification

In reply to Jan Beulich

A 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
Index: 2.6.14-nlkd/include/linux/kernel.h
===================================================================
@@ -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
Index: 2.6.14-nlkd/kernel/panic.c
===================================================================
@@ -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);
 
 	/*
#10 lore raw

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
Index: 2.6.14-nlkd/include/linux/sched.h
===================================================================
@@ -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 __user
 extern 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
Index: 2.6.14-nlkd/kernel/fork.c
===================================================================
@@ -64,6 +64,9 @@ DEFINE_PER_CPU(unsigned long, process_co
 
 EXPORT_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
#11 lore raw

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
Index: 2.6.14-nlkd/kernel/module.c
===================================================================
@@ -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(&notify_mutex);
+	notifier_call_chain(&module_notify_list, MODULE_STATE_GOING, mod);
+	up(&notify_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(&notify_mutex);
+			notifier_call_chain(&module_notify_list, MODULE_STATE_GOING, mod);
+			up(&notify_mutex);
+		}
 		else {
 			module_put(mod);
 			down(&module_mutex);
#12 lore raw

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
Index: 2.6.14-nlkd/drivers/char/keyboard.c
===================================================================
@@ -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
Index: 2.6.14-nlkd/include/linux/kdebug.h
===================================================================
@@ -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
#13 lore raw

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
Index: 2.6.14-nlkd/drivers/video/console/fbcon.c
===================================================================
@@ -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(struct
 	return 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, int 
  		if (!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
Index: 2.6.14-nlkd/drivers/video/console/fbcon.h
===================================================================
@@ -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
Index: 2.6.14-nlkd/drivers/video/console/vgacon.c
===================================================================
@@ -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 v
 	outb_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
Index: 2.6.14-nlkd/drivers/video/fbmem.c
===================================================================
@@ -673,8 +673,17 @@ fb_set_var(struct fb_info *info, struct 
 
 		if ((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
Index: 2.6.14-nlkd/include/linux/fb.h
===================================================================
@@ -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
Index: 2.6.14-nlkd/include/video/vga.h
===================================================================
@@ -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__ */
#14 lore raw

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
Index: 2.6.14-nlkd/include/linux/jiffies.h
===================================================================
@@ -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
Index: 2.6.14-nlkd/kernel/timer.c
===================================================================
@@ -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);
#15 lore raw

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
Index: 2.6.14-nlkd/arch/i386/kernel/timers/common.c
===================================================================
@@ -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
Index: 2.6.14-nlkd/arch/i386/kernel/timers/timer_hpet.c
===================================================================
@@ -99,7 +99,7 @@ static unsigned long get_offset_hpet(voi
 static 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
Index: 2.6.14-nlkd/include/asm-i386/timer.h
===================================================================
@@ -57,7 +57,7 @@ extern struct init_timer_opts timer_cycl
 
 extern 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;
#16 lore raw

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.

(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/
#17 lore raw

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.

(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

#18 lore raw

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/
#19 lore raw

PATCH 13/39 NLKD/x86-64 - time adjustment

In reply to 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]>

(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
Index: 2.6.14-nlkd/arch/x86_64/kernel/pmtimer.c
===================================================================
@@ -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
Index: 2.6.14-nlkd/include/asm-x86_64/vsyscall.h
===================================================================
@@ -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;
#20 lore raw

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
Index: 2.6.14-nlkd/arch/x86_64/kernel/asm-offsets.c
===================================================================
@@ -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
Index: 2.6.14-nlkd/arch/x86_64/kernel/entry.S
===================================================================
@@ -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
Index: 2.6.14-nlkd/arch/x86_64/kernel/setup64.c
===================================================================
@@ -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
Index: 2.6.14-nlkd/arch/x86_64/kernel/traps.c
===================================================================
@@ -121,19 +121,31 @@ int printk_address(unsigned long address
 static 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 pt
 		io_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,&divide_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
Index: 2.6.14-nlkd/include/asm-x86_64/desc.h
===================================================================
@@ -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
Index: 2.6.14-nlkd/include/asm-x86_64/pda.h
===================================================================
@@ -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
Index: 2.6.14-nlkd/include/asm-x86_64/processor.h
===================================================================
@@ -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));	 \
#21 lore raw

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
Index: 2.6.14-nlkd/arch/x86_64/ia32/ia32entry.S
===================================================================
@@ -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
Index: 2.6.14-nlkd/arch/x86_64/kernel/entry.S
===================================================================
@@ -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
Index: 2.6.14-nlkd/arch/x86_64/kernel/vmlinux.lds.S
===================================================================
@@ -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
Index: 2.6.14-nlkd/include/asm-x86_64/calling.h
===================================================================
@@ -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
#22 lore raw

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
Index: 2.6.14-nlkd/arch/x86_64/kernel/process.c
===================================================================
@@ -505,6 +505,10 @@ struct task_struct *__switch_to(struct t
 	int 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);
 
 	/*
#23 lore raw

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
Index: 2.6.14-nlkd/arch/x86_64/ia32/ptrace32.c
===================================================================
@@ -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
Index: 2.6.14-nlkd/arch/x86_64/kernel/process.c
===================================================================
@@ -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 cl
 		if (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
Index: 2.6.14-nlkd/arch/x86_64/kernel/ptrace.c
===================================================================
@@ -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
Index: 2.6.14-nlkd/arch/x86_64/kernel/setup64.c
===================================================================
@@ -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
Index: 2.6.14-nlkd/arch/x86_64/kernel/signal.c
===================================================================
@@ -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
Index: 2.6.14-nlkd/arch/x86_64/kernel/suspend.c
===================================================================
@@ -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
Index: 2.6.14-nlkd/arch/x86_64/kernel/traps.c
===================================================================
@@ -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
Index: 2.6.14-nlkd/arch/x86_64/kernel/vmlinux.lds.S
===================================================================
@@ -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
Index: 2.6.14-nlkd/include/asm-x86_64/processor.h
===================================================================
@@ -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
Index: 2.6.14-nlkd/include/asm-x86_64/suspend.h
===================================================================
@@ -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
Index: 2.6.14-nlkd/include/asm-x86_64/system.h
===================================================================
@@ -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 */
#24 lore raw

Re: [PATCH 20/39] NLKD/x86-64 - switch_to() floating point adjustment

In reply to Jan Beulich
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's TS_USEDFPU flag and CR0.TS could get out of sync.

Didn't we agree earlier on moving unlazy_fpu() down instead?

-Andi

#25 lore raw

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's TS_USEDFPU flag 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

#26 lore raw

Re: [PATCH 19/39] NLKD/x86-64 - stack-pointer-invalid markers

In reply to Jan Beulich
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?

-Andi

#27 lore raw

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

#28 lore raw

Re: [PATCH 18/39] NLKD/x86-64 - INT1/INT3 handling changes

In reply to Jan Beulich
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

Looks reasonable except for the CONFIG_NLKD hunk, which doesn't seem to be related. I think I'll apply it without that.

-Andi

#29 lore raw

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_NLKD hunk, 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

#30 lore raw

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_NLKD hunk, 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.

!NLKD code relying on CONFIG_NLKD code? That sounds wrong. I won't apply it then. Please clean up first.

-Andi

#31 lore raw

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_NLKD hunk, 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.c and traps.c.

!NLKD code relying on CONFIG_NLKD code? 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

#32 lore raw

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.h cannot include processor.h, and I see no solution for that (other than breaking up processor.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

#33 lore raw

Re: [PATCH 13/39] NLKD/x86-64 - time adjustment

In reply to Jan Beulich
Quoted 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

#34 lore raw

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_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.

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_data is 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

#35 lore raw

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_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.

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.

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

#36 lore raw

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_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.

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.

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
#37 lore raw

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

#38 lore raw

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
#39 lore raw

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/
#40 lore raw

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

#41 lore raw

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
#42 lore raw

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

#43 lore raw

Re: [PATCH 13/39] NLKD/x86-64 - time adjustment

In reply to Andi Kleen
Quoted 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_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

(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_data is 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
#44 lore raw

PATCH 14/39 NLKD - kernel trace buffer access

In reply to Jan Beulich

Debug 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
Index: 2.6.14-nlkd/kernel/printk.c
===================================================================
@@ -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
#45 lore raw

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
Index: 2.6.14-nlkd/include/linux/epfs.h
===================================================================
@@ -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
Index: 2.6.14-nlkd/init/Kconfig
===================================================================
@@ -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
Index: 2.6.14-nlkd/init/Makefile
===================================================================
@@ -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

#46 lore raw

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
Index: 2.6.14-nlkd/include/asm-generic/bug.h
===================================================================
@@ -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
Index: 2.6.14-nlkd/include/linux/sched.h
===================================================================
@@ -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
Index: 2.6.14-nlkd/init/Kconfig
===================================================================
@@ -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
Index: 2.6.14-nlkd/init/main.c
===================================================================
@@ -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(void
 	sort_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
Index: 2.6.14-nlkd/kernel/exit.c
===================================================================
@@ -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 co
 	struct 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
Index: 2.6.14-nlkd/kernel/fork.c
===================================================================
@@ -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(struct
 
 	if (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_struct 
 void 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
Index: 2.6.14-nlkd/kernel/power/swsusp.c
===================================================================
@@ -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
Index: 2.6.14-nlkd/kernel/sched.c
===================================================================
@@ -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;
 }
 
#47 lore raw

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
Index: 2.6.14-nlkd/arch/i386/Kconfig
===================================================================
@@ -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
Index: 2.6.14-nlkd/arch/i386/Kconfig.debug
===================================================================
@@ -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
Index: 2.6.14-nlkd/arch/i386/kernel/cpu/common.c
===================================================================
@@ -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
Index: 2.6.14-nlkd/arch/i386/kernel/process.c
===================================================================
@@ -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
Index: 2.6.14-nlkd/arch/i386/kernel/ptrace.c
===================================================================
@@ -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
Index: 2.6.14-nlkd/arch/i386/kernel/signal.c
===================================================================
@@ -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
Index: 2.6.14-nlkd/arch/i386/kernel/traps.c
===================================================================
@@ -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
Index: 2.6.14-nlkd/arch/i386/kernel/vmlinux.lds.S
===================================================================
@@ -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
Index: 2.6.14-nlkd/arch/i386/power/cpu.c
===================================================================
@@ -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
Index: 2.6.14-nlkd/include/asm-i386/processor.h
===================================================================
@@ -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)
#48 lore raw

Re: [PATCH 17/39] NLKD/i386 - core adjustments

Quoted 5 lines · Jan Beulich

The core i386 NLKD adjustments to pre-existing code.

(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 Seed
#49 lore raw

Re: [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

(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

#50 lore raw

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.

(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 Seed
#51 lore raw

Re: [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

#52 lore raw

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"
#53 lore raw

PATCH 22/39 NLKD - core

In reply to Jan Beulich

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.

(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
Index: 2.6.14-nlkd/Makefile
===================================================================
@@ -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
Index: 2.6.14-nlkd/debug/Kconfig
===================================================================
@@ -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
Index: 2.6.14-nlkd/debug/Makefile
===================================================================
@@ -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

#54 lore raw

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
Index: 2.6.14-nlkd/debug/nlkd/asm-x86.h
===================================================================
@@ -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
#55 lore raw

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
Index: 2.6.14-nlkd/arch/i386/Kconfig.debug
===================================================================
@@ -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

#56 lore raw

PATCH 25/39 NLKD/x86-64 - core

In reply to Jan Beulich

The core x86-64 NLKD additions.

(actual patch attached)

The core x86-64 NLKD additions.

arch/x86_64/Kconfig.debug +1 -0
Index: 2.6.14-nlkd/arch/x86_64/Kconfig.debug
===================================================================
@@ -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

#57 lore raw

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

#58 lore raw

PATCH 26/39 NLKD - run time library

In reply to Jan Beulich

Some 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
Index: 2.6.14-nlkd/debug/nlkd/dbgutil.c
===================================================================
@@ -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

#59 lore raw

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
Index: 2.6.14-nlkd/debug/nlkd/dbgIA32.S
===================================================================
@@ -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
#60 lore raw

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
Index: 2.6.14-nlkd/debug/nlkd/dbgAMD64.S
===================================================================
@@ -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
#61 lore raw

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]

#64 lore raw

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
Index: 2.6.14-nlkd/debug/nlkd/cda/x86_1.c
===================================================================
@@ -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]

#66 lore raw

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
Index: 2.6.14-nlkd/debug/nlkd/rda/rdaIA32.c
===================================================================
@@ -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

#67 lore raw

PATCH 39/39 NLKD/x86-64 - Remote Debug Agent

In reply to a message not in the archive

The 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
Index: 2.6.14-nlkd/debug/nlkd/rda/rdaAMD64.c
===================================================================
@@ -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

#68 lore raw

Re: [PATCH 15/39] NLKD - early pseudo-fs

In reply to Jan Beulich
Quoted 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.

#69 lore raw

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

#70 lore raw

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"

#71 lore raw

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

#72 lore raw

Re: [PATCH 14/39] NLKD - kernel trace buffer access

In reply to Jan Beulich
Quoted 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 */

#73 lore raw

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

*/
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);

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

#74 lore raw

Re: [PATCH 11/39] NLKD - time adjustment

In reply to Jan Beulich
Quoted 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.

(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/
#76 lore raw

Re: [PATCH 3/39] NLKD - early/late CPU up/down notification

In reply to Jan Beulich
Quoted 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_64 will follow.

(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

#77 lore raw

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_64 will follow.

(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

#78 lore raw

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

#79 lore raw

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

#80 lore raw

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_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

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

#81 lore raw

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_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

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

#82 lore raw

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_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

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

#83 lore raw

Re: [PATCH 3/39] NLKD - early/late CPU up/down notification

In reply to Jan Beulich
Quoted 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_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).

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

#84 lore raw

Re: [PATCH 2/39] NLKD - an alternative early ioremap approach

In reply to Jan Beulich

Hi!

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.

(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!
#85 lore raw

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

#86 lore raw

Re: [PATCH 1/39] NLKD - an alternative kallsyms approach

In reply to Jan Beulich
Quoted 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 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.

Quoted 3 lines

(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
#87 lore raw

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

#88 lore raw

Re: [PATCH 1/39] NLKD - an alternative kallsyms approach

In reply to Randy.Dunlap
Quoted 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

#89 lore raw
In reply to Jan Beulich
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

#90 lore raw
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
#91 lore raw
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

#92 lore raw
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

#93 lore raw
In reply to Jan Beulich
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

#94 lore raw
In reply to Jan Beulich
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.0401
#95 lore raw
In reply to Jan Beulich
Quoted 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.

#96 lore raw
In reply to Randy.Dunlap
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

#97 lore raw
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/

#98 lore raw
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.c is 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

#99 lore raw
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.c is 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
diff -Naur ./kdb/kdbmain.c ../linux-2.6.9-mdb/./kdb/kdbmain.c
@@ -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 int
kdb_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
+
void
kdb_ps1(struct task_struct *p)
{
@@ -3835,6 +3900,10 @@
void __init
kdb_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);
#100 lore raw
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.c is 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.c

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

11: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 */
+#else

static volatile int kdb_new_cpu; /* Which cpu to switch to */
+#endif

volatile 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_t db_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 __init
kdb_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 preset 

breakpoints 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

#101 lore raw
In reply to Jeff Garzik
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

#102 lore raw
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/

#103 lore raw
In reply to Alan Cox
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

#104 lore raw
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/
#105 lore raw
In reply to Mark Lord
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

#106 lore raw
In reply to Mark Lord
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]

#109 lore raw

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