public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Andi Kleen <ak@suse.de>
To: jbeulich@novell.com, patches@x86-64.org, linux-kernel@vger.kernel.org
Subject: [PATCH] [32/50] x86: Show last exception from/to register  contents
Date: Sat, 22 Sep 2007 00:32:31 +0200 (CEST)	[thread overview]
Message-ID: <20070921223231.DF0BA13DCD@wotan.suse.de> (raw)
In-Reply-To: <200709221231.836138000@suse.de>


From: "Jan Beulich" <jbeulich@novell.com>
.. when dumping register state. This is particularly useful when gcc
managed to tail-call optimize an indirect call which happens to hit a
NULL (or otherwise invalid) pointer.

The result is unreliable because interrupts happening inbetween can mess
it up

AK: added some warnings that the result can be unreliable

Signed-off-by: Jan Beulich <jbeulich@novell.com>
Signed-off-by: Andi Kleen <ak@suse.de>

 Documentation/kernel-parameters.txt |    3 +++
 arch/i386/kernel/cpu/amd.c          |    4 ++++
 arch/i386/kernel/cpu/common.c       |    2 ++
 arch/i386/kernel/cpu/intel.c        |   20 ++++++++++++++------
 arch/i386/kernel/traps.c            |   35 +++++++++++++++++++++++++++++++++++
 arch/x86_64/kernel/setup.c          |   23 ++++++++++++++++++-----
 arch/x86_64/kernel/traps.c          |   33 +++++++++++++++++++++++++++++++++
 include/asm-i386/msr-index.h        |    3 +++
 include/asm-i386/processor.h        |    4 ++++
 include/asm-x86_64/msr.h            |    6 ++++++
 include/asm-x86_64/processor.h      |    3 +++
 11 files changed, 125 insertions(+), 11 deletions(-)

Index: linux/Documentation/kernel-parameters.txt
===================================================================
--- linux.orig/Documentation/kernel-parameters.txt
+++ linux/Documentation/kernel-parameters.txt
@@ -1152,6 +1152,9 @@ and is between 256 and 4096 characters. 
 
 	nolapic_timer	[X86-32,APIC] Do not use the local APIC timer.
 
+	noler		[X86-32/X86-64] Do not print last exception records
+			with kernel register dumps.
+
 	noltlbs		[PPC] Do not use large page/tlb entries for kernel
 			lowmem mapping on PPC40x.
 
Index: linux/arch/i386/kernel/cpu/amd.c
===================================================================
--- linux.orig/arch/i386/kernel/cpu/amd.c
+++ linux/arch/i386/kernel/cpu/amd.c
@@ -238,9 +238,13 @@ static void __cpuinit init_amd(struct cp
 	case 0x10:
 	case 0x11:
 		set_bit(X86_FEATURE_K8, c->x86_capability);
+		if (ler_enabled)
+			__get_cpu_var(ler_msr) = MSR_IA32_LASTINTFROMIP;
 		break;
 	case 6:
 		set_bit(X86_FEATURE_K7, c->x86_capability); 
+		if (ler_enabled)
+			__get_cpu_var(ler_msr) = MSR_IA32_LASTINTFROMIP;
 		break;
 	}
 	if (c->x86 >= 6)
Index: linux/arch/i386/kernel/cpu/common.c
===================================================================
--- linux.orig/arch/i386/kernel/cpu/common.c
+++ linux/arch/i386/kernel/cpu/common.c
@@ -503,6 +503,8 @@ static void __cpuinit identify_cpu(struc
 
 	/* Init Machine Check Exception if available. */
 	mcheck_init(c);
+
+	ler_enable();
 }
 
 void __init identify_boot_cpu(void)
Index: linux/arch/i386/kernel/cpu/intel.c
===================================================================
--- linux.orig/arch/i386/kernel/cpu/intel.c
+++ linux/arch/i386/kernel/cpu/intel.c
@@ -188,15 +188,23 @@ static void __cpuinit init_intel(struct 
 	}
 #endif
 
-	if (c->x86 == 15) {
+	switch (c->x86) {
+	case 15:
 		set_bit(X86_FEATURE_P4, c->x86_capability);
 		set_bit(X86_FEATURE_SYNC_RDTSC, c->x86_capability);
-	}
-	if (c->x86 == 6) 
+		if (c->x86_model >= 0x03)
+			set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability);
+		if (ler_enabled)
+			__get_cpu_var(ler_msr) = MSR_P4_LER_FROM_LIP;
+		break;
+	case 6:
 		set_bit(X86_FEATURE_P3, c->x86_capability);
-	if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
-		(c->x86 == 0x6 && c->x86_model >= 0x0e))
-		set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability);
+		if (c->x86_model >= 0x0e)
+			set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability);
+		if (ler_enabled)
+			__get_cpu_var(ler_msr) = MSR_IA32_LASTINTFROMIP;
+		break;
+	}
 
 	if (cpu_has_ds) {
 		unsigned int l1;
Index: linux/arch/i386/kernel/traps.c
===================================================================
--- linux.orig/arch/i386/kernel/traps.c
+++ linux/arch/i386/kernel/traps.c
@@ -374,6 +374,20 @@ void show_registers(struct pt_regs *regs
 		unsigned int code_len = code_bytes;
 		unsigned char c;
 
+		if (oops_in_progress && __get_cpu_var(ler_msr)) {
+			u32 from, to, hi;
+
+			if (rdmsr_safe(__get_cpu_var(ler_msr), &from, &hi) == 0
+			    && rdmsr_safe(__get_cpu_var(ler_msr) + 1, &to, &hi) == 0) {
+				printk("\n" KERN_EMERG
+				       "last branch before last exception/interrupt\n");
+				printk(KERN_EMERG " from %08x", from);
+				print_symbol(" (%s)\n", from);
+				printk(KERN_EMERG " to %08x", to);
+				print_symbol(" (%s)", to);
+			} else
+				__get_cpu_var(ler_msr) = 0;
+		}
 		printk("\n" KERN_EMERG "Stack: ");
 		show_stack_log_lvl(NULL, regs, &regs->esp, KERN_EMERG);
 
@@ -413,6 +427,19 @@ int is_valid_bugaddr(unsigned long eip)
 	return ud2 == 0x0b0f;
 }
 
+DEFINE_PER_CPU(u32, ler_msr);
+int ler_enabled = 1;
+
+void ler_enable(void) {
+	if (__get_cpu_var(ler_msr)) {
+		u32 lo, hi;
+
+		if (rdmsr_safe(MSR_IA32_DEBUGCTLMSR, &lo, &hi) < 0
+		    || wrmsr_safe(MSR_IA32_DEBUGCTLMSR, lo | 1, hi) < 0)
+			__get_cpu_var(ler_msr) = 0;
+	}
+}
+
 /*
  * This is gone through when something in the kernel has done something bad and
  * is about to be terminated.
@@ -891,6 +918,7 @@ fastcall void __kprobes do_debug(struct 
 	struct task_struct *tsk = current;
 
 	get_debugreg(condition, 6);
+	ler_enable();
 
 	if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
 					SIGTRAP) == NOTIFY_STOP)
@@ -1275,6 +1303,13 @@ static int __init kstack_setup(char *s)
 }
 __setup("kstack=", kstack_setup);
 
+static int __init ler_setup(char *s)
+{
+	ler_enabled = 0;
+	return 1;
+}
+__setup("noler", ler_setup);
+
 static int __init code_bytes_setup(char *s)
 {
 	code_bytes = simple_strtoul(s, NULL, 0);
Index: linux/arch/x86_64/kernel/setup.c
===================================================================
--- linux.orig/arch/x86_64/kernel/setup.c
+++ linux/arch/x86_64/kernel/setup.c
@@ -639,6 +639,9 @@ static void __cpuinit init_amd(struct cp
 	    !rdmsr_safe(MSR_VM_CR, &flags, &dummy) &&
 	    (flags & 0x18))
 		set_bit(X86_FEATURE_VIRT_DISABLED, &c->x86_capability);
+
+	if (ler_enabled && c->x86 <= 17)
+		__get_cpu_var(ler_msr) = MSR_IA32_LASTINTFROMIP;
 }
 
 static int enable_svm_lock(char *s)
@@ -774,13 +777,22 @@ static void __cpuinit init_intel(struct 
 			c->x86_phys_bits = 36;
 	}
 
-	if (c->x86 == 15)
+	switch (c->x86) {
+	case 15:
 		c->x86_cache_alignment = c->x86_clflush_size * 2;
-	if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
-	    (c->x86 == 0x6 && c->x86_model >= 0x0e))
-		set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
-	if (c->x86 == 6)
+		if (c->x86_model >= 0x03)
+			set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
+		if (ler_enabled)
+			__get_cpu_var(ler_msr) = MSR_P4_LER_FROM_LIP;
+		break;
+	case 6:
+		if (c->x86_model >= 0x0e)
+			set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
 		set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability);
+		if (ler_enabled)
+			__get_cpu_var(ler_msr) = MSR_IA32_LASTINTFROMIP;
+		break;
+	}
 	if (c->x86 == 15)
 		set_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
 	else
@@ -951,6 +963,7 @@ void __cpuinit identify_cpu(struct cpuin
 #ifdef CONFIG_NUMA
 	numa_add_cpu(smp_processor_id());
 #endif
+	ler_enable();
 }
  
 
Index: linux/arch/x86_64/kernel/traps.c
===================================================================
--- linux.orig/arch/x86_64/kernel/traps.c
+++ linux/arch/x86_64/kernel/traps.c
@@ -492,6 +492,19 @@ void show_registers(struct pt_regs *regs
 	 * time of the fault..
 	 */
 	if (in_kernel) {
+		if (oops_in_progress && __get_cpu_var(ler_msr)) {
+			u64 from, to;
+
+			if (checking_rdmsrl(__get_cpu_var(ler_msr), from) == 0
+			    && checking_rdmsrl(__get_cpu_var(ler_msr) + 1, to) == 0) {
+				printk("last branch before last exception/interrupt\n");
+				printk(" from ");
+				printk_address(from);
+				printk(" to ");
+				printk_address(to);
+			} else
+				__get_cpu_var(ler_msr) = 0;
+		}
 		printk("Stack: ");
 		_show_stack(NULL, regs, (unsigned long*)rsp);
 
@@ -530,6 +543,19 @@ void out_of_line_bug(void)
 EXPORT_SYMBOL(out_of_line_bug);
 #endif
 
+DEFINE_PER_CPU(u32, ler_msr);
+int ler_enabled = 1;
+
+void ler_enable(void) {
+	if (__get_cpu_var(ler_msr)) {
+		u32 lo, hi;
+
+		if (rdmsr_safe(MSR_IA32_DEBUGCTLMSR, &lo, &hi) < 0
+		    || wrmsr_safe(MSR_IA32_DEBUGCTLMSR, lo | 1, hi) < 0)
+			__get_cpu_var(ler_msr) = 0;
+	}
+}
+
 static DEFINE_SPINLOCK(die_lock);
 static int die_owner = -1;
 static unsigned int die_nest_count;
@@ -920,6 +946,7 @@ asmlinkage void __kprobes do_debug(struc
 	siginfo_t info;
 
 	get_debugreg(condition, 6);
+	ler_enable();
 
 	if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
 						SIGTRAP) == NOTIFY_STOP)
@@ -1188,6 +1215,12 @@ void __init trap_init(void)
 	cpu_init();
 }
 
+static int __init ler_setup(char *s)
+{
+	ler_enabled = 0;
+	return 1;
+}
+__setup("noler", ler_setup);
 
 static int __init oops_setup(char *s)
 { 
Index: linux/include/asm-i386/msr-index.h
===================================================================
--- linux.orig/include/asm-i386/msr-index.h
+++ linux/include/asm-i386/msr-index.h
@@ -63,6 +63,9 @@
 #define MSR_IA32_LASTINTFROMIP		0x000001dd
 #define MSR_IA32_LASTINTTOIP		0x000001de
 
+#define MSR_P4_LER_FROM_LIP 		0x000001d7
+#define MSR_P4_LER_TO_LIP 		0x000001d8
+
 #define MSR_IA32_MC0_CTL		0x00000400
 #define MSR_IA32_MC0_STATUS		0x00000401
 #define MSR_IA32_MC0_ADDR		0x00000402
Index: linux/include/asm-i386/processor.h
===================================================================
--- linux.orig/include/asm-i386/processor.h
+++ linux/include/asm-i386/processor.h
@@ -643,6 +643,10 @@ static inline unsigned int cpuid_edx(uns
 	return edx;
 }
 
+DECLARE_PER_CPU(u32, ler_msr);
+extern int ler_enabled;
+void ler_enable(void);
+
 /* generic versions from gas */
 #define GENERIC_NOP1	".byte 0x90\n"
 #define GENERIC_NOP2    	".byte 0x89,0xf6\n"
Index: linux/include/asm-x86_64/msr.h
===================================================================
--- linux.orig/include/asm-x86_64/msr.h
+++ linux/include/asm-x86_64/msr.h
@@ -63,6 +63,12 @@
                       :"c"(msr), "i"(-EIO), "0"(0));		\
 	  ret__; })		
 
+#define checking_rdmsrl(msr,val) ({				\
+	u32 lo__, hi__;						\
+	int rc__ = rdmsr_safe(msr, &lo__, &hi__);		\
+	val = lo__ | ((u64)hi__ << 32);				\
+	rc__; })
+
 #define rdtsc(low,high) \
      __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
 
Index: linux/include/asm-x86_64/processor.h
===================================================================
--- linux.orig/include/asm-x86_64/processor.h
+++ linux/include/asm-x86_64/processor.h
@@ -334,6 +334,9 @@ struct extended_sigtable {
 	struct extended_signature sigs[0];
 };
 
+DECLARE_PER_CPU(u32, ler_msr);
+extern int ler_enabled;
+void ler_enable(void);
 
 #define ASM_NOP1 K8_NOP1
 #define ASM_NOP2 K8_NOP2

  parent reply	other threads:[~2007-09-21 22:44 UTC|newest]

Thread overview: 105+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-09-21 22:31 [PATCH] [0/50] x86 2.6.24 patches review II Andi Kleen
2007-09-21 22:31 ` [PATCH] [1/50] x86_64: store core id bits in cpuinfo_x8 Andi Kleen
2007-09-21 22:31 ` [PATCH] [2/50] x86_64: use core id bits for apicid_to_node initialization Andi Kleen
2007-09-21 22:32 ` [PATCH] [3/50] x86_64: remove never used apic_mapped Andi Kleen
2007-09-21 22:32 ` [PATCH] [4/50] x86: add cpu codenames for Kconfig.cpu Andi Kleen
2007-09-21 22:45   ` Dave Jones
2007-09-21 23:52     ` Alan Cox
2007-09-22  6:57     ` Sam Ravnborg
2007-09-22  9:46       ` Jan Engelhardt
2007-09-22 14:23       ` Dave Jones
2007-09-22 17:40         ` Randy Dunlap
2007-09-30 10:09     ` Andi Kleen
2007-09-22 17:50   ` Thomas Gleixner
2007-10-01 11:17     ` Andi Kleen
2007-09-21 22:32 ` [PATCH] [5/50] i386: change order in Kconfig.cpu Andi Kleen
2007-09-21 22:32 ` [PATCH] [6/50] i386: clean up oops/bug reports Andi Kleen
2007-09-21 22:41   ` Chuck Ebbert
2007-09-22  9:47     ` Jan Engelhardt
2007-09-22  2:51   ` Killing printk calls for size (Re: [PATCH] [6/50] i386: clean up oops/bug reports) Oleg Verych
2007-09-21 22:32 ` [PATCH] [7/50] x86: expand /proc/interrupts to include missing vectors, v2 Andi Kleen
2007-09-22  3:35   ` possible corrections in the docs (Re: [PATCH] [7/50] x86: expand /proc/interrupts to include missing vectors, v2) Oleg Verych
2007-09-22  3:52     ` Joe Korty
2007-09-21 22:32 ` [PATCH] [8/50] x86_64: remove x86_cpu_to_log_apicid Andi Kleen
2007-09-21 22:32 ` [PATCH] [9/50] i386: validate against ACPI motherboard resources Andi Kleen
2007-09-22  6:49   ` Yinghai Lu
2007-09-22  6:56     ` Yinghai Lu
2007-09-22 16:28     ` Robert Hancock
2007-09-22 18:01       ` Thomas Gleixner
2007-09-22 18:42         ` Robert Hancock
2007-09-22 20:40           ` Yinghai Lu
2007-09-22 20:56             ` H. Peter Anvin
2007-09-22 21:27             ` Robert Hancock
2007-09-23  1:20               ` Yinghai Lu
2007-09-23  1:34               ` Yinghai Lu
2007-09-22 20:47       ` Yinghai Lu
2007-09-21 22:32 ` [PATCH] [10/50] x86_64: install unstripped copies of compat vdso on disk Andi Kleen
2007-09-21 22:32 ` [PATCH] [11/50] x86_64: Install unstripped copy of 64bit vdso to disk Andi Kleen
2007-09-21 22:32 ` [PATCH] [12/50] x86_64: Untable __init references between IO data Andi Kleen
2007-09-22  5:37   ` [patches] " Yinghai Lu
2007-09-21 22:32 ` [PATCH] [13/50] x86: Fix and reenable CLFLUSH support in change_page_attr() Andi Kleen
2007-09-22  5:47   ` Oleg Verych
2007-10-01 10:59     ` Andi Kleen
2007-09-24  8:23   ` [patches] [PATCH] [13/50] x86: Fix and reenable CLFLUSH support inchange_page_attr() Jan Beulich
2007-10-01 10:38     ` Andi Kleen
2007-09-21 22:32 ` [PATCH] [14/50] x86: Minor code-style cleanups to change_page_attr Andi Kleen
2007-09-21 22:32 ` [PATCH] [15/50] x86_64: Return EINVAL for unknown address in change_page_attr Andi Kleen
2007-09-24  8:32   ` [patches] [PATCH] [15/50] x86_64: Return EINVAL for unknown addressin change_page_attr Jan Beulich
2007-09-21 22:32 ` [PATCH] [16/50] x86: Use macros to modify the PG_arch_1 page flags in change_page_attr Andi Kleen
2007-09-21 22:32 ` [PATCH] [17/50] x86_64: remove STR() macros Andi Kleen
2007-09-21 22:32 ` [PATCH] [18/50] x86_64: Save registers in saved_context during suspend and hibernation Andi Kleen
2007-09-21 22:32 ` [PATCH] [19/50] Experimental: detect if SVM is disabled by BIOS Andi Kleen
2007-09-22  6:59   ` Sam Ravnborg
2007-09-22  9:17   ` Joerg Roedel
2007-10-01 16:47     ` Andi Kleen
2007-10-01 20:12       ` Joerg Roedel
2007-10-01 21:45         ` [patches] " Andi Kleen
2007-10-01 22:13           ` Joerg Roedel
2007-09-22 19:05   ` Thomas Gleixner
2007-09-21 22:32 ` [PATCH] [20/50] x86_64: Fix some broken white space in arch/x86_64/mm/init.c Andi Kleen
2007-09-22 19:17   ` Thomas Gleixner
2007-09-23  1:47     ` Oleg Verych
2007-09-21 22:32 ` [PATCH] [21/50] i386: Misc cpuinit annotations Andi Kleen
2007-09-21 22:32 ` [PATCH] [22/50] " Andi Kleen
2007-09-21 22:32 ` [PATCH] [23/50] x86_64: Implement missing x86_64 function smp_call_function_mask() Andi Kleen
2007-09-21 22:32 ` [PATCH] [24/50] x86_64: Eliminate result signage problem in asm-x86_64/bitops.h Andi Kleen
2007-09-21 22:32 ` [PATCH] [25/50] x86_64: Add parenthesis to IRQ vector macros Andi Kleen
2007-09-21 22:32 ` [PATCH] [26/50] i386: export i386 smp_call_function_mask() to modules Andi Kleen
2007-09-21 22:32 ` [PATCH] [27/50] x86_64: Remove duplicated vsyscall nsec update Andi Kleen
2007-09-21 22:32 ` [PATCH] [28/50] i386: remove stub early_printk.c Andi Kleen
2007-09-21 22:32 ` [PATCH] [29/50] x86: honor _PAGE_PSE bit on page walks Andi Kleen
2007-09-21 22:32 ` [PATCH] [30/50] x86_64: remove some dead code Andi Kleen
2007-09-21 22:32 ` [PATCH] [31/50] x86_64: honor notify_die() returning NOTIFY_STOP Andi Kleen
2007-09-22 19:23   ` Thomas Gleixner
2007-09-21 22:32 ` Andi Kleen [this message]
2007-09-21 22:32 ` [PATCH] [33/50] x86: rename .i assembler includes to .h Andi Kleen
2007-09-21 22:32 ` [PATCH] [34/50] i386: Fix argument signedness warnings Andi Kleen
2007-09-22  5:06   ` Satyam Sharma
2007-09-22 10:01     ` Jan Engelhardt
2007-09-22 17:42       ` Randy Dunlap
2007-09-21 22:32 ` [PATCH] [35/50] i386: Do cpuid_device_create() in CPU_UP_PREPARE instead of CPU_ONLINE Andi Kleen
2007-09-22 19:33   ` Thomas Gleixner
2007-09-23  1:52     ` Akinobu Mita
2007-09-23  7:52       ` Thomas Gleixner
2007-09-21 22:32 ` [PATCH] [36/50] x86: Use raw locks during oopses Andi Kleen
2007-09-21 22:32 ` [PATCH] [37/50] x86_64: Clean up mce= argument parsing slightly Andi Kleen
2007-09-21 22:32 ` [PATCH] [38/50] x86_64: fix off-by-one in find_next_zero_string Andi Kleen
2007-09-21 22:32 ` [PATCH] [39/50] i386: fix 4 bit apicid assumption of mach-default Andi Kleen
2007-09-21 22:32 ` [PATCH] [40/50] i386: Fix section mismatch Andi Kleen
2007-09-21 22:32 ` [PATCH] [41/50] i386: fix section mismatch warning in intel.c Andi Kleen
2007-09-21 22:32 ` [PATCH] [42/50] i386: constify wd_ops Andi Kleen
2007-09-21 22:32 ` [PATCH] [43/50] x86: multi-byte single instruction NOPs Andi Kleen
2007-09-21 22:32 ` [PATCH] [44/50] i386: Introduce "used_vectors" bitmap which can be used to reserve vectors Andi Kleen
2007-09-21 22:32 ` [PATCH] [45/50] x86_64: configure HPET_EMULATE_RTC automatically Andi Kleen
2007-09-21 22:32 ` [PATCH] [46/50] x86: also show non-zero IRQ counts for vectors that currently don't have a handler Andi Kleen
2007-09-21 22:32 ` [PATCH] [47/50] i386: avoid temporarily inconsistent pte-s Andi Kleen
2007-09-21 22:32 ` [PATCH] [48/50] x86_64: return correct error code from child_rip in x86_64 entry.S Andi Kleen
2007-09-21 22:32 ` [PATCH] [49/50] x86_64: Initialize 64bit registers for a.out executables Andi Kleen
2007-09-21 22:32 ` [PATCH] [50/50] x86_64: Remove fpu io port resource Andi Kleen
2007-09-21 23:00   ` Jeff Garzik
2007-10-01 10:40     ` Andi Kleen
2007-10-01 11:30       ` Jeff Garzik
2007-10-01 11:48         ` Andi Kleen
2007-10-01 13:33           ` Jeff Garzik
2007-10-01 14:16             ` Mark Lord
2007-10-02 14:37         ` Alan Cox

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20070921223231.DF0BA13DCD@wotan.suse.de \
    --to=ak@suse.de \
    --cc=jbeulich@novell.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=patches@x86-64.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox