From mort@sgi.com Fri May 1 09:31:18 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-2.4 required=5.0 tests=AWL,BAYES_00 autolearn=ham version=3.3.0-rupdated Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n41EVH5g014119 for ; Fri, 1 May 2009 09:31:18 -0500 Received: from attica.americas.sgi.com (attica.americas.sgi.com [128.162.236.44]) by relay3.corp.sgi.com (Postfix) with ESMTP id 1ECBFAC00E for ; Fri, 1 May 2009 07:31:16 -0700 (PDT) Received: by attica.americas.sgi.com (Postfix, from userid 44682) id B3516A04A1E9; Fri, 1 May 2009 09:31:15 -0500 (CDT) Date: Fri, 1 May 2009 09:31:15 -0500 From: Martin Hicks To: kdb@oss.sgi.com Subject: git updates and patches for 2.6.30-rc4 Message-ID: <20090501143115.GB21457@alcatraz.americas.sgi.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.17 (2007-11-01) X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean Just the one small patch for x86. Git and patches available in the usual places: git://oss.sgi.com/kdb/kdb.git ftp://oss.sgi.com/projects/kdb/download/v4.4/ mh From info@moeschwag.com Wed May 6 16:35:17 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: **** X-Spam-Status: No, score=4.4 required=5.0 tests=BAYES_50,HTML_MESSAGE, SUBJ_DOLLARS autolearn=no version=3.3.0-rupdated Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n46LZFrg149515 for ; Wed, 6 May 2009 16:35:17 -0500 X-ASG-Debug-ID: 1241645958-4ba303930000-sLlkUa X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi Received: from elasmtp-masked.atl.sa.earthlink.net (localhost [127.0.0.1]) by cuda.sgi.com (Spam Firewall) with ESMTP id 49742147A089; Wed, 6 May 2009 14:39:18 -0700 (PDT) Received: from elasmtp-masked.atl.sa.earthlink.net (elasmtp-masked.atl.sa.earthlink.net [209.86.89.68]) by cuda.sgi.com with ESMTP id YI3rhMizlUywClEb; Wed, 06 May 2009 14:39:18 -0700 (PDT) Received: from [98.96.40.230] (helo=GaryPC) by elasmtp-masked.atl.sa.earthlink.net with esmtpa (Exim 4.67) (envelope-from ) id 1M1oWf-0003le-Vh; Wed, 06 May 2009 17:19:38 -0400 Message-ID: <26D072A4330743A7ADF3B2731F510749@GaryPC> From: "Moe Wampum Tees" To: "Moe Wampum Tees" X-ASG-Orig-Subj: $6 closeout tees + latest funny tees and other novelty t-shirts! Subject: $6 closeout tees + latest funny tees and other novelty t-shirts! Date: Wed, 6 May 2009 14:17:58 -0700 MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_NextPart_000_0593_01C9CE55.74D8FF50" X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Windows Mail 6.0.6001.18000 X-MimeOLE: Produced By Microsoft MimeOLE V6.0.6001.18049 X-ELNK-Trace: dec35cb6f6963e745e89bb4777695beb00ff6c36d42eb1fad43c1c45eb54791b7d0c79e9837f3e16350badd9bab72f9c350badd9bab72f9c350badd9bab72f9c X-Originating-IP: 98.96.40.230 X-Barracuda-Connect: elasmtp-masked.atl.sa.earthlink.net[209.86.89.68] X-Barracuda-Start-Time: 1241645963 X-Barracuda-Bayes: INNOCENT GLOBAL 0.4829 1.0000 0.0000 X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com X-Barracuda-Spam-Score: 1.34 X-Barracuda-Spam-Status: No, SCORE=1.34 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests=BSF_SC0_SA_TO_FROM_ADDR_MATCH, BSF_SC0_TG035a, HTML_MESSAGE, SUBJ_DOLLARS X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.1.25102 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.84 SUBJ_DOLLARS Subject starts with dollar amount 0.00 HTML_MESSAGE BODY: HTML included in message 0.00 BSF_SC0_TG035a Message contains invalid style definition 0.50 BSF_SC0_SA_TO_FROM_ADDR_MATCH Sender Address Matches Recipient Address X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean This is a multi-part message in MIME format. ------=_NextPart_000_0593_01C9CE55.74D8FF50 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Thought that you'd be interested in our $6 closeout tees + latest funny = tees and other novelty t-shirts!=20 http://www.moeschwag.com ! spread the word!=20 see the latest, along with some really new funny t-shirts & more! http://www.moeschwag.com enjoy~! This message is the property of Moe Wampum, Inc or its affiliates. if = you have received this communication in error, please immediately notify = the sender and delete this message. To unsubscribe, or if you believe = that this message was sent in error, or wish to be removed from our = mailing list, please send email to info@moeschwag.com with REMOVE as = title.=20 ------=_NextPart_000_0593_01C9CE55.74D8FF50 Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable
 
Thought that you'd be interested in our = $6 closeout=20 tees + latest funny tees and other novelty t-shirts!
 http://www.moeschwag.com ! spread = the word!=20
see the latest,  along with some really new funny t-shirts = &=20 more!
http://www.moeschwag.com
enjoy~!=
 
 
 
This message is the property of Moe = Wampum, Inc or=20 its affiliates.  if you have received this communication in error, = please=20 immediately notify the sender and delete this message.  To = unsubscribe, or=20 if you believe that this message was sent in error, or wish to be = removed from=20 our mailing list, please send email to info@moeschwag.com with REMOVE as = title.=20
------=_NextPart_000_0593_01C9CE55.74D8FF50-- From jason.wessel@windriver.com Fri May 8 16:23:31 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00 autolearn=ham version=3.3.0-rupdated Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n48LNUUL031447 for ; Fri, 8 May 2009 16:23:30 -0500 X-ASG-Debug-ID: 1241817814-3e1600420000-sLlkUa X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi Received: from mail.wrs.com (localhost [127.0.0.1]) by cuda.sgi.com (Spam Firewall) with ESMTP id B11901D1EBFA for ; Fri, 8 May 2009 14:23:34 -0700 (PDT) Received: from mail.wrs.com (mail.windriver.com [147.11.1.11]) by cuda.sgi.com with ESMTP id 1XUC55tXSVH9fDqT for ; Fri, 08 May 2009 14:23:34 -0700 (PDT) Received: from ALA-MAIL03.corp.ad.wrs.com (ala-mail03 [147.11.57.144]) by mail.wrs.com (8.13.6/8.13.6) with ESMTP id n48LNTL4005511; Fri, 8 May 2009 14:23:29 -0700 (PDT) Received: from ala-mail06.corp.ad.wrs.com ([147.11.57.147]) by ALA-MAIL03.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:29 -0700 Received: from localhost.localdomain ([172.25.32.41]) by ala-mail06.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:28 -0700 From: Jason Wessel To: linux-kernel@vger.kernel.org Cc: kgdb-bugreport@lists.sourceforge.net, kdb@oss.sgi.com, Jason Wessel X-ASG-Orig-Subj: [PATCH 06/13] kgdb: remove post_primary_code references Subject: [PATCH 06/13] kgdb: remove post_primary_code references Date: Fri, 8 May 2009 16:23:13 -0500 Message-Id: <1241817800-9320-7-git-send-email-jason.wessel@windriver.com> X-Mailer: git-send-email 1.6.3.rc0.1.gf800 In-Reply-To: <1241817800-9320-6-git-send-email-jason.wessel@windriver.com> References: <1241817800-9320-1-git-send-email-jason.wessel@windriver.com> <1241817800-9320-2-git-send-email-jason.wessel@windriver.com> <1241817800-9320-3-git-send-email-jason.wessel@windriver.com> <1241817800-9320-4-git-send-email-jason.wessel@windriver.com> <1241817800-9320-5-git-send-email-jason.wessel@windriver.com> <1241817800-9320-6-git-send-email-jason.wessel@windriver.com> X-OriginalArrivalTime: 08 May 2009 21:23:28.0731 (UTC) FILETIME=[3AE552B0:01C9D023] X-Barracuda-Connect: mail.windriver.com[147.11.1.11] X-Barracuda-Start-Time: 1241817814 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com X-Barracuda-Spam-Score: -1.52 X-Barracuda-Spam-Status: No, SCORE=-1.52 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests=BSF_RULE7568M X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.1.25266 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.50 BSF_RULE7568M Custom Rule 7568M X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean Remove all the references to the kgdb_post_primary_code. This function serves no useful purpose because you can obtain the same information from the "struct kgdb_state *ks" from with in the debugger, if for some reason you want the data. Also remove the unintentional duplicate assignment for ks->ex_vector. Signed-off-by: Jason Wessel --- arch/x86/kernel/kgdb.c | 29 ----------------------------- include/linux/kgdb.h | 14 -------------- kernel/kgdb.c | 8 -------- 3 files changed, 0 insertions(+), 51 deletions(-) diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index 6d2503d..a61a138 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c @@ -45,20 +45,8 @@ #include #include - #include -/* - * Put the error code here just in case the user cares: - */ -static int gdb_x86errcode; - -/* - * Likewise, the vector number here (since GDB only gets the signal - * number through the usual means, and that's not very specific): - */ -static int gdb_x86vector = -1; - /** * pt_regs_to_gdb_regs - Convert ptrace regs to GDB regs * @gdb_regs: A pointer to hold the registers in the order GDB wants. @@ -311,23 +299,6 @@ void kgdb_disable_hw_debug(struct pt_regs *regs) set_debugreg(0UL, 7); } -/** - * kgdb_post_primary_code - Save error vector/code numbers. - * @regs: Original pt_regs. - * @e_vector: Original error vector. - * @err_code: Original error code. - * - * This is needed on architectures which support SMP and KGDB. - * This function is called after all the slave cpus have been put - * to a know spin state and the primary CPU has control over KGDB. - */ -void kgdb_post_primary_code(struct pt_regs *regs, int e_vector, int err_code) -{ - /* primary processor is completely in the debugger */ - gdb_x86vector = e_vector; - gdb_x86errcode = err_code; -} - #ifdef CONFIG_SMP /** * kgdb_roundup_cpus - Get other CPUs into a holding pattern diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h index 0299b79..8ecf20f 100644 --- a/include/linux/kgdb.h +++ b/include/linux/kgdb.h @@ -35,20 +35,6 @@ struct pt_regs; extern int kgdb_skipexception(int exception, struct pt_regs *regs); /** - * kgdb_post_primary_code - (optional) Save error vector/code numbers. - * @regs: Original pt_regs. - * @e_vector: Original error vector. - * @err_code: Original error code. - * - * This is usually needed on architectures which support SMP and - * KGDB. This function is called after all the secondary cpus have - * been put to a know spin state and the primary CPU has control over - * KGDB. - */ -extern void kgdb_post_primary_code(struct pt_regs *regs, int e_vector, - int err_code); - -/** * kgdb_disable_hw_debug - (optional) Disable hardware debugging hook * @regs: Current &struct pt_regs. * diff --git a/kernel/kgdb.c b/kernel/kgdb.c index 484f106..6d31c0c 100644 --- a/kernel/kgdb.c +++ b/kernel/kgdb.c @@ -233,12 +233,6 @@ int __weak kgdb_skipexception(int exception, struct pt_regs *regs) return 0; } -void __weak -kgdb_post_primary_code(struct pt_regs *regs, int e_vector, int err_code) -{ - return; -} - /** * kgdb_disable_hw_debug - Disable hardware debugging while we in kgdb. * @regs: Current &struct pt_regs. @@ -1632,7 +1626,6 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs) ks->cpu = raw_smp_processor_id(); ks->ex_vector = evector; ks->signo = signo; - ks->ex_vector = evector; ks->err_code = ecode; ks->kgdb_usethreadid = 0; ks->linux_regs = regs; @@ -1724,7 +1717,6 @@ acquirelock: * At this point the primary processor is completely * in the debugger and all secondary CPUs are quiescent */ - kgdb_post_primary_code(ks->linux_regs, ks->ex_vector, ks->err_code); kgdb_deactivate_sw_breakpoints(); kgdb_single_step = 0; kgdb_contthread = current; -- 1.6.3.rc0.1.gf800 From jason.wessel@windriver.com Fri May 8 16:23:31 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-1.7 required=5.0 tests=AWL,BAYES_00,FRT_LEVITRA autolearn=no version=3.3.0-rupdated Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n48LNUF1031452 for ; Fri, 8 May 2009 16:23:31 -0500 X-ASG-Debug-ID: 1241817814-3fe600370000-sLlkUa X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi Received: from mail.wrs.com (localhost [127.0.0.1]) by cuda.sgi.com (Spam Firewall) with ESMTP id 40FA71D1EA32 for ; Fri, 8 May 2009 14:23:34 -0700 (PDT) Received: from mail.wrs.com (mail.windriver.com [147.11.1.11]) by cuda.sgi.com with ESMTP id SsTW1EuVl2ybOnAC for ; Fri, 08 May 2009 14:23:34 -0700 (PDT) Received: from ALA-MAIL03.corp.ad.wrs.com (ala-mail03 [147.11.57.144]) by mail.wrs.com (8.13.6/8.13.6) with ESMTP id n48LNTUO005517; Fri, 8 May 2009 14:23:29 -0700 (PDT) Received: from ala-mail06.corp.ad.wrs.com ([147.11.57.147]) by ALA-MAIL03.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:29 -0700 Received: from localhost.localdomain ([172.25.32.41]) by ala-mail06.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:29 -0700 From: Jason Wessel To: linux-kernel@vger.kernel.org Cc: kgdb-bugreport@lists.sourceforge.net, kdb@oss.sgi.com, Jason Wessel X-ASG-Orig-Subj: [PATCH 07/13] RFC ONLY - x86,kgdb: Add low level debug hook Subject: [PATCH 07/13] RFC ONLY - x86,kgdb: Add low level debug hook Date: Fri, 8 May 2009 16:23:14 -0500 Message-Id: <1241817800-9320-8-git-send-email-jason.wessel@windriver.com> X-Mailer: git-send-email 1.6.3.rc0.1.gf800 In-Reply-To: <1241817800-9320-7-git-send-email-jason.wessel@windriver.com> References: <1241817800-9320-1-git-send-email-jason.wessel@windriver.com> <1241817800-9320-2-git-send-email-jason.wessel@windriver.com> <1241817800-9320-3-git-send-email-jason.wessel@windriver.com> <1241817800-9320-4-git-send-email-jason.wessel@windriver.com> <1241817800-9320-5-git-send-email-jason.wessel@windriver.com> <1241817800-9320-6-git-send-email-jason.wessel@windriver.com> <1241817800-9320-7-git-send-email-jason.wessel@windriver.com> X-OriginalArrivalTime: 08 May 2009 21:23:29.0544 (UTC) FILETIME=[3B616080:01C9D023] X-Barracuda-Connect: mail.windriver.com[147.11.1.11] X-Barracuda-Start-Time: 1241817815 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com X-Barracuda-Spam-Score: -0.78 X-Barracuda-Spam-Status: No, SCORE=-0.78 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests=BSF_RULE7568M, FRT_LEVITRA X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.1.25266 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.74 FRT_LEVITRA BODY: ReplaceTags: Levitra 0.50 BSF_RULE7568M Custom Rule 7568M X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean This is a RFC patch. The work to possibly merge kdb and kgdb is being evaluated and this patch is considered only a proof of concept or prototype. The only way the debugger can handle a trap in inside rcu_lock, notify_die, or atomic_notifier_call_chain without a triple fault is to have a low level "first opportunity handler" in the int3 exception handler. Generally this will be something the vast majority of folks will not need, but for those who need it, it is added as a kernel .config option called KGDB_LOW_LEVEL_TRAP. Since this is an RFC, the question would be how to implement this as an "alternative? The idea is that you want the calls to be always be NOP's unless a kgdb I/O driver has been loaded. Signed-off-by: Jason Wessel --- arch/x86/include/asm/kgdb.h | 3 +++ arch/x86/kernel/kgdb.c | 22 +++++++++++++++++++++- arch/x86/kernel/traps.c | 6 ++++++ include/linux/kgdb.h | 1 + kernel/kgdb.c | 2 +- lib/Kconfig.kgdb | 9 +++++++++ 6 files changed, 41 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/kgdb.h b/arch/x86/include/asm/kgdb.h index e6c6c80..006da36 100644 --- a/arch/x86/include/asm/kgdb.h +++ b/arch/x86/include/asm/kgdb.h @@ -76,4 +76,7 @@ static inline void arch_kgdb_breakpoint(void) #define BREAK_INSTR_SIZE 1 #define CACHE_FLUSH_IS_SAFE 1 +extern int kgdb_ll_trap(int cmd, const char *str, + struct pt_regs *regs, long err, int trap, int sig); + #endif /* _ASM_X86_KGDB_H */ diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index a61a138..8c652f7 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c @@ -462,7 +462,7 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd) return NOTIFY_DONE; } - if (kgdb_handle_exception(args->trapnr, args->signr, args->err, regs)) + if (kgdb_handle_exception(args->trapnr, args->signr, cmd, regs)) return NOTIFY_DONE; /* Must touch watchdog before return to normal operation */ @@ -470,6 +470,26 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd) return NOTIFY_STOP; } +#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP +int kgdb_ll_trap(int cmd, const char *str, + struct pt_regs *regs, long err, int trap, int sig) +{ + struct die_args args = { + .regs = regs, + .str = str, + .err = err, + .trapnr = trap, + .signr = sig, + + }; + + if (!kgdb_io_module_registered) + return NOTIFY_DONE; + + return __kgdb_notify(&args, cmd); +} +#endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */ + static int kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr) { diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index a1d2883..5525c23 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -460,6 +461,11 @@ void restart_nmi(void) /* May run on IST stack. */ dotraplinkage void __kprobes do_int3(struct pt_regs *regs, long error_code) { +#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP + if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) + == NOTIFY_STOP) + return; +#endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */ #ifdef CONFIG_KPROBES if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h index 8ecf20f..166cd07 100644 --- a/include/linux/kgdb.h +++ b/include/linux/kgdb.h @@ -59,6 +59,7 @@ struct uart_port; void kgdb_breakpoint(void); extern int kgdb_connected; +extern int kgdb_io_module_registered; extern atomic_t kgdb_setting_breakpoint; extern atomic_t kgdb_cpu_doing_single_step; diff --git a/kernel/kgdb.c b/kernel/kgdb.c index 6d31c0c..da738a2 100644 --- a/kernel/kgdb.c +++ b/kernel/kgdb.c @@ -85,7 +85,7 @@ int kgdb_connected; EXPORT_SYMBOL_GPL(kgdb_connected); /* All the KGDB handlers are installed */ -static int kgdb_io_module_registered; +int kgdb_io_module_registered; /* Guard for recursive entry */ static int exception_level; diff --git a/lib/Kconfig.kgdb b/lib/Kconfig.kgdb index 772e14b..617f797 100644 --- a/lib/Kconfig.kgdb +++ b/lib/Kconfig.kgdb @@ -57,6 +57,15 @@ config KGDB_TESTS_BOOT_STRING information about other strings you could use beyond the default of V1F100. +config KGDB_LOW_LEVEL_TRAP + bool "KGDB: Allow debugging with traps in notifiers" + depends on X86 + default n + help + This will add an extra call back to kgdb for the breakpoint + exception handler on which will will allow kgdb to step + through a notify handler. + config KGDB_KDB bool "KGDB_KDB: include kdb frontend for kgdb" default n -- 1.6.3.rc0.1.gf800 From jason.wessel@windriver.com Fri May 8 16:23:32 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-2.2 required=5.0 tests=AWL,BAYES_00,J_CHICKENPOX_35 autolearn=no version=3.3.0-rupdated Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n48LNV2F031481 for ; Fri, 8 May 2009 16:23:32 -0500 X-ASG-Debug-ID: 1241817815-367e00df0000-sLlkUa X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi Received: from mail.wrs.com (localhost [127.0.0.1]) by cuda.sgi.com (Spam Firewall) with ESMTP id 8F84E1D1EC01 for ; Fri, 8 May 2009 14:23:36 -0700 (PDT) Received: from mail.wrs.com (mail.windriver.com [147.11.1.11]) by cuda.sgi.com with ESMTP id 1uqUIQE6v52vNLJd for ; Fri, 08 May 2009 14:23:36 -0700 (PDT) Received: from ALA-MAIL03.corp.ad.wrs.com (ala-mail03 [147.11.57.144]) by mail.wrs.com (8.13.6/8.13.6) with ESMTP id n48LNU9K005547; Fri, 8 May 2009 14:23:30 -0700 (PDT) Received: from ala-mail06.corp.ad.wrs.com ([147.11.57.147]) by ALA-MAIL03.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:30 -0700 Received: from localhost.localdomain ([172.25.32.41]) by ala-mail06.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:30 -0700 From: Jason Wessel To: linux-kernel@vger.kernel.org Cc: kgdb-bugreport@lists.sourceforge.net, kdb@oss.sgi.com, Jason Wessel X-ASG-Orig-Subj: [PATCH 08/13] RFC ONLY - arm,kgdb: Add hook to catch an oops with debugger Subject: [PATCH 08/13] RFC ONLY - arm,kgdb: Add hook to catch an oops with debugger Date: Fri, 8 May 2009 16:23:15 -0500 Message-Id: <1241817800-9320-9-git-send-email-jason.wessel@windriver.com> X-Mailer: git-send-email 1.6.3.rc0.1.gf800 In-Reply-To: <1241817800-9320-8-git-send-email-jason.wessel@windriver.com> References: <1241817800-9320-1-git-send-email-jason.wessel@windriver.com> <1241817800-9320-2-git-send-email-jason.wessel@windriver.com> <1241817800-9320-3-git-send-email-jason.wessel@windriver.com> <1241817800-9320-4-git-send-email-jason.wessel@windriver.com> <1241817800-9320-5-git-send-email-jason.wessel@windriver.com> <1241817800-9320-6-git-send-email-jason.wessel@windriver.com> <1241817800-9320-7-git-send-email-jason.wessel@windriver.com> <1241817800-9320-8-git-send-email-jason.wessel@windriver.com> X-OriginalArrivalTime: 08 May 2009 21:23:30.0216 (UTC) FILETIME=[3BC7EA80:01C9D023] X-Barracuda-Connect: mail.windriver.com[147.11.1.11] X-Barracuda-Start-Time: 1241817816 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com X-Barracuda-Spam-Score: -1.52 X-Barracuda-Spam-Status: No, SCORE=-1.52 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests=BSF_RULE7568M X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.1.25266 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.50 BSF_RULE7568M Custom Rule 7568M X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean This is a RFC patch. The work to possibly merge kdb and kgdb is being evaluated and this patch is considered only a proof of concept or prototype. Add in a low level hook to catch calls to die() in the debugger. After the debugger is done, the standard system rules will be in play for the original exception. The kdb debugger wanted a chance to catch these sorts of exceptions for analysis. Signed-off-by: Jason Wessel --- arch/arm/include/asm/kgdb.h | 2 ++ arch/arm/kernel/kgdb.c | 8 ++++++++ arch/arm/kernel/traps.c | 5 +++++ 3 files changed, 15 insertions(+), 0 deletions(-) diff --git a/arch/arm/include/asm/kgdb.h b/arch/arm/include/asm/kgdb.h index 67af4b8..5a2e60e 100644 --- a/arch/arm/include/asm/kgdb.h +++ b/arch/arm/include/asm/kgdb.h @@ -95,6 +95,8 @@ extern int kgdb_fault_expected; #define _PC 15 #define _CPSR (GDB_MAX_REGS - 1) +int kgdb_die_hook(int cmd, const char *str, struct pt_regs *regs, int err); + /* * So that we can denote the end of a frame for tracing, * in the simple case: diff --git a/arch/arm/kernel/kgdb.c b/arch/arm/kernel/kgdb.c index bb17e9b..3c0e5e5 100644 --- a/arch/arm/kernel/kgdb.c +++ b/arch/arm/kernel/kgdb.c @@ -10,6 +10,7 @@ * Deepak Saxena */ #include +#include #include /* Make a local copy of the registers passed into the handler (bletch) */ @@ -189,6 +190,13 @@ void kgdb_arch_exit(void) unregister_undef_hook(&kgdb_compiled_brkpt_hook); } +int kgdb_die_hook(int cmd, const char *str, struct pt_regs *regs, int err) +{ + if (kgdb_handle_exception(1, err, cmd, regs)) + return NOTIFY_DONE; + return NOTIFY_STOP; +} + /* * Register our undef instruction hooks with ARM undef core. * We regsiter a hook specifically looking for the KGB break inst diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 57eb0f6..e649019 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -21,6 +21,9 @@ #include #include #include +#include +#include +#include #include #include @@ -248,6 +251,8 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err) { struct thread_info *thread = current_thread_info(); + kgdb_die_hook(DIE_OOPS, str, regs, err); + oops_enter(); console_verbose(); -- 1.6.3.rc0.1.gf800 From jason.wessel@windriver.com Fri May 8 16:23:30 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=AWL,BAYES_00 autolearn=ham version=3.3.0-rupdated Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n48LNT9M031435 for ; Fri, 8 May 2009 16:23:29 -0500 X-ASG-Debug-ID: 1241817813-364a00c00000-sLlkUa X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi Received: from mail.wrs.com (localhost [127.0.0.1]) by cuda.sgi.com (Spam Firewall) with ESMTP id 012E81D1EBEF for ; Fri, 8 May 2009 14:23:33 -0700 (PDT) Received: from mail.wrs.com (mail.windriver.com [147.11.1.11]) by cuda.sgi.com with ESMTP id PbCwv2fh6UOmc0KB for ; Fri, 08 May 2009 14:23:33 -0700 (PDT) Received: from ALA-MAIL03.corp.ad.wrs.com (ala-mail03 [147.11.57.144]) by mail.wrs.com (8.13.6/8.13.6) with ESMTP id n48LNRnx005497; Fri, 8 May 2009 14:23:27 -0700 (PDT) Received: from ala-mail06.corp.ad.wrs.com ([147.11.57.147]) by ALA-MAIL03.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:27 -0700 Received: from localhost.localdomain ([172.25.32.41]) by ala-mail06.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:27 -0700 From: Jason Wessel To: linux-kernel@vger.kernel.org Cc: kgdb-bugreport@lists.sourceforge.net, kdb@oss.sgi.com, Jason Wessel X-ASG-Orig-Subj: [PATCH 04/13] RFC ONLY - kgdb: gdb "monitor" -> kdb passthrough Subject: [PATCH 04/13] RFC ONLY - kgdb: gdb "monitor" -> kdb passthrough Date: Fri, 8 May 2009 16:23:11 -0500 Message-Id: <1241817800-9320-5-git-send-email-jason.wessel@windriver.com> X-Mailer: git-send-email 1.6.3.rc0.1.gf800 In-Reply-To: <1241817800-9320-4-git-send-email-jason.wessel@windriver.com> References: <1241817800-9320-1-git-send-email-jason.wessel@windriver.com> <1241817800-9320-2-git-send-email-jason.wessel@windriver.com> <1241817800-9320-3-git-send-email-jason.wessel@windriver.com> <1241817800-9320-4-git-send-email-jason.wessel@windriver.com> X-OriginalArrivalTime: 08 May 2009 21:23:27.0184 (UTC) FILETIME=[39F94500:01C9D023] X-Barracuda-Connect: mail.windriver.com[147.11.1.11] X-Barracuda-Start-Time: 1241817814 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com X-Barracuda-Spam-Score: -2.02 X-Barracuda-Spam-Status: No, SCORE=-2.02 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.1.25266 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean This is a RFC patch. The work to possibly merge kdb and kgdb is being evaluated and this patch is considered only a proof of concept or prototype. One of the driving forces behind integrating another front end to kgdb is to allow front end commands to be accessible via gdb's monitor command. It is true that you could write gdb macros to get certain data, but you may want to just use gdb to access the commands that are available in the kdb front end. This patch implements the Rcmd gdb stub packet. In gdb you access this with the "monitor" command. For instance you could type "monitor help", "monitor lsmod" or "monitor ps A" etc... There is no error checking or command restrictions on what you can and cannot access at this point. Doing something like trying to set breakpoints with the monitor command is going to cause nothing but problems. Perhaps in the future only the commands that are actually known to work with the gdb monitor command will be available. Signed-off-by: Jason Wessel --- include/linux/kgdb.h | 3 ++- kdb/kdb_io.c | 13 +++++++++---- kernel/kgdb.c | 28 +++++++++++++++++++++++++--- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h index 967803d..0299b79 100644 --- a/include/linux/kgdb.h +++ b/include/linux/kgdb.h @@ -279,7 +279,8 @@ extern int kgdb_handle_exception(int ex_vector, int signo, int err_code, struct pt_regs *regs); extern int kgdb_nmicallback(int cpu, void *regs); - +extern int kgdb_use_passthrough; +extern void kgdb_msg_write(const char *s, int len); extern int kgdb_single_step; extern atomic_t kgdb_active; diff --git a/kdb/kdb_io.c b/kdb/kdb_io.c index e7c3b40..d00f05c 100644 --- a/kdb/kdb_io.c +++ b/kdb/kdb_io.c @@ -24,6 +24,7 @@ #include #include #include +#include static struct console *kdbcons; @@ -698,10 +699,14 @@ kdb_printit: else #endif - while (c) { - c->write(c, kdb_buffer, strlen(kdb_buffer)); - touch_nmi_watchdog(); - c = c->next; + if (!kgdb_use_passthrough && kgdb_connected) { + kgdb_msg_write(kdb_buffer, strlen(kdb_buffer)); + } else { + while (c) { + c->write(c, kdb_buffer, strlen(kdb_buffer)); + touch_nmi_watchdog(); + c = c->next; + } } if (logging) { saved_loglevel = console_loglevel; diff --git a/kernel/kgdb.c b/kernel/kgdb.c index 2f093bc..484f106 100644 --- a/kernel/kgdb.c +++ b/kernel/kgdb.c @@ -100,9 +100,9 @@ static int kgdb_use_con; /* Controls for using the kgdb passthrough */ #ifdef CONFIG_KGDB_KDB_PRIMARY -static int kgdb_use_passthrough = 1; +int kgdb_use_passthrough = 1; #else /* ! CONFIG_KGDB_KDB_PRIMARY */ -static int kgdb_use_passthrough; +int kgdb_use_passthrough; #endif /* CONFIG_KGDB_KDB_PRIMARY */ #define KGDB_PASS_EVENT -12345 @@ -963,12 +963,15 @@ static inline int shadow_pid(int realpid) static char gdbmsgbuf[BUFMAX + 1]; -static void kgdb_msg_write(const char *s, int len) +void kgdb_msg_write(const char *s, int len) { char *bufptr; int wcount; int i; + if (len == 0) + len = strlen(s); + /* 'O'utput */ gdbmsgbuf[0] = 'O'; @@ -1270,6 +1273,25 @@ static void gdb_cmd_query(struct kgdb_state *ks) kgdb_mem2hex(tmpstr, remcom_out_buffer, strlen(tmpstr)); } break; +#ifdef CONFIG_KGDB_KDB + case 'R': + if (strncmp(remcom_in_buffer, "qRcmd,", 6) == 0) { + int len = strlen(remcom_in_buffer + 6); + + if ((len % 2) != 0) { + strcpy(remcom_out_buffer, "E01"); + break; + } + kgdb_hex2mem(remcom_in_buffer + 6, + remcom_out_buffer, len); + len = len / 2; + remcom_out_buffer[len++] = 0; + + kdb_parse(remcom_out_buffer); + strcpy(remcom_out_buffer, "OK"); + } + break; +#endif } } -- 1.6.3.rc0.1.gf800 From jason.wessel@windriver.com Fri May 8 16:23:32 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-3.0 required=5.0 tests=AWL,BAYES_00,FRT_LEVITRA, LOCAL_GNU_PATCH autolearn=ham version=3.3.0-rupdated Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n48LNW83031489 for ; Fri, 8 May 2009 16:23:32 -0500 X-ASG-Debug-ID: 1241817816-3e17003f0000-sLlkUa X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi Received: from mail.wrs.com (localhost [127.0.0.1]) by cuda.sgi.com (Spam Firewall) with ESMTP id EE9071D1EC05 for ; Fri, 8 May 2009 14:23:36 -0700 (PDT) Received: from mail.wrs.com (mail.windriver.com [147.11.1.11]) by cuda.sgi.com with ESMTP id STbWzwlHIqEfqHNd for ; Fri, 08 May 2009 14:23:36 -0700 (PDT) Received: from ALA-MAIL03.corp.ad.wrs.com (ala-mail03 [147.11.57.144]) by mail.wrs.com (8.13.6/8.13.6) with ESMTP id n48LNV7V005551; Fri, 8 May 2009 14:23:31 -0700 (PDT) Received: from ala-mail06.corp.ad.wrs.com ([147.11.57.147]) by ALA-MAIL03.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:31 -0700 Received: from localhost.localdomain ([172.25.32.41]) by ala-mail06.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:30 -0700 From: Jason Wessel To: linux-kernel@vger.kernel.org Cc: kgdb-bugreport@lists.sourceforge.net, kdb@oss.sgi.com, Jason Wessel X-ASG-Orig-Subj: [PATCH 09/13] RFC ONLY - powerpc,kgdb: Introduce low level trap catching Subject: [PATCH 09/13] RFC ONLY - powerpc,kgdb: Introduce low level trap catching Date: Fri, 8 May 2009 16:23:16 -0500 Message-Id: <1241817800-9320-10-git-send-email-jason.wessel@windriver.com> X-Mailer: git-send-email 1.6.3.rc0.1.gf800 In-Reply-To: <1241817800-9320-9-git-send-email-jason.wessel@windriver.com> References: <1241817800-9320-1-git-send-email-jason.wessel@windriver.com> <1241817800-9320-2-git-send-email-jason.wessel@windriver.com> <1241817800-9320-3-git-send-email-jason.wessel@windriver.com> <1241817800-9320-4-git-send-email-jason.wessel@windriver.com> <1241817800-9320-5-git-send-email-jason.wessel@windriver.com> <1241817800-9320-6-git-send-email-jason.wessel@windriver.com> <1241817800-9320-7-git-send-email-jason.wessel@windriver.com> <1241817800-9320-8-git-send-email-jason.wessel@windriver.com> <1241817800-9320-9-git-send-email-jason.wessel@windriver.com> X-OriginalArrivalTime: 08 May 2009 21:23:31.0075 (UTC) FILETIME=[3C4AFD30:01C9D023] X-Barracuda-Connect: mail.windriver.com[147.11.1.11] X-Barracuda-Start-Time: 1241817816 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com X-Barracuda-Spam-Score: -1.28 X-Barracuda-Spam-Status: No, SCORE=-1.28 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests=FRT_LEVITRA X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.1.25266 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.74 FRT_LEVITRA BODY: ReplaceTags: Levitra X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean This is a RFC patch. The work to possibly merge kdb and kgdb is being evaluated and this patch is considered only a proof of concept or prototype. The only way the debugger can handle a trap in inside rcu_lock, notify_die, or atomic_notifier_call_chain without a recursive fault is to have a low level "first opportunity handler" low level program_check_exception() handler. The other change here is to make sure that kgdb_handle_exception() is called with correct parameters when catching an oops, because kdb needs to know if the entry was an oops, single step, or breakpoint exception. Signed-off-by: Jason Wessel --- arch/powerpc/kernel/kgdb.c | 7 +++++-- arch/powerpc/kernel/traps.c | 7 +++++++ lib/Kconfig.kgdb | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c index e8207a3..d0ef25c 100644 --- a/arch/powerpc/kernel/kgdb.c +++ b/arch/powerpc/kernel/kgdb.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -115,7 +116,9 @@ void kgdb_roundup_cpus(unsigned long flags) /* KGDB functions to use existing PowerPC64 hooks. */ static int kgdb_debugger(struct pt_regs *regs) { - return kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs); + if (kgdb_handle_exception(1, computeSignal(TRAP(regs)), DIE_OOPS, regs)) + return 0; + return 1; } static int kgdb_handle_breakpoint(struct pt_regs *regs) @@ -123,7 +126,7 @@ static int kgdb_handle_breakpoint(struct pt_regs *regs) if (user_mode(regs)) return 0; - if (kgdb_handle_exception(0, SIGTRAP, 0, regs) != 0) + if (kgdb_handle_exception(1, SIGTRAP, 0, regs) != 0) return 0; if (*(u32 *) (regs->nip) == *(u32 *) (&arch_kgdb_ops.gdb_bpt_instr)) diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 678fbff..ae409df 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -812,12 +812,19 @@ void __kprobes program_check_exception(struct pt_regs *regs) return; } if (reason & REASON_TRAP) { + +#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP + if (debugger_bpt(regs)) + return; +#endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */ /* trap exception */ if (notify_die(DIE_BPT, "breakpoint", regs, 5, 5, SIGTRAP) == NOTIFY_STOP) return; +#ifndef CONFIG_KGDB_LOW_LEVEL_TRAP if (debugger_bpt(regs)) return; +#endif /* ! CONFIG_KGDB_LOW_LEVEL_TRAP */ if (!(regs->msr & MSR_PR) && /* not user-mode */ report_bug(regs->nip, regs) == BUG_TRAP_TYPE_WARN) { diff --git a/lib/Kconfig.kgdb b/lib/Kconfig.kgdb index 617f797..a2f63be 100644 --- a/lib/Kconfig.kgdb +++ b/lib/Kconfig.kgdb @@ -59,7 +59,7 @@ config KGDB_TESTS_BOOT_STRING config KGDB_LOW_LEVEL_TRAP bool "KGDB: Allow debugging with traps in notifiers" - depends on X86 + depends on X86 || PPC default n help This will add an extra call back to kgdb for the breakpoint -- 1.6.3.rc0.1.gf800 From jason.wessel@windriver.com Fri May 8 16:23:31 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-2.5 required=5.0 tests=AWL,BAYES_00 autolearn=ham version=3.3.0-rupdated Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n48LNUq9031446 for ; Fri, 8 May 2009 16:23:30 -0500 X-ASG-Debug-ID: 1241817813-364700b90000-sLlkUa X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi Received: from mail.wrs.com (localhost [127.0.0.1]) by cuda.sgi.com (Spam Firewall) with ESMTP id 5B5AA1D1EBF3 for ; Fri, 8 May 2009 14:23:33 -0700 (PDT) Received: from mail.wrs.com (mail.windriver.com [147.11.1.11]) by cuda.sgi.com with ESMTP id FoSuMTqSYsA62sSi for ; Fri, 08 May 2009 14:23:33 -0700 (PDT) Received: from ALA-MAIL03.corp.ad.wrs.com (ala-mail03 [147.11.57.144]) by mail.wrs.com (8.13.6/8.13.6) with ESMTP id n48LNQj5005491; Fri, 8 May 2009 14:23:26 -0700 (PDT) Received: from ala-mail06.corp.ad.wrs.com ([147.11.57.147]) by ALA-MAIL03.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:25 -0700 Received: from localhost.localdomain ([172.25.32.41]) by ala-mail06.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:25 -0700 From: Jason Wessel To: linux-kernel@vger.kernel.org Cc: kgdb-bugreport@lists.sourceforge.net, kdb@oss.sgi.com, Jason Wessel X-ASG-Orig-Subj: [PATCH 02/13] RFC ONLY - kgdb: core changes to support kdb Subject: [PATCH 02/13] RFC ONLY - kgdb: core changes to support kdb Date: Fri, 8 May 2009 16:23:09 -0500 Message-Id: <1241817800-9320-3-git-send-email-jason.wessel@windriver.com> X-Mailer: git-send-email 1.6.3.rc0.1.gf800 In-Reply-To: <1241817800-9320-2-git-send-email-jason.wessel@windriver.com> References: <1241817800-9320-1-git-send-email-jason.wessel@windriver.com> <1241817800-9320-2-git-send-email-jason.wessel@windriver.com> X-OriginalArrivalTime: 08 May 2009 21:23:25.0638 (UTC) FILETIME=[390D5E60:01C9D023] X-Barracuda-Connect: mail.windriver.com[147.11.1.11] X-Barracuda-Start-Time: 1241817814 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com X-Barracuda-Spam-Score: -2.02 X-Barracuda-Spam-Status: No, SCORE=-2.02 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.1.25266 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean This is a RFC patch. The work to possibly merge kdb and kgdb is being evaluated and this patch is considered only a proof of concept or prototype. These are the minimum changes to the kgdb core in order to enable an API to add on a different kgdb front end instead of the gdb stub driver. This patch introduces the comm_passthrough which is simply an alternate frontend that gets to talk to the kgdb I/O drivers instead of the gdb stub. You can switch back and forth between kdb or the gdb stub mode of operation dynamically. From gdb stub mode you can blindly type "$3#33", or from the kdb mode you can enter "kgdb" to switch to the gdb stub. The logic in the kgdb core depends on the kdb mode to to look for the typical gdb connection sequences and return with KGDB_PASS_EVENT. That should allow a reasonably seemless transition without leaving the kernel exception state. The two gdb queries are the "?" and "qSupported" query. Signed-off-by: Jason Wessel --- arch/arm/kernel/kgdb.c | 5 + arch/mips/kernel/kgdb.c | 5 + arch/powerpc/kernel/kgdb.c | 5 + arch/x86/kernel/kgdb.c | 5 + include/linux/kgdb.h | 3 + kernel/kgdb.c | 202 ++++++++++++++++++++++++++++++++++++++++++-- lib/Kconfig.kgdb | 14 +++ 7 files changed, 233 insertions(+), 6 deletions(-) diff --git a/arch/arm/kernel/kgdb.c b/arch/arm/kernel/kgdb.c index ba8ccfe..bb17e9b 100644 --- a/arch/arm/kernel/kgdb.c +++ b/arch/arm/kernel/kgdb.c @@ -97,6 +97,11 @@ sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *task) gdb_regs[_CPSR] = thread_regs->ARM_cpsr; } +void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc) +{ + regs->ARM_pc = pc; +} + static int compiled_break; int kgdb_arch_handle_exception(int exception_vector, int signo, diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c index 6e152c8..54f2d40 100644 --- a/arch/mips/kernel/kgdb.c +++ b/arch/mips/kernel/kgdb.c @@ -179,6 +179,11 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) *(ptr++) = regs->cp0_epc; } +void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc) +{ + regs->cp0_epc = pc; +} + /* * Calls linux_debug_hook before the kernel dies. If KGDB is enabled, * then try to fall into the debugger diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c index fe8f71d..e8207a3 100644 --- a/arch/powerpc/kernel/kgdb.c +++ b/arch/powerpc/kernel/kgdb.c @@ -315,6 +315,11 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) (unsigned long)(((void *)gdb_regs) + NUMREGBYTES)); } +void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc) +{ + regs->nip = pc; +} + /* * This function does PowerPC specific procesing for interfacing to gdb. */ diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index eedfaeb..6d2503d 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c @@ -572,6 +572,11 @@ unsigned long kgdb_arch_pc(int exception, struct pt_regs *regs) return instruction_pointer(regs); } +void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip) +{ + regs->ip = ip; +} + struct kgdb_arch arch_kgdb_ops = { /* Breakpoint instruction: */ .gdb_bpt_instr = { 0xcc }, diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h index 6adcc29..3e838d6 100644 --- a/include/linux/kgdb.h +++ b/include/linux/kgdb.h @@ -263,6 +263,7 @@ extern struct kgdb_arch arch_kgdb_ops; extern unsigned long __weak kgdb_arch_pc(int exception, struct pt_regs *regs); +extern void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc); extern int kgdb_register_io_module(struct kgdb_io *local_kgdb_io_ops); extern void kgdb_unregister_io_module(struct kgdb_io *local_kgdb_io_ops); @@ -271,6 +272,8 @@ extern int kgdb_mem2hex(char *mem, char *buf, int count); extern int kgdb_hex2mem(char *buf, char *mem, int count); extern int kgdb_isremovedbreak(unsigned long addr); +extern int kgdb_remove_sw_break(unsigned long addr); +extern int kgdb_set_sw_break(unsigned long addr); extern int kgdb_handle_exception(int ex_vector, int signo, int err_code, diff --git a/kernel/kgdb.c b/kernel/kgdb.c index e4dcfb2..067f2cf 100644 --- a/kernel/kgdb.c +++ b/kernel/kgdb.c @@ -47,6 +47,9 @@ #include #include #include +#include +#include +#include #include #include @@ -94,6 +97,15 @@ static int kgdb_con_registered; /* determine if kgdb console output should be used */ static int kgdb_use_con; +/* Controls for using the kgdb passthrough */ +#ifdef CONFIG_KGDB_KDB_PRIMARY +static int kgdb_use_passthrough = 1; +#else /* ! CONFIG_KGDB_KDB_PRIMARY */ +static int kgdb_use_passthrough; +#endif /* CONFIG_KGDB_KDB_PRIMARY */ +#define KGDB_PASS_EVENT -12345 + + static int __init opt_kgdb_con(char *str) { kgdb_use_con = 1; @@ -239,6 +251,155 @@ void __weak kgdb_disable_hw_debug(struct pt_regs *regs) } /* + * KDB interface to KGDB internals + */ +#ifdef CONFIG_KGDB_KDB +static void gdb_cmd_status(struct kgdb_state *ks); +static void put_packet(char *buffer); +static int kgdb_activate_sw_breakpoints(void); + +static int kgdbio_get_char(void) +{ + int ret = kgdb_io_ops->read_char(); + if (!kgdb_use_passthrough) + return ret; + if (ret == 127) + return 8; + return ret; +} + +get_char_func kdb_poll_funcs[] = { + kgdbio_get_char, + NULL, +}; + +static int comm_passthrough(struct kgdb_state *ks) +{ + int error = 0; + unsigned long addr = kgdb_arch_pc(ks->ex_vector, ks->linux_regs); + kdb_reason_t reason = KDB_REASON_OOPS; + kdb_dbtrap_t db_result = KDB_DB_NOBPT; + int i; + + ks->pass_exception = 0; + if (ks->err_code == DIE_OOPS) + KDB_FLAG_SET(CATASTROPHIC); + if (atomic_read(&kgdb_setting_breakpoint)) + reason = KDB_REASON_KEYBOARD; + + for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { + if ((kgdb_break[i].state == BP_SET) && + (kgdb_break[i].bpt_addr == addr)) { + reason = KDB_REASON_BREAK; + db_result = KDB_DB_BPT; + if (addr != instruction_pointer(ks->linux_regs)) + kgdb_arch_set_pc(ks->linux_regs, addr); + break; + } + } + if (reason == KDB_REASON_BREAK) { + kdb_bp_t *bp; + for (i = 0, bp = kdb_breakpoints; i < KDB_MAXBPT; i++, bp++) { + if (bp->bp_free) + continue; + if (bp->bp_addr == addr) { + bp->bp_delay = 1; + bp->bp_delayed = 1; + /* SSBPT is set when the kernel debugger must + * single step a task in order to re-establish + * an instruction breakpoint which uses the + * instruction replacement mechanism. It is + * cleared by any action that removes the need + * to single-step the breakpoint. + */ + KDB_STATE_SET(SSBPT); + break; + } + } + } + + if (reason != KDB_REASON_BREAK && ks->ex_vector == 0 && + ks->signo == SIGTRAP) { + reason = KDB_REASON_SSTEP; + db_result = KDB_DB_BPT; + } + /* Set initial kdb state variables */ + KDB_STATE_CLEAR(KGDB_TRANS); + kdb_initial_cpu = ks->cpu; + kdb_current_task = kgdb_info[ks->cpu].task; + kdb_current_regs = kgdb_info[ks->cpu].debuggerinfo; + /* Remove any breakpoints as needed by kdb and clear single step*/ + kdb_bp_remove_local(); + kdb_bp_remove_global(); + KDB_STATE_CLEAR(DOING_SS); + KDB_STATE_CLEAR(DOING_SSB); + for_each_online_cpu(i) { + kdb_save_running_cpu(kgdb_info[i].debuggerinfo, + kgdb_info[i].task, i); + } + /* XXX FIXME XXX + * Need to fix this such that it is locked to a + * specific thread and address + */ + kdb_initial_cpu = ks->cpu; + if (KDB_STATE(SSBPT) && reason == KDB_REASON_SSTEP) { + KDB_STATE_CLEAR(SSBPT); + KDB_STATE_CLEAR(DOING_SS); + } else { + /* Start kdb main loop */ + error = kdb_main_loop(KDB_REASON_ENTER, reason, + ks->err_code, db_result, ks->linux_regs); + } + /* Upon exit from the kdb main loop setup break points and restart + * the system based on the requested continue state + */ + kdb_initial_cpu = -1; + kdb_current_task = NULL; + kdb_current_regs = NULL; + kdbnearsym_cleanup(); + if (error == KDB_CMD_KGDB) { + if (KDB_STATE(DOING_KGDB) || KDB_STATE(DOING_KGDB2)) { + kgdb_io_ops->write_char('+'); + if (KDB_STATE(DOING_KGDB)) + gdb_cmd_status(ks); + else + strcpy(remcom_out_buffer, ""); + KDB_STATE_CLEAR(DOING_KGDB); + KDB_STATE_CLEAR(DOING_KGDB2); + put_packet(remcom_out_buffer); + } + return KGDB_PASS_EVENT; + } + kdb_bp_install_global(ks->linux_regs); + kdb_bp_install_local(ks->linux_regs); + kgdb_activate_sw_breakpoints(); + if (KDB_STATE(DOING_SS)) + strcpy(remcom_in_buffer, "s"); + else + strcpy(remcom_in_buffer, "c"); + + if (KDB_FLAG(CATASTROPHIC) && ks->err_code == DIE_OOPS) + ks->pass_exception = 1; + KDB_FLAG_CLEAR(CATASTROPHIC); + + error = kgdb_arch_handle_exception(ks->ex_vector, + ks->signo, + ks->err_code, + remcom_in_buffer, + remcom_out_buffer, + ks->linux_regs); + if (ks->pass_exception) + error = 1; + return error; +} +#else /* ! CONFIG_KGDB_KDB */ +static int comm_passthrough(struct kgdb_state *ks) +{ + return KGDB_PASS_EVENT; +} +#endif /* CONFIG_KGDB_KDB */ + +/* * GDB remote protocol parser: */ @@ -638,7 +799,7 @@ static int kgdb_activate_sw_breakpoints(void) return 0; } -static int kgdb_set_sw_break(unsigned long addr) +int kgdb_set_sw_break(unsigned long addr) { int err = kgdb_validate_break_address(addr); int breakno = -1; @@ -700,7 +861,7 @@ static int kgdb_deactivate_sw_breakpoints(void) return 0; } -static int kgdb_remove_sw_break(unsigned long addr) +int kgdb_remove_sw_break(unsigned long addr) { int i; @@ -817,8 +978,14 @@ static int kgdb_io_ready(int print_wait) return 1; if (atomic_read(&kgdb_setting_breakpoint)) return 1; - if (print_wait) + if (print_wait) { +#ifdef CONFIG_KGDB_KDB + if (!kgdb_use_passthrough) + printk(KERN_CRIT "KGDB: waiting... or $3#33 for KDB\n"); +#else printk(KERN_CRIT "KGDB: Waiting for remote debugger\n"); +#endif + } return 1; } @@ -1293,6 +1460,13 @@ static int gdb_serial_stub(struct kgdb_state *ks) case 'Z': /* Break point set */ gdb_cmd_break(ks); break; +#ifdef CONFIG_KGDB_KDB + case '3': /* Escape into the comm_passthrough */ + if (remcom_in_buffer[1] == '\0') { + gdb_cmd_detachkill(ks); + return KGDB_PASS_EVENT; + } +#endif case 'C': /* Exception passing */ tmp = gdb_cmd_exception_pass(ks); if (tmp > 0) @@ -1499,8 +1673,18 @@ acquirelock: kgdb_contthread = current; exception_level = 0; - /* Talk to debugger with gdbserial protocol */ - error = gdb_serial_stub(ks); + while (1) { + if (kgdb_use_passthrough) { + error = comm_passthrough(ks); + } else { + /* Talk to debugger with gdbserial protocol */ + error = gdb_serial_stub(ks); + } + if (error == KGDB_PASS_EVENT) + kgdb_use_passthrough = !kgdb_use_passthrough; + else + break; + } /* Call the I/O driver's post_exception routine */ if (kgdb_io_ops->post_exception) @@ -1575,8 +1759,14 @@ static void sysrq_handle_gdb(int key, struct tty_struct *tty) printk(KERN_CRIT "ERROR: No KGDB I/O module available\n"); return; } - if (!kgdb_connected) + if (!kgdb_connected) { +#ifdef CONFIG_KGDB_KDB + if (!kgdb_use_passthrough) + printk(KERN_CRIT "KGDB or $3#33 for KDB\n"); +#else printk(KERN_CRIT "Entering KGDB\n"); +#endif + } kgdb_breakpoint(); } diff --git a/lib/Kconfig.kgdb b/lib/Kconfig.kgdb index 9b5d1d7..59b47b9 100644 --- a/lib/Kconfig.kgdb +++ b/lib/Kconfig.kgdb @@ -57,4 +57,18 @@ config KGDB_TESTS_BOOT_STRING information about other strings you could use beyond the default of V1F100. +config KGDB_KDB + bool "KGDB_KDB: include kdb frontend for kgdb" + default n + help + KDB frontend for kernel + +config KGDB_KDB_PRIMARY + bool "KGDB_KDB: Make kdb the default debugger" + depends on KGDB_KDB + default y + help + KDB will be the active debugger instead of the typical kgdb + frontend. + endif # KGDB -- 1.6.3.rc0.1.gf800 From jason.wessel@windriver.com Fri May 8 16:23:34 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-2.5 required=5.0 tests=AWL,BAYES_00 autolearn=ham version=3.3.0-rupdated Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n48LNXbQ031512 for ; Fri, 8 May 2009 16:23:34 -0500 X-ASG-Debug-ID: 1241817817-367d00a80000-sLlkUa X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi Received: from mail.wrs.com (localhost [127.0.0.1]) by cuda.sgi.com (Spam Firewall) with ESMTP id A46521D1EC09 for ; Fri, 8 May 2009 14:23:38 -0700 (PDT) Received: from mail.wrs.com (mail.windriver.com [147.11.1.11]) by cuda.sgi.com with ESMTP id SdBLenWmj1ole0zn for ; Fri, 08 May 2009 14:23:38 -0700 (PDT) Received: from ALA-MAIL03.corp.ad.wrs.com (ala-mail03 [147.11.57.144]) by mail.wrs.com (8.13.6/8.13.6) with ESMTP id n48LNXwD005557; Fri, 8 May 2009 14:23:33 -0700 (PDT) Received: from ala-mail06.corp.ad.wrs.com ([147.11.57.147]) by ALA-MAIL03.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:32 -0700 Received: from localhost.localdomain ([172.25.32.41]) by ala-mail06.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:32 -0700 From: Jason Wessel To: linux-kernel@vger.kernel.org Cc: kgdb-bugreport@lists.sourceforge.net, kdb@oss.sgi.com, Jason Wessel X-ASG-Orig-Subj: [PATCH 11/13] kgdb: Add the ability to schedule a breakpoint via a tasklet Subject: [PATCH 11/13] kgdb: Add the ability to schedule a breakpoint via a tasklet Date: Fri, 8 May 2009 16:23:18 -0500 Message-Id: <1241817800-9320-12-git-send-email-jason.wessel@windriver.com> X-Mailer: git-send-email 1.6.3.rc0.1.gf800 In-Reply-To: <1241817800-9320-11-git-send-email-jason.wessel@windriver.com> References: <1241817800-9320-1-git-send-email-jason.wessel@windriver.com> <1241817800-9320-2-git-send-email-jason.wessel@windriver.com> <1241817800-9320-3-git-send-email-jason.wessel@windriver.com> <1241817800-9320-4-git-send-email-jason.wessel@windriver.com> <1241817800-9320-5-git-send-email-jason.wessel@windriver.com> <1241817800-9320-6-git-send-email-jason.wessel@windriver.com> <1241817800-9320-7-git-send-email-jason.wessel@windriver.com> <1241817800-9320-8-git-send-email-jason.wessel@windriver.com> <1241817800-9320-9-git-send-email-jason.wessel@windriver.com> <1241817800-9320-10-git-send-email-jason.wessel@windriver.com> <1241817800-9320-11-git-send-email-jason.wessel@windriver.com> X-OriginalArrivalTime: 08 May 2009 21:23:32.0513 (UTC) FILETIME=[3D266910:01C9D023] X-Barracuda-Connect: mail.windriver.com[147.11.1.11] X-Barracuda-Start-Time: 1241817818 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com X-Barracuda-Spam-Score: -2.02 X-Barracuda-Spam-Status: No, SCORE=-2.02 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.1.25266 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean Some kgdb I/O modules require the ability to create a breakpoint tasklet, such as kgdboc and external modules such as kgdboe. The breakpoint tasklet is used as an asynchronous entry point into the debugger which will have a different function scope than the current execution path where it might not be safe to have an inline breakpoint inside the kgdb I/O driver. Signed-off-by: Jason Wessel --- include/linux/kgdb.h | 1 + kernel/kgdb.c | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 0 deletions(-) diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h index 166cd07..1fa0bcc 100644 --- a/include/linux/kgdb.h +++ b/include/linux/kgdb.h @@ -270,6 +270,7 @@ extern int kgdb_use_passthrough; extern void kgdb_msg_write(const char *s, int len); extern int kgdb_single_step; extern atomic_t kgdb_active; +extern void kgdb_schedule_breakpoint(void); #ifdef CONFIG_KGDB_SERIAL_CONSOLE extern void __init early_kgdboc_init(void); diff --git a/kernel/kgdb.c b/kernel/kgdb.c index da738a2..f303410 100644 --- a/kernel/kgdb.c +++ b/kernel/kgdb.c @@ -136,6 +136,7 @@ atomic_t kgdb_active = ATOMIC_INIT(-1); */ static atomic_t passive_cpu_wait[NR_CPUS]; static atomic_t cpu_in_kgdb[NR_CPUS]; +static atomic_t kgdb_break_tasklet_var; atomic_t kgdb_setting_breakpoint; struct task_struct *kgdb_usethread; @@ -1862,6 +1863,31 @@ static void kgdb_unregister_callbacks(void) } } +/* + * There are times a tasklet needs to be used vs a compiled in + * break point so as to cause an exception outside a kgdb I/O module, + * such as is the case with kgdboe, where calling a breakpoint in the + * I/O driver itself would be fatal. + */ +static void kgdb_tasklet_bpt(unsigned long ing) +{ + kgdb_breakpoint(); + atomic_set(&kgdb_break_tasklet_var, 0); +} + +static DECLARE_TASKLET(kgdb_tasklet_breakpoint, kgdb_tasklet_bpt, 0); + +void kgdb_schedule_breakpoint(void) +{ + if (atomic_read(&kgdb_break_tasklet_var) || + atomic_read(&kgdb_active) != -1 || + atomic_read(&kgdb_setting_breakpoint)) + return; + atomic_inc(&kgdb_break_tasklet_var); + tasklet_schedule(&kgdb_tasklet_breakpoint); +} +EXPORT_SYMBOL_GPL(kgdb_schedule_breakpoint); + static void kgdb_initial_breakpoint(void) { kgdb_break_asap = 0; -- 1.6.3.rc0.1.gf800 From jason.wessel@windriver.com Fri May 8 16:23:34 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-2.5 required=5.0 tests=AWL,BAYES_00 autolearn=ham version=3.3.0-rupdated Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n48LNY21031518 for ; Fri, 8 May 2009 16:23:34 -0500 X-ASG-Debug-ID: 1241817818-3e15005c0000-sLlkUa X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi Received: from mail.wrs.com (localhost [127.0.0.1]) by cuda.sgi.com (Spam Firewall) with ESMTP id 1EDBF1D1EC0B for ; Fri, 8 May 2009 14:23:38 -0700 (PDT) Received: from mail.wrs.com (mail.windriver.com [147.11.1.11]) by cuda.sgi.com with ESMTP id S2Hgu2Wz6dyUlGFt for ; Fri, 08 May 2009 14:23:38 -0700 (PDT) Received: from ALA-MAIL03.corp.ad.wrs.com (ala-mail03 [147.11.57.144]) by mail.wrs.com (8.13.6/8.13.6) with ESMTP id n48LNXLu005560; Fri, 8 May 2009 14:23:33 -0700 (PDT) Received: from ala-mail06.corp.ad.wrs.com ([147.11.57.147]) by ALA-MAIL03.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:33 -0700 Received: from localhost.localdomain ([172.25.32.41]) by ala-mail06.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:33 -0700 From: Jason Wessel To: linux-kernel@vger.kernel.org Cc: kgdb-bugreport@lists.sourceforge.net, kdb@oss.sgi.com, Jason Wessel X-ASG-Orig-Subj: [PATCH 12/13] RFC ONLY - kgdb,kdb: use async breakpoint for sysrq for usb Subject: [PATCH 12/13] RFC ONLY - kgdb,kdb: use async breakpoint for sysrq for usb Date: Fri, 8 May 2009 16:23:19 -0500 Message-Id: <1241817800-9320-13-git-send-email-jason.wessel@windriver.com> X-Mailer: git-send-email 1.6.3.rc0.1.gf800 In-Reply-To: <1241817800-9320-12-git-send-email-jason.wessel@windriver.com> References: <1241817800-9320-1-git-send-email-jason.wessel@windriver.com> <1241817800-9320-2-git-send-email-jason.wessel@windriver.com> <1241817800-9320-3-git-send-email-jason.wessel@windriver.com> <1241817800-9320-4-git-send-email-jason.wessel@windriver.com> <1241817800-9320-5-git-send-email-jason.wessel@windriver.com> <1241817800-9320-6-git-send-email-jason.wessel@windriver.com> <1241817800-9320-7-git-send-email-jason.wessel@windriver.com> <1241817800-9320-8-git-send-email-jason.wessel@windriver.com> <1241817800-9320-9-git-send-email-jason.wessel@windriver.com> <1241817800-9320-10-git-send-email-jason.wessel@windriver.com> <1241817800-9320-11-git-send-email-jason.wessel@windriver.com> <1241817800-9320-12-git-send-email-jason.wessel@windriver.com> X-OriginalArrivalTime: 08 May 2009 21:23:33.0372 (UTC) FILETIME=[3DA97BC0:01C9D023] X-Barracuda-Connect: mail.windriver.com[147.11.1.11] X-Barracuda-Start-Time: 1241817819 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com X-Barracuda-Spam-Score: -2.02 X-Barracuda-Spam-Status: No, SCORE=-2.02 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.1.25266 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean This is a RFC patch. The work to possibly merge kdb and kgdb is being evaluated and this patch is considered only a proof of concept or prototype. For kdb, the usb keyboard will become disabled if you use a sysrq sequence to enter kdb. Using a tasklet solves the problem. Signed-off-by: Jason Wessel --- kernel/kgdb.c | 12 +++++++++++- 1 files changed, 11 insertions(+), 1 deletions(-) diff --git a/kernel/kgdb.c b/kernel/kgdb.c index f303410..034f6eb 100644 --- a/kernel/kgdb.c +++ b/kernel/kgdb.c @@ -1817,8 +1817,18 @@ static void sysrq_handle_gdb(int key, struct tty_struct *tty) printk(KERN_CRIT "Entering KGDB\n"); #endif } - +#ifdef CONFIG_KDB_USB + /* XXX FIX ME XXX + * For now force the sysrq break point to be in a tasklet + * else if you send it from a usb keyboard, the keyboard cannot be + * used to interact with kdb because all the locks for the USB hcd + * device will be held. This probably needs a run time check + * against what i/o driver submitted the breakpoint request. + */ + kgdb_schedule_breakpoint(); +#else /* ! CONFIG_KDB_USB */ kgdb_breakpoint(); +#endif /* CONFIG_KDB_USB */ } static struct sysrq_key_op sysrq_gdb_op = { -- 1.6.3.rc0.1.gf800 From jason.wessel@windriver.com Fri May 8 16:23:37 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=AWL,BAYES_00 autolearn=ham version=3.3.0-rupdated Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n48LNbSt031538 for ; Fri, 8 May 2009 16:23:37 -0500 X-ASG-Debug-ID: 1241817819-3fb700440000-sLlkUa X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi Received: from mail.wrs.com (localhost [127.0.0.1]) by cuda.sgi.com (Spam Firewall) with ESMTP id 86CBE1D1EC0C for ; Fri, 8 May 2009 14:23:39 -0700 (PDT) Received: from mail.wrs.com (mail.windriver.com [147.11.1.11]) by cuda.sgi.com with ESMTP id vYzGpuxrDKpMRVSG for ; Fri, 08 May 2009 14:23:39 -0700 (PDT) Received: from ALA-MAIL03.corp.ad.wrs.com (ala-mail03 [147.11.57.144]) by mail.wrs.com (8.13.6/8.13.6) with ESMTP id n48LNYur005563; Fri, 8 May 2009 14:23:34 -0700 (PDT) Received: from ala-mail06.corp.ad.wrs.com ([147.11.57.147]) by ALA-MAIL03.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:34 -0700 Received: from localhost.localdomain ([172.25.32.41]) by ala-mail06.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:33 -0700 From: Jason Wessel To: linux-kernel@vger.kernel.org Cc: kgdb-bugreport@lists.sourceforge.net, kdb@oss.sgi.com, Jason Wessel X-ASG-Orig-Subj: [PATCH 13/13] RFC ONLY - usb,keyboard: uchi, echi, and ochi polling keyboard urbs Subject: [PATCH 13/13] RFC ONLY - usb,keyboard: uchi, echi, and ochi polling keyboard urbs Date: Fri, 8 May 2009 16:23:20 -0500 Message-Id: <1241817800-9320-14-git-send-email-jason.wessel@windriver.com> X-Mailer: git-send-email 1.6.3.rc0.1.gf800 In-Reply-To: <1241817800-9320-13-git-send-email-jason.wessel@windriver.com> References: <1241817800-9320-1-git-send-email-jason.wessel@windriver.com> <1241817800-9320-2-git-send-email-jason.wessel@windriver.com> <1241817800-9320-3-git-send-email-jason.wessel@windriver.com> <1241817800-9320-4-git-send-email-jason.wessel@windriver.com> <1241817800-9320-5-git-send-email-jason.wessel@windriver.com> <1241817800-9320-6-git-send-email-jason.wessel@windriver.com> <1241817800-9320-7-git-send-email-jason.wessel@windriver.com> <1241817800-9320-8-git-send-email-jason.wessel@windriver.com> <1241817800-9320-9-git-send-email-jason.wessel@windriver.com> <1241817800-9320-10-git-send-email-jason.wessel@windriver.com> <1241817800-9320-11-git-send-email-jason.wessel@windriver.com> <1241817800-9320-12-git-send-email-jason.wessel@windriver.com> <1241817800-9320-13-git-send-email-jason.wessel@windriver.com> X-OriginalArrivalTime: 08 May 2009 21:23:34.0044 (UTC) FILETIME=[3E1005C0:01C9D023] X-Barracuda-Connect: mail.windriver.com[147.11.1.11] X-Barracuda-Start-Time: 1241817820 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com X-Barracuda-Spam-Score: -1.52 X-Barracuda-Spam-Status: No, SCORE=-1.52 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests=BSF_RULE7568M X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.1.25266 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.50 BSF_RULE7568M Custom Rule 7568M X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean This is a RFC patch. The work to possibly merge kdb and kgdb is being evaluated and this patch is considered only a proof of concept or prototype. This is a direct port of the kdb usb polling code, with some clean up for checkpatch.pl. I would rate this particular patch in the "highly experimental/controversial" classification. Based on the ehci and ochi implementations from the kdb 4.4, I added a uhci implementation, because that was the only usb keyboard type I had at the time. The uhci polling code "appears to work", but has problems in that it does not seem to remove the urbs completely from the queue on resume from debugging mode. I am not actually certain if the ehci and ochi drivers have the same problem because I was not able to test them. As I understand it from reading the original ehci and uhci polling implementation, the concept is to poll the queue for a particular urb and process only that urb from the driver queue. At the same time, the poll code attempts to leave everything else alone. Assuming that is the intent behind this code, that means only the usb keyboard(s) stay alive while kdb is active. Perhaps we can get further comments from the original authors at some point down the road. :-) Signed-off-by: Jason Wessel --- drivers/char/kdb_keyboard.c | 199 ++++++++++++++++++++++++++++++++++++ drivers/hid/usbhid/hid-core.c | 26 +++++ drivers/hid/usbhid/usbkbd.c | 13 +++ drivers/serial/kgdboc.c | 12 ++ drivers/usb/core/hcd.c | 14 +++ drivers/usb/core/hcd.h | 4 + drivers/usb/host/ehci-hcd.c | 42 ++++++++ drivers/usb/host/ehci-pci.c | 6 + drivers/usb/host/ehci-q.c | 225 +++++++++++++++++++++++++++++++++++++++++ drivers/usb/host/ohci-hcd.c | 66 ++++++++++++ drivers/usb/host/ohci-pci.c | 6 +- drivers/usb/host/ohci-q.c | 63 ++++++++++++ drivers/usb/host/uhci-hcd.c | 36 +++++++ drivers/usb/host/uhci-q.c | 51 +++++++++ include/linux/kdb.h | 1 + include/linux/kdbprivate.h | 1 + lib/Kconfig.kgdb | 7 ++ 17 files changed, 771 insertions(+), 1 deletions(-) diff --git a/drivers/char/kdb_keyboard.c b/drivers/char/kdb_keyboard.c index 6dcbb07..6cc4636 100644 --- a/drivers/char/kdb_keyboard.c +++ b/drivers/char/kdb_keyboard.c @@ -11,6 +11,7 @@ #ifdef CONFIG_VT_CONSOLE #include +#include #include #include #include @@ -20,6 +21,204 @@ static int kbd_exists; +#ifdef CONFIG_KDB_USB + +/* support up to 8 USB keyboards (probably excessive, but...) */ +#define KDB_USB_NUM_KEYBOARDS 8 +struct kdb_usb_kbd_info kdb_usb_kbds[KDB_USB_NUM_KEYBOARDS]; + +static unsigned char kdb_usb_keycode[256] = { + 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, + 36, 37, 38, 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, + 17, 45, 21, 44, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 28, 1, 14, 15, 57, 12, 13, 26, 27, 43, 84, 39, + 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 87, 88, 99, 70, 119, 110, 102, 104, 111, 107, + 109, 106, 105, 108, 103, 69, 98, 55, 74, 78, 96, 79, 80, + 81, 75, 76, 77, 71, 72, 73, 82, 83, 86, 127, 116, 117, + 85, 89, 90, 91, 92, 93, 94, 95, 120, 121, 122, 123, 134, + 138, 130, 132, 128, 129, 131, 137, 133, 135, 136, 113, 115, 114, + 0, 0, 0, 124, 0, 181, 182, 183, 184, 185, 186, 187, 188, + 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 29, 42, 56, 125, 97, 54, 100, 126, 164, 166, + 165, 163, 161, 115, 114, 113, 150, 158, 159, 128, 136, 177, 178, + 176, 142, 152, 173, 140 +}; + +/* + * kdb_usb_keyboard_attach() + * Attach a USB keyboard to kdb. + */ +int +kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func) +{ + int i; + int rc = -1; + + if (kdb_no_usb) + return 0; + + /* + * Search through the array of KDB USB keyboards (kdb_usb_kbds) + * looking for a free index. If found, assign the keyboard to + * the array index. + */ + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb) /* index is already assigned */ + continue; + + /* found a free array index */ + kdb_usb_kbds[i].urb = urb; + kdb_usb_kbds[i].buffer = buffer; + kdb_usb_kbds[i].poll_func = poll_func; + + rc = 0; /* success */ + + break; + } + + return rc; +} +EXPORT_SYMBOL_GPL(kdb_usb_keyboard_attach); + +/* + * kdb_usb_keyboard_detach() + * Detach a USB keyboard from kdb. + */ +int +kdb_usb_keyboard_detach(struct urb *urb) +{ + int i; + int rc = -1; + + if (kdb_no_usb) + return 0; + + /* + * Search through the array of KDB USB keyboards (kdb_usb_kbds) + * looking for the index with the matching URB. If found, + * clear the array index. + */ + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb != urb) + continue; + + /* found it, clear the index */ + kdb_usb_kbds[i].urb = NULL; + kdb_usb_kbds[i].buffer = NULL; + kdb_usb_kbds[i].poll_func = NULL; + kdb_usb_kbds[i].caps_lock = 0; + + rc = 0; /* success */ + + break; + } + + return rc; +} +EXPORT_SYMBOL_GPL(kdb_usb_keyboard_detach); + +/* + * get_usb_char + * This function drives the USB attached keyboards. + * Fetch the USB scancode and decode it. + */ +int +kdb_get_usb_char(void) +{ + int i; + int ret; + unsigned char keycode, spec; + + if (kdb_no_usb) + return -1; + + /* + * Loop through all the USB keyboard(s) and return + * the first character obtained from them. + */ + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + /* skip uninitialized keyboard array entries */ + if (!kdb_usb_kbds[i].urb || !kdb_usb_kbds[i].buffer || + !kdb_usb_kbds[i].poll_func) + continue; + + /* Transfer char */ + ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); + if (ret == -EBUSY && kdb_usb_kbds[i].poll_ret != -EBUSY) + kdb_printf("NOTICE: USB HD driver BUSY. " + "USB keyboard has been disabled.\n"); + + kdb_usb_kbds[i].poll_ret = ret; + + if (ret < 0) /* error or no characters, try the next kbd */ + continue; + + spec = kdb_usb_kbds[i].buffer[0]; + keycode = kdb_usb_kbds[i].buffer[2]; + kdb_usb_kbds[i].buffer[0] = (char)0; + kdb_usb_kbds[i].buffer[2] = (char)0; + + if (kdb_usb_kbds[i].buffer[3]) { + kdb_usb_kbds[i].buffer[3] = (char)0; + continue; + } + + /* A normal key is pressed, decode it */ + if (keycode) + keycode = kdb_usb_keycode[keycode]; + + /* 2 Keys pressed at one time ? */ + if (spec && keycode) { + switch (spec) { + case 0x2: + case 0x20: /* Shift */ + return shift_map[keycode]; + case 0x1: + case 0x10: /* Ctrl */ + return ctrl_map[keycode]; + case 0x4: + case 0x40: /* Alt */ + break; + } + } else if (keycode) { /* If only one key pressed */ + switch (keycode) { + case 0x1C: /* Enter */ + return 13; + + case 0x3A: /* Capslock */ + kdb_usb_kbds[i].caps_lock = + !(kdb_usb_kbds[i].caps_lock); + break; + case 0x0E: /* Backspace */ + return 8; + case 0x0F: /* TAB */ + return 9; + case 0x77: /* Pause */ + break; + default: + if (!kdb_usb_kbds[i].caps_lock) + return plain_map[keycode]; + else + return shift_map[keycode]; + } + } + } + + /* no chars were returned from any of the USB keyboards */ + + return -1; +} +#endif /* CONFIG_KDB_USB */ + /* * Check if the keyboard controller has a keypress for us. * Some parts (Enter Release, LED change) are still blocking polled here, diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 900ce18..d82dfc8 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "usbhid.h" /* @@ -47,6 +48,7 @@ #define DRIVER_DESC "USB HID core driver" #define DRIVER_LICENSE "GPL" + /* * Module parameters. */ @@ -1037,6 +1039,14 @@ static void usbhid_stop(struct hid_device *hid) if (WARN_ON(!usbhid)) return; +#ifdef CONFIG_KDB_USB + /* + * If the URB was for a Keyboard, detach it from kdb. + * If the URB was for another type of device, just + * allow kdb_usb_keyboard_detach() to silently fail. + */ + kdb_usb_keyboard_detach(usbhid->urbin); +#endif clear_bit(HID_STARTED, &usbhid->iofl); spin_lock_irq(&usbhid->lock); /* Sync with error handler */ @@ -1176,6 +1186,22 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) goto err_free; } +#ifdef CONFIG_KDB_USB + /* Attach USB keyboards to kdb */ + if (intf->cur_altsetting->desc.bInterfaceProtocol == + USB_INTERFACE_PROTOCOL_KEYBOARD) { + int ret; + struct usbhid_device *usbhid = hid->driver_data; + + ret = kdb_usb_keyboard_attach(usbhid->urbin, usbhid->inbuf, + usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf))); + + if (ret == -1) + printk(KERN_ERR ": FAILED to register keyboard (%s) " + "with KDB\n", hid->phys); + } +#endif /* CONFIG_KDB_USB */ + return 0; err_free: kfree(usbhid); diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c index b342926..7ecbf6f 100644 --- a/drivers/hid/usbhid/usbkbd.c +++ b/drivers/hid/usbhid/usbkbd.c @@ -30,6 +30,7 @@ #include #include #include +#include /* * Version Information @@ -292,6 +293,14 @@ static int usb_kbd_probe(struct usb_interface *iface, usb_fill_int_urb(kbd->irq, dev, pipe, kbd->new, (maxp > 8 ? 8 : maxp), usb_kbd_irq, kbd, endpoint->bInterval); + +#ifdef CONFIG_KDB_USB + /* Attach keyboard to kdb */ + kdb_usb_keyboard_attach(kbd->irq, kbd->new, + usb_hcd_get_kdb_poll_func(dev)); + +#endif /* CONFIG_KDB_USB */ + kbd->irq->transfer_dma = kbd->new_dma; kbd->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; @@ -329,6 +338,10 @@ static void usb_kbd_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); if (kbd) { +#ifdef CONFIG_KDB_USB + /* Detach the keyboard from kdb */ + kdb_usb_keyboard_detach(kbd->irq); +#endif /* CONFIG_KDB_USB */ usb_kill_urb(kbd->irq); input_unregister_device(kbd->dev); usb_kbd_free_mem(interface_to_usbdev(intf), kbd); diff --git a/drivers/serial/kgdboc.c b/drivers/serial/kgdboc.c index cac8ae7..593a67a 100644 --- a/drivers/serial/kgdboc.c +++ b/drivers/serial/kgdboc.c @@ -54,7 +54,12 @@ static void cleanup_kgdboc(void) /* Unregister the keyboard poll hook, if registered */ for (i = 0; i < kdb_poll_idx; i++) { +#ifdef CONFIG_KDB_USB + if (kdb_poll_funcs[i] == kdb_get_kbd_char || + kdb_poll_funcs[i] == kdb_get_usb_char) { +#else /* ! CONFIG_KDB_USB */ if (kdb_poll_funcs[i] == kdb_get_kbd_char) { +#endif /* CONFIG_KDB_USB */ kdb_poll_idx--; kdb_poll_funcs[i] = kdb_poll_funcs[kdb_poll_idx]; kdb_poll_funcs[kdb_poll_idx] = NULL; @@ -87,11 +92,18 @@ static int configure_kgdboc(void) if (kdb_poll_idx < KDB_POLL_FUNC_MAX) { kdb_poll_funcs[kdb_poll_idx] = kdb_get_kbd_char; kdb_poll_idx++; +#ifdef CONFIG_KDB_USB + if (kdb_poll_idx < KDB_POLL_FUNC_MAX) { + kdb_poll_funcs[kdb_poll_idx] = kdb_get_usb_char; + kdb_poll_idx++; + } +#endif /* CONFIG_KDB_USB */ if (cptr[3] == ',') cptr += 4; else goto do_register; } + /* XXX must fix error handling XXX */ } #endif /* CONFIG_KDB_KEYBOARD */ diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 42b93da..6f1935e 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2045,6 +2045,20 @@ usb_hcd_platform_shutdown(struct platform_device* dev) } EXPORT_SYMBOL_GPL(usb_hcd_platform_shutdown); +#ifdef CONFIG_KDB_USB +void * +usb_hcd_get_kdb_poll_func(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + if (hcd && hcd->driver) + return (void *)(hcd->driver->kdb_poll_char); + + return NULL; +} +EXPORT_SYMBOL_GPL(usb_hcd_get_kdb_poll_func); +#endif /* CONFIG_KDB_USB */ + /*-------------------------------------------------------------------------*/ #if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE) diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index e7d4479..a99689d 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -224,6 +224,10 @@ struct hc_driver { void (*relinquish_port)(struct usb_hcd *, int); /* has a port been handed over to a companion? */ int (*port_handed_over)(struct usb_hcd *, int); +#ifdef CONFIG_KDB_USB + /* KDB poll function for this HC */ + int (*kdb_poll_char)(struct urb *urb); +#endif /* CONFIG_KDB_USB */ }; extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb); diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index c637207..fd81238 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1031,6 +1031,48 @@ static int ehci_get_frame (struct usb_hcd *hcd) ehci->periodic_size; } +#ifdef CONFIG_KDB_USB + +int +ehci_kdb_poll_char(struct urb *urb) +{ + struct ehci_hcd *ehci; + + /* just to make sure */ + if (!urb || !urb->dev || !urb->dev->bus) + return -1; + + ehci = (struct ehci_hcd *) hcd_to_ehci(bus_to_hcd(urb->dev->bus)); + + /* make sure */ + if (!ehci) + return -1; + + if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) + return -1; + + /* + * If ehci->lock is held coming into this routine, it could + * mean KDB was entered while the HC driver was in the midst + * of processing URBs. Therefore it could be dangerous to + * processes URBs from this poll routine. And, we can't wait on + * the lock since we are in KDB and kernel threads (including the + * one holding the lock) are suspended. + * So, we punt and return an error. Keyboards attached to this + * HC will not be useable from KDB at this time. + */ + if (spin_is_locked(&ehci->lock)) + return -EBUSY; + + /* processes the URB */ + if (qh_completions_kdb(ehci, urb->hcpriv, urb)) + return 0; + + return -1; +} + +#endif /* CONFIG_KDB_USB */ + /*-------------------------------------------------------------------------*/ MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 5aa8bce..65779fb 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -22,6 +22,8 @@ #error "This file is PCI bus glue. CONFIG_PCI must be defined." #endif +#include + /*-------------------------------------------------------------------------*/ /* called after powerup, by probe or system-pm "wakeup" */ @@ -408,6 +410,10 @@ static const struct hc_driver ehci_pci_hc_driver = { .bus_resume = ehci_bus_resume, .relinquish_port = ehci_relinquish_port, .port_handed_over = ehci_port_handed_over, + +#ifdef CONFIG_KDB_USB + .kdb_poll_char = ehci_kdb_poll_char, +#endif }; /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 1976b1b..3c3d920 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -499,6 +499,231 @@ halt: return count; } +#ifdef CONFIG_KDB_USB +/* + * This routine is basically a copy of qh_completions() for use by KDB. + * It is modified to only work on qtds which are associated + * with 'kdburb'. Also, there are some fixups related to locking. + */ +unsigned +qh_completions_kdb(struct ehci_hcd *ehci, struct ehci_qh *qh, + struct urb *kdburb) +{ + struct ehci_qtd *last = NULL, *end = qh->dummy; + struct list_head *entry, *tmp; + int last_status = -EINPROGRESS; + int stopped; + unsigned count = 0; + int do_status = 0; + u8 state; + u32 halt = HALT_BIT(ehci); + + /* verify params are valid */ + if (!qh || !kdburb) + return 0; + + if (unlikely(list_empty(&qh->qtd_list))) + return count; + + /* completions (or tasks on other cpus) must never clobber HALT + * till we've gone through and cleaned everything up, even when + * they add urbs to this qh's queue or mark them for unlinking. + * + * NOTE: unlinking expects to be done in queue order. + */ + state = qh->qh_state; + qh->qh_state = QH_STATE_COMPLETING; + stopped = (state == QH_STATE_IDLE); + + /* remove de-activated QTDs from front of queue. + * after faults (including short reads), cleanup this urb + * then let the queue advance. + * if queue is stopped, handles unlinks. + */ + list_for_each_safe(entry, tmp, &qh->qtd_list) { + struct ehci_qtd *qtd; + struct urb *urb; + u32 token = 0; + int qtd_status; + + qtd = list_entry(entry, struct ehci_qtd, qtd_list); + urb = qtd->urb; + + if (urb != kdburb) + continue; + + /* clean up any state from previous QTD ...*/ + if (last) { + if (likely(last->urb != urb)) { + /* + * Lock hackery here... + * ehci_urb_done() makes the assumption + * that it's called with ehci->lock held. + * So, lock it if it isn't already. + */ + if (!spin_is_locked(&ehci->lock)) + spin_lock(&ehci->lock); + + ehci_urb_done(ehci, last->urb, last_status); + + /* + * ehci_urb_done() releases and reacquires + * ehci->lock, so release it here. + */ + if (spin_is_locked(&ehci->lock)) + spin_unlock(&ehci->lock); + + count++; + } + ehci_qtd_free(ehci, last); + last = NULL; + last_status = -EINPROGRESS; + } + + /* ignore urbs submitted during completions we reported */ + if (qtd == end) + break; + + /* hardware copies qtd out of qh overlay */ + rmb(); + token = hc32_to_cpu(ehci, qtd->hw_token); + + /* always clean up qtds the hc de-activated */ + if ((token & QTD_STS_ACTIVE) == 0) { + + if ((token & QTD_STS_HALT) != 0) { + stopped = 1; + + /* magic dummy for some short reads; + * qh won't advance. that silicon + * quirk can kick in with this dummy + * too. + */ + } else if (IS_SHORT_READ(token) + && !(qtd->hw_alt_next + & EHCI_LIST_END(ehci))) { + stopped = 1; + goto halt; + } + + /* stop scanning when we reach qtds the hc is using */ + } else if (likely(!stopped && + HC_IS_RUNNING(ehci_to_hcd(ehci)->state))) { + break; + + } else { + stopped = 1; + + if (unlikely(!HC_IS_RUNNING(ehci_to_hcd(ehci)->state))) + last_status = -ESHUTDOWN; + + /* ignore active urbs unless some previous qtd + * for the urb faulted (including short read) or + * its urb was canceled. we may patch qh or qtds. + */ + if (likely(last_status == -EINPROGRESS && + !urb->unlinked)) + continue; + + /* issue status after short control reads */ + if (unlikely(do_status != 0) + && QTD_PID(token) == 0 /* OUT */) { + do_status = 0; + continue; + } + + /* token in overlay may be most current */ + if (state == QH_STATE_IDLE + && cpu_to_hc32(ehci, qtd->qtd_dma) + == qh->hw_current) + token = hc32_to_cpu(ehci, qh->hw_token); + + /* force halt for unlinked or blocked qh, so we'll + * patch the qh later and so that completions can't + * activate it while we "know" it's stopped. + */ + if ((halt & qh->hw_token) == 0) { +halt: + qh->hw_token |= halt; + wmb(); + } + } + + /* remove it from the queue */ + qtd_status = qtd_copy_status(ehci, urb, qtd->length, token); + if (unlikely(qtd_status == -EREMOTEIO)) { + do_status = (!urb->unlinked && + usb_pipecontrol(urb->pipe)); + qtd_status = 0; + } + if (likely(last_status == -EINPROGRESS)) + last_status = qtd_status; + + if (stopped && qtd->qtd_list.prev != &qh->qtd_list) { + last = list_entry(qtd->qtd_list.prev, + struct ehci_qtd, qtd_list); + last->hw_next = qtd->hw_next; + } + list_del(&qtd->qtd_list); + last = qtd; + } + + /* last urb's completion might still need calling */ + if (likely(last != NULL)) { + /* + * Lock hackery here... + * ehci_urb_done() makes the assumption + * that it's called with ehci->lock held. + * So, lock it if it isn't already. + */ + if (!spin_is_locked(&ehci->lock)) + spin_lock(&ehci->lock); + + ehci_urb_done(ehci, last->urb, last_status); + + /* + * ehci_urb_done() releases and reacquires + * ehci->lock, so release it here. + */ + if (spin_is_locked(&ehci->lock)) + spin_unlock(&ehci->lock); + + count++; + ehci_qtd_free(ehci, last); + } + + /* restore original state; caller must unlink or relink */ + qh->qh_state = state; + + /* be sure the hardware's done with the qh before refreshing + * it after fault cleanup, or recovering from silicon wrongly + * overlaying the dummy qtd (which reduces DMA chatter). + */ + if (stopped != 0 || qh->hw_qtd_next == EHCI_LIST_END(ehci)) { + switch (state) { + case QH_STATE_IDLE: + qh_refresh(ehci, qh); + break; + case QH_STATE_LINKED: + /* should be rare for periodic transfers, + * except maybe high bandwidth ... + */ + if ((cpu_to_hc32(ehci, QH_SMASK) + & qh->hw_info2) != 0) { + intr_deschedule(ehci, qh); + (void) qh_schedule(ehci, qh); + } else + unlink_async(ehci, qh); + break; + /* otherwise, unlink already started */ + } + } + + return count; +} + +#endif /* CONFIG_KDB_USB */ + /*-------------------------------------------------------------------------*/ // high bandwidth multiplier, as encoded in highspeed endpoint descriptors diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 25db704..3732a31 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -983,6 +983,72 @@ static int ohci_restart (struct ohci_hcd *ohci) /*-------------------------------------------------------------------------*/ +#ifdef CONFIG_KDB_USB + +int ohci_kdb_poll_char(struct urb *urb) +{ + struct ohci_hcd *ohci; + struct ohci_regs *regs; + + /* just to make sure */ + if (!urb || !urb->dev || !urb->dev->bus) + return -1; + + ohci = (struct ohci_hcd *) hcd_to_ohci(bus_to_hcd(urb->dev->bus)); + + /* make sure */ + if (!ohci || !ohci->hcca) + return -1; + + if (!HC_IS_RUNNING(ohci_to_hcd(ohci)->state)) + return -1; + + /* + * If ohci->lock is held coming into this routine, it could + * mean KDB was entered while the HC driver was in the midst + * of processing URBs. Therefore it could be dangerous to + * processes URBs from this poll routine. And, we can't wait on + * the lock since we are in KDB and kernel threads (including the + * one holding the lock) are suspended. + * So, we punt and return an error. Keyboards attached to this + * HC will not be useable from KDB at this time. + */ + if (spin_is_locked(&ohci->lock)) + return -EBUSY; + + regs = ohci->regs; + + /* if the urb is not currently in progress resubmit it */ + if (urb->status != -EINPROGRESS) { + + if (usb_submit_urb(urb, GFP_ATOMIC)) + return -1; + + /* make sure the HC registers are set correctly */ + ohci_writel(ohci, OHCI_INTR_WDH, ®s->intrenable); + ohci_writel(ohci, OHCI_INTR_WDH, ®s->intrstatus); + ohci_writel(ohci, OHCI_INTR_MIE, ®s->intrenable); + + /* flush those pci writes */ + (void) ohci_readl(ohci, &ohci->regs->control); + } + + if (ohci->hcca->done_head) { + dl_done_list_kdb(ohci, urb); + ohci_writel(ohci, OHCI_INTR_WDH, ®s->intrstatus); + /* flush the pci write */ + (void) ohci_readl(ohci, &ohci->regs->control); + + return 0; + } + + return -1; +} + +#endif /* CONFIG_KDB_USB */ + +/*-------------------------------------------------------------------------*/ + MODULE_AUTHOR (DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE ("GPL"); diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index f9961b4..8de9079 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -20,7 +20,7 @@ #include #include - +#include /* constants used to work around PM-related transfer * glitches in some AMD 700 series southbridges @@ -367,6 +367,7 @@ static int __devinit ohci_pci_start (struct usb_hcd *hcd) ohci_err (ohci, "can't start\n"); ohci_stop (hcd); } + return ret; } @@ -464,6 +465,9 @@ static const struct hc_driver ohci_pci_hc_driver = { .bus_resume = ohci_bus_resume, #endif .start_port_reset = ohci_start_port_reset, +#ifdef CONFIG_KDB_USB + .kdb_poll_char = ohci_kdb_poll_char, +#endif }; /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index c2d80f8..06688e3 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -1127,3 +1127,66 @@ dl_done_list (struct ohci_hcd *ohci) td = td_next; } } + + +/*-------------------------------------------------------------------------*/ + +#ifdef CONFIG_KDB_USB +static void +dl_done_list_kdb(struct ohci_hcd *ohci, struct urb *kdburb) +{ + struct td *td = dl_reverse_done_list(ohci); + + while (td) { + struct td *td_next = td->next_dl_td; + struct urb *urb = td->urb; + urb_priv_t *urb_priv = urb->hcpriv; + struct ed *ed = td->ed; + + if (urb != kdburb) { + td = td_next; + continue; + } + + /* update URB's length and status from TD */ + td_done(ohci, urb, td); + urb_priv->td_cnt++; + + /* If all this urb's TDs are done, just resubmit it */ + if (urb_priv->td_cnt == urb_priv->length) { + urb->actual_length = 0; + urb->status = -EINPROGRESS; + td_submit_urb(ohci, urb); + } + + /* clean schedule: unlink EDs that are no longer busy */ + if (list_empty(&ed->td_list)) { + if (ed->state == ED_OPER) + start_ed_unlink(ohci, ed); + + /* ... reenabling halted EDs only after fault cleanup */ + } else if ((ed->hwINFO & cpu_to_hc32(ohci, + ED_SKIP | ED_DEQUEUE)) + == cpu_to_hc32(ohci, ED_SKIP)) { + td = list_entry(ed->td_list.next, struct td, td_list); + if (!(td->hwINFO & cpu_to_hc32(ohci, TD_DONE))) { + ed->hwINFO &= ~cpu_to_hc32(ohci, ED_SKIP); + /* ... hc may need waking-up */ + switch (ed->type) { + case PIPE_CONTROL: + ohci_writel(ohci, OHCI_CLF, + &ohci->regs->cmdstatus); + break; + case PIPE_BULK: + ohci_writel(ohci, OHCI_BLF, + &ohci->regs->cmdstatus); + break; + } + } + } + + td = td_next; + } +} + +#endif /* CONFIG_KDB_USB */ diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index cf5e4cf..8397f07 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -891,6 +892,38 @@ static int uhci_hcd_get_frame_number(struct usb_hcd *hcd) return frame_number + delta; } +#ifdef CONFIG_KDB_USB +int uhci_kdb_poll_char(struct urb *urb) +{ + struct uhci_hcd *uhci; + struct urb_priv *urbp; + struct uhci_qh *qh; + + /* just to make sure */ + if (!urb || !urb->dev || !urb->dev->bus || !urb->hcpriv) + return -1; + + urbp = urb->hcpriv; + qh = urbp->qh; + + uhci = (struct uhci_hcd *) hcd_to_uhci(bus_to_hcd(urb->dev->bus)); + + /* make sure */ + if (!uhci) + return -1; + + if (!HC_IS_RUNNING(uhci_to_hcd(uhci)->state)) + return -1; + + if (spin_is_locked(&uhci->lock)) + return -EBUSY; + + if (uhci_scan_qh_kdb(uhci, qh, urb)) + return 0; + return -1; +} +#endif /* CONFIG_KDB_USB */ + static const char hcd_name[] = "uhci_hcd"; static const struct hc_driver uhci_driver = { @@ -921,6 +954,9 @@ static const struct hc_driver uhci_driver = { .hub_status_data = uhci_hub_status_data, .hub_control = uhci_hub_control, +#ifdef CONFIG_KDB_USB + .kdb_poll_char = uhci_kdb_poll_char, +#endif }; static const struct pci_device_id uhci_pci_ids[] = { { diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 3e5807d..f0e6a4c 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -1760,3 +1760,54 @@ rescan: else uhci_set_next_interrupt(uhci); } + +#ifdef CONFIG_KDB_USB + +int uhci_scan_qh_kdb(struct uhci_hcd *uhci, struct uhci_qh *qh, + struct urb *kdburb) +{ + struct urb_priv *urbp; + struct urb *urb; + int status; + + if (!qh || !kdburb) + return 0; + + while (!list_empty(&qh->queue)) { + urbp = list_entry(qh->queue.next, struct urb_priv, node); + urb = urbp->urb; + + if (urb != kdburb) + continue; + + if (qh->type == USB_ENDPOINT_XFER_ISOC) + status = uhci_result_isochronous(uhci, urb); + else + status = uhci_result_common(uhci, urb); + if (status == -EINPROGRESS) + break; + + /* Dequeued but completed URBs can't be given back unless + * the QH is stopped or has finished unlinking. */ + if (urb->unlinked) { + if (QH_FINISHED_UNLINKING(qh)) + qh->is_stopped = 1; + else if (!qh->is_stopped) + return 0; + } + urb->actual_length = 0; + urb->status = -EINPROGRESS; + /* Local lock hackery */ + spin_lock(&uhci->lock); + uhci_giveback_urb(uhci, qh, urb, status); + spin_unlock(&uhci->lock); + if (status < 0) + break; + } + + /* XXX probably need further clean up to get the urbs out of the + * queuu XXX */ + return 1; +} + +#endif /* CONFIG_KDB_USB */ diff --git a/include/linux/kdb.h b/include/linux/kdb.h index 200af81..9d89054 100644 --- a/include/linux/kdb.h +++ b/include/linux/kdb.h @@ -137,6 +137,7 @@ extern int kdb_no_usb; extern int kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func); extern int kdb_usb_keyboard_detach(struct urb *urb); +extern void *usb_hcd_get_kdb_poll_func(struct usb_device *udev); #endif /* CONFIG_KDB_USB */ diff --git a/include/linux/kdbprivate.h b/include/linux/kdbprivate.h index 8579e97..03f0004 100644 --- a/include/linux/kdbprivate.h +++ b/include/linux/kdbprivate.h @@ -333,6 +333,7 @@ typedef int (*get_char_func)(void); extern get_char_func kdb_poll_funcs[]; extern int kdb_poll_idx; extern int kdb_get_kbd_char(void); +extern int kdb_get_usb_char(void); #ifndef CONFIG_IA64 /* diff --git a/lib/Kconfig.kgdb b/lib/Kconfig.kgdb index b5d3637..1c94a2b 100644 --- a/lib/Kconfig.kgdb +++ b/lib/Kconfig.kgdb @@ -87,4 +87,11 @@ config KDB_KEYBOARD help KDB can use a PS/2 type keyboard for an input device +config KDB_USB + bool "KGDB_KDB: Allow usb input device devices" + depends on VT && KGDB_KDB && KDB_KEYBOARD + default y + help + KDB can use a USB keyboard for an input device + endif # KGDB -- 1.6.3.rc0.1.gf800 From jason.wessel@windriver.com Fri May 8 16:23:30 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-1.6 required=5.0 tests=AWL,BAYES_00,FRT_LEVITRA, J_CHICKENPOX_63 autolearn=no version=3.3.0-rupdated Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n48LNTs4031438 for ; Fri, 8 May 2009 16:23:29 -0500 X-ASG-Debug-ID: 1241817812-367f00ac0000-sLlkUa X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi Received: from mail.wrs.com (localhost [127.0.0.1]) by cuda.sgi.com (Spam Firewall) with ESMTP id C562E1D1EA32 for ; Fri, 8 May 2009 14:23:32 -0700 (PDT) Received: from mail.wrs.com (mail.windriver.com [147.11.1.11]) by cuda.sgi.com with ESMTP id QXKipU6BYVp1uIfJ for ; Fri, 08 May 2009 14:23:32 -0700 (PDT) Received: from ALA-MAIL03.corp.ad.wrs.com (ala-mail03 [147.11.57.144]) by mail.wrs.com (8.13.6/8.13.6) with ESMTP id n48LNOjd005483; Fri, 8 May 2009 14:23:24 -0700 (PDT) Received: from ala-mail06.corp.ad.wrs.com ([147.11.57.147]) by ALA-MAIL03.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:23 -0700 Received: from localhost.localdomain ([172.25.32.41]) by ala-mail06.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:23 -0700 From: Jason Wessel To: linux-kernel@vger.kernel.org Cc: kgdb-bugreport@lists.sourceforge.net, kdb@oss.sgi.com X-ASG-Orig-Subj: [PATCH 0/13] RFC ONLY - kdb for kgdb Subject: [PATCH 0/13] RFC ONLY - kdb for kgdb Date: Fri, 8 May 2009 16:23:07 -0500 Message-Id: <1241817800-9320-1-git-send-email-jason.wessel@windriver.com> X-Mailer: git-send-email 1.6.3.rc0.1.gf800 X-OriginalArrivalTime: 08 May 2009 21:23:23.0684 (UTC) FILETIME=[37E33640:01C9D023] X-Barracuda-Connect: mail.windriver.com[147.11.1.11] X-Barracuda-Start-Time: 1241817813 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0217 1.0000 -1.8800 X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com X-Barracuda-Spam-Score: -1.14 X-Barracuda-Spam-Status: No, SCORE=-1.14 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests=FRT_LEVITRA X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.1.25266 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.74 FRT_LEVITRA BODY: ReplaceTags: Levitra X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean This patch series is a request for comments on several levels. 1) Do people find kdb useful? (See * and **) 2) Would kdb folks be willing to use it if it was a front end to kgdb? 3) Does kdb have a future in the mainline kernel? 4) Is this a reasonable approach to have some level of unification to end up with a more robust kernel debugger? * This is not meant to be a religious war ** This will never replace printk :-) What follows is a series of patches to the development kernel which enable kdb as a front end to kgdb for arm, mips, powerpc, and x86. This is a very raw prototype, but enough of it it works such that folks can try it out. To get the most basic functionality, you only need the first 2 patches in the series. The remainder of the patches go on to incrementally add back some of the functionality that was removed from kdb. I made an attempt to try to make the first part just the generic set of changes required to get kdb working on 1 or more archs. The kdb front end works a little differently than if you were to take the original kdb patch set from: ftp://oss.sgi.com/projects/kdb/download/v4.4/ In the kernel .config you should enable the following options: CONFIG_KGDB=y CONFIG_KGDB_SERIAL_CONSOLE=y CONFIG_KGDB_LOW_LEVEL_TRAP=y CONFIG_KGDB_KDB=y CONFIG_KGDB_KDB_PRIMARY=y CONFIG_KDB_KEYBOARD=y CONFIG_KDB_USB=y If you were using the serial port with kdb before, now you just use the kgdboc mechanism with no differences at all. IE use you kernel command line with: console=ttyS0,115200 kgdboc=ttyS0 kgdbwait That will get you access to kdb just after the console has been registered. If you want to use the keyboard, you could use: console=tty0 kgdboc=kdb kgdbwait You can also use the keyboard and or serial console: console=ttyS0,115200 console=tty0 kgdboc=kdb,ttyS0 In terms of breaking into the debugger after the system is up, you must use the sysrq-g sequence. That means you could run: echo g > /proc/sysrq-trigger Or you can use the SysRq key on your key board. On a typical laptop you might have to do the following: press and hold ALT -- You will be holding this the whole time press and hold FN press and release the key with the SysRq label release FN press and release g release ALT I have also found on some PS/2 keyboards you have press alt again after resuming the system because the key up event got lost somewhere. Once you are in kdb you can run help to see a limited list of commands. You can also still connect gdb or re-enter kdb without leaving the exception state. To get out of kgdb mode you can type "$3#33", or to get into kgdb mode from kdb, you can type "kgdb". Also from gdb you can issue commands to the kdb front end, via gdb's montior command. For instance you could issue "monitor lsmod". Allowing the gdb monitor extension was certainly another motivation behind the prototype. >From here it is a matter of deciding if it is worth continuing down this route. The evaulation of this project will definitely cause some further cleanup and improvement to kgdb, regardless of if this effort is carried forward. Two of the patches in this series are patches likely to get integrated into kgdb's code base and do not bear the "RFC ONLY" indication. Thanks, Jason. You can find the development branch for this here: http://git.kernel.org/?p=linux/kernel/git/jwessel/linux-2.6-kgdb.git;a=shortlog;h=kdb_prototype or grab a static version of the patches here: http://kernel.org/pub/linux/kernel/people/jwessel/branches/kdb_prototype.tar.bz2 short log info follows: Jason Wessel (13): RFC ONLY - kdb: core for kgdb backend RFC ONLY - kgdb: core changes to support kdb RFC ONLY - kgdb,8250,pl011: Return immediately from console poll RFC ONLY - kgdb: gdb "monitor" -> kdb passthrough RFC ONLY - kgdboc,keyboard: Keyboard driver for kdb with kgdb kgdb: remove post_primary_code references RFC ONLY - x86,kgdb: Add low level debug hook RFC ONLY - arm,kgdb: Add hook to catch an oops with debugger RFC ONLY - powerpc,kgdb: Introduce low level trap catching RFC ONLY - mips,kgdb: kdb low level trap catch and stack trace kgdb: Add the ability to schedule a breakpoint via a tasklet RFC ONLY - kgdb,kdb: use async breakpoint for sysrq for usb RFC ONLY - usb,keyboard: uchi, echi, and ochi polling keyboard urbs Makefile | 1 + arch/arm/include/asm/kgdb.h | 2 + arch/arm/include/asm/kmap_types.h | 1 + arch/arm/kernel/kgdb.c | 13 + arch/arm/kernel/traps.c | 5 + arch/mips/include/asm/kgdb.h | 2 + arch/mips/include/asm/kmap_types.h | 3 +- arch/mips/kernel/kgdb.c | 27 +- arch/mips/kernel/traps.c | 14 + arch/powerpc/include/asm/kmap_types.h | 1 + arch/powerpc/kernel/kgdb.c | 12 +- arch/powerpc/kernel/traps.c | 7 + arch/x86/include/asm/kgdb.h | 3 + arch/x86/include/asm/kmap_types.h | 3 +- arch/x86/kernel/kgdb.c | 56 +- arch/x86/kernel/traps.c | 6 + drivers/char/Makefile | 1 + drivers/char/kdb_keyboard.c | 407 ++++ drivers/char/kdb_keyboard.h | 143 ++ drivers/hid/usbhid/hid-core.c | 26 + drivers/hid/usbhid/usbkbd.c | 13 + drivers/serial/8250.c | 4 +- drivers/serial/amba-pl011.c | 6 +- drivers/serial/kgdboc.c | 80 +- drivers/usb/core/hcd.c | 14 + drivers/usb/core/hcd.h | 4 + drivers/usb/host/ehci-hcd.c | 42 + drivers/usb/host/ehci-pci.c | 6 + drivers/usb/host/ehci-q.c | 225 ++ drivers/usb/host/ohci-hcd.c | 66 + drivers/usb/host/ohci-pci.c | 6 +- drivers/usb/host/ohci-q.c | 63 + drivers/usb/host/uhci-hcd.c | 36 + drivers/usb/host/uhci-q.c | 51 + fs/proc/meminfo.c | 145 ++ fs/proc/mmu.c | 16 +- include/linux/kdb.h | 172 ++ include/linux/kdbprivate.h | 611 ++++++ include/linux/keyboard.h | 2 + include/linux/kgdb.h | 25 +- include/linux/serial_core.h | 1 + init/main.c | 26 + kdb/.gitignore | 1 + kdb/Makefile | 48 + kdb/kdb_bp.c | 863 ++++++++ kdb/kdb_bt.c | 209 ++ kdb/kdb_cmds | 32 + kdb/kdb_io.c | 895 ++++++++ kdb/kdbmain.c | 3669 +++++++++++++++++++++++++++++++++ kdb/kdbsupport.c | 1120 ++++++++++ kernel/kallsyms.c | 22 + kernel/kgdb.c | 321 +++- kernel/module.c | 19 +- kernel/panic.c | 6 + kernel/printk.c | 14 + kernel/sched.c | 93 +- kernel/signal.c | 49 + lib/Kconfig.kgdb | 37 + mm/hugetlb.c | 22 + mm/swapfile.c | 22 + 60 files changed, 9697 insertions(+), 92 deletions(-) create mode 100644 drivers/char/kdb_keyboard.c create mode 100644 drivers/char/kdb_keyboard.h create mode 100644 include/linux/kdb.h create mode 100644 include/linux/kdbprivate.h create mode 100644 kdb/.gitignore create mode 100644 kdb/Makefile create mode 100644 kdb/kdb_bp.c create mode 100644 kdb/kdb_bt.c create mode 100644 kdb/kdb_cmds create mode 100644 kdb/kdb_io.c create mode 100644 kdb/kdbmain.c create mode 100644 kdb/kdbsupport.c From jason.wessel@windriver.com Fri May 8 16:23:31 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-2.4 required=5.0 tests=AWL,BAYES_00,J_CHICKENPOX_21, J_CHICKENPOX_43,J_CHICKENPOX_63 autolearn=no version=3.3.0-rupdated Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n48LNV9U031455 for ; Fri, 8 May 2009 16:23:31 -0500 X-ASG-Debug-ID: 1241817814-3e19004b0000-sLlkUa X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi Received: from mail.wrs.com (localhost [127.0.0.1]) by cuda.sgi.com (Spam Firewall) with ESMTP id BB2401D1EBFC for ; Fri, 8 May 2009 14:23:34 -0700 (PDT) Received: from mail.wrs.com (mail.windriver.com [147.11.1.11]) by cuda.sgi.com with ESMTP id sXdMxyItL9qv97HT for ; Fri, 08 May 2009 14:23:34 -0700 (PDT) Received: from ALA-MAIL03.corp.ad.wrs.com (ala-mail03 [147.11.57.144]) by mail.wrs.com (8.13.6/8.13.6) with ESMTP id n48LNSO1005508; Fri, 8 May 2009 14:23:28 -0700 (PDT) Received: from ala-mail06.corp.ad.wrs.com ([147.11.57.147]) by ALA-MAIL03.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:28 -0700 Received: from localhost.localdomain ([172.25.32.41]) by ala-mail06.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:27 -0700 From: Jason Wessel To: linux-kernel@vger.kernel.org Cc: kgdb-bugreport@lists.sourceforge.net, kdb@oss.sgi.com, Jason Wessel X-ASG-Orig-Subj: [PATCH 05/13] RFC ONLY - kgdboc,keyboard: Keyboard driver for kdb with kgdb Subject: [PATCH 05/13] RFC ONLY - kgdboc,keyboard: Keyboard driver for kdb with kgdb Date: Fri, 8 May 2009 16:23:12 -0500 Message-Id: <1241817800-9320-6-git-send-email-jason.wessel@windriver.com> X-Mailer: git-send-email 1.6.3.rc0.1.gf800 In-Reply-To: <1241817800-9320-5-git-send-email-jason.wessel@windriver.com> References: <1241817800-9320-1-git-send-email-jason.wessel@windriver.com> <1241817800-9320-2-git-send-email-jason.wessel@windriver.com> <1241817800-9320-3-git-send-email-jason.wessel@windriver.com> <1241817800-9320-4-git-send-email-jason.wessel@windriver.com> <1241817800-9320-5-git-send-email-jason.wessel@windriver.com> X-OriginalArrivalTime: 08 May 2009 21:23:28.0044 (UTC) FILETIME=[3A7C7EC0:01C9D023] X-Barracuda-Connect: mail.windriver.com[147.11.1.11] X-Barracuda-Start-Time: 1241817814 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com X-Barracuda-Spam-Score: -1.52 X-Barracuda-Spam-Status: No, SCORE=-1.52 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests=BSF_RULE7568M X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.1.25266 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.50 BSF_RULE7568M Custom Rule 7568M X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean This is a RFC patch. The work to possibly merge kdb and kgdb is being evaluated and this patch is considered only a proof of concept or prototype. This patch adds in the kdb PS/2 keyboard driver. This was mostly a direct port from the original kdb where I cleaned up the code against checkpatch.pl and added the glue to stitch it into kgdb. This patch also enables early kdb debug via kgdbwait and the keyboard. All the access to configure kdb using either a serial console or the keyboard is done via kgdboc. If you want to use only the keyboard and want to break in early you would add to your kernel command arguments: kgdboc=kbd kgdbwait If you wanted serial and or the keyboard access you could use: kgdboc=kbd,ttyS0 You can also configure kgdboc as a kernel module or at runtime with the sysfs where you can activate and deactivate kgdb. Turn it on: echo kbd,ttyS0 > /sys/module/kgdboc/parameters/kgdboc Turn it off: echo "" > /sys/module/kgdboc/parameters/kgdboc Signed-off-by: Jason Wessel --- drivers/char/Makefile | 1 + drivers/char/kdb_keyboard.c | 208 +++++++++++++++++++++++++++++++++++++++++++ drivers/char/kdb_keyboard.h | 143 +++++++++++++++++++++++++++++ drivers/serial/kgdboc.c | 68 +++++++++++++-- include/linux/keyboard.h | 2 + kdb/kdbmain.c | 3 + lib/Kconfig.kgdb | 7 ++ 7 files changed, 425 insertions(+), 7 deletions(-) create mode 100644 drivers/char/kdb_keyboard.c create mode 100644 drivers/char/kdb_keyboard.h diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 9caf5b5..5ae13d2 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_LEGACY_PTYS) += pty.o obj-$(CONFIG_UNIX98_PTYS) += pty.o obj-y += misc.o obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o selection.o keyboard.o +obj-$(CONFIG_KDB_KEYBOARD) += kdb_keyboard.o obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o obj-$(CONFIG_AUDIT) += tty_audit.o diff --git a/drivers/char/kdb_keyboard.c b/drivers/char/kdb_keyboard.c new file mode 100644 index 0000000..6dcbb07 --- /dev/null +++ b/drivers/char/kdb_keyboard.c @@ -0,0 +1,208 @@ +/* + * Kernel Debugger Architecture Dependent Console I/O handler + * + * This file is subject to the terms and conditions of the GNU General Public + * License. + * + * Copyright (c) 1999-2006 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2009 Wind River Systems, Inc. All Rights Reserved. + */ + + +#ifdef CONFIG_VT_CONSOLE +#include +#include +#include +#include +#include +#include "kdb_keyboard.h" + + +static int kbd_exists; + +/* + * Check if the keyboard controller has a keypress for us. + * Some parts (Enter Release, LED change) are still blocking polled here, + * but hopefully they are all short. + */ +int kdb_get_kbd_char(void) +{ + int scancode, scanstatus; + static int shift_lock; /* CAPS LOCK state (0-off, 1-on) */ + static int shift_key; /* Shift next keypress */ + static int ctrl_key; + u_short keychar; + + if (KDB_FLAG(NO_I8042) || KDB_FLAG(NO_VT_CONSOLE) || + (inb(KBD_STATUS_REG) == 0xff && inb(KBD_DATA_REG) == 0xff)) { + kbd_exists = 0; + return -1; + } + kbd_exists = 1; + + if ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0) + return -1; + + /* + * Fetch the scancode + */ + scancode = inb(KBD_DATA_REG); + scanstatus = inb(KBD_STATUS_REG); + + /* + * Ignore mouse events. + */ + if (scanstatus & KBD_STAT_MOUSE_OBF) + return -1; + + /* + * Ignore release, trigger on make + * (except for shift keys, where we want to + * keep the shift state so long as the key is + * held down). + */ + + if (((scancode&0x7f) == 0x2a) || ((scancode&0x7f) == 0x36)) { + /* + * Next key may use shift table + */ + if ((scancode & 0x80) == 0) + shift_key = 1; + else + shift_key = 0; + return -1; + } + + if ((scancode&0x7f) == 0x1d) { + /* + * Left ctrl key + */ + if ((scancode & 0x80) == 0) + ctrl_key = 1; + else + ctrl_key = 0; + return -1; + } + + if ((scancode & 0x80) != 0) + return -1; + + scancode &= 0x7f; + + /* + * Translate scancode + */ + + if (scancode == 0x3a) { + /* + * Toggle caps lock + */ + shift_lock ^= 1; + +#ifdef KDB_BLINK_LED + kdb_toggleled(0x4); +#endif + return -1; + } + + if (scancode == 0x0e) { + /* + * Backspace + */ + return 8; + } + + /* Special Key */ + switch (scancode) { + case 0xF: /* Tab */ + return 9; + case 0x53: /* Del */ + return 4; + case 0x47: /* Home */ + return 1; + case 0x4F: /* End */ + return 5; + case 0x4B: /* Left */ + return 2; + case 0x48: /* Up */ + return 16; + case 0x50: /* Down */ + return 14; + case 0x4D: /* Right */ + return 6; + } + + if (scancode == 0xe0) + return -1; + + /* + * For Japanese 86/106 keyboards + * See comment in drivers/char/pc_keyb.c. + * - Masahiro Adegawa + */ + if (scancode == 0x73) + scancode = 0x59; + else if (scancode == 0x7d) + scancode = 0x7c; + + if (!shift_lock && !shift_key && !ctrl_key) { + keychar = plain_map[scancode]; + } else if (shift_lock || shift_key) { + keychar = shift_map[scancode]; + } else if (ctrl_key) { + keychar = ctrl_map[scancode]; + } else { + keychar = 0x0020; + kdb_printf("Unknown state/scancode (%d)\n", scancode); + } + keychar &= 0x0fff; + if (keychar == '\t') + keychar = ' '; + switch (KTYP(keychar)) { + case KT_LETTER: + case KT_LATIN: + if (isprint(keychar)) + break; /* printable characters */ + /* drop through */ + case KT_SPEC: + if (keychar == K_ENTER) + break; + /* drop through */ + default: + return -1; /* ignore unprintables */ + } + + if ((scancode & 0x7f) == 0x1c) { + /* + * enter key. All done. Absorb the release scancode. + */ + while ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0) + ; + + /* + * Fetch the scancode + */ + scancode = inb(KBD_DATA_REG); + scanstatus = inb(KBD_STATUS_REG); + + while (scanstatus & KBD_STAT_MOUSE_OBF) { + scancode = inb(KBD_DATA_REG); + scanstatus = inb(KBD_STATUS_REG); + } + + if (scancode != 0x9c) { + /* + * Wasn't an enter-release, why not? + */ + kdb_printf("kdb: expected enter got 0x%x status 0x%x\n", + scancode, scanstatus); + } + + kdb_printf("\n"); + return 13; + } + + return keychar & 0xff; +} +EXPORT_SYMBOL_GPL(kdb_get_kbd_char); +#endif /* CONFIG_VT_CONSOLE */ diff --git a/drivers/char/kdb_keyboard.h b/drivers/char/kdb_keyboard.h new file mode 100644 index 0000000..5541668 --- /dev/null +++ b/drivers/char/kdb_keyboard.h @@ -0,0 +1,143 @@ +/* + * include/linux/pc_keyb.h + * + * PC Keyboard And Keyboard Controller + * + * (c) 1997 Martin Mares + */ + +/* + * Configuration Switches + */ + +#undef KBD_REPORT_ERR /* Report keyboard errors */ +#define KBD_REPORT_UNKN /* Report unknown scan codes */ +#define KBD_REPORT_TIMEOUTS /* Report keyboard timeouts */ +#undef KBD_IS_FOCUS_9000 /* We have the brain-damaged + * FOCUS-9000 keyboard */ +#undef INITIALIZE_MOUSE /* Define if your PS/2 mouse + * needs initialization. */ + +#define KBD_INIT_TIMEOUT 1000 /* Timeout in ms for initializing the + * keyboard */ +#define KBC_TIMEOUT 250 /* Timeout in ms for sending + * to keyboard controller */ +#define KBD_TIMEOUT 1000 /* Timeout in ms for keyboard + * command acknowledge */ + +/* + * Internal variables of the driver + */ + +extern unsigned char pckbd_read_mask; +extern unsigned char aux_device_present; + +/* + * Keyboard Controller Registers on normal PCs. + */ + +#define KBD_STATUS_REG 0x64 /* Status register (R) */ +#define KBD_CNTL_REG 0x64 /* Controller command register (W) */ +#define KBD_DATA_REG 0x60 /* Keyboard data register (R/W) */ + +/* + * Keyboard Controller Commands + */ + +#define KBD_CCMD_READ_MODE 0x20 /* Read mode bits */ +#define KBD_CCMD_WRITE_MODE 0x60 /* Write mode bits */ +#define KBD_CCMD_GET_VERSION 0xA1 /* Get controller version */ +#define KBD_CCMD_MOUSE_DISABLE 0xA7 /* Disable mouse interface */ +#define KBD_CCMD_MOUSE_ENABLE 0xA8 /* Enable mouse interface */ +#define KBD_CCMD_TEST_MOUSE 0xA9 /* Mouse interface test */ +#define KBD_CCMD_SELF_TEST 0xAA /* Controller self test */ +#define KBD_CCMD_KBD_TEST 0xAB /* Keyboard interface test */ +#define KBD_CCMD_KBD_DISABLE 0xAD /* Keyboard interface disable */ +#define KBD_CCMD_KBD_ENABLE 0xAE /* Keyboard interface enable */ +#define KBD_CCMD_WRITE_AUX_OBUF 0xD3 /* Write to output buffer as if + initiated by the auxiliary device */ +#define KBD_CCMD_WRITE_MOUSE 0xD4 /* Write the following byte to + * the mouse */ + +/* + * Keyboard Commands + */ + +#define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */ +#define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */ +#define KBD_CMD_ENABLE 0xF4 /* Enable scanning */ +#define KBD_CMD_DISABLE 0xF5 /* Disable scanning */ +#define KBD_CMD_RESET 0xFF /* Reset */ + +/* + * Keyboard Replies + */ + +#define KBD_REPLY_POR 0xAA /* Power on reset */ +#define KBD_REPLY_ACK 0xFA /* Command ACK */ +#define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */ + +/* + * Status Register Bits + */ + +#define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */ +#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */ +#define KBD_STAT_SELFTEST 0x04 /* Self test successful */ +#define KBD_STAT_CMD 0x08 /* Last write was a command + * write (0=data) */ +#define KBD_STAT_UNLOCKED 0x10 /* Zero if keyboard locked */ +#define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */ +#define KBD_STAT_GTO 0x40 /* General receive/xmit timeout */ +#define KBD_STAT_PERR 0x80 /* Parity error */ + +#define AUX_STAT_OBF (KBD_STAT_OBF | KBD_STAT_MOUSE_OBF) + +/* + * Controller Mode Register Bits + */ + +#define KBD_MODE_KBD_INT 0x01 /* Keyboard data generate IRQ1 */ +#define KBD_MODE_MOUSE_INT 0x02 /* Mouse data generate IRQ12 */ +#define KBD_MODE_SYS 0x04 /* The system flag (?) */ +#define KBD_MODE_NO_KEYLOCK 0x08 /* The keylock doesn't affect + * the keyboard if set */ +#define KBD_MODE_DISABLE_KBD 0x10 /* Disable keyboard interface */ +#define KBD_MODE_DISABLE_MOUSE 0x20 /* Disable mouse interface */ +#define KBD_MODE_KCC 0x40 /* Scan code conversion to PC format */ +#define KBD_MODE_RFU 0x80 + +/* + * Mouse Commands + */ + +#define AUX_SET_RES 0xE8 /* Set resolution */ +#define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */ +#define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */ +#define AUX_GET_SCALE 0xE9 /* Get scaling factor */ +#define AUX_SET_STREAM 0xEA /* Set stream mode */ +#define AUX_SET_SAMPLE 0xF3 /* Set sample rate */ +#define AUX_ENABLE_DEV 0xF4 /* Enable aux device */ +#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */ +#define AUX_RESET 0xFF /* Reset aux device */ +#define AUX_ACK 0xFA /* Command byte ACK. */ + +#define AUX_BUF_SIZE 2048 /* This might be better divisible by + three to make overruns stay in sync + but then the read function would need + a lock etc - ick */ + +struct aux_queue { + unsigned long head; + unsigned long tail; + wait_queue_head_t proc_list; + struct fasync_struct *fasync; + unsigned char buf[AUX_BUF_SIZE]; +}; + + +/* How to access the keyboard macros on this platform. */ +#define kbd_read_input() inb(KBD_DATA_REG) +#define kbd_read_status() inb(KBD_STATUS_REG) +#define kbd_write_output(val) outb(val, KBD_DATA_REG) +#define kbd_write_command(val) outb(val, KBD_CNTL_REG) diff --git a/drivers/serial/kgdboc.c b/drivers/serial/kgdboc.c index eadc1ab..cac8ae7 100644 --- a/drivers/serial/kgdboc.c +++ b/drivers/serial/kgdboc.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include #define MAX_CONFIG_LEN 40 @@ -45,11 +47,32 @@ static int kgdboc_option_setup(char *opt) __setup("kgdboc=", kgdboc_option_setup); +static void cleanup_kgdboc(void) +{ +#ifdef CONFIG_KDB_KEYBOARD + int i; + + /* Unregister the keyboard poll hook, if registered */ + for (i = 0; i < kdb_poll_idx; i++) { + if (kdb_poll_funcs[i] == kdb_get_kbd_char) { + kdb_poll_idx--; + kdb_poll_funcs[i] = kdb_poll_funcs[kdb_poll_idx]; + kdb_poll_funcs[kdb_poll_idx] = NULL; + i--; + } + } +#endif /* CONFIG_KDB_KEYBOARD */ + + if (configured == 1) + kgdb_unregister_io_module(&kgdboc_io_ops); +} + static int configure_kgdboc(void) { struct tty_driver *p; int tty_line = 0; int err; + char *cptr = config; err = kgdboc_option_setup(config); if (err || !strlen(config) || isspace(config[0])) @@ -57,13 +80,32 @@ static int configure_kgdboc(void) err = -ENODEV; - p = tty_find_polling_driver(config, &tty_line); +#ifdef CONFIG_KDB_KEYBOARD + kgdb_tty_driver = NULL; + + if (strncmp(cptr, "kbd", 3) == 0) { + if (kdb_poll_idx < KDB_POLL_FUNC_MAX) { + kdb_poll_funcs[kdb_poll_idx] = kdb_get_kbd_char; + kdb_poll_idx++; + if (cptr[3] == ',') + cptr += 4; + else + goto do_register; + } + } +#endif /* CONFIG_KDB_KEYBOARD */ + + p = tty_find_polling_driver(cptr, &tty_line); if (!p) goto noconfig; kgdb_tty_driver = p; kgdb_tty_line = tty_line; +#ifdef CONFIG_KDB_KEYBOARD +do_register: +#endif /* CONFIG_KDB_KEYBOARD */ + err = kgdb_register_io_module(&kgdboc_io_ops); if (err) goto noconfig; @@ -75,6 +117,7 @@ static int configure_kgdboc(void) noconfig: config[0] = 0; configured = 0; + cleanup_kgdboc(); return err; } @@ -88,20 +131,18 @@ static int __init init_kgdboc(void) return configure_kgdboc(); } -static void cleanup_kgdboc(void) -{ - if (configured == 1) - kgdb_unregister_io_module(&kgdboc_io_ops); -} - static int kgdboc_get_char(void) { + if (!kgdb_tty_driver) + return -1; return kgdb_tty_driver->ops->poll_get_char(kgdb_tty_driver, kgdb_tty_line); } static void kgdboc_put_char(u8 chr) { + if (!kgdb_tty_driver) + return; kgdb_tty_driver->ops->poll_put_char(kgdb_tty_driver, kgdb_tty_line, chr); } @@ -162,6 +203,19 @@ static struct kgdb_io kgdboc_io_ops = { .post_exception = kgdboc_post_exp_handler, }; +#ifdef CONFIG_KGDB_SERIAL_CONSOLE +/* This is only available if kgdboc is a built in for early debugging */ +void __init early_kgdboc_init(void) +{ + /* save the first character of the config string because the + * init routine can destroy it. + */ + char save_ch = config[0]; + init_kgdboc(); + config[0] = save_ch; +} +#endif /* CONFIG_KGDB_SERIAL_CONSOLE */ + module_init(init_kgdboc); module_exit(cleanup_kgdboc); module_param_call(kgdboc, param_set_kgdboc_var, param_get_string, &kps, 0644); diff --git a/include/linux/keyboard.h b/include/linux/keyboard.h index a3c984d..74e0753 100644 --- a/include/linux/keyboard.h +++ b/include/linux/keyboard.h @@ -28,6 +28,8 @@ extern const int NR_TYPES; extern const int max_vals[]; extern unsigned short *key_maps[MAX_NR_KEYMAPS]; extern unsigned short plain_map[NR_KEYS]; +extern unsigned short shift_map[NR_KEYS]; +extern unsigned short ctrl_map[NR_KEYS]; struct keyboard_notifier_param { struct vc_data *vc; /* VC on which the keyboard press was done */ diff --git a/kdb/kdbmain.c b/kdb/kdbmain.c index b445a17..a995269 100644 --- a/kdb/kdbmain.c +++ b/kdb/kdbmain.c @@ -3643,6 +3643,9 @@ kdb_init(void) kdb_initial_cpu = -1; // kdb_wait_for_cpus_secs = max(10, 2*num_online_cpus()); +#if defined(CONFIG_KDB_KEYBOARD) && defined(CONFIG_KGDB_SERIAL_CONSOLE) + early_kgdboc_init(); +#endif /* CONFIG_KDB_KEYBOARD && CONFIG_KGDB_SERIAL_CONSOLE */ } // HACK have to sort through these later, some probably are not needed EXPORT_SYMBOL_GPL(kdb_register); diff --git a/lib/Kconfig.kgdb b/lib/Kconfig.kgdb index 59b47b9..772e14b 100644 --- a/lib/Kconfig.kgdb +++ b/lib/Kconfig.kgdb @@ -71,4 +71,11 @@ config KGDB_KDB_PRIMARY KDB will be the active debugger instead of the typical kgdb frontend. +config KDB_KEYBOARD + bool "KGDB_KDB: keyboard as input device" + depends on VT && KGDB_KDB + default y + help + KDB can use a PS/2 type keyboard for an input device + endif # KGDB -- 1.6.3.rc0.1.gf800 From jason.wessel@windriver.com Fri May 8 16:23:30 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-2.5 required=5.0 tests=AWL,BAYES_00 autolearn=ham version=3.3.0-rupdated Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n48LNUVc031441 for ; Fri, 8 May 2009 16:23:30 -0500 X-ASG-Debug-ID: 1241817813-3fb700410000-sLlkUa X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi Received: from mail.wrs.com (localhost [127.0.0.1]) by cuda.sgi.com (Spam Firewall) with ESMTP id 5BB2E1D1EBF4 for ; Fri, 8 May 2009 14:23:34 -0700 (PDT) Received: from mail.wrs.com (mail.windriver.com [147.11.1.11]) by cuda.sgi.com with ESMTP id CCwpoG6CesDkKf9j for ; Fri, 08 May 2009 14:23:34 -0700 (PDT) Received: from ALA-MAIL03.corp.ad.wrs.com (ala-mail03 [147.11.57.144]) by mail.wrs.com (8.13.6/8.13.6) with ESMTP id n48LNQge005494; Fri, 8 May 2009 14:23:26 -0700 (PDT) Received: from ala-mail06.corp.ad.wrs.com ([147.11.57.147]) by ALA-MAIL03.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:26 -0700 Received: from localhost.localdomain ([172.25.32.41]) by ala-mail06.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:26 -0700 From: Jason Wessel To: linux-kernel@vger.kernel.org Cc: kgdb-bugreport@lists.sourceforge.net, kdb@oss.sgi.com, Jason Wessel X-ASG-Orig-Subj: [PATCH 03/13] RFC ONLY - kgdb,8250,pl011: Return immediately from console poll Subject: [PATCH 03/13] RFC ONLY - kgdb,8250,pl011: Return immediately from console poll Date: Fri, 8 May 2009 16:23:10 -0500 Message-Id: <1241817800-9320-4-git-send-email-jason.wessel@windriver.com> X-Mailer: git-send-email 1.6.3.rc0.1.gf800 In-Reply-To: <1241817800-9320-3-git-send-email-jason.wessel@windriver.com> References: <1241817800-9320-1-git-send-email-jason.wessel@windriver.com> <1241817800-9320-2-git-send-email-jason.wessel@windriver.com> <1241817800-9320-3-git-send-email-jason.wessel@windriver.com> X-OriginalArrivalTime: 08 May 2009 21:23:26.0513 (UTC) FILETIME=[3992E210:01C9D023] X-Barracuda-Connect: mail.windriver.com[147.11.1.11] X-Barracuda-Start-Time: 1241817814 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com X-Barracuda-Spam-Score: -2.02 X-Barracuda-Spam-Status: No, SCORE=-2.02 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.1.25266 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean This is a RFC patch. The work to possibly merge kdb and kgdb is being evaluated and this patch is considered only a proof of concept or prototype. The design of kdb required that every device that can provide input to kdb have a polling routine that exits immediately if there is no character available. This is required in order to get the page scrolling mechanism working, it is also a reasonable requirement for future kgdb I/O drivers because that allows for the possibility of multiple input channels. NO_POLL_CHAR will be the return code to the polling routine when ever there is no character available. There are several other console polling drivers which can be modified, but for the prototype only the 8250 and pl011 driver have been changed to make use of this. Signed-off-by: Jason Wessel --- drivers/serial/8250.c | 4 +- drivers/serial/amba-pl011.c | 6 ++-- include/linux/kgdb.h | 3 ++ include/linux/serial_core.h | 1 + kernel/kgdb.c | 47 +++++++++++++++++++++++++++++++++++++----- 5 files changed, 50 insertions(+), 11 deletions(-) diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index b4b3981..03f815b 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -1884,8 +1884,8 @@ static int serial8250_get_poll_char(struct uart_port *port) struct uart_8250_port *up = (struct uart_8250_port *)port; unsigned char lsr = serial_inp(up, UART_LSR); - while (!(lsr & UART_LSR_DR)) - lsr = serial_inp(up, UART_LSR); + if (!(lsr & UART_LSR_DR)) + return NO_POLL_CHAR; return serial_inp(up, UART_RX); } diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index 8b2b970..fb2ed6a 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c @@ -318,9 +318,9 @@ static int pl010_get_poll_char(struct uart_port *port) struct uart_amba_port *uap = (struct uart_amba_port *)port; unsigned int status; - do { - status = readw(uap->port.membase + UART01x_FR); - } while (status & UART01x_FR_RXFE); + status = readw(uap->port.membase + UART01x_FR); + if (status & UART01x_FR_RXFE) + return NO_POLL_CHAR; return readw(uap->port.membase + UART01x_DR); } diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h index 3e838d6..967803d 100644 --- a/include/linux/kgdb.h +++ b/include/linux/kgdb.h @@ -283,4 +283,7 @@ extern int kgdb_nmicallback(int cpu, void *regs); extern int kgdb_single_step; extern atomic_t kgdb_active; +#ifdef CONFIG_KGDB_SERIAL_CONSOLE +extern void __init early_kgdboc_init(void); +#endif /* CONFIG_KGDB_SERIAL_CONSOLE */ #endif /* _KGDB_H_ */ diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 57a97e5..6fda5b8 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -232,6 +232,7 @@ struct uart_ops { #endif }; +#define NO_POLL_CHAR 0x00ff0000 #define UART_CONFIG_TYPE (1 << 0) #define UART_CONFIG_IRQ (1 << 1) diff --git a/kernel/kgdb.c b/kernel/kgdb.c index 067f2cf..2f093bc 100644 --- a/kernel/kgdb.c +++ b/kernel/kgdb.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -254,6 +255,8 @@ void __weak kgdb_disable_hw_debug(struct pt_regs *regs) * KDB interface to KGDB internals */ #ifdef CONFIG_KGDB_KDB +int kdb_poll_idx = 1; +EXPORT_SYMBOL_GPL(kdb_poll_idx); static void gdb_cmd_status(struct kgdb_state *ks); static void put_packet(char *buffer); static int kgdb_activate_sw_breakpoints(void); @@ -261,6 +264,8 @@ static int kgdb_activate_sw_breakpoints(void); static int kgdbio_get_char(void) { int ret = kgdb_io_ops->read_char(); + if (ret == NO_POLL_CHAR) + return -1; if (!kgdb_use_passthrough) return ret; if (ret == 127) @@ -271,7 +276,27 @@ static int kgdbio_get_char(void) get_char_func kdb_poll_funcs[] = { kgdbio_get_char, NULL, + NULL, + NULL, + NULL, + NULL, }; +EXPORT_SYMBOL_GPL(kdb_poll_funcs); + +static int kgdb_read_wait(void) +{ + int ret = -1; + int i; + + /* poll any additional I/O interfaces that are defined */ + while (ret < 0) + for (i = 0; kdb_poll_funcs[i] != NULL; i++) { + ret = kdb_poll_funcs[i](); + if (ret > 0) + break; + } + return ret; +} static int comm_passthrough(struct kgdb_state *ks) { @@ -333,6 +358,7 @@ static int comm_passthrough(struct kgdb_state *ks) kdb_bp_remove_global(); KDB_STATE_CLEAR(DOING_SS); KDB_STATE_CLEAR(DOING_SSB); + KDB_STATE_SET(PAGER); for_each_online_cpu(i) { kdb_save_running_cpu(kgdb_info[i].debuggerinfo, kgdb_info[i].task, i); @@ -356,6 +382,7 @@ static int comm_passthrough(struct kgdb_state *ks) kdb_initial_cpu = -1; kdb_current_task = NULL; kdb_current_regs = NULL; + KDB_STATE_CLEAR(PAGER); kdbnearsym_cleanup(); if (error == KDB_CMD_KGDB) { if (KDB_STATE(DOING_KGDB) || KDB_STATE(DOING_KGDB2)) { @@ -397,6 +424,14 @@ static int comm_passthrough(struct kgdb_state *ks) { return KGDB_PASS_EVENT; } + +static int kgdb_read_wait(void) +{ + int ret = kgdb_io_ops->read_char(); + while (ret == NO_POLL_CHAR) + ret = kgdb_io_ops->read_char(); + return ret; +} #endif /* CONFIG_KGDB_KDB */ /* @@ -427,7 +462,7 @@ static void get_packet(char *buffer) * Spin and wait around for the start character, ignore all * other characters: */ - while ((ch = (kgdb_io_ops->read_char())) != '$') + while ((ch = (kgdb_read_wait())) != '$') /* nothing */; kgdb_connected = 1; @@ -440,7 +475,7 @@ static void get_packet(char *buffer) * now, read until a # or end of buffer is found: */ while (count < (BUFMAX - 1)) { - ch = kgdb_io_ops->read_char(); + ch = kgdb_read_wait(); if (ch == '#') break; checksum = checksum + ch; @@ -450,8 +485,8 @@ static void get_packet(char *buffer) buffer[count] = 0; if (ch == '#') { - xmitcsum = hex(kgdb_io_ops->read_char()) << 4; - xmitcsum += hex(kgdb_io_ops->read_char()); + xmitcsum = hex(kgdb_read_wait()) << 4; + xmitcsum += hex(kgdb_read_wait()); if (checksum != xmitcsum) /* failed checksum */ @@ -496,10 +531,10 @@ static void put_packet(char *buffer) kgdb_io_ops->flush(); /* Now see what we get in reply. */ - ch = kgdb_io_ops->read_char(); + ch = kgdb_read_wait(); if (ch == 3) - ch = kgdb_io_ops->read_char(); + ch = kgdb_read_wait(); /* If we get an ACK, we are done. */ if (ch == '+') -- 1.6.3.rc0.1.gf800 From jason.wessel@windriver.com Fri May 8 16:23:33 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-1.5 required=5.0 tests=AWL,BAYES_00,FRT_LEVITRA, J_CHICKENPOX_35 autolearn=no version=3.3.0-rupdated Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n48LNX89031503 for ; Fri, 8 May 2009 16:23:33 -0500 X-ASG-Debug-ID: 1241817817-3fb700420000-sLlkUa X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi Received: from mail.wrs.com (localhost [127.0.0.1]) by cuda.sgi.com (Spam Firewall) with ESMTP id A310B1D1EC09 for ; Fri, 8 May 2009 14:23:37 -0700 (PDT) Received: from mail.wrs.com (mail.windriver.com [147.11.1.11]) by cuda.sgi.com with ESMTP id OHHMPrFPACLGDG9L for ; Fri, 08 May 2009 14:23:37 -0700 (PDT) Received: from ALA-MAIL03.corp.ad.wrs.com (ala-mail03 [147.11.57.144]) by mail.wrs.com (8.13.6/8.13.6) with ESMTP id n48LNWvc005554; Fri, 8 May 2009 14:23:32 -0700 (PDT) Received: from ala-mail06.corp.ad.wrs.com ([147.11.57.147]) by ALA-MAIL03.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:32 -0700 Received: from localhost.localdomain ([172.25.32.41]) by ala-mail06.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:31 -0700 From: Jason Wessel To: linux-kernel@vger.kernel.org Cc: kgdb-bugreport@lists.sourceforge.net, kdb@oss.sgi.com, Jason Wessel X-ASG-Orig-Subj: [PATCH 10/13] RFC ONLY - mips,kgdb: kdb low level trap catch and stack trace Subject: [PATCH 10/13] RFC ONLY - mips,kgdb: kdb low level trap catch and stack trace Date: Fri, 8 May 2009 16:23:17 -0500 Message-Id: <1241817800-9320-11-git-send-email-jason.wessel@windriver.com> X-Mailer: git-send-email 1.6.3.rc0.1.gf800 In-Reply-To: <1241817800-9320-10-git-send-email-jason.wessel@windriver.com> References: <1241817800-9320-1-git-send-email-jason.wessel@windriver.com> <1241817800-9320-2-git-send-email-jason.wessel@windriver.com> <1241817800-9320-3-git-send-email-jason.wessel@windriver.com> <1241817800-9320-4-git-send-email-jason.wessel@windriver.com> <1241817800-9320-5-git-send-email-jason.wessel@windriver.com> <1241817800-9320-6-git-send-email-jason.wessel@windriver.com> <1241817800-9320-7-git-send-email-jason.wessel@windriver.com> <1241817800-9320-8-git-send-email-jason.wessel@windriver.com> <1241817800-9320-9-git-send-email-jason.wessel@windriver.com> <1241817800-9320-10-git-send-email-jason.wessel@windriver.com> X-OriginalArrivalTime: 08 May 2009 21:23:31.0856 (UTC) FILETIME=[3CC22900:01C9D023] X-Barracuda-Connect: mail.windriver.com[147.11.1.11] X-Barracuda-Start-Time: 1241817817 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com X-Barracuda-Spam-Score: -1.28 X-Barracuda-Spam-Status: No, SCORE=-1.28 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests=FRT_LEVITRA X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.1.25266 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.74 FRT_LEVITRA BODY: ReplaceTags: Levitra X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean This is a RFC patch. The work to possibly merge kdb and kgdb is being evaluated and this patch is considered only a proof of concept or prototype. The only way the debugger can handle a trap in inside rcu_lock, notify_die, or atomic_notifier_call_chain without a recursive fault is to have a low level "first opportunity handler" do_trap_or_bp() handler. Generally this will be something the vast majority of folks will not need, but for those who need it, it is added as a kernel .config option called KGDB_LOW_LEVEL_TRAP. Also added was a die notification for oops such that kdb can catch an oops for analysis. There appeared no obvious way to pass the struct pt_regs from the original exception back to the stack back tracer, so a special case was added to show_stack() for when kdb is active because you generally desire to generally look at the back trace of the original exception. Signed-off-by: Jason Wessel --- arch/mips/include/asm/kgdb.h | 2 ++ arch/mips/kernel/kgdb.c | 22 +++++++++++++++++++++- arch/mips/kernel/traps.c | 14 ++++++++++++++ lib/Kconfig.kgdb | 2 +- 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/arch/mips/include/asm/kgdb.h b/arch/mips/include/asm/kgdb.h index 48223b0..19002d6 100644 --- a/arch/mips/include/asm/kgdb.h +++ b/arch/mips/include/asm/kgdb.h @@ -38,6 +38,8 @@ extern int kgdb_early_setup; extern void *saved_vectors[32]; extern void handle_exception(struct pt_regs *regs); extern void breakinst(void); +extern int kgdb_ll_trap(int cmd, const char *str, + struct pt_regs *regs, long err, int trap, int sig); #endif /* __KERNEL__ */ diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c index 54f2d40..a4e546a 100644 --- a/arch/mips/kernel/kgdb.c +++ b/arch/mips/kernel/kgdb.c @@ -202,7 +202,7 @@ static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd, if (atomic_read(&kgdb_active) != -1) kgdb_nmicallback(smp_processor_id(), regs); - if (kgdb_handle_exception(trap, compute_signal(trap), 0, regs)) + if (kgdb_handle_exception(trap, compute_signal(trap), cmd, regs)) return NOTIFY_DONE; if (atomic_read(&kgdb_setting_breakpoint)) @@ -216,6 +216,26 @@ static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd, return NOTIFY_STOP; } +#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP +int kgdb_ll_trap(int cmd, const char *str, + struct pt_regs *regs, long err, int trap, int sig) +{ + struct die_args args = { + .regs = regs, + .str = str, + .err = err, + .trapnr = trap, + .signr = sig, + + }; + + if (!kgdb_io_module_registered) + return NOTIFY_DONE; + + return kgdb_mips_notify(NULL, cmd, &args); +} +#endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */ + static struct notifier_block kgdb_notifier = { .notifier_call = kgdb_mips_notify, }; diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index e83da17..fbf427e 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include @@ -186,6 +188,11 @@ void show_stack(struct task_struct *task, unsigned long *sp) regs.regs[29] = task->thread.reg29; regs.regs[31] = 0; regs.cp0_epc = task->thread.reg31; +#ifdef CONFIG_KGDB_KDB + } else if (atomic_read(&kgdb_active) != -1 && + kdb_current_regs) { + memcpy(®s, kdb_current_regs, sizeof(regs)); +#endif /* CONFIG_KGDB_KDB */ } else { prepare_frametrace(®s); } @@ -360,6 +367,8 @@ void __noreturn die(const char * str, const struct pt_regs * regs) unsigned long dvpret = dvpe(); #endif /* CONFIG_MIPS_MT_SMTC */ + notify_die(DIE_OOPS, str, (struct pt_regs *)regs, SIGSEGV, 0, 0); + console_verbose(); spin_lock_irq(&die_lock); bust_spinlocks(1); @@ -701,6 +710,11 @@ static void do_trap_or_bp(struct pt_regs *regs, unsigned int code, siginfo_t info; char b[40]; +#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP + if (kgdb_ll_trap(DIE_TRAP, str, regs, code, 0, 0) == NOTIFY_STOP) + return; +#endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */ + if (notify_die(DIE_TRAP, str, regs, code, 0, 0) == NOTIFY_STOP) return; diff --git a/lib/Kconfig.kgdb b/lib/Kconfig.kgdb index a2f63be..b5d3637 100644 --- a/lib/Kconfig.kgdb +++ b/lib/Kconfig.kgdb @@ -59,7 +59,7 @@ config KGDB_TESTS_BOOT_STRING config KGDB_LOW_LEVEL_TRAP bool "KGDB: Allow debugging with traps in notifiers" - depends on X86 || PPC + depends on X86 || PPC || MIPS default n help This will add an extra call back to kgdb for the breakpoint -- 1.6.3.rc0.1.gf800 From jason.wessel@windriver.com Fri May 8 16:23:42 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-1.4 required=5.0 tests=AWL,BAYES_00,J_CHICKENPOX_21, J_CHICKENPOX_23,J_CHICKENPOX_24,J_CHICKENPOX_26,J_CHICKENPOX_31, J_CHICKENPOX_33,J_CHICKENPOX_34,J_CHICKENPOX_35,J_CHICKENPOX_36, J_CHICKENPOX_54,J_CHICKENPOX_55,J_CHICKENPOX_61,J_CHICKENPOX_62, J_CHICKENPOX_63,J_CHICKENPOX_64,J_CHICKENPOX_66,J_CHICKENPOX_71, J_CHICKENPOX_72,J_CHICKENPOX_73,J_CHICKENPOX_83 autolearn=no version=3.3.0-rupdated Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n48LNfGT031548 for ; Fri, 8 May 2009 16:23:41 -0500 X-ASG-Debug-ID: 1241817815-3e1600430000-sLlkUa X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi Received: from mail.wrs.com (localhost [127.0.0.1]) by cuda.sgi.com (Spam Firewall) with ESMTP id BDA701D1EBFA for ; Fri, 8 May 2009 14:23:36 -0700 (PDT) Received: from mail.wrs.com (mail.windriver.com [147.11.1.11]) by cuda.sgi.com with ESMTP id 5rV5gl2fypFbb6Z3 for ; Fri, 08 May 2009 14:23:36 -0700 (PDT) Received: from ALA-MAIL03.corp.ad.wrs.com (ala-mail03 [147.11.57.144]) by mail.wrs.com (8.13.6/8.13.6) with ESMTP id n48LNPfJ005486; Fri, 8 May 2009 14:23:25 -0700 (PDT) Received: from ala-mail06.corp.ad.wrs.com ([147.11.57.147]) by ALA-MAIL03.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:25 -0700 Received: from localhost.localdomain ([172.25.32.41]) by ala-mail06.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Fri, 8 May 2009 14:23:24 -0700 From: Jason Wessel To: linux-kernel@vger.kernel.org Cc: kgdb-bugreport@lists.sourceforge.net, kdb@oss.sgi.com, Jason Wessel X-ASG-Orig-Subj: [PATCH 01/13] RFC ONLY - kdb: core for kgdb back end Subject: [PATCH 01/13] RFC ONLY - kdb: core for kgdb back end Date: Fri, 8 May 2009 16:23:08 -0500 Message-Id: <1241817800-9320-2-git-send-email-jason.wessel@windriver.com> X-Mailer: git-send-email 1.6.3.rc0.1.gf800 In-Reply-To: <1241817800-9320-1-git-send-email-jason.wessel@windriver.com> References: <1241817800-9320-1-git-send-email-jason.wessel@windriver.com> X-OriginalArrivalTime: 08 May 2009 21:23:24.0372 (UTC) FILETIME=[384C3140:01C9D023] X-Barracuda-Connect: mail.windriver.com[147.11.1.11] X-Barracuda-Start-Time: 1241817816 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com X-Barracuda-Spam-Score: -1.52 X-Barracuda-Spam-Status: No, SCORE=-1.52 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests=BSF_RULE_7582B X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.1.25266 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.50 BSF_RULE_7582B Custom Rule 7582B X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean This is an RFC patch. This work is by no means in its final form, nor is it in a form that would be suitible for upstream merging. This is an early prototype of a kdb frontend talking to a kgdb backend. It is meant to foster some discussion around the usefulness of merging kdb and kgdb together, as well as experiment with changes to kgdb's core to improve robustness and functionality. This patch contains the kdb core and some instrumentation into the core kernel which kdb requires in order to gather information for some of its reporting functions. This work is directly derived from kdb v4.4 found at: ftp://oss.sgi.com/projects/kdb/download/v4.4/ This particular patch is not even close to sanitized with sparse, or checkpatch.pl. This is more or less a very raw port of the original kdb which attempts to break down kdb into a architecture independent front end to attach to kgdb. The original starting point for the 2.6.29 kernel was: "129 files changed, 57952 insertions(+), 10 deletions(-)" You can imagine some stuff got severly chopped in order to get it down to ~8000 lines worth changes. Things like the x86 disasembler, kdump/kexec analysis, x86 specific backtracer, usb support, and even the scrolling pager got tossed overboard. There is a lot of clean up that can happen with in the kdb internals as a result of the integration as well as to improve modularity. It seems that it would be nice to have a modular front end for kgdb which you can add additional commands for other post mortem activities. Part of the motivation behind adding another front end to kgdb is to make the built in kernel debugger better and join the user base of kdb and kgdb vs further fragmentation. With all the disclaimers out of the way, it can be noted that this is a working prototype for 4 architechtures, and it is reasonably easy to add more. Signed-off-by: Jason Wessel --- Makefile | 1 + arch/arm/include/asm/kmap_types.h | 1 + arch/mips/include/asm/kmap_types.h | 3 +- arch/powerpc/include/asm/kmap_types.h | 1 + arch/x86/include/asm/kmap_types.h | 3 +- fs/proc/meminfo.c | 145 ++ fs/proc/mmu.c | 16 +- include/linux/kdb.h | 171 ++ include/linux/kdbprivate.h | 610 ++++++ init/main.c | 26 + kdb/.gitignore | 1 + kdb/Makefile | 48 + kdb/kdb_bp.c | 863 ++++++++ kdb/kdb_bt.c | 209 ++ kdb/kdb_cmds | 32 + kdb/kdb_io.c | 890 ++++++++ kdb/kdbmain.c | 3666 +++++++++++++++++++++++++++++++++ kdb/kdbsupport.c | 1120 ++++++++++ kernel/kallsyms.c | 22 + kernel/module.c | 19 +- kernel/panic.c | 6 + kernel/printk.c | 14 + kernel/sched.c | 93 +- kernel/signal.c | 49 + mm/hugetlb.c | 22 + mm/swapfile.c | 22 + 26 files changed, 8045 insertions(+), 8 deletions(-) create mode 100644 include/linux/kdb.h create mode 100644 include/linux/kdbprivate.h create mode 100644 kdb/.gitignore create mode 100644 kdb/Makefile create mode 100644 kdb/kdb_bp.c create mode 100644 kdb/kdb_bt.c create mode 100644 kdb/kdb_cmds create mode 100644 kdb/kdb_io.c create mode 100644 kdb/kdbmain.c create mode 100644 kdb/kdbsupport.c diff --git a/Makefile b/Makefile index b18afad..b2c349a 100644 --- a/Makefile +++ b/Makefile @@ -647,6 +647,7 @@ export mod_strip_cmd ifeq ($(KBUILD_EXTMOD),) core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ +core-$(CONFIG_KGDB_KDB) += kdb/ vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \ $(core-y) $(core-m) $(drivers-y) $(drivers-m) \ diff --git a/arch/arm/include/asm/kmap_types.h b/arch/arm/include/asm/kmap_types.h index d16ec97..93cc780 100644 --- a/arch/arm/include/asm/kmap_types.h +++ b/arch/arm/include/asm/kmap_types.h @@ -19,6 +19,7 @@ enum km_type { KM_SOFTIRQ0, KM_SOFTIRQ1, KM_L2_CACHE, + KM_KDB, KM_TYPE_NR }; diff --git a/arch/mips/include/asm/kmap_types.h b/arch/mips/include/asm/kmap_types.h index 806aae3..ec3f7a7 100644 --- a/arch/mips/include/asm/kmap_types.h +++ b/arch/mips/include/asm/kmap_types.h @@ -22,7 +22,8 @@ D(9) KM_IRQ0, D(10) KM_IRQ1, D(11) KM_SOFTIRQ0, D(12) KM_SOFTIRQ1, -D(13) KM_TYPE_NR +D(13) KM_KDB, +D(14) KM_TYPE_NR }; #undef D diff --git a/arch/powerpc/include/asm/kmap_types.h b/arch/powerpc/include/asm/kmap_types.h index b6bac6f..96ae0f2 100644 --- a/arch/powerpc/include/asm/kmap_types.h +++ b/arch/powerpc/include/asm/kmap_types.h @@ -26,6 +26,7 @@ enum km_type { KM_SOFTIRQ1, KM_PPC_SYNC_PAGE, KM_PPC_SYNC_ICACHE, + KM_KDB, KM_TYPE_NR }; diff --git a/arch/x86/include/asm/kmap_types.h b/arch/x86/include/asm/kmap_types.h index 5759c16..9e7a73f 100644 --- a/arch/x86/include/asm/kmap_types.h +++ b/arch/x86/include/asm/kmap_types.h @@ -21,7 +21,8 @@ D(9) KM_IRQ0, D(10) KM_IRQ1, D(11) KM_SOFTIRQ0, D(12) KM_SOFTIRQ1, -D(13) KM_TYPE_NR +D(13) KM_KDB, +D(14) KM_TYPE_NR }; #undef D diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c index c6b0302..4124657 100644 --- a/fs/proc/meminfo.c +++ b/fs/proc/meminfo.c @@ -154,6 +154,151 @@ static int meminfo_proc_show(struct seq_file *m, void *v) #undef K } +#ifdef CONFIG_KGDB_KDB +#include +#include +/* Like meminfo_proc_show() but without the locks and using kdb_printf() */ +void +kdb_meminfo_proc_show(void) +{ + struct sysinfo i; + unsigned long committed; + unsigned long allowed; + struct vmalloc_info vmi; + long cached; + unsigned long pages[NR_LRU_LISTS]; + int lru; + +/* + * display in kilobytes. + */ +#define K(x) ((x) << (PAGE_SHIFT - 10)) + si_meminfo(&i); + kdb_si_swapinfo(&i); + committed = percpu_counter_read_positive(&vm_committed_as); + allowed = ((totalram_pages - hugetlb_total_pages()) + * sysctl_overcommit_ratio / 100) + total_swap_pages; + + cached = global_page_state(NR_FILE_PAGES) - + total_swapcache_pages - i.bufferram; + if (cached < 0) + cached = 0; + + get_vmalloc_info(&vmi); + + for (lru = LRU_BASE; lru < NR_LRU_LISTS; lru++) + pages[lru] = global_page_state(NR_LRU_BASE + lru); + + kdb_printf( + "MemTotal: %8lu kB\n" + "MemFree: %8lu kB\n" + "Buffers: %8lu kB\n", + K(i.totalram), + K(i.freeram), + K(i.bufferram) + ); + kdb_printf( + "Cached: %8lu kB\n" + "SwapCached: %8lu kB\n" + "Active: %8lu kB\n" + "Inactive: %8lu kB\n", + K(cached), + K(total_swapcache_pages), + K(pages[LRU_ACTIVE_ANON] + pages[LRU_ACTIVE_FILE]), + K(pages[LRU_INACTIVE_ANON] + pages[LRU_INACTIVE_FILE]) + ); + kdb_printf( + "Active(anon): %8lu kB\n" + "Inactive(anon): %8lu kB\n" + "Active(file): %8lu kB\n" + "Inactive(file): %8lu kB\n", + K(pages[LRU_ACTIVE_ANON]), + K(pages[LRU_INACTIVE_ANON]), + K(pages[LRU_ACTIVE_FILE]), + K(pages[LRU_INACTIVE_FILE]) + ); +#ifdef CONFIG_UNEVICTABLE_LRU + kdb_printf( + "Unevictable: %8lu kB\n" + "Mlocked: %8lu kB\n", + K(pages[LRU_UNEVICTABLE]), + K(global_page_state(NR_MLOCK)) + ); +#endif +#ifdef CONFIG_HIGHMEM + kdb_printf( + "HighTotal: %8lu kB\n" + "HighFree: %8lu kB\n" + "LowTotal: %8lu kB\n" + "LowFree: %8lu kB\n", + K(i.totalhigh), + K(i.freehigh), + K(i.totalram-i.totalhigh), + K(i.freeram-i.freehigh) + ); +#endif + kdb_printf( + "SwapTotal: %8lu kB\n" + "SwapFree: %8lu kB\n" + "Dirty: %8lu kB\n", + K(i.totalswap), + K(i.freeswap), + K(global_page_state(NR_FILE_DIRTY)) + ); + kdb_printf( + "Writeback: %8lu kB\n" + "AnonPages: %8lu kB\n" + "Mapped: %8lu kB\n", + K(global_page_state(NR_WRITEBACK)), + K(global_page_state(NR_ANON_PAGES)), + K(global_page_state(NR_FILE_MAPPED)) + ); + kdb_printf( + "Slab: %8lu kB\n" + "SReclaimable: %8lu kB\n" + "SUnreclaim: %8lu kB\n", + K(global_page_state(NR_SLAB_RECLAIMABLE) + + global_page_state(NR_SLAB_UNRECLAIMABLE)), + K(global_page_state(NR_SLAB_RECLAIMABLE)), + K(global_page_state(NR_SLAB_UNRECLAIMABLE)) + ); + kdb_printf( + "PageTables: %8lu kB\n" +#ifdef CONFIG_QUICKLIST + "Quicklists: %8lu kB\n" +#endif + "NFS_Unstable: %8lu kB\n" + "Bounce: %8lu kB\n", + K(global_page_state(NR_PAGETABLE)), +#ifdef CONFIG_QUICKLIST + K(quicklist_total_size()), +#endif + K(global_page_state(NR_UNSTABLE_NFS)), + K(global_page_state(NR_BOUNCE)) + ); + kdb_printf( + "WritebackTmp: %8lu kB\n" + "CommitLimit: %8lu kB\n" + "Committed_AS: %8lu kB\n", + K(global_page_state(NR_WRITEBACK_TEMP)), + K(allowed), + K(committed) + ); + kdb_printf( + "VmallocTotal: %8lu kB\n" + "VmallocUsed: %8lu kB\n" + "VmallocChunk: %8lu kB\n", + (unsigned long)VMALLOC_TOTAL >> 10, + vmi.used >> 10, + vmi.largest_chunk >> 10 + ); + +#ifdef CONFIG_HUGETLBFS + kdb_hugetlb_report_meminfo(); +#endif +} +#endif /* CONFIG_KGDB_KDB */ + static int meminfo_proc_open(struct inode *inode, struct file *file) { return single_open(file, meminfo_proc_show, NULL); diff --git a/fs/proc/mmu.c b/fs/proc/mmu.c index 8ae221d..7fdb075 100644 --- a/fs/proc/mmu.c +++ b/fs/proc/mmu.c @@ -14,11 +14,21 @@ #include #include "internal.h" +#ifdef CONFIG_KGDB_KDB +#include +#endif + void get_vmalloc_info(struct vmalloc_info *vmi) { struct vm_struct *vma; unsigned long free_area_size; unsigned long prev_end; +#ifdef CONFIG_KGDB_KDB + int get_lock = !KDB_IS_RUNNING(); +#else +#define get_lock 1 +#endif + vmi->used = 0; @@ -30,7 +40,8 @@ void get_vmalloc_info(struct vmalloc_info *vmi) prev_end = VMALLOC_START; - read_lock(&vmlist_lock); + if (get_lock) + read_lock(&vmlist_lock); for (vma = vmlist; vma; vma = vma->next) { unsigned long addr = (unsigned long) vma->addr; @@ -55,6 +66,7 @@ void get_vmalloc_info(struct vmalloc_info *vmi) if (VMALLOC_END - prev_end > vmi->largest_chunk) vmi->largest_chunk = VMALLOC_END - prev_end; - read_unlock(&vmlist_lock); + if (get_lock) + read_unlock(&vmlist_lock); } } diff --git a/include/linux/kdb.h b/include/linux/kdb.h new file mode 100644 index 0000000..200af81 --- /dev/null +++ b/include/linux/kdb.h @@ -0,0 +1,171 @@ +#ifndef _KDB_H +#define _KDB_H + +/* + * Kernel Debugger Architecture Independent Global Headers + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 2000-2007 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (C) 2000 Stephane Eranian + */ + +#ifdef CONFIG_KGDB_KDB +#include +#include +#include + +#define KDB_MAJOR_VERSION 4 +#define KDB_MINOR_VERSION 4 +#define KDB_TEST_VERSION "" +#define KDB_POLL_FUNC_MAX 5 + +/* + * kdb_initial_cpu is initialized to -1, and is set to the cpu + * number whenever the kernel debugger is entered. + */ +extern int kdb_initial_cpu; +extern atomic_t kdb_event; +extern atomic_t kdb_8250; + +#define KDB_IS_RUNNING() (kdb_initial_cpu != -1) +#define KDB_8250() (atomic_read(&kdb_8250) != 0) + +/* + * kdb_on + * + * Defines whether kdb is on or not. Default value + * is set by CONFIG_KDB_OFF. Boot with kdb=on/off/on-nokey + * or echo "[012]" > /proc/sys/kernel/kdb to change it. + */ +extern int kdb_on; + +#if defined(CONFIG_SERIAL_8250_CONSOLE) || defined(CONFIG_SERIAL_SGI_L1_CONSOLE) +/* + * kdb_serial.iobase is initialized to zero, and is set to the I/O + * address of the serial port when the console is setup in + * serial_console_setup. + */ +extern struct kdb_serial { + int io_type; + unsigned long iobase; + unsigned long ioreg_shift; +} kdb_serial; +#endif + +/* + * kdb_diemsg + * + * Contains a pointer to the last string supplied to the + * kernel 'die' panic function. + */ +extern const char *kdb_diemsg; + +#define KDB_FLAG_EARLYKDB (1 << 0) /* set from boot parameter kdb=early */ +#define KDB_FLAG_CATASTROPHIC (1 << 1) /* A catastrophic event has occurred */ +#define KDB_FLAG_CMD_INTERRUPT (1 << 2) /* Previous command was interrupted */ +#define KDB_FLAG_NOIPI (1 << 3) /* Do not send IPIs */ +#define KDB_FLAG_ONLY_DO_DUMP (1 << 4) /* Only do a dump, used when + * kdb is off */ +#define KDB_FLAG_NO_CONSOLE (1 << 5) /* No console is available, + * kdb is disabled */ +#define KDB_FLAG_NO_VT_CONSOLE (1 << 6) /* No VT console is available, do + * not use keyboard */ +#define KDB_FLAG_NO_I8042 (1 << 7) /* No i8042 chip is available, do + * not use keyboard */ +#define KDB_FLAG_RECOVERY (1 << 8) /* kdb is being entered for an + * error which has been recovered */ + +extern int kdb_flags; /* Global flags, see kdb_state for per cpu state */ + +extern void kdb_save_flags(void); +extern void kdb_restore_flags(void); + +#define KDB_FLAG(flag) (kdb_flags & KDB_FLAG_##flag) +#define KDB_FLAG_SET(flag) ((void)(kdb_flags |= KDB_FLAG_##flag)) +#define KDB_FLAG_CLEAR(flag) ((void)(kdb_flags &= ~KDB_FLAG_##flag)) + +/* + * External entry point for the kernel debugger. The pt_regs + * at the time of entry are supplied along with the reason for + * entry to the kernel debugger. + */ + +typedef enum { + KDB_REASON_ENTER = 1, /* KDB_ENTER() trap/fault - regs valid */ + KDB_REASON_ENTER_SLAVE, /* KDB_ENTER_SLAVE() trap/fault - regs valid */ + KDB_REASON_BREAK, /* Breakpoint inst. - regs valid */ + KDB_REASON_DEBUG, /* Debug Fault - regs valid */ + KDB_REASON_OOPS, /* Kernel Oops - regs valid */ + KDB_REASON_SWITCH, /* CPU switch - regs valid*/ + KDB_REASON_KEYBOARD, /* Keyboard entry - regs valid */ + KDB_REASON_NMI, /* Non-maskable interrupt; regs valid */ + KDB_REASON_RECURSE, /* Recursive entry to kdb; + * regs probably valid */ + KDB_REASON_CPU_UP, /* Add one cpu to kdb; regs invalid */ + KDB_REASON_SILENT, /* Silent entry/exit to kdb; + * regs invalid - internal only */ + KDB_REASON_SSTEP, /* Single Step trap. - regs valid */ +} kdb_reason_t; + +/* Mainly used by kdb code, but this function is sometimes used + * by hacked debug code so make it generally available, not private. + */ +extern void kdb_printf(const char *, ...) + __attribute__ ((format (printf, 1, 2))); +typedef void (*kdb_printf_t)(const char *, ...) + __attribute__ ((format (printf, 1, 2))); +extern void kdb_init(void); + +#if defined(CONFIG_SMP) +/* + * Kernel debugger non-maskable IPI handler. + */ +extern int kdb_ipi(struct pt_regs *, void (*ack_interrupt)(void)); +extern void smp_kdb_stop(void); +#else /* CONFIG_SMP */ +#define smp_kdb_stop() +#endif /* CONFIG_SMP */ + +#ifdef CONFIG_KDB_USB + +#include + +extern int kdb_no_usb; +extern int kdb_usb_keyboard_attach(struct urb *urb, + unsigned char *buffer, void *poll_func); +extern int kdb_usb_keyboard_detach(struct urb *urb); + +#endif /* CONFIG_KDB_USB */ + +static inline +int kdb_process_cpu(const struct task_struct *p) +{ + unsigned int cpu = task_thread_info(p)->cpu; + if (cpu > NR_CPUS) + cpu = 0; + return cpu; +} + +extern const char kdb_serial_str[]; + +#ifdef CONFIG_KDB_KDUMP +/* Define values for kdb_kdump_state */ +extern int kdb_kdump_state; /* KDB kdump state */ +#define KDB_KDUMP_RESET 0 +#define KDB_KDUMP_KDUMP 1 + +void kdba_kdump_prepare(struct pt_regs *); +void machine_crash_shutdown(struct pt_regs *); +void machine_crash_shutdown_begin(void); +void machine_crash_shutdown_end(struct pt_regs *); + +#endif /* CONFIG_KDB_KDUMP */ +#else /* ! CONFIG_KGDB_KDB */ +#define KDB_IS_RUNNING() (0) +#define KDB_8250() (0) +#endif /* CONFIG_KGDB_KDB */ + +#endif /* !_KDB_H */ diff --git a/include/linux/kdbprivate.h b/include/linux/kdbprivate.h new file mode 100644 index 0000000..8579e97 --- /dev/null +++ b/include/linux/kdbprivate.h @@ -0,0 +1,610 @@ +#ifndef _KDBPRIVATE_H +#define _KDBPRIVATE_H + +/* + * Kernel Debugger Architecture Independent Private Headers + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. + */ + + + /* + * Kernel Debugger Error codes. Must not overlap with command codes. + */ + +#define KDB_NOTFOUND (-1) +#define KDB_ARGCOUNT (-2) +#define KDB_BADWIDTH (-3) +#define KDB_BADRADIX (-4) +#define KDB_NOTENV (-5) +#define KDB_NOENVVALUE (-6) +#define KDB_NOTIMP (-7) +#define KDB_ENVFULL (-8) +#define KDB_ENVBUFFULL (-9) +#define KDB_TOOMANYBPT (-10) +#define KDB_TOOMANYDBREGS (-11) +#define KDB_DUPBPT (-12) +#define KDB_BPTNOTFOUND (-13) +#define KDB_BADMODE (-14) +#define KDB_BADINT (-15) +#define KDB_INVADDRFMT (-16) +#define KDB_BADREG (-17) +#define KDB_BADCPUNUM (-18) +#define KDB_BADLENGTH (-19) +#define KDB_NOBP (-20) +#define KDB_BADADDR (-21) + + /* + * Kernel Debugger Command codes. Must not overlap with error codes. + */ +#define KDB_CMD_GO (-1001) +#define KDB_CMD_CPU (-1002) +#define KDB_CMD_SS (-1003) +#define KDB_CMD_SSB (-1004) +#define KDB_CMD_KGDB (-1005) +#define KDB_CMD_KGDB2 (-1006) + + /* + * Internal debug flags + */ +/* KDB_DEBUG_FLAG_BT 0x0001 Was Stack traceback debug */ +#define KDB_DEBUG_FLAG_BP 0x0002 /* Breakpoint subsystem debug */ +#define KDB_DEBUG_FLAG_BB_SUMM 0x0004 /* Basic block analysis, summary only */ +#define KDB_DEBUG_FLAG_AR 0x0008 /* Activation record, generic */ +#define KDB_DEBUG_FLAG_ARA 0x0010 /* Activation record, arch specific */ +#define KDB_DEBUG_FLAG_BB 0x0020 /* All basic block analysis */ +#define KDB_DEBUG_FLAG_STATE 0x0040 /* State flags */ +#define KDB_DEBUG_FLAG_MASK 0xffff /* All debug flags */ +#define KDB_DEBUG_FLAG_SHIFT 16 /* Shift factor for dbflags */ + +#define KDB_DEBUG(flag) (kdb_flags & \ + (KDB_DEBUG_FLAG_##flag << KDB_DEBUG_FLAG_SHIFT)) +#define KDB_DEBUG_STATE(text, value) if (KDB_DEBUG(STATE)) \ + kdb_print_state(text, value) + +/* merged code from arch independent section */ + +#if BITS_PER_LONG == 32 + +#define KDB_PLATFORM_ENV "BYTESPERWORD=4" + +#define kdb_machreg_fmt "0x%lx" +#define kdb_machreg_fmt0 "0x%08lx" +#define kdb_bfd_vma_fmt "0x%lx" +#define kdb_bfd_vma_fmt0 "0x%08lx" +#define kdb_elfw_addr_fmt "0x%x" +#define kdb_elfw_addr_fmt0 "0x%08x" +#define kdb_f_count_fmt "%d" + +#elif BITS_PER_LONG == 64 + +#define KDB_PLATFORM_ENV "BYTESPERWORD=8" + +#define kdb_machreg_fmt "0x%lx" +#define kdb_machreg_fmt0 "0x%016lx" +#define kdb_bfd_vma_fmt "0x%lx" +#define kdb_bfd_vma_fmt0 "0x%016lx" +#define kdb_elfw_addr_fmt "0x%x" +#define kdb_elfw_addr_fmt0 "0x%016x" +#define kdb_f_count_fmt "%ld" + +#endif + +typedef unsigned long kdb_machreg_t; +typedef unsigned char kdb_machinst_t; + +/* + * KDB_MAXBPT describes the total number of breakpoints + * supported by this architecure. + */ +#define KDB_MAXBPT 16 + +/* + * KDB_MAXHARDBPT describes the total number of hardware + * breakpoint registers that exist. + */ +#define KDB_MAXHARDBPT 4 + +/* Maximum number of arguments to a function */ +#define KDBA_MAXARGS 16 + +typedef struct _kdbhard_bp { + kdb_machreg_t bph_reg; /* Register this breakpoint uses */ + + unsigned int bph_free:1; /* Register available for use */ + unsigned int bph_data:1; /* Data Access breakpoint */ + + unsigned int bph_write:1; /* Write Data breakpoint */ + unsigned int bph_mode:2; /* 0=inst, 1=write, 2=io, 3=read */ + unsigned int bph_length:2; /* 0=1, 1=2, 2=BAD, 3=4 (bytes) */ + unsigned int bph_installed; /* flag: hw bp is installed */ +} kdbhard_bp_t; + + +/* end merge */ + +typedef enum { + KDB_REPEAT_NONE = 0, /* Do not repeat this command */ + KDB_REPEAT_NO_ARGS, /* Repeat the command without arguments */ + KDB_REPEAT_WITH_ARGS, /* Repeat the command including its arguments */ +} kdb_repeat_t; + +typedef int (*kdb_func_t)(int, const char **); + + /* + * Symbol table format returned by kallsyms. + */ + +typedef struct __ksymtab { + unsigned long value; /* Address of symbol */ + const char *mod_name; /* Module containing symbol or + * "kernel" */ + unsigned long mod_start; + unsigned long mod_end; + const char *sec_name; /* Section containing symbol */ + unsigned long sec_start; + unsigned long sec_end; + const char *sym_name; /* Full symbol name, including + * any version */ + unsigned long sym_start; + unsigned long sym_end; + } kdb_symtab_t; +extern int kallsyms_symbol_next(char *prefix_name, int flag); +extern int kallsyms_symbol_complete(char *prefix_name, int max_len); + + /* + * Exported Symbols for kernel loadable modules to use. + */ +extern int kdb_register(char *, kdb_func_t, char *, char *, short); +extern int kdb_register_repeat(char *, kdb_func_t, char *, char *, + short, kdb_repeat_t); +extern int kdb_unregister(char *); + +extern int kdb_getarea_size(void *, unsigned long, size_t); +extern int kdb_putarea_size(unsigned long, void *, size_t); + +/* Like get_user and put_user, kdb_getarea and kdb_putarea take variable + * names, not pointers. The underlying *_size functions take pointers. + */ +#define kdb_getarea(x, addr) kdb_getarea_size(&(x), addr, sizeof((x))) +#define kdb_putarea(addr, x) kdb_putarea_size(addr, &(x), sizeof((x))) + +extern int kdb_getphysword(unsigned long *word, + unsigned long addr, size_t size); +extern int kdb_getword(unsigned long *, unsigned long, size_t); +extern int kdb_putword(unsigned long, unsigned long, size_t); + +extern int kdbgetularg(const char *, unsigned long *); +extern char *kdbgetenv(const char *); +extern int kdbgetintenv(const char *, int *); +extern int kdbgetaddrarg(int, const char**, int*, unsigned long *, + long *, char **); +extern int kdbgetsymval(const char *, kdb_symtab_t *); +extern int kdbnearsym(unsigned long, kdb_symtab_t *); +extern void kdbnearsym_cleanup(void); +extern char *kdb_read(char *buffer, size_t bufsize); +extern char *kdb_strdup(const char *str, gfp_t type); +extern void kdb_symbol_print(kdb_machreg_t, const kdb_symtab_t *, unsigned int); + + /* + * Do we have a set of registers? + */ + +#define KDB_NULL_REGS(regs) \ + (regs == (struct pt_regs *)NULL ? \ + kdb_printf("%s: null regs - should never happen\n", __func__), \ + 1 : 0) + + /* + * Routine for debugging the debugger state. + */ + +extern void kdb_print_state(const char *, int); + + /* + * Per cpu kdb state. A cpu can be under kdb control but outside kdb, + * for example when doing single step. + */ +extern int kdb_state[]; /* [NR_CPUS] */ +#define KDB_STATE_KDB 0x00000001 /* Cpu is inside kdb */ +#define KDB_STATE_LEAVING 0x00000002 /* Cpu is leaving kdb */ +#define KDB_STATE_CMD 0x00000004 /* Running a kdb command */ +#define KDB_STATE_KDB_CONTROL 0x00000008 /* This cpu is under + * kdb control */ +#define KDB_STATE_HOLD_CPU 0x00000010 /* Hold this cpu inside kdb */ +#define KDB_STATE_DOING_SS 0x00000020 /* Doing ss command */ +#define KDB_STATE_DOING_SSB 0x00000040 /* Doing ssb command, + * DOING_SS is also set */ +#define KDB_STATE_SSBPT 0x00000080 /* Install breakpoint + * after one ss, independent of + * DOING_SS */ +#define KDB_STATE_REENTRY 0x00000100 /* Valid re-entry into kdb */ +#define KDB_STATE_SUPPRESS 0x00000200 /* Suppress error messages */ +#define KDB_STATE_PAGER 0x00000400 /* pager is available */ +#define KDB_STATE_GO_SWITCH 0x00000800 /* go is switching + * back to initial cpu */ +#define KDB_STATE_PRINTF_LOCK 0x00001000 /* Holds kdb_printf lock */ +#define KDB_STATE_WAIT_IPI 0x00002000 /* Waiting for kdb_ipi() NMI */ +#define KDB_STATE_RECURSE 0x00004000 /* Recursive entry to kdb */ +#define KDB_STATE_IP_ADJUSTED 0x00008000 /* Restart IP has been + * adjusted */ +#define KDB_STATE_GO1 0x00010000 /* go only releases one cpu */ +#define KDB_STATE_KEYBOARD 0x00020000 /* kdb entered via + * keyboard on this cpu */ +#define KDB_STATE_KEXEC 0x00040000 /* kexec issued */ +#define KDB_STATE_DOING_KGDB 0x00080000 /* kgdb enter now issued */ +#define KDB_STATE_DOING_KGDB2 0x00100000 /* kgdb enter now issued */ +#define KDB_STATE_KGDB_TRANS 0x00200000 /* Transition to kgdb */ +#define KDB_STATE_ARCH 0xff000000 /* Reserved for arch + * specific use */ + +#define KDB_STATE_CPU(flag, cpu) (kdb_state[cpu] & KDB_STATE_##flag) +#define KDB_STATE_SET_CPU(flag, cpu) \ + ((void)(kdb_state[cpu] |= KDB_STATE_##flag)) +#define KDB_STATE_CLEAR_CPU(flag, cpu) \ + ((void)(kdb_state[cpu] &= ~KDB_STATE_##flag)) + +#define KDB_STATE(flag) KDB_STATE_CPU(flag, smp_processor_id()) +#define KDB_STATE_SET(flag) KDB_STATE_SET_CPU(flag, smp_processor_id()) +#define KDB_STATE_CLEAR(flag) KDB_STATE_CLEAR_CPU(flag, smp_processor_id()) + + /* + * kdb_nextline + * + * Contains the current line number on the screen. Used + * to handle the built-in pager (LINES env variable) + */ +extern int kdb_nextline; + + /* + * Breakpoint state + * + * Each active and inactive breakpoint is represented by + * an instance of the following data structure. + */ + +typedef struct _kdb_bp { + unsigned long bp_addr; /* Address breakpoint is present at */ + kdb_machinst_t bp_inst; /* Replaced instruction */ + + unsigned int bp_free:1; /* This entry is available */ + + unsigned int bp_enabled:1; /* Breakpoint is active in register */ + unsigned int bp_global:1; /* Global to all processors */ + + unsigned int bp_hardtype:1; /* Uses hardware register */ + unsigned int bp_forcehw:1; /* Force hardware register */ + unsigned int bp_installed:1; /* Breakpoint is installed */ + unsigned int bp_delay:1; /* Do delayed bp handling */ + unsigned int bp_delayed:1; /* Delayed breakpoint */ + + int bp_cpu; /* Cpu # (if bp_global == 0) */ + kdbhard_bp_t bp_template; /* Hardware breakpoint template */ + kdbhard_bp_t *bp_hard[NR_CPUS]; /* Hardware breakpoint structure */ + int bp_adjust; /* Adjustment to PC for real + * instruction */ +} kdb_bp_t; + +#ifdef CONFIG_KGDB_KDB + /* + * Breakpoint handling subsystem global variables + */ +extern kdb_bp_t kdb_breakpoints[/* KDB_MAXBPT */]; + + /* + * Breakpoint architecture dependent functions. Must be provided + * in some form for all architectures. + */ +extern void kdba_initbp(void); +extern void kdba_printbp(kdb_bp_t *); +extern void kdba_alloc_hwbp(kdb_bp_t *bp, int *diagp); +extern void kdba_free_hwbp(kdb_bp_t *bp); +extern int kdba_parsebp(int, const char**, int *, kdb_bp_t*); +extern char *kdba_bptype(kdbhard_bp_t *); +extern void kdba_setsinglestep(struct pt_regs *); +extern void kdba_clearsinglestep(struct pt_regs *); + + /* + * Adjust instruction pointer architecture dependent function. Must be + * provided in some form for all architectures. + */ +extern void kdba_adjust_ip(kdb_reason_t, int, struct pt_regs *); + + /* + * KDB-only global function prototypes. + */ +extern void kdb_id1(unsigned long); +extern void kdb_id_init(void); + + /* + * Initialization functions. + */ +extern void kdba_init(void); +extern void kdb_io_init(void); + + /* + * Architecture specific function to read a string. + */ +typedef int (*get_char_func)(void); +extern get_char_func kdb_poll_funcs[]; +extern int kdb_poll_idx; +extern int kdb_get_kbd_char(void); + +#ifndef CONFIG_IA64 + /* + * Data for a single activation record on stack. + */ + +struct kdb_stack_info { + kdb_machreg_t physical_start; + kdb_machreg_t physical_end; + kdb_machreg_t logical_start; + kdb_machreg_t logical_end; + kdb_machreg_t next; + const char *id; +}; + +typedef struct { DECLARE_BITMAP(bits, KDBA_MAXARGS); } valid_t; + +struct kdb_activation_record { + struct kdb_stack_info stack; /* information about + * current stack */ + int args; /* number of arguments + * detected */ + kdb_machreg_t arg[KDBA_MAXARGS]; /* -> arguments */ + valid_t valid; /* is argument n valid? */ +}; +#endif + + /* + * Architecture specific Stack Traceback functions. + */ + +struct task_struct; + +extern int kdba_bt_address(kdb_machreg_t, int); +extern int kdba_bt_process(const struct task_struct *, int); + + /* + * KDB Command Table + */ + +typedef struct _kdbtab { + char *cmd_name; /* Command name */ + kdb_func_t cmd_func; /* Function to execute command */ + char *cmd_usage; /* Usage String for this command */ + char *cmd_help; /* Help message for this command */ + short cmd_flags; /* Parsing flags */ + short cmd_minlen; /* Minimum legal # command + * chars required */ + kdb_repeat_t cmd_repeat; /* Does command auto repeat on enter? */ +} kdbtab_t; + + /* + * External command function declarations + */ + +extern int kdb_id(int, const char **); +extern int kdb_bt(int, const char **); + + /* + * External utility function declarations + */ +extern char *kdb_getstr(char *, size_t, char *); + + /* + * Register contents manipulation + */ +extern int kdba_getregcontents(const char *, struct pt_regs *, kdb_machreg_t *); +extern int kdba_setregcontents(const char *, struct pt_regs *, kdb_machreg_t); +extern int kdba_dumpregs(struct pt_regs *, const char *, const char *); +extern int kdba_setpc(struct pt_regs *, kdb_machreg_t); +extern kdb_machreg_t kdba_getpc(struct pt_regs *); + + /* + * Debug register handling. + */ +extern void kdba_installdbreg(kdb_bp_t *); +extern void kdba_removedbreg(kdb_bp_t *); + + /* + * Breakpoint handling - External interfaces + */ +extern void kdb_initbptab(void); +extern void kdb_bp_install_global(struct pt_regs *); +extern void kdb_bp_install_local(struct pt_regs *); +extern void kdb_bp_remove_global(void); +extern void kdb_bp_remove_local(void); + + /* + * Breakpoint handling - Internal to kdb_bp.c/kdba_bp.c + */ +extern int kdba_installbp(struct pt_regs *regs, kdb_bp_t *); +extern int kdba_removebp(kdb_bp_t *); + + +typedef enum { + KDB_DB_BPT, /* Breakpoint */ + KDB_DB_SS, /* Single-step trap */ + KDB_DB_SSB, /* Single step to branch */ + KDB_DB_SSBPT, /* Single step over breakpoint */ + KDB_DB_NOBPT /* Spurious breakpoint */ +} kdb_dbtrap_t; + +/* DEBUG trap/fault handler */ +extern kdb_dbtrap_t kdba_db_trap(struct pt_regs *, int); +/* Breakpoint trap/fault hdlr */ +extern kdb_dbtrap_t kdba_bp_trap(struct pt_regs *, int); + + /* + * Interrupt Handling + */ +typedef unsigned long kdb_intstate_t; + +extern void kdba_disableint(kdb_intstate_t *); +extern void kdba_restoreint(kdb_intstate_t *); + + /* + * SMP and process stack manipulation routines. + */ +extern int kdba_ipi(struct pt_regs *, void (*)(void)); +extern int kdba_main_loop(kdb_reason_t, kdb_reason_t, + int, kdb_dbtrap_t, struct pt_regs *); +extern int kdb_main_loop(kdb_reason_t, kdb_reason_t, + int, kdb_dbtrap_t, struct pt_regs *); + + /* + * General Disassembler interfaces + */ +#if 0 +extern int kdb_dis_fprintf(PTR, const char *, ...) \ + __attribute__ ((format (printf, 2, 3))); +extern int kdb_dis_fprintf_dummy(PTR, const char *, ...) \ + __attribute__ ((format (printf, 2, 3))); +extern disassemble_info kdb_di; +#endif + + /* + * Architecture Dependent Disassembler interfaces + */ +#if 0 +extern int kdba_id_printinsn(kdb_machreg_t, disassemble_info *); +extern int kdba_id_parsemode(const char *, disassemble_info*); +extern void kdba_id_init(disassemble_info *); +extern void kdba_check_pc(kdb_machreg_t *); +#endif + + /* + * Miscellaneous functions and data areas + */ +extern char *kdb_cmds[]; +extern void kdb_syslog_data(char *syslog_data[]); +extern unsigned long kdb_task_state_string(const char *); +extern char kdb_task_state_char (const struct task_struct *); +extern unsigned long kdb_task_state(const struct task_struct *p, + unsigned long mask); +extern void kdb_ps_suppressed(void); +extern void kdb_ps1(const struct task_struct *p); +extern int kdb_parse(const char *cmdstr); +extern void kdb_print_nameval(const char *name, unsigned long val); +extern void kdb_send_sig_info(struct task_struct *p, + struct siginfo *info, int seqno); +#ifdef CONFIG_SWAP +extern void kdb_si_swapinfo(struct sysinfo *); +#else +#include +#define kdb_si_swapinfo(x) si_swapinfo(x) +#endif +extern void kdb_meminfo_proc_show(void); +#ifdef CONFIG_HUGETLB_PAGE +extern void kdb_hugetlb_report_meminfo(void); +#endif /* CONFIG_HUGETLB_PAGE */ +extern const char *kdb_walk_kallsyms(loff_t *pos); + + /* + * Architecture Dependant Local Processor setup & cleanup interfaces + */ +extern void kdba_local_arch_setup(void); +extern void kdba_local_arch_cleanup(void); + + /* + * Defines for kdb_symbol_print. + */ +#define KDB_SP_SPACEB 0x0001 /* Space before string */ +#define KDB_SP_SPACEA 0x0002 /* Space after string */ +#define KDB_SP_PAREN 0x0004 /* Parenthesis around string */ +#define KDB_SP_VALUE 0x0008 /* Print the value of the address */ +#define KDB_SP_SYMSIZE 0x0010 /* Print the size of the symbol */ +#define KDB_SP_NEWLINE 0x0020 /* Newline after string */ +#define KDB_SP_DEFAULT (KDB_SP_VALUE|KDB_SP_PAREN) + +/* Save data about running processes */ + +#if 0 +struct kdba_running_process { + long sp; /* KDB may be on a different stack */ + long ip; /* eip when esp was set */ +}; +#endif + +struct kdb_running_process { + struct task_struct *p; + struct pt_regs *regs; + int seqno; /* kdb sequence number */ + int irq_depth; /* irq count */ + /*struct kdba_running_process arch; */ /* arch dependent save data */ +}; + +extern struct kdb_running_process kdb_running_process[/* NR_CPUS */]; + +extern void kdb_save_running_cpu(struct pt_regs *, struct task_struct *, int); +extern int kdb_save_running(struct pt_regs *, kdb_reason_t, + kdb_reason_t, int, kdb_dbtrap_t); +extern void kdb_unsave_running(struct pt_regs *); +extern struct task_struct *kdb_curr_task(int); + +/* Incremented each time the main kdb loop is entered on the initial cpu, + * it gives some indication of how old the saved data is. + */ +extern int kdb_seqno; + +#define kdb_task_has_cpu(p) (task_curr(p)) +extern void kdb_runqueue(unsigned long cpu, kdb_printf_t xxx_printf); + +/* Simplify coexistence with NPTL */ +#define kdb_do_each_thread(g, p) do_each_thread(g, p) +#define kdb_while_each_thread(g, p) while_each_thread(g, p) + +#define GFP_KDB (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL) + +extern void *debug_kmalloc(size_t size, gfp_t flags); +extern void debug_kfree(void *); +extern void debug_kusage(void); + +extern void kdba_set_current_task(const struct task_struct *); +extern const struct task_struct *kdb_current_task; +extern struct pt_regs *kdb_current_regs; + +/* Functions to safely read and write kernel areas. The {to,from}_xxx + * addresses are not necessarily valid, these functions must check for + * validity. If the arch already supports get and put routines with suitable + * validation and/or recovery on invalid addresses then use those routines, + * otherwise check it yourself. + */ + +extern int kdba_putarea_size(unsigned long to_xxx, void *from, size_t size); +extern int kdba_getarea_size(void *to, unsigned long from_xxx, size_t size); +extern int kdba_verify_rw(unsigned long addr, size_t size); + +#ifndef KDB_RUNNING_PROCESS_ORIGINAL +#define KDB_RUNNING_PROCESS_ORIGINAL kdb_running_process +#endif + +extern int kdb_wait_for_cpus_secs; +extern void kdba_cpu_up(void); +extern char kdb_prompt_str[]; + +#define KDB_WORD_SIZE ((int)sizeof(kdb_machreg_t)) + +#ifdef CONFIG_KDB_USB +#include + +struct kdb_usb_kbd_info { + struct urb *urb; /* pointer to the URB */ + unsigned char *buffer; /* pointer to the kbd char buffer */ + int (*poll_func)(struct urb *urb); /* poll function to retrieve chars */ + int poll_ret; /* return val from poll_func */ + int caps_lock; /* state of the caps lock for this keyboard */ +}; +#endif /* CONFIG_KDB_USB */ + +#ifdef CONFIG_KDB_KDUMP +#define KDUMP_REASON_RESET 0 +extern void kdba_kdump_shutdown_slave(struct pt_regs *); +#endif /* CONFIG_KDB_KDUMP */ +#endif /* CONFIG_KGDB_KDB */ +#endif /* !_KDBPRIVATE_H */ diff --git a/init/main.c b/init/main.c index 3bbf93b..5b16c8b 100644 --- a/init/main.c +++ b/init/main.c @@ -62,6 +62,7 @@ #include #include #include +#include #include #include #include @@ -190,6 +191,26 @@ static const char *panic_later, *panic_param; extern struct obs_kernel_param __setup_start[], __setup_end[]; +#ifdef CONFIG_KGDB_KDB +static int __init kdb_setup(char *str) +{ + if (strcmp(str, "on") == 0) { + kdb_on = 1; + } else if (strcmp(str, "on-nokey") == 0) { + kdb_on = 2; + } else if (strcmp(str, "off") == 0) { + kdb_on = 0; + } else if (strcmp(str, "early") == 0) { + kdb_on = 1; + kdb_flags |= KDB_FLAG_EARLYKDB; + } else + printk(KERN_ERR "kdb flag %s not recognised\n", str); + return 0; +} + +__setup("kdb=", kdb_setup); +#endif /* CONFIG_KGDB_KDB */ + static int __init obsolete_checksetup(char *line) { struct obs_kernel_param *p; @@ -666,6 +687,11 @@ asmlinkage void __init start_kernel(void) pgtable_cache_init(); prio_tree_init(); anon_vma_init(); + +#ifdef CONFIG_KGDB_KDB + kdb_init(); +#endif /* CONFIG_KGDB_KDB */ + #ifdef CONFIG_X86 if (efi_enabled) efi_enter_virtual_mode(); diff --git a/kdb/.gitignore b/kdb/.gitignore new file mode 100644 index 0000000..396d12e --- /dev/null +++ b/kdb/.gitignore @@ -0,0 +1 @@ +gen-kdb_cmds.c diff --git a/kdb/Makefile b/kdb/Makefile new file mode 100644 index 0000000..6f67941 --- /dev/null +++ b/kdb/Makefile @@ -0,0 +1,48 @@ +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright (c) 1999-2004 Silicon Graphics, Inc. All Rights Reserved. +# + +EXTRA_CFLAGS += -O0 + +CCVERSION := $(shell $(CC) -v 2>&1 | sed -ne '$$p') +obj-y := kdb_io.o kdbmain.o kdbsupport.o kdb_bt.o gen-kdb_cmds.o kdb_bp.o +#obj-$(CONFIG_KDB_LXCRASH) += kdbdereference.o +# +#obj-y := kdb_bt.o kdb_bp.o kdb_id.o kdbsupport.o gen-kdb_cmds.o kdbmain.o kdb_io.o kdbdereference.o +#CFLAGS_kdbmain.o += -DCCVERSION="$(CCVERSION)" +# +#subdir-$(CONFIG_KDB_MODULES) := modules +#obj-y += $(addsuffix /built-in.o, $(subdir-y)) +# +clean-files := gen-kdb_cmds.c +# +#override CFLAGS := $(CFLAGS:%-pg=% ) +# +## define architecture dependent kdb_cmds +#ifeq ($(CONFIG_IA64),y) +# KDB_CMDS = ia64/kdb/kdb_cmds +#else +# ifeq ($(CONFIG_X86_64),y) +# KDB_CMDS = x86/kdb/kdb_cmds_64 +# else +# ifeq ($(CONFIG_X86_32),y) +# KDB_CMDS = x86/kdb/kdb_cmds_32 +# endif +# endif +#endif +# +quiet_cmd_gen-kdb = GENKDB $@ + cmd_gen-kdb = $(AWK) 'BEGIN {print "\#include "; print "\#include "} \ + /^\#/{next} \ + /^[ \t]*$$/{next} \ + {gsub(/"/, "\\\"", $$0); \ + print "static __initdata char kdb_cmd" cmds++ "[] = \"" $$0 "\\n\";"} \ + END {print "extern char *kdb_cmds[]; char __initdata *kdb_cmds[] = {"; for (i = 0; i < cmds; ++i) {print " kdb_cmd" i ","}; print(" NULL\n};");}' \ + $(filter-out %/Makefile,$^) > $@# + +$(obj)/gen-kdb_cmds.c: $(src)/kdb_cmds $(if $(KDB_CMDS),(wildcard $(TOPDIR)/arch/$(KDB_CMDS))) $(src)/Makefile + $(call cmd,gen-kdb) diff --git a/kdb/kdb_bp.c b/kdb/kdb_bp.c new file mode 100644 index 0000000..7f2264e --- /dev/null +++ b/kdb/kdb_bp.c @@ -0,0 +1,863 @@ +/* + * Kernel Debugger Architecture Independent Breakpoint Handler + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 1999-2004 Silicon Graphics, Inc. All Rights Reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Table of kdb_breakpoints + */ +kdb_bp_t kdb_breakpoints[KDB_MAXBPT]; + +/* HACK HACK HACK */ + +void kdba_setsinglestep(struct pt_regs *regs) +{ + KDB_STATE_SET(DOING_SS); +} + +void +kdba_alloc_hwbp(kdb_bp_t *bp, int *diagp) +{ +} + +void kdba_free_hwbp(kdb_bp_t *bp) +{ +} + +static char *kdba_rwtypes[] = { "Instruction(Register)", "Data Write", + "I/O", "Data Access"}; + +char *kdba_bptype(kdbhard_bp_t *bph) +{ + char *mode; + + mode = kdba_rwtypes[bph->bph_mode]; + + return mode; +} + +void +kdba_printbp(kdb_bp_t *bp) +{ + kdb_printf("\n is enabled"); +} + +int +kdba_parsebp(int argc, const char **argv, int *nextargp, kdb_bp_t *bp) +{ + int nextarg = *nextargp; + int diag; + kdbhard_bp_t *bph = &bp->bp_template; + + bph->bph_mode = 0; /* Default to instruction breakpoint */ + bph->bph_length = 0; /* Length must be zero for insn bp */ + if ((argc + 1) != nextarg) { + if (strnicmp(argv[nextarg], "datar", sizeof("datar")) == 0) + bph->bph_mode = 3; + else if (strnicmp(argv[nextarg], "dataw", sizeof("dataw")) == 0) + bph->bph_mode = 1; + else if (strnicmp(argv[nextarg], "io", sizeof("io")) == 0) + bph->bph_mode = 2; + else if (strnicmp(argv[nextarg], "inst", sizeof("inst")) == 0) + bph->bph_mode = 0; + else + return KDB_ARGCOUNT; + + bph->bph_length = 3; /* Default to 4 byte */ + + nextarg++; + + if ((argc + 1) != nextarg) { + unsigned long len; + + diag = kdbgetularg((char *)argv[nextarg], + &len); + if (diag) + return diag; + + + if ((len > 4) || (len == 3)) + return KDB_BADLENGTH; + + bph->bph_length = len; + bph->bph_length--; /* Normalize for debug register */ + nextarg++; + } + + if ((argc + 1) != nextarg) + return KDB_ARGCOUNT; + + /* + * Indicate to architecture independent level that + * a hardware register assignment is required to enable + * this breakpoint. + */ + + bph->bph_free = 0; + } else { + if (KDB_DEBUG(BP)) + kdb_printf("kdba_bp: no args, forcehw is %d\n", + bp->bp_forcehw); + if (bp->bp_forcehw) { + /* + * We are forced to use a hardware register for this + * breakpoint because either the bph or bpha + * commands were used to establish this breakpoint. + */ + bph->bph_free = 0; + } else { + /* + * Indicate to architecture dependent level that + * the instruction replacement breakpoint technique + * should be used for this breakpoint. + */ + bph->bph_free = 1; + bp->bp_adjust = 1; /* software, int 3 is one byte */ + } + } + + if (bph->bph_mode != 2 && + kdba_verify_rw(bp->bp_addr, bph->bph_length+1)) { + kdb_printf("Invalid address for breakpoint, " + "ignoring bp command\n"); + return KDB_BADADDR; + } + + *nextargp = nextarg; + return 0; +} + +int +kdba_removebp(kdb_bp_t *bp) +{ + int ret = 1; + if (!bp->bp_hardtype) { + if (bp->bp_installed) { + ret = kgdb_remove_sw_break(bp->bp_addr); + if (ret == 0) + bp->bp_installed = 0; + } + } + return ret; +} + +static void +kdba_handle_bp(struct pt_regs *regs, kdb_bp_t *bp) +{ + if (KDB_NULL_REGS(regs)) + return; + + if (KDB_DEBUG(BP)) + kdb_printf("regs->ip = 0x%lx\n", instruction_pointer(regs)); + + /* + * Setup single step + */ + kdba_setsinglestep(regs); + + /* + * Reset delay attribute + */ + bp->bp_delay = 0; + bp->bp_delayed = 1; +} + +int +kdba_installbp(struct pt_regs *regs, kdb_bp_t *bp) +{ + /* + * Install the breakpoint, if it is not already installed. + */ + + if (KDB_DEBUG(BP)) + kdb_printf("kdba_installbp bp_installed %d\n", + bp->bp_installed); + if (!KDB_STATE(SSBPT)) + bp->bp_delay = 0; + + if (!bp->bp_hardtype && !bp->bp_installed) { + if (bp->bp_delay || (bp->bp_delayed && KDB_STATE(DOING_SS))) { + if (KDB_DEBUG(BP)) + kdb_printf("kdba_installbp delayed bp\n"); + kdba_handle_bp(regs, bp); + } else { + if (kgdb_set_sw_break(bp->bp_addr) == 0) { + bp->bp_installed = 1; + } else { + kdb_printf("kdba_installbp failed to set " + "software breakpoint at 0x%lx\n", + bp->bp_addr); + return 1; + } + } + return 0; + } + return 1; +} +int +kdba_verify_rw(unsigned long addr, size_t size) +{ + unsigned char data[size]; + return kdb_getarea_size(data, addr, size) || + kdb_putarea_size(addr, data, size); +} + +/* END HACK HACK HACK */ + +/* + * Predicate to test whether a breakpoint should be installed + * on this CPU. + * + * Note that for purposes of installation, hardware breakpoints + * are treated as local (even if the global flag is set), on + * the assumption that the require per-cpu registers to be set. + */ + +static inline int kdb_is_installable_global_bp(const kdb_bp_t *bp) +{ + return bp->bp_enabled && + bp->bp_global && + !bp->bp_forcehw; +} + +static int kdb_is_installable_local_bp(const kdb_bp_t *bp) +{ + if (!bp->bp_enabled) + return 0; + + if (bp->bp_forcehw) { + if (bp->bp_cpu == smp_processor_id() || bp->bp_global) + return 1; + } else { + if (bp->bp_cpu == smp_processor_id() && !bp->bp_global) + return 1; + } + return 0; +} + +/* + * kdb_bp_install_global + * + * Install global kdb_breakpoints prior to returning from the + * kernel debugger. This allows the kdb_breakpoints to be set + * upon functions that are used internally by kdb, such as + * printk(). + * + * Parameters: + * regs Execution frame. + * Outputs: + * None. + * Returns: + * None. + * Locking: + * None. + * Remarks: + * + * This function is only called once per kdb session. + */ + +void +kdb_bp_install_global(struct pt_regs *regs) +{ + int i; + + for (i = 0; i < KDB_MAXBPT; i++) { + kdb_bp_t *bp = &kdb_breakpoints[i]; + + if (KDB_DEBUG(BP)) { + kdb_printf("kdb_bp_install_global bp %d " + "bp_enabled %d bp_global %d\n", + i, bp->bp_enabled, bp->bp_global); + } + /* HW BP local or global are installed in kdb_bp_install_local*/ + if (kdb_is_installable_global_bp(bp)) + kdba_installbp(regs, bp); + } +} + +/* + * kdb_bp_install_local + * + * Install local kdb_breakpoints prior to returning from the + * kernel debugger. This allows the kdb_breakpoints to be set + * upon functions that are used internally by kdb, such as + * printk(). + * + * Parameters: + * regs Execution frame. + * Outputs: + * None. + * Returns: + * None. + * Locking: + * None. + * Remarks: + * + * This function is called once per processor. + */ + +void +kdb_bp_install_local(struct pt_regs *regs) +{ + int i; + + for (i = 0; i < KDB_MAXBPT; i++) { + kdb_bp_t *bp = &kdb_breakpoints[i]; + + if (KDB_DEBUG(BP)) { + kdb_printf("kdb_bp_install_local bp %d bp_enabled " + "%d bp_global %d cpu %d bp_cpu %d\n", + i, bp->bp_enabled, bp->bp_global, + smp_processor_id(), bp->bp_cpu); + } + if (kdb_is_installable_local_bp(bp)) + kdba_installbp(regs, bp); + } +} + +/* + * kdb_bp_remove_global + * + * Remove global kdb_breakpoints upon entry to the kernel debugger. + * + * Parameters: + * None. + * Outputs: + * None. + * Returns: + * None. + * Locking: + * None. + * Remarks: + */ + +void +kdb_bp_remove_global(void) +{ + int i; + + for (i = KDB_MAXBPT - 1; i >= 0; i--) { + kdb_bp_t *bp = &kdb_breakpoints[i]; + + if (KDB_DEBUG(BP)) { + kdb_printf("kdb_bp_remove_global bp %d bp_enabled " + "%d bp_global %d\n", + i, bp->bp_enabled, bp->bp_global); + } + if (kdb_is_installable_global_bp(bp)) + kdba_removebp(bp); + } +} + + +/* + * kdb_bp_remove_local + * + * Remove local kdb_breakpoints upon entry to the kernel debugger. + * + * Parameters: + * None. + * Outputs: + * None. + * Returns: + * None. + * Locking: + * None. + * Remarks: + */ + +void +kdb_bp_remove_local(void) +{ + int i; + + for (i = KDB_MAXBPT - 1; i >= 0; i--) { + kdb_bp_t *bp = &kdb_breakpoints[i]; + + if (KDB_DEBUG(BP)) { + kdb_printf("kdb_bp_remove_local bp %d bp_enabled " + "%d bp_global %d cpu %d bp_cpu %d\n", + i, bp->bp_enabled, bp->bp_global, + smp_processor_id(), bp->bp_cpu); + } + if (kdb_is_installable_local_bp(bp)) + kdba_removebp(bp); + } +} + +/* + * kdb_printbp + * + * Internal function to format and print a breakpoint entry. + * + * Parameters: + * None. + * Outputs: + * None. + * Returns: + * None. + * Locking: + * None. + * Remarks: + */ + +static void +kdb_printbp(kdb_bp_t *bp, int i) +{ + if (bp->bp_forcehw) + kdb_printf("Forced "); + + if (!bp->bp_template.bph_free) + kdb_printf("%s ", kdba_bptype(&bp->bp_template)); + else + kdb_printf("Instruction(i) "); + + kdb_printf("BP #%d at ", i); + kdb_symbol_print(bp->bp_addr, NULL, KDB_SP_DEFAULT); + + if (bp->bp_enabled) { + kdba_printbp(bp); + if (bp->bp_global) + kdb_printf(" globally"); + else + kdb_printf(" on cpu %d", bp->bp_cpu); + if (bp->bp_adjust) + kdb_printf(" adjust %d", bp->bp_adjust); + } else { + kdb_printf("\n is disabled"); + } + + kdb_printf("\taddr at %016lx, hardtype=%d, forcehw=%d, " + "installed=%d, hard=%p\n", + bp->bp_addr, bp->bp_hardtype, bp->bp_forcehw, + bp->bp_installed, bp->bp_hard); + + kdb_printf("\n"); +} + +/* + * kdb_bp + * + * Handle the bp, and bpa commands. + * + * [bp|bpa|bph] [DATAR|DATAW|IO [length]] + * + * Parameters: + * argc Count of arguments in argv + * argv Space delimited command line arguments + * Outputs: + * None. + * Returns: + * Zero for success, a kdb diagnostic if failure. + * Locking: + * None. + * Remarks: + * + * bp Set breakpoint. Only use hardware assist if necessary. + * bpa Set breakpoint on all cpus, only use hardware regs if necessary + * bph Set breakpoint - force hardware register + * bpha Set breakpoint on all cpus, force hardware register + */ + +static int +kdb_bp(int argc, const char **argv) +{ + int i, bpno; + kdb_bp_t *bp, *bp_check; + int diag; + int free; + char *symname = NULL; + long offset = 0ul; + int nextarg; + kdb_bp_t template = {0}; + + if (argc == 0) { + /* + * Display breakpoint table + */ + for (bpno = 0, bp = kdb_breakpoints; bpno < KDB_MAXBPT; + bpno++, bp++) { + if (bp->bp_free) + continue; + kdb_printbp(bp, bpno); + } + + return 0; + } + + template.bp_global = ((strcmp(argv[0], "bpa") == 0) + || (strcmp(argv[0], "bpha") == 0)); + template.bp_forcehw = ((strcmp(argv[0], "bph") == 0) + || (strcmp(argv[0], "bpha") == 0)); + + /* Fix me: "bp" is treated as "bpa" to avoid system freeze. -jlan */ + if (strcmp(argv[0], "bp") == 0) + template.bp_global = 1; + + nextarg = 1; + diag = kdbgetaddrarg(argc, argv, &nextarg, &template.bp_addr, + &offset, &symname); + if (diag) + return diag; + if (!template.bp_addr) + return KDB_BADINT; + + /* + * Find an empty bp structure, to allocate + */ + free = KDB_MAXBPT; + for (bpno = 0, bp = kdb_breakpoints; bpno < KDB_MAXBPT; bpno++, bp++) { + if (bp->bp_free) + break; + } + + if (bpno == KDB_MAXBPT) + return KDB_TOOMANYBPT; + + /* + * Handle architecture dependent parsing + */ + diag = kdba_parsebp(argc, argv, &nextarg, &template); + if (diag) + return diag; + + /* + * Check for clashing breakpoints. + * + * Note, in this design we can't have hardware breakpoints + * enabled for both read and write on the same address, even + * though ia64 allows this. + */ + for (i = 0, bp_check = kdb_breakpoints; i < KDB_MAXBPT; + i++, bp_check++) { + if (!bp_check->bp_free && + bp_check->bp_addr == template.bp_addr && + (bp_check->bp_global || + bp_check->bp_cpu == template.bp_cpu)) { + kdb_printf("You already have a breakpoint at " + kdb_bfd_vma_fmt0 "\n", template.bp_addr); + return KDB_DUPBPT; + } + } + + template.bp_enabled = 1; + + /* + * Actually allocate the breakpoint found earlier + */ + *bp = template; + bp->bp_free = 0; + + if (!bp->bp_global) + bp->bp_cpu = smp_processor_id(); + + /* + * Allocate a hardware breakpoint. If one is not available, + * disable the breakpoint, but leave it in the breakpoint + * table. When the breakpoint is re-enabled (via 'be'), we'll + * attempt to allocate a hardware register for it. + */ + if (!bp->bp_template.bph_free) { + kdba_alloc_hwbp(bp, &diag); + if (diag) { + bp->bp_enabled = 0; + bp->bp_hardtype = 0; + kdba_free_hwbp(bp); + return diag; + } + } + + kdb_printbp(bp, bpno); + + return 0; +} + +/* + * kdb_bc + * + * Handles the 'bc', 'be', and 'bd' commands + * + * [bd|bc|be] + * [bd|bc|be] * + * + * Parameters: + * argc Count of arguments in argv + * argv Space delimited command line arguments + * Outputs: + * None. + * Returns: + * Zero for success, a kdb diagnostic for failure + * Locking: + * None. + * Remarks: + */ + +#define KDBCMD_BC 0 +#define KDBCMD_BE 1 +#define KDBCMD_BD 2 + +static int +kdb_bc(int argc, const char **argv) +{ + kdb_machreg_t addr; + kdb_bp_t *bp = NULL; + int lowbp = KDB_MAXBPT; + int highbp = 0; + int done = 0; + int i; + int diag = 0; + int cmd; /* KDBCMD_B? */ + + if (strcmp(argv[0], "be") == 0) + cmd = KDBCMD_BE; + else if (strcmp(argv[0], "bd") == 0) + cmd = KDBCMD_BD; + else + cmd = KDBCMD_BC; + + if (argc != 1) + return KDB_ARGCOUNT; + + if (strcmp(argv[1], "*") == 0) { + lowbp = 0; + highbp = KDB_MAXBPT; + } else { + diag = kdbgetularg(argv[1], &addr); + if (diag) + return diag; + + /* + * For addresses less than the maximum breakpoint number, + * assume that the breakpoint number is desired. + */ + if (addr < KDB_MAXBPT) { + bp = &kdb_breakpoints[addr]; + lowbp = highbp = addr; + highbp++; + } else { + for (i = 0, bp = kdb_breakpoints; i < KDB_MAXBPT; + i++, bp++) { + if (bp->bp_addr == addr) { + lowbp = highbp = i; + highbp++; + break; + } + } + } + } + + /* + * Now operate on the set of breakpoints matching the input + * criteria (either '*' for all, or an individual breakpoint). + */ + for (bp = &kdb_breakpoints[lowbp], i = lowbp; + i < highbp; + i++, bp++) { + if (bp->bp_free) + continue; + + done++; + + switch (cmd) { + case KDBCMD_BC: + if (bp->bp_hardtype) + kdba_free_hwbp(bp); + + bp->bp_enabled = 0; + bp->bp_global = 0; + + kdb_printf("Breakpoint %d at " + kdb_bfd_vma_fmt " cleared\n", + i, bp->bp_addr); + + bp->bp_addr = 0; + bp->bp_free = 1; + + break; + case KDBCMD_BE: + /* + * Allocate a hardware breakpoint. If one is not + * available, don't enable the breakpoint. + */ + if (!bp->bp_template.bph_free + && !bp->bp_hardtype) { + kdba_alloc_hwbp(bp, &diag); + if (diag) { + bp->bp_enabled = 0; + bp->bp_hardtype = 0; + kdba_free_hwbp(bp); + return diag; + } + } + + bp->bp_enabled = 1; + + kdb_printf("Breakpoint %d at " + kdb_bfd_vma_fmt " enabled", + i, bp->bp_addr); + + kdb_printf("\n"); + break; + case KDBCMD_BD: + if (!bp->bp_enabled) + break; + + /* + * Since this breakpoint is now disabled, we can + * give up the hardware register which is allocated + * to it. + */ + if (bp->bp_hardtype) + kdba_free_hwbp(bp); + + bp->bp_enabled = 0; + + kdb_printf("Breakpoint %d at " + kdb_bfd_vma_fmt " disabled\n", + i, bp->bp_addr); + + break; + } + if (bp->bp_delay && (cmd == KDBCMD_BC || cmd == KDBCMD_BD)) { + bp->bp_delay = 0; + KDB_STATE_CLEAR(SSBPT); + } + } + + return (!done) ? KDB_BPTNOTFOUND : 0; +} + +/* + * kdb_ss + * + * Process the 'ss' (Single Step) and 'ssb' (Single Step to Branch) + * commands. + * + * ss + * ssb + * + * Parameters: + * argc Argument count + * argv Argument vector + * Outputs: + * None. + * Returns: + * KDB_CMD_SS[B] for success, a kdb error if failure. + * Locking: + * None. + * Remarks: + * + * Set the arch specific option to trigger a debug trap after the next + * instruction. + * + * For 'ssb', set the trace flag in the debug trap handler + * after printing the current insn and return directly without + * invoking the kdb command processor, until a branch instruction + * is encountered. + */ + +static int +kdb_ss(int argc, const char **argv) +{ + int ssb = 0; + // HACK HACK HACK no need to exec the get_irq_regs() with kgdb + // struct pt_regs *regs = get_irq_regs(); + + ssb = (strcmp(argv[0], "ssb") == 0); + if (argc != 0) + return KDB_ARGCOUNT; + + // if (!regs) { + // kdb_printf("%s: pt_regs not available\n", __FUNCTION__); + // return KDB_BADREG; + // } + + /* + * Set trace flag and go. + */ + KDB_STATE_SET(DOING_SS); + if (ssb) + KDB_STATE_SET(DOING_SSB); + + // kdba_setsinglestep(regs); /* Enable single step */ + + if (ssb) + return KDB_CMD_SSB; + return KDB_CMD_SS; +} + +/* + * kdb_initbptab + * + * Initialize the breakpoint table. Register breakpoint commands. + * + * Parameters: + * None. + * Outputs: + * None. + * Returns: + * None. + * Locking: + * None. + * Remarks: + */ + +void __init +kdb_initbptab(void) +{ + int i; + kdb_bp_t *bp; + + /* + * First time initialization. + */ + memset(&kdb_breakpoints, '\0', sizeof(kdb_breakpoints)); + + for (i = 0, bp = kdb_breakpoints; i < KDB_MAXBPT; i++, bp++) { + bp->bp_free = 1; + /* + * The bph_free flag is architecturally required. It + * is set by architecture-dependent code to false (zero) + * in the event a hardware breakpoint register is required + * for this breakpoint. + * + * The rest of the template is reserved to the architecture + * dependent code and _must_ not be touched by the architecture + * independent code. + */ + bp->bp_template.bph_free = 1; + } + + kdb_register_repeat("bp", kdb_bp, "[]", "Set/Display breakpoints", 0, KDB_REPEAT_NO_ARGS); + kdb_register_repeat("bl", kdb_bp, "[]", "Display breakpoints", 0, KDB_REPEAT_NO_ARGS); + kdb_register_repeat("bpa", kdb_bp, "[]", "Set/Display global breakpoints", 0, KDB_REPEAT_NO_ARGS); +#if 0 /* temporarily not supported */ + kdb_register_repeat("bph", kdb_bp, "[]", "Set hardware breakpoint", 0, KDB_REPEAT_NO_ARGS); + kdb_register_repeat("bpha", kdb_bp, "[]", "Set global hardware breakpoint", 0, KDB_REPEAT_NO_ARGS); +#endif + kdb_register_repeat("bc", kdb_bc, "", "Clear Breakpoint", 0, KDB_REPEAT_NONE); + kdb_register_repeat("be", kdb_bc, "", "Enable Breakpoint", 0, KDB_REPEAT_NONE); + kdb_register_repeat("bd", kdb_bc, "", "Disable Breakpoint", 0, KDB_REPEAT_NONE); + + kdb_register_repeat("ss", kdb_ss, "", "Single Step", 1, KDB_REPEAT_NO_ARGS); + kdb_register_repeat("ssb", kdb_ss, "", "Single step to branch/call", 0, KDB_REPEAT_NO_ARGS); + /* + * Architecture dependent initialization. + */ +} diff --git a/kdb/kdb_bt.c b/kdb/kdb_bt.c new file mode 100644 index 0000000..80d9665 --- /dev/null +++ b/kdb/kdb_bt.c @@ -0,0 +1,209 @@ +/* + * Kernel Debugger Architecture Independent Stack Traceback + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 1999-2004 Silicon Graphics, Inc. All Rights Reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + * kdb_bt + * + * This function implements the 'bt' command. Print a stack + * traceback. + * + * bt [] (addr-exp is for alternate stacks) + * btp Kernel stack for + * btt Kernel stack for task structure at + * + * bta [DRSTCZEUIMA] All useful processes, optionally + * filtered by state + * btc [] The current process on one cpu, + * default is all cpus + * + * bt refers to a address on the stack, that location + * is assumed to contain a return address. + * + * btt refers to the address of a struct task. + * + * Inputs: + * argc argument count + * argv argument vector + * Outputs: + * None. + * Returns: + * zero for success, a kdb diagnostic if error + * Locking: + * none. + * Remarks: + * Backtrack works best when the code uses frame pointers. But even + * without frame pointers we should get a reasonable trace. + * + * mds comes in handy when examining the stack to do a manual traceback or + * to get a starting point for bt . + */ + +static int +kdb_bt1(const struct task_struct *p, unsigned long mask, + int argcount, int btaprompt) +{ + // int diag; + char buffer[2]; + if (kdb_getarea(buffer[0], (unsigned long)p) || + kdb_getarea(buffer[0], (unsigned long)(p+1)-1)) + return KDB_BADADDR; + if (!kdb_task_state(p, mask)) + return 0; + kdb_printf("Stack traceback for pid %d\n", p->pid); + kdb_ps1(p); + //diag = kdba_bt_process(p, argcount); + { + int old_lvl = console_loglevel; + console_loglevel = 15; + kdba_set_current_task(p); + if (kdb_current_regs) { + // HACK HACK HACK below, this needs to be fixed to be + // architecture independent + // But this is a poof of concept for now... +#ifdef CONFIG_X86 + show_stack((struct task_struct *)p, + &kdb_current_regs->sp); +#else + show_stack((struct task_struct *)p, 0); +#endif + } else { + show_stack((struct task_struct *)p, 0); + } + console_loglevel = old_lvl; + } + // HACK HACK HACK + if (btaprompt) { + kdb_getstr(buffer, sizeof(buffer), + "Enter to end, to continue:"); + if (buffer[0] == 'q') { + kdb_printf("\n"); + return 1; + } + } + touch_nmi_watchdog(); + return 0; +} + +int +kdb_bt(int argc, const char **argv) +{ + int diag; + int argcount = 5; + int btaprompt = 1; + int nextarg; + unsigned long addr; + long offset; + + kdbgetintenv("BTARGS", &argcount); /* Arguments to print */ + kdbgetintenv("BTAPROMPT", &btaprompt); /* Prompt after each + * proc in bta */ + + if (strcmp(argv[0], "bta") == 0) { + struct task_struct *g, *p; + unsigned long cpu; + unsigned long mask = kdb_task_state_string(argc ? argv[1] : + NULL); + if (argc == 0) + kdb_ps_suppressed(); + /* Run the active tasks first */ + for (cpu = 0; cpu < NR_CPUS; ++cpu) { + if (!cpu_online(cpu)) + continue; + p = kdb_curr_task(cpu); + if (kdb_bt1(p, mask, argcount, btaprompt)) + return 0; + } + /* Now the inactive tasks */ + kdb_do_each_thread(g, p) { + if (task_curr(p)) + continue; + if (kdb_bt1(p, mask, argcount, btaprompt)) + return 0; + } kdb_while_each_thread(g, p); + } else if (strcmp(argv[0], "btp") == 0) { + struct task_struct *p; + unsigned long pid; + if (argc != 1) + return KDB_ARGCOUNT; + if ((diag = kdbgetularg((char *)argv[1], &pid))) + return diag; + if ((p = find_task_by_pid_type_ns(PIDTYPE_PID, pid, &init_pid_ns))) { + kdba_set_current_task(p); + return kdb_bt1(p, ~0UL, argcount, 0); + } + kdb_printf("No process with pid == %ld found\n", pid); + return 0; + } else if (strcmp(argv[0], "btt") == 0) { + if (argc != 1) + return KDB_ARGCOUNT; + if ((diag = kdbgetularg((char *)argv[1], &addr))) + return diag; + kdba_set_current_task((struct task_struct *)addr); + return kdb_bt1((struct task_struct *)addr, ~0UL, argcount, 0); + } else if (strcmp(argv[0], "btc") == 0) { + unsigned long cpu = ~0; + struct kdb_running_process *krp; + const struct task_struct *save_current_task = kdb_current_task; + char buf[80]; + if (argc > 1) + return KDB_ARGCOUNT; + if (argc == 1 && (diag = kdbgetularg((char *)argv[1], &cpu))) + return diag; + /* Recursive use of kdb_parse, do not use argv after this point */ + argv = NULL; + if (cpu != ~0) { + krp = kdb_running_process + cpu; + if (cpu >= NR_CPUS || !krp->seqno || !cpu_online(cpu)) { + kdb_printf("no process for cpu %ld\n", cpu); + return 0; + } + sprintf(buf, "btt 0x%p\n", krp->p); + kdb_parse(buf); + return 0; + } + kdb_printf("btc: cpu status: "); + kdb_parse("cpu\n"); + for (cpu = 0, krp = kdb_running_process; cpu < NR_CPUS; ++cpu, ++krp) { + if (!cpu_online(cpu) || !krp->seqno) + continue; + sprintf(buf, "btt 0x%p\n", krp->p); + kdb_parse(buf); + touch_nmi_watchdog(); + } + kdba_set_current_task(save_current_task); + return 0; + } else { + if (argc) { + nextarg = 1; + diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, + &offset, NULL); + if (diag) + return diag; + // return kdba_bt_address(addr, argcount); + // HACK HACK HACK + return 0; + } else { + return kdb_bt1(kdb_current_task, ~0UL, argcount, 0); + } + } + + /* NOTREACHED */ + return 0; +} diff --git a/kdb/kdb_cmds b/kdb/kdb_cmds new file mode 100644 index 0000000..343955c --- /dev/null +++ b/kdb/kdb_cmds @@ -0,0 +1,32 @@ +# Initial commands for kdb, alter to suit your needs. +# These commands are executed in kdb_init() context, no SMP, no +# processes. Commands that require process data (including stack or +# registers) are not reliable this early. set and bp commands should +# be safe. Global breakpoint commands affect each cpu as it is booted. + +# Standard debugging information for first level support, just type archkdb +# or archkdbcpu or archkdbshort at the kdb prompt. + +defcmd archkdb "" "First line arch debugging" + set BTSYMARG 1 + set BTARGS 9 + pid R + -archkdbcommon + -bta +endefcmd + +defcmd archkdbcpu "" "archkdb with only tasks on cpus" + set BTSYMARG 1 + set BTARGS 9 + pid R + -archkdbcommon + -btc +endefcmd + +defcmd archkdbshort "" "archkdb with less detailed backtrace" + set BTSYMARG 0 + set BTARGS 0 + pid R + -archkdbcommon + -bta +endefcmd diff --git a/kdb/kdb_io.c b/kdb/kdb_io.c new file mode 100644 index 0000000..e7c3b40 --- /dev/null +++ b/kdb/kdb_io.c @@ -0,0 +1,890 @@ +/* + * Kernel Debugger Architecture Independent Console I/O handler + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 1999-2006 Silicon Graphics, Inc. All Rights Reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static struct console *kdbcons; + +#ifdef CONFIG_PPC64 +#include +#endif + +#define CMD_BUFLEN 256 +char kdb_prompt_str[CMD_BUFLEN]; + +extern int kdb_grepping_flag; +extern char kdb_grep_string[]; +extern int kdb_grep_leading; +extern int kdb_grep_trailing; +extern int kdb_get_kbd_char(void); + +/* + * kdb_read + * + * This function reads a string of characters, terminated by + * a newline, or by reaching the end of the supplied buffer, + * from the current kernel debugger console device. + * Parameters: + * buffer - Address of character buffer to receive input characters. + * bufsize - size, in bytes, of the character buffer + * Returns: + * Returns a pointer to the buffer containing the received + * character string. This string will be terminated by a + * newline character. + * Locking: + * No locks are required to be held upon entry to this + * function. It is not reentrant - it relies on the fact + * that while kdb is running on any one processor all other + * processors will be spinning at the kdb barrier. + * Remarks: + * + * Davidm asks, why doesn't kdb use the console abstraction; + * here are some reasons: + * - you cannot debug the console abstraction with kdb if + * kdb uses it. + * - you rely on the correct functioning of the abstraction + * in the presence of general system failures. + * - You must acquire the console spinlock thus restricting + * the usability - what if the kernel fails with the spinlock + * held - one still wishes to debug such situations. + * - How about debugging before the console(s) are registered? + * - None of the current consoles (sercons, vt_console_driver) + * have read functions defined. + * - The standard pc keyboard and terminal drivers are interrupt + * driven. We cannot enable interrupts while kdb is active, + * so the standard input functions cannot be used by kdb. + * + * An implementation could be improved by removing the need for + * lock acquisition - just keep a 'struct console *kdbconsole;' global + * variable which refers to the preferred kdb console. + * + * The bulk of this function is architecture dependent. + * + * The buffer size must be >= 2. A buffer size of 2 means that the caller only + * wants a single key. + * + * An escape key could be the start of a vt100 control sequence such as \e[D + * (left arrow) or it could be a character in its own right. The standard + * method for detecting the difference is to wait for 2 seconds to see if there + * are any other characters. kdb is complicated by the lack of a timer service + * (interrupts are off), by multiple input sources and by the need to sometimes + * return after just one key. Escape sequence processing has to be done as + * states in the polling loop. + */ + +char * +kdb_read(char *buffer, size_t bufsize) +{ + char *cp = buffer; + char *bufend = buffer+bufsize-2; /* Reserve space for newline + * and null byte */ + char *lastchar; + char *p_tmp; + char tmp; + static char tmpbuffer[CMD_BUFLEN]; + int len = strlen(buffer); + int len_tmp; + int tab = 0; + int count; + int i; + int diag, dtab_count; + +#define ESCAPE_UDELAY 1000 +#define ESCAPE_DELAY 2*1000000/ESCAPE_UDELAY /* 2 seconds worth of udelays */ + char escape_data[5]; /* longest vt100 escape sequence is 4 bytes */ + char *ped = escape_data; + int escape_delay = 0; + get_char_func *f, *f_escape = NULL; + + diag = kdbgetintenv("DTABCOUNT", &dtab_count); + if (diag) + dtab_count = 30; + + if (len > 0) { + cp += len; + if (*(buffer+len-1) == '\n') + cp--; + } + + lastchar = cp; + *cp = '\0'; + kdb_printf("%s", buffer); + + for (;;) { + int key; + for (f = &kdb_poll_funcs[0]; ; ++f) { + if (*f == NULL) { + /* Reset NMI watchdog once per poll loop */ + touch_nmi_watchdog(); + f = &kdb_poll_funcs[0]; + } + if (escape_delay == 2) { + *ped = '\0'; + ped = escape_data; + --escape_delay; + } + if (escape_delay == 1) { + key = *ped++; + if (!*ped) + --escape_delay; + break; + } + key = (*f)(); + if (key == -1) { + if (escape_delay) { + udelay(ESCAPE_UDELAY); + --escape_delay; + } + continue; + } + if (bufsize <= 2) { + if (key == '\r') + key = '\n'; + kdb_printf("%c", key); + *buffer++ = key; + *buffer = '\0'; + return buffer; + } + if (escape_delay == 0 && key == '\e') { + escape_delay = ESCAPE_DELAY; + ped = escape_data; + f_escape = f; + } + if (escape_delay) { + *ped++ = key; + if (f_escape != f) { + escape_delay = 2; + continue; + } + if (ped - escape_data == 1) { + /* \e */ + continue; + } else if (ped - escape_data == 2) { + /* \e */ + if (key != '[') + escape_delay = 2; + continue; + } else if (ped - escape_data == 3) { + /* \e[ */ + int mapkey = 0; + switch (key) { + /* \e[A, up arrow */ + case 'A': mapkey = 16; break; + /* \e[B, down arrow */ + case 'B': mapkey = 14; break; + /* \e[C, right arrow */ + case 'C': mapkey = 6; break; + /* \e[D, left arrow */ + case 'D': mapkey = 2; break; + case '1': /* dropthrough */ + case '3': /* dropthrough */ + /* \e[<1,3,4>], may be home, del, end */ + case '4': mapkey = -1; break; + } + if (mapkey != -1) { + if (mapkey > 0) { + escape_data[0] = mapkey; + escape_data[1] = '\0'; + } + escape_delay = 2; + } + continue; + } else if (ped - escape_data == 4) { + /* \e[<1,3,4> */ + int mapkey = 0; + if (key == '~') { + switch (escape_data[2]) { + /* \e[1~, home */ + case '1': mapkey = 1; break; + /* \e[3~, del */ + case '3': mapkey = 4; break; + /* \e[4~, end */ + case '4': mapkey = 5; break; + } + } + if (mapkey > 0) { + escape_data[0] = mapkey; + escape_data[1] = '\0'; + } + escape_delay = 2; + continue; + } + } + break; /* A key to process */ + } + + if (key != 9) + tab = 0; + switch (key) { + case 8: /* backspace */ + if (cp > buffer) { + if (cp < lastchar) { + memcpy(tmpbuffer, cp, lastchar - cp); + memcpy(cp-1, tmpbuffer, lastchar - cp); + } + *(--lastchar) = '\0'; + --cp; + kdb_printf("\b%s \r", cp); + tmp = *cp; + *cp = '\0'; + kdb_printf(kdb_prompt_str); + kdb_printf("%s", buffer); + *cp = tmp; + } + break; + case 13: /* enter */ + *lastchar++ = '\n'; + *lastchar++ = '\0'; + kdb_printf("\n"); + return buffer; + case 4: /* Del */ + if (cp < lastchar) { + memcpy(tmpbuffer, cp+1, lastchar - cp - 1); + memcpy(cp, tmpbuffer, lastchar - cp - 1); + *(--lastchar) = '\0'; + kdb_printf("%s \r", cp); + tmp = *cp; + *cp = '\0'; + kdb_printf(kdb_prompt_str); + kdb_printf("%s", buffer); + *cp = tmp; + } + break; + case 1: /* Home */ + if (cp > buffer) { + kdb_printf("\r"); + kdb_printf(kdb_prompt_str); + cp = buffer; + } + break; + case 5: /* End */ + if (cp < lastchar) { + kdb_printf("%s", cp); + cp = lastchar; + } + break; + case 2: /* Left */ + if (cp > buffer) { + kdb_printf("\b"); + --cp; + } + break; + case 14: /* Down */ + memset(tmpbuffer, ' ', + strlen(kdb_prompt_str) + (lastchar-buffer)); + *(tmpbuffer+strlen(kdb_prompt_str) + + (lastchar-buffer)) = '\0'; + kdb_printf("\r%s\r", tmpbuffer); + *lastchar = (char)key; + *(lastchar+1) = '\0'; + return lastchar; + case 6: /* Right */ + if (cp < lastchar) { + kdb_printf("%c", *cp); + ++cp; + } + break; + case 16: /* Up */ + memset(tmpbuffer, ' ', + strlen(kdb_prompt_str) + (lastchar-buffer)); + *(tmpbuffer+strlen(kdb_prompt_str) + + (lastchar-buffer)) = '\0'; + kdb_printf("\r%s\r", tmpbuffer); + *lastchar = (char)key; + *(lastchar+1) = '\0'; + return lastchar; + case 9: /* Tab */ + if (tab < 2) + ++tab; + p_tmp = buffer; + while (*p_tmp == ' ') + p_tmp++; + if (p_tmp <= cp) { + memcpy(tmpbuffer, p_tmp, cp-p_tmp); + *(tmpbuffer + (cp-p_tmp)) = '\0'; + p_tmp = strrchr(tmpbuffer, ' '); + if (p_tmp) + ++p_tmp; + else + p_tmp = tmpbuffer; + len = strlen(p_tmp); + count = kallsyms_symbol_complete(p_tmp, + sizeof(tmpbuffer) - + (p_tmp - tmpbuffer)); + if (tab == 2) { + if (count > 0) { + kdb_printf("\n%d symbols are found.", count); + if(count>dtab_count) { + count=dtab_count; + kdb_printf(" But only first %d symbols will be printed.\nYou can change the environment variable DTABCOUNT.", count); + } + kdb_printf("\n"); + for(i=0;i=dtab_count)kdb_printf("..."); + kdb_printf("\n"); + kdb_printf(kdb_prompt_str); + kdb_printf("%s", buffer); + } + } + else { + if (count > 0) { + len_tmp = strlen(p_tmp); + strncpy(p_tmp+len_tmp,cp, lastchar-cp+1); + len_tmp = strlen(p_tmp); + strncpy(cp, p_tmp+len, len_tmp-len+1); + len = len_tmp - len; + kdb_printf("%s", cp); + cp+=len; + lastchar+=len; + } + } + kdb_nextline = 1; /* reset output line number */ + } + break; + default: + if (key >= 32 &&lastchar < bufend) { + if (cp < lastchar) { + memcpy(tmpbuffer, cp, lastchar - cp); + memcpy(cp+1, tmpbuffer, lastchar - cp); + *++lastchar = '\0'; + *cp = key; + kdb_printf("%s\r", cp); + ++cp; + tmp = *cp; + *cp = '\0'; + kdb_printf(kdb_prompt_str); + kdb_printf("%s", buffer); + *cp = tmp; + } else { + *++lastchar = '\0'; + *cp++ = key; + /* Hide printed characters if we think that kgdb is connecting */ + if (!KDB_STATE(KGDB_TRANS)) { + int len = strlen(buffer); + if (strncmp(buffer,"$?#3f",len) != 0 && + strncmp(buffer,"$qSupported#37",len) != 0 && + strncmp(buffer,"+$qSupported#37",len) != 0) { + KDB_STATE_SET(KGDB_TRANS); + kdb_printf("%s",buffer); + } + } else { + kdb_printf("%c", key); + } + } + /* Special escape to kgdb */ + if (lastchar - buffer >= 5 && strcmp(lastchar - 5, "$?#3f") == 0) { + strcpy(buffer,"kgdb"); + KDB_STATE_SET(DOING_KGDB); + return buffer; + } + if (lastchar - buffer >= 14 && strcmp(lastchar - 14, "$qSupported#37") == 0) { + strcpy(buffer,"kgdb"); + KDB_STATE_SET(DOING_KGDB2); + return buffer; + } + } + break; + } + } +} +EXPORT_SYMBOL_GPL(kdb_read); + +/* + * kdb_getstr + * + * Print the prompt string and read a command from the + * input device. + * + * Parameters: + * buffer Address of buffer to receive command + * bufsize Size of buffer in bytes + * prompt Pointer to string to use as prompt string + * Returns: + * Pointer to command buffer. + * Locking: + * None. + * Remarks: + * For SMP kernels, the processor number will be + * substituted for %d, %x or %o in the prompt. + */ + +char * +kdb_getstr(char *buffer, size_t bufsize, char *prompt) +{ + if(prompt && kdb_prompt_str!=prompt) + strncpy(kdb_prompt_str, prompt, CMD_BUFLEN); + kdb_printf(kdb_prompt_str); + kdb_nextline = 1; /* Prompt and input resets line number */ + return kdb_read(buffer, bufsize); +} + +/* + * kdb_input_flush + * + * Get rid of any buffered console input. + * + * Parameters: + * none + * Returns: + * nothing + * Locking: + * none + * Remarks: + * Call this function whenever you want to flush input. If there is any + * outstanding input, it ignores all characters until there has been no + * data for approximately half a second. + */ + +#define FLUSH_UDELAY 100 +#define FLUSH_DELAY 500000/FLUSH_UDELAY /* 0.5 seconds worth of udelays */ + +static void +kdb_input_flush(void) +{ + get_char_func *f; + int flush_delay = 1; + while (flush_delay--) { + touch_nmi_watchdog(); + for (f = &kdb_poll_funcs[0]; *f; ++f) { + if ((*f)() != -1) { + flush_delay = FLUSH_DELAY; + break; + } + } + if (flush_delay) + udelay(FLUSH_UDELAY); + } +} + +/* + * kdb_printf + * + * Print a string to the output device(s). + * + * Parameters: + * printf-like format and optional args. + * Returns: + * 0 + * Locking: + * None. + * Remarks: + * use 'kdbcons->write()' to avoid polluting 'log_buf' with + * kdb output. + * + * If the user is doing a cmd args | grep srch + * then kdb_grepping_flag is set. + * In that case we need to accumulate full lines (ending in \n) before + * searching for the pattern. + */ + +static char kdb_buffer[256]; /* A bit too big to go on stack */ +static char *next_avail = kdb_buffer; +static int size_avail; +static int suspend_grep = 0; + +/* + * search arg1 to see if it contains arg2 + * (kdmain.c provides flags for ^pat and pat$) + * + * return 1 for found, 0 for not found + */ +int +kdb_search_string(char *searched, char *searchfor) +{ + char firstchar, *cp; + int len1, len2; + + /* not counting the newline at the end of "searched" */ + len1 = strlen(searched)-1; + len2 = strlen(searchfor); + if (len1 < len2) + return 0; + if (kdb_grep_leading && kdb_grep_trailing && len1 != len2) + return 0; + if (kdb_grep_leading) { + if (!strncmp(searched, searchfor, len2)) + return 1; + } else if (kdb_grep_trailing) { + if (!strncmp(searched+len1-len2, searchfor, len2)) + return 1; + } else { + firstchar = *searchfor; + cp = searched; + while ((cp = strchr(cp, firstchar))) { + if (!strncmp(cp, searchfor, len2)) + return 1; + cp++; + } + } + return 0; +} + +void +kdb_printf(const char *fmt, ...) +{ + va_list ap; + int diag; + int linecount; + int logging, saved_loglevel = 0; + int do_longjmp = 0; + int got_printf_lock = 0; + int fnd, len; + char *cp, *cp2, *cphold = NULL, replaced_byte = ' '; + char *moreprompt = "more> "; + struct console *c = console_drivers; + static DEFINE_SPINLOCK(kdb_printf_lock); + unsigned long uninitialized_var(flags); + + preempt_disable(); + /* Serialize kdb_printf if multiple cpus try to write at once. + * But if any cpu goes recursive in kdb, just print the output, + * even if it is interleaved with any other text. + */ + if (!KDB_STATE(PRINTF_LOCK)) { + KDB_STATE_SET(PRINTF_LOCK); + spin_lock_irqsave(&kdb_printf_lock, flags); + got_printf_lock = 1; + atomic_inc(&kdb_event); + } else { + __acquire(kdb_printf_lock); + } + + diag = kdbgetintenv("LINES", &linecount); + if (diag || linecount <= 1) + linecount = 22; + + diag = kdbgetintenv("LOGGING", &logging); + if (diag) + logging = 0; + + if (!kdb_grepping_flag || suspend_grep) { + /* normally, every vsnprintf starts a new buffer */ + next_avail = kdb_buffer; + size_avail = sizeof(kdb_buffer); + } + va_start(ap, fmt); + vsnprintf(next_avail, size_avail, fmt, ap); + va_end(ap); + + /* + * If kdb_parse() found that the command was cmd xxx | grep yyy + * then kdb_grepping_flag is set, and kdb_grep_string contains yyy + * + * Accumulate the print data up to a newline before searching it. + * (vsnprintf does null-terminate the string that it generates) + */ + + /* skip the search if prints are temporarily unconditional */ + if (!suspend_grep) { + + if (kdb_grepping_flag) { + cp = strchr(kdb_buffer, '\n'); + if (!cp) { + /* + * Special cases that don't end with newlines + * but should be written without one: + * The "[nn]kdb> " prompt should + * appear at the front of the buffer. + * + * The "[nn]more " prompt should also be + * (MOREPROMPT -> moreprompt) + * written * but we print that ourselves, + * we set the suspend_grep flag to make + * it unconditional. + * + */ + if (next_avail == kdb_buffer) { + /* + * these should occur after a newline, + * so they will be at the front of + * the buffer + */ + cp2 = kdb_buffer; + len = strlen(kdb_prompt_str); + if (!strncmp(cp2, kdb_prompt_str, len)) { + /* + * We're about to start a new + * command, so we can go back + * to normal mode. + */ + kdb_grepping_flag = 0; + goto kdb_printit; + } + } + /* no newline; don't search/write the buffer + until one is there */ + len = strlen(kdb_buffer); + next_avail = kdb_buffer + len; + size_avail = sizeof(kdb_buffer) - len; + goto kdb_print_out; + } + + /* + * The newline is present; print through it or discard + * it, depending on the results of the search. + */ + cp++; /* to byte after the newline */ + replaced_byte = *cp; /* remember what/where it was */ + cphold = cp; + *cp = '\0'; /* end the string for our search */ + + /* + * We now have a newline at the end of the string + * Only continue with this output if it contains the + * search string. + */ + fnd = kdb_search_string(kdb_buffer, kdb_grep_string); + if (!fnd) { + /* + * At this point the complete line at the start + * of kdb_buffer can be discarded, as it does + * not contain what the user is looking for. + * Shift the buffer left. + */ + *cphold = replaced_byte; + strcpy(kdb_buffer, cphold); + len = strlen(kdb_buffer); + next_avail = kdb_buffer + len; + size_avail = sizeof(kdb_buffer) - len; + goto kdb_print_out; + } + /* + * at this point the string is a full line and + * should be printed, up to the null. + */ + } + } +kdb_printit: + + /* + * Write to all consoles. + */ +#ifdef CONFIG_SPARC64 + if (c == NULL) + prom_printf("%s", kdb_buffer); + else +#endif + +#ifdef CONFIG_PPC64 + if (udbg_write) + udbg_write(kdb_buffer, strlen(kdb_buffer)); + else +#endif + + while (c) { + c->write(c, kdb_buffer, strlen(kdb_buffer)); + touch_nmi_watchdog(); + c = c->next; + } + if (logging) { + saved_loglevel = console_loglevel; + console_loglevel = 0; + printk(KERN_INFO "%s", kdb_buffer); + } + + if (KDB_STATE(PAGER) && strchr(kdb_buffer, '\n')) + kdb_nextline++; + + /* check for having reached the LINES number of printed lines */ + if (kdb_nextline == linecount) { + char buf1[16] = ""; +#if defined(CONFIG_SMP) + char buf2[32]; +#endif + + /* Watch out for recursion here. Any routine that calls + * kdb_printf will come back through here. And kdb_read + * uses kdb_printf to echo on serial consoles ... + */ + kdb_nextline = 1; /* In case of recursion */ + + /* + * Pause until cr. + */ + moreprompt = kdbgetenv("MOREPROMPT"); + if (moreprompt == NULL) + moreprompt = "more> "; + +#if defined(CONFIG_SMP) + if (strchr(moreprompt, '%')) { + sprintf(buf2, moreprompt, get_cpu()); + put_cpu(); + moreprompt = buf2; + } +#endif + + kdb_input_flush(); + c = console_drivers; +#ifdef CONFIG_SPARC64 + if (c == NULL) + prom_printf("%s", moreprompt); + else +#endif + +#ifdef CONFIG_PPC64 + if (udbg_write) + udbg_write(moreprompt, strlen(moreprompt)); + else +#endif + + while (c) { + c->write(c, moreprompt, strlen(moreprompt)); + touch_nmi_watchdog(); + c = c->next; + } + + if (logging) + printk("%s", moreprompt); + + kdb_read(buf1, 2); /* '2' indicates to return + * immediately after getting one key. */ + kdb_nextline = 1; /* Really set output line 1 */ + + /* empty and reset the buffer: */ + kdb_buffer[0] = '\0'; + next_avail = kdb_buffer; + size_avail = sizeof(kdb_buffer); + if ((buf1[0] == 'q') || (buf1[0] == 'Q')) { + /* user hit q or Q */ + do_longjmp = 1; + KDB_FLAG_SET(CMD_INTERRUPT); /* command was interrupted */ + KDB_STATE_CLEAR(PAGER); + /* end of command output; back to normal mode */ + kdb_grepping_flag = 0; + kdb_printf("\n"); + } else if (buf1[0] && buf1[0] != '\n') { + /* user hit something other than enter */ + suspend_grep = 1; /* for this recursion */ + kdb_printf("\nOnly 'q' or 'Q' are processed at more prompt, input ignored\n"); + } else if (kdb_grepping_flag) { + /* user hit enter */ + suspend_grep = 1; /* for this recursion */ + kdb_printf("\n"); + } + kdb_input_flush(); + } + + /* + * For grep searches, shift the printed string left. + * replaced_byte contains the character that was overwritten with + * the terminating null, and cphold points to the null. + * Then adjust the notion of available space in the buffer. + */ + if (kdb_grepping_flag && !suspend_grep) { + *cphold = replaced_byte; + strcpy(kdb_buffer, cphold); + len = strlen(kdb_buffer); + next_avail = kdb_buffer + len; + size_avail = sizeof(kdb_buffer) - len; + } + +kdb_print_out: + suspend_grep = 0; /* end of what may have been a recursive call */ + if (logging) + console_loglevel = saved_loglevel; + if (KDB_STATE(PRINTF_LOCK) && got_printf_lock) { + got_printf_lock = 0; + spin_unlock_irqrestore(&kdb_printf_lock, flags); + KDB_STATE_CLEAR(PRINTF_LOCK); + atomic_dec(&kdb_event); + } else { + __release(kdb_printf_lock); + } + preempt_enable(); + if (do_longjmp) +#ifdef kdba_setjmp + kdba_longjmp(&kdbjmpbuf[smp_processor_id()], 1) +#endif /* kdba_setjmp */ + ; +} + +/* + * kdb_io_init + * + * Initialize kernel debugger output environment. + * + * Parameters: + * None. + * Returns: + * None. + * Locking: + * None. + * Remarks: + * Select a console device. Only use a VT console if the user specified + * or defaulted console= /^tty[0-9]*$/ + */ + +void __init +kdb_io_init(void) +{ + /* + * Select a console. + */ + struct console *c = console_drivers; + int vt_console = 0; + + while (c) { + if ((c->flags & CON_CONSDEV) && !kdbcons) + kdbcons = c; + if ((c->flags & CON_ENABLED) && + strncmp(c->name, "tty", 3) == 0) { + char *p = c->name + 3; + while (isdigit(*p)) + ++p; + if (*p == '\0') + vt_console = 1; + } + c = c->next; + } + + if (kdbcons == NULL) { + printk(KERN_ERR "kdb: Initialization failed - no console. kdb is disabled.\n"); + KDB_FLAG_SET(NO_CONSOLE); + kdb_on = 0; + } + if (!vt_console) + KDB_FLAG_SET(NO_VT_CONSOLE); + kdb_input_flush(); + return; +} + +#ifdef CONFIG_KDB_USB + +int kdb_no_usb; + +static int __init opt_kdbnousb(char *str) +{ + kdb_no_usb = 1; + return 0; +} + +early_param("kdbnousb", opt_kdbnousb); + +#endif diff --git a/kdb/kdbmain.c b/kdb/kdbmain.c new file mode 100644 index 0000000..b445a17 --- /dev/null +++ b/kdb/kdbmain.c @@ -0,0 +1,3666 @@ +/* + * Kernel Debugger Architecture Independent Main Code + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1999-2004 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (C) 2000 Stephane Eranian + * Xscale (R) modifications copyright (C) 2003 Intel Corporation. + */ + +/* + * Updated for Xscale (R) architecture support + * Eddie Dong 8 Jan 03 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(CONFIG_LKCD_DUMP) || defined(CONFIG_LKCD_DUMP_MODULE) +#include +#endif +#include +#include +#ifdef CONFIG_KDB_KDUMP +#include +#endif + +#ifdef CONFIG_ACPI +#include +#endif + +#include +#include +#include +#include + +char kdb_debug_info_filename[256] = {""}; +EXPORT_SYMBOL(kdb_debug_info_filename); +#define GREP_LEN 256 +char kdb_grep_string[GREP_LEN]; +int kdb_grepping_flag; +EXPORT_SYMBOL(kdb_grepping_flag); +int kdb_grep_leading; +int kdb_grep_trailing; + +/* + * Kernel debugger state flags + */ +int kdb_flags; +atomic_t kdb_event; +atomic_t kdb_8250; + +/* + * kdb_lock protects updates to kdb_initial_cpu. Used to + * single thread processors through the kernel debugger. + */ +int kdb_initial_cpu = -1; /* cpu number that owns kdb */ +int kdb_seqno = 2; /* how many times kdb has been entered */ + +int kdb_nextline = 1; +static volatile int kdb_new_cpu; /* Which cpu to switch to */ + +int kdb_state[NR_CPUS]; /* Per cpu state */ + +const struct task_struct *kdb_current_task; +EXPORT_SYMBOL(kdb_current_task); +struct pt_regs *kdb_current_regs; + +#ifdef CONFIG_KDB_OFF +int kdb_on; /* Default is off */ +#else +int kdb_on = 1; /* Default is on */ +#endif /* CONFIG_KDB_OFF */ + +const char *kdb_diemsg; +static int kdb_go_count; +#ifdef CONFIG_KDB_CONTINUE_CATASTROPHIC +static unsigned int kdb_continue_catastrophic = + CONFIG_KDB_CONTINUE_CATASTROPHIC; +#else +static unsigned int kdb_continue_catastrophic; +#endif + +#ifdef kdba_setjmp + /* + * Must have a setjmp buffer per CPU. Switching cpus will + * cause the jump buffer to be setup for the new cpu, and + * subsequent switches (and pager aborts) will use the + * appropriate per-processor values. + */ +kdb_jmp_buf *kdbjmpbuf; +#endif /* kdba_setjmp */ + + /* + * kdb_commands describes the available commands. + */ +static kdbtab_t *kdb_commands; +static int kdb_max_commands; + +typedef struct _kdbmsg { + int km_diag; /* kdb diagnostic */ + char *km_msg; /* Corresponding message text */ +} kdbmsg_t; + +#define KDBMSG(msgnum, text) \ + { KDB_##msgnum, text } + +static kdbmsg_t kdbmsgs[] = { + KDBMSG(NOTFOUND, "Command Not Found"), + KDBMSG(ARGCOUNT, "Improper argument count, see usage."), + KDBMSG(BADWIDTH, "Illegal value for BYTESPERWORD use 1, 2, 4 or 8, 8 is only allowed on 64 bit systems"), + KDBMSG(BADRADIX, "Illegal value for RADIX use 8, 10 or 16"), + KDBMSG(NOTENV, "Cannot find environment variable"), + KDBMSG(NOENVVALUE, "Environment variable should have value"), + KDBMSG(NOTIMP, "Command not implemented"), + KDBMSG(ENVFULL, "Environment full"), + KDBMSG(ENVBUFFULL, "Environment buffer full"), + KDBMSG(TOOMANYBPT, "Too many breakpoints defined"), +#ifdef CONFIG_CPU_XSCALE + KDBMSG(TOOMANYDBREGS, "More breakpoints than ibcr registers defined"), +#else + KDBMSG(TOOMANYDBREGS, "More breakpoints than db registers defined"), +#endif + KDBMSG(DUPBPT, "Duplicate breakpoint address"), + KDBMSG(BPTNOTFOUND, "Breakpoint not found"), + KDBMSG(BADMODE, "Invalid IDMODE"), + KDBMSG(BADINT, "Illegal numeric value"), + KDBMSG(INVADDRFMT, "Invalid symbolic address format"), + KDBMSG(BADREG, "Invalid register name"), + KDBMSG(BADCPUNUM, "Invalid cpu number"), + KDBMSG(BADLENGTH, "Invalid length field"), + KDBMSG(NOBP, "No Breakpoint exists"), + KDBMSG(BADADDR, "Invalid address"), +}; +#undef KDBMSG + +static const int __nkdb_err = sizeof(kdbmsgs) / sizeof(kdbmsg_t); + + +/* + * Initial environment. This is all kept static and local to + * this file. We don't want to rely on the memory allocation + * mechanisms in the kernel, so we use a very limited allocate-only + * heap for new and altered environment variables. The entire + * environment is limited to a fixed number of entries (add more + * to __env[] if required) and a fixed amount of heap (add more to + * KDB_ENVBUFSIZE if required). + */ + +static char *__env[] = { +#if defined(CONFIG_SMP) + "PROMPT=[%d]kdb> ", + "MOREPROMPT=[%d]more> ", +#else + "PROMPT=kdb> ", + "MOREPROMPT=more> ", +#endif + "RADIX=16", + "LINES=24", + "COLUMNS=80", + "MDCOUNT=8", /* lines of md output */ + "BTARGS=9", /* 9 possible args in bt */ + KDB_PLATFORM_ENV, + "DTABCOUNT=30", + "NOSECT=1", + (char *)0, + (char *)0, + (char *)0, + (char *)0, + (char *)0, + (char *)0, + (char *)0, + (char *)0, + (char *)0, + (char *)0, + (char *)0, + (char *)0, + (char *)0, + (char *)0, + (char *)0, + (char *)0, + (char *)0, + (char *)0, + (char *)0, + (char *)0, + (char *)0, + (char *)0, + (char *)0, +}; + +static const int __nenv = (sizeof(__env) / sizeof(char *)); + +/* external commands: */ +int kdb_debuginfo_print(int argc, const char **argv); +int kdb_pxhelp(int argc, const char **argv); +int kdb_walkhelp(int argc, const char **argv); +int kdb_walk(int argc, const char **argv); + +/* + * kdb_serial_str is the sequence that the user must enter on a serial + * console to invoke kdb. It can be a single character such as "\001" + * (control-A) or multiple characters such as "\eKDB". NOTE: All except the + * last character are passed through to the application reading from the serial + * console. + * + * I tried to make the sequence a CONFIG_ option but most of CML1 cannot cope + * with '\' in strings. CML2 would have been able to do it but we lost CML2. + * KAO. + */ +const char kdb_serial_str[] = "\eKDB"; +EXPORT_SYMBOL(kdb_serial_str); + +struct task_struct * +kdb_curr_task(int cpu) +{ + struct task_struct *p = curr_task(cpu); +#ifdef _TIF_MCA_INIT + struct kdb_running_process *krp = kdb_running_process + cpu; + if ((task_thread_info(p)->flags & _TIF_MCA_INIT) && krp->p) + p = krp->p; +#endif + return p; +} + +/* + * kdbgetenv + * + * This function will return the character string value of + * an environment variable. + * + * Parameters: + * match A character string representing an environment variable. + * Outputs: + * None. + * Returns: + * NULL No environment variable matches 'match' + * char* Pointer to string value of environment variable. + * Locking: + * No locking considerations required. + * Remarks: + */ +char * +kdbgetenv(const char *match) +{ + char **ep = __env; + int matchlen = strlen(match); + int i; + + for(i = 0; i < __nenv; i++) { + char *e = *ep++; + + if (!e) + continue; + + if ((strncmp(match, e, matchlen) == 0) + && ((e[matchlen] == '\0') + || (e[matchlen] == '='))) { + char *cp = strchr(e, '='); + return (cp ? ++cp : ""); + } + } + return NULL; +} + +/* + * kdballocenv + * + * This function is used to allocate bytes for environment entries. + * + * Parameters: + * match A character string representing a numeric value + * Outputs: + * *value the unsigned long represntation of the env variable 'match' + * Returns: + * Zero on success, a kdb diagnostic on failure. + * Locking: + * No locking considerations required. Must be called with all + * processors halted. + * Remarks: + * We use a static environment buffer (envbuffer) to hold the values + * of dynamically generated environment variables (see kdb_set). Buffer + * space once allocated is never free'd, so over time, the amount of space + * (currently 512 bytes) will be exhausted if env variables are changed + * frequently. + */ +static char * +kdballocenv(size_t bytes) +{ +#define KDB_ENVBUFSIZE 512 + static char envbuffer[KDB_ENVBUFSIZE]; + static int envbufsize; + char *ep = NULL; + + if ((KDB_ENVBUFSIZE - envbufsize) >= bytes) { + ep = &envbuffer[envbufsize]; + envbufsize += bytes; + } + return ep; +} + +/* + * kdbgetulenv + * + * This function will return the value of an unsigned long-valued + * environment variable. + * + * Parameters: + * match A character string representing a numeric value + * Outputs: + * *value the unsigned long represntation of the env variable 'match' + * Returns: + * Zero on success, a kdb diagnostic on failure. + * Locking: + * No locking considerations required. + * Remarks: + */ + +static int +kdbgetulenv(const char *match, unsigned long *value) +{ + char *ep; + + ep = kdbgetenv(match); + if (!ep) + return KDB_NOTENV; + if (strlen(ep) == 0) + return KDB_NOENVVALUE; + + *value = simple_strtoul(ep, NULL, 0); + + return 0; +} + +/* + * kdbgetintenv + * + * This function will return the value of an integer-valued + * environment variable. + * + * Parameters: + * match A character string representing an integer-valued env variable + * Outputs: + * *value the integer representation of the environment variable 'match' + * Returns: + * Zero on success, a kdb diagnostic on failure. + * Locking: + * No locking considerations required. + * Remarks: + */ + +int +kdbgetintenv(const char *match, int *value) { + unsigned long val; + int diag; + + diag = kdbgetulenv(match, &val); + if (!diag) + *value = (int) val; + return diag; +} + +/* + * kdbgetularg + * + * This function will convert a numeric string + * into an unsigned long value. + * + * Parameters: + * arg A character string representing a numeric value + * Outputs: + * *value the unsigned long represntation of arg. + * Returns: + * Zero on success, a kdb diagnostic on failure. + * Locking: + * No locking considerations required. + * Remarks: + */ + +int +kdbgetularg(const char *arg, unsigned long *value) +{ + char *endp; + unsigned long val; + + val = simple_strtoul(arg, &endp, 0); + + if (endp == arg) { + /* + * Try base 16, for us folks too lazy to type the + * leading 0x... + */ + val = simple_strtoul(arg, &endp, 16); + if (endp == arg) + return KDB_BADINT; + } + + *value = val; + + return 0; +} + +/* + * kdb_set + * + * This function implements the 'set' command. Alter an existing + * environment variable or create a new one. + * + * Inputs: + * argc argument count + * argv argument vector + * Outputs: + * None. + * Returns: + * zero for success, a kdb diagnostic if error + * Locking: + * none. + * Remarks: + */ + +static int +kdb_set(int argc, const char **argv) +{ + int i; + char *ep; + size_t varlen, vallen; + + /* + * we can be invoked two ways: + * set var=value argv[1]="var", argv[2]="value" + * set var = value argv[1]="var", argv[2]="=", argv[3]="value" + * - if the latter, shift 'em down. + */ + if (argc == 3) { + argv[2] = argv[3]; + argc--; + } + + if (argc != 2) + return KDB_ARGCOUNT; + + /* + * Check for internal variables + */ + if (strcmp(argv[1], "KDBDEBUG") == 0) { + unsigned int debugflags; + char *cp; + + debugflags = simple_strtoul(argv[2], &cp, 0); + if (cp == argv[2] || debugflags & ~KDB_DEBUG_FLAG_MASK) { + kdb_printf("kdb: illegal debug flags '%s'\n", + argv[2]); + return 0; + } + kdb_flags = (kdb_flags & + ~(KDB_DEBUG_FLAG_MASK << KDB_DEBUG_FLAG_SHIFT)) + | (debugflags << KDB_DEBUG_FLAG_SHIFT); + + return 0; + } + + /* + * Tokenizer squashed the '=' sign. argv[1] is variable + * name, argv[2] = value. + */ + varlen = strlen(argv[1]); + vallen = strlen(argv[2]); + ep = kdballocenv(varlen + vallen + 2); + if (ep == (char *)0) + return KDB_ENVBUFFULL; + + sprintf(ep, "%s=%s", argv[1], argv[2]); + + ep[varlen+vallen+1] = '\0'; + + for(i = 0; i < __nenv; i++) { + if (__env[i] + && ((strncmp(__env[i], argv[1], varlen) == 0) + && ((__env[i][varlen] == '\0') + || (__env[i][varlen] == '=')))) { + __env[i] = ep; + return 0; + } + } + + /* + * Wasn't existing variable. Fit into slot. + */ + for(i = 0; i < __nenv-1; i++) { + if (__env[i] == (char *)0) { + __env[i] = ep; + return 0; + } + } + + return KDB_ENVFULL; +} + +static int +kdb_check_regs(void) +{ + if (!kdb_current_regs) { + kdb_printf("No current kdb registers." + " You may need to select another task\n"); + return KDB_BADREG; + } + return 0; +} + +/* + * kdbgetaddrarg + * + * This function is responsible for parsing an + * address-expression and returning the value of + * the expression, symbol name, and offset to the caller. + * + * The argument may consist of a numeric value (decimal or + * hexidecimal), a symbol name, a register name (preceeded + * by the percent sign), an environment variable with a numeric + * value (preceeded by a dollar sign) or a simple arithmetic + * expression consisting of a symbol name, +/-, and a numeric + * constant value (offset). + * + * Parameters: + * argc - count of arguments in argv + * argv - argument vector + * *nextarg - index to next unparsed argument in argv[] + * regs - Register state at time of KDB entry + * Outputs: + * *value - receives the value of the address-expression + * *offset - receives the offset specified, if any + * *name - receives the symbol name, if any + * *nextarg - index to next unparsed argument in argv[] + * + * Returns: + * zero is returned on success, a kdb diagnostic code is + * returned on error. + * + * Locking: + * No locking requirements. + * + * Remarks: + * + */ + +int +kdbgetaddrarg(int argc, const char **argv, int *nextarg, + kdb_machreg_t *value, long *offset, + char **name) +{ + kdb_machreg_t addr; + unsigned long off = 0; + int positive; + int diag; + int found = 0; + char *symname; + char symbol = '\0'; + char *cp; + kdb_symtab_t symtab; + + /* + * Process arguments which follow the following syntax: + * + * symbol | numeric-address [+/- numeric-offset] + * %register + * $environment-variable + */ + + if (*nextarg > argc) + return KDB_ARGCOUNT; + + symname = (char *)argv[*nextarg]; + + /* + * If there is no whitespace between the symbol + * or address and the '+' or '-' symbols, we + * remember the character and replace it with a + * null so the symbol/value can be properly parsed + */ + if ((cp = strpbrk(symname, "+-")) != NULL) { + symbol = *cp; + *cp++ = '\0'; + } + + if (symname[0] == '$') { + diag = kdbgetulenv(&symname[1], &addr); + if (diag) + return diag; + } else if (symname[0] == '%') { + if ((diag = kdb_check_regs())) + return diag; + // diag = kdba_getregcontents(&symname[1], kdb_current_regs, &addr); + // HACK HACK HACK + diag = 0; + if (diag) + return diag; + } else { + found = kdbgetsymval(symname, &symtab); + if (found) { + addr = symtab.sym_start; + } else { + diag = kdbgetularg(argv[*nextarg], &addr); + if (diag) + return diag; + } + } + + if (!found) + found = kdbnearsym(addr, &symtab); + + (*nextarg)++; + + if (name) + *name = symname; + if (value) + *value = addr; + if (offset && name && *name) + *offset = addr - symtab.sym_start; + + if ((*nextarg > argc) + && (symbol == '\0')) + return 0; + + /* + * check for +/- and offset + */ + + if (symbol == '\0') { + if ((argv[*nextarg][0] != '+') + && (argv[*nextarg][0] != '-')) { + /* + * Not our argument. Return. + */ + return 0; + } else { + positive = (argv[*nextarg][0] == '+'); + (*nextarg)++; + } + } else + positive = (symbol == '+'); + + /* + * Now there must be an offset! + */ + if ((*nextarg > argc) + && (symbol == '\0')) { + return KDB_INVADDRFMT; + } + + if (!symbol) { + cp = (char *)argv[*nextarg]; + (*nextarg)++; + } + + diag = kdbgetularg(cp, &off); + if (diag) + return diag; + + if (!positive) + off = -off; + + if (offset) + *offset += off; + + if (value) + *value += off; + + return 0; +} + +static void +kdb_cmderror(int diag) +{ + int i; + + if (diag >= 0) { + kdb_printf("no error detected (diagnostic is %d)\n", diag); + return; + } + + for(i = 0; i < __nkdb_err; i++) { + if (kdbmsgs[i].km_diag == diag) { + kdb_printf("diag: %d: %s\n", diag, kdbmsgs[i].km_msg); + return; + } + } + + kdb_printf("Unknown diag %d\n", -diag); +} + +/* + * kdb_defcmd, kdb_defcmd2 + * + * This function implements the 'defcmd' command which defines one + * command as a set of other commands, terminated by endefcmd. + * kdb_defcmd processes the initial 'defcmd' command, kdb_defcmd2 + * is invoked from kdb_parse for the following commands until + * 'endefcmd'. + * + * Inputs: + * argc argument count + * argv argument vector + * Outputs: + * None. + * Returns: + * zero for success, a kdb diagnostic if error + * Locking: + * none. + * Remarks: + */ + +struct defcmd_set { + int count; + int usable; + char *name; + char *usage; + char *help; + char **command; +}; +static struct defcmd_set *defcmd_set; +static int defcmd_set_count; +static int defcmd_in_progress; + +/* Forward references */ +static int kdb_exec_defcmd(int argc, const char **argv); + +static int +kdb_defcmd2(const char *cmdstr, const char *argv0) +{ + struct defcmd_set *s = defcmd_set + defcmd_set_count - 1; + char **save_command = s->command; + if (strcmp(argv0, "endefcmd") == 0) { + defcmd_in_progress = 0; + if (!s->count) + s->usable = 0; + if (s->usable) + kdb_register(s->name, kdb_exec_defcmd, + s->usage, s->help, 0); + return 0; + } + if (!s->usable) + return KDB_NOTIMP; + s->command = kmalloc((s->count + 1) * sizeof(*(s->command)), GFP_KDB); + if (!s->command) { + kdb_printf("Could not allocate new kdb_defcmd table for %s\n", cmdstr); + s->usable = 0; + return KDB_NOTIMP; + } + memcpy(s->command, save_command, s->count * sizeof(*(s->command))); + s->command[s->count++] = kdb_strdup(cmdstr, GFP_KDB); + kfree(save_command); + return 0; +} + +static int +kdb_defcmd(int argc, const char **argv) +{ + struct defcmd_set *save_defcmd_set = defcmd_set, *s; + if (defcmd_in_progress) { + kdb_printf("kdb: nested defcmd detected, assuming missing endefcmd\n"); + kdb_defcmd2("endefcmd", "endefcmd"); + } + if (argc == 0) { + int i; + for (s = defcmd_set; s < defcmd_set + defcmd_set_count; ++s) { + kdb_printf("defcmd %s \"%s\" \"%s\"\n", s->name, s->usage, s->help); + for (i = 0; i < s->count; ++i) + kdb_printf("%s", s->command[i]); + kdb_printf("endefcmd\n"); + } + return 0; + } + if (argc != 3) + return KDB_ARGCOUNT; + defcmd_set = kmalloc((defcmd_set_count + 1) * sizeof(*defcmd_set), GFP_KDB); + if (!defcmd_set) { + kdb_printf("Could not allocate new defcmd_set entry for %s\n", argv[1]); + defcmd_set = save_defcmd_set; + return KDB_NOTIMP; + } + memcpy(defcmd_set, save_defcmd_set, defcmd_set_count * sizeof(*defcmd_set)); + kfree(save_defcmd_set); + s = defcmd_set + defcmd_set_count; + memset(s, 0, sizeof(*s)); + s->usable = 1; + s->name = kdb_strdup(argv[1], GFP_KDB); + s->usage = kdb_strdup(argv[2], GFP_KDB); + s->help = kdb_strdup(argv[3], GFP_KDB); + if (s->usage[0] == '"') { + strcpy(s->usage, s->usage+1); + s->usage[strlen(s->usage)-1] = '\0'; + } + if (s->help[0] == '"') { + strcpy(s->help, s->help+1); + s->help[strlen(s->help)-1] = '\0'; + } + ++defcmd_set_count; + defcmd_in_progress = 1; + return 0; +} + +/* + * kdb_exec_defcmd + * + * Execute the set of commands associated with this defcmd name. + * + * Inputs: + * argc argument count + * argv argument vector + * Outputs: + * None. + * Returns: + * zero for success, a kdb diagnostic if error + * Locking: + * none. + * Remarks: + */ + +static int +kdb_exec_defcmd(int argc, const char **argv) +{ + int i, ret; + struct defcmd_set *s; + if (argc != 0) + return KDB_ARGCOUNT; + for (s = defcmd_set, i = 0; i < defcmd_set_count; ++i, ++s) { + if (strcmp(s->name, argv[0]) == 0) + break; + } + if (i == defcmd_set_count) { + kdb_printf("kdb_exec_defcmd: could not find commands for %s\n", argv[0]); + return KDB_NOTIMP; + } + for (i = 0; i < s->count; ++i) { + /* Recursive use of kdb_parse, do not use argv after + * this point */ + argv = NULL; + kdb_printf("[%s]kdb> %s\n", s->name, s->command[i]); + if ((ret = kdb_parse(s->command[i]))) + return ret; + } + return 0; +} + +/* Command history */ +#define KDB_CMD_HISTORY_COUNT 32 +#define CMD_BUFLEN 200 /* kdb_printf: max printline + * size == 256 */ +static unsigned int cmd_head, cmd_tail; +static unsigned int cmdptr; +static char cmd_hist[KDB_CMD_HISTORY_COUNT][CMD_BUFLEN]; +static char cmd_cur[CMD_BUFLEN]; + +/* + * The "str" argument may point to something like | grep xyz + * + */ +static void +parse_grep(const char *str) +{ + int len; + char *cp = (char *)str, *cp2; + + /* sanity check: we should have been called with the \ first */ + if (*cp != '|') + return; + cp++; + while (isspace(*cp)) + cp++; + if (strncmp(cp, "grep ",5)) { + kdb_printf("invalid 'pipe', see grephelp\n"); + return; + } + cp += 5; + while (isspace(*cp)) + cp++; + cp2 = strchr(cp, '\n'); + if (cp2) + *cp2 = '\0'; /* remove the trailing newline */ + len = strlen(cp); + if (len == 0) { + kdb_printf("invalid 'pipe', see grephelp\n"); + return; + } + /* now cp points to a nonzero length search string */ + if (*cp == '"') { + /* allow it be "x y z" by removing the "'s - there must + be two of them */ + cp++; + cp2 = strchr(cp, '"'); + if (!cp2) { + kdb_printf("invalid quoted string, see grephelp\n"); + return; + } + *cp2 = '\0'; /* end the string where the 2nd " was */ + } + kdb_grep_leading = 0; + if (*cp == '^') { + kdb_grep_leading = 1; + cp++; + } + len = strlen(cp); + kdb_grep_trailing = 0; + if (*(cp+len-1) == '$') { + kdb_grep_trailing = 1; + *(cp+len-1) = '\0'; + } + len = strlen(cp); + if (!len) return; + if (len >= GREP_LEN) { + kdb_printf("search string too long\n"); + return; + } + strcpy(kdb_grep_string, cp); + kdb_grepping_flag++; + return; +} + +/* + * kdb_parse + * + * Parse the command line, search the command table for a + * matching command and invoke the command function. + * This function may be called recursively, if it is, the second call + * will overwrite argv and cbuf. It is the caller's responsibility to + * save their argv if they recursively call kdb_parse(). + * + * Parameters: + * cmdstr The input command line to be parsed. + * regs The registers at the time kdb was entered. + * Outputs: + * None. + * Returns: + * Zero for success, a kdb diagnostic if failure. + * Locking: + * None. + * Remarks: + * Limited to 20 tokens. + * + * Real rudimentary tokenization. Basically only whitespace + * is considered a token delimeter (but special consideration + * is taken of the '=' sign as used by the 'set' command). + * + * The algorithm used to tokenize the input string relies on + * there being at least one whitespace (or otherwise useless) + * character between tokens as the character immediately following + * the token is altered in-place to a null-byte to terminate the + * token string. + */ + +#define MAXARGC 20 + +int +kdb_parse(const char *cmdstr) +{ + static char *argv[MAXARGC]; + static int argc = 0; + static char cbuf[CMD_BUFLEN+2]; + char *cp; + char *cpp, quoted; + kdbtab_t *tp; + int i, escaped, ignore_errors = 0, check_grep; + + /* + * First tokenize the command string. + */ + cp = (char *)cmdstr; + kdb_grepping_flag = check_grep = 0; + + if (KDB_FLAG(CMD_INTERRUPT)) { + /* Previous command was interrupted, newline must not repeat the command */ + KDB_FLAG_CLEAR(CMD_INTERRUPT); + KDB_STATE_SET(PAGER); + argc = 0; /* no repeat */ + } + + if (*cp != '\n' && *cp != '\0') { + argc = 0; + cpp = cbuf; + while (*cp) { + /* skip whitespace */ + while (isspace(*cp)) cp++; + if ((*cp == '\0') || (*cp == '\n') || (*cp == '#' && !defcmd_in_progress)) + break; + /* special case: check for | grep pattern */ + if (*cp == '|') { + check_grep++; + break; + } + if (cpp >= cbuf + CMD_BUFLEN) { + kdb_printf("kdb_parse: command buffer overflow, command ignored\n%s\n", cmdstr); + return KDB_NOTFOUND; + } + if (argc >= MAXARGC - 1) { + kdb_printf("kdb_parse: too many arguments, command ignored\n%s\n", cmdstr); + return KDB_NOTFOUND; + } + argv[argc++] = cpp; + escaped = 0; + quoted = '\0'; + /* Copy to next unquoted and unescaped whitespace or '=' */ + while (*cp && *cp != '\n' && (escaped || quoted || !isspace(*cp))) { + if (cpp >= cbuf + CMD_BUFLEN) + break; + if (escaped) { + escaped = 0; + *cpp++ = *cp++; + continue; + } + if (*cp == '\\') { + escaped = 1; + ++cp; + continue; + } + if (*cp == quoted) { + quoted = '\0'; + } else if (*cp == '\'' || *cp == '"') { + quoted = *cp; + } + if ((*cpp = *cp++) == '=' && !quoted) + break; + ++cpp; + } + *cpp++ = '\0'; /* Squash a ws or '=' character */ + } + } + if (!argc) + return 0; + if (check_grep) + parse_grep(cp); + if (defcmd_in_progress) { + int result = kdb_defcmd2(cmdstr, argv[0]); + if (!defcmd_in_progress) { + argc = 0; /* avoid repeat on endefcmd */ + *(argv[0]) = '\0'; + } + return result; + } + if (argv[0][0] == '-' && argv[0][1] && (argv[0][1] < '0' || argv[0][1] > '9')) { + ignore_errors = 1; + ++argv[0]; + } + + for(tp=kdb_commands, i=0; i < kdb_max_commands; i++,tp++) { + if (tp->cmd_name) { + /* + * If this command is allowed to be abbreviated, + * check to see if this is it. + */ + + if (tp->cmd_minlen + && (strlen(argv[0]) <= tp->cmd_minlen)) { + if (strncmp(argv[0], + tp->cmd_name, + tp->cmd_minlen) == 0) { + break; + } + } + + if (strcmp(argv[0], tp->cmd_name)==0) { + break; + } + } + } + + /* + * If we don't find a command by this name, see if the first + * few characters of this match any of the known commands. + * e.g., md1c20 should match md. + */ + if (i == kdb_max_commands) { + for(tp=kdb_commands, i=0; i < kdb_max_commands; i++,tp++) { + if (tp->cmd_name) { + if (strncmp(argv[0], + tp->cmd_name, + strlen(tp->cmd_name))==0) { + break; + } + } + } + } + + if (i < kdb_max_commands) { + int result; + KDB_STATE_SET(CMD); + result = (*tp->cmd_func)(argc-1, + (const char**)argv); + if (result && ignore_errors && result > KDB_CMD_GO) + result = 0; + KDB_STATE_CLEAR(CMD); + switch (tp->cmd_repeat) { + case KDB_REPEAT_NONE: + argc = 0; + if (argv[0]) + *(argv[0]) = '\0'; + break; + case KDB_REPEAT_NO_ARGS: + argc = 1; + if (argv[1]) + *(argv[1]) = '\0'; + break; + case KDB_REPEAT_WITH_ARGS: + break; + } + return result; + } + + /* + * If the input with which we were presented does not + * map to an existing command, attempt to parse it as an + * address argument and display the result. Useful for + * obtaining the address of a variable, or the nearest symbol + * to an address contained in a register. + */ + { + kdb_machreg_t value; + char *name = NULL; + long offset; + int nextarg = 0; + + if (kdbgetaddrarg(0, (const char **)argv, &nextarg, + &value, &offset, &name)) { + return KDB_NOTFOUND; + } + + kdb_printf("%s = ", argv[0]); + kdb_symbol_print(value, NULL, KDB_SP_DEFAULT); + kdb_printf("\n"); + return 0; + } +} + + +static int +handle_ctrl_cmd(char *cmd) +{ +#define CTRL_P 16 +#define CTRL_N 14 + + /* initial situation */ + if (cmd_head == cmd_tail) return 0; + + switch(*cmd) { + case CTRL_P: + if (cmdptr != cmd_tail) + cmdptr = (cmdptr-1) % KDB_CMD_HISTORY_COUNT; + strncpy(cmd_cur, cmd_hist[cmdptr], CMD_BUFLEN); + return 1; + case CTRL_N: + if (cmdptr != cmd_head) + cmdptr = (cmdptr+1) % KDB_CMD_HISTORY_COUNT; + strncpy(cmd_cur, cmd_hist[cmdptr], CMD_BUFLEN); + return 1; + } + return 0; +} + +/* + * kdb_do_dump + * + * Call the dump() function if the kernel is configured for LKCD. + * Inputs: + * None. + * Outputs: + * None. + * Returns: + * None. dump() may or may not return. + * Locking: + * none. + * Remarks: + */ + +static void +kdb_do_dump(void) +{ +#if defined(CONFIG_LKCD_DUMP) || defined(CONFIG_LKCD_DUMP_MODULE) + kdb_printf("Forcing dump (if configured)\n"); + console_loglevel = 8; /* to see the dump messages */ + dump("kdb_do_dump"); +#endif +} + +/* + * kdb_reboot + * + * This function implements the 'reboot' command. Reboot the system + * immediately. + * + * Inputs: + * argc argument count + * argv argument vector + * Outputs: + * None. + * Returns: + * zero for success, a kdb diagnostic if error + * Locking: + * none. + * Remarks: + * Shouldn't return from this function. + */ + +static int +kdb_reboot(int argc, const char **argv) +{ + emergency_restart(); + kdb_printf("Hmm, kdb_reboot did not reboot, spinning here\n"); + while (1) {}; + /* NOTREACHED */ + return 0; +} + +#ifdef CONFIG_KDB_KDUMP + +int kdb_kdump_state = KDB_KDUMP_RESET; /* KDB kdump state */ + +static int kdb_cpu(int argc, const char **argv); + +/* + * kdb_kdump_check + * + * This is where the kdump on monarch cpu is handled. + * + */ +void kdb_kdump_check(struct pt_regs *regs) +{ + if (kdb_kdump_state != KDB_KDUMP_RESET) { + crash_kexec(regs); + + /* If the call above returned then something + didn't work */ + kdb_printf("kdb_kdump_check: crash_kexec failed!\n"); + kdb_printf(" Please check if the kdump kernel has been properly loaded\n"); + kdb_kdump_state = KDB_KDUMP_RESET; + } +} + + +/* + * kdb_kdump + * + * This function implements the 'kdump' command. + * + * Inputs: + * argc argument count + * argv argument vector + * envp environment vector + * regs registers at time kdb was entered. + * Outputs: + * None. + * Returns: + * zero for success, a kdb diagnostic if error + * Locking: + * none. + * Remarks: + * Shouldn't return from this function. + */ + +static int +kdb_kdump(int argc, const char **argv) +{ + char cpu_id[6]; /* up to 99,999 cpus */ + const char *cpu_argv[] = {NULL, cpu_id, NULL}; + int ret; + + kdb_kdump_state = KDB_KDUMP_KDUMP; + /* Switch back to the initial cpu before process kdump command */ + if (smp_processor_id() != kdb_initial_cpu) { + sprintf(cpu_id, "%d", kdb_initial_cpu); + ret = kdb_cpu(1, cpu_argv); + if (ret != KDB_CMD_CPU) { + kdb_printf("kdump: Failed to switch to initial cpu %d;" + " aborted\n", kdb_initial_cpu); + kdb_kdump_state = KDB_KDUMP_RESET; + } + } else + ret = KDB_CMD_CPU; + + return ret; +} + +#endif /* CONFIG_KDB_KDUMP */ + +static int +kdb_quiet(int reason) +{ + return (reason == KDB_REASON_CPU_UP || reason == KDB_REASON_SILENT); +} + +kdb_machreg_t kdba_getpc(struct pt_regs *regs) +{ + return instruction_pointer(regs); +} + +int +kdba_dumpregs(struct pt_regs *regs, + const char *type, + const char *extra) +{ + return 0; +} + + +void +kdba_set_current_task(const struct task_struct *p) +{ + kdb_current_task = p; + + if (kdb_task_has_cpu(p)) { + struct kdb_running_process *krp = kdb_running_process + kdb_process_cpu(p); + kdb_current_regs = krp->regs; + return; + } + kdb_current_regs = NULL; +} + +/* + * kdb_local + * + * The main code for kdb. This routine is invoked on a specific + * processor, it is not global. The main kdb() routine ensures + * that only one processor at a time is in this routine. This + * code is called with the real reason code on the first entry + * to a kdb session, thereafter it is called with reason SWITCH, + * even if the user goes back to the original cpu. + * + * Inputs: + * reason The reason KDB was invoked + * error The hardware-defined error code + * regs The exception frame at time of fault/breakpoint. NULL + * for reason SILENT or CPU_UP, otherwise valid. + * db_result Result code from the break or debug point. + * Returns: + * 0 KDB was invoked for an event which it wasn't responsible + * 1 KDB handled the event for which it was invoked. + * KDB_CMD_GO User typed 'go'. + * KDB_CMD_CPU User switched to another cpu. + * KDB_CMD_SS Single step. + * KDB_CMD_SSB Single step until branch. + * Locking: + * none + * Remarks: + * none + */ + +static int +kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs, kdb_dbtrap_t db_result) +{ + char *cmdbuf; + int diag; + struct task_struct *kdb_current = kdb_curr_task(smp_processor_id()); + +#ifdef CONFIG_KDB_KDUMP + kdb_kdump_check(regs); +#endif + + /* If kdb has been entered for an event which has been/will be + * recovered then silently return. We have to get this far into kdb in + * order to synchronize all the cpus, typically only one cpu (monarch) + * knows that the event is recoverable but the other cpus (slaves) may + * also be driven into kdb before that decision is made by the monarch. + * + * To pause in kdb even for recoverable events, 'set RECOVERY_PAUSE 1' + */ + KDB_DEBUG_STATE("kdb_local 1", reason); + if (reason == KDB_REASON_ENTER + && KDB_FLAG(RECOVERY) + && !KDB_FLAG(CATASTROPHIC)) { + int recovery_pause = 0; + kdbgetintenv("RECOVERY_PAUSE", &recovery_pause); + if (recovery_pause == 0) + reason = KDB_REASON_SILENT; + else + kdb_printf("%s: Recoverable error detected but" + " RECOVERY_PAUSE is set, staying in KDB\n", + __FUNCTION__); + } + + KDB_DEBUG_STATE("kdb_local 2", reason); + kdb_go_count = 0; + if (kdb_quiet(reason)) { + /* no message */ + } else if (reason == KDB_REASON_DEBUG) { + /* special case below */ + } else { + kdb_printf("\nEntering kdb (current=0x%p, pid %d) ", kdb_current, kdb_current->pid); +#if defined(CONFIG_SMP) + kdb_printf("on processor %d ", smp_processor_id()); +#endif + } + + switch (reason) { + case KDB_REASON_DEBUG: + { + /* + * If re-entering kdb after a single step + * command, don't print the message. + */ + switch(db_result) { + case KDB_DB_BPT: + kdb_printf("\nEntering kdb (0x%p, pid %d) ", kdb_current, kdb_current->pid); +#if defined(CONFIG_SMP) + kdb_printf("on processor %d ", smp_processor_id()); +#endif + kdb_printf("due to Debug @ " kdb_machreg_fmt "\n", kdba_getpc(regs)); + break; + case KDB_DB_SSB: + /* + * In the midst of ssb command. Just return. + */ + KDB_DEBUG_STATE("kdb_local 3", reason); + return KDB_CMD_SSB; /* Continue with SSB command */ + + break; + case KDB_DB_SS: + break; + case KDB_DB_SSBPT: + KDB_DEBUG_STATE("kdb_local 4", reason); + return 1; /* kdba_db_trap did the work */ + default: + kdb_printf("kdb: Bad result from kdba_db_trap: %d\n", + db_result); + break; + } + + } + break; + case KDB_REASON_ENTER: + if (KDB_STATE(KEYBOARD)) + kdb_printf("due to Keyboard Entry\n"); + else { + kdb_printf("due to KDB_ENTER()\n"); + } + break; + case KDB_REASON_KEYBOARD: + KDB_STATE_SET(KEYBOARD); + kdb_printf("due to Keyboard Entry\n"); + break; + case KDB_REASON_ENTER_SLAVE: /* drop through, slaves only get released via cpu switch */ + case KDB_REASON_SWITCH: + kdb_printf("due to cpu switch\n"); + if (KDB_STATE(GO_SWITCH)) { + KDB_STATE_CLEAR(GO_SWITCH); + KDB_DEBUG_STATE("kdb_local 5", reason); + return KDB_CMD_GO; + } + break; + case KDB_REASON_OOPS: + kdb_printf("Oops: %s\n", kdb_diemsg); + kdb_printf("due to oops @ " kdb_machreg_fmt "\n", kdba_getpc(regs)); + kdba_dumpregs(regs, NULL, NULL); + break; + case KDB_REASON_NMI: + kdb_printf("due to NonMaskable Interrupt @ " kdb_machreg_fmt "\n", + kdba_getpc(regs)); + kdba_dumpregs(regs, NULL, NULL); + break; + case KDB_REASON_SSTEP: + case KDB_REASON_BREAK: + kdb_printf("due to %s @ " kdb_machreg_fmt "\n", + reason == KDB_REASON_BREAK ? "Breakpoint" : "SS trap", kdba_getpc(regs)); + /* + * Determine if this breakpoint is one that we + * are interested in. + */ + if (db_result != KDB_DB_BPT) { + kdb_printf("kdb: error return from kdba_bp_trap: %d\n", db_result); + KDB_DEBUG_STATE("kdb_local 6", reason); + return 0; /* Not for us, dismiss it */ + } + break; + case KDB_REASON_RECURSE: + kdb_printf("due to Recursion @ " kdb_machreg_fmt "\n", kdba_getpc(regs)); + break; + case KDB_REASON_CPU_UP: + case KDB_REASON_SILENT: + KDB_DEBUG_STATE("kdb_local 7", reason); + // if (reason == KDB_REASON_CPU_UP) + // kdba_cpu_up(); + // HACK HACK HACK + return KDB_CMD_GO; /* Silent entry, silent exit */ + break; + default: + kdb_printf("kdb: unexpected reason code: %d\n", reason); + KDB_DEBUG_STATE("kdb_local 8", reason); + return 0; /* Not for us, dismiss it */ + } + + // kdba_local_arch_setup(); + // HACK HACK HACK + + // kdba_set_current_task(kdb_current); + // HACK HACK HACK + + while (1) { + /* + * Initialize pager context. + */ + kdb_nextline = 1; + KDB_STATE_CLEAR(SUPPRESS); +#ifdef kdba_setjmp + /* + * Use kdba_setjmp/kdba_longjmp to break out of + * the pager early and to attempt to recover from kdb errors. + */ + KDB_STATE_CLEAR(LONGJMP); + if (kdbjmpbuf) { + if (kdba_setjmp(&kdbjmpbuf[smp_processor_id()])) { + /* Command aborted (usually in pager) */ + continue; + } + else + KDB_STATE_SET(LONGJMP); + } +#endif /* kdba_setjmp */ + + cmdbuf = cmd_cur; + *cmdbuf = '\0'; + *(cmd_hist[cmd_head])='\0'; + + if (KDB_FLAG(ONLY_DO_DUMP)) { + /* kdb is off but a catastrophic error requires a dump. + * Take the dump and reboot. + * Turn on logging so the kdb output appears in the log + * buffer in the dump. + */ + const char *setargs[] = { "set", "LOGGING", "1" }; + kdb_set(2, setargs); + kdb_do_dump(); + kdb_reboot(0, NULL); + /*NOTREACHED*/ + } + +do_full_getstr: +#if defined(CONFIG_SMP) + snprintf(kdb_prompt_str, CMD_BUFLEN, kdbgetenv("PROMPT"), smp_processor_id()); +#else + // snprintf(kdb_prompt_str, CMD_BUFLEN, kdbgetenv("PROMPT")); + snprintf(kdb_prompt_str, CMD_BUFLEN, "KDB>"); +#endif + if (defcmd_in_progress) + strncat(kdb_prompt_str, "[defcmd]", CMD_BUFLEN); + + /* + * Fetch command from keyboard + */ + cmdbuf = kdb_getstr(cmdbuf, CMD_BUFLEN, kdb_prompt_str); + if (*cmdbuf != '\n') { + if (*cmdbuf < 32) { + if(cmdptr == cmd_head) { + strncpy(cmd_hist[cmd_head], cmd_cur, CMD_BUFLEN); + *(cmd_hist[cmd_head]+strlen(cmd_hist[cmd_head])-1) = '\0'; + } + if(!handle_ctrl_cmd(cmdbuf)) + *(cmd_cur+strlen(cmd_cur)-1) = '\0'; + cmdbuf = cmd_cur; + goto do_full_getstr; + } + else + strncpy(cmd_hist[cmd_head], cmd_cur, CMD_BUFLEN); + + cmd_head = (cmd_head+1) % KDB_CMD_HISTORY_COUNT; + if (cmd_head == cmd_tail) cmd_tail = (cmd_tail+1) % KDB_CMD_HISTORY_COUNT; + + } + + cmdptr = cmd_head; + diag = kdb_parse(cmdbuf); + if (diag == KDB_NOTFOUND) { + kdb_printf("Unknown kdb command: '%s'\n", cmdbuf); + diag = 0; + } + if (diag == KDB_CMD_GO + || diag == KDB_CMD_CPU + || diag == KDB_CMD_SS + || diag == KDB_CMD_SSB + || diag == KDB_CMD_KGDB) + break; + + if (diag) + kdb_cmderror(diag); + } + + // kdba_local_arch_cleanup(); + // HACK HACK HACK + + KDB_DEBUG_STATE("kdb_local 9", diag); + return diag; +} + + +/* + * kdb_print_state + * + * Print the state data for the current processor for debugging. + * + * Inputs: + * text Identifies the debug point + * value Any integer value to be printed, e.g. reason code. + * Returns: + * None. + * Locking: + * none + * Remarks: + * none + */ + +void kdb_print_state(const char *text, int value) +{ + kdb_printf("state: %s cpu %d value %d initial %d state %x\n", + text, smp_processor_id(), value, kdb_initial_cpu, kdb_state[smp_processor_id()]); +} + +/* + * kdb_wait_for_cpus + * + * Invoked once at the start of a kdb event, from the controlling cpu. Wait a + * short period for the other cpus to enter kdb state. + * + * Inputs: + * none + * Returns: + * none + * Locking: + * none + * Remarks: + * none + */ + +int kdb_wait_for_cpus_secs; + +/* + * kdb_main_loop + * + * The main kdb loop. After initial setup and assignment of the controlling + * cpu, all cpus are in this loop. One cpu is in control and will issue the kdb + * prompt, the others will spin until 'go' or cpu switch. + * + * To get a consistent view of the kernel stacks for all processes, this routine + * is invoked from the main kdb code via an architecture specific routine. + * kdba_main_loop is responsible for making the kernel stacks consistent for all + * processes, there should be no difference between a blocked process and a + * running process as far as kdb is concerned. + * + * Inputs: + * reason The reason KDB was invoked + * error The hardware-defined error code + * reason2 kdb's current reason code. Initially error but can change + * acording to kdb state. + * db_result Result code from break or debug point. + * regs The exception frame at time of fault/breakpoint. If reason + * is SILENT or CPU_UP then regs is NULL, otherwise it + * should always be valid. + * Returns: + * 0 KDB was invoked for an event which it wasn't responsible + * 1 KDB handled the event for which it was invoked. + * Locking: + * none + * Remarks: + * none + */ + +int +kdb_main_loop(kdb_reason_t reason, kdb_reason_t reason2, int error, + kdb_dbtrap_t db_result, struct pt_regs *regs) +{ + int result = 1; + /* Stay in kdb() until 'go', 'ss[b]' or an error */ + while (1) { + /* + * All processors except the one that is in control + * will spin here. + */ + KDB_DEBUG_STATE("kdb_main_loop 1", reason); + while (KDB_STATE(HOLD_CPU)) { + /* state KDB is turned off by kdb_cpu to see if the + * other cpus are still live, each cpu in this loop + * turns it back on. + */ + if (!KDB_STATE(KDB)) { + KDB_STATE_SET(KDB); + } + +#if defined(CONFIG_KDB_KDUMP) + if (KDB_STATE(KEXEC)) { + struct pt_regs r; + if (regs == NULL) + regs = &r; + + kdba_kdump_shutdown_slave(regs); + return 0; + } +#endif + } + + KDB_STATE_CLEAR(SUPPRESS); + KDB_DEBUG_STATE("kdb_main_loop 2", reason); + if (KDB_STATE(LEAVING)) + break; /* Another cpu said 'go' */ + + // if (!kdb_quiet(reason)) + // kdb_wait_for_cpus(); + /* Still using kdb, this processor is in control */ + result = kdb_local(reason2, error, regs, db_result); + KDB_DEBUG_STATE("kdb_main_loop 3", result); + + if (result == KDB_CMD_CPU) { + /* Cpu switch, hold the current cpu, release the target one. */ + reason2 = KDB_REASON_SWITCH; + KDB_STATE_SET(HOLD_CPU); + KDB_STATE_CLEAR_CPU(HOLD_CPU, kdb_new_cpu); + continue; + } + + if (result == KDB_CMD_SS) { + KDB_STATE_SET(DOING_SS); + break; + } + + if (result == KDB_CMD_SSB) { + KDB_STATE_SET(DOING_SS); + KDB_STATE_SET(DOING_SSB); + break; + + } + + if (result == KDB_CMD_KGDB) { + if (!(KDB_STATE(DOING_KGDB) || KDB_STATE(DOING_KGDB2))) + kdb_printf("Entering please attach debugger or use $D#44+ or $3#33\n"); + break; + } + if (result && result != 1 && result != KDB_CMD_GO) + kdb_printf("\nUnexpected kdb_local return code %d\n", result); + + KDB_DEBUG_STATE("kdb_main_loop 4", reason); + break; + } + if (KDB_STATE(DOING_SS)) + KDB_STATE_CLEAR(SSBPT); + + return result; +} + +/* + * kdb_mdr + * + * This function implements the guts of the 'mdr' command. + * + * mdr , + * + * Inputs: + * addr Start address + * count Number of bytes + * Outputs: + * None. + * Returns: + * Always 0. Any errors are detected and printed by kdb_getarea. + * Locking: + * none. + * Remarks: + */ + +static int +kdb_mdr(kdb_machreg_t addr, unsigned int count) +{ + unsigned char c; + while (count--) { + if (kdb_getarea(c, addr)) + return 0; + kdb_printf("%02x", c); + addr++; + } + kdb_printf("\n"); + return 0; +} + +/* + * kdb_md + * + * This function implements the 'md', 'md1', 'md2', 'md4', 'md8' + * 'mdr' and 'mds' commands. + * + * md|mds [ [ []]] + * mdWcN [ [ []]] + * where W = is the width (1, 2, 4 or 8) and N is the count. + * for eg., md1c20 reads 20 bytes, 1 at a time. + * mdr , + * + * Inputs: + * argc argument count + * argv argument vector + * Outputs: + * None. + * Returns: + * zero for success, a kdb diagnostic if error + * Locking: + * none. + * Remarks: + */ + +static void +kdb_md_line(const char *fmtstr, kdb_machreg_t addr, + int symbolic, int nosect, int bytesperword, + int num, int repeat, int phys) +{ + /* print just one line of data */ + kdb_symtab_t symtab; + char cbuf[32]; + char *c = cbuf; + int i; + unsigned long word; + + memset(cbuf, '\0', sizeof(cbuf)); + if (phys) + kdb_printf("phys " kdb_machreg_fmt0 " ", addr); + else + kdb_printf(kdb_machreg_fmt0 " ", addr); + + for (i = 0; i < num && repeat--; i++) { + if (phys) { + if (kdb_getphysword(&word, addr, bytesperword)) + break; + } else if (kdb_getword(&word, addr, bytesperword)) + break; + kdb_printf(fmtstr, word); + if (symbolic) + kdbnearsym(word, &symtab); + else + memset(&symtab, 0, sizeof(symtab)); + if (symtab.sym_name) { + kdb_symbol_print(word, &symtab, 0); + if (!nosect) { + kdb_printf("\n"); + kdb_printf(" %s %s " + kdb_machreg_fmt " " kdb_machreg_fmt " " kdb_machreg_fmt, + symtab.mod_name, + symtab.sec_name, + symtab.sec_start, + symtab.sym_start, + symtab.sym_end); + } + addr += bytesperword; + } else { + union { + u64 word; + unsigned char c[8]; + } wc; + unsigned char *cp; +#ifdef __BIG_ENDIAN + cp = wc.c + 8 - bytesperword; +#else + cp = wc.c; +#endif + wc.word = word; +#define printable_char(c) ({unsigned char __c = c; isascii(__c) && isprint(__c) ? __c : '.';}) + switch (bytesperword) { + case 8: + *c++ = printable_char(*cp++); + *c++ = printable_char(*cp++); + *c++ = printable_char(*cp++); + *c++ = printable_char(*cp++); + addr += 4; + case 4: + *c++ = printable_char(*cp++); + *c++ = printable_char(*cp++); + addr += 2; + case 2: + *c++ = printable_char(*cp++); + addr++; + case 1: + *c++ = printable_char(*cp++); + addr++; + break; + } +#undef printable_char + } + } + kdb_printf("%*s %s\n", (int)((num-i)*(2*bytesperword + 1)+1), " ", cbuf); +} + +static int +kdb_md(int argc, const char **argv) +{ + static kdb_machreg_t last_addr; + static int last_radix, last_bytesperword, last_repeat; + int radix = 16, mdcount = 8, bytesperword = KDB_WORD_SIZE, repeat; + int nosect = 0; + char fmtchar, fmtstr[64]; + kdb_machreg_t addr; + unsigned long word; + long offset = 0; + int symbolic = 0; + int valid = 0; + int phys = 0; + + kdbgetintenv("MDCOUNT", &mdcount); + kdbgetintenv("RADIX", &radix); + kdbgetintenv("BYTESPERWORD", &bytesperword); + + /* Assume 'md ' and start with environment values */ + repeat = mdcount * 16 / bytesperword; + + if (strcmp(argv[0], "mdr") == 0) { + if (argc != 2) + return KDB_ARGCOUNT; + valid = 1; + } else if (isdigit(argv[0][2])) { + bytesperword = (int)(argv[0][2] - '0'); + if (bytesperword == 0) { + bytesperword = last_bytesperword; + if (bytesperword == 0) { + bytesperword = 4; + } + } + last_bytesperword = bytesperword; + repeat = mdcount * 16 / bytesperword; + if (!argv[0][3]) + valid = 1; + else if (argv[0][3] == 'c' && argv[0][4]) { + char *p; + repeat = simple_strtoul(argv[0]+4, &p, 10); + mdcount = ((repeat * bytesperword) + 15) / 16; + valid = !*p; + } + last_repeat = repeat; + } else if (strcmp(argv[0], "md") == 0) + valid = 1; + else if (strcmp(argv[0], "mds") == 0) + valid = 1; + else if (strcmp(argv[0], "mdp") == 0) { + phys = valid = 1; + } + if (!valid) + return KDB_NOTFOUND; + + if (argc == 0) { + if (last_addr == 0) + return KDB_ARGCOUNT; + addr = last_addr; + radix = last_radix; + bytesperword = last_bytesperword; + repeat = last_repeat; + mdcount = ((repeat * bytesperword) + 15) / 16; + } + + if (argc) { + kdb_machreg_t val; + int diag, nextarg = 1; + diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL); + if (diag) + return diag; + if (argc > nextarg+2) + return KDB_ARGCOUNT; + + if (argc >= nextarg) { + diag = kdbgetularg(argv[nextarg], &val); + if (!diag) { + mdcount = (int) val; + repeat = mdcount * 16 / bytesperword; + } + } + if (argc >= nextarg+1) { + diag = kdbgetularg(argv[nextarg+1], &val); + if (!diag) + radix = (int) val; + } + } + + if (strcmp(argv[0], "mdr") == 0) { + return kdb_mdr(addr, mdcount); + } + + switch (radix) { + case 10: + fmtchar = 'd'; + break; + case 16: + fmtchar = 'x'; + break; + case 8: + fmtchar = 'o'; + break; + default: + return KDB_BADRADIX; + } + + last_radix = radix; + + if (bytesperword > KDB_WORD_SIZE) + return KDB_BADWIDTH; + + switch (bytesperword) { + case 8: + sprintf(fmtstr, "%%16.16l%c ", fmtchar); + break; + case 4: + sprintf(fmtstr, "%%8.8l%c ", fmtchar); + break; + case 2: + sprintf(fmtstr, "%%4.4l%c ", fmtchar); + break; + case 1: + sprintf(fmtstr, "%%2.2l%c ", fmtchar); + break; + default: + return KDB_BADWIDTH; + } + + last_repeat = repeat; + last_bytesperword = bytesperword; + + if (strcmp(argv[0], "mds") == 0) { + symbolic = 1; + /* Do not save these changes as last_*, they are temporary mds + * overrides. + */ + bytesperword = KDB_WORD_SIZE; + repeat = mdcount; + kdbgetintenv("NOSECT", &nosect); + } + + /* Round address down modulo BYTESPERWORD */ + + addr &= ~(bytesperword-1); + + while (repeat > 0) { + unsigned long a; + int n, z, num = (symbolic ? 1 : (16 / bytesperword)); + + for (a = addr, z = 0; z < repeat; a += bytesperword, ++z) { + if (phys) { + if (kdb_getphysword(&word, a, bytesperword) + || word) + break; + } else if (kdb_getword(&word, a, bytesperword) || word) + break; + } + n = min(num, repeat); + kdb_md_line(fmtstr, addr, symbolic, nosect, bytesperword, num, repeat, phys); + addr += bytesperword * n; + repeat -= n; + z = (z + num - 1) / num; + if (z > 2) { + int s = num * (z-2); + kdb_printf(kdb_machreg_fmt0 "-" kdb_machreg_fmt0 " zero suppressed\n", + addr, addr + bytesperword * s - 1); + addr += bytesperword * s; + repeat -= s; + } + } + last_addr = addr; + + return 0; +} + +/* + * kdb_mm + * + * This function implements the 'mm' command. + * + * mm address-expression new-value + * + * Inputs: + * argc argument count + * argv argument vector + * Outputs: + * None. + * Returns: + * zero for success, a kdb diagnostic if error + * Locking: + * none. + * Remarks: + * mm works on machine words, mmW works on bytes. + */ + +static int +kdb_mm(int argc, const char **argv) +{ + int diag; + kdb_machreg_t addr; + long offset = 0; + unsigned long contents; + int nextarg; + int width; + + if (argv[0][2] && !isdigit(argv[0][2])) + return KDB_NOTFOUND; + + if (argc < 2) { + return KDB_ARGCOUNT; + } + + nextarg = 1; + if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL))) + return diag; + + if (nextarg > argc) + return KDB_ARGCOUNT; + + if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &contents, NULL, NULL))) + return diag; + + if (nextarg != argc + 1) + return KDB_ARGCOUNT; + + width = argv[0][2] ? (argv[0][2] - '0') : (KDB_WORD_SIZE); + if ((diag = kdb_putword(addr, contents, width))) + return diag; + + kdb_printf(kdb_machreg_fmt " = " kdb_machreg_fmt "\n", addr, contents); + + return 0; +} + +/* + * kdb_go + * + * This function implements the 'go' command. + * + * go [address-expression] + * + * Inputs: + * argc argument count + * argv argument vector + * Outputs: + * None. + * Returns: + * KDB_CMD_GO for success, a kdb diagnostic if error + * Locking: + * none. + * Remarks: + */ + +static int +kdb_go(int argc, const char **argv) +{ + kdb_machreg_t addr; + int diag; + int nextarg; + long offset; + // HACK HACK HACK + // struct pt_regs *regs = get_irq_regs(); + + if (argc == 1) { + if (smp_processor_id() != kdb_initial_cpu) { + kdb_printf("go
must be issued from the initial cpu, do cpu %d first\n", kdb_initial_cpu); + return KDB_ARGCOUNT; + } + nextarg = 1; + diag = kdbgetaddrarg(argc, argv, &nextarg, + &addr, &offset, NULL); + if (diag) + return diag; + + //kdba_setpc(regs, addr); + // HACK HACK HACK + + } else if (argc) + return KDB_ARGCOUNT; + + diag = KDB_CMD_GO; + if (KDB_FLAG(CATASTROPHIC)) { + kdb_printf("Catastrophic error detected\n"); + kdb_printf("kdb_continue_catastrophic=%d, ", + kdb_continue_catastrophic); + if (kdb_continue_catastrophic == 0 && kdb_go_count++ == 0) { + kdb_printf("type go a second time if you really want to continue\n"); + return 0; + } + if (kdb_continue_catastrophic == 2) { + kdb_do_dump(); + kdb_printf("forcing reboot\n"); + kdb_reboot(0, NULL); + } + kdb_printf("attempting to continue\n"); + } + if (smp_processor_id() != kdb_initial_cpu) { + char buf[80]; + kdb_printf("go was not issued from initial cpu, switching back to cpu %d\n", kdb_initial_cpu); + sprintf(buf, "cpu %d\n", kdb_initial_cpu); + /* Recursive use of kdb_parse, do not use argv after this point */ + argv = NULL; + diag = kdb_parse(buf); + if (diag == KDB_CMD_CPU) + KDB_STATE_SET_CPU(GO_SWITCH, kdb_initial_cpu); + } + return diag; +} + +/* + * kdb_rd + * + * This function implements the 'rd' command. + * + * rd display all general registers. + * rd c display all control registers. + * rd d display all debug registers. + * + * Inputs: + * argc argument count + * argv argument vector + * Outputs: + * None. + * Returns: + * zero for success, a kdb diagnostic if error + * Locking: + * none. + * Remarks: + */ + +static int +kdb_rd(int argc, const char **argv) +{ + int diag; + if (argc == 0) { + if ((diag = kdb_check_regs())) + return diag; + return kdba_dumpregs(kdb_current_regs, NULL, NULL); + } + + if (argc > 2) { + return KDB_ARGCOUNT; + } + + if ((diag = kdb_check_regs())) + return diag; + return kdba_dumpregs(kdb_current_regs, argv[1], argc==2 ? argv[2]: NULL); +} + +/* + * kdb_rm + * + * This function implements the 'rm' (register modify) command. + * + * rm register-name new-contents + * + * Inputs: + * argc argument count + * argv argument vector + * Outputs: + * None. + * Returns: + * zero for success, a kdb diagnostic if error + * Locking: + * none. + * Remarks: + * Currently doesn't allow modification of control or + * debug registers. + */ + +static int +kdb_rm(int argc, const char **argv) +{ + int diag; + int ind = 0; + kdb_machreg_t contents; + + if (argc != 2) { + return KDB_ARGCOUNT; + } + + /* + * Allow presence or absence of leading '%' symbol. + */ + + if (argv[1][0] == '%') + ind = 1; + + diag = kdbgetularg(argv[2], &contents); + if (diag) + return diag; + + if ((diag = kdb_check_regs())) + return diag; + // diag = kdba_setregcontents(&argv[1][ind], kdb_current_regs, contents); + // HACK HACK HACK + diag = 0; + + if (diag) + return diag; + + return 0; +} + +#if defined(CONFIG_MAGIC_SYSRQ) +/* + * kdb_sr + * + * This function implements the 'sr' (SYSRQ key) command which + * interfaces to the soi-disant MAGIC SYSRQ functionality. + * + * sr + * + * Inputs: + * argc argument count + * argv argument vector + * Outputs: + * None. + * Returns: + * zero for success, a kdb diagnostic if error + * Locking: + * none. + * Remarks: + * None. + */ +static int +kdb_sr(int argc, const char **argv) +{ + extern int __sysrq_enabled; + if (argc != 1) { + return KDB_ARGCOUNT; + } + if (!__sysrq_enabled) { + kdb_printf("Auto activating sysrq\n"); + __sysrq_enabled = 1; + } + + handle_sysrq(*argv[1], NULL); + + return 0; +} +#endif /* CONFIG_MAGIC_SYSRQ */ + +/* + * kdb_ef + * + * This function implements the 'regs' (display exception frame) + * command. This command takes an address and expects to find + * an exception frame at that address, formats and prints it. + * + * regs address-expression + * + * Inputs: + * argc argument count + * argv argument vector + * Outputs: + * None. + * Returns: + * zero for success, a kdb diagnostic if error + * Locking: + * none. + * Remarks: + * Not done yet. + */ + +static int +kdb_ef(int argc, const char **argv) +{ + int diag; + kdb_machreg_t addr; + long offset; + int nextarg; + + if (argc == 1) { + nextarg = 1; + diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL); + if (diag) + return diag; + + //return kdba_dumpregs((struct pt_regs *)addr, NULL, NULL); + // HACK HACK HACK + return 0; + } + + return KDB_ARGCOUNT; +} + +#if defined(CONFIG_MODULES) +extern struct list_head *kdb_modules; +extern void free_module(struct module *); + +/* modules using other modules */ +struct module_use +{ + struct list_head list; + struct module *module_which_uses; +}; + +/* + * kdb_lsmod + * + * This function implements the 'lsmod' command. Lists currently + * loaded kernel modules. + * + * Mostly taken from userland lsmod. + * + * Inputs: + * argc argument count + * argv argument vector + * Outputs: + * None. + * Returns: + * zero for success, a kdb diagnostic if error + * Locking: + * none. + * Remarks: + * + */ + +static int +kdb_lsmod(int argc, const char **argv) +{ + struct module *mod; + + if (argc != 0) + return KDB_ARGCOUNT; + + kdb_printf("Module Size modstruct Used by\n"); + list_for_each_entry(mod, kdb_modules, list) { + + kdb_printf("%-20s%8u 0x%p ", mod->name, + mod->core_size, (void *)mod); +#ifdef CONFIG_MODULE_UNLOAD + kdb_printf("%4d ", module_refcount(mod)); +#endif + if (mod->state == MODULE_STATE_GOING) + kdb_printf(" (Unloading)"); + else if (mod->state == MODULE_STATE_COMING) + kdb_printf(" (Loading)"); + else + kdb_printf(" (Live)"); + +#ifdef CONFIG_MODULE_UNLOAD + { + struct module_use *use; + kdb_printf(" [ "); + list_for_each_entry(use, &mod->modules_which_use_me, list) + kdb_printf("%s ", use->module_which_uses->name); + kdb_printf("]\n"); + } +#endif + } + + return 0; +} + +#endif /* CONFIG_MODULES */ + +/* + * kdb_env + * + * This function implements the 'env' command. Display the current + * environment variables. + * + * Inputs: + * argc argument count + * argv argument vector + * Outputs: + * None. + * Returns: + * zero for success, a kdb diagnostic if error + * Locking: + * none. + * Remarks: + */ + +static int +kdb_env(int argc, const char **argv) +{ + int i; + + for(i=0; i<__nenv; i++) { + if (__env[i]) { + kdb_printf("%s\n", __env[i]); + } + } + + if (KDB_DEBUG(MASK)) + kdb_printf("KDBFLAGS=0x%x\n", kdb_flags); + + return 0; +} + +/* + * kdb_dmesg + * + * This function implements the 'dmesg' command to display the contents + * of the syslog buffer. + * + * dmesg [lines] [adjust] + * + * Inputs: + * argc argument count + * argv argument vector + * Outputs: + * None. + * Returns: + * zero for success, a kdb diagnostic if error + * Locking: + * none. + * Remarks: + * None. + */ + +static int +kdb_dmesg(int argc, const char **argv) +{ + char *syslog_data[4], *start, *end, c = '\0', *p; + int diag, logging, logsize, lines = 0, adjust = 0, n; + + if (argc > 2) + return KDB_ARGCOUNT; + if (argc) { + char *cp; + lines = simple_strtol(argv[1], &cp, 0); + if (*cp) + lines = 0; + if (argc > 1) { + adjust = simple_strtoul(argv[2], &cp, 0); + if (*cp || adjust < 0) + adjust = 0; + } + } + + /* disable LOGGING if set */ + diag = kdbgetintenv("LOGGING", &logging); + if (!diag && logging) { + const char *setargs[] = { "set", "LOGGING", "0" }; + kdb_set(2, setargs); + } + + /* syslog_data[0,1] physical start, end+1. syslog_data[2,3] logical start, end+1. */ + kdb_syslog_data(syslog_data); + if (syslog_data[2] == syslog_data[3]) + return 0; + logsize = syslog_data[1] - syslog_data[0]; + start = syslog_data[2]; + end = syslog_data[3]; +#define KDB_WRAP(p) (((p - syslog_data[0]) % logsize) + syslog_data[0]) + for (n = 0, p = start; p < end; ++p) { + if ((c = *KDB_WRAP(p)) == '\n') + ++n; + } + if (c != '\n') + ++n; + if (lines < 0) { + if (adjust >= n) + kdb_printf("buffer only contains %d lines, nothing printed\n", n); + else if (adjust - lines >= n) + kdb_printf("buffer only contains %d lines, last %d lines printed\n", + n, n - adjust); + if (adjust) { + for (; start < end && adjust; ++start) { + if (*KDB_WRAP(start) == '\n') + --adjust; + } + if (start < end) + ++start; + } + for (p = start; p < end && lines; ++p) { + if (*KDB_WRAP(p) == '\n') + ++lines; + } + end = p; + } else if (lines > 0) { + int skip = n - (adjust + lines); + if (adjust >= n) { + kdb_printf("buffer only contains %d lines, nothing printed\n", n); + skip = n; + } else if (skip < 0) { + lines += skip; + skip = 0; + kdb_printf("buffer only contains %d lines, first %d lines printed\n", + n, lines); + } + for (; start < end && skip; ++start) { + if (*KDB_WRAP(start) == '\n') + --skip; + } + for (p = start; p < end && lines; ++p) { + if (*KDB_WRAP(p) == '\n') + --lines; + } + end = p; + } + /* Do a line at a time (max 200 chars) to reduce protocol overhead */ + c = '\n'; + while (start != end) { + char buf[201]; + p = buf; + while (start < end && (c = *KDB_WRAP(start)) && (p - buf) < sizeof(buf)-1) { + ++start; + *p++ = c; + if (c == '\n') + break; + } + *p = '\0'; + kdb_printf("%s", buf); + } + if (c != '\n') + kdb_printf("\n"); + + return 0; +} + +/* + * kdb_cpu + * + * This function implements the 'cpu' command. + * + * cpu [] + * + * Inputs: + * argc argument count + * argv argument vector + * Outputs: + * None. + * Returns: + * KDB_CMD_CPU for success, a kdb diagnostic if error + * Locking: + * none. + * Remarks: + * All cpu's should be spinning in kdb(). However just in case + * a cpu did not take the smp_kdb_stop NMI, check that a cpu + * entered kdb() before passing control to it. + */ + +static void +kdb_cpu_status(void) +{ + int i, start_cpu, first_print = 1; + char state, prev_state = '?'; + + kdb_printf("Currently on cpu %d\n", smp_processor_id()); + kdb_printf("Available cpus: "); + for (start_cpu = -1, i = 0; i < NR_CPUS; i++) { + if (!cpu_online(i)) + state = 'F'; /* cpu is offline */ + else { + struct kdb_running_process *krp = kdb_running_process+i; + if (KDB_STATE_CPU(KDB, i)) { + state = ' '; /* cpu is responding to kdb */ + if (kdb_task_state_char(krp->p) == 'I') + state = 'I'; /* running the idle task */ + } else if (krp->seqno && krp->p && krp->seqno >= kdb_seqno - 1) + state = '+'; /* some kdb data, but not responding */ + else + state = '*'; /* no kdb data */ + } + if (state != prev_state) { + if (prev_state != '?') { + if (!first_print) + kdb_printf(", "); + first_print = 0; + kdb_printf("%d", start_cpu); + if (start_cpu < i-1) + kdb_printf("-%d", i-1); + if (prev_state != ' ') + kdb_printf("(%c)", prev_state); + } + prev_state = state; + start_cpu = i; + } + } + /* print the trailing cpus, ignoring them if they are all offline */ + if (prev_state != 'F') { + if (!first_print) + kdb_printf(", "); + kdb_printf("%d", start_cpu); + if (start_cpu < i-1) + kdb_printf("-%d", i-1); + if (prev_state != ' ') + kdb_printf("(%c)", prev_state); + } + kdb_printf("\n"); +} + +static int +kdb_cpu(int argc, const char **argv) +{ + unsigned long cpunum; + int diag, i; + + /* ask the other cpus if they are still active */ + for (i=0; i NR_CPUS) + || !cpu_online(cpunum) + || !KDB_STATE_CPU(KDB, cpunum)) + return KDB_BADCPUNUM; + + kdb_new_cpu = cpunum; + + /* + * Switch to other cpu + */ + return KDB_CMD_CPU; +} + +/* The user may not realize that ps/bta with no parameters does not print idle + * or sleeping system daemon processes, so tell them how many were suppressed. + */ +void +kdb_ps_suppressed(void) +{ + int idle = 0, daemon = 0; + unsigned long mask_I = kdb_task_state_string("I"), + mask_M = kdb_task_state_string("M"); + unsigned long cpu; + const struct task_struct *p, *g; + for (cpu = 0; cpu < NR_CPUS; ++cpu) { + if (!cpu_online(cpu)) + continue; + p = kdb_curr_task(cpu); + if (kdb_task_state(p, mask_I)) + ++idle; + } + kdb_do_each_thread(g, p) { + if (kdb_task_state(p, mask_M)) + ++daemon; + } kdb_while_each_thread(g, p); + if (idle || daemon) { + if (idle) + kdb_printf("%d idle process%s (state I)%s\n", + idle, idle == 1 ? "" : "es", + daemon ? " and " : ""); + if (daemon) + kdb_printf("%d sleeping system daemon (state M) process%s", + daemon, daemon == 1 ? "" : "es"); + kdb_printf(" suppressed,\nuse 'ps A' to see all.\n"); + } +} + +/* + * kdb_ps + * + * This function implements the 'ps' command which shows + * a list of the active processes. + * + * ps [DRSTCZEUIMA] All processes, optionally filtered by state + * + * Inputs: + * argc argument count + * argv argument vector + * Outputs: + * None. + * Returns: + * zero for success, a kdb diagnostic if error + * Locking: + * none. + * Remarks: + */ + +void +kdb_ps1(const struct task_struct *p) +{ + struct kdb_running_process *krp = kdb_running_process + kdb_process_cpu(p); + kdb_printf("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), + kdb_task_state_char(p), + (void *)(&p->thread), + p == kdb_curr_task(smp_processor_id()) ? '*': ' ', + p->comm); + if (kdb_task_has_cpu(p)) { + if (!krp->seqno || !krp->p) + kdb_printf(" Error: no saved data for this cpu\n"); + else { + if (krp->seqno < kdb_seqno - 1) + kdb_printf(" Warning: process state is stale\n"); + if (krp->p != p) + kdb_printf(" Error: does not match running process table (0x%p)\n", krp->p); + } + } +} + +static int +kdb_ps(int argc, const char **argv) +{ + struct task_struct *g, *p; + unsigned long mask, cpu; + + if (argc == 0) + kdb_ps_suppressed(); + kdb_printf("%-*s Pid Parent [*] cpu State %-*s Command\n", + (int)(2*sizeof(void *))+2, "Task Addr", + (int)(2*sizeof(void *))+2, "Thread"); + mask = kdb_task_state_string(argc ? argv[1] : NULL); + /* Run the active tasks first */ + for (cpu = 0; cpu < NR_CPUS; ++cpu) { + if (!cpu_online(cpu)) + continue; + p = kdb_curr_task(cpu); + if (kdb_task_state(p, mask)) + kdb_ps1(p); + } + kdb_printf("\n"); + /* Now the real tasks */ + kdb_do_each_thread(g, p) { + if (kdb_task_state(p, mask)) + kdb_ps1(p); + } kdb_while_each_thread(g, p); + + return 0; +} + +/* + * kdb_pid + * + * This function implements the 'pid' command which switches + * the currently active process. + * + * pid [ | R] + * + * Inputs: + * argc argument count + * argv argument vector + * Outputs: + * None. + * Returns: + * zero for success, a kdb diagnostic if error + * Locking: + * none. + * Remarks: + */ + + +static int +kdb_pid(int argc, const char **argv) +{ + struct task_struct *p; + unsigned long val; + int diag; + + if (argc > 1) + return KDB_ARGCOUNT; + + if (argc) { + if (strcmp(argv[1], "R") == 0) { + p = KDB_RUNNING_PROCESS_ORIGINAL[kdb_initial_cpu].p; + } else { + diag = kdbgetularg(argv[1], &val); + if (diag) + return KDB_BADINT; + + p = find_task_by_pid_type_ns(PIDTYPE_PID, (pid_t)val, + &init_pid_ns); + if (!p) { + kdb_printf("No task with pid=%d\n", (pid_t)val); + return 0; + } + } + + // kdba_set_current_task(p); + // HACK HACK HACK + printk(KERN_CRIT "DOH NEED TO IMPLEMENT THIS!"); + } + + kdb_printf("KDB current process is %s(pid=%d)\n", kdb_current_task->comm, + kdb_current_task->pid); + + return 0; +} + +/* + * kdb_ll + * + * This function implements the 'll' command which follows a linked + * list and executes an arbitrary command for each element. + * + * Inputs: + * argc argument count + * argv argument vector + * Outputs: + * None. + * Returns: + * zero for success, a kdb diagnostic if error + * Locking: + * none. + * Remarks: + */ + +static int +kdb_ll(int argc, const char **argv) +{ + int diag; + kdb_machreg_t addr; + long offset = 0; + kdb_machreg_t va; + unsigned long linkoffset; + int nextarg; + const char *command; + + if (argc != 3) { + return KDB_ARGCOUNT; + } + + nextarg = 1; + diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL); + if (diag) + return diag; + + diag = kdbgetularg(argv[2], &linkoffset); + if (diag) + return diag; + + /* + * Using the starting address as + * the first element in the list, and assuming that + * the list ends with a null pointer. + */ + + va = addr; + if (!(command = kdb_strdup(argv[3], GFP_KDB))) { + kdb_printf("%s: cannot duplicate command\n", __FUNCTION__); + return 0; + } + /* Recursive use of kdb_parse, do not use argv after this point */ + argv = NULL; + + while (va) { + char buf[80]; + + sprintf(buf, "%s " kdb_machreg_fmt "\n", command, va); + diag = kdb_parse(buf); + if (diag) + return diag; + + addr = va + linkoffset; + if (kdb_getword(&va, addr, sizeof(va))) + return 0; + } + kfree(command); + + return 0; +} + +static int +kdb_kgdb(int argc, const char **argv) +{ + return KDB_CMD_KGDB; +} + +/* + * kdb_help + * + * This function implements the 'help' and '?' commands. + * + * Inputs: + * argc argument count + * argv argument vector + * Outputs: + * None. + * Returns: + * zero for success, a kdb diagnostic if error + * Locking: + * none. + * Remarks: + */ + +static int +kdb_help(int argc, const char **argv) +{ + kdbtab_t *kt; + int i; + + kdb_printf("%-15.15s %-20.20s %s\n", "Command", "Usage", "Description"); + kdb_printf("----------------------------------------------------------\n"); + for(i=0, kt=kdb_commands; icmd_name) + kdb_printf("%-15.15s %-20.20s %s\n", kt->cmd_name, + kt->cmd_usage, kt->cmd_help); + } + return 0; +} + +extern int kdb_wake_up_process(struct task_struct * p); + +/* + * kdb_kill + * + * This function implements the 'kill' commands. + * + * Inputs: + * argc argument count + * argv argument vector + * Outputs: + * None. + * Returns: + * zero for success, a kdb diagnostic if error + * Locking: + * none. + * Remarks: + */ + +static int +kdb_kill(int argc, const char **argv) +{ + long sig, pid; + char *endp; + struct task_struct *p; + struct siginfo info; + + if (argc!=2) + return KDB_ARGCOUNT; + + sig = simple_strtol(argv[1], &endp, 0); + if (*endp) + return KDB_BADINT; + if (sig >= 0 ) { + kdb_printf("Invalid signal parameter.<-signal>\n"); + return 0; + } + sig=-sig; + + pid = simple_strtol(argv[2], &endp, 0); + if (*endp) + return KDB_BADINT; + if (pid <=0 ) { + kdb_printf("Process ID must be large than 0.\n"); + return 0; + } + + /* Find the process. */ + if (!(p = find_task_by_pid_type_ns(PIDTYPE_PID, pid, &init_pid_ns))) { + kdb_printf("The specified process isn't found.\n"); + return 0; + } + p = p->group_leader; + info.si_signo = sig; + info.si_errno = 0; + info.si_code = SI_USER; + info.si_pid = pid; /* use same capabilities as process being signalled */ + info.si_uid = 0; /* kdb has root authority */ + kdb_send_sig_info(p, &info, kdb_seqno); + return 0; +} + +struct kdb_tm { + int tm_sec; /* seconds */ + int tm_min; /* minutes */ + int tm_hour; /* hours */ + int tm_mday; /* day of the month */ + int tm_mon; /* month */ + int tm_year; /* year */ +}; + +static void +kdb_gmtime(struct timespec *tv, struct kdb_tm *tm) +{ + /* This will work from 1970-2099, 2100 is not a leap year */ + static int mon_day[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + memset(tm, 0, sizeof(*tm)); + tm->tm_sec = tv->tv_sec % (24 * 60 * 60); + tm->tm_mday = tv->tv_sec / (24 * 60 * 60) + (2 * 365 + 1); /* shift base from 1970 to 1968 */ + tm->tm_min = tm->tm_sec / 60 % 60; + tm->tm_hour = tm->tm_sec / 60 / 60; + tm->tm_sec = tm->tm_sec % 60; + tm->tm_year = 68 + 4*(tm->tm_mday / (4*365+1)); + tm->tm_mday %= (4*365+1); + mon_day[1] = 29; + while (tm->tm_mday >= mon_day[tm->tm_mon]) { + tm->tm_mday -= mon_day[tm->tm_mon]; + if (++tm->tm_mon == 12) { + tm->tm_mon = 0; + ++tm->tm_year; + mon_day[1] = 28; + } + } + ++tm->tm_mday; +} + +/* + * Most of this code has been lifted from kernel/timer.c::sys_sysinfo(). + * I cannot call that code directly from kdb, it has an unconditional + * cli()/sti() and calls routines that take locks which can stop the debugger. + */ + +static void +kdb_sysinfo(struct sysinfo *val) +{ + struct timespec uptime; + do_posix_clock_monotonic_gettime(&uptime); + memset(val, 0, sizeof(*val)); + val->uptime = uptime.tv_sec; + val->loads[0] = avenrun[0]; + val->loads[1] = avenrun[1]; + val->loads[2] = avenrun[2]; + val->procs = nr_threads-1; + si_meminfo(val); + kdb_si_swapinfo(val); + + return; +} + +/* + * kdb_summary + * + * This function implements the 'summary' command. + * + * Inputs: + * argc argument count + * argv argument vector + * Outputs: + * None. + * Returns: + * zero for success, a kdb diagnostic if error + * Locking: + * none. + * Remarks: + */ + +static int +kdb_summary(int argc, const char **argv) +{ + extern struct timespec xtime; + extern struct timezone sys_tz; + struct kdb_tm tm; + struct sysinfo val; + + if (argc) + return KDB_ARGCOUNT; + + kdb_printf("sysname %s\n", init_uts_ns.name.sysname); + kdb_printf("release %s\n", init_uts_ns.name.release); + kdb_printf("version %s\n", init_uts_ns.name.version); + kdb_printf("machine %s\n", init_uts_ns.name.machine); + kdb_printf("nodename %s\n", init_uts_ns.name.nodename); + kdb_printf("domainname %s\n", init_uts_ns.name.domainname); + kdb_printf("ccversion %s\n", __stringify(CCVERSION)); + + kdb_gmtime(&xtime, &tm); + kdb_printf("date %04d-%02d-%02d %02d:%02d:%02d tz_minuteswest %d\n", + 1900+tm.tm_year, tm.tm_mon+1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec, + sys_tz.tz_minuteswest); + + kdb_sysinfo(&val); + kdb_printf("uptime "); + if (val.uptime > (24*60*60)) { + int days = val.uptime / (24*60*60); + val.uptime %= (24*60*60); + kdb_printf("%d day%s ", days, days == 1 ? "" : "s"); + } + kdb_printf("%02ld:%02ld\n", val.uptime/(60*60), (val.uptime/60)%60); + + /* lifted from fs/proc/proc_misc.c::loadavg_read_proc() */ + +#define LOAD_INT(x) ((x) >> FSHIFT) +#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100) + kdb_printf("load avg %ld.%02ld %ld.%02ld %ld.%02ld\n", + LOAD_INT(val.loads[0]), LOAD_FRAC(val.loads[0]), + LOAD_INT(val.loads[1]), LOAD_FRAC(val.loads[1]), + LOAD_INT(val.loads[2]), LOAD_FRAC(val.loads[2])); + kdb_printf("\n"); +#undef LOAD_INT +#undef LOAD_FRAC + + kdb_meminfo_proc_show(); /* in fs/proc/meminfo.c */ + + return 0; +} + +/* + * kdb_per_cpu + * + * This function implements the 'per_cpu' command. + * + * Inputs: + * argc argument count + * argv argument vector + * Outputs: + * None. + * Returns: + * zero for success, a kdb diagnostic if error + * Locking: + * none. + * Remarks: + */ + +static int +kdb_per_cpu(int argc, const char **argv) +{ + char buf[256], fmtstr[64]; + kdb_symtab_t symtab; + cpumask_t suppress = CPU_MASK_NONE; + int cpu, diag; + unsigned long addr, val, bytesperword = 0, whichcpu = ~0UL; + + if (argc < 1 || argc > 3) + return KDB_ARGCOUNT; + + snprintf(buf, sizeof(buf), "per_cpu__%s", argv[1]); + if (!kdbgetsymval(buf, &symtab)) { + kdb_printf("%s is not a per_cpu variable\n", argv[1]); + return KDB_BADADDR; + } + if (argc >=2 && (diag = kdbgetularg(argv[2], &bytesperword))) + return diag; + if (!bytesperword) + bytesperword = KDB_WORD_SIZE; + else if (bytesperword > KDB_WORD_SIZE) + return KDB_BADWIDTH; + sprintf(fmtstr, "%%0%dlx ", (int)(2*bytesperword)); + if (argc >= 3) { + if ((diag = kdbgetularg(argv[3], &whichcpu))) + return diag; + if (!cpu_online(whichcpu)) { + kdb_printf("cpu %ld is not online\n", whichcpu); + return KDB_BADCPUNUM; + } + } + + /* Most architectures use __per_cpu_offset[cpu], some use + * __per_cpu_offset(cpu), smp has no __per_cpu_offset. + */ +#ifdef __per_cpu_offset +#define KDB_PCU(cpu) __per_cpu_offset(cpu) +#else +#ifdef CONFIG_SMP +#define KDB_PCU(cpu) __per_cpu_offset[cpu] +#else +#define KDB_PCU(cpu) 0 +#endif +#endif + + for_each_online_cpu(cpu) { + if (whichcpu != ~0UL && whichcpu != cpu) + continue; + addr = symtab.sym_start + KDB_PCU(cpu); + if ((diag = kdb_getword(&val, addr, bytesperword))) { + kdb_printf("%5d " kdb_bfd_vma_fmt0 " - unable to read, diag=%d\n", + cpu, addr, diag); + continue; + } +#ifdef CONFIG_SMP + if (!val) { + cpu_set(cpu, suppress); + continue; + } +#endif /* CONFIG_SMP */ + kdb_printf("%5d ", cpu); + kdb_md_line(fmtstr, addr, + bytesperword == KDB_WORD_SIZE, + 1, bytesperword, 1, 1, 0); + } + if (cpus_weight(suppress) == 0) + return 0; + kdb_printf("Zero suppressed cpu(s):"); + for (cpu = first_cpu(suppress); cpu < NR_CPUS; cpu = next_cpu(cpu, suppress)) { + kdb_printf(" %d", cpu); + if (cpu == NR_CPUS-1 || next_cpu(cpu, suppress) != cpu + 1) + continue; + while (cpu < NR_CPUS && next_cpu(cpu, suppress) == cpu + 1) + ++cpu; + kdb_printf("-%d", cpu); + } + kdb_printf("\n"); + +#undef KDB_PCU + + return 0; +} + +/* + * display help for the use of cmd | grep pattern + */ +static int +kdb_grep_help(int argc, const char **argv) +{ + kdb_printf("Usage of cmd args | grep pattern:\n"); + kdb_printf(" Any command's output may be filtered through an "); + kdb_printf("emulated 'pipe'.\n"); + kdb_printf(" 'grep' is just a key word.\n"); + kdb_printf(" The pattern may include a very limited set of metacharacters:\n"); + kdb_printf(" pattern or ^pattern or pattern$ or ^pattern$\n"); + kdb_printf(" And if there are spaces in the pattern, you may quote it:\n"); + kdb_printf(" \"pat tern\" or \"^pat tern\" or \"pat tern$\" or \"^pat tern$\"\n"); + return 0; +} + +/* + * kdb_register_repeat + * + * This function is used to register a kernel debugger command. + * + * Inputs: + * cmd Command name + * func Function to execute the command + * usage A simple usage string showing arguments + * help A simple help string describing command + * repeat Does the command auto repeat on enter? + * Outputs: + * None. + * Returns: + * zero for success, one if a duplicate command. + * Locking: + * none. + * Remarks: + * + */ + +#define kdb_command_extend 50 /* arbitrary */ +int +kdb_register_repeat(char *cmd, + kdb_func_t func, + char *usage, + char *help, + short minlen, + kdb_repeat_t repeat) +{ + int i; + kdbtab_t *kp; + + /* + * Brute force method to determine duplicates + */ + for (i=0, kp=kdb_commands; icmd_name && (strcmp(kp->cmd_name, cmd)==0)) { + kdb_printf("Duplicate kdb command registered: " + "%s, func %p help %s\n", cmd, func, help); + return 1; + } + } + + /* + * Insert command into first available location in table + */ + for (i=0, kp=kdb_commands; icmd_name == NULL) { + break; + } + } + + if (i >= kdb_max_commands) { + kdbtab_t *new = kmalloc((kdb_max_commands + kdb_command_extend) * sizeof(*new), GFP_KDB); + if (!new) { + kdb_printf("Could not allocate new kdb_command table\n"); + return 1; + } + if (kdb_commands) { + memcpy(new, kdb_commands, kdb_max_commands * sizeof(*new)); + kfree(kdb_commands); + } + memset(new + kdb_max_commands, 0, kdb_command_extend * sizeof(*new)); + kdb_commands = new; + kp = kdb_commands + kdb_max_commands; + kdb_max_commands += kdb_command_extend; + } + + kp->cmd_name = cmd; + kp->cmd_func = func; + kp->cmd_usage = usage; + kp->cmd_help = help; + kp->cmd_flags = 0; + kp->cmd_minlen = minlen; + kp->cmd_repeat = repeat; + + return 0; +} + +/* + * kdb_register + * + * Compatibility register function for commands that do not need to + * specify a repeat state. Equivalent to kdb_register_repeat with + * KDB_REPEAT_NONE. + * + * Inputs: + * cmd Command name + * func Function to execute the command + * usage A simple usage string showing arguments + * help A simple help string describing command + * Outputs: + * None. + * Returns: + * zero for success, one if a duplicate command. + * Locking: + * none. + * Remarks: + * + */ + +int +kdb_register(char *cmd, + kdb_func_t func, + char *usage, + char *help, + short minlen) +{ + return kdb_register_repeat(cmd, func, usage, help, minlen, KDB_REPEAT_NONE); +} + +/* + * kdb_unregister + * + * This function is used to unregister a kernel debugger command. + * It is generally called when a module which implements kdb + * commands is unloaded. + * + * Inputs: + * cmd Command name + * Outputs: + * None. + * Returns: + * zero for success, one command not registered. + * Locking: + * none. + * Remarks: + * + */ + +int +kdb_unregister(char *cmd) +{ + int i; + kdbtab_t *kp; + + /* + * find the command. + */ + for (i=0, kp=kdb_commands; icmd_name && (strcmp(kp->cmd_name, cmd)==0)) { + kp->cmd_name = NULL; + return 0; + } + } + + /* + * Couldn't find it. + */ + return 1; +} + +/* + * kdb_inittab + * + * This function is called by the kdb_init function to initialize + * the kdb command table. It must be called prior to any other + * call to kdb_register_repeat. + * + * Inputs: + * None. + * Outputs: + * None. + * Returns: + * None. + * Locking: + * None. + * Remarks: + * + */ + +static void __init +kdb_inittab(void) +{ + int i; + kdbtab_t *kp; + + for(i=0, kp=kdb_commands; i < kdb_max_commands; i++,kp++) { + kp->cmd_name = NULL; + } + + kdb_register_repeat("md", kdb_md, "", "Display Memory Contents, also mdWcN, e.g. md8c1", 1, KDB_REPEAT_NO_ARGS); + kdb_register_repeat("mdr", kdb_md, " ", "Display Raw Memory", 0, KDB_REPEAT_NO_ARGS); + kdb_register_repeat("mdp", kdb_md, " ", "Display Physical Memory", 0, KDB_REPEAT_NO_ARGS); + kdb_register_repeat("mds", kdb_md, "", "Display Memory Symbolically", 0, KDB_REPEAT_NO_ARGS); + kdb_register_repeat("mm", kdb_mm, " ", "Modify Memory Contents", 0, KDB_REPEAT_NO_ARGS); + // kdb_register_repeat("id", kdb_id, "", "Display Instructions", 1, KDB_REPEAT_NO_ARGS); + // HACK HACK HACK + kdb_register_repeat("go", kdb_go, "[]", "Continue Execution", 1, KDB_REPEAT_NONE); + kdb_register_repeat("rd", kdb_rd, "", "Display Registers", 1, KDB_REPEAT_NONE); + kdb_register_repeat("rm", kdb_rm, " ", "Modify Registers", 0, KDB_REPEAT_NONE); + kdb_register_repeat("ef", kdb_ef, "", "Display exception frame", 0, KDB_REPEAT_NONE); + kdb_register_repeat("bt", kdb_bt, "[]", "Stack traceback", 1, KDB_REPEAT_NONE); + kdb_register_repeat("btp", kdb_bt, "", "Display stack for process ", 0, KDB_REPEAT_NONE); + kdb_register_repeat("bta", kdb_bt, "[DRSTCZEUIMA]", "Display stack all processes", 0, KDB_REPEAT_NONE); + kdb_register_repeat("btc", kdb_bt, "", "Backtrace current process on each cpu", 0, KDB_REPEAT_NONE); + kdb_register_repeat("btt", kdb_bt, "", "Backtrace process given its struct task address", 0, KDB_REPEAT_NONE); + kdb_register_repeat("ll", kdb_ll, " ", "Execute cmd for each element in linked list", 0, KDB_REPEAT_NONE); + kdb_register_repeat("env", kdb_env, "", "Show environment variables", 0, KDB_REPEAT_NONE); + kdb_register_repeat("set", kdb_set, "", "Set environment variables", 0, KDB_REPEAT_NONE); + kdb_register_repeat("help", kdb_help, "", "Display Help Message", 1, KDB_REPEAT_NONE); + kdb_register_repeat("?", kdb_help, "", "Display Help Message", 0, KDB_REPEAT_NONE); + kdb_register_repeat("kgdb", kdb_kgdb, "", "Enter kgdb mode", 0, KDB_REPEAT_NONE); + kdb_register_repeat("cpu", kdb_cpu, "","Switch to new cpu", 0, KDB_REPEAT_NONE); + kdb_register_repeat("ps", kdb_ps, "[|A]", "Display active task list", 0, KDB_REPEAT_NONE); + kdb_register_repeat("pid", kdb_pid, "", "Switch to another task", 0, KDB_REPEAT_NONE); + kdb_register_repeat("reboot", kdb_reboot, "", "Reboot the machine immediately", 0, KDB_REPEAT_NONE); +#if defined(CONFIG_KDB_KDUMP) + kdb_register_repeat("kdump", kdb_kdump, "", "Calls kdump mode", 0, KDB_REPEAT_NONE); +#endif +#if defined(CONFIG_MODULES) + kdb_register_repeat("lsmod", kdb_lsmod, "", "List loaded kernel modules", 0, KDB_REPEAT_NONE); +#endif +#if defined(CONFIG_MAGIC_SYSRQ) + kdb_register_repeat("sr", kdb_sr, "", "Magic SysRq key", 0, KDB_REPEAT_NONE); +#endif + kdb_register_repeat("dmesg", kdb_dmesg, "[lines]", "Display syslog buffer", 0, KDB_REPEAT_NONE); + kdb_register_repeat("defcmd", kdb_defcmd, "name \"usage\" \"help\"", "Define a set of commands, down to endefcmd", 0, KDB_REPEAT_NONE); + kdb_register_repeat("kill", kdb_kill, "<-signal> ", "Send a signal to a process", 0, KDB_REPEAT_NONE); + kdb_register_repeat("summary", kdb_summary, "", "Summarize the system", 4, KDB_REPEAT_NONE); + kdb_register_repeat("per_cpu", kdb_per_cpu, "", "Display per_cpu variables", 3, KDB_REPEAT_NONE); + kdb_register_repeat("grephelp", kdb_grep_help, "", + "Display help on | grep", 0, KDB_REPEAT_NONE); +#ifdef CONFIG_KDB_LKCRASH + kdb_register_repeat("print", kdb_debuginfo_print, "", + "Type casting, as in lcrash", 0, KDB_REPEAT_NONE); + kdb_register_repeat("px", kdb_debuginfo_print, "", + "Print in hex (type casting) (see 'pxhelp')", 0, KDB_REPEAT_NONE); + kdb_register_repeat("pxhelp", kdb_pxhelp, "", + "Display help for the px command", 0, KDB_REPEAT_NONE); + kdb_register_repeat("pd", kdb_debuginfo_print, "", + "Print in decimal (type casting)", 0, KDB_REPEAT_NONE); + kdb_register_repeat("whatis", kdb_debuginfo_print,"", + "Display the type, or the address for a symbol", 0, KDB_REPEAT_NONE); + kdb_register_repeat("sizeof", kdb_debuginfo_print, "", + "Display the size of a structure, typedef, etc.", 0, KDB_REPEAT_NONE); + kdb_register_repeat("walk", kdb_walk, "", + "Walk a linked list (see 'walkhelp')", 0, KDB_REPEAT_NONE); + kdb_register_repeat("walkhelp", kdb_walkhelp, "", + "Display help for the walk command", 0, KDB_REPEAT_NONE); +#endif +} + +/* + * kdb_cmd_init + * + * This function is called by the kdb_init function to execute any + * commands defined in kdb_cmds. + * + * Inputs: + * Commands in *kdb_cmds[]; + * Outputs: + * None. + * Returns: + * None. + * Locking: + * None. + * Remarks: + * + */ + +static void __init +kdb_cmd_init(void) +{ + int i, diag; + for (i = 0; kdb_cmds[i]; ++i) { + diag = kdb_parse(kdb_cmds[i]); + if (diag) + kdb_printf("kdb command %s failed, kdb diag %d\n", + kdb_cmds[i], diag); + } + if (defcmd_in_progress) { + kdb_printf("Incomplete 'defcmd' set, forcing endefcmd\n"); + kdb_parse("endefcmd"); + } +} + +/* + * kdb_init + * + * Initialize the kernel debugger environment. + * + * Parameters: + * None. + * Returns: + * None. + * Locking: + * None. + * Remarks: + * None. + */ + +void __init +kdb_init(void) +{ + kdb_initial_cpu = smp_processor_id(); + /* + * This must be called before any calls to kdb_printf. + */ + // Start hacking away... kgdb does a lot of the same things already + // kdb_io_init(); + // HACK HACK HACK + + kdb_inittab(); /* Initialize Command Table */ + kdb_initbptab(); /* Initialize Breakpoint Table */ + // kdb_id_init(); /* Initialize Disassembler */ + // kdba_init(); /* Architecture Dependent Initialization */ + // HACK HACK HACK + + /* + * Use printk() to get message in log_buf[]; + */ + + kdb_cmd_init(); /* Preset commands from kdb_cmds */ + kdb_initial_cpu = -1; /* Avoid recursion problems */ + return; + // HACK HACK HACK + // kdb(KDB_REASON_CPU_UP, 0, NULL); /* do kdb setup on boot cpu */ + kdb_initial_cpu = smp_processor_id(); + // atomic_notifier_chain_register(&panic_notifier_list, &kdb_block); + // register_cpu_notifier(&kdb_cpu_nfb); + +#ifdef kdba_setjmp + kdbjmpbuf = vmalloc(NR_CPUS * sizeof(*kdbjmpbuf)); + if (!kdbjmpbuf) + printk(KERN_ERR "Cannot allocate kdbjmpbuf, no kdb recovery will be possible\n"); +#endif /* kdba_setjmp */ + + kdb_initial_cpu = -1; + // kdb_wait_for_cpus_secs = max(10, 2*num_online_cpus()); +} +// HACK have to sort through these later, some probably are not needed +EXPORT_SYMBOL_GPL(kdb_register); +EXPORT_SYMBOL_GPL(kdb_register_repeat); +EXPORT_SYMBOL_GPL(kdb_unregister); +EXPORT_SYMBOL_GPL(kdb_getarea_size); +EXPORT_SYMBOL_GPL(kdb_putarea_size); +//EXPORT_SYMBOL(kdb_getuserarea_size); +//EXPORT_SYMBOL(kdb_putuserarea_size); +EXPORT_SYMBOL_GPL(kdbgetularg); +EXPORT_SYMBOL_GPL(kdbgetenv); +EXPORT_SYMBOL_GPL(kdbgetintenv); +EXPORT_SYMBOL_GPL(kdbgetaddrarg); +//EXPORT_SYMBOL(kdb); +EXPORT_SYMBOL_GPL(kdb_on); +EXPORT_SYMBOL_GPL(kdb_seqno); +EXPORT_SYMBOL_GPL(kdb_initial_cpu); +EXPORT_SYMBOL_GPL(kdbnearsym); +EXPORT_SYMBOL_GPL(kdb_printf); +EXPORT_SYMBOL_GPL(kdb_symbol_print); +EXPORT_SYMBOL_GPL(kdb_running_process); diff --git a/kdb/kdbsupport.c b/kdb/kdbsupport.c new file mode 100644 index 0000000..6234380 --- /dev/null +++ b/kdb/kdbsupport.c @@ -0,0 +1,1120 @@ +/* + * Kernel Debugger Architecture Independent Support Functions + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 1999-2004 Silicon Graphics, Inc. All Rights Reserved. + * 03/02/13 added new 2.5 kallsyms + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +/* + * Symbol table functions. + */ + +/* + * kdbgetsymval + * + * Return the address of the given symbol. + * + * Parameters: + * symname Character string containing symbol name + * symtab Structure to receive results + * Outputs: + * Returns: + * 0 Symbol not found, symtab zero filled + * 1 Symbol mapped to module/symbol/section, data in symtab + * Locking: + * None. + * Remarks: + */ + +int +kdbgetsymval(const char *symname, kdb_symtab_t *symtab) +{ + if (KDB_DEBUG(AR)) + kdb_printf("kdbgetsymval: symname=%s, symtab=%p\n", symname, symtab); + memset(symtab, 0, sizeof(*symtab)); + + if ((symtab->sym_start = kallsyms_lookup_name(symname))) { + if (KDB_DEBUG(AR)) + kdb_printf("kdbgetsymval: returns 1, symtab->sym_start=0x%lx\n", symtab->sym_start); + return 1; + } + if (KDB_DEBUG(AR)) + kdb_printf("kdbgetsymval: returns 0\n"); + return 0; +} +EXPORT_SYMBOL(kdbgetsymval); + +/* + * kdbnearsym + * + * Return the name of the symbol with the nearest address + * less than 'addr'. + * + * Parameters: + * addr Address to check for symbol near + * symtab Structure to receive results + * Outputs: + * Returns: + * 0 No sections contain this address, symtab zero filled + * 1 Address mapped to module/symbol/section, data in symtab + * Locking: + * None. + * Remarks: + * 2.6 kallsyms has a "feature" where it unpacks the name into a string. + * If that string is reused before the caller expects it then the caller + * sees its string change without warning. To avoid cluttering up the + * main kdb code with lots of kdb_strdup, tests and kfree calls, kdbnearsym + * maintains an LRU list of the last few unique strings. The list is sized + * large enough to hold active strings, no kdb caller of kdbnearsym makes + * more than ~20 later calls before using a saved value. + */ + +static char *kdb_name_table[100]; /* arbitrary size */ + +int +kdbnearsym(unsigned long addr, kdb_symtab_t *symtab) +{ + int ret = 0; + unsigned long symbolsize; + unsigned long offset; +#define knt1_size 128 /* must be >= kallsyms table size */ + char *knt1 = NULL; + + if (KDB_DEBUG(AR)) + kdb_printf("kdbnearsym: addr=0x%lx, symtab=%p\n", addr, symtab); + memset(symtab, 0, sizeof(*symtab)); + + if (addr < 4096) + goto out; + knt1 = debug_kmalloc(knt1_size, GFP_ATOMIC); + if (!knt1) { + kdb_printf("kdbnearsym: addr=0x%lx cannot kmalloc knt1\n", addr); + goto out; + } + symtab->sym_name = kallsyms_lookup(addr, &symbolsize , &offset, (char **)(&symtab->mod_name), knt1); + if (offset > 8*1024*1024) { + symtab->sym_name = NULL; + addr = offset = symbolsize = 0; + } + symtab->sym_start = addr - offset; + symtab->sym_end = symtab->sym_start + symbolsize; + ret = symtab->sym_name != NULL && *(symtab->sym_name) != '\0'; + + if (ret) { + int i; + /* Another 2.6 kallsyms "feature". Sometimes the sym_name is + * set but the buffer passed into kallsyms_lookup is not used, + * so it contains garbage. The caller has to work out which + * buffer needs to be saved. + * + * What was Rusty smoking when he wrote that code? + */ + if (symtab->sym_name != knt1) { + strncpy(knt1, symtab->sym_name, knt1_size); + knt1[knt1_size-1] = '\0'; + } + for (i = 0; i < ARRAY_SIZE(kdb_name_table); ++i) { + if (kdb_name_table[i] && strcmp(kdb_name_table[i], knt1) == 0) + break; + } + if (i >= ARRAY_SIZE(kdb_name_table)) { + debug_kfree(kdb_name_table[0]); + memcpy(kdb_name_table, kdb_name_table+1, + sizeof(kdb_name_table[0])*(ARRAY_SIZE(kdb_name_table)-1)); + } else { + debug_kfree(knt1); + knt1 = kdb_name_table[i]; + memcpy(kdb_name_table+i, kdb_name_table+i+1, + sizeof(kdb_name_table[0])*(ARRAY_SIZE(kdb_name_table)-i-1)); + } + i = ARRAY_SIZE(kdb_name_table) - 1; + kdb_name_table[i] = knt1; + symtab->sym_name = kdb_name_table[i]; + knt1 = NULL; + } + + if (symtab->mod_name == NULL) + symtab->mod_name = "kernel"; + if (KDB_DEBUG(AR)) + kdb_printf("kdbnearsym: returns %d symtab->sym_start=0x%lx, symtab->mod_name=%p, symtab->sym_name=%p (%s)\n", ret, symtab->sym_start, symtab->mod_name, symtab->sym_name, symtab->sym_name); + +out: + debug_kfree(knt1); + return ret; +} + +void +kdbnearsym_cleanup(void) +{ + int i; + for (i = 0; i < ARRAY_SIZE(kdb_name_table); ++i) { + if (kdb_name_table[i]) { + debug_kfree(kdb_name_table[i]); + kdb_name_table[i] = NULL; + } + } +} + +/* + * kallsyms_symbol_complete + * + * Parameters: + * prefix_name prefix of a symbol name to lookup + * max_len maximum length that can be returned + * Returns: + * Number of symbols which match the given prefix. + * Notes: + * prefix_name is changed to contain the longest unique prefix that + * starts with this prefix (tab completion). + */ + +static char ks_namebuf[KSYM_NAME_LEN+1], ks_namebuf_prev[KSYM_NAME_LEN+1]; + +int kallsyms_symbol_complete(char *prefix_name, int max_len) +{ + loff_t pos = 0; + int prefix_len = strlen(prefix_name), prev_len = 0; + int i, number = 0; + const char *name; + + while ((name = kdb_walk_kallsyms(&pos))) { + if (strncmp(name, prefix_name, prefix_len) == 0) { + strcpy(ks_namebuf, name); + /* Work out the longest name that matches the prefix */ + if (++number == 1) { + prev_len = min_t(int, max_len-1, strlen(ks_namebuf)); + memcpy(ks_namebuf_prev, ks_namebuf, prev_len); + ks_namebuf_prev[prev_len] = '\0'; + } else for (i = 0; i < prev_len; ++i) { + if (ks_namebuf[i] != ks_namebuf_prev[i]) { + prev_len = i; + ks_namebuf_prev[i] = '\0'; + break; + } + } + } + } + if (prev_len > prefix_len) + memcpy(prefix_name, ks_namebuf_prev, prev_len+1); + return number; +} + +/* + * kallsyms_symbol_next + * + * Parameters: + * prefix_name prefix of a symbol name to lookup + * flag 0 means search from the head, 1 means continue search. + * Returns: + * 1 if a symbol matches the given prefix. + * 0 if no string found + */ + +int kallsyms_symbol_next(char *prefix_name, int flag) +{ + int prefix_len = strlen(prefix_name); + static loff_t pos; + const char *name; + + if (!flag) + pos = 0; + + while ((name = kdb_walk_kallsyms(&pos))) { + if (strncmp(name, prefix_name, prefix_len) == 0) { + strncpy(prefix_name, name, strlen(name)+1); + return 1; + } + } + return 0; +} + +/* + * kdb_symbol_print + * + * Standard method for printing a symbol name and offset. + * Inputs: + * addr Address to be printed. + * symtab Address of symbol data, if NULL this routine does its + * own lookup. + * punc Punctuation for string, bit field. + * Outputs: + * None. + * Returns: + * Always 0. + * Locking: + * none. + * Remarks: + * The string and its punctuation is only printed if the address + * is inside the kernel, except that the value is always printed + * when requested. + */ + +void +kdb_symbol_print(kdb_machreg_t addr, const kdb_symtab_t *symtab_p, unsigned int punc) +{ + kdb_symtab_t symtab, *symtab_p2; + if (symtab_p) { + symtab_p2 = (kdb_symtab_t *)symtab_p; + } + else { + symtab_p2 = &symtab; + kdbnearsym(addr, symtab_p2); + } + if (symtab_p2->sym_name || (punc & KDB_SP_VALUE)) { + ; /* drop through */ + } + else { + return; + } + if (punc & KDB_SP_SPACEB) { + kdb_printf(" "); + } + if (punc & KDB_SP_VALUE) { + kdb_printf(kdb_machreg_fmt0, addr); + } + if (symtab_p2->sym_name) { + if (punc & KDB_SP_VALUE) { + kdb_printf(" "); + } + if (punc & KDB_SP_PAREN) { + kdb_printf("("); + } + if (strcmp(symtab_p2->mod_name, "kernel")) { + kdb_printf("[%s]", symtab_p2->mod_name); + } + kdb_printf("%s", symtab_p2->sym_name); + if (addr != symtab_p2->sym_start) { + kdb_printf("+0x%lx", addr - symtab_p2->sym_start); + } + if (punc & KDB_SP_SYMSIZE) { + kdb_printf("/0x%lx", symtab_p2->sym_end - symtab_p2->sym_start); + } + if (punc & KDB_SP_PAREN) { + kdb_printf(")"); + } + } + if (punc & KDB_SP_SPACEA) { + kdb_printf(" "); + } + if (punc & KDB_SP_NEWLINE) { + kdb_printf("\n"); + } +} + +/* + * kdb_strdup + * + * kdb equivalent of strdup, for disasm code. + * Inputs: + * str The string to duplicate. + * type Flags to kmalloc for the new string. + * Outputs: + * None. + * Returns: + * Address of the new string, NULL if storage could not be allocated. + * Locking: + * none. + * Remarks: + * This is not in lib/string.c because it uses kmalloc which is not + * available when string.o is used in boot loaders. + */ + +char *kdb_strdup(const char *str, gfp_t type) +{ + int n = strlen(str)+1; + char *s = kmalloc(n, type); + if (!s) return NULL; + return strcpy(s, str); +} + +/* + * kdb_getarea_size + * + * Read an area of data. The kdb equivalent of copy_from_user, with + * kdb messages for invalid addresses. + * Inputs: + * res Pointer to the area to receive the result. + * addr Address of the area to copy. + * size Size of the area. + * Outputs: + * none. + * Returns: + * 0 for success, < 0 for error. + * Locking: + * none. + */ + +int kdb_getarea_size(void *res, unsigned long addr, size_t size) +{ + // int ret = kdba_getarea_size(res, addr, size); + // HACK HACK HACK + int ret = probe_kernel_read((char *)res, (char *)addr, size); + if (ret) { + if (!KDB_STATE(SUPPRESS)) { + kdb_printf("kdb_getarea: Bad address 0x%lx\n", addr); + KDB_STATE_SET(SUPPRESS); + } + ret = KDB_BADADDR; + } + else { + KDB_STATE_CLEAR(SUPPRESS); + } + return(ret); +} + +/* + * kdb_putarea_size + * + * Write an area of data. The kdb equivalent of copy_to_user, with + * kdb messages for invalid addresses. + * Inputs: + * addr Address of the area to write to. + * res Pointer to the area holding the data. + * size Size of the area. + * Outputs: + * none. + * Returns: + * 0 for success, < 0 for error. + * Locking: + * none. + */ + +int kdb_putarea_size(unsigned long addr, void *res, size_t size) +{ + // int ret = kdba_putarea_size(addr, res, size); + // HACK HACK HACK + int ret = probe_kernel_read((char *)addr, (char *)res, size); + if (ret) { + if (!KDB_STATE(SUPPRESS)) { + kdb_printf("kdb_putarea: Bad address 0x%lx\n", addr); + KDB_STATE_SET(SUPPRESS); + } + ret = KDB_BADADDR; + } + else { + KDB_STATE_CLEAR(SUPPRESS); + } + return(ret); +} + +/* + * kdb_getphys + * + * Read data from a physical address. Validate the address is in range, + * use kmap_atomic() to get data + * + * Similar to kdb_getarea() - but for phys addresses + * + * Inputs: + * res Pointer to the word to receive the result + * addr Physical address of the area to copy + * size Size of the area + * Outputs: + * none. + * Returns: + * 0 for success, < 0 for error. + * Locking: + * none. + */ +static int kdb_getphys(void *res, unsigned long addr, size_t size) +{ + unsigned long pfn; + void *vaddr; + struct page *page; + + pfn = (addr >> PAGE_SHIFT); + if (!pfn_valid(pfn)) + return 1; + page = pfn_to_page(pfn); + vaddr = kmap_atomic(page, KM_KDB); + memcpy(res, vaddr + (addr & (PAGE_SIZE -1)), size); + kunmap_atomic(vaddr, KM_KDB); + + return 0; +} + +/* + * kdb_getphysword + * + * Inputs: + * word Pointer to the word to receive the result. + * addr Address of the area to copy. + * size Size of the area. + * Outputs: + * none. + * Returns: + * 0 for success, < 0 for error. + * Locking: + * none. + */ +int kdb_getphysword(unsigned long *word, unsigned long addr, size_t size) +{ + int diag; + __u8 w1; + __u16 w2; + __u32 w4; + __u64 w8; + *word = 0; /* Default value if addr or size is invalid */ + + switch (size) { + case 1: + if (!(diag = kdb_getphys(&w1, addr, sizeof(w1)))) + *word = w1; + break; + case 2: + if (!(diag = kdb_getphys(&w2, addr, sizeof(w2)))) + *word = w2; + break; + case 4: + if (!(diag = kdb_getphys(&w4, addr, sizeof(w4)))) + *word = w4; + break; + case 8: + if (size <= sizeof(*word)) { + if (!(diag = kdb_getphys(&w8, addr, sizeof(w8)))) + *word = w8; + break; + } + /* drop through */ + default: + diag = KDB_BADWIDTH; + kdb_printf("kdb_getphysword: bad width %ld\n", (long) size); + } + return(diag); +} + +/* + * kdb_getword + * + * Read a binary value. Unlike kdb_getarea, this treats data as numbers. + * Inputs: + * word Pointer to the word to receive the result. + * addr Address of the area to copy. + * size Size of the area. + * Outputs: + * none. + * Returns: + * 0 for success, < 0 for error. + * Locking: + * none. + */ + +int kdb_getword(unsigned long *word, unsigned long addr, size_t size) +{ + int diag; + __u8 w1; + __u16 w2; + __u32 w4; + __u64 w8; + *word = 0; /* Default value if addr or size is invalid */ + switch (size) { + case 1: + if (!(diag = kdb_getarea(w1, addr))) + *word = w1; + break; + case 2: + if (!(diag = kdb_getarea(w2, addr))) + *word = w2; + break; + case 4: + if (!(diag = kdb_getarea(w4, addr))) + *word = w4; + break; + case 8: + if (size <= sizeof(*word)) { + if (!(diag = kdb_getarea(w8, addr))) + *word = w8; + break; + } + /* drop through */ + default: + diag = KDB_BADWIDTH; + kdb_printf("kdb_getword: bad width %ld\n", (long) size); + } + return(diag); +} + +/* + * kdb_putword + * + * Write a binary value. Unlike kdb_putarea, this treats data as numbers. + * Inputs: + * addr Address of the area to write to.. + * word The value to set. + * size Size of the area. + * Outputs: + * none. + * Returns: + * 0 for success, < 0 for error. + * Locking: + * none. + */ + +int kdb_putword(unsigned long addr, unsigned long word, size_t size) +{ + int diag; + __u8 w1; + __u16 w2; + __u32 w4; + __u64 w8; + switch (size) { + case 1: + w1 = word; + diag = kdb_putarea(addr, w1); + break; + case 2: + w2 = word; + diag = kdb_putarea(addr, w2); + break; + case 4: + w4 = word; + diag = kdb_putarea(addr, w4); + break; + case 8: + if (size <= sizeof(word)) { + w8 = word; + diag = kdb_putarea(addr, w8); + break; + } + /* drop through */ + default: + diag = KDB_BADWIDTH; + kdb_printf("kdb_putword: bad width %ld\n", (long) size); + } + return(diag); +} + +/* + * kdb_task_state_string + * + * Convert a string containing any of the letters DRSTCZEUIMA to a mask + * for the process state field and return the value. If no argument is + * supplied, return the mask that corresponds to environment variable PS, + * DRSTCZEU by default. + * Inputs: + * s String to convert + * Outputs: + * none. + * Returns: + * Mask for process state. + * Locking: + * none. + * Notes: + * The mask folds data from several sources into a single long value, so + * be carefull not to overlap the bits. TASK_* bits are in the LSB, + * special cases like UNRUNNABLE are in the MSB. As of 2.6.10-rc1 there + * is no overlap between TASK_* and EXIT_* but that may not always be + * true, so EXIT_* bits are shifted left 16 bits before being stored in + * the mask. + */ + +#define UNRUNNABLE (1UL << (8*sizeof(unsigned long) - 1)) /* unrunnable is < 0 */ +#define RUNNING (1UL << (8*sizeof(unsigned long) - 2)) +#define IDLE (1UL << (8*sizeof(unsigned long) - 3)) +#define DAEMON (1UL << (8*sizeof(unsigned long) - 4)) + +unsigned long +kdb_task_state_string(const char *s) +{ + long res = 0; + if (!s && !(s = kdbgetenv("PS"))) { + s = "DRSTCZEU"; /* default value for ps */ + } + while (*s) { + switch (*s) { + case 'D': res |= TASK_UNINTERRUPTIBLE; break; + case 'R': res |= RUNNING; break; + case 'S': res |= TASK_INTERRUPTIBLE; break; + case 'T': res |= TASK_STOPPED; break; + case 'C': res |= TASK_TRACED; break; + case 'Z': res |= EXIT_ZOMBIE << 16; break; + case 'E': res |= EXIT_DEAD << 16; break; + case 'U': res |= UNRUNNABLE; break; + case 'I': res |= IDLE; break; + case 'M': res |= DAEMON; break; + case 'A': res = ~0UL; break; + default: + kdb_printf("%s: unknown flag '%c' ignored\n", __FUNCTION__, *s); + break; + } + ++s; + } + return res; +} + +/* + * kdb_task_state_char + * + * Return the character that represents the task state. + * Inputs: + * p struct task for the process + * Outputs: + * none. + * Returns: + * One character to represent the task state. + * Locking: + * none. + */ + +char +kdb_task_state_char (const struct task_struct *p) +{ + int cpu = kdb_process_cpu(p); + struct kdb_running_process *krp = kdb_running_process + cpu; + char state = (p->state == 0) ? 'R' : + (p->state < 0) ? 'U' : + (p->state & TASK_UNINTERRUPTIBLE) ? 'D' : + (p->state & TASK_STOPPED) ? 'T' : + (p->state & TASK_TRACED) ? 'C' : + (p->exit_state & EXIT_ZOMBIE) ? 'Z' : + (p->exit_state & EXIT_DEAD) ? 'E' : + (p->state & TASK_INTERRUPTIBLE) ? 'S' : '?'; + if (p->pid == 0) { + /* Idle task. Is it really idle, apart from the kdb interrupt? */ + if (!kdb_task_has_cpu(p) || krp->irq_depth == 1) { + /* There is a corner case when the idle task takes an + * interrupt and dies in the interrupt code. It has an + * interrupt count of 1 but that did not come from kdb. + * This corner case can only occur on the initial cpu, + * all the others were entered via the kdb IPI. + */ + if (cpu != kdb_initial_cpu || KDB_STATE_CPU(KEYBOARD, cpu)) + state = 'I'; /* idle task */ + } + } + else if (!p->mm && state == 'S') { + state = 'M'; /* sleeping system daemon */ + } + return state; +} + +/* + * kdb_task_state + * + * Return true if a process has the desired state given by the mask. + * Inputs: + * p struct task for the process + * mask mask from kdb_task_state_string to select processes + * Outputs: + * none. + * Returns: + * True if the process matches at least one criteria defined by the mask. + * Locking: + * none. + */ + +unsigned long +kdb_task_state(const struct task_struct *p, unsigned long mask) +{ + char state[] = { kdb_task_state_char(p), '\0' }; + return (mask & kdb_task_state_string(state)) != 0; +} + +struct kdb_running_process kdb_running_process[NR_CPUS]; + +void +kdb_save_running_cpu(struct pt_regs *regs, struct task_struct *task, int cpu) +{ + struct kdb_running_process *krp = kdb_running_process + cpu; + krp->p = task; + krp->regs = regs; + krp->seqno = kdb_seqno; + // HACK HACK HACK - kgdb does not store this value per cpu + krp->irq_depth = hardirq_count() >> HARDIRQ_SHIFT; +} + +/* Save the state of a running process and invoke kdb_main_loop. This is + * invoked on the current process on each cpu (assuming the cpu is responding). + */ +#if 0 +int +kdb_save_running(struct pt_regs *regs, kdb_reason_t reason, + kdb_reason_t reason2, int error, kdb_dbtrap_t db_result) +{ + struct kdb_running_process *krp = kdb_running_process + smp_processor_id(); + krp->p = current; + krp->regs = regs; + krp->seqno = kdb_seqno; + krp->irq_depth = hardirq_count() >> HARDIRQ_SHIFT; + kdba_save_running(&(krp->arch), regs); + return kdb_main_loop(reason, reason2, error, db_result, regs); +} + +/* + * kdb_unsave_running + * + * Reverse the effect of kdb_save_running. + * Inputs: + * regs struct pt_regs for the process + * Outputs: + * Updates kdb_running_process[] for this cpu. + * Returns: + * none. + * Locking: + * none. + */ + +void +kdb_unsave_running(struct pt_regs *regs) +{ + struct kdb_running_process *krp = kdb_running_process + smp_processor_id(); + kdba_unsave_running(&(krp->arch), regs); + krp->seqno = 0; +} +#endif + + +/* + * kdb_print_nameval + * + * Print a name and its value, converting the value to a symbol lookup + * if possible. + * Inputs: + * name field name to print + * val value of field + * Outputs: + * none. + * Returns: + * none. + * Locking: + * none. + */ + +void +kdb_print_nameval(const char *name, unsigned long val) +{ + kdb_symtab_t symtab; + kdb_printf(" %-11.11s ", name); + if (kdbnearsym(val, &symtab)) + kdb_symbol_print(val, &symtab, KDB_SP_VALUE|KDB_SP_SYMSIZE|KDB_SP_NEWLINE); + else + kdb_printf("0x%lx\n", val); +} + +static struct page * kdb_get_one_user_page(const struct task_struct *tsk, unsigned long start, + int len, int write) +{ + struct mm_struct *mm = tsk->mm; + unsigned int flags; + struct vm_area_struct * vma; + + /* shouldn't cross a page boundary. */ + if ((start & PAGE_MASK) != ((start+len) & PAGE_MASK)) + return NULL; + + /* we need to align start address to the current page boundy, PAGE_ALIGN + * aligns to next page boundry. + * FIXME: What about hugetlb? + */ + start = start & PAGE_MASK; + flags = write ? (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD); + + vma = find_extend_vma(mm, start); + + /* may be we can allow access to VM_IO pages inside KDB? */ + if (!vma || (vma->vm_flags & VM_IO) || !(flags & vma->vm_flags)) + return NULL; + + return follow_page(vma, start, write ? FOLL_WRITE : 0); +} + +int kdb_getuserarea_size(void *to, unsigned long from, size_t size) +{ + struct page *page; + void *vaddr; + + page = kdb_get_one_user_page(kdb_current_task, from, size, 0); + if (!page) + return size; + + vaddr = kmap_atomic(page, KM_KDB); + memcpy(to, vaddr+ (from & (PAGE_SIZE - 1)), size); + kunmap_atomic(vaddr, KM_KDB); + + return 0; +} + +int kdb_putuserarea_size(unsigned long to, void *from, size_t size) +{ + struct page *page; + void *vaddr; + + page = kdb_get_one_user_page(kdb_current_task, to, size, 1); + if (!page) + return size; + + vaddr = kmap_atomic(page, KM_KDB); + memcpy(vaddr+ (to & (PAGE_SIZE - 1)), from, size); + kunmap_atomic(vaddr, KM_KDB); + + return 0; +} + +/* Last ditch allocator for debugging, so we can still debug even when the + * GFP_ATOMIC pool has been exhausted. The algorithms are tuned for space + * usage, not for speed. One smallish memory pool, the free chain is always in + * ascending address order to allow coalescing, allocations are done in brute + * force best fit. + */ + +struct debug_alloc_header { + u32 next; /* offset of next header from start of pool */ + u32 size; + void *caller; +}; + +/* The memory returned by this allocator must be aligned, which means so must + * the header size. Do not assume that sizeof(struct debug_alloc_header) is a + * multiple of the alignment, explicitly calculate the overhead of this header, + * including the alignment. The rest of this code must not use sizeof() on any + * header or pointer to a header. + */ +#define dah_align 8 +#define dah_overhead ALIGN(sizeof(struct debug_alloc_header), dah_align) + +static u64 debug_alloc_pool_aligned[256*1024/dah_align]; /* 256K pool */ +static char *debug_alloc_pool = (char *)debug_alloc_pool_aligned; +static u32 dah_first, dah_first_call = 1, dah_used = 0, dah_used_max = 0; + +/* Locking is awkward. The debug code is called from all contexts, including + * non maskable interrupts. A normal spinlock is not safe in NMI context. Try + * to get the debug allocator lock, if it cannot be obtained after a second + * then give up. If the lock could not be previously obtained on this cpu then + * only try once. + * + * sparse has no annotation for "this function _sometimes_ acquires a lock", so + * fudge the acquire/release notation. + */ +static DEFINE_SPINLOCK(dap_lock); +static int +get_dap_lock(void) + __acquires(dap_lock) +{ + static int dap_locked = -1; + int count; + if (dap_locked == smp_processor_id()) + count = 1; + else + count = 1000; + while (1) { + if (spin_trylock(&dap_lock)) { + dap_locked = -1; + return 1; + } + if (!count--) + break; + udelay(1000); + } + dap_locked = smp_processor_id(); + __acquire(dap_lock); + return 0; +} + +void +*debug_kmalloc(size_t size, gfp_t flags) +{ + unsigned int rem, h_offset; + struct debug_alloc_header *best, *bestprev, *prev, *h; + void *p = NULL; + if (!get_dap_lock()) { + __release(dap_lock); /* we never actually got it */ + return NULL; + } + h = (struct debug_alloc_header *)(debug_alloc_pool + dah_first); + if (dah_first_call) { + h->size = sizeof(debug_alloc_pool_aligned) - dah_overhead; + dah_first_call = 0; + } + size = ALIGN(size, dah_align); + prev = best = bestprev = NULL; + while (1) { + if (h->size >= size && (!best || h->size < best->size)) { + best = h; + bestprev = prev; + if (h->size == size) + break; + } + if (!h->next) + break; + prev = h; + h = (struct debug_alloc_header *)(debug_alloc_pool + h->next); + } + if (!best) + goto out; + rem = best->size - size; + /* The pool must always contain at least one header */ + if (best->next == 0 && bestprev == NULL && rem < dah_overhead) + goto out; + if (rem >= dah_overhead) { + best->size = size; + h_offset = ((char *)best - debug_alloc_pool) + + dah_overhead + best->size; + h = (struct debug_alloc_header *)(debug_alloc_pool + h_offset); + h->size = rem - dah_overhead; + h->next = best->next; + } else + h_offset = best->next; + best->caller = __builtin_return_address(0); + dah_used += best->size; + dah_used_max = max(dah_used, dah_used_max); + if (bestprev) + bestprev->next = h_offset; + else + dah_first = h_offset; + p = (char *)best + dah_overhead; + memset(p, POISON_INUSE, best->size - 1); + *((char *)p + best->size - 1) = POISON_END; +out: + spin_unlock(&dap_lock); + return p; +} + +void +debug_kfree(void *p) +{ + struct debug_alloc_header *h; + unsigned int h_offset; + if (!p) + return; + if ((char *)p < debug_alloc_pool || + (char *)p >= debug_alloc_pool + sizeof(debug_alloc_pool_aligned)) { + kfree(p); + return; + } + if (!get_dap_lock()) { + __release(dap_lock); /* we never actually got it */ + return; /* memory leak, cannot be helped */ + } + h = (struct debug_alloc_header *)((char *)p - dah_overhead); + memset(p, POISON_FREE, h->size - 1); + *((char *)p + h->size - 1) = POISON_END; + h->caller = NULL; + dah_used -= h->size; + h_offset = (char *)h - debug_alloc_pool; + if (h_offset < dah_first) { + h->next = dah_first; + dah_first = h_offset; + } else { + struct debug_alloc_header *prev; + unsigned int prev_offset; + prev = (struct debug_alloc_header *)(debug_alloc_pool + dah_first); + while (1) { + if (!prev->next || prev->next > h_offset) + break; + prev = (struct debug_alloc_header *) + (debug_alloc_pool + prev->next); + } + prev_offset = (char *)prev - debug_alloc_pool; + if (prev_offset + dah_overhead + prev->size == h_offset) { + prev->size += dah_overhead + h->size; + memset(h, POISON_FREE, dah_overhead - 1); + *((char *)h + dah_overhead - 1) = POISON_END; + h = prev; + h_offset = prev_offset; + } else { + h->next = prev->next; + prev->next = h_offset; + } + } + if (h_offset + dah_overhead + h->size == h->next) { + struct debug_alloc_header *next; + next = (struct debug_alloc_header *) + (debug_alloc_pool + h->next); + h->size += dah_overhead + next->size; + h->next = next->next; + memset(next, POISON_FREE, dah_overhead - 1); + *((char *)next + dah_overhead - 1) = POISON_END; + } + spin_unlock(&dap_lock); +} + +void +debug_kusage(void) +{ + struct debug_alloc_header *h_free, *h_used; +#ifdef CONFIG_IA64 + /* FIXME: using dah for ia64 unwind always results in a memory leak. + * Fix that memory leak first, then set debug_kusage_one_time = 1 for + * all architectures. + */ + static int debug_kusage_one_time = 0; +#else + static int debug_kusage_one_time = 1; +#endif + if (!get_dap_lock()) { + __release(dap_lock); /* we never actually got it */ + return; + } + h_free = (struct debug_alloc_header *)(debug_alloc_pool + dah_first); + if (dah_first == 0 && + (h_free->size == sizeof(debug_alloc_pool_aligned) - dah_overhead || + dah_first_call)) + goto out; + if (!debug_kusage_one_time) + goto out; + debug_kusage_one_time = 0; + kdb_printf("%s: debug_kmalloc memory leak dah_first %d\n", + __FUNCTION__, dah_first); + if (dah_first) { + h_used = (struct debug_alloc_header *)debug_alloc_pool; + kdb_printf("%s: h_used %p size %d\n", __FUNCTION__, h_used, h_used->size); + } + do { + h_used = (struct debug_alloc_header *) + ((char *)h_free + dah_overhead + h_free->size); + kdb_printf("%s: h_used %p size %d caller %p\n", + __FUNCTION__, h_used, h_used->size, h_used->caller); + h_free = (struct debug_alloc_header *) + (debug_alloc_pool + h_free->next); + } while (h_free->next); + h_used = (struct debug_alloc_header *) + ((char *)h_free + dah_overhead + h_free->size); + if ((char *)h_used - debug_alloc_pool != + sizeof(debug_alloc_pool_aligned)) + kdb_printf("%s: h_used %p size %d caller %p\n", + __FUNCTION__, h_used, h_used->size, h_used->caller); +out: + spin_unlock(&dap_lock); +} + +/* Maintain a small stack of kdb_flags to allow recursion without disturbing + * the global kdb state. + */ + +static int kdb_flags_stack[4], kdb_flags_index; + +void +kdb_save_flags(void) +{ + BUG_ON(kdb_flags_index >= ARRAY_SIZE(kdb_flags_stack)); + kdb_flags_stack[kdb_flags_index++] = kdb_flags; +} + +void +kdb_restore_flags(void) +{ + BUG_ON(kdb_flags_index <= 0); + kdb_flags = kdb_flags_stack[--kdb_flags_index]; +} diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c index 374faf9..be88346 100644 --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c @@ -504,3 +504,25 @@ __initcall(kallsyms_init); EXPORT_SYMBOL(__print_symbol); EXPORT_SYMBOL_GPL(sprint_symbol); + +#ifdef CONFIG_KGDB_KDB +#include +#include + +const char *kdb_walk_kallsyms(loff_t *pos) +{ + static struct kallsym_iter kdb_walk_kallsyms_iter; + if (*pos == 0) { + memset(&kdb_walk_kallsyms_iter, 0, sizeof(kdb_walk_kallsyms_iter)); + reset_iter(&kdb_walk_kallsyms_iter, 0); + } + while (1) { + if (!update_iter(&kdb_walk_kallsyms_iter, *pos)) + return NULL; + ++*pos; + /* Some debugging symbols have no name. Ignore them. */ + if (kdb_walk_kallsyms_iter.name[0]) + return kdb_walk_kallsyms_iter.name; + } +} +#endif /* CONFIG_KGDB_KDB */ diff --git a/kernel/module.c b/kernel/module.c index e797812..0523b4c 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -71,6 +72,10 @@ DEFINE_MUTEX(module_mutex); EXPORT_SYMBOL_GPL(module_mutex); static LIST_HEAD(modules); +#ifdef CONFIG_KGDB_KDB +struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */ +#endif /* CONFIG_KGDB_KDB */ + /* Waiting for a module to finish initializing? */ static DECLARE_WAIT_QUEUE_HEAD(module_wq); @@ -2547,8 +2552,14 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type, char *name, char *module_name, int *exported) { struct module *mod; +#ifdef CONFIG_KGDB_KDB + int get_lock = !KDB_IS_RUNNING(); +#else +#define get_lock 1 +#endif - preempt_disable(); + if (get_lock) + preempt_disable(); list_for_each_entry_rcu(mod, &modules, list) { if (symnum < mod->num_symtab) { *value = mod->symtab[symnum].st_value; @@ -2557,12 +2568,14 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type, KSYM_NAME_LEN); strlcpy(module_name, mod->name, MODULE_NAME_LEN); *exported = is_exported(name, *value, mod); - preempt_enable(); + if (get_lock) + preempt_enable(); return 0; } symnum -= mod->num_symtab; } - preempt_enable(); + if (get_lock) + preempt_enable(); return -ERANGE; } diff --git a/kernel/panic.c b/kernel/panic.c index 874ecf1..fdb7e5b 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -22,6 +22,7 @@ #include #include #include +#include int panic_on_oops; static unsigned long tainted_mask; @@ -81,6 +82,11 @@ NORET_TYPE void panic(const char * fmt, ...) */ crash_kexec(NULL); +#ifdef CONFIG_KDB_KDUMP + if (kdb_kdump_state == KDB_KDUMP_RESET) { + (void)kdb(KDB_REASON_OOPS, 999, get_irq_regs()); + } +#endif /* * Note smp_send_stop is the usual smp shutdown function, which * unfortunately means it may not be hardened to work in a panic diff --git a/kernel/printk.c b/kernel/printk.c index 5052b54..2c3e8ea 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -405,6 +405,20 @@ SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len) return do_syslog(type, buf, len); } +#ifdef CONFIG_KGDB_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_KGDB_KDB */ + /* * Call the console drivers on a range of log_buf */ diff --git a/kernel/sched.c b/kernel/sched.c index 26efa47..fe5784e 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -9153,7 +9153,7 @@ void normalize_rt_tasks(void) #endif /* CONFIG_MAGIC_SYSRQ */ -#ifdef CONFIG_IA64 +#if defined(CONFIG_IA64) || defined(CONFIG_KGDB_KDB) /* * These functions are only useful for the IA64 MCA handling. * @@ -10239,3 +10239,94 @@ struct cgroup_subsys cpuacct_subsys = { .subsys_id = cpuacct_subsys_id, }; #endif /* CONFIG_CGROUP_CPUACCT */ + +#ifdef CONFIG_KGDB_KDB + +#include + +static void +kdb_prio(char *name, struct rt_prio_array *array, kdb_printf_t xxx_printf, + unsigned int cpu) +{ + int pri, printed_header = 0; + struct task_struct *p; + + xxx_printf(" %s rt bitmap: 0x%lx 0x%lx 0x%lx\n", + name, + array->bitmap[0], array->bitmap[1], array->bitmap[2]); + + pri = sched_find_first_bit(array->bitmap); + if (pri < MAX_RT_PRIO) { + xxx_printf(" rt bitmap priorities:"); + while (pri < MAX_RT_PRIO) { + xxx_printf(" %d", pri); + pri++; + pri = find_next_bit(array->bitmap, MAX_RT_PRIO, pri); + } + xxx_printf("\n"); + } + + for (pri = 0; pri < MAX_RT_PRIO; pri++) { + int printed_hdr = 0; + struct list_head *head, *curr; + + head = array->queue + pri; + curr = head->next; + while(curr != head) { + struct task_struct *task; + if (!printed_hdr) { + xxx_printf(" queue at priority=%d\n", pri); + printed_hdr = 1; + } + task = list_entry(curr, struct task_struct, rt.run_list); + if (task) + xxx_printf(" 0x%p %d %s time_slice:%d\n", + task, task->pid, task->comm, + task->rt.time_slice); + curr = curr->next; + } + } + for_each_process(p) { + if (p->se.on_rq && (task_cpu(p) == cpu) && + (p->policy == SCHED_NORMAL)) { + if (!printed_header) { + xxx_printf(" sched_normal queue:\n"); + printed_header = 1; + } + xxx_printf(" 0x%p %d %s pri:%d spri:%d npri:%d\n", + p, p->pid, p->comm, p->prio, + p->static_prio, p->normal_prio); + } + } +} + +/* This code must be in sched.c because struct rq is only defined in this + * source. To allow most of kdb to be modular, this code cannot call any kdb + * functions directly, any external functions that it needs must be passed in + * as parameters. + */ + +void +kdb_runqueue(unsigned long cpu, kdb_printf_t xxx_printf) +{ + struct rq *rq; + + rq = cpu_rq(cpu); + + xxx_printf("CPU%ld lock:%s curr:0x%p(%d)(%s)", + cpu, (spin_is_locked(&rq->lock))?"LOCKED":"free", + rq->curr, rq->curr->pid, rq->curr->comm); + if (rq->curr == rq->idle) + xxx_printf(" is idle"); + xxx_printf("\n "); +#ifdef CONFIG_SMP + xxx_printf(" cpu_load:%lu %lu %lu", + rq->cpu_load[0], rq->cpu_load[1], rq->cpu_load[2]); +#endif + xxx_printf(" nr_running:%lu nr_switches:%llu\n", + rq->nr_running, (long long)rq->nr_switches); + kdb_prio("active", &rq->rt.active, xxx_printf, (unsigned int)cpu); +} +EXPORT_SYMBOL(kdb_runqueue); + +#endif /* CONFIG_KGDB_KDB */ diff --git a/kernel/signal.c b/kernel/signal.c index d803473..8526c90 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -2656,3 +2656,52 @@ void __init signals_init(void) { sigqueue_cachep = KMEM_CACHE(sigqueue, SLAB_PANIC); } + +#ifdef CONFIG_KGDB_KDB +#include +/* + * kdb_send_sig_info + * + * Allows kdb to send signals without exposing signal internals. + * + * Inputs: + * t task + * siginfo signal information + * seqno current kdb sequence number (avoid including kdbprivate.h) + * Outputs: + * None. + * Returns: + * None. + * Locking: + * Checks if the required locks are available before calling the main + * signal code, to avoid kdb deadlocks. + * Remarks: + */ +void +kdb_send_sig_info(struct task_struct *t, struct siginfo *info, int seqno) +{ + static struct task_struct *kdb_prev_t; + static int kdb_prev_seqno; + int sig, new_t; + if (!spin_trylock(&t->sighand->siglock)) { + kdb_printf("Can't do kill command now.\n" + "The sigmask lock is held somewhere else in kernel, try again later\n"); + return; + } + spin_unlock(&t->sighand->siglock); + new_t = kdb_prev_t != t || kdb_prev_seqno != seqno; + kdb_prev_t = t; + kdb_prev_seqno = seqno; + if (t->state != TASK_RUNNING && new_t) { + kdb_printf("Process is not RUNNING, sending a signal from kdb risks deadlock\n" + "on the run queue locks. The signal has _not_ been sent.\n" + "Reissue the kill command if you want to risk the deadlock.\n"); + return; + } + sig = info->si_signo; + if (send_sig_info(sig, info, t)) + kdb_printf("Fail to deliver Signal %d to process %d.\n", sig, t->pid); + else + kdb_printf("Signal %d is sent to process %d.\n", sig, t->pid); +} +#endif /* CONFIG_KGDB_KDB */ diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 28c655b..5e65f6a 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -1533,6 +1533,28 @@ int hugetlb_overcommit_handler(struct ctl_table *table, int write, #endif /* CONFIG_SYSCTL */ +#ifdef CONFIG_KGDB_KDB +#include +#include +/* Like hugetlb_report_meminfo() but using kdb_printf() */ +void +kdb_hugetlb_report_meminfo(void) +{ + struct hstate *h = &default_hstate; + kdb_printf( + "HugePages_Total: %5lu\n" + "HugePages_Free: %5lu\n" + "HugePages_Rsvd: %5lu\n" + "HugePages_Surp: %5lu\n" + "Hugepagesize: %5lu kB\n", + h->nr_huge_pages, + h->free_huge_pages, + h->resv_huge_pages, + h->surplus_huge_pages, + 1UL << (huge_page_order(h) + PAGE_SHIFT - 10)); +} +#endif /* CONFIG_KGDB_KDB */ + void hugetlb_report_meminfo(struct seq_file *m) { struct hstate *h = &default_hstate; diff --git a/mm/swapfile.c b/mm/swapfile.c index 312fafe..7e3a336 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -13,6 +13,10 @@ #include #include #include +#ifdef CONFIG_KGDB_KDB +#include +#include +#endif /* CONFIG_KGDB_KDB */ #include #include #include @@ -1937,6 +1941,24 @@ void si_swapinfo(struct sysinfo *val) spin_unlock(&swap_lock); } +#ifdef CONFIG_KGDB_KDB +/* Like si_swapinfo() but without the locks */ +void kdb_si_swapinfo(struct sysinfo *val) +{ + unsigned int i; + unsigned long nr_to_be_unused = 0; + + for (i = 0; i < nr_swapfiles; i++) { + if (!(swap_info[i].flags & SWP_USED) || + (swap_info[i].flags & SWP_WRITEOK)) + continue; + nr_to_be_unused += swap_info[i].inuse_pages; + } + val->freeswap = nr_swap_pages + nr_to_be_unused; + val->totalswap = total_swap_pages + nr_to_be_unused; +} +#endif /* CONFIG_KGDB_KDB */ + /* * Verify that a swap entry is valid and increment its swap map count. * -- 1.6.3.rc0.1.gf800 From maximlevitsky@gmail.com Fri May 8 16:49:59 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00 autolearn=ham version=3.3.0-rupdated Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n48Lnwsi033008 for ; Fri, 8 May 2009 16:49:59 -0500 X-ASG-Debug-ID: 1241819657-6020030f0000-sLlkUa X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi Received: from mail-fx0-f177.google.com (localhost [127.0.0.1]) by cuda.sgi.com (Spam Firewall) with ESMTP id 9B536F7CBB0 for ; Fri, 8 May 2009 14:54:17 -0700 (PDT) Received: from mail-fx0-f177.google.com (mail-fx0-f177.google.com [209.85.220.177]) by cuda.sgi.com with ESMTP id LeB8DVx0qyE3sE0N for ; Fri, 08 May 2009 14:54:17 -0700 (PDT) Received: by fxm25 with SMTP id 25so1659362fxm.20 for ; Fri, 08 May 2009 14:50:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:subject:from:to:cc :in-reply-to:references:content-type:date:message-id:mime-version :x-mailer:content-transfer-encoding; bh=bAbH8vkxC0+UeLCvV0xqy3DHsu9JPztGvDFRiDCQ/Sg=; b=EIZhJzPC7WvR/edlAb7AaPIdF6IKpdjGmuXHgQZuS0pyAb4L4FqXZhlMIdrMnkSq1V Fg3npcIsmYU0mG6oErkESThbpSed4ml98FdZsUGbzK6KWKqQiTj2anOBnizALEaKeZcS qdkh/5jnEmaMvDA7UHMWQWxyZFRvv6N1s0Jxo= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=subject:from:to:cc:in-reply-to:references:content-type:date :message-id:mime-version:x-mailer:content-transfer-encoding; b=aK42dNynRHXcDpJPBp6SVLe/tptoSjb5j4JX71vUAgm8CUJkd4AYT2Tahd1nmKdGA8 9LPFTdyfD82OUrKka90RViA8X2Yp7a6ueMMYZcYiv7KkxnOh9PEpVl8lB0/uc9vxfVEq YcAApHe++vbWx/cAc3P1PGC1gDjEuIV6gJr2U= Received: by 10.103.248.17 with SMTP id a17mr2610800mus.97.1241819401490; Fri, 08 May 2009 14:50:01 -0700 (PDT) Received: from ?10.1.0.2? (adsl249-16.technion.ac.il [132.68.249.16]) by mx.google.com with ESMTPS id n7sm3498885mue.28.2009.05.08.14.49.59 (version=SSLv3 cipher=RC4-MD5); Fri, 08 May 2009 14:50:00 -0700 (PDT) X-ASG-Orig-Subj: Re: [PATCH 0/13] RFC ONLY - kdb for kgdb Subject: Re: [PATCH 0/13] RFC ONLY - kdb for kgdb From: Maxim Levitsky To: Jason Wessel Cc: linux-kernel@vger.kernel.org, kgdb-bugreport@lists.sourceforge.net, kdb@oss.sgi.com In-Reply-To: <1241817800-9320-1-git-send-email-jason.wessel@windriver.com> References: <1241817800-9320-1-git-send-email-jason.wessel@windriver.com> Content-Type: text/plain Date: Sat, 09 May 2009 00:49:56 +0300 Message-Id: <1241819396.4735.2.camel@maxim-laptop> Mime-Version: 1.0 X-Mailer: Evolution 2.26.1 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: mail-fx0-f177.google.com[209.85.220.177] X-Barracuda-Start-Time: 1241819658 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0209 X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com X-Barracuda-Spam-Score: -2.02 X-Barracuda-Spam-Status: No, SCORE=-2.02 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.1.25266 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean On Fri, 2009-05-08 at 16:23 -0500, Jason Wessel wrote: > This patch series is a request for comments on several levels. > > 1) Do people find kdb useful? (See * and **) > 2) Would kdb folks be willing to use it if it was a front end to kgdb? > 3) Does kdb have a future in the mainline kernel? > 4) Is this a reasonable approach to have some level of > unification to end up with a more robust kernel debugger? > > * This is not meant to be a religious war > I am just a ordinary user of linux, but I want to say that I enjoyed the kdb back when I used it. I really would like to see that in kernel. But it would be even better to see a kdb over ethernet first (I have no serial port in my notebook....) Best regards, Maxim Levitsky From mingo@elte.hu Fri May 8 23:09:55 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-1.3 required=5.0 tests=AWL,BAYES_00 autolearn=ham version=3.3.0-rupdated Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n4949skj053775 for ; Fri, 8 May 2009 23:09:55 -0500 X-ASG-Debug-ID: 1241842197-394d02020000-sLlkUa X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi Received: from mx3.mail.elte.hu (localhost [127.0.0.1]) by cuda.sgi.com (Spam Firewall) with ESMTP id 543A31D1F1E9 for ; Fri, 8 May 2009 21:09:58 -0700 (PDT) Received: from mx3.mail.elte.hu (mx3.mail.elte.hu [157.181.1.138]) by cuda.sgi.com with ESMTP id vdAAIJ1hGjmJRuGo for ; Fri, 08 May 2009 21:09:58 -0700 (PDT) Received: from elvis.elte.hu ([157.181.1.14]) by mx3.mail.elte.hu with esmtp (Exim) id 1M2dsf-0001qc-Tt from ; Sat, 09 May 2009 06:09:54 +0200 Received: by elvis.elte.hu (Postfix, from userid 1004) id 3FD2D3E213A; Sat, 9 May 2009 06:09:38 +0200 (CEST) Date: Sat, 9 May 2009 06:09:42 +0200 From: Ingo Molnar To: Jason Wessel Cc: linux-kernel@vger.kernel.org, kgdb-bugreport@lists.sourceforge.net, kdb@oss.sgi.com, Andrew Morton X-ASG-Orig-Subj: Re: [PATCH 01/13] RFC ONLY - kdb: core for kgdb back end Subject: Re: [PATCH 01/13] RFC ONLY - kdb: core for kgdb back end Message-ID: <20090509040942.GB8007@elte.hu> References: <1241817800-9320-1-git-send-email-jason.wessel@windriver.com> <1241817800-9320-2-git-send-email-jason.wessel@windriver.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1241817800-9320-2-git-send-email-jason.wessel@windriver.com> User-Agent: Mutt/1.5.18 (2008-05-17) Received-SPF: neutral (mx3: 157.181.1.14 is neither permitted nor denied by domain of elte.hu) client-ip=157.181.1.14; envelope-from=mingo@elte.hu; helo=elvis.elte.hu; X-ELTE-VirusStatus: clean X-ELTE-SpamScore: -1.5 X-ELTE-SpamLevel: X-ELTE-SpamCheck: no X-ELTE-SpamVersion: ELTE 2.0 X-ELTE-SpamCheck-Details: score=-1.5 required=5.9 tests=BAYES_00 autolearn=no SpamAssassin version=3.2.3 -1.5 BAYES_00 BODY: Bayesian spam probability is 0 to 1% [score: 0.0000] X-Barracuda-Connect: mx3.mail.elte.hu[157.181.1.138] X-Barracuda-Start-Time: 1241842199 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com X-Barracuda-Spam-Score: -2.02 X-Barracuda-Spam-Status: No, SCORE=-2.02 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.1.25289 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean * Jason Wessel wrote: > This is an RFC patch. This work is by no means in its final form, > nor is it in a form that would be suitible for upstream merging. > This is an early prototype of a kdb frontend talking to a kgdb > backend. It is meant to foster some discussion around the > usefulness of merging kdb and kgdb together, as well as experiment > with changes to kgdb's core to improve robustness and > functionality. > > This patch contains the kdb core and some instrumentation into the > core kernel which kdb requires in order to gather information for > some of its reporting functions. Just a first quick 30-seconds impression from skimming through the patch: - The cleanups are an absolute must before doing any in-depth review. We only want to waste valuable review bandwidth on code that at least _looks_ nice and tidy. - Many functions are way too large, with many indentation levels - they need a split-up. - Most of the code patterns dont match core kernel standards and practices, so it's not reviewable in detail. It needs a thorough clean-up not just on the surface, but on the algorithmic level as well. bits like: > + // HACK HACK HACK > + printk(KERN_CRIT "DOH NEED TO IMPLEMENT THIS!"); need fixed. Locking needs reviewed and fixed: > +/* Locking is awkward. The debug code is called from all contexts, including > + * non maskable interrupts. A normal spinlock is not safe in NMI context. Try > + * to get the debug allocator lock, if it cannot be obtained after a second > + * then give up. If the lock could not be previously obtained on this cpu then > + * only try once. > + * > + * sparse has no annotation for "this function _sometimes_ acquires a lock", so > + * fudge the acquire/release notation. > + */ Plus, if _any_ debugger front-end is considered for merging, it _must_ work with Kernel Mode Setting properly, out of X. No ifs and when. Also, high-level file organization: i'd suggest to move it all under the kernel/debug/ hierarchy, and move kernel/kgdb.c to kernel/debug/backend/core.c or so [possibly split up a bit, it's getting quite large] and the KDB bits under kernel/debug/frontend/. We dont want multiple back-ends nor multiple front-ends. We want one good back-end and one good (built-in) front-end. I supported and helped a debugging backend and i dont consider a front-end completely impossible either. But it will have to meet a _lot_ of stringent standards because a good kernel debugging front-end's cross section to the system is even larger than a backend's. It's a tough job to get this done. Ingo From info@easycitycorporation.com Fri May 8 23:45:28 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=BAYES_50 autolearn=ham version=3.3.0-rupdated Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n494jROn056196 for ; Fri, 8 May 2009 23:45:28 -0500 X-ASG-Debug-ID: 1241844330-394d02760000-sLlkUa X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi Received: from customer-server9.catalservers.com (localhost [127.0.0.1]) by cuda.sgi.com (Spam Firewall) with ESMTP id 74ACD1D1F7F0 for ; Fri, 8 May 2009 21:45:30 -0700 (PDT) Received: from customer-server9.catalservers.com (customer-server9.catalservers.com [91.212.126.21]) by cuda.sgi.com with ESMTP id B6FCRjOTagucccDc for ; Fri, 08 May 2009 21:45:30 -0700 (PDT) Received: from easycitycorporation.com (customer-server9.catalservers.com [91.212.126.21]) by customer-server9.catalservers.com (Postfix) with ESMTPA id 0997E308FB for ; Sat, 9 May 2009 04:28:32 +0000 (UTC) Date: Sat, 9 May 2009 04:28:32 +0000 Errors-To: info@easycitycorporation.com To: kdb@oss.sgi.com From: World Business Register Reply-To: register@wbg2day.com X-ASG-Orig-Subj: Business Registration 2009/2010 Subject: Business Registration 2009/2010 Message-ID: <3cd9431b2c724af1b5cfddb4f0591813@easycitycorporation.com> MSMail-Priority: normal X-Priority: 3 X-Mailer: Mail sent with Web2Life-Newsletter v1.1.5 -- www.Web2Life.de MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="b1_3cd9431b2c724af1b5cfddb4f0591813" X-Barracuda-Connect: customer-server9.catalservers.com[91.212.126.21] X-Barracuda-Start-Time: 1241844332 X-Barracuda-Bayes: INNOCENT GLOBAL 0.5000 1.0000 0.0000 X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.1.25290 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean --b1_3cd9431b2c724af1b5cfddb4f0591813 Content-Type: text/plain; charset = "UTF-8" Content-Transfer-Encoding: 8bit Dear Ladies and Gentlemen. In order to have your company inserted in the registry of World Businesses for 2009/2010 edition, please print, complete and submit the enclosed form (PDF file) to the following address: WORLD BUSINESS GUIDE P.O. Box 2021 3500 GA Utrecht The Netherlands email: register@wbg2day.com FAX: +31 20 524 8107 Updating is free of charge! If you are not the intended recipient, please submit an email to unsubscribe@wbg2day.com Your request shall be dealt with accordingly. --b1_3cd9431b2c724af1b5cfddb4f0591813 Content-Type: application/octet-stream; name="Registration_Form.pdf" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="Registration_Form.pdf" JVBERi0xLjYNJeLjz9MNCjggMCBvYmoNPDwvTGluZWFyaXplZCAxL0wgNDM2NTkvTyAxMS9FIDM4 NjcxL04gMS9UIDQzMzg1L0ggWyA5MzYgMjA2XT4+DWVuZG9iag0gICAgICAgICAgICAgICAgICAg IA14cmVmDTggMzINMDAwMDAwMDAxNiAwMDAwMCBuDQowMDAwMDAxMTQyIDAwMDAwIG4NCjAwMDAw MDEyMTggMDAwMDAgbg0KMDAwMDAwMTM0NCAwMDAwMCBuDQowMDAwMDAxODc1IDAwMDAwIG4NCjAw MDAwMDI0NTAgMDAwMDAgbg0KMDAwMDAwMzE0NSAwMDAwMCBuDQowMDAwMDAzNjEyIDAwMDAwIG4N CjAwMDAwMDQ0NDUgMDAwMDAgbg0KMDAwMDAwNTAyNSAwMDAwMCBuDQowMDAwMDA2NTEwIDAwMDAw IG4NCjAwMDAwMDc5MTIgMDAwMDAgbg0KMDAwMDAwOTE3NSAwMDAwMCBuDQowMDAwMDEwNDg5IDAw MDAwIG4NCjAwMDAwMTA2MzIgMDAwMDAgbg0KMDAwMDAxMjE0MCAwMDAwMCBuDQowMDAwMDEzMzky IDAwMDAwIG4NCjAwMDAwMTM1MDUgMDAwMDAgbg0KMDAwMDAxMzU3NCAwMDAwMCBuDQowMDAwMDEz NjUzIDAwMDAwIG4NCjAwMDAwMTgyMTEgMDAwMDAgbg0KMDAwMDAxODQ5OCAwMDAwMCBuDQowMDAw MDE4NzY4IDAwMDAwIG4NCjAwMDAwMTg3OTMgMDAwMDAgbg0KMDAwMDAxOTE3MyAwMDAwMCBuDQow MDAwMDI0NTkxIDAwMDAwIG4NCjAwMDAwMjUwMTggMDAwMDAgbg0KMDAwMDAyNTEwMiAwMDAwMCBu DQowMDAwMDI4OTI2IDAwMDAwIG4NCjAwMDAwMjkzOTIgMDAwMDAgbg0KMDAwMDAzODM5NyAwMDAw MCBuDQowMDAwMDAwOTM2IDAwMDAwIG4NCnRyYWlsZXINPDwvU2l6ZSA0MC9Sb290IDkgMCBSL0lu Zm8gNyAwIFIvSURbPDUzNjdDREQwMTk4NDQxOEZBOURBNjlFREQ4QTg4RjBFPjwyREM2OEY2MTU1 Nzg0N0FGQjA4RTYzRURBRDU5MjMzRT5dL1ByZXYgNDMzNzc+Pg1zdGFydHhyZWYNMA0lJUVPRg0g ICAgICAgICAgICAgICAgICAgICAgICANMzkgMCBvYmoNPDwvRmlsdGVyL0ZsYXRlRGVjb2RlL0kg MTQwL0xlbmd0aCAxMjAvUyAzOS9WIDExOD4+c3RyZWFtDQpo3mJgYJBlYGD+wgAEk3wZUAEzELMw cDQwqiEJykIxA4MkAx/jFPkFnU3z2F4YNXQd3SLa4pvo5FAmruOzQYxBh+GmdIBjw1cGBjFTF8dJ DG/eFuQlizA/gRrDyMAwzRFsPgNrLNxwdgaGFR4QWYZogAADANG4GG0NZW5kc3RyZWFtDWVuZG9i ag05IDAgb2JqDTw8L0Fjcm9Gb3JtIDEwIDAgUi9NZXRhZGF0YSA2IDAgUi9QYWdlcyA1IDAgUi9U eXBlL0NhdGFsb2c+Pg1lbmRvYmoNMTAgMCBvYmoNPDwvREEoL0hlbHYgMCBUZiAwIGcgKS9EUjw8 L0VuY29kaW5nPDwvUERGRG9jRW5jb2RpbmcgNCAwIFI+Pi9Gb250PDwvSGVsdiAyIDAgUi9aYURi IDMgMCBSPj4+Pi9GaWVsZHMgMSAwIFI+Pg1lbmRvYmoNMTEgMCBvYmoNPDwvQXJ0Qm94WzAuMCAw LjAwMDk3NjU2MiA1OTUuMjc1IDg0MS44OV0vQmxlZWRCb3hbMC4wIDAuMCA1OTUuMjc1IDg0MS44 OV0vQ29udGVudHNbMTMgMCBSIDE1IDAgUiAxNyAwIFIgMTggMCBSIDE5IDAgUiAyMCAwIFIgMjIg MCBSIDIzIDAgUl0vQ3JvcEJveFswLjAgMC4wIDU5NS4yNzUgODQxLjg5XS9NZWRpYUJveFswLjAg MC4wIDU5NS4yNzUgODQxLjg5XS9QYXJlbnQgNSAwIFIvUmVzb3VyY2VzPDwvRXh0R1N0YXRlPDwv R1MwIDI0IDAgUj4+L0ZvbnQ8PC9DMl8wIDIxIDAgUi9UMV8wIDE0IDAgUi9UMV8xIDE2IDAgUi9U VDAgMTIgMCBSPj4vUHJvY1NldFsvUERGL1RleHRdL1Byb3BlcnRpZXM8PC9NQzA8PC9Db2xvclsy MDIyNCAzMjc2OCA2NTUzNV0vRGltbWVkIGZhbHNlL0VkaXRhYmxlIHRydWUvUHJldmlldyB0cnVl L1ByaW50ZWQgdHJ1ZS9UaXRsZShMYXllciAxKS9WaXNpYmxlIHRydWU+Pj4+Pj4vUm90YXRlIDAv VHJpbUJveFswLjAgMC4wIDU5NS4yNzUgODQxLjg5XS9UeXBlL1BhZ2U+Pg1lbmRvYmoNMTIgMCBv YmoNPDwvQmFzZUZvbnQvTkJJU1dCK0hlbHZldGljYU5ldWVMVFN0ZC1CZC9FbmNvZGluZy9XaW5B bnNpRW5jb2RpbmcvRmlyc3RDaGFyIDMyL0ZvbnREZXNjcmlwdG9yIDM4IDAgUi9MYXN0Q2hhciAx ODMvU3VidHlwZS9UcnVlVHlwZS9UeXBlL0ZvbnQvV2lkdGhzWzI3OCAwIDAgMCAwIDAgMCAwIDI5 NiAyOTYgMCAwIDI3OCA0MDcgMjc4IDAgNTU2IDU1NiA1NTYgNTU2IDAgNTU2IDAgMCAwIDAgMjc4 IDAgMCAwIDAgMCAwIDY4NSA3MDQgNzQxIDc0MSA2NDggNTkzIDc1OSA3NDEgMjk1IDU1NiAwIDU5 MyAwIDc0MSA3NzggNjY3IDAgNzIyIDY0OSA2MTEgNzQxIDAgOTQ0IDAgMCAwIDAgMCAwIDAgMCAw IDU3NCA2MTEgNTc0IDYxMSA1NzQgMzMzIDYxMSA1OTMgMjU4IDAgMCAyNTggOTA2IDU5MyA2MTEg NjExIDAgMzg5IDUzNyAzNTIgNTkzIDAgMCA1MzcgNTE5IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMjc4XT4+DWVuZG9iag0x MyAwIG9iag08PC9GaWx0ZXIvRmxhdGVEZWNvZGUvTGVuZ3RoIDYyNj4+c3RyZWFtDQpIiayXTU9V QQyG/0qXkOjQdqadqTsvEhIFv7iu1AXBiySARnCh/972KCMmYmJobvLmzEef05n2dObuHBx/31zB zuEuwurJLgAW0uGKzKG9AsI57OwfIXy89mfvQwIxKdwFRqMyhsHVBk59yDCMwqbwiEdicmuErqO0 JtOu16W5mK3WsLNeIxCsT4HILYnjRfOZUIsqKnArRgLrS3i79XKbcOsgZC/kccjRbELI69lch7yZ fc/nlGXgRcij2bfIgi9ztMyBVcjnkG+zj0NwPtEceMfaZ6OGyJyKc2B/LgCmn19DrkI2ISchZ3Pg wZ8LOJvzYC5vMyf/Hl14FyHHIZ9CPoRcb79fP4W9NXzxKCxbD9yLDhJrw4OGRQ09uB1OLu8K8zNo cAiLtc+Bh9RL88y4gCN4dYtbzblqppLLFXIWG5LmcrU6a5Bpy+V2KR2rWPL2ju5YE6ycyzUrnVrP cRd//c4XawprlsU8rKnfWC856AtprYzqKWnNXyPgLDaK4rG6I2GVwwkxd+pfLt72TpX/lqsmxMht QbLVYSb3QopjGD3ylIbUFlvbEWsasmvp4l8TaxpymB8po1vN85LQDwjrI8KcxqRaRHv1Tz6PyeL5 q8PGyGPWUfxcrMFJYwqW2hWxJ67dOdoEsSXGqMc9oIlpXnqSF04aDVNzyYtmk4rW8mLEfinqzN2t 05Bci5lXJc5LT65aWClOuDxmG0UqsUmin4plIDoqD+l3W1TzStfzmENKrdaQEsNu3o/DK13e6ea5 Xkb3imx5flb2w7x1Qb3vft5cJyjK8X/cJqr/Wfn1fWTdJhyp+rOCORJ+CDAARY+rlg1lbmRzdHJl YW0NZW5kb2JqDTE0IDAgb2JqDTw8L0Jhc2VGb250L01UWU1JRCtUcmFqYW5Qcm8tQm9sZC9FbmNv ZGluZy9XaW5BbnNpRW5jb2RpbmcvRmlyc3RDaGFyIDMyL0ZvbnREZXNjcmlwdG9yIDMzIDAgUi9M YXN0Q2hhciAxNDgvU3VidHlwZS9UeXBlMS9UeXBlL0ZvbnQvV2lkdGhzWzMwMCAwIDAgMCAwIDAg MCAwIDM2MCAzNjAgMCAwIDI1MCA0MjUgMjUwIDU0MiAwIDAgMCAwIDAgNjAwIDAgMCAwIDYwMCAy NTAgMCAwIDAgMCAwIDAgNzAwIDcwNyA4MDAgOTM2IDYzMiA2MjIgODg2IDk3MiA0NTIgNDE2IDc2 OCA2MDUgMTA0MyA5NDcgOTI3IDY1NSAwIDc1NSA1ODIgNzEwIDg1MiA3MjQgMTA4NSA3MTIgNjcw IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAy MTggMzYwIDM2MF0+Pg1lbmRvYmoNMTUgMCBvYmoNPDwvRmlsdGVyL0ZsYXRlRGVjb2RlL0xlbmd0 aCA3NjQ+PnN0cmVhbQ0KSImsVl1vUkEQ/Sv7CA+Mszv7Nb5Rg02sqTXF+GCMwZbGpsVW0MT+e8/e CwskRatuCMPlzp6z873LpOwMUxIIl8ujddacGMZnge/IJorRmVtzbt6ab8Z2GmuCI+c4seBRBEt8 0BjNBTD/Shk9+ayJWZpRpkgpqFMXm1FmJXY5qbSz0rIlpwm+N+S0QiEm0dwuQdYFyhKz5tyOUzJZ jqIa2nEGJkmROTX0PToCDbNvmKPkSW3P04wzJ7LZc9NaUiUfhNW3y5GzlpJzCehmlE5IFVPJtStP J5FctJhzDV33mYJYp6GhnZEpMzttl3WXhDgqJl1qx5kDiahn2zDtivecMel8M07UOuWEiazt7BTn yPoUOP5vPI+mhxA35tl0WjabXpncoTPiYyJO6+wVrxfmw+DFcOQGd0V8LeJ7EbMiLupfU8R9EfMi lkWs9mHPhx+nr8yIib0zI0EzezO9BP24aC+rWFaWVRU9FlB0VQfVHnpWt1jtW3Zbjdoaf1mJezoc ThJ7g9aWbNf+2Pe2s+lhx4s1FknBTWFrypd9l+f7frvO78ihR7ys1v7c89FJt2xj1KQoR0UsKuC6 +lhR3KGCph71vu7/uYZi9tRAW1QLSsTifoV62YbmugZkJxaTaVc35XODW0QkxpTCKPAGfeZFcWrh smLNcm6OMB7tjt6it9O+HmWLnXt9cki4PKaPLLhNJpSqR0WHR5fI4SV/2Q8ZrRRMzBhvYdMTpzWg ixpGU7N/Vf8+7JfUsiouqmJRe2dWK+dQfDfOxT/673OkrP63S0IiDY+zHIyP4NDEnDOCTCdXegC5 sDmWdrKYTkBf9QFmGAhpq+yiaz+tw2t7n/AjjDoJAdSBXIi5j/BrhIAH49Oh5cHxu6GVwfh4cm7O z96UNyeT003pPz2RXikEn4woqrQcU91G45qx5brIpc/ObN3rniTjB26H2pJS8ik94q483Rcx79sH czt2PRl3Jtyqks/qKhjazZ+8s67j3Y6z5e5Mk0pgfgkwAMhhvkoNZW5kc3RyZWFtDWVuZG9iag0x NiAwIG9iag08PC9CYXNlRm9udC9NVFlNSUQrSGVsdmV0aWNhTmV1ZUxUU3RkLVJvbWFuL0VuY29k aW5nIDM0IDAgUi9GaXJzdENoYXIgMzEvRm9udERlc2NyaXB0b3IgMzYgMCBSL0xhc3RDaGFyIDE4 My9TdWJ0eXBlL1R5cGUxL1R5cGUvRm9udC9XaWR0aHNbNTE4IDI3OCAwIDAgMCAwIDAgMCAwIDAg MCAwIDYwMCAyNzggMCAyNzggMzMzIDU1NiA1NTYgNTU2IDU1NiA1NTYgNTU2IDAgNTU2IDU1NiAw IDI3OCAwIDAgMCAwIDAgMCA2NDggNjg1IDcyMiA3MDQgMCA1NzQgNzU5IDAgMjU5IDAgMCA1NTYg ODcxIDcyMiA3NjAgNjQ4IDAgNjg1IDY0OCA1NzQgMCAwIDkyNiA2MTEgMCAwIDAgMCAwIDAgMCAw IDUzNyA1OTMgNTM3IDU5MyA1MzcgMjk2IDU3NCA1NTYgMjIyIDIyMiA1MTkgMjIyIDg1MyA1NTYg NTc0IDU5MyAwIDMzMyA1MDAgMzE1IDU1NiA1MDAgNzU4IDUxOCA1MDAgNDgwIDAgMCAwIDAgMCAw IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDI3OF0+ Pg1lbmRvYmoNMTcgMCBvYmoNPDwvRmlsdGVyL0ZsYXRlRGVjb2RlL0xlbmd0aCAxNDE1Pj5zdHJl YW0NCkiJjFbbUuNGEP2C/EM/SikspBmNLvsm24OtLSNckoxDxakUBSbrLMFbBh42X5++jGwZQ3YL ai6tvvfpHrefYaDiQCkNgzxIUgXtPfzuWX+gvSda/qLlkZYNLc/+QHlf/D/azxCpIIpyCEWioa/f aLkllqcPJFSIhsIgDCMR+0xfWeKN7JpOLLtmWfJSZ7gFaWZEdiSaO0PvipGTCZDBRIQuiGsnDJ2t u+OgVMQuxplI1PT1dR8KL5uesyRmW9BKo2s5xFGK6UxhoEMdRFkCyqALBnZreACTxoFB/XEYB1lI 4SgVmDQDnQYmi4Vp2JLDqALXaL/CVzhvoz9DwMw9QBQC/eGmwyDWxkCMdkyWo9P/UG6u/Cj0qras bNWuvGblw3Jqaws3vgq9q0UNyGG8y7lvQq+obqBsoBghpS2v7SeOSaP7OuZUaC2pGJJwXVSkezRd eZb0lhWqLoXEgiEMogCBNEaJj8yxe3NbF36CNm0jJmOJCrcoC3QSZZBmYZAYgiVFtWSxejaG4aLB 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 Rmd3RM/XDe7L26SjrwVUZSMfEQr8Odik4uhBKkM3M7FTXbqJI4cIlelW4fc4RUPM4Kv7AMUpnF/o mrFnGZ1UGuHpCdnzbsa1FLc58bt6MAdE52m/q8bwhEwZJDNPh76vBm1GiubODG6WZF9+bfAQpihB cKLLYP5qcudlztXYbEejpbui0TiATkwcdUa37yCOGkli34wi8uZSyQmK+IaMEc3fvNdGoJHfCMxy v/CibuMdailUox9sBAv47MDmun42MqtCvn3c2fCTo/P5NmeD51CfH1+rb3tecG7t92tOc/WnMoaP Hz7lh5NioAgHIqg//AsGeLzv/LMDA7TDxrE0n4DmE+a8o3//TVDNsmfWmc0MjMImVnSb1yjsBOTj GQazjAyE1OnQTj+6n03gNBaSZ6DLwqBwjKpkt5g0Kt1GoJxSWWUuOuvfgZyjyMpW4ax+0RAjsg44 fzoJZP8zwQmdT+js5Nm+YCx883THcILCqRj5f28YKeugcdbBSEZ7prOdYKzp1mB8CMxkHZ/vhBS0 9nAPkwZJ0MDgHxNMXOUEOTZ9Kjn8rFX+CYKZ5gAP5vVHgAEAbIaGBw1lbmRzdHJlYW0NZW5kb2Jq DTIxIDAgb2JqDTw8L0Jhc2VGb250L09KU1lLWitIZWx2ZXRpY2FOZXVlTFRTdGQtQmQvRGVzY2Vu ZGFudEZvbnRzIDMwIDAgUi9FbmNvZGluZy9JZGVudGl0eS1IL1N1YnR5cGUvVHlwZTAvVG9Vbmlj b2RlIDMxIDAgUi9UeXBlL0ZvbnQ+Pg1lbmRvYmoNMjIgMCBvYmoNPDwvRmlsdGVyL0ZsYXRlRGVj b2RlL0xlbmd0aCAxNDM4Pj5zdHJlYW0NCkiJbFbbchw1EP0C/kGPa/Aquo/EmxM7wVTIzUtBFaao rcmYLFnvmvG6IHw9p7sl7RbFy4zOdE+rr0daBu2zVYP2wall0C4wwKel16WDUS2dzrnLrE6OgXME XF1CzejYJU2dtLshslMBtmNdB3HU3liV+O8RKCdCNtAzYR21dW3t9cCmBDntsTLQNPAYRg0U4ccg dmAVvkMwaEuuBz1AnrXHr8uoSyJLRQeSQYXcNvDFESLHgJIgiRA4O8EktdpUKQVqtU0djYS9O5UG 0Q3hFMXgRLfiwbBdJ5aGILs42xC5a49wi2CM6RD2BCSApIvERb5Swvg/fDWUUZ9aBqjwlJrA2fdw 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 zg3llddZF4fMbVO7KIvBS7TbAhYQK1FA2cKXonkBbCiaLPxc3K8TmoRov1oDmgNaAs7soq63ReN7 5BQYlzE9xfCENbx5Kz/1K4X77YqDSgxLYmPcxmVEamid/sC5EpzrGf4t/iXnRnvMFed2Fr7NvKzP 8f+Tx8YgTvdcHeMYQkP4MoxpP0ayOfDjdK2XzfmPmMh+bWvcSeNhNbqWhmaWHVbve7dmJbNS7El3 N7+9n8HF7fzd9eV8Dle372aXfm3jxmf3vF/YDYOL+k+QHNXvpY1x++Icrs7htmuKxaojLcVifhAB bS/XBS1mXGTLlhiXGR4EuPlpwZIUTEonAW60QcaN7Q4q4OG3BqklE3g2DKepO1HUwcFygVua8Zz+ 8DnB0Ymj+CPMBIqGwHSU3tUxRx1xelfylCvxijPiawj5KC19KuR/QzmKxhxRhgIecfRJjjzFCVnJ lAnsuVSKcZ6CTCRLxXHi7pjjLOUSn3iYcYYsfAqcMOuDadoff2jSJhak0a4wuKY+RjeTqYg63GWi FaGCUEOIdp7oPT1yEit6PJG4I5QPotNoB437iOCW4GYw6NjtwIZBZTuMLehR0tgjoRdC9xO3G/3H GaysO+RB4UVHGsw6XCkOK9dzZIr3AGvHOXHMbKzHOcYwhbUf5VAn05OUcF953S/sUxrj5UilFqeL Mb5j11SfejJV1Cc59E5RWVV0TuLzUNYmlFX5Auf/p6B4V2QGp64QnNmULm2YkbF42TOcJdL6HMId E1m4kQn5D6yhOdayRI8XTGnNMOlTlMsPbwGrBn8LMACL5skjDWVuZHN0cmVhbQ1lbmRvYmoNMjQg MCBvYmoNPDwvQUlTIGZhbHNlL0JNL05vcm1hbC9DQSAxLjAvT1AgZmFsc2UvT1BNIDEvU0EgdHJ1 ZS9TTWFzay9Ob25lL1R5cGUvRXh0R1N0YXRlL2NhIDEuMC9vcCBmYWxzZT4+DWVuZG9iag0yNSAw IG9iag08PC9PcmRlcmluZyhJZGVudGl0eSkvUmVnaXN0cnkoQWRvYmUpL1N1cHBsZW1lbnQgMD4+ DWVuZG9iag0yNiAwIG9iag08PC9GaWx0ZXIvRmxhdGVEZWNvZGUvTGVuZ3RoIDExPj5zdHJlYW0N CkiJagAIMAAAgQCBDWVuZHN0cmVhbQ1lbmRvYmoNMjcgMCBvYmoNPDwvRmlsdGVyL0ZsYXRlRGVj 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 IDI2IDAgUi9DYXBIZWlnaHQgNzE0L0Rlc2NlbnQgLTI5My9GbGFncyA0L0ZvbnRCQm94Wy0xNjYg LTI5MyAxMDc4IDk3NV0vRm9udEZhbWlseShIZWx2ZXRpY2FOZXVlTFQgU3RkKS9Gb250RmlsZTIg MjcgMCBSL0ZvbnROYW1lL09KU1lLWitIZWx2ZXRpY2FOZXVlTFRTdGQtQmQvRm9udFN0cmV0Y2gv Tm9ybWFsL0ZvbnRXZWlnaHQgNzAwL0l0YWxpY0FuZ2xlIDAvU3RlbVYgMTQ0L1R5cGUvRm9udERl c2NyaXB0b3IvWEhlaWdodCA1MTc+Pg1lbmRvYmoNMjkgMCBvYmoNPDwvQmFzZUZvbnQvT0pTWUta K0hlbHZldGljYU5ldWVMVFN0ZC1CZC9DSURTeXN0ZW1JbmZvIDI1IDAgUi9DSURUb0dJRE1hcC9J ZGVudGl0eS9EVyAxMDAwL0ZvbnREZXNjcmlwdG9yIDI4IDAgUi9TdWJ0eXBlL0NJREZvbnRUeXBl Mi9UeXBlL0ZvbnQvV1szWzI3OF00OVs2NjddNjZbNTc0XTY4WzU3NF03MFs1NzQgMzMzXTczWzU5 MyAyNThdNzdbMjU4IDkwNiA1OTNdODAgODEgNjExIDgzWzM4OSA1MzcgMzUyXTkwWzUxOV0xMDlb NjExXV0+Pg1lbmRvYmoNMzAgMCBvYmoNWzI5IDAgUl0NZW5kb2JqDTMxIDAgb2JqDTw8L0ZpbHRl ci9GbGF0ZURlY29kZS9MZW5ndGggMzExPj5zdHJlYW0NCkiJXNLNaoNAEAfwu08xx+YQVk3UBERI kwge+kFtH8DsjqlQ12U1B9++6/5DCl1Q+DE7zjCjOFanSncTiXc7yJonajutLI/DzUqmC187HUQx qU5Od/m37BsTCJdcz+PEfaXbIchzEh8uOE52pqeDGi68CsSbVWw7faWnr2O9IlHfjPnhnvVEIRUF KW7dh14a89r0TMKnrSvl4t00r13O343P2TDF3hGakYPi0TSSbaOvHOShOwXlpTtFwFr9i0c7pF1a +d1Yf33jrodhHBaLNpFXAm1jrzSCttAGSqEEyqAU2kM76ADtoRN0hM7QCSqhs1cSQiWEzjJ0lqDr LIbQWYbOkgTaQqieoXq6VC+fw8gP5z6FZUxum/TYgbxZ68bvV+7nvky80/z4K8xgyGUtT/ArwABu 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 NzUwL0NoYXJTZXQoL3NwYWNlL3BhcmVubGVmdC9wYXJlbnJpZ2h0L2NvbW1hL2h5cGhlbi9wZXJp b2Qvc2xhc2gvZml2ZS9uaW5lL2NvbG9uL0EvQi9DL0QvRS9GL0cvSC9JL0ovSy9ML00vTi9PL1Av Ui9TL1QvVS9WL1cvWC9ZL3F1b3RlcmlnaHQvcXVvdGVkYmxsZWZ0L3F1b3RlZGJscmlnaHQpL0Rl c2NlbnQgLTI4NC9GbGFncyAxMzExMDYvRm9udEJCb3hbLTI0OCAtMjg0IDE1MjggOTg1XS9Gb250 RmFtaWx5KFRyYWphbiBQcm8pL0ZvbnRGaWxlMyAzMiAwIFIvRm9udE5hbWUvTVRZTUlEK1RyYWph blByby1Cb2xkL0ZvbnRTdHJldGNoL05vcm1hbC9Gb250V2VpZ2h0IDcwMC9JdGFsaWNBbmdsZSAw L1N0ZW1WIDEyMC9UeXBlL0ZvbnREZXNjcmlwdG9yL1hIZWlnaHQgNjQwPj4NZW5kb2JqDTM0IDAg b2JqDTw8L0Jhc2VFbmNvZGluZy9XaW5BbnNpRW5jb2RpbmcvRGlmZmVyZW5jZXNbMzEvZl9pXS9U eXBlL0VuY29kaW5nPj4NZW5kb2JqDTM1IDAgb2JqDTw8L0ZpbHRlci9GbGF0ZURlY29kZS9MZW5n dGggMzczOS9TdWJ0eXBlL1R5cGUxQz4+c3RyZWFtDQpIiVxUDVBTVxZ+z0duAsagZF+0xCZPGrQg Kj+K+EcFVBBBWXWttC4Sk6gRSGgSglCtrEsVDdFqZ3d1/Vk7rTLb7eyWZWxpi3XRxfqzLEXZCD7U UA06WX+6Vve8eLKze4MzO7M7b+ace+6758x3vvPdyzJRoxiWZYXi1aXFSxdNLbBUui0uq8m43FJj KVq9ymWettJeZbRFzuiliaw0IUp6WcnjXNzy/OLzIhk8iZWEcS0Tx16JYzhaiYlinrPyjeutefbq Ood102aXkDYnKyuF2jmpIzYjRUhPTU0XRlxGjtm+wSKsqnO6LFVOYanNZHdU2x1Gl8U8XciprBRW Rko4hZUWp8Xhjmz+F6BgdQpGYbXDaLZUGR0Vgn0j/Wc1Wyo3WBybLA5hkaPGVFFldJo2W20Wm5CT L1i2miprnFa3pbJOqLSaLDanxSy4NjvsNZs2C0VWm91VV22hiw0Oo6NOyK/aUJAiGG1mocpYJ1CQ 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 OM1tcFDEkJs4B+Ig7ibMgRAIjabVIQ7jonEOhsrOQLAODoyPDyajFeclJUdGJg3APJpYTC6GTLrJ AOYd2Rv/f2R1u54vqtC8m/3EuDLBPUApxHpCluEkZN2q0N9NsMoYPHrhGvxCdvIRe17csCHOl862 g4nARHtp67Sa6IQyNdVJdD5+GmJFDKi7vR58pXvAd4D/ndiTMU02YXhJ05MHuoM+/2vDZxcvF6ft ozUWrFVPtCGTnrS/vHCRumWslOheLR2rSAtKTypfk5x2YmgXrWcttJibFZObWifdE01DHxG1/Hsc ZaFntn0vX1E2UiPVn7XB1SnFztMymW+0zYO6dGoVRrNhJwvPTrGnv/JRjwxTMeji0fzxUph/9fKp 3jaZaKI0foTQ1H6XPuPboL0ubNXKyDOSkOICPclg/mAtiQtlsFpv4P5OfbWsdgIG/kmqccRTILR7 ttHpKJovPcE4O0tL4MLZQq/hR0YYg6fI8RYT+qe1CFKMe3oE52SWFFLbT4pPFkNliXW/tkvo3B84 xcAOm8GOmzkwMVwPrZAClVwwQxHT8BFI49DEhGFaCao5SzS+ouQWe/JKrH/QSoX2GbikjsHel0Po 5RAG+frBgiiuaHtpWYFUVlZft90mbF3KC+1VTc3VzdLQmfa7Z22Wx7xZPqalmo8FaqkKfsugXwvg LuuO5dDJ4xV9rvEPEGohwKRAgFmBXrHwVNGZD061tv6p6FRhYdGvC2QDD5GeazpVIc6DNFVwP6Q9 mptB/j+Yz03Md+N/mU9wwzQsEadjFvKqfl8kGtEbeEvZEU/uEdx8iMF79Xfq9YlDvPIzdY7WFaCN if8WYABopmZVDWVuZHN0cmVhbQ1lbmRvYmoNMzYgMCBvYmoNPDwvQXNjZW50IDk1Mi9DYXBIZWln aHQgNzE0L0NoYXJTZXQoL2ZfaS9zcGFjZS9wbHVzL2NvbW1hL3BlcmlvZC9zbGFzaC96ZXJvL29u ZS90d28vdGhyZWUvZm91ci9maXZlL3NldmVuL2VpZ2h0L2NvbG9uL0EvQi9DL0QvRi9HL0kvTC9N L04vTy9QL1IvUy9UL1cvWC9hL2IvYy9kL2UvZi9nL2gvaS9qL2svbC9tL24vby9wL3Ivcy90L3Uv di93L3gveS96L3BlcmlvZGNlbnRlcmVkKS9EZXNjZW50IC0yMTQvRmxhZ3MgMzIvRm9udEJCb3hb LTE2NiAtMjE0IDEwNzYgOTUyXS9Gb250RmFtaWx5KEhlbHZldGljYU5ldWVMVCBTdGQpL0ZvbnRG aWxlMyAzNSAwIFIvRm9udE5hbWUvTVRZTUlEK0hlbHZldGljYU5ldWVMVFN0ZC1Sb21hbi9Gb250 U3RyZXRjaC9Ob3JtYWwvRm9udFdlaWdodCA0MDAvSXRhbGljQW5nbGUgMC9TdGVtViA4NC9UeXBl L0ZvbnREZXNjcmlwdG9yL1hIZWlnaHQgNTE3Pj4NZW5kb2JqDTM3IDAgb2JqDTw8L0ZpbHRlci9G bGF0ZURlY29kZS9MZW5ndGggODkyMS9MZW5ndGgxIDE2NTgyPj5zdHJlYW0NCkiJdFYJWFTXFf7v ezOMoCwDg8ug43szwzrsMIJGES2g0aooLkxaDURxQVFccclCkyYxoyVrk5Rqm7Z2kdg4aYwdRA1p EhdsGxutWTSDidEmbZq2KV3y+cH0f2/GiVozfJd37rn3nv/cc/5z74UAEItWyKieVZNXuG1U4hpq LrDVLW6qb+4r/bQFEOMBw/2LN21QREvMnYDxKMfTljYva4ry7Cph/yPOWb9s1ZalpiMHhwOmBUD2 geUN9Ut6rxY+DRQP5vwxy6kwpcqvsj+Jfefypg2bS6yjuthvoH3nqjWL6zMvuQ8ApY8AkqWpfnOz rEjLgXG7OV9ZXd/UsLqzLZP9I8RsaV6zfkPQj0KgvFgbb17X0HzJc8rC/lz210EWAekwjDBIXqmW mumhr1iEQjGGCIMHGSTtZ2gF9pdDmYbwb1LF5EooUK5KUs/Ahzghv4n3qJa1Mcko9WhjMGgdCH2B hWOURABRokfzBReJbhAyZxkRBROWIxoxGIwhjHYc4pEAMxKRxJXJGIphGI4RsCIFIzEKNoymBRV2 OOBEKtKQjgxkIgsuZCMHuchDPgq48yIUw40xKEEpxmIcbsN4TEAZJqIcd2MyvoYKVKIKUzAVt2Ma puPrmIGZmIVqzMYc1GAu5mE+FqAWHtyBb+CbWIhFYI7xS+zHi/gVDuEIXsMJnMJJ9OB3+C1+jzfx Fk7jDziDcziLP+JtvIPzeJdRuoAAPkAv99+MH6Eed2EpNmA9voufogPfwz14AH3w4jv4B3bhX/g3 luBZfIrP8Fd8jM+xA4/iCh7Dk9iGOjyDv6MB/8RlNGIztuC/eAE+vII2PIU1eAQr0IJJGIQf4j+4 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 fcAPR6MO+hgfUkmyQ5hTGjOXwLTT49SCo0wcZus6LuFDum2VhC7BrQdnGoUD6pKRxKuwUoLYlfh8 xzowkRp5yW0Z/lOAAQA2uVTdDWVuZHN0cmVhbQ1lbmRvYmoNMzggMCBvYmoNPDwvQXNjZW50IDk3 NS9DYXBIZWlnaHQgNzE0L0Rlc2NlbnQgLTI5My9GbGFncyAzMi9Gb250QkJveFstMTY2IC0yOTMg MTA3OCA5NzVdL0ZvbnRGYW1pbHkoSGVsdmV0aWNhTmV1ZUxUIFN0ZCkvRm9udEZpbGUyIDM3IDAg Ui9Gb250TmFtZS9OQklTV0IrSGVsdmV0aWNhTmV1ZUxUU3RkLUJkL0ZvbnRTdHJldGNoL05vcm1h bC9Gb250V2VpZ2h0IDcwMC9JdGFsaWNBbmdsZSAwL1N0ZW1WIDE0NC9UeXBlL0ZvbnREZXNjcmlw dG9yL1hIZWlnaHQgNTE3Pj4NZW5kb2JqDTEgMCBvYmoNW10NZW5kb2JqDTIgMCBvYmoNPDwvQmFz ZUZvbnQvSGVsdmV0aWNhL0VuY29kaW5nIDQgMCBSL05hbWUvSGVsdi9TdWJ0eXBlL1R5cGUxL1R5 cGUvRm9udD4+DWVuZG9iag0zIDAgb2JqDTw8L0Jhc2VGb250L1phcGZEaW5nYmF0cy9OYW1lL1ph RGIvU3VidHlwZS9UeXBlMS9UeXBlL0ZvbnQ+Pg1lbmRvYmoNNCAwIG9iag08PC9EaWZmZXJlbmNl c1syNC9icmV2ZS9jYXJvbi9jaXJjdW1mbGV4L2RvdGFjY2VudC9odW5nYXJ1bWxhdXQvb2dvbmVr L3JpbmcvdGlsZGUgMzkvcXVvdGVzaW5nbGUgOTYvZ3JhdmUgMTI4L2J1bGxldC9kYWdnZXIvZGFn Z2VyZGJsL2VsbGlwc2lzL2VtZGFzaC9lbmRhc2gvZmxvcmluL2ZyYWN0aW9uL2d1aWxzaW5nbGxl ZnQvZ3VpbHNpbmdscmlnaHQvbWludXMvcGVydGhvdXNhbmQvcXVvdGVkYmxiYXNlL3F1b3RlZGJs bGVmdC9xdW90ZWRibHJpZ2h0L3F1b3RlbGVmdC9xdW90ZXJpZ2h0L3F1b3Rlc2luZ2xiYXNlL3Ry YWRlbWFyay9maS9mbC9Mc2xhc2gvT0UvU2Nhcm9uL1lkaWVyZXNpcy9aY2Fyb24vZG90bGVzc2kv bHNsYXNoL29lL3NjYXJvbi96Y2Fyb24gMTYwL0V1cm8gMTY0L2N1cnJlbmN5IDE2Ni9icm9rZW5i YXIgMTY4L2RpZXJlc2lzL2NvcHlyaWdodC9vcmRmZW1pbmluZSAxNzIvbG9naWNhbG5vdC8ubm90 ZGVmL3JlZ2lzdGVyZWQvbWFjcm9uL2RlZ3JlZS9wbHVzbWludXMvdHdvc3VwZXJpb3IvdGhyZWVz dXBlcmlvci9hY3V0ZS9tdSAxODMvcGVyaW9kY2VudGVyZWQvY2VkaWxsYS9vbmVzdXBlcmlvci9v cmRtYXNjdWxpbmUgMTg4L29uZXF1YXJ0ZXIvb25laGFsZi90aHJlZXF1YXJ0ZXJzIDE5Mi9BZ3Jh dmUvQWFjdXRlL0FjaXJjdW1mbGV4L0F0aWxkZS9BZGllcmVzaXMvQXJpbmcvQUUvQ2NlZGlsbGEv RWdyYXZlL0VhY3V0ZS9FY2lyY3VtZmxleC9FZGllcmVzaXMvSWdyYXZlL0lhY3V0ZS9JY2lyY3Vt ZmxleC9JZGllcmVzaXMvRXRoL050aWxkZS9PZ3JhdmUvT2FjdXRlL09jaXJjdW1mbGV4L090aWxk ZS9PZGllcmVzaXMvbXVsdGlwbHkvT3NsYXNoL1VncmF2ZS9VYWN1dGUvVWNpcmN1bWZsZXgvVWRp ZXJlc2lzL1lhY3V0ZS9UaG9ybi9nZXJtYW5kYmxzL2FncmF2ZS9hYWN1dGUvYWNpcmN1bWZsZXgv YXRpbGRlL2FkaWVyZXNpcy9hcmluZy9hZS9jY2VkaWxsYS9lZ3JhdmUvZWFjdXRlL2VjaXJjdW1m bGV4L2VkaWVyZXNpcy9pZ3JhdmUvaWFjdXRlL2ljaXJjdW1mbGV4L2lkaWVyZXNpcy9ldGgvbnRp bGRlL29ncmF2ZS9vYWN1dGUvb2NpcmN1bWZsZXgvb3RpbGRlL29kaWVyZXNpcy9kaXZpZGUvb3Ns YXNoL3VncmF2ZS91YWN1dGUvdWNpcmN1bWZsZXgvdWRpZXJlc2lzL3lhY3V0ZS90aG9ybi95ZGll cmVzaXNdL1R5cGUvRW5jb2Rpbmc+Pg1lbmRvYmoNNSAwIG9iag08PC9Db3VudCAxL0tpZHNbMTEg MCBSXS9UeXBlL1BhZ2VzPj4NZW5kb2JqDTYgMCBvYmoNPDwvTGVuZ3RoIDMxMTQvU3VidHlwZS9Y TUwvVHlwZS9NZXRhZGF0YT4+c3RyZWFtDQo8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBN cENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEv IiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA0LjIuMS1jMDQxIDUyLjM0Mjk5NiwgMjAwOC8wNS8w Ny0yMTozNzoxOSAgICAgICAgIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3Lncz Lm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiBy ZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hh cC8xLjAvIj4KICAgICAgICAgPHhtcDpNb2RpZnlEYXRlPjIwMDktMDQtMjFUMTA6MTM6NDQrMDM6 MDA8L3htcDpNb2RpZnlEYXRlPgogICAgICAgICA8eG1wOkNyZWF0ZURhdGU+MjAwOS0wNC0yMVQx MDoxMzo0NCswMzowMDwveG1wOkNyZWF0ZURhdGU+CiAgICAgICAgIDx4bXA6TWV0YWRhdGFEYXRl PjIwMDktMDQtMjFUMTA6MTM6NDQrMDM6MDA8L3htcDpNZXRhZGF0YURhdGU+CiAgICAgIDwvcmRm OkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAg ICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iPgogICAgICAg ICA8ZGM6Zm9ybWF0PmFwcGxpY2F0aW9uL3BkZjwvZGM6Zm9ybWF0PgogICAgICA8L3JkZjpEZXNj cmlwdGlvbj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAg eG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iPgogICAgICAgICA8 eG1wTU06RG9jdW1lbnRJRD51dWlkOmNiYzA4YzE2LWVmNGItYjg0Zi1hNzY0LTA2YzM2ZWZlMGM4 MDwveG1wTU06RG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkluc3RhbmNlSUQ+dXVpZDozYzNm YzcyYy1hMzlmLTA4NGEtOWRlMC0xYzNlYjcxNTMzYWE8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAg IDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgogICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAK ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgCjw/eHBhY2tldCBlbmQ9 InciPz4NZW5kc3RyZWFtDWVuZG9iag03IDAgb2JqDTw8L0NyZWF0aW9uRGF0ZShEOjIwMDkwNDIx MTAxMzQ0KzAzJzAwJykvTW9kRGF0ZShEOjIwMDkwNDIxMTAxMzQ0KzAzJzAwJyk+Pg1lbmRvYmoN eHJlZg0wIDgNMDAwMDAwMDAwMCA2NTUzNSBmDQowMDAwMDM4NjcxIDAwMDAwIG4NCjAwMDAwMzg2 ODkgMDAwMDAgbg0KMDAwMDAzODc3NyAwMDAwMCBuDQowMDAwMDM4ODUzIDAwMDAwIG4NCjAwMDAw NDAwNDQgMDAwMDAgbg0KMDAwMDA0MDA5NiAwMDAwMCBuDQowMDAwMDQzMjg2IDAwMDAwIG4NCnRy YWlsZXINPDwvU2l6ZSA4L0lEWzw1MzY3Q0REMDE5ODQ0MThGQTlEQTY5RUREOEE4OEYwRT48MkRD NjhGNjE1NTc4NDdBRkIwOEU2M0VEQUQ1OTIzM0U+XT4+DXN0YXJ0eHJlZg0xMTYNJSVFT0YNNiAw IG9iag08PC9MZW5ndGggMzExNC9TdWJ0eXBlL1hNTC9UeXBlL01ldGFkYXRhPj5zdHJlYW0NCjw/ eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+Cjx4Onht cG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDQu Mi4xLWMwNDEgNTIuMzQyOTk2LCAyMDA4LzA1LzA3LTIwOjQ4OjAwICAgICAgICAiPgogICA8cmRm OlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1u cyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxu czp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPgogICAgICAgICA8eG1wOk1vZGlm eURhdGU+MjAwOS0wNC0yNlQxOTowNzozNyswMjowMDwveG1wOk1vZGlmeURhdGU+CiAgICAgICAg IDx4bXA6Q3JlYXRlRGF0ZT4yMDA5LTA0LTIxVDEwOjEzOjQ0KzAzOjAwPC94bXA6Q3JlYXRlRGF0 ZT4KICAgICAgICAgPHhtcDpNZXRhZGF0YURhdGU+MjAwOS0wNC0yNlQxOTowNzozNyswMjowMDwv eG1wOk1ldGFkYXRhRGF0ZT4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgICAgIDxyZGY6RGVz Y3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5v cmcvZGMvZWxlbWVudHMvMS4xLyI+CiAgICAgICAgIDxkYzpmb3JtYXQ+YXBwbGljYXRpb24vcGRm PC9kYzpmb3JtYXQ+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0 aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2Jl LmNvbS94YXAvMS4wL21tLyI+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPnV1aWQ6Y2JjMDhj MTYtZWY0Yi1iODRmLWE3NjQtMDZjMzZlZmUwYzgwPC94bXBNTTpEb2N1bWVudElEPgogICAgICAg ICA8eG1wTU06SW5zdGFuY2VJRD51dWlkOjExOWJmZjcxLTQ3MTYtNDMwZC05YTk2LTc4ZDNjZmY4 M2IwYzwveG1wTU06SW5zdGFuY2VJRD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRm OlJERj4KPC94OnhtcG1ldGE+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAK ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAg ICAgICAgICAgICAgICAKPD94cGFja2V0IGVuZD0idyI/Pg0KZW5kc3RyZWFtDWVuZG9iag03IDAg b2JqDTw8L0NyZWF0aW9uRGF0ZShEOjIwMDkwNDIxMTAxMzQ0KzAzJzAwJykvTW9kRGF0ZShEOjIw MDkwNDI2MTkwNzM3KzAyJzAwJyk+Pg1lbmRvYmoNMTAgMCBvYmoNPDwvREEoL0hlbHYgMCBUZiAw IGcgKS9EUjw8L0VuY29kaW5nPDwvUERGRG9jRW5jb2RpbmcgNCAwIFI+Pi9Gb250PDwvQ291ciA0 MCAwIFIvSGVsdiAyIDAgUi9aYURiIDMgMCBSPj4+Pi9GaWVsZHMgMSAwIFI+Pg1lbmRvYmoNMTEg MCBvYmoNPDwvQW5ub3RzIDQxIDAgUi9BcnRCb3hbMC4wIDAuMDAwOTc2NTYyIDU5NS4yNzUgODQx Ljg5XS9CbGVlZEJveFswLjAgMC4wIDU5NS4yNzUgODQxLjg5XS9Db250ZW50c1sxMyAwIFIgMTUg MCBSIDE3IDAgUiAxOCAwIFIgMTkgMCBSIDIwIDAgUiAyMiAwIFIgMjMgMCBSXS9Dcm9wQm94WzAu MCAwLjAgNTk1LjI3NSA4NDEuODldL01lZGlhQm94WzAuMCAwLjAgNTk1LjI3NSA4NDEuODldL1Bh cmVudCA1IDAgUi9SZXNvdXJjZXM8PC9FeHRHU3RhdGU8PC9HUzAgMjQgMCBSPj4vRm9udDw8L0My XzAgMjEgMCBSL1QxXzAgMTQgMCBSL1QxXzEgMTYgMCBSL1RUMCAxMiAwIFI+Pi9Qcm9jU2V0Wy9Q REYvVGV4dF0vUHJvcGVydGllczw8L01DMDw8L0NvbG9yWzIwMjI0IDMyNzY4IDY1NTM1XS9EaW1t ZWQgZmFsc2UvRWRpdGFibGUgdHJ1ZS9QcmV2aWV3IHRydWUvUHJpbnRlZCB0cnVlL1RpdGxlKExh eWVyIDEpL1Zpc2libGUgdHJ1ZT4+Pj4+Pi9Sb3RhdGUgMC9UcmltQm94WzAuMCAwLjAgNTk1LjI3 NSA4NDEuODldL1R5cGUvUGFnZT4+DWVuZG9iag00MCAwIG9iag08PC9CYXNlRm9udC9Db3VyaWVy L0VuY29kaW5nIDQgMCBSL05hbWUvQ291ci9TdWJ0eXBlL1R5cGUxL1R5cGUvRm9udD4+DWVuZG9i ag00MSAwIG9iag1bNDIgMCBSIDQzIDAgUiA0NCAwIFIgNDUgMCBSIDQ2IDAgUiA0NyAwIFIgNDgg MCBSIDQ5IDAgUiA1MCAwIFIgNTEgMCBSXQ1lbmRvYmoNNDIgMCBvYmoNPDwvQVA8PC9OIDcxIDAg Uj4+L0JTIDcwIDAgUi9DcmVhdGlvbkRhdGUoRDoyMDA5MDQyNjE5MDMxMCswMicwMCcpL0RBKDE2 LjI1IFRMIC9Db3VyIDEyIFRmKS9EUyhmb250OiBDb3VyaWVyIDEyLjBwdDsgdGV4dC1hbGlnbjps ZWZ0OyBjb2xvcjojMDAwMDAwICkvRiA0L0lUL0ZyZWVUZXh0VHlwZXdyaXRlci9NKEQ6MjAwOTA0 MjYxOTAzMTIrMDInMDAnKS9OTSg3NmI1MWMyYS01OGNiLTQ3MzMtYTFlNy0wODJkMDU0MmY3NGYp L1AgMTEgMCBSL1JEWzAuNSAwLjUgMC41IDAuNV0vUmVjdFsyNTIuMDgxIDUuNTE4MzQgMjY3LjQ4 MSAxOC41MTgzXS9TdWJqKFNjaHJlaWJtYXNjaGluZW50ZXh0KS9TdWJ0eXBlL0ZyZWVUZXh0L1Qo WFRSRU1FKS9UeXBlL0Fubm90Pj4NZW5kb2JqDTQzIDAgb2JqDTw8L0FQPDwvTiA2OSAwIFI+Pi9C UyA2OCAwIFIvQ3JlYXRpb25EYXRlKEQ6MjAwOTA0MjYxOTAzMTIrMDInMDAnKS9EQSgxMSBUTCAv Q291ciA4IFRmKS9EUyhmb250OiBDb3VyaWVyIDguMHB0OyB0ZXh0LWFsaWduOmxlZnQ7IGNvbG9y OiMwMDAwMDAgKS9GIDQvSVQvRnJlZVRleHRUeXBld3JpdGVyL00oRDoyMDA5MDQyNjE5MDYxOCsw MicwMCcpL05NKGNiZGQxMTNiLTE2M2ItNDEyNy04ZWZjLTRmMjVmNjBjOTBmYSkvUCAxMSAwIFIv UkRbMC41IDAuNSAwLjUgMC41XS9SZWN0WzI5MS45NCA1LjA1MzU5IDMzNi4xNSAxOC45NTE2XS9T dWJqKFNjaHJlaWJtYXNjaGluZW50ZXh0KS9TdWJ0eXBlL0ZyZWVUZXh0L1QoWFRSRU1FKS9UeXBl L0Fubm90Pj4NZW5kb2JqDTQ0IDAgb2JqDTw8L0FQPDwvTiA2NyAwIFI+Pi9CUyA2NiAwIFIvQ3Jl YXRpb25EYXRlKEQ6MjAwOTA0MjYxOTAzMTIrMDInMDAnKS9EQSgxNi4yNSBUTCAvQ291ciAxMiBU ZikvRFMoZm9udDogQ291cmllciAxMi4wcHQ7IHRleHQtYWxpZ246bGVmdDsgY29sb3I6IzAwMDAw MCApL0YgNC9JVC9GcmVlVGV4dFR5cGV3cml0ZXIvTShEOjIwMDkwNDI2MTkwMzEzKzAyJzAwJykv Tk0oNWIyODhhM2YtNzEzNS00MGYyLWE0NWYtMjQ0OGMzNmNlMmQxKS9QIDExIDAgUi9SRFswLjUg MC41IDAuNSAwLjVdL1JlY3RbMjc1LjQ3NyAyMC42ODE5IDI5MC44NzcgMzMuNjgxOV0vU3ViaihT Y2hyZWlibWFzY2hpbmVudGV4dCkvU3VidHlwZS9GcmVlVGV4dC9UKFhUUkVNRSkvVHlwZS9Bbm5v dD4+DWVuZG9iag00NSAwIG9iag08PC9BUDw8L04gNjUgMCBSPj4vQlMgNjQgMCBSL0NyZWF0aW9u RGF0ZShEOjIwMDkwNDI2MTkwNDA5KzAyJzAwJykvREEoMTYuMjUgVEwgL0NvdXIgMTIgVGYpL0RT KGZvbnQ6IENvdXJpZXIgMTIuMHB0OyB0ZXh0LWFsaWduOmxlZnQ7IGNvbG9yOiMwMDAwMDAgKS9G IDQvSVQvRnJlZVRleHRUeXBld3JpdGVyL00oRDoyMDA5MDQyNjE5MDU1NCswMicwMCcpL05NKDA1 NjY4Mzc1LTE2MTQtNDQwYi05MWMxLWYxM2FlNjQ5NjdjYikvUCAxMSAwIFIvUkRbMC41IDAuNSAw LjUgMC41XS9SZWN0WzMxNi4yMDIgOS44NTA3OCAzMzEuNjAyIDIyLjg1MDhdL1N1YmooU2NocmVp Ym1hc2NoaW5lbnRleHQpL1N1YnR5cGUvRnJlZVRleHQvVChYVFJFTUUpL1R5cGUvQW5ub3Q+Pg1l bmRvYmoNNDYgMCBvYmoNPDwvQVA8PC9OIDYzIDAgUj4+L0JTIDYyIDAgUi9DcmVhdGlvbkRhdGUo RDoyMDA5MDQyNjE5MDQ1MCswMicwMCcpL0RBKDEyLjI1IFRMIC9Db3VyIDkgVGYpL0RTKGZvbnQ6 IENvdXJpZXIgOS4wcHQ7IHRleHQtYWxpZ246bGVmdDsgY29sb3I6IzAwMDAwMCApL0YgNC9JVC9G cmVlVGV4dFR5cGV3cml0ZXIvTShEOjIwMDkwNDI2MTkwNDUzKzAyJzAwJykvTk0oNjM1YjE2Zjkt MjYwZi00ODNiLWFjMTQtMjE1NmM4YTRkNjNlKS9QIDExIDAgUi9SRFswLjUgMC41IDAuNSAwLjVd L1JlY3RbMjgyLjQwOSAzLjM1MjEzIDI5Ny44MDkgMTYuMzUyMV0vU3ViaihTY2hyZWlibWFzY2hp bmVudGV4dCkvU3VidHlwZS9GcmVlVGV4dC9UKFhUUkVNRSkvVHlwZS9Bbm5vdD4+DWVuZG9iag00 NyAwIG9iag08PC9BUDw8L04gNjEgMCBSPj4vQlMgNjAgMCBSL0NyZWF0aW9uRGF0ZShEOjIwMDkw NDI2MTkwNTA5KzAyJzAwJykvREEoMTIuMjUgVEwgL0NvdXIgOSBUZikvRFMoZm9udDogQ291cmll ciA5LjBwdDsgdGV4dC1hbGlnbjpsZWZ0OyBjb2xvcjojMDAwMDAwICkvRiA0L0lUL0ZyZWVUZXh0 VHlwZXdyaXRlci9NKEQ6MjAwOTA0MjYxOTA1MTArMDInMDAnKS9OTSgyMTc2ZjliMi1lNzdkLTQz MjEtYmYxNy1lNmRjMjU0MzRjYWEpL1AgMTEgMCBSL1JEWzAuNSAwLjUgMC41IDAuNV0vUmVjdFsy OTYuNzA2IDEwLjcxNzMgMzEyLjEwNiAyMy43MTczXS9TdWJqKFNjaHJlaWJtYXNjaGluZW50ZXh0 KS9TdWJ0eXBlL0ZyZWVUZXh0L1QoWFRSRU1FKS9UeXBlL0Fubm90Pj4NZW5kb2JqDTQ4IDAgb2Jq DTw8L0FQPDwvTiA1OSAwIFI+Pi9CUyA1OCAwIFIvQ3JlYXRpb25EYXRlKEQ6MjAwOTA0MjYxOTA1 NTArMDInMDAnKS9EQSgxMi4yNSBUTCAvQ291ciA5IFRmKS9EUyhmb250OiBDb3VyaWVyIDkuMHB0 OyB0ZXh0LWFsaWduOmxlZnQ7IGNvbG9yOiMwMDAwMDAgKS9GIDQvSVQvRnJlZVRleHRUeXBld3Jp dGVyL00oRDoyMDA5MDQyNjE5MDU1NyswMicwMCcpL05NKDVlN2I4ODY4LTljYWYtNDY3ZS05MWYz LWI3ZTZhYTFhNWQwMikvUCAxMSAwIFIvUkRbMC41IDAuNSAwLjUgMC41XS9SZWN0WzI4OC45MDcg Ny42ODQ1NyAzMDQuMzA3IDIwLjY4NDZdL1N1YmooU2NocmVpYm1hc2NoaW5lbnRleHQpL1N1YnR5 cGUvRnJlZVRleHQvVChYVFJFTUUpL1R5cGUvQW5ub3Q+Pg1lbmRvYmoNNDkgMCBvYmoNPDwvQVA8 PC9OIDU3IDAgUj4+L0JTIDU2IDAgUi9Db250ZW50cygwNC8yNikvQ3JlYXRpb25EYXRlKEQ6MjAw OTA0MjYxOTA2MjArMDInMDAnKS9EQSgwIEcgMCBnIDAgVGMgMCBUdyAxMDAgVHogMTYuMjUgVEwg MCBUcyAwIFRyIC9Db3VyIDggVGYpL0RTKGZvbnQ6IENvdXIgOC4wcHQ7Zm9udC1zdHJldGNoOk5v cm1hbDsgdGV4dC1hbGlnbjpsZWZ0OyBjb2xvcjojMDAwMDAwICkvRiA0L0lUL0ZyZWVUZXh0VHlw ZXdyaXRlci9NKEQ6MjAwOTA0MjYxOTA3MjIrMDInMDAnKS9OTSgxMzZhM2E3MC0wMmFlLTQwOWEt YTViMy0wZWNiMWQ4NDA5YzQpL1AgMTEgMCBSL1JDKDw/eG1sIHZlcnNpb249IjEuMCI/Pjxib2R5 IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiB4bWxuczp4ZmE9Imh0dHA6Ly93 d3cueGZhLm9yZy9zY2hlbWEveGZhLWRhdGEvMS4wLyIgeGZhOkFQSVZlcnNpb249IkFjcm9iYXQ6 OS4wLjAiIHhmYTpzcGVjPSIyLjAuMiIgIHN0eWxlPSJmb250LXNpemU6OC4wcHQ7dGV4dC1hbGln bjpsZWZ0O2NvbG9yOiMwMDAwMDA7Zm9udC13ZWlnaHQ6bm9ybWFsO2ZvbnQtc3R5bGU6bm9ybWFs O1wNZm9udC1mYW1pbHk6Q291cjtmb250LXN0cmV0Y2g6bm9ybWFsIj48cCBkaXI9Imx0ciI+PHNw YW4gc3R5bGU9ImxpbmUtaGVpZ2h0OjE2LjNwdDtmb250LWZhbWlseTpDb3VyaWVyIj4wNC8yNjwv c3Bhbj48L3A+PC9ib2R5PikvUkRbMC41IDAuNSAwLjUgMC41XS9SZWN0WzI4Ny42MDcgMC43NTI2 NyAzMTIuNjE3IDEzLjc1MjddL1N1YmooU2NocmVpYm1hc2NoaW5lbnRleHQpL1N1YnR5cGUvRnJl ZVRleHQvVChYVFJFTUUpL1R5cGUvQW5ub3Q+Pg1lbmRvYmoNNTAgMCBvYmoNPDwvQVA8PC9OIDU1 IDAgUj4+L0JTIDU0IDAgUi9DcmVhdGlvbkRhdGUoRDoyMDA5MDQyNjE5MDY1NSswMicwMCcpL0RB KDExIFRMIC9Db3VyIDggVGYpL0RTKGZvbnQ6IENvdXJpZXIgOC4wcHQ7IHRleHQtYWxpZ246bGVm dDsgY29sb3I6IzAwMDAwMCApL0YgNC9JVC9GcmVlVGV4dFR5cGV3cml0ZXIvTShEOjIwMDkwNDI2 MTkwNzA2KzAyJzAwJykvTk0oM2NlYjMwNzItMmY5Ni00ZDNiLTljYWEtNzc0ZTZmOTc0ZTc3KS9Q IDExIDAgUi9SRFswLjUgMC41IDAuNSAwLjVdL1JlY3RbMjk2LjcwNiAyLjA1MjQgMzEyLjEwNiAx NS4wNTI0XS9TdWJqKFNjaHJlaWJtYXNjaGluZW50ZXh0KS9TdWJ0eXBlL0ZyZWVUZXh0L1QoWFRS RU1FKS9UeXBlL0Fubm90Pj4NZW5kb2JqDTUxIDAgb2JqDTw8L0FQPDwvTiA1MyAwIFI+Pi9CUyA1 MiAwIFIvQ3JlYXRpb25EYXRlKEQ6MjAwOTA0MjYxOTA3MjMrMDInMDAnKS9EQSgxMSBUTCAvQ291 ciA4IFRmKS9EUyhmb250OiBDb3VyaWVyIDguMHB0OyB0ZXh0LWFsaWduOmxlZnQ7IGNvbG9yOiMw MDAwMDAgKS9GIDQvSVQvRnJlZVRleHRUeXBld3JpdGVyL00oRDoyMDA5MDQyNjE5MDczNyswMicw MCcpL05NKDYzYjI1OWI4LTRkZWYtNDVkMy1hMDkwLWE1OWEwOTUzZjI4NykvUCAxMSAwIFIvUkRb MC41IDAuNSAwLjUgMC41XS9SZWN0WzM1My44OTQgMy4zNTIxMyAzNjkuMjk0IDE2LjM1MjFdL1N1 YmooU2NocmVpYm1hc2NoaW5lbnRleHQpL1N1YnR5cGUvRnJlZVRleHQvVChYVFJFTUUpL1R5cGUv QW5ub3Q+Pg1lbmRvYmoNNTIgMCBvYmoNPDwvVyAwLjA+Pg1lbmRvYmoNNTMgMCBvYmoNPDwvQkJv eFszNTMuODk0IDMuMzUyMTMgMzY5LjI5NCAxNi4zNTIxXS9Gb3JtVHlwZSAxL0xlbmd0aCA1NC9N YXRyaXhbMS4wIDAuMCAwLjAgMS4wIC0zNTMuODk0IC0zLjM1MjEzXS9SZXNvdXJjZXM8PC9Qcm9j U2V0Wy9QREZdPj4vU3VidHlwZS9Gb3JtL1R5cGUvWE9iamVjdD4+c3RyZWFtDQpxCjEgMCAwIDEg MCAwIGNtCjM1NC4zOTM5IDMuODUyMSAxNC40IDEyIHJlClcKbgowIGcKUQoNCmVuZHN0cmVhbQ1l bmRvYmoNNTQgMCBvYmoNPDwvVyAwLjA+Pg1lbmRvYmoNNTUgMCBvYmoNPDwvQkJveFsyOTYuNzA2 IDIuMDUyNCAzMTIuMTA2IDE1LjA1MjRdL0Zvcm1UeXBlIDEvTGVuZ3RoIDU0L01hdHJpeFsxLjAg MC4wIDAuMCAxLjAgLTI5Ni43MDYgLTIuMDUyNF0vUmVzb3VyY2VzPDwvUHJvY1NldFsvUERGXT4+ L1N1YnR5cGUvRm9ybS9UeXBlL1hPYmplY3Q+PnN0cmVhbQ0KcQoxIDAgMCAxIDAgMCBjbQoyOTcu MjA1NiAyLjU1MjQgMTQuNCAxMiByZQpXCm4KMCBnClEKDQplbmRzdHJlYW0NZW5kb2JqDTU2IDAg b2JqDTw8L1cgMC4wPj4NZW5kb2JqDTU3IDAgb2JqDTw8L0JCb3hbMjg3LjYwNyAwLjc1MjY3IDMx Mi42MTcgMTMuNzUyN10vRm9ybVR5cGUgMS9MZW5ndGggMTA0L01hdHJpeFsxLjAgMC4wIDAuMCAx LjAgLTI4Ny42MDcgLTAuNzUyNjddL1Jlc291cmNlczw8L0ZvbnQ8PC9Db3VyIDQwIDAgUj4+L1By b2NTZXRbL1BERi9UZXh0XT4+L1N1YnR5cGUvRm9ybS9UeXBlL1hPYmplY3Q+PnN0cmVhbQ0KcQox IDAgMCAxIDAgMCBjbQoyODguMTA3NSAxLjI1MjcgMjQuMDEgMTIgcmUKVwpuCjAgZwpCVAovQ291 ciA4IFRmCjAgZwoyODguMTA3IDcuNjQ1IFRkCigwNC8yNikgVGoKRVQKUQoNCmVuZHN0cmVhbQ1l bmRvYmoNNTggMCBvYmoNPDwvVyAwLjA+Pg1lbmRvYmoNNTkgMCBvYmoNPDwvQkJveFsyODguOTA3 IDcuNjg0NTcgMzA0LjMwNyAyMC42ODQ2XS9Gb3JtVHlwZSAxL0xlbmd0aCA1NC9NYXRyaXhbMS4w IDAuMCAwLjAgMS4wIC0yODguOTA3IC03LjY4NDU3XS9SZXNvdXJjZXM8PC9Qcm9jU2V0Wy9QREZd Pj4vU3VidHlwZS9Gb3JtL1R5cGUvWE9iamVjdD4+c3RyZWFtDQpxCjEgMCAwIDEgMCAwIGNtCjI4 OS40MDcyIDguMTg0NiAxNC40IDEyIHJlClcKbgowIGcKUQoNCmVuZHN0cmVhbQ1lbmRvYmoNNjAg MCBvYmoNPDwvVyAwLjA+Pg1lbmRvYmoNNjEgMCBvYmoNPDwvQkJveFsyOTYuNzA2IDEwLjcxNzMg MzEyLjEwNiAyMy43MTczXS9Gb3JtVHlwZSAxL0xlbmd0aCA1NS9NYXRyaXhbMS4wIDAuMCAwLjAg MS4wIC0yOTYuNzA2IC0xMC43MTczXS9SZXNvdXJjZXM8PC9Qcm9jU2V0Wy9QREZdPj4vU3VidHlw ZS9Gb3JtL1R5cGUvWE9iamVjdD4+c3RyZWFtDQpxCjEgMCAwIDEgMCAwIGNtCjI5Ny4yMDU2IDEx LjIxNzMgMTQuNCAxMiByZQpXCm4KMCBnClEKDQplbmRzdHJlYW0NZW5kb2JqDTYyIDAgb2JqDTw8 L1cgMC4wPj4NZW5kb2JqDTYzIDAgb2JqDTw8L0JCb3hbMjgyLjQwOSAzLjM1MjEzIDI5Ny44MDkg MTYuMzUyMV0vRm9ybVR5cGUgMS9MZW5ndGggNTQvTWF0cml4WzEuMCAwLjAgMC4wIDEuMCAtMjgy LjQwOSAtMy4zNTIxM10vUmVzb3VyY2VzPDwvUHJvY1NldFsvUERGXT4+L1N1YnR5cGUvRm9ybS9U eXBlL1hPYmplY3Q+PnN0cmVhbQ0KcQoxIDAgMCAxIDAgMCBjbQoyODIuOTA4NiAzLjg1MjEgMTQu NCAxMiByZQpXCm4KMCBnClEKDQplbmRzdHJlYW0NZW5kb2JqDTY0IDAgb2JqDTw8L1cgMC4wPj4N ZW5kb2JqDTY1IDAgb2JqDTw8L0JCb3hbMzE2LjIwMiA5Ljg1MDc4IDMzMS42MDIgMjIuODUwOF0v Rm9ybVR5cGUgMS9MZW5ndGggNTUvTWF0cml4WzEuMCAwLjAgMC4wIDEuMCAtMzE2LjIwMiAtOS44 NTA3OF0vUmVzb3VyY2VzPDwvUHJvY1NldFsvUERGXT4+L1N1YnR5cGUvRm9ybS9UeXBlL1hPYmpl Y3Q+PnN0cmVhbQ0KcQoxIDAgMCAxIDAgMCBjbQozMTYuNzAxNiAxMC4zNTA4IDE0LjQgMTIgcmUK VwpuCjAgZwpRCg0KZW5kc3RyZWFtDWVuZG9iag02NiAwIG9iag08PC9XIDAuMD4+DWVuZG9iag02 NyAwIG9iag08PC9CQm94WzI3NS40NzcgMjAuNjgxOSAyOTAuODc3IDMzLjY4MTldL0Zvcm1UeXBl IDEvTGVuZ3RoIDU1L01hdHJpeFsxLjAgMC4wIDAuMCAxLjAgLTI3NS40NzcgLTIwLjY4MTldL1Jl c291cmNlczw8L1Byb2NTZXRbL1BERl0+Pi9TdWJ0eXBlL0Zvcm0vVHlwZS9YT2JqZWN0Pj5zdHJl YW0NCnEKMSAwIDAgMSAwIDAgY20KMjc1Ljk3NjcgMjEuMTgxOSAxNC40IDEyIHJlClcKbgowIGcK UQoNCmVuZHN0cmVhbQ1lbmRvYmoNNjggMCBvYmoNPDwvVyAwLjA+Pg1lbmRvYmoNNjkgMCBvYmoN PDwvQkJveFsyOTEuOTQgNS4wNTM1OSAzMzYuMTUgMTguOTUxNl0vRm9ybVR5cGUgMS9MZW5ndGgg NTkvTWF0cml4WzEuMCAwLjAgMC4wIDEuMCAtMjkxLjk0IC01LjA1MzU5XS9SZXNvdXJjZXM8PC9Q cm9jU2V0Wy9QREZdPj4vU3VidHlwZS9Gb3JtL1R5cGUvWE9iamVjdD4+c3RyZWFtDQpxCjEgMCAw IDEgMCAwIGNtCjI5Mi40Mzk5IDUuNTUzNiA0My4yMSAxMi44OTggcmUKVwpuCjAgZwpRCg0KZW5k c3RyZWFtDWVuZG9iag03MCAwIG9iag08PC9XIDAuMD4+DWVuZG9iag03MSAwIG9iag08PC9CQm94 WzI1Mi4wODEgNS41MTgzNCAyNjcuNDgxIDE4LjUxODNdL0Zvcm1UeXBlIDEvTGVuZ3RoIDU0L01h dHJpeFsxLjAgMC4wIDAuMCAxLjAgLTI1Mi4wODEgLTUuNTE4MzRdL1Jlc291cmNlczw8L1Byb2NT ZXRbL1BERl0+Pi9TdWJ0eXBlL0Zvcm0vVHlwZS9YT2JqZWN0Pj5zdHJlYW0NCnEKMSAwIDAgMSAw IDAgY20KMjUyLjU4MTUgNi4wMTgzIDE0LjQgMTIgcmUKVwpuCjAgZwpRCg0KZW5kc3RyZWFtDWVu ZG9iag14cmVmDQowIDENCjAwMDAwMDAwMDAgNjU1MzUgZg0KNiAyDQowMDAwMDQzNjU5IDAwMDAw IG4NCjAwMDAwNDY4NTAgMDAwMDAgbg0KMTAgMg0KMDAwMDA0Njk0MSAwMDAwMCBuDQowMDAwMDQ3 MDc5IDAwMDAwIG4NCjQwIDMyDQowMDAwMDQ3NjI0IDAwMDAwIG4NCjAwMDAwNDc3MTEgMDAwMDAg bg0KMDAwMDA0Nzc5OSAwMDAwMCBuDQowMDAwMDQ4MTkzIDAwMDAwIG4NCjAwMDAwNDg1ODAgMDAw MDAgbg0KMDAwMDA0ODk3NCAwMDAwMCBuDQowMDAwMDQ5MzY4IDAwMDAwIG4NCjAwMDAwNDk3NjAg MDAwMDAgbg0KMDAwMDA1MDE1MiAwMDAwMCBuDQowMDAwMDUwNTQ0IDAwMDAwIG4NCjAwMDAwNTEz OTMgMDAwMDAgbg0KMDAwMDA1MTc4MSAwMDAwMCBuDQowMDAwMDUyMTcwIDAwMDAwIG4NCjAwMDAw NTIxOTcgMDAwMDAgbg0KMDAwMDA1MjQ0NiAwMDAwMCBuDQowMDAwMDUyNDczIDAwMDAwIG4NCjAw MDAwNTI3MjAgMDAwMDAgbg0KMDAwMDA1Mjc0NyAwMDAwMCBuDQowMDAwMDUzMDczIDAwMDAwIG4N CjAwMDAwNTMxMDAgMDAwMDAgbg0KMDAwMDA1MzM0OSAwMDAwMCBuDQowMDAwMDUzMzc2IDAwMDAw IG4NCjAwMDAwNTM2MjYgMDAwMDAgbg0KMDAwMDA1MzY1MyAwMDAwMCBuDQowMDAwMDUzOTAyIDAw MDAwIG4NCjAwMDAwNTM5MjkgMDAwMDAgbg0KMDAwMDA1NDE3OSAwMDAwMCBuDQowMDAwMDU0MjA2 IDAwMDAwIG4NCjAwMDAwNTQ0NTYgMDAwMDAgbg0KMDAwMDA1NDQ4MyAwMDAwMCBuDQowMDAwMDU0 NzM0IDAwMDAwIG4NCjAwMDAwNTQ3NjEgMDAwMDAgbg0KdHJhaWxlcg0KPDwvU2l6ZSA3Mi9Sb290 IDkgMCBSL0luZm8gNyAwIFIvSURbPDUzNjdDREQwMTk4NDQxOEZBOURBNjlFREQ4QTg4RjBFPjw0 RTRCRDM5NkEzRUU1MDQ4QjkxMTQ5NTc0RUI1MEM5RT5dL1ByZXYgMTE2Pj4NCnN0YXJ0eHJlZg0K NTUwMTANCiUlRU9GDQo2IDAgb2JqDTw8L0xlbmd0aCAzMTE0L1N1YnR5cGUvWE1ML1R5cGUvTWV0 YWRhdGE+PnN0cmVhbQ0KPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6 TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0i QWRvYmUgWE1QIENvcmUgNC4yLjEtYzA0MyA1Mi4zNzI3MjgsIDIwMDkvMDEvMTgtMTU6MDg6MDQg ICAgICAgICI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8w Mi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIi CiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyI+CiAg ICAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDA5LTA0LTI3VDE5OjM3OjIwKzAyOjAwPC94bXA6TW9k aWZ5RGF0ZT4KICAgICAgICAgPHhtcDpDcmVhdGVEYXRlPjIwMDktMDQtMjFUMTA6MTM6NDQrMDM6 MDA8L3htcDpDcmVhdGVEYXRlPgogICAgICAgICA8eG1wOk1ldGFkYXRhRGF0ZT4yMDA5LTA0LTI3 VDE5OjM3OjIwKzAyOjAwPC94bXA6TWV0YWRhdGFEYXRlPgogICAgICA8L3JkZjpEZXNjcmlwdGlv bj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6 ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KICAgICAgICAgPGRjOmZvcm1h dD5hcHBsaWNhdGlvbi9wZGY8L2RjOmZvcm1hdD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAg ICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcE1N PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIj4KICAgICAgICAgPHhtcE1NOkRvY3Vt ZW50SUQ+dXVpZDpjYmMwOGMxNi1lZjRiLWI4NGYtYTc2NC0wNmMzNmVmZTBjODA8L3htcE1NOkRv Y3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpJbnN0YW5jZUlEPnV1aWQ6YzVjZTI5ZWMtMjUwOS00 ZTBlLThmZWMtMDVlOGU1MTUyMzUzPC94bXBNTTpJbnN0YW5jZUlEPgogICAgICA8L3JkZjpEZXNj cmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAog ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIAo8P3hwYWNrZXQgZW5kPSJ3Ij8+DQplbmRz dHJlYW0NZW5kb2JqDTcgMCBvYmoNPDwvQ3JlYXRpb25EYXRlKEQ6MjAwOTA0MjExMDEzNDQrMDMn MDAnKS9Nb2REYXRlKEQ6MjAwOTA0MjcxOTM3MjArMDInMDAnKT4+DWVuZG9iag00OSAwIG9iag08 PC9BUDw8L04gNzIgMCBSPj4vQlMgNTYgMCBSL0NvbnRlbnRzKDA0LzI3KS9DcmVhdGlvbkRhdGUo RDoyMDA5MDQyNjE5MDYyMCswMicwMCcpL0RBKDAgRyAwIGcgMCBUYyAwIFR3IDEwMCBUeiAxNi4z IFRMIDAgVHMgMCBUciAvQ291ciA4IFRmKS9EUyhmb250OiBDb3VyIDguMHB0O2ZvbnQtc3RyZXRj aDpOb3JtYWw7IHRleHQtYWxpZ246bGVmdDsgY29sb3I6IzAwMDAwMCApL0YgNC9JVC9GcmVlVGV4 dFR5cGV3cml0ZXIvTShEOjIwMDkwNDI3MTkzNzIwKzAyJzAwJykvTk0oMTM2YTNhNzAtMDJhZS00 MDlhLWE1YjMtMGVjYjFkODQwOWM0KS9QIDExIDAgUi9SQyg8P3htbCB2ZXJzaW9uPSIxLjAiPz48 Ym9keSB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgeG1sbnM6eGZhPSJodHRw Oi8vd3d3LnhmYS5vcmcvc2NoZW1hL3hmYS1kYXRhLzEuMC8iIHhmYTpBUElWZXJzaW9uPSJBY3Jv YmF0OjkuMS4wIiB4ZmE6c3BlYz0iMi4wLjIiICBzdHlsZT0iZm9udC1zaXplOjguMHB0O3RleHQt YWxpZ246bGVmdDtjb2xvcjojMDAwMDAwO2ZvbnQtd2VpZ2h0Om5vcm1hbDtmb250LXN0eWxlOm5v cm1hbDtcDWZvbnQtZmFtaWx5OkNvdXI7Zm9udC1zdHJldGNoOm5vcm1hbCI+PHAgZGlyPSJsdHIi PjxzcGFuIHN0eWxlPSJsaW5lLWhlaWdodDoxNi4zcHQ7Zm9udC1mYW1pbHk6Q291cmllciI+MDQv Mjc8L3NwYW4+PC9wPjwvYm9keT4pL1JEWzAuNSAwLjUgMC41IDAuNV0vUmVjdFsyODcuNjA3IDAu NzUyNjcgMzEyLjYxNyAxMy43NTI3XS9TdWJqKFNjaHJlaWJtYXNjaGluZW50ZXh0KS9TdWJ0eXBl L0ZyZWVUZXh0L1QoWFRSRU1FKS9UeXBlL0Fubm90Pj4NZW5kb2JqDTcyIDAgb2JqDTw8L0JCb3hb Mjg3LjYwNyAwLjc1MjY3IDMxMi42MTcgMTMuNzUyN10vRm9ybVR5cGUgMS9MZW5ndGggMTAzL01h dHJpeFsxLjAgMC4wIDAuMCAxLjAgLTI4Ny42MDcgLTAuNzUyNjddL1Jlc291cmNlczw8L0ZvbnQ8 PC9Db3VyIDQwIDAgUj4+L1Byb2NTZXRbL1BERi9UZXh0XT4+L1N1YnR5cGUvRm9ybS9UeXBlL1hP YmplY3Q+PnN0cmVhbQ0KcQoxIDAgMCAxIDAgMCBjbQoyODguMTA3IDEuMjUyNyAyNC4wMSAxMiBy ZQpXCm4KMCBnCkJUCi9Db3VyIDggVGYKMCBnCjI4OC4xMDcgNy42NDUgVGQKKDA0LzI3KSBUagpF VApRCg0KZW5kc3RyZWFtDWVuZG9iag14cmVmDQowIDENCjAwMDAwMDAwMDAgNjU1MzUgZg0KNiAy DQowMDAwMDU1OTMxIDAwMDAwIG4NCjAwMDAwNTkxMjIgMDAwMDAgbg0KNDkgMQ0KMDAwMDA1OTIx MyAwMDAwMCBuDQo3MiAxDQowMDAwMDYwMDYxIDAwMDAwIG4NCnRyYWlsZXINCjw8L1NpemUgNzMv Um9vdCA5IDAgUi9JbmZvIDcgMCBSL0lEWzw1MzY3Q0REMDE5ODQ0MThGQTlEQTY5RUREOEE4OEYw RT48QjM2QjZFQkI2NUFFN0E0REE0OTIyQkExRkFEMkNFQUE+XS9QcmV2IDU1MDEwPj4NCnN0YXJ0 eHJlZg0KNjAzODYNCiUlRU9GDQo2IDAgb2JqDTw8L0xlbmd0aCAzMTE0L1N1YnR5cGUvWE1ML1R5 cGUvTWV0YWRhdGE+PnN0cmVhbQ0KPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhp SHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4 bXB0az0iQWRvYmUgWE1QIENvcmUgNC4yLjEtYzA0MyA1Mi4zNzI3MjgsIDIwMDkvMDEvMTgtMTU6 MDg6MDQgICAgICAgICI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcv MTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFi b3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4w LyI+CiAgICAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDA5LTA1LTAzVDE2OjA0OjA3KzAyOjAwPC94 bXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcDpDcmVhdGVEYXRlPjIwMDktMDQtMjFUMTA6MTM6 NDQrMDM6MDA8L3htcDpDcmVhdGVEYXRlPgogICAgICAgICA8eG1wOk1ldGFkYXRhRGF0ZT4yMDA5 LTA1LTAzVDE2OjA0OjA3KzAyOjAwPC94bXA6TWV0YWRhdGFEYXRlPgogICAgICA8L3JkZjpEZXNj cmlwdGlvbj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAg eG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KICAgICAgICAgPGRj OmZvcm1hdD5hcHBsaWNhdGlvbi9wZGY8L2RjOmZvcm1hdD4KICAgICAgPC9yZGY6RGVzY3JpcHRp b24+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5z OnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIj4KICAgICAgICAgPHhtcE1N OkRvY3VtZW50SUQ+dXVpZDpjYmMwOGMxNi1lZjRiLWI4NGYtYTc2NC0wNmMzNmVmZTBjODA8L3ht cE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpJbnN0YW5jZUlEPnV1aWQ6YTEyMmMwOTgt YzQ4Ni00YjJlLThjMWMtMjI5NTg0YTI5NzEzPC94bXBNTTpJbnN0YW5jZUlEPgogICAgICA8L3Jk ZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAK ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIAo8P3hwYWNrZXQgZW5kPSJ3Ij8+ DQplbmRzdHJlYW0NZW5kb2JqDTcgMCBvYmoNPDwvQ3JlYXRpb25EYXRlKEQ6MjAwOTA0MjExMDEz NDQrMDMnMDAnKS9Nb2REYXRlKEQ6MjAwOTA1MDMxNjA0MDcrMDInMDAnKT4+DWVuZG9iag00OSAw IG9iag08PC9BUDw8L04gNzMgMCBSPj4vQlMgNTYgMCBSL0NvbnRlbnRzKDA1LzAzKS9DcmVhdGlv bkRhdGUoRDoyMDA5MDQyNjE5MDYyMCswMicwMCcpL0RBKDAgRyAwIGcgMCBUYyAwIFR3IDEwMCBU eiAxNi4zIFRMIDAgVHMgMCBUciAvQ291ciA4IFRmKS9EUyhmb250OiBDb3VyIDguMHB0O2ZvbnQt c3RyZXRjaDpOb3JtYWw7IHRleHQtYWxpZ246bGVmdDsgY29sb3I6IzAwMDAwMCApL0YgNC9JVC9G cmVlVGV4dFR5cGV3cml0ZXIvTShEOjIwMDkwNTAzMTYwNDA3KzAyJzAwJykvTk0oMTM2YTNhNzAt MDJhZS00MDlhLWE1YjMtMGVjYjFkODQwOWM0KS9QIDExIDAgUi9SQyg8P3htbCB2ZXJzaW9uPSIx LjAiPz48Ym9keSB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgeG1sbnM6eGZh PSJodHRwOi8vd3d3LnhmYS5vcmcvc2NoZW1hL3hmYS1kYXRhLzEuMC8iIHhmYTpBUElWZXJzaW9u PSJBY3JvYmF0OjkuMS4wIiB4ZmE6c3BlYz0iMi4wLjIiICBzdHlsZT0iZm9udC1zaXplOjguMHB0 O3RleHQtYWxpZ246bGVmdDtjb2xvcjojMDAwMDAwO2ZvbnQtd2VpZ2h0Om5vcm1hbDtmb250LXN0 eWxlOm5vcm1hbDtcDWZvbnQtZmFtaWx5OkNvdXI7Zm9udC1zdHJldGNoOm5vcm1hbCI+PHAgZGly PSJsdHIiPjxzcGFuIHN0eWxlPSJsaW5lLWhlaWdodDoxNi4zcHQ7Zm9udC1mYW1pbHk6Q291cmll ciI+MDUvMDM8L3NwYW4+PC9wPjwvYm9keT4pL1JEWzAuNSAwLjUgMC41IDAuNV0vUmVjdFsyODcu NjA3IDAuNzUyNjcgMzEyLjYxNyAxMy43NTI3XS9TdWJqKFNjaHJlaWJtYXNjaGluZW50ZXh0KS9T dWJ0eXBlL0ZyZWVUZXh0L1QoWFRSRU1FKS9UeXBlL0Fubm90Pj4NZW5kb2JqDTczIDAgb2JqDTw8 L0JCb3hbMjg3LjYwNyAwLjc1MjY3IDMxMi42MTcgMTMuNzUyN10vRm9ybVR5cGUgMS9MZW5ndGgg MTAzL01hdHJpeFsxLjAgMC4wIDAuMCAxLjAgLTI4Ny42MDcgLTAuNzUyNjddL1Jlc291cmNlczw8 L0ZvbnQ8PC9Db3VyIDQwIDAgUj4+L1Byb2NTZXRbL1BERi9UZXh0XT4+L1N1YnR5cGUvRm9ybS9U eXBlL1hPYmplY3Q+PnN0cmVhbQ0KcQoxIDAgMCAxIDAgMCBjbQoyODguMTA3IDEuMjUyNyAyNC4w MSAxMiByZQpXCm4KMCBnCkJUCi9Db3VyIDggVGYKMCBnCjI4OC4xMDcgNy42NDUgVGQKKDA1LzAz KSBUagpFVApRCg0KZW5kc3RyZWFtDWVuZG9iag14cmVmDQowIDENCjAwMDAwMDAwMDAgNjU1MzUg Zg0KNiAyDQowMDAwMDYwNjY4IDAwMDAwIG4NCjAwMDAwNjM4NTkgMDAwMDAgbg0KNDkgMQ0KMDAw MDA2Mzk1MCAwMDAwMCBuDQo3MyAxDQowMDAwMDY0Nzk4IDAwMDAwIG4NCnRyYWlsZXINCjw8L1Np emUgNzQvUm9vdCA5IDAgUi9JbmZvIDcgMCBSL0lEWzw1MzY3Q0REMDE5ODQ0MThGQTlEQTY5RURE OEE4OEYwRT48NjVBMzA5MDI0NkRCRTI0MEFCMDY3QUM0OTk1NEY0OTM+XS9QcmV2IDYwMzg2Pj4N CnN0YXJ0eHJlZg0KNjUxMjMNCiUlRU9GDQo2IDAgb2JqDTw8L0xlbmd0aCAzMTE0L1N1YnR5cGUv WE1ML1R5cGUvTWV0YWRhdGE+PnN0cmVhbQ0KPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0w TXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRh LyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNC4yLjEtYzA0MyA1Mi4zNzI3MjgsIDIwMDkvMDEv MTgtMTU6MDg6MDQgICAgICAgICI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53 My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24g cmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94 YXAvMS4wLyI+CiAgICAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDA5LTA1LTA0VDE2OjEwOjM4KzAy OjAwPC94bXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcDpDcmVhdGVEYXRlPjIwMDktMDQtMjFU MTA6MTM6NDQrMDM6MDA8L3htcDpDcmVhdGVEYXRlPgogICAgICAgICA8eG1wOk1ldGFkYXRhRGF0 ZT4yMDA5LTA1LTA0VDE2OjEwOjM4KzAyOjAwPC94bXA6TWV0YWRhdGFEYXRlPgogICAgICA8L3Jk ZjpEZXNjcmlwdGlvbj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAg ICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KICAgICAg ICAgPGRjOmZvcm1hdD5hcHBsaWNhdGlvbi9wZGY8L2RjOmZvcm1hdD4KICAgICAgPC9yZGY6RGVz Y3JpcHRpb24+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAg IHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIj4KICAgICAgICAg PHhtcE1NOkRvY3VtZW50SUQ+dXVpZDpjYmMwOGMxNi1lZjRiLWI4NGYtYTc2NC0wNmMzNmVmZTBj ODA8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpJbnN0YW5jZUlEPnV1aWQ6ZDdh OWFkYjAtODg1Ni00MWJhLWJiMjctOGEyMDIzNTc0ZGIwPC94bXBNTTpJbnN0YW5jZUlEPgogICAg ICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIAo8P3hwYWNrZXQgZW5k PSJ3Ij8+DQplbmRzdHJlYW0NZW5kb2JqDTcgMCBvYmoNPDwvQ3JlYXRpb25EYXRlKEQ6MjAwOTA0 MjExMDEzNDQrMDMnMDAnKS9Nb2REYXRlKEQ6MjAwOTA1MDQxNjEwMzgrMDInMDAnKT4+DWVuZG9i ag00OSAwIG9iag08PC9BUDw8L04gNzQgMCBSPj4vQlMgNTYgMCBSL0NvbnRlbnRzKDA1LzA0KS9D cmVhdGlvbkRhdGUoRDoyMDA5MDQyNjE5MDYyMCswMicwMCcpL0RBKDAgRyAwIGcgMCBUYyAwIFR3 IDEwMCBUeiAxNi4zIFRMIDAgVHMgMCBUciAvQ291ciA4IFRmKS9EUyhmb250OiBDb3VyIDguMHB0 O2ZvbnQtc3RyZXRjaDpOb3JtYWw7IHRleHQtYWxpZ246bGVmdDsgY29sb3I6IzAwMDAwMCApL0Yg NC9JVC9GcmVlVGV4dFR5cGV3cml0ZXIvTShEOjIwMDkwNTA0MTYxMDM4KzAyJzAwJykvTk0oMTM2 YTNhNzAtMDJhZS00MDlhLWE1YjMtMGVjYjFkODQwOWM0KS9QIDExIDAgUi9SQyg8P3htbCB2ZXJz aW9uPSIxLjAiPz48Ym9keSB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgeG1s bnM6eGZhPSJodHRwOi8vd3d3LnhmYS5vcmcvc2NoZW1hL3hmYS1kYXRhLzEuMC8iIHhmYTpBUElW ZXJzaW9uPSJBY3JvYmF0OjkuMS4wIiB4ZmE6c3BlYz0iMi4wLjIiICBzdHlsZT0iZm9udC1zaXpl OjguMHB0O3RleHQtYWxpZ246bGVmdDtjb2xvcjojMDAwMDAwO2ZvbnQtd2VpZ2h0Om5vcm1hbDtm b250LXN0eWxlOm5vcm1hbDtcDWZvbnQtZmFtaWx5OkNvdXI7Zm9udC1zdHJldGNoOm5vcm1hbCI+ PHAgZGlyPSJsdHIiPjxzcGFuIHN0eWxlPSJsaW5lLWhlaWdodDoxNi4zcHQ7Zm9udC1mYW1pbHk6 Q291cmllciI+MDUvMDQ8L3NwYW4+PC9wPjwvYm9keT4pL1JEWzAuNSAwLjUgMC41IDAuNV0vUmVj dFsyODcuNjA3IDAuNzUyNjcgMzEyLjYxNyAxMy43NTI3XS9TdWJqKFNjaHJlaWJtYXNjaGluZW50 ZXh0KS9TdWJ0eXBlL0ZyZWVUZXh0L1QoWFRSRU1FKS9UeXBlL0Fubm90Pj4NZW5kb2JqDTc0IDAg b2JqDTw8L0JCb3hbMjg3LjYwNyAwLjc1MjY3IDMxMi42MTcgMTMuNzUyN10vRm9ybVR5cGUgMS9M ZW5ndGggMTAzL01hdHJpeFsxLjAgMC4wIDAuMCAxLjAgLTI4Ny42MDcgLTAuNzUyNjddL1Jlc291 cmNlczw8L0ZvbnQ8PC9Db3VyIDQwIDAgUj4+L1Byb2NTZXRbL1BERi9UZXh0XT4+L1N1YnR5cGUv Rm9ybS9UeXBlL1hPYmplY3Q+PnN0cmVhbQ0KcQoxIDAgMCAxIDAgMCBjbQoyODguMTA3IDEuMjUy NyAyNC4wMSAxMiByZQpXCm4KMCBnCkJUCi9Db3VyIDggVGYKMCBnCjI4OC4xMDcgNy42NDUgVGQK KDA1LzA0KSBUagpFVApRCg0KZW5kc3RyZWFtDWVuZG9iag14cmVmDQowIDENCjAwMDAwMDAwMDAg NjU1MzUgZg0KNiAyDQowMDAwMDY1NDA1IDAwMDAwIG4NCjAwMDAwNjg1OTYgMDAwMDAgbg0KNDkg MQ0KMDAwMDA2ODY4NyAwMDAwMCBuDQo3NCAxDQowMDAwMDY5NTM1IDAwMDAwIG4NCnRyYWlsZXIN Cjw8L1NpemUgNzUvUm9vdCA5IDAgUi9JbmZvIDcgMCBSL0lEWzw1MzY3Q0REMDE5ODQ0MThGQTlE QTY5RUREOEE4OEYwRT48NzQ0QTA0MTREMjVCNTE0RUI0MDJGRUZGQjhGMjA2QjE+XS9QcmV2IDY1 MTIzPj4NCnN0YXJ0eHJlZg0KNjk4NjANCiUlRU9GDQo2IDAgb2JqDTw8L0xlbmd0aCAzMTE0L1N1 YnR5cGUvWE1ML1R5cGUvTWV0YWRhdGE+PnN0cmVhbQ0KPD94cGFja2V0IGJlZ2luPSLvu78iIGlk PSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpu czptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNC4yLjEtYzA0MyA1Mi4zNzI3MjgsIDIw MDkvMDEvMTgtMTU6MDg6MDQgICAgICAgICI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDov L3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3Jp cHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2Jl LmNvbS94YXAvMS4wLyI+CiAgICAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDA5LTA1LTA1VDE3OjUz OjUwKzAyOjAwPC94bXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcDpDcmVhdGVEYXRlPjIwMDkt MDQtMjFUMTA6MTM6NDQrMDM6MDA8L3htcDpDcmVhdGVEYXRlPgogICAgICAgICA8eG1wOk1ldGFk YXRhRGF0ZT4yMDA5LTA1LTA1VDE3OjUzOjUwKzAyOjAwPC94bXA6TWV0YWRhdGFEYXRlPgogICAg ICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIK ICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4K ICAgICAgICAgPGRjOmZvcm1hdD5hcHBsaWNhdGlvbi9wZGY8L2RjOmZvcm1hdD4KICAgICAgPC9y ZGY6RGVzY3JpcHRpb24+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAg ICAgICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIj4KICAg ICAgICAgPHhtcE1NOkRvY3VtZW50SUQ+dXVpZDpjYmMwOGMxNi1lZjRiLWI4NGYtYTc2NC0wNmMz NmVmZTBjODA8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpJbnN0YW5jZUlEPnV1 aWQ6MDcxOTlmODctNDA2ZS00MjMyLWEyMjMtZDk0MDA2NGFlNGZlPC94bXBNTTpJbnN0YW5jZUlE PgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAog ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIAo8P3hwYWNr ZXQgZW5kPSJ3Ij8+DQplbmRzdHJlYW0NZW5kb2JqDTcgMCBvYmoNPDwvQ3JlYXRpb25EYXRlKEQ6 MjAwOTA0MjExMDEzNDQrMDMnMDAnKS9Nb2REYXRlKEQ6MjAwOTA1MDUxNzUzNTArMDInMDAnKT4+ DWVuZG9iag00OSAwIG9iag08PC9BUDw8L04gNzYgMCBSPj4vQlMgNTYgMCBSL0NvbnRlbnRzKDA1 LzA1KS9DcmVhdGlvbkRhdGUoRDoyMDA5MDQyNjE5MDYyMCswMicwMCcpL0RBKDAgRyAwIGcgMCBU YyAwIFR3IDEwMCBUeiAxNi4zIFRMIDAgVHMgMCBUciAvQ291ciA4IFRmKS9EUyhmb250OiBDb3Vy IDguMHB0O2ZvbnQtc3RyZXRjaDpOb3JtYWw7IHRleHQtYWxpZ246bGVmdDsgY29sb3I6IzAwMDAw MCApL0YgNC9JVC9GcmVlVGV4dFR5cGV3cml0ZXIvTShEOjIwMDkwNTA1MTc1MzUwKzAyJzAwJykv Tk0oMTM2YTNhNzAtMDJhZS00MDlhLWE1YjMtMGVjYjFkODQwOWM0KS9QIDExIDAgUi9SQyg8P3ht bCB2ZXJzaW9uPSIxLjAiPz48Ym9keSB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRt bCIgeG1sbnM6eGZhPSJodHRwOi8vd3d3LnhmYS5vcmcvc2NoZW1hL3hmYS1kYXRhLzEuMC8iIHhm YTpBUElWZXJzaW9uPSJBY3JvYmF0OjkuMS4wIiB4ZmE6c3BlYz0iMi4wLjIiICBzdHlsZT0iZm9u dC1zaXplOjguMHB0O3RleHQtYWxpZ246bGVmdDtjb2xvcjojMDAwMDAwO2ZvbnQtd2VpZ2h0Om5v cm1hbDtmb250LXN0eWxlOm5vcm1hbDtcDWZvbnQtZmFtaWx5OkNvdXI7Zm9udC1zdHJldGNoOm5v cm1hbCI+PHAgZGlyPSJsdHIiPjxzcGFuIHN0eWxlPSJsaW5lLWhlaWdodDoxNi4zcHQ7Zm9udC1m YW1pbHk6Q291cmllciI+MDUvMDU8L3NwYW4+PC9wPjwvYm9keT4pL1JEWzAuNSAwLjUgMC41IDAu NV0vUmVjdFsyODcuNjA3IDAuNzUyNjcgMzEyLjYxNyAxMy43NTI3XS9TdWJqKFNjaHJlaWJtYXNj aGluZW50ZXh0KS9TdWJ0eXBlL0ZyZWVUZXh0L1QoWFRSRU1FKS9UeXBlL0Fubm90Pj4NZW5kb2Jq DTUwIDAgb2JqDTw8L0FQPDwvTiA3NSAwIFI+Pi9CUyA1NCAwIFIvQ3JlYXRpb25EYXRlKEQ6MjAw OTA0MjYxOTA2NTUrMDInMDAnKS9EQSgxMSBUTCAvQ291ciA4IFRmKS9EUyhmb250OiBDb3VyaWVy IDguMHB0OyB0ZXh0LWFsaWduOmxlZnQ7IGNvbG9yOiMwMDAwMDAgKS9GIDQvSVQvRnJlZVRleHRU eXBld3JpdGVyL00oRDoyMDA5MDUwNTE3NTMzNyswMicwMCcpL05NKDNjZWIzMDcyLTJmOTYtNGQz Yi05Y2FhLTc3NGU2Zjk3NGU3NykvUCAxMSAwIFIvUkRbMC41IDAuNSAwLjUgMC41XS9SZWN0WzI5 Ni43MDYgMi4wNTI0IDMxMi4xMDYgMTUuMDUyNF0vU3ViaihTY2hyZWlibWFzY2hpbmVudGV4dCkv U3VidHlwZS9GcmVlVGV4dC9UKFhUUkVNRSkvVHlwZS9Bbm5vdD4+DWVuZG9iag03NSAwIG9iag08 PC9CQm94WzI5Ni43MDYgMi4wNTI0IDMxMi4xMDYgMTUuMDUyNF0vRm9ybVR5cGUgMS9MZW5ndGgg NTMvTWF0cml4WzEuMCAwLjAgMC4wIDEuMCAtMjk2LjcwNiAtMi4wNTI0XS9SZXNvdXJjZXM8PC9Q cm9jU2V0Wy9QREZdPj4vU3VidHlwZS9Gb3JtL1R5cGUvWE9iamVjdD4+c3RyZWFtDQpxCjEgMCAw IDEgMCAwIGNtCjI5Ny4yMDYgMi41NTI0IDE0LjQgMTIgcmUKVwpuCjAgZwpRCg0KZW5kc3RyZWFt DWVuZG9iag03NiAwIG9iag08PC9CQm94WzI4Ny42MDcgMC43NTI2NyAzMTIuNjE3IDEzLjc1Mjdd L0Zvcm1UeXBlIDEvTGVuZ3RoIDEwMy9NYXRyaXhbMS4wIDAuMCAwLjAgMS4wIC0yODcuNjA3IC0w Ljc1MjY3XS9SZXNvdXJjZXM8PC9Gb250PDwvQ291ciA0MCAwIFI+Pi9Qcm9jU2V0Wy9QREYvVGV4 dF0+Pi9TdWJ0eXBlL0Zvcm0vVHlwZS9YT2JqZWN0Pj5zdHJlYW0NCnEKMSAwIDAgMSAwIDAgY20K Mjg4LjEwNyAxLjI1MjcgMjQuMDEgMTIgcmUKVwpuCjAgZwpCVAovQ291ciA4IFRmCjAgZwoyODgu MTA3IDcuNjQ1IFRkCigwNS8wNSkgVGoKRVQKUQoNCmVuZHN0cmVhbQ1lbmRvYmoNeHJlZg0KMCAx DQowMDAwMDAwMDAwIDY1NTM1IGYNCjYgMg0KMDAwMDA3MDE0MiAwMDAwMCBuDQowMDAwMDczMzMz IDAwMDAwIG4NCjQ5IDINCjAwMDAwNzM0MjQgMDAwMDAgbg0KMDAwMDA3NDI3MiAwMDAwMCBuDQo3 NSAyDQowMDAwMDc0NjYwIDAwMDAwIG4NCjAwMDAwNzQ5MDYgMDAwMDAgbg0KdHJhaWxlcg0KPDwv U2l6ZSA3Ny9Sb290IDkgMCBSL0luZm8gNyAwIFIvSURbPDUzNjdDREQwMTk4NDQxOEZBOURBNjlF REQ4QTg4RjBFPjwzQkU1QTU1MUE4Mzg3NjQzOERFOTU1MEMyRkJFOUU5Mj5dL1ByZXYgNjk4NjA+ Pg0Kc3RhcnR4cmVmDQo3NTIzMQ0KJSVFT0YNCjYgMCBvYmoNPDwvTGVuZ3RoIDMxMTQvU3VidHlw ZS9YTUwvVHlwZS9NZXRhZGF0YT4+c3RyZWFtDQo8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1 TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1l dGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA0LjIuMS1jMDQzIDUyLjM3MjcyOCwgMjAwOS8w MS8xOC0xNTowODowNCAgICAgICAgIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3 LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlv biByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29t L3hhcC8xLjAvIj4KICAgICAgICAgPHhtcDpNb2RpZnlEYXRlPjIwMDktMDUtMDZUMTg6NDM6NTMr MDI6MDA8L3htcDpNb2RpZnlEYXRlPgogICAgICAgICA8eG1wOkNyZWF0ZURhdGU+MjAwOS0wNC0y MVQxMDoxMzo0NCswMzowMDwveG1wOkNyZWF0ZURhdGU+CiAgICAgICAgIDx4bXA6TWV0YWRhdGFE YXRlPjIwMDktMDUtMDZUMTg6NDM6NTMrMDI6MDA8L3htcDpNZXRhZGF0YURhdGU+CiAgICAgIDwv cmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAg ICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iPgogICAg ICAgICA8ZGM6Zm9ybWF0PmFwcGxpY2F0aW9uL3BkZjwvZGM6Zm9ybWF0PgogICAgICA8L3JkZjpE ZXNjcmlwdGlvbj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAg ICAgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iPgogICAgICAg ICA8eG1wTU06RG9jdW1lbnRJRD51dWlkOmNiYzA4YzE2LWVmNGItYjg0Zi1hNzY0LTA2YzM2ZWZl MGM4MDwveG1wTU06RG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkluc3RhbmNlSUQ+dXVpZDo2 MmEwNTY0ZC1lMjAwLTQzOTctYTdmOS01NTdkMjI2YWI4NGU8L3htcE1NOkluc3RhbmNlSUQ+CiAg ICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgogICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAK ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgCjw/eHBhY2tldCBl bmQ9InciPz4NCmVuZHN0cmVhbQ1lbmRvYmoNNyAwIG9iag08PC9DcmVhdGlvbkRhdGUoRDoyMDA5 MDQyMTEwMTM0NCswMycwMCcpL01vZERhdGUoRDoyMDA5MDUwNjE4NDM1MyswMicwMCcpPj4NZW5k b2JqDTQ5IDAgb2JqDTw8L0FQPDwvTiA3OCAwIFI+Pi9CUyA1NiAwIFIvQ29udGVudHMoMDUvMDYp L0NyZWF0aW9uRGF0ZShEOjIwMDkwNDI2MTkwNjIwKzAyJzAwJykvREEoMCBHIDAgZyAwIFRjIDAg VHcgMTAwIFR6IDE2LjMgVEwgMCBUcyAwIFRyIC9Db3VyIDggVGYpL0RTKGZvbnQ6IENvdXIgOC4w cHQ7Zm9udC1zdHJldGNoOk5vcm1hbDsgdGV4dC1hbGlnbjpsZWZ0OyBjb2xvcjojMDAwMDAwICkv RiA0L0lUL0ZyZWVUZXh0VHlwZXdyaXRlci9NKEQ6MjAwOTA1MDYxODQzNTMrMDInMDAnKS9OTSgx MzZhM2E3MC0wMmFlLTQwOWEtYTViMy0wZWNiMWQ4NDA5YzQpL1AgMTEgMCBSL1JDKDw/eG1sIHZl cnNpb249IjEuMCI/Pjxib2R5IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiB4 bWxuczp4ZmE9Imh0dHA6Ly93d3cueGZhLm9yZy9zY2hlbWEveGZhLWRhdGEvMS4wLyIgeGZhOkFQ SVZlcnNpb249IkFjcm9iYXQ6OS4xLjAiIHhmYTpzcGVjPSIyLjAuMiIgIHN0eWxlPSJmb250LXNp emU6OC4wcHQ7dGV4dC1hbGlnbjpsZWZ0O2NvbG9yOiMwMDAwMDA7Zm9udC13ZWlnaHQ6bm9ybWFs O2ZvbnQtc3R5bGU6bm9ybWFsO1wNZm9udC1mYW1pbHk6Q291cjtmb250LXN0cmV0Y2g6bm9ybWFs Ij48cCBkaXI9Imx0ciI+PHNwYW4gc3R5bGU9ImxpbmUtaGVpZ2h0OjE2LjNwdDtmb250LWZhbWls eTpDb3VyaWVyIj4wNS8wNjwvc3Bhbj48L3A+PC9ib2R5PikvUkRbMC41IDAuNSAwLjUgMC41XS9S ZWN0WzI4Ny42MDcgMC43NTI2NyAzMTIuNjE3IDEzLjc1MjddL1N1YmooU2NocmVpYm1hc2NoaW5l bnRleHQpL1N1YnR5cGUvRnJlZVRleHQvVChYVFJFTUUpL1R5cGUvQW5ub3Q+Pg1lbmRvYmoNNTAg MCBvYmoNPDwvQVA8PC9OIDc3IDAgUj4+L0JTIDU0IDAgUi9DcmVhdGlvbkRhdGUoRDoyMDA5MDQy NjE5MDY1NSswMicwMCcpL0RBKDExIFRMIC9Db3VyIDggVGYpL0RTKGZvbnQ6IENvdXJpZXIgOC4w cHQ7IHRleHQtYWxpZ246bGVmdDsgY29sb3I6IzAwMDAwMCApL0YgNC9JVC9GcmVlVGV4dFR5cGV3 cml0ZXIvTShEOjIwMDkwNTA2MTg0MzQxKzAyJzAwJykvTk0oM2NlYjMwNzItMmY5Ni00ZDNiLTlj YWEtNzc0ZTZmOTc0ZTc3KS9QIDExIDAgUi9SRFswLjUgMC41IDAuNSAwLjVdL1JlY3RbMjk2Ljcw NiAyLjA1MjQgMzEyLjEwNiAxNS4wNTI0XS9TdWJqKFNjaHJlaWJtYXNjaGluZW50ZXh0KS9TdWJ0 eXBlL0ZyZWVUZXh0L1QoWFRSRU1FKS9UeXBlL0Fubm90Pj4NZW5kb2JqDTc3IDAgb2JqDTw8L0JC b3hbMjk2LjcwNiAyLjA1MjQgMzEyLjEwNiAxNS4wNTI0XS9Gb3JtVHlwZSAxL0xlbmd0aCA1My9N YXRyaXhbMS4wIDAuMCAwLjAgMS4wIC0yOTYuNzA2IC0yLjA1MjRdL1Jlc291cmNlczw8L1Byb2NT ZXRbL1BERl0+Pi9TdWJ0eXBlL0Zvcm0vVHlwZS9YT2JqZWN0Pj5zdHJlYW0NCnEKMSAwIDAgMSAw IDAgY20KMjk3LjIwNiAyLjU1MjQgMTQuNCAxMiByZQpXCm4KMCBnClEKDQplbmRzdHJlYW0NZW5k b2JqDTc4IDAgb2JqDTw8L0JCb3hbMjg3LjYwNyAwLjc1MjY3IDMxMi42MTcgMTMuNzUyN10vRm9y bVR5cGUgMS9MZW5ndGggMTAzL01hdHJpeFsxLjAgMC4wIDAuMCAxLjAgLTI4Ny42MDcgLTAuNzUy NjddL1Jlc291cmNlczw8L0ZvbnQ8PC9Db3VyIDQwIDAgUj4+L1Byb2NTZXRbL1BERi9UZXh0XT4+ L1N1YnR5cGUvRm9ybS9UeXBlL1hPYmplY3Q+PnN0cmVhbQ0KcQoxIDAgMCAxIDAgMCBjbQoyODgu MTA3IDEuMjUyNyAyNC4wMSAxMiByZQpXCm4KMCBnCkJUCi9Db3VyIDggVGYKMCBnCjI4OC4xMDcg Ny42NDUgVGQKKDA1LzA2KSBUagpFVApRCg0KZW5kc3RyZWFtDWVuZG9iag14cmVmDQowIDENCjAw MDAwMDAwMDAgNjU1MzUgZg0KNiAyDQowMDAwMDc1NTUzIDAwMDAwIG4NCjAwMDAwNzg3NDQgMDAw MDAgbg0KNDkgMg0KMDAwMDA3ODgzNSAwMDAwMCBuDQowMDAwMDc5NjgzIDAwMDAwIG4NCjc3IDIN CjAwMDAwODAwNzEgMDAwMDAgbg0KMDAwMDA4MDMxNyAwMDAwMCBuDQp0cmFpbGVyDQo8PC9TaXpl IDc5L1Jvb3QgOSAwIFIvSW5mbyA3IDAgUi9JRFs8NTM2N0NERDAxOTg0NDE4RkE5REE2OUVERDhB ODhGMEU+PEYzQkQwRDBENTU2OUIxNDBBRTJDRERCQzc0MjhCM0E5Pl0vUHJldiA3NTIzMT4+DQpz dGFydHhyZWYNCjgwNjQyDQolJUVPRg0KNiAwIG9iag08PC9MZW5ndGggMzExNC9TdWJ0eXBlL1hN TC9UeXBlL01ldGFkYXRhPj5zdHJlYW0NCjw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1w Q2VoaUh6cmVTek5UY3prYzlkIj8+Cjx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8i IHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDQuMi4xLWMwNDMgNTIuMzcyNzI4LCAyMDA5LzAxLzE4 LTE1OjA4OjA0ICAgICAgICAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMu b3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJk ZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFw LzEuMC8iPgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAwOS0wNS0wN1QxNDoxMzo1MiswMjow MDwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRlRGF0ZT4yMDA5LTA0LTIxVDEw OjEzOjQ0KzAzOjAwPC94bXA6Q3JlYXRlRGF0ZT4KICAgICAgICAgPHhtcDpNZXRhZGF0YURhdGU+ MjAwOS0wNS0wN1QxNDoxMzo1MiswMjowMDwveG1wOk1ldGFkYXRhRGF0ZT4KICAgICAgPC9yZGY6 RGVzY3JpcHRpb24+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAg ICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyI+CiAgICAgICAg IDxkYzpmb3JtYXQ+YXBwbGljYXRpb24vcGRmPC9kYzpmb3JtYXQ+CiAgICAgIDwvcmRmOkRlc2Ny aXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4 bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyI+CiAgICAgICAgIDx4 bXBNTTpEb2N1bWVudElEPnV1aWQ6Y2JjMDhjMTYtZWY0Yi1iODRmLWE3NjQtMDZjMzZlZmUwYzgw PC94bXBNTTpEb2N1bWVudElEPgogICAgICAgICA8eG1wTU06SW5zdGFuY2VJRD51dWlkOjcwZjIy YTdjLTkxOWMtNDRhZC04ZDJjLWIyNjhiMDljOWYxODwveG1wTU06SW5zdGFuY2VJRD4KICAgICAg PC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CiAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAog ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0IGVuZD0i dyI/Pg0KZW5kc3RyZWFtDWVuZG9iag03IDAgb2JqDTw8L0NyZWF0aW9uRGF0ZShEOjIwMDkwNDIx MTAxMzQ0KzAzJzAwJykvTW9kRGF0ZShEOjIwMDkwNTA3MTQxMzUyKzAyJzAwJyk+Pg1lbmRvYmoN NDkgMCBvYmoNPDwvQVA8PC9OIDgwIDAgUj4+L0JTIDU2IDAgUi9Db250ZW50cygwNS8wNykvQ3Jl YXRpb25EYXRlKEQ6MjAwOTA0MjYxOTA2MjArMDInMDAnKS9EQSgwIEcgMCBnIDAgVGMgMCBUdyAx MDAgVHogMTYuMyBUTCAwIFRzIDAgVHIgL0NvdXIgOCBUZikvRFMoZm9udDogQ291ciA4LjBwdDtm b250LXN0cmV0Y2g6Tm9ybWFsOyB0ZXh0LWFsaWduOmxlZnQ7IGNvbG9yOiMwMDAwMDAgKS9GIDQv SVQvRnJlZVRleHRUeXBld3JpdGVyL00oRDoyMDA5MDUwNzE0MTM1MiswMicwMCcpL05NKDEzNmEz YTcwLTAyYWUtNDA5YS1hNWIzLTBlY2IxZDg0MDljNCkvUCAxMSAwIFIvUkMoPD94bWwgdmVyc2lv bj0iMS4wIj8+PGJvZHkgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHhtbG5z OnhmYT0iaHR0cDovL3d3dy54ZmEub3JnL3NjaGVtYS94ZmEtZGF0YS8xLjAvIiB4ZmE6QVBJVmVy c2lvbj0iQWNyb2JhdDo5LjEuMCIgeGZhOnNwZWM9IjIuMC4yIiAgc3R5bGU9ImZvbnQtc2l6ZTo4 LjBwdDt0ZXh0LWFsaWduOmxlZnQ7Y29sb3I6IzAwMDAwMDtmb250LXdlaWdodDpub3JtYWw7Zm9u dC1zdHlsZTpub3JtYWw7XA1mb250LWZhbWlseTpDb3VyO2ZvbnQtc3RyZXRjaDpub3JtYWwiPjxw IGRpcj0ibHRyIj48c3BhbiBzdHlsZT0ibGluZS1oZWlnaHQ6MTYuM3B0O2ZvbnQtZmFtaWx5OkNv dXJpZXIiPjA1LzA3PC9zcGFuPjwvcD48L2JvZHk+KS9SRFswLjUgMC41IDAuNSAwLjVdL1JlY3Rb Mjg3LjYwNyAwLjc1MjY3IDMxMi42MTcgMTMuNzUyN10vU3ViaihTY2hyZWlibWFzY2hpbmVudGV4 dCkvU3VidHlwZS9GcmVlVGV4dC9UKFhUUkVNRSkvVHlwZS9Bbm5vdD4+DWVuZG9iag01MCAwIG9i ag08PC9BUDw8L04gNzkgMCBSPj4vQlMgNTQgMCBSL0NyZWF0aW9uRGF0ZShEOjIwMDkwNDI2MTkw NjU1KzAyJzAwJykvREEoMTEgVEwgL0NvdXIgOCBUZikvRFMoZm9udDogQ291cmllciA4LjBwdDsg dGV4dC1hbGlnbjpsZWZ0OyBjb2xvcjojMDAwMDAwICkvRiA0L0lUL0ZyZWVUZXh0VHlwZXdyaXRl ci9NKEQ6MjAwOTA1MDcxNDEzMzkrMDInMDAnKS9OTSgzY2ViMzA3Mi0yZjk2LTRkM2ItOWNhYS03 NzRlNmY5NzRlNzcpL1AgMTEgMCBSL1JEWzAuNSAwLjUgMC41IDAuNV0vUmVjdFsyOTYuNzA2IDIu MDUyNCAzMTIuMTA2IDE1LjA1MjRdL1N1YmooU2NocmVpYm1hc2NoaW5lbnRleHQpL1N1YnR5cGUv RnJlZVRleHQvVChYVFJFTUUpL1R5cGUvQW5ub3Q+Pg1lbmRvYmoNNzkgMCBvYmoNPDwvQkJveFsy OTYuNzA2IDIuMDUyNCAzMTIuMTA2IDE1LjA1MjRdL0Zvcm1UeXBlIDEvTGVuZ3RoIDUzL01hdHJp eFsxLjAgMC4wIDAuMCAxLjAgLTI5Ni43MDYgLTIuMDUyNF0vUmVzb3VyY2VzPDwvUHJvY1NldFsv UERGXT4+L1N1YnR5cGUvRm9ybS9UeXBlL1hPYmplY3Q+PnN0cmVhbQ0KcQoxIDAgMCAxIDAgMCBj bQoyOTcuMjA2IDIuNTUyNCAxNC40IDEyIHJlClcKbgowIGcKUQoNCmVuZHN0cmVhbQ1lbmRvYmoN ODAgMCBvYmoNPDwvQkJveFsyODcuNjA3IDAuNzUyNjcgMzEyLjYxNyAxMy43NTI3XS9Gb3JtVHlw ZSAxL0xlbmd0aCAxMDMvTWF0cml4WzEuMCAwLjAgMC4wIDEuMCAtMjg3LjYwNyAtMC43NTI2N10v UmVzb3VyY2VzPDwvRm9udDw8L0NvdXIgNDAgMCBSPj4vUHJvY1NldFsvUERGL1RleHRdPj4vU3Vi dHlwZS9Gb3JtL1R5cGUvWE9iamVjdD4+c3RyZWFtDQpxCjEgMCAwIDEgMCAwIGNtCjI4OC4xMDcg MS4yNTI3IDI0LjAxIDEyIHJlClcKbgowIGcKQlQKL0NvdXIgOCBUZgowIGcKMjg4LjEwNyA3LjY0 NSBUZAooMDUvMDcpIFRqCkVUClEKDQplbmRzdHJlYW0NZW5kb2JqDXhyZWYNCjAgMQ0KMDAwMDAw MDAwMCA2NTUzNSBmDQo2IDINCjAwMDAwODA5NjQgMDAwMDAgbg0KMDAwMDA4NDE1NSAwMDAwMCBu DQo0OSAyDQowMDAwMDg0MjQ2IDAwMDAwIG4NCjAwMDAwODUwOTQgMDAwMDAgbg0KNzkgMg0KMDAw MDA4NTQ4MiAwMDAwMCBuDQowMDAwMDg1NzI4IDAwMDAwIG4NCnRyYWlsZXINCjw8L1NpemUgODEv Um9vdCA5IDAgUi9JbmZvIDcgMCBSL0lEWzw1MzY3Q0REMDE5ODQ0MThGQTlEQTY5RUREOEE4OEYw RT48QTYxRTZBMDFEQzM2QUY0NkE5MEYzNjdCMzg1Q0NGRDk+XS9QcmV2IDgwNjQyPj4NCnN0YXJ0 eHJlZg0KODYwNTMNCiUlRU9GDQo2IDAgb2JqDTw8L0xlbmd0aCAzMTE0L1N1YnR5cGUvWE1ML1R5 cGUvTWV0YWRhdGE+PnN0cmVhbQ0KPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhp SHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4 bXB0az0iQWRvYmUgWE1QIENvcmUgNC4yLjEtYzA0MyA1Mi4zNzI3MjgsIDIwMDkvMDEvMTgtMTU6 MDg6MDQgICAgICAgICI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcv MTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFi b3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4w LyI+CiAgICAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDA5LTA1LTA4VDE1OjQ3OjQxKzAyOjAwPC94 bXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcDpDcmVhdGVEYXRlPjIwMDktMDQtMjFUMTA6MTM6 NDQrMDM6MDA8L3htcDpDcmVhdGVEYXRlPgogICAgICAgICA8eG1wOk1ldGFkYXRhRGF0ZT4yMDA5 LTA1LTA4VDE1OjQ3OjQxKzAyOjAwPC94bXA6TWV0YWRhdGFEYXRlPgogICAgICA8L3JkZjpEZXNj cmlwdGlvbj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAg eG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KICAgICAgICAgPGRj OmZvcm1hdD5hcHBsaWNhdGlvbi9wZGY8L2RjOmZvcm1hdD4KICAgICAgPC9yZGY6RGVzY3JpcHRp b24+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5z OnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIj4KICAgICAgICAgPHhtcE1N OkRvY3VtZW50SUQ+dXVpZDpjYmMwOGMxNi1lZjRiLWI4NGYtYTc2NC0wNmMzNmVmZTBjODA8L3ht cE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpJbnN0YW5jZUlEPnV1aWQ6YWJhY2JhMDYt NjQyMS00ZjAyLTk5OTQtYmIzODQ2ODg1MjJkPC94bXBNTTpJbnN0YW5jZUlEPgogICAgICA8L3Jk ZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAK ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIAo8P3hwYWNrZXQgZW5kPSJ3Ij8+ DQplbmRzdHJlYW0NZW5kb2JqDTcgMCBvYmoNPDwvQ3JlYXRpb25EYXRlKEQ6MjAwOTA0MjExMDEz NDQrMDMnMDAnKS9Nb2REYXRlKEQ6MjAwOTA1MDgxNTQ3NDErMDInMDAnKT4+DWVuZG9iag00MSAw IG9iag1bNDIgMCBSIDQzIDAgUiA0NCAwIFIgNDUgMCBSIDQ2IDAgUiA0NyAwIFIgNDggMCBSIDQ5 IDAgUiA1MCAwIFIgNTEgMCBSIDgxIDAgUl0NZW5kb2JqDTQzIDAgb2JqDTw8L0FQPDwvTiA4NyAw IFI+Pi9CUyA2OCAwIFIvQ3JlYXRpb25EYXRlKEQ6MjAwOTA0MjYxOTAzMTIrMDInMDAnKS9EQSgx MSBUTCAvQ291ciA4IFRmKS9EUyhmb250OiBDb3VyaWVyIDguMHB0OyB0ZXh0LWFsaWduOmxlZnQ7 IGNvbG9yOiMwMDAwMDAgKS9GIDQvSVQvRnJlZVRleHRUeXBld3JpdGVyL00oRDoyMDA5MDUwODE1 NDcwNyswMicwMCcpL05NKGNiZGQxMTNiLTE2M2ItNDEyNy04ZWZjLTRmMjVmNjBjOTBmYSkvUCAx MSAwIFIvUkRbMC41IDAuNSAwLjUgMC41XS9SZWN0WzI5MS45NCA1LjA1MzU5IDMzNi4xNSAxOC45 NTE2XS9TdWJqKFNjaHJlaWJtYXNjaGluZW50ZXh0KS9TdWJ0eXBlL0ZyZWVUZXh0L1QoWFRSRU1F KS9UeXBlL0Fubm90Pj4NZW5kb2JqDTQ4IDAgb2JqDTw8L0FQPDwvTiA4NiAwIFI+Pi9CUyA1OCAw IFIvQ3JlYXRpb25EYXRlKEQ6MjAwOTA0MjYxOTA1NTArMDInMDAnKS9EQSgxMi4yNSBUTCAvQ291 ciA5IFRmKS9EUyhmb250OiBDb3VyaWVyIDkuMHB0OyB0ZXh0LWFsaWduOmxlZnQ7IGNvbG9yOiMw MDAwMDAgKS9GIDQvSVQvRnJlZVRleHRUeXBld3JpdGVyL00oRDoyMDA5MDUwODE1NDcyMiswMicw MCcpL05NKDVlN2I4ODY4LTljYWYtNDY3ZS05MWYzLWI3ZTZhYTFhNWQwMikvUCAxMSAwIFIvUkRb MC41IDAuNSAwLjUgMC41XS9SZWN0WzI4OC45MDcgNy42ODQ1NyAzMDQuMzA3IDIwLjY4NDZdL1N1 YmooU2NocmVpYm1hc2NoaW5lbnRleHQpL1N1YnR5cGUvRnJlZVRleHQvVChYVFJFTUUpL1R5cGUv QW5ub3Q+Pg1lbmRvYmoNNDkgMCBvYmoNPDwvQVA8PC9OIDg1IDAgUj4+L0JTIDU2IDAgUi9Db250 ZW50cygwNS8wOCkvQ3JlYXRpb25EYXRlKEQ6MjAwOTA0MjYxOTA2MjArMDInMDAnKS9EQSgwIEcg MCBnIDAgVGMgMCBUdyAxMDAgVHogMTYuMyBUTCAwIFRzIDAgVHIgL0NvdXIgOCBUZikvRFMoZm9u dDogQ291ciA4LjBwdDtmb250LXN0cmV0Y2g6Tm9ybWFsOyB0ZXh0LWFsaWduOmxlZnQ7IGNvbG9y OiMwMDAwMDAgKS9GIDQvSVQvRnJlZVRleHRUeXBld3JpdGVyL00oRDoyMDA5MDUwODE1NDc0MSsw MicwMCcpL05NKDEzNmEzYTcwLTAyYWUtNDA5YS1hNWIzLTBlY2IxZDg0MDljNCkvUCAxMSAwIFIv UkMoPD94bWwgdmVyc2lvbj0iMS4wIj8+PGJvZHkgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5 OTkveGh0bWwiIHhtbG5zOnhmYT0iaHR0cDovL3d3dy54ZmEub3JnL3NjaGVtYS94ZmEtZGF0YS8x LjAvIiB4ZmE6QVBJVmVyc2lvbj0iQWNyb2JhdDo5LjEuMCIgeGZhOnNwZWM9IjIuMC4yIiAgc3R5 bGU9ImZvbnQtc2l6ZTo4LjBwdDt0ZXh0LWFsaWduOmxlZnQ7Y29sb3I6IzAwMDAwMDtmb250LXdl aWdodDpub3JtYWw7Zm9udC1zdHlsZTpub3JtYWw7XA1mb250LWZhbWlseTpDb3VyO2ZvbnQtc3Ry ZXRjaDpub3JtYWwiPjxwIGRpcj0ibHRyIj48c3BhbiBzdHlsZT0ibGluZS1oZWlnaHQ6MTYuM3B0 O2ZvbnQtZmFtaWx5OkNvdXJpZXIiPjA1LzA4PC9zcGFuPjwvcD48L2JvZHk+KS9SRFswLjUgMC41 IDAuNSAwLjVdL1JlY3RbMjg3LjYwNyAwLjc1MjY3IDMxMi42MTcgMTMuNzUyN10vU3ViaihTY2hy ZWlibWFzY2hpbmVudGV4dCkvU3VidHlwZS9GcmVlVGV4dC9UKFhUUkVNRSkvVHlwZS9Bbm5vdD4+ DWVuZG9iag01MCAwIG9iag08PC9BUDw8L04gODQgMCBSPj4vQlMgNTQgMCBSL0NyZWF0aW9uRGF0 ZShEOjIwMDkwNDI2MTkwNjU1KzAyJzAwJykvREEoMTEgVEwgL0NvdXIgOCBUZikvRFMoZm9udDog Q291cmllciA4LjBwdDsgdGV4dC1hbGlnbjpsZWZ0OyBjb2xvcjojMDAwMDAwICkvRiA0L0lUL0Zy ZWVUZXh0VHlwZXdyaXRlci9NKEQ6MjAwOTA1MDgxNTQ3MDIrMDInMDAnKS9OTSgzY2ViMzA3Mi0y Zjk2LTRkM2ItOWNhYS03NzRlNmY5NzRlNzcpL1AgMTEgMCBSL1JEWzAuNSAwLjUgMC41IDAuNV0v UmVjdFsyOTkuNzA2IDIuMDUyNCAzMTMuMzcxIDE4LjAwOTldL1N1YmooU2NocmVpYm1hc2NoaW5l bnRleHQpL1N1YnR5cGUvRnJlZVRleHQvVChYVFJFTUUpL1R5cGUvQW5ub3Q+Pg1lbmRvYmoNODEg MCBvYmoNPDwvQVA8PC9OIDgzIDAgUj4+L0JTIDgyIDAgUi9DcmVhdGlvbkRhdGUoRDoyMDA5MDUw ODE1NDcwNyswMicwMCcpL0RBKDkuNzUgVEwgL0NvdXIgNyBUZikvRFMoZm9udDogQ291cmllciA3 LjBwdDsgdGV4dC1hbGlnbjpsZWZ0OyBjb2xvcjojMDAwMDAwICkvRiA0L0lUL0ZyZWVUZXh0VHlw ZXdyaXRlci9NKEQ6MjAwOTA1MDgxNTQ3MDgrMDInMDAnKS9OTShkNGI4NjdmZC04ZGNjLTQ5YTct OWVjMy1hMWQ5ZGNiODg2Y2QpL1AgMTEgMCBSL1JEWzAuNSAwLjUgMC41IDAuNV0vUmVjdFsyODAu MDA1IC00LjYwMDg4IDI5NS40MDUgOC4zOTkxMl0vU3ViaihTY2hyZWlibWFzY2hpbmVudGV4dCkv U3VidHlwZS9GcmVlVGV4dC9UKFhUUkVNRSkvVHlwZS9Bbm5vdD4+DWVuZG9iag04MiAwIG9iag08 PC9XIDAuMD4+DWVuZG9iag04MyAwIG9iag08PC9CQm94WzI4MC4wMDUgLTQuNjAwODggMjk1LjQw NSA4LjM5OTEyXS9Gb3JtVHlwZSAxL0xlbmd0aCA1NC9NYXRyaXhbMS4wIDAuMCAwLjAgMS4wIC0y ODAuMDA1IDQuNjAwODhdL1Jlc291cmNlczw8L1Byb2NTZXRbL1BERl0+Pi9TdWJ0eXBlL0Zvcm0v VHlwZS9YT2JqZWN0Pj5zdHJlYW0NCnEKMSAwIDAgMSAwIDAgY20KMjgwLjUwNSAtNC4xMDA5IDE0 LjQgMTIgcmUKVwpuCjAgZwpRCg0KZW5kc3RyZWFtDWVuZG9iag04NCAwIG9iag08PC9CQm94WzI5 OS43MDYgMi4wNTI0IDMxMy4zNzEgMTguMDA5OV0vRm9ybVR5cGUgMS9MZW5ndGggNjAvTWF0cml4 WzEuMCAwLjAgMC4wIDEuMCAtMjk5LjcwNiAtMi4wNTI0XS9SZXNvdXJjZXM8PC9Qcm9jU2V0Wy9Q REZdPj4vU3VidHlwZS9Gb3JtL1R5cGUvWE9iamVjdD4+c3RyZWFtDQpxCjEgMCAwIDEgMCAwIGNt CjMwMC4yMDYgMi41NTI0IDEyLjY2NSAxNC45NTc1IHJlClcKbgowIGcKUQoNCmVuZHN0cmVhbQ1l bmRvYmoNODUgMCBvYmoNPDwvQkJveFsyODcuNjA3IDAuNzUyNjcgMzEyLjYxNyAxMy43NTI3XS9G b3JtVHlwZSAxL0xlbmd0aCAxMDMvTWF0cml4WzEuMCAwLjAgMC4wIDEuMCAtMjg3LjYwNyAtMC43 NTI2N10vUmVzb3VyY2VzPDwvRm9udDw8L0NvdXIgNDAgMCBSPj4vUHJvY1NldFsvUERGL1RleHRd Pj4vU3VidHlwZS9Gb3JtL1R5cGUvWE9iamVjdD4+c3RyZWFtDQpxCjEgMCAwIDEgMCAwIGNtCjI4 OC4xMDcgMS4yNTI3IDI0LjAxIDEyIHJlClcKbgowIGcKQlQKL0NvdXIgOCBUZgowIGcKMjg4LjEw NyA3LjY0NSBUZAooMDUvMDgpIFRqCkVUClEKDQplbmRzdHJlYW0NZW5kb2JqDTg2IDAgb2JqDTw8 L0JCb3hbMjg4LjkwNyA3LjY4NDU3IDMwNC4zMDcgMjAuNjg0Nl0vRm9ybVR5cGUgMS9MZW5ndGgg NTMvTWF0cml4WzEuMCAwLjAgMC4wIDEuMCAtMjg4LjkwNyAtNy42ODQ1N10vUmVzb3VyY2VzPDwv UHJvY1NldFsvUERGXT4+L1N1YnR5cGUvRm9ybS9UeXBlL1hPYmplY3Q+PnN0cmVhbQ0KcQoxIDAg MCAxIDAgMCBjbQoyODkuNDA3IDguMTg0NiAxNC40IDEyIHJlClcKbgowIGcKUQoNCmVuZHN0cmVh bQ1lbmRvYmoNODcgMCBvYmoNPDwvQkJveFsyOTEuOTQgNS4wNTM1OSAzMzYuMTUgMTguOTUxNl0v Rm9ybVR5cGUgMS9MZW5ndGggNTcvTWF0cml4WzEuMCAwLjAgMC4wIDEuMCAtMjkxLjk0IC01LjA1 MzU5XS9SZXNvdXJjZXM8PC9Qcm9jU2V0Wy9QREZdPj4vU3VidHlwZS9Gb3JtL1R5cGUvWE9iamVj dD4+c3RyZWFtDQpxCjEgMCAwIDEgMCAwIGNtCjI5Mi40NCA1LjU1MzYgNDMuMjEgMTIuODk4IHJl ClcKbgowIGcKUQoNCmVuZHN0cmVhbQ1lbmRvYmoNeHJlZg0KMCAxDQowMDAwMDAwMDAwIDY1NTM1 IGYNCjYgMg0KMDAwMDA4NjM3NSAwMDAwMCBuDQowMDAwMDg5NTY2IDAwMDAwIG4NCjQxIDENCjAw MDAwODk2NTcgMDAwMDAgbg0KNDMgMQ0KMDAwMDA4OTc1MiAwMDAwMCBuDQo0OCAzDQowMDAwMDkw MTM5IDAwMDAwIG4NCjAwMDAwOTA1MzEgMDAwMDAgbg0KMDAwMDA5MTM3OSAwMDAwMCBuDQo4MSA3 DQowMDAwMDkxNzY3IDAwMDAwIG4NCjAwMDAwOTIxNTkgMDAwMDAgbg0KMDAwMDA5MjE4NiAwMDAw MCBuDQowMDAwMDkyNDM1IDAwMDAwIG4NCjAwMDAwOTI2ODggMDAwMDAgbg0KMDAwMDA5MzAxMyAw MDAwMCBuDQowMDAwMDkzMjYxIDAwMDAwIG4NCnRyYWlsZXINCjw8L1NpemUgODgvUm9vdCA5IDAg Ui9JbmZvIDcgMCBSL0lEWzw1MzY3Q0REMDE5ODQ0MThGQTlEQTY5RUREOEE4OEYwRT48RUJEM0Uy OTBCNDdBRUM0ODkwOTJDRjczRDgzMUY4QUY+XS9QcmV2IDg2MDUzPj4NCnN0YXJ0eHJlZg0KOTM1 MTANCiUlRU9GDQo= --b1_3cd9431b2c724af1b5cfddb4f0591813-- From Louis.Rilling@kerlabs.com Mon May 11 04:15:39 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-0.6 required=5.0 tests=BAYES_00,FRT_LEVITRA, J_CHICKENPOX_57,J_CHICKENPOX_63 autolearn=no version=3.3.0-rupdated Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n4B9FcHY242139 for ; Mon, 11 May 2009 04:15:39 -0500 X-ASG-Debug-ID: 1242033341-085700e30000-sLlkUa X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi Received: from bohort.kerlabs.com (localhost [127.0.0.1]) by cuda.sgi.com (Spam Firewall) with ESMTP id 0EF4F1D22AE2 for ; Mon, 11 May 2009 02:15:42 -0700 (PDT) Received: from bohort.kerlabs.com (bohort.kerlabs.com [62.160.40.57]) by cuda.sgi.com with ESMTP id QCdupkET8SET6INy for ; Mon, 11 May 2009 02:15:42 -0700 (PDT) Received: from hawkmoon.kerlabs.com (hawkmoon.kerlabs.com [::ffff:10.3.0.7]) (AUTH: LOGIN louis, SSL: TLSv1/SSLv3,128bits,AES128-SHA) by bohort.kerlabs.com with esmtp; Mon, 11 May 2009 11:15:24 +0200 id 0000000000968080.000000004A07ECAC.00002323 Date: Mon, 11 May 2009 11:15:39 +0200 From: Louis Rilling To: Jason Wessel Cc: linux-kernel@vger.kernel.org, kgdb-bugreport@lists.sourceforge.net, kdb@oss.sgi.com X-ASG-Orig-Subj: Re: [PATCH 0/13] RFC ONLY - kdb for kgdb Subject: Re: [PATCH 0/13] RFC ONLY - kdb for kgdb Message-ID: <20090511091539.GM25550@hawkmoon.kerlabs.com> Reply-To: Louis.Rilling@kerlabs.com Mail-Followup-To: Jason Wessel , linux-kernel@vger.kernel.org, kgdb-bugreport@lists.sourceforge.net, kdb@oss.sgi.com References: <1241817800-9320-1-git-send-email-jason.wessel@windriver.com> Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="=_bohort-8995-1242033324-0001-2" Content-Disposition: inline In-Reply-To: <1241817800-9320-1-git-send-email-jason.wessel@windriver.com> User-Agent: Mutt/1.5.17+20080114 (2008-01-14) X-Barracuda-Connect: bohort.kerlabs.com[62.160.40.57] X-Barracuda-Start-Time: 1242033343 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com X-Barracuda-Spam-Score: -1.28 X-Barracuda-Spam-Status: No, SCORE=-1.28 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests=FRT_LEVITRA X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.1.25486 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.74 FRT_LEVITRA BODY: ReplaceTags: Levitra X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean This is a MIME-formatted message. If you see this text it means that your E-mail software does not support MIME-formatted messages. --=_bohort-8995-1242033324-0001-2 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Hi Jason, On 08/05/09 16:23 -0500, Jason Wessel wrote: > This patch series is a request for comments on several levels. >=20 > 1) Do people find kdb useful? (See * and **) Yes! Having a debugger on the main console is very handy, especially when a) it is a pain, when it's possible (*), to setup a serial console, and b) over ethernet, neither kgdb nor kdb is as reliable as kdb on tty0. I won't answer the other questions since I'm definitely a user, not a devel= oper of kernel debugger. (*) not everybody has IPMI 2 boards with serial over lan consoles. > 2) Would kdb folks be willing to use it if it was a front end to kgdb? > 3) Does kdb have a future in the mainline kernel? > 4) Is this a reasonable approach to have some level of > unification to end up with a more robust kernel debugger? >=20 > * This is not meant to be a religious war >=20 > ** This will never replace printk :-) >=20 > What follows is a series of patches to the development kernel which > enable kdb as a front end to kgdb for arm, mips, powerpc, and x86. > This is a very raw prototype, but enough of it it works such that > folks can try it out. >=20 > To get the most basic functionality, you only need the first 2 patches > in the series. The remainder of the patches go on to incrementally > add back some of the functionality that was removed from kdb. I made > an attempt to try to make the first part just the generic set of > changes required to get kdb working on 1 or more archs. Do you intend to support kdb modules? If yes, in which extent should they be adapted? Thanks, Louis >=20 > The kdb front end works a little differently than if you were to take > the original kdb patch set from: >=20 > ftp://oss.sgi.com/projects/kdb/download/v4.4/ >=20 > In the kernel .config you should enable the following options: >=20 > CONFIG_KGDB=3Dy > CONFIG_KGDB_SERIAL_CONSOLE=3Dy > CONFIG_KGDB_LOW_LEVEL_TRAP=3Dy > CONFIG_KGDB_KDB=3Dy > CONFIG_KGDB_KDB_PRIMARY=3Dy > CONFIG_KDB_KEYBOARD=3Dy > CONFIG_KDB_USB=3Dy >=20 > If you were using the serial port with kdb before, now you just use > the kgdboc mechanism with no differences at all. IE use you kernel > command line with: >=20 > console=3DttyS0,115200 kgdboc=3DttyS0 kgdbwait >=20 > That will get you access to kdb just after the console has been > registered. If you want to use the keyboard, you could use: >=20 > console=3Dtty0 kgdboc=3Dkdb kgdbwait >=20 > You can also use the keyboard and or serial console: >=20 > console=3DttyS0,115200 console=3Dtty0 kgdboc=3Dkdb,ttyS0 >=20 >=20 > In terms of breaking into the debugger after the system is up, you > must use the sysrq-g sequence. That means you could run: > echo g > /proc/sysrq-trigger >=20 > Or you can use the SysRq key on your key board. On a typical laptop > you might have to do the following: >=20 > press and hold ALT -- You will be holding this the whole time > press and hold FN > press and release the key with the SysRq label > release FN > press and release g > release ALT >=20 > I have also found on some PS/2 keyboards you have press alt again > after resuming the system because the key up event got lost somewhere. >=20 > Once you are in kdb you can run help to see a limited list of > commands. >=20 > You can also still connect gdb or re-enter kdb without leaving the > exception state. To get out of kgdb mode you can type "$3#33", or to > get into kgdb mode from kdb, you can type "kgdb". Also from gdb you > can issue commands to the kdb front end, via gdb's montior command. > For instance you could issue "monitor lsmod". Allowing the gdb > monitor extension was certainly another motivation behind the > prototype. >=20 > From here it is a matter of deciding if it is worth continuing down > this route. >=20 > The evaulation of this project will definitely cause some further > cleanup and improvement to kgdb, regardless of if this effort is > carried forward. Two of the patches in this series are patches likely > to get integrated into kgdb's code base and do not bear the "RFC ONLY" > indication. >=20 > Thanks, > Jason. >=20 > You can find the development branch for this here: >=20 > http://git.kernel.org/?p=3Dlinux/kernel/git/jwessel/linux-2.6-kgdb.git;a= =3Dshortlog;h=3Dkdb_prototype >=20 > or grab a static version of the patches here: >=20 > http://kernel.org/pub/linux/kernel/people/jwessel/branches/kdb_prototype.= tar.bz2 >=20 > short log info follows: >=20 > Jason Wessel (13): > RFC ONLY - kdb: core for kgdb backend > RFC ONLY - kgdb: core changes to support kdb > RFC ONLY - kgdb,8250,pl011: Return immediately from console poll > RFC ONLY - kgdb: gdb "monitor" -> kdb passthrough > RFC ONLY - kgdboc,keyboard: Keyboard driver for kdb with kgdb > kgdb: remove post_primary_code references > RFC ONLY - x86,kgdb: Add low level debug hook > RFC ONLY - arm,kgdb: Add hook to catch an oops with debugger > RFC ONLY - powerpc,kgdb: Introduce low level trap catching > RFC ONLY - mips,kgdb: kdb low level trap catch and stack trace > kgdb: Add the ability to schedule a breakpoint via a tasklet > RFC ONLY - kgdb,kdb: use async breakpoint for sysrq for usb > RFC ONLY - usb,keyboard: uchi, echi, and ochi polling keyboard urbs >=20 > Makefile | 1 + > arch/arm/include/asm/kgdb.h | 2 + > arch/arm/include/asm/kmap_types.h | 1 + > arch/arm/kernel/kgdb.c | 13 + > arch/arm/kernel/traps.c | 5 + > arch/mips/include/asm/kgdb.h | 2 + > arch/mips/include/asm/kmap_types.h | 3 +- > arch/mips/kernel/kgdb.c | 27 +- > arch/mips/kernel/traps.c | 14 + > arch/powerpc/include/asm/kmap_types.h | 1 + > arch/powerpc/kernel/kgdb.c | 12 +- > arch/powerpc/kernel/traps.c | 7 + > arch/x86/include/asm/kgdb.h | 3 + > arch/x86/include/asm/kmap_types.h | 3 +- > arch/x86/kernel/kgdb.c | 56 +- > arch/x86/kernel/traps.c | 6 + > drivers/char/Makefile | 1 + > drivers/char/kdb_keyboard.c | 407 ++++ > drivers/char/kdb_keyboard.h | 143 ++ > drivers/hid/usbhid/hid-core.c | 26 + > drivers/hid/usbhid/usbkbd.c | 13 + > drivers/serial/8250.c | 4 +- > drivers/serial/amba-pl011.c | 6 +- > drivers/serial/kgdboc.c | 80 +- > drivers/usb/core/hcd.c | 14 + > drivers/usb/core/hcd.h | 4 + > drivers/usb/host/ehci-hcd.c | 42 + > drivers/usb/host/ehci-pci.c | 6 + > drivers/usb/host/ehci-q.c | 225 ++ > drivers/usb/host/ohci-hcd.c | 66 + > drivers/usb/host/ohci-pci.c | 6 +- > drivers/usb/host/ohci-q.c | 63 + > drivers/usb/host/uhci-hcd.c | 36 + > drivers/usb/host/uhci-q.c | 51 + > fs/proc/meminfo.c | 145 ++ > fs/proc/mmu.c | 16 +- > include/linux/kdb.h | 172 ++ > include/linux/kdbprivate.h | 611 ++++++ > include/linux/keyboard.h | 2 + > include/linux/kgdb.h | 25 +- > include/linux/serial_core.h | 1 + > init/main.c | 26 + > kdb/.gitignore | 1 + > kdb/Makefile | 48 + > kdb/kdb_bp.c | 863 ++++++++ > kdb/kdb_bt.c | 209 ++ > kdb/kdb_cmds | 32 + > kdb/kdb_io.c | 895 ++++++++ > kdb/kdbmain.c | 3669 +++++++++++++++++++++++++++= ++++++ > kdb/kdbsupport.c | 1120 ++++++++++ > kernel/kallsyms.c | 22 + > kernel/kgdb.c | 321 +++- > kernel/module.c | 19 +- > kernel/panic.c | 6 + > kernel/printk.c | 14 + > kernel/sched.c | 93 +- > kernel/signal.c | 49 + > lib/Kconfig.kgdb | 37 + > mm/hugetlb.c | 22 + > mm/swapfile.c | 22 + > 60 files changed, 9697 insertions(+), 92 deletions(-) > create mode 100644 drivers/char/kdb_keyboard.c > create mode 100644 drivers/char/kdb_keyboard.h > create mode 100644 include/linux/kdb.h > create mode 100644 include/linux/kdbprivate.h > create mode 100644 kdb/.gitignore > create mode 100644 kdb/Makefile > create mode 100644 kdb/kdb_bp.c > create mode 100644 kdb/kdb_bt.c > create mode 100644 kdb/kdb_cmds > create mode 100644 kdb/kdb_io.c > create mode 100644 kdb/kdbmain.c > create mode 100644 kdb/kdbsupport.c > -- > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > Please read the FAQ at http://www.tux.org/lkml/ --=20 Dr Louis Rilling Kerlabs Skype: louis.rilling Batiment Germanium Phone: (+33|0) 6 80 89 08 23 80 avenue des Buttes de Coesmes http://www.kerlabs.com/ 35700 Rennes --=_bohort-8995-1242033324-0001-2 Content-Type: application/pgp-signature; name="signature.asc" Content-Transfer-Encoding: 7bit Content-Description: Digital signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iD8DBQFKB+y7VKcRuvQ9Q1QRAhjrAJ9s9CJAJbJiPi1Di9HByVI+XMFxDwCeLCp0 pKWl/SXBInzRidwzCVVydGk= =b1Me -----END PGP SIGNATURE----- --=_bohort-8995-1242033324-0001-2-- From BATV+4cd80222a6d8dd6c43b0+2087+infradead.org+hch@bombadil.srs.infradead.org Mon May 11 04:22:05 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=AWL,BAYES_00 autolearn=ham version=3.3.0-rupdated Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n4B9M20P242484 for ; Mon, 11 May 2009 04:22:05 -0500 X-ASG-Debug-ID: 1242033996-6d1700ba0000-sLlkUa X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi Received: from bombadil.infradead.org (localhost [127.0.0.1]) by cuda.sgi.com (Spam Firewall) with ESMTP id 862ABF823F3 for ; Mon, 11 May 2009 02:26:36 -0700 (PDT) Received: from bombadil.infradead.org (bombadil.infradead.org [18.85.46.34]) by cuda.sgi.com with ESMTP id 7AAqatpFcmjuRhEU for ; Mon, 11 May 2009 02:26:36 -0700 (PDT) X-ASG-Whitelist: Client Received: from hch by bombadil.infradead.org with local (Exim 4.69 #1 (Red Hat Linux)) id 1M3Ri0-0005zY-It; Mon, 11 May 2009 09:22:04 +0000 Date: Mon, 11 May 2009 05:22:04 -0400 From: Christoph Hellwig To: Jason Wessel Cc: linux-kernel@vger.kernel.org, kgdb-bugreport@lists.sourceforge.net, kdb@oss.sgi.com X-ASG-Orig-Subj: Re: [kdb] [PATCH 0/13] RFC ONLY - kdb for kgdb Subject: Re: [kdb] [PATCH 0/13] RFC ONLY - kdb for kgdb Message-ID: <20090511092204.GA19351@infradead.org> References: <1241817800-9320-1-git-send-email-jason.wessel@windriver.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1241817800-9320-1-git-send-email-jason.wessel@windriver.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org See http://www.infradead.org/rpr.html X-Barracuda-Connect: bombadil.infradead.org[18.85.46.34] X-Barracuda-Start-Time: 1242033997 X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean On Fri, May 08, 2009 at 04:23:07PM -0500, Jason Wessel wrote: > This patch series is a request for comments on several levels. > > 1) Do people find kdb useful? (See * and **) Yes. > 2) Would kdb folks be willing to use it if it was a front end to kgdb? Yes. > 3) Does kdb have a future in the mainline kernel? Well, if someone invest the effort to clean it up, cut it into small mergeable pieces and gets it done. > 4) Is this a reasonable approach to have some level of > unification to end up with a more robust kernel debugger? Sounds fine to me. > To get the most basic functionality, you only need the first 2 patches > in the series. The remainder of the patches go on to incrementally > add back some of the functionality that was removed from kdb. I made > an attempt to try to make the first part just the generic set of > changes required to get kdb working on 1 or more archs. Patch 1 still containes a lot random junk. E.g. all those meminfo and whatever hooks aren't required for a very basic kernel debugger. From BATV+4cd80222a6d8dd6c43b0+2087+infradead.org+hch@bombadil.srs.infradead.org Mon May 11 04:23:39 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=AWL,BAYES_00 autolearn=ham version=3.3.0-rupdated Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n4B9NcQc242583 for ; Mon, 11 May 2009 04:23:38 -0500 X-ASG-Debug-ID: 1242033824-085701360000-sLlkUa X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi Received: from bombadil.infradead.org (localhost [127.0.0.1]) by cuda.sgi.com (Spam Firewall) with ESMTP id D4FA41D22F67 for ; Mon, 11 May 2009 02:23:44 -0700 (PDT) Received: from bombadil.infradead.org (bombadil.infradead.org [18.85.46.34]) by cuda.sgi.com with ESMTP id GK07C2Q1Pp3NAbY0 for ; Mon, 11 May 2009 02:23:44 -0700 (PDT) X-ASG-Whitelist: Client Received: from hch by bombadil.infradead.org with local (Exim 4.69 #1 (Red Hat Linux)) id 1M3Rjb-0006BH-1G; Mon, 11 May 2009 09:23:43 +0000 Date: Mon, 11 May 2009 05:23:43 -0400 From: Christoph Hellwig To: Jason Wessel , linux-kernel@vger.kernel.org, kgdb-bugreport@lists.sourceforge.net, kdb@oss.sgi.com X-ASG-Orig-Subj: Re: [PATCH 0/13] RFC ONLY - kdb for kgdb Subject: Re: [PATCH 0/13] RFC ONLY - kdb for kgdb Message-ID: <20090511092342.GA23055@infradead.org> References: <1241817800-9320-1-git-send-email-jason.wessel@windriver.com> <20090511091539.GM25550@hawkmoon.kerlabs.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20090511091539.GM25550@hawkmoon.kerlabs.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org See http://www.infradead.org/rpr.html X-Barracuda-Connect: bombadil.infradead.org[18.85.46.34] X-Barracuda-Start-Time: 1242033824 X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean On Mon, May 11, 2009 at 11:15:39AM +0200, Louis Rilling wrote: > Do you intend to support kdb modules? If yes, in which extent should they be > adapted? I think that would be a very low priority. What would be useful is the hack to load debuginfo into kdb so that it can pretty-print arbitrary structures. That alone would replace about 90% of the kdb modules I think. And yes, that code in current kdb is even more ugly than core kdb, so it would need a major cleanup first. From Louis.Rilling@kerlabs.com Mon May 11 04:52:16 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-1.5 required=5.0 tests=AWL,BAYES_00,J_CHICKENPOX_57 autolearn=no version=3.3.0-rupdated Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n4B9qGnZ244457 for ; Mon, 11 May 2009 04:52:16 -0500 X-ASG-Debug-ID: 1242035516-5c3001210000-sLlkUa X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi Received: from bohort.kerlabs.com (localhost [127.0.0.1]) by cuda.sgi.com (Spam Firewall) with ESMTP id E6317277BAC for ; Mon, 11 May 2009 02:51:57 -0700 (PDT) Received: from bohort.kerlabs.com (bohort.kerlabs.com [62.160.40.57]) by cuda.sgi.com with ESMTP id hF5frQXZ3gmCSHqg for ; Mon, 11 May 2009 02:51:57 -0700 (PDT) Received: from hawkmoon.kerlabs.com (hawkmoon.kerlabs.com [::ffff:10.3.0.7]) (AUTH: LOGIN louis, SSL: TLSv1/SSLv3,128bits,AES128-SHA) by bohort.kerlabs.com with esmtp; Mon, 11 May 2009 11:51:39 +0200 id 000000000096808B.000000004A07F52B.000028A2 Date: Mon, 11 May 2009 11:51:54 +0200 From: Louis Rilling To: Christoph Hellwig Cc: Jason Wessel , linux-kernel@vger.kernel.org, kgdb-bugreport@lists.sourceforge.net, kdb@oss.sgi.com X-ASG-Orig-Subj: Re: [PATCH 0/13] RFC ONLY - kdb for kgdb Subject: Re: [PATCH 0/13] RFC ONLY - kdb for kgdb Message-ID: <20090511095154.GQ25550@hawkmoon.kerlabs.com> Reply-To: Louis.Rilling@kerlabs.com Mail-Followup-To: Christoph Hellwig , Jason Wessel , linux-kernel@vger.kernel.org, kgdb-bugreport@lists.sourceforge.net, kdb@oss.sgi.com References: <1241817800-9320-1-git-send-email-jason.wessel@windriver.com> <20090511091539.GM25550@hawkmoon.kerlabs.com> <20090511092342.GA23055@infradead.org> Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="=_bohort-10402-1242035499-0001-2" Content-Disposition: inline In-Reply-To: <20090511092342.GA23055@infradead.org> User-Agent: Mutt/1.5.17+20080114 (2008-01-14) X-Barracuda-Connect: bohort.kerlabs.com[62.160.40.57] X-Barracuda-Start-Time: 1242035517 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com X-Barracuda-Spam-Score: -2.02 X-Barracuda-Spam-Status: No, SCORE=-2.02 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.1.25489 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean This is a MIME-formatted message. If you see this text it means that your E-mail software does not support MIME-formatted messages. --=_bohort-10402-1242035499-0001-2 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On 11/05/09 5:23 -0400, Christoph Hellwig wrote: > On Mon, May 11, 2009 at 11:15:39AM +0200, Louis Rilling wrote: > > Do you intend to support kdb modules? If yes, in which extent should th= ey be > > adapted? >=20 > I think that would be a very low priority. What would be useful is the > hack to load debuginfo into kdb so that it can pretty-print arbitrary > structures. That alone would replace about 90% of the kdb modules I > think. >=20 > And yes, that code in current kdb is even more ugly than core kdb, so > it would need a major cleanup first. I was thinking about custom KDB modules, but I agree that most of them coul= d be replaced by pretty-print of arbitrary structures. Thanks, Louis --=20 Dr Louis Rilling Kerlabs Skype: louis.rilling Batiment Germanium Phone: (+33|0) 6 80 89 08 23 80 avenue des Buttes de Coesmes http://www.kerlabs.com/ 35700 Rennes --=_bohort-10402-1242035499-0001-2 Content-Type: application/pgp-signature; name="signature.asc" Content-Transfer-Encoding: 7bit Content-Description: Digital signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iD8DBQFKB/U6VKcRuvQ9Q1QRAtk2AKCPcnxS8OKwDKJetZurAhPF6Qf8zACfXyIp RzR+q0YDW6WycbK4NZZcZUo= =Ddqb -----END PGP SIGNATURE----- --=_bohort-10402-1242035499-0001-2-- From mort@sgi.com Mon May 11 07:57:00 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-2.5 required=5.0 tests=AWL,BAYES_00 autolearn=ham version=3.3.0-rupdated Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n4BCv0Nh255027 for ; Mon, 11 May 2009 07:57:00 -0500 Received: from attica.americas.sgi.com (attica.americas.sgi.com [128.162.236.44]) by relay3.corp.sgi.com (Postfix) with ESMTP id 3E04BAC002; Mon, 11 May 2009 05:57:02 -0700 (PDT) Received: by attica.americas.sgi.com (Postfix, from userid 44682) id 6CBC3A0BB90D; Mon, 11 May 2009 07:57:02 -0500 (CDT) Date: Mon, 11 May 2009 07:57:02 -0500 From: Martin Hicks To: Jason Wessel Cc: Christoph Hellwig , linux-kernel@vger.kernel.org, kgdb-bugreport@lists.sourceforge.net, kdb@oss.sgi.com Subject: Re: [kdb] [PATCH 0/13] RFC ONLY - kdb for kgdb Message-ID: <20090511125702.GL14353@alcatraz.americas.sgi.com> References: <1241817800-9320-1-git-send-email-jason.wessel@windriver.com> <20090511092204.GA19351@infradead.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20090511092204.GA19351@infradead.org> User-Agent: Mutt/1.5.17 (2007-11-01) X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean On Mon, May 11, 2009 at 05:22:04AM -0400, Christoph Hellwig wrote: > On Fri, May 08, 2009 at 04:23:07PM -0500, Jason Wessel wrote: > > This patch series is a request for comments on several levels. > > > > > 2) Would kdb folks be willing to use it if it was a front end to kgdb? > > Yes. absolutely. > > 3) Does kdb have a future in the mainline kernel? > > Well, if someone invest the effort to clean it up, cut it into small > mergeable pieces and gets it done. I'll play with these patches later today, Jason. Thanks for getting this patchset out. mh From myhostweb@myjaring.net Tue May 12 20:03:07 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: *** X-Spam-Status: No, score=3.1 required=5.0 tests=BAYES_50,HTML_FONT_SIZE_HUGE, HTML_MESSAGE autolearn=no version=3.3.0-rupdated Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n4D1366k105990 for ; Tue, 12 May 2009 20:03:07 -0500 X-ASG-Debug-ID: 1242176589-530b00e00000-sLlkUa X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi Received: from vsmtp6.jaring.my (localhost [127.0.0.1]) by cuda.sgi.com (Spam Firewall) with ESMTP id C61881D11963 for ; Tue, 12 May 2009 18:03:09 -0700 (PDT) Received: from vsmtp6.jaring.my (vsmtp6.jaring.my [192.228.250.86]) by cuda.sgi.com with ESMTP id kHXqtd3uudljwHE1 for ; Tue, 12 May 2009 18:03:09 -0700 (PDT) Received: from localhost (localhost.jaring.my [127.0.0.1]) by vsmtp6.jaring.my (8.14.3/8.14.3) with ESMTP id n4D0wsoJ014782; Wed, 13 May 2009 08:58:54 +0800 (MYT) (envelope-from myhostweb@myjaring.net) X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Scanned: by JARING Malware Filters (jaring.my) Received: from vsmtp6.jaring.my ([127.0.0.1]) by localhost (vsmtp6.jaring.my [127.0.0.1]) (amavisd-new, port 10024) with LMTP id 9iV4cRkzci69; Wed, 13 May 2009 08:58:53 +0800 (MYT) Received: from Director (j464.bkj71.jaring.my [61.6.177.238]) by vsmtp6.jaring.my (8.14.3/8.14.3) with ESMTP id n4D0u0Zm013838; Wed, 13 May 2009 08:56:01 +0800 (MYT) (envelope-from myhostweb@myjaring.net) Message-Id: <200905130056.n4D0u0Zm013838@vsmtp6.jaring.my> From: "Sean Wong" Reply-To: sales@channel2.com.my X-ASG-Orig-Subj: 2009 New Web Design from only RM750 Subject: 2009 New Web Design from only RM750 To: users09@asianrefer.org Date: Wed, 13 May 2009 08:55:57 +0800 X-Mailer: diffondi V4,0,4,0 (W95/NT) (Build: Aug 26 2001) Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_007F_01BDF6C7.FABAC1B0" Content-Transfer-Encoding: 7bit X-Barracuda-Connect: vsmtp6.jaring.my[192.228.250.86] X-Barracuda-Start-Time: 1242176592 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0208 1.0000 -1.8857 X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com X-Barracuda-Spam-Score: -1.50 X-Barracuda-Spam-Status: No, SCORE=-1.50 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests=HTML_FONT_SIZE_HUGE, HTML_MESSAGE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.1.25628 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 HTML_MESSAGE BODY: HTML included in message 0.39 HTML_FONT_SIZE_HUGE BODY: HTML font size is huge X-Virus-Status: Clean This is a MIME Message ------=_NextPart_000_007F_01BDF6C7.FABAC1B0 Content-Type: multipart/alternative; boundary="----=_NextPart_001_0080_01BDF6C7.FABAC1B0" ------=_NextPart_001_0080_01BDF6C7.FABAC1B0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Greetings! Now you may have a new web design for only RM750 while a full web package for only RM880 including domain name, web/email hosting, plus 4-pages web design! We also provide web page updates and maintenance at reasonable rate=2E You may also order or renew your web/email hosting = at only RM200/year (unlimited email accounts): Domain Name =2Ecom RM50 =2Ecom=2Emy RM100 Web Hosting Unlimited Emails 1Gig RM200 Web Design 4 Pages RM750 10 Pages RM1490 WebChois 4 Pages + Domain + Hosting =3D RM880 Your web pages will be customized to your corporate image and marketing strategy=2E You'll be amazed how easy and affordable to have your fresh website online now! Feel free to contact me for more information=2E Thanks!   Regards, Sean WongMarketing Executive Tel: 03-58822355, 58821580 Details check: http://www=2Echannel2=2Ecom=2Emy To unsubscribe pls reply: nolist@channel2=2Ecom=2Emy R R R R R ------=_NextPart_001_0080_01BDF6C7.FABAC1B0 Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Greetings!

Now you may have a new w= eb design for only RM750 while a full web package for only RM880 including domain = name, web/email hosting, plus 4-pages web design!

We also provide web page updates and maintenanc= e at reasonable rate=2E You may also order or renew your web/email= hosting at only RM200/year (unlimited email accounts)
:


Domain = Name
=2Ecom RM50
=2Ecom=2Emy RM100
Web Hosting
Unlimited Emails
1Gig RM200
<= /div>

Web Design
4 Pages RM750
10 Pages RM1490

WebChois
4 Pages + Domain
+ Hosting =3D RM880


Your web pages will be customized to your corporate image and marketing st= rategy=2E You'll be amazed how easy and affordable to have your fresh website online now!

Feel free to contact me = for more information=2E Thanks!
 

Regards,

= Sean Wong
Marketing Execu= tive

Tel: 03-58822355, 58821580


Details check: http://www=2Echannel2=2Ecom=2Emy
=

To unsubscribe pls = reply:
nolist@channel2=2Ecom=2Emy

R R R R R
------=_NextPart_001_0080_01BDF6C7.FABAC1B0-- ------=_NextPart_000_007F_01BDF6C7.FABAC1B0 Content-Type: application/octet-stream; name="new_web_design.jpg" Content-Transfer-Encoding: base64 Content-Description: new_web_design.jpg Content-ID: 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 ------=_NextPart_000_007F_01BDF6C7.FABAC1B0-- From 565-177-kdb=oss.sgi.com@srp-chocolat.com Wed May 20 03:06:27 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: **** X-Spam-Status: No, score=4.7 required=5.0 tests=BAYES_50,HTML_FONT_SIZE_LARGE, HTML_MESSAGE,MIME_8BIT_HEADER,MIME_QP_LONG_LINE autolearn=no version=3.3.0-rupdated Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n4K86Qpe096941 for ; Wed, 20 May 2009 03:06:27 -0500 X-ASG-Debug-ID: 1242806791-4cdf00ad0000-sLlkUa X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi Received: from mta0.srp-chocolat.com (localhost [127.0.0.1]) by cuda.sgi.com (Spam Firewall) with ESMTP id D605A19EF227 for ; Wed, 20 May 2009 01:06:31 -0700 (PDT) Received: from mta0.srp-chocolat.com (mta0.srp-chocolat.com [62.193.226.15]) by cuda.sgi.com with ESMTP id YpXGZ793O1O3OV1I for ; Wed, 20 May 2009 01:06:31 -0700 (PDT) Received: by mta0.srp-chocolat.com (PowerMTA(TM) v3.5r8) id h2etqk0kg785 for ; Wed, 20 May 2009 10:13:20 +0200 (envelope-from <565-177-kdb=oss.sgi.com@srp-chocolat.com>) From: =?iso-8859-1?Q?Philippe_-_Lochness_Production?= To: "=?iso-8859-1?Q?kdb@oss.sgi.com?=" Reply-To: =?iso-8859-1?Q?Philippe_-_Lochness_Production?= X-ASG-Orig-Subj: =?iso-8859-1?Q?Cocons_-_Spectacle_de_cirque_a=E9rien_-_Aerial_Pyrotechnic_Circus?= Subject: =?iso-8859-1?Q?Cocons_-_Spectacle_de_cirque_a=E9rien_-_Aerial_Pyrotechnic_Circus?= Date: Wed, 20 May 2009 09:34:31 +0200 Mime-Version: 1.0 Organization: =?iso-8859-1?Q?Lochness_Production?= list-unsubscribe: Content-Type: multipart/related; boundary="----=_Part_095_0725482484.1242804871428" Message-Id: <565-177-0000013820@srp-chocolat.com> X-Barracuda-Connect: mta0.srp-chocolat.com[62.193.226.15] X-Barracuda-Start-Time: 1242806795 X-Barracuda-Bayes: INNOCENT GLOBAL 0.6548 1.0000 1.0521 X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com X-Barracuda-Spam-Score: 1.87 X-Barracuda-Spam-Status: No, SCORE=1.87 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests=HTML_FONT_SIZE_LARGE, HTML_MESSAGE, MIME_QP_LONG_LINE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.1.26252 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 HTML_MESSAGE BODY: HTML included in message 0.00 HTML_FONT_SIZE_LARGE BODY: HTML font size is large 0.82 MIME_QP_LONG_LINE RAW: Quoted-printable line longer than 76 chars X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean ------=_Part_095_0725482484.1242804871428 Content-Type: multipart/alternative; boundary="----=_Part_349_2910481946.1242804871446" ------=_Part_349_2910481946.1242804871446 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Cocons, spectacle de cirque a=E9rien Aerial circus with high stunt-flying and pyrotechnic 2 versions : en salle ou en plein air Compagnie des Tr=E9teaux du Coeur Volant Contact tourn=E9e : Lochness Production - +33 (0) 1 48 58 13 21 - +33 (0) 6 = 85 10 28 55 - lochness@inbox.as ----------------------------------------------------------------------------= ---- Un concept original : le camion funambule D=E9ploy=E9 sur 20 m de long et 12 m de haut, le Camion Funambule se r=E9vei= lle. La lumi=E8re et les effets sp=E9ciaux (vid=E9o, pyrotechnie, embrasements) v= iennent couronner cette alchimie o=F9 la part la plus belle sera donn=E9e au= r=EAve et au merveilleux. Le spectacle =AB Cocons =BB : La r=E9alit=E9 n'est-elle que le miroir de notre imaginaire ? Et si la machine =E9tait capable de donner la vie=85 D'=E9tranges Cocons naissent de la ferraille, se d=E9forment, se d=E9gonflen= t, se d=E9chirent pour faire exister de fragiles cr=E9atures. Des =EAtres =E9= tranges viennent habiter l=92espace : funambules et voltigeurs s=92=E9lancen= t vers leur libert=E9. La compagnie : Cr=E9=E9e en 1985 par Pascualito, la compagnie a h=E9rit=E9 de tous les "tra= vers" de son fondateur : gourmandise, provocation, go=FBt immod=E9r=E9 pour = la ferraille et d=E9bordements baroques. ----------------------------------------------------------------------------= ---- Copiez les liens suivants dans votre navigateur : Pr=E9sentation : http://www.lochnessprod.com/presentationcocon.htm Extrait vid=E9o : http://www.lochnessprod.com/flvplayercocon.php Photos : http://www.lochnessprod.com/photococon.htm R=E9f=E9rences : http://www.lochnessprod.com/Refcocon.htm Presse : http://www.lochnessprod.com/pressecocon.htm ----------------------------------------------------------------------------= ---- Prix : sur simple demande en remplissant le formulaire ci-dessous ----------------------------------------------------------------------------= ---- Formulaire a compl=E9ter pour toute demande de devis : Pour pouvoir remplir le formulaire, faites r=E9pondre au message ou copier /= coller le formulaire Cocons - - Devis Pr=E9nom + Nom : Fonction : Etablissement : Type d'=E9tablissement (Mairie, CE, Salle de spectacle, Entreprise...) : Adresse : Code postal + Ville : Pays : Ligne standard : Ligne directe : Portable : Fax : Email : Site internet : Salle ou ext=E9rieur ? : Nom du lieu de repr=E9sentation : Code postal + Ville du lieu de repr=E9sentation : Nombre de personnes : Configuration assise ou debout ? : Payant ou gratuit ? : Quelles dates envisagez-vous pour une =E9ventuelle programmation : Jour - Mois - Ann=E9e ? : Les dates que vous nous indiquez ne vous engagent nullement mais nous permet= tent de v=E9rifier la faisabilit=E9 sur le planning de tourn=E9e ----------------------------------------------------------------------------= ---- Pour vous assurer de recevoir nos mails, inscrivez dans votre carnet d'adres= ses nos emails : lochness.emailing@free.fr - lochness@inbox.as ----------------------------------------------------------------------------= ---- Lochness Production 83 rue Michel Ange - 75016 Paris tel : 01 48 58 13 21 - fax : 01 48 58 97 12 - devis.email@free.fr ----------------------------------------------------------------------------= ---- Si vous ne souhaitez plus recevoir d=92emails sur ce spectacle, envoyez-nous= un mail a devis.email@free.fr en pr=E9cisant bien "D=E9sabonnement" dans l'= objet du message ------=_Part_349_2910481946.1242804871446 Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: Quoted-Printable </T= ITLE> <META name=3DGENERATOR content=3D"MSHTML 8.00.6001.18702"></HEAD> <BODY> <DIV><FONT size=3D2 face=3DArial> <DIV><FONT size=3D2 face=3DArial> <TABLE border=3D0 cellSpacing=3D0 cellPadding=3D40 width=3D"100%" bgColor=3D= #346d2c> <TBODY> <TR> <TD> <DIV align=3Dcenter> <CENTER> <TABLE border=3D4 cellSpacing=3D0 borderColor=3D#003818 cellPadding=3D= 0 width=3D750 bgColor=3D#a8d868> <TBODY> <TR> <TD vAlign=3Dtop width=3D"100%"> <DIV align=3Dcenter> <TABLE style=3D"WIDTH: 311px; HEIGHT: 35px" border=3D0 cellSpaci= ng=3D0 cellPadding=3D5> <TBODY> <TR> <TD bgColor=3D#003818><FONT color=3D#ffffff face=3DNasalizat= ion> <P align=3Dcenter><FONT face=3D"Arial, Helvetica, sans-serif"><STRONG>A l'att= ention du responsable<BR> de la programmation des spectacles</STRONG></FONT></P></FONT></TD></TR></TBODY></T= ABLE></DIV> <DIV align=3Dcenter> </DIV> <CENTER> <TABLE border=3D0 cellSpacing=3D0 cellPadding=3D30 width=3D628 height=3D1376><TBODY> <TR> <TD vAlign=3Dcenter><FONT size=3D6 face=3D"Arial Black"> <P align=3Dcenter><FONT size=3D4 face=3DArial><STRONG><FON= T size=3D5>"Cocons"</FONT><BR></STRONG></FONT><FONT size=3D4= face=3DArial><STRONG>Spectacle de cirque a=E9rien sur le c= amion funambule<BR><BR>2 versions : en salle ou en plein air<BR><BR></STRONG></FONT><STRONG><FONT size=3D4 face=3DArial>Aerial circus with high stunt-flying and pyrotechnic</FONT></STRONG></P> <P align=3Dcenter><FONT size=3D2><FONT face=3DArial><A hre= f=3D"http://www.lochnessprod.com/desabonnement1.php?3&565-186&0&sLlkUa5BKqbSrSWAhgChqA"><= IMG border=3D"1" hspace=3D"0" alt=3D"Pour afficher le visuel, autoriser le t= =E9l=E9chargement des images dans votre navigateur" src=3D"cid:B8E7C2B456623= 520D99708157E3BE588@Emailing6"></A><BR></FONT></FONT><FONT size=3D2><FONT size=3D2><FONT size=3D2><FONT face=3DArial>= <A href=3D"http://www.lochnessprod.com/desabonnement1.php?3&565-186&0&= sLlkUa5BKqbSrSWAhgChqA"><IMG border=3D"1" hspace=3D"0" alt=3D"Pour afficher le visuel, autorise= r le t=E9l=E9chargement des images dans votre navigateur" src=3D"cid:758EFCD= AD96D5FC81402DB20D9135D7E@Emailing6"></A></FONT></FONT></FONT></FONT></P> <P align=3Dcenter><FONT size=3D2><FONT size=3D2><FONT size= =3D2><FONT face=3DArial>  Pour visionner la vid=E9o, cliquez sur   : </FONT><FONT size=3D3><A href=3D"ht= tp://www.lochnessprod.com/desabonnement1.php?3&565-186&0&sLlkUa5BKqbSrSWAhgChqA"><STRONG>= <FONT face=3DArial>Vid=E9o</FONT></STRONG></A><BR></FONT></FONT>= </FONT></FONT><FONT size=3D2><FONT size=3D2><FONT size=3D2><FONT size=3D3><FON= T size=3D2><FONT face=3DArial>Pour visionner les photos, cli= quez sur   : <FONT size=3D3><A href=3D"http://ww= w.lochnessprod.com/desabonnement1.php?3&565-186&1&sLlkUa5BKqbSrSWAhgChqA"><STRONG>Photos<= /STRONG></A></FONT><BR>   Pour visionner les r=E9f=E9rences, cliquez sur  =  : <FONT size=3D3><A href=3D"http://www.lochnessprod.com/desa= bonnement1.php?3&565-186&2&sLlkUa5BKqbSrSWAhgChqA"><STRONG>R=E9f=E9rences</STRONG></A><BR= ><FONT size=3D2>Pour visionner les articles de presse, cliquez sur   : </FONT><A href=3D"http://www.lochne= ssprod.com/desabonnement1.php?3&565-186&3&sLlkUa5BKqbSrSWAhgChqA"><STRONG><FONT size=3D3>Presse</STRONG></A>     =              </FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></= P><FONT size=3D2><FONT size=3D2><FONT size=3D2><FONT size=3D3><FON= T size=3D2><FONT face=3DArial><SPAN style=3D"LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-ser= if'; FONT-SIZE: 10pt"><o:p> <P style=3D"TEXT-ALIGN: justify; MARGIN: 0cm 0cm 0pt" class=3DMsoNormal><SPAN style=3D"LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-ser= if'; FONT-SIZE: 10pt"></SPAN> </P> <P style=3D"TEXT-ALIGN: justify; MARGIN: 0cm 0cm 0pt" class=3DMsoNormal><SPAN style=3D"LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-ser= if'; FONT-SIZE: 10pt"><SPAN style=3D"LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-ser= if'; BACKGROUND: yellow; FONT-SIZE: 10pt; mso-highlight: yellow"><STRONG>&nb= sp;Un concept original : le camion funambule </STRONG></SPAN></P> <P style=3D"TEXT-ALIGN: justify; MARGIN: 0cm 0cm 0pt" class=3DMsoNormal><SPAN style=3D"LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-ser= if'; FONT-SIZE: 10pt">D=E9ploy=E9 sur 20 m de long et 12 m de haut, le Camion Funambule se r=E9veille. </SPAN></P> <P style=3D"TEXT-ALIGN: justify; MARGIN: 0cm 0cm 0pt" class=3DMsoNormal><SPAN style=3D"LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-ser= if'; FONT-SIZE: 10pt">La lumi=E8re et les effets sp=E9ciaux (vid=E9o, pyrotechnie, = embrasements) viennent couronner cette alchimie o=F9 la pa= rt la plus belle sera donn=E9e au r=EAve et au merveilleux.</SPA= N></P> <P style=3D"TEXT-ALIGN: justify; MARGIN: 0cm 0cm 0pt" class=3DMsoNormal><SPAN style=3D"LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-ser= if'; FONT-SIZE: 10pt"></SPAN></SPAN> </o:p></SPAN></P> <P style=3D"TEXT-ALIGN: justify; MARGIN: 0cm 0cm 0pt" class=3DMsoNormal><SPAN><STRONG><FONT style=3D"BACKGROUND-COLOR: #ffff00"> Le spectacle =AB Cocons =BB : <o:p></o:p></FONT></STRONG></SPAN></P> <P style=3D"TEXT-ALIGN: justify; MARGIN: 0cm 0cm 0pt" class=3DMsoNormal><SPAN style=3D"LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-ser= if'; FONT-SIZE: 10pt">La r=E9alit=E9 n'est-elle que le miroir de notre imaginaire ?= <o:p></o:p></SPAN></P> <P style=3D"TEXT-ALIGN: justify; MARGIN: 0cm 0cm 0pt" class=3DMsoNormal><SPAN style=3D"LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-ser= if'; FONT-SIZE: 10pt">Et si la machine =E9tait capable de donner la vie=85 <o:p></o:p></SPAN></P> <P style=3D"TEXT-ALIGN: justify; MARGIN: 0cm 0cm 0pt" class=3DMsoNormal><SPAN style=3D"LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-ser= if'; FONT-SIZE: 10pt">D'=E9tranges <STRONG>Cocons</STRONG> naissent de la ferraille, se d=E9forment, se d=E9gonflent, se d=E9chirent pour faire ex= ister de fragiles cr=E9atures. Des =EAtres =E9tranges viennent habi= ter l=92espace : funambules et voltigeurs s=92=E9lancent = vers leur libert=E9.</SPAN></P><SPAN style=3D"LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-ser= if'; FONT-SIZE: 10pt"> <P style=3D"TEXT-ALIGN: justify; MARGIN: 0cm 0cm 0pt" class=3DMsoNormal> </P> <P style=3D"TEXT-ALIGN: justify; MARGIN: 0cm 0cm 0pt" class=3DMsoNormal><SPAN style=3D"LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-ser= if'; BACKGROUND: yellow; FONT-SIZE: 10pt; mso-highlight: yellow"><STRONG>&nb= sp;La compagnie : <o:p></o:p></STRONG></SPAN></P> <P style=3D"TEXT-ALIGN: justify; MARGIN: 0cm 0cm 0pt" class=3DMsoNormal><SPAN style=3D"LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-ser= if'; FONT-SIZE: 10pt">Cr=E9=E9e en 1985 par Pascualito, la compagnie a h=E9rit=E9 de tous = les "travers" de son fondateur : gourmandise, provocation, go=FB= t immod=E9r=E9 pour la ferraille et d=E9bordements baroques.<o:p></o:p></SPAN></P><o:p></o:p></SPAN> <P align=3Dcenter><STRONG>Pour vous assurer de recevoir no= s emails,<BR>inscrivez nos emails dans votre carnet d'adress= es :<BR></STRONG></FONT><A href=3D"http://www.lochnessprod.co= m/desabonnement1.php?3&565-186&4&sLlkUa5BKqbSrSWAhgChqA"><FONT face=3DArial><STRONG>lochness.emailing@free.fr</STRONG></F= ONT></A><FONT face=3DArial> <STRONG>- </STRONG></FONT><A href=3D"ht= tp://www.lochnessprod.com/desabonnement1.php?3&565-186&5&sLlkUa5BKqbSrSWAhgChqA"><STRONG>= <FONT face=3DArial>lochness@inbox.as</FONT></STRONG></A></FONT><= /FONT></FONT></FONT></FONT></P></FONT></TD></TR></TBODY></TABLE></CENTER></T= D></TR> <TR> <TD bgColor=3D#ffffff width=3D"100%">  <DIV align=3Dcenter> <TABLE style=3D"WIDTH: 624px; HEIGHT: 65px" border=3D0 cellSpaci= ng=3D0 cellPadding=3D10 width=3D624> <TBODY> <TR> <TD vAlign=3Dtop width=3D"100%"><FONT size=3D2><SPAN><SPAN style=3D"TEXT-DECORATION: none"><SPAN style=3D"FONT-FAMILY: Arial; FONT-SIZE: 10pt"><SPAN style=3D"FONT-FAMILY: Arial; FONT-SIZE: 10pt"><SPAN style=3D"FONT-FAMILY: Arial; COLOR: black; FONT-SIZE: 10pt= "><SPAN style=3D"FONT-FAMILY: Arial; COLOR: black; FONT-SIZE: 10pt= "><SPAN><FONT style=3D"BACKGROUND-COLOR: #ffffff"><SPAN><SPAN style=3D"TEXT-DECORATION: none"><SPAN style=3D"FONT-FAMILY: Arial; FONT-SIZE: 10pt"><SPAN style=3D"FONT-FAMILY: Arial; FONT-SIZE: 10pt"><SPAN style=3D"FONT-FAMILY: Arial; COLOR: black; FONT-SIZE: 10pt= "><SPAN style=3D"FONT-FAMILY: Arial; COLOR: black; FONT-SIZE: 10pt= "><SPAN style=3D"FONT-FAMILY: Arial; FONT-SIZE: 10pt"> <P style=3D"MARGIN: 0cm 0cm 0pt" class=3DMsoNormal><STRONG= ><FONT style=3D"BACKGROUND-COLOR: #ffff00"> Deux formules disponibles :</FONT></STRONG></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN= ></SPAN></P><STRONG> <P style=3D"LINE-HEIGHT: normal; MARGIN: 0cm 0cm 0pt 7.1pt; m= so-add-space: auto" class=3DMsoListParagraphCxSpFirst><B><SPAN style=3D"FONT-FAMILY: 'Arial','sans-serif'; COLOR: black; = FONT-SIZE: 10pt; mso-fareast-font-family: 'Times New Roman'; mso-fareast-lan= guage: FR">- En salle (th=E9=E2tre, centre culturel, =E9v=E9nementiel=85)</SPAN></B><B style=3D"mso-bidi-font-weight: normal"><SPAN style=3D"FONT-FAMILY: 'Arial','sans-serif'; COLOR: red; FO= NT-SIZE: 10pt"><o:p></o:p></SPAN></B></P> <P style=3D"LINE-HEIGHT: normal; MARGIN: 0cm 0cm 0pt 7.1pt; m= so-add-space: auto" class=3DMsoListParagraphCxSpLast><B><SPAN style=3D"FONT-FAMILY: 'Arial','sans-serif'; COLOR: black; = FONT-SIZE: 10pt; mso-fareast-font-family: 'Times New Roman'; mso-fareast-lan= guage: FR">- En plein air (jusqu=92=E0 </SPAN></B><B style=3D"mso-bidi-font-weight: normal"><SPAN style=3D"FONT-FAMILY: 'Arial','sans-serif'; BACKGROUND: wh= ite; COLOR: black; FONT-SIZE: 10pt; mso-fareast-font-family: 'Times New Roma= n'; mso-fareast-language: FR">8 000 personnes) sur le camion funambule</SPAN></B><B style=3D"mso-bidi-font-weight: normal"><SPAN style=3D"FONT-FAMILY: 'Arial','sans-serif'; COLOR: red; FO= NT-SIZE: 10pt"><o:p></o:p></SPAN></B></P> <P style=3D"MARGIN: 0cm 0cm 0pt" class=3DMsoNormal></STRONG> </P> <P style=3D"MARGIN: 0cm 0cm 0pt" class=3DMsoNormal><STRONG= >Prix </STRONG>: </FONT><FONT style=3D"BACKGROUND-COLOR: #ffff00"><STRONG>sur simple dem= ande en remplissant le formulaire ci-dessous</STRONG></FONT></S= PAN> <BR></P> <HR id=3D0> <P></P> <P><SPAN><FONT style=3D"BACKGROUND-COLOR: #ffffff"><U><STRONG><FONT size=3D3><FONT style=3D"BACKGROUND-COLOR: #ffff00">Formulaire =E0 co= mpl=E9ter pour toute demande de devis :</FONT><BR></FONT></STRONG></U><SPAN style=3D"FONT-FAMILY: Arial; COLOR: red; FONT-SIZE: 10pt">= <SPAN style=3D"FONT-FAMILY: Arial; COLOR: black; FONT-SIZE: 10pt= "><SPAN style=3D"FONT-FAMILY: Arial; COLOR: black; FONT-SIZE: 10pt= ">Pour pouvoir remplir le formulaire, faites r=E9pondre au messag= e ou copier / coller le formulaire</SPAN></SPAN></SPAN></FONT></SPAN></P> <P><SPAN><FONT style=3D"BACKGROUND-COLOR: #ffffff"><SPAN style=3D"FONT-FAMILY: Arial; COLOR: red; FONT-SIZE: 10pt">= <SPAN style=3D"FONT-FAMILY: Arial; COLOR: black; FONT-SIZE: 10pt= "><SPAN style=3D"FONT-FAMILY: Arial; COLOR: black; FONT-SIZE: 10pt= ">Cocons -  - Devis - kdb@oss.sgi.com <BR></SPAN></SPAN></SPAN>Pr=E9nom = ;et Nom : <BR></FONT></SPAN><SPAN style=3D"FONT-FAMILY: Arial; COLOR: black; FONT-SIZE: 10pt= "><FONT style=3D"BACKGROUND-COLOR: #ffffff">Fonction :<BR>Etabliss= ement : <BR></FONT></SPAN><SPAN style=3D"FONT-FAMILY: Arial; COLOR: black; FONT-SIZE: 10pt= "><FONT style=3D"BACKGROUND-COLOR: #ffffff">Type d'=E9tablissement= (Mairie, CE, Salle de spectacle, Entreprise...) : <BR>Adre= sse : <BR>C</FONT></SPAN><SPAN style=3D"FONT-FAMILY: Arial; COLOR: black; FONT-SIZE: 10pt= "><FONT style=3D"BACKGROUND-COLOR: #ffffff">ode postal + Ville : <BR></FONT></SPAN><SPAN style=3D"FONT-FAMILY: Arial; COLOR: black; FONT-SIZE: 10pt= "><FONT style=3D"BACKGROUND-COLOR: #ffffff">Pays :<BR></FONT></SPAN><SPAN style=3D"FONT-FAMILY: Arial; COLOR: black; FONT-SIZE: 10pt= "><FONT style=3D"BACKGROUND-COLOR: #ffffff">Ligne standard :<BR>Li= gne directe :<BR></FONT></SPAN><SPAN style=3D"FONT-FAMILY: Arial; COLOR: black; FONT-SIZE: 10pt= "><FONT style=3D"BACKGROUND-COLOR: #ffffff">Portable : <BR></FONT></SPAN><SPAN style=3D"FONT-FAMILY: Arial; COLOR: black; FONT-SIZE: 10pt= "><FONT style=3D"BACKGROUND-COLOR: #ffffff">Fax : <BR></FONT></SPAN><SPAN style=3D"FONT-FAMILY: Arial; COLOR: black; FONT-SIZE: 10pt= "><FONT style=3D"BACKGROUND-COLOR: #ffffff">Email :</FONT><SPAN style=3D"mso-tab-count: 1"><FONT style=3D"BACKGROUND-COLOR: #ffffff"> <BR>Site internet :  <BR></FONT></SPAN></SPAN><STRONG><SP= AN style=3D"FONT-FAMILY: Arial; COLOR: red; FONT-SIZE: 10pt">= <FONT style=3D"BACKGROUND-COLOR: #ffffff">Salle ou ext=E9rieur&n= bsp;? : <BR></FONT></SPAN></STRONG><SPAN style=3D"FONT-FAMILY: Arial; COLOR: black; FONT-SIZE: 10pt= "><FONT style=3D"BACKGROUND-COLOR: #ffffff">Nom du lieu de repr=E9sentation : <BR>Code postal + Ville du lieu de= repr=E9sentation : <BR></FONT></SPAN><STRONG><SPAN style=3D"FONT-FAMILY: Arial; COLOR: red; FONT-SIZE: 10pt">= <FONT style=3D"BACKGROUND-COLOR: #ffffff">Nombre de personnes ?&= nbsp;: <BR></FONT></SPAN></STRONG><SPAN style=3D"FONT-FAMILY: Arial; COLOR: red; FONT-SIZE: 10pt">= <STRONG><FONT style=3D"BACKGROUND-COLOR: #ffffff">Configuration assise o= u debout ? : <BR></FONT></STRONG></SPAN><FONT style=3D"BACKGROUND-COLOR: #ffffff"><SPAN style=3D"FONT-FAMILY: Arial; COLOR: red; FONT-SIZE: 10pt">= <STRONG>Payant ou gratuit ? :<BR><BR>Quelles sont les dates que vous= envisagez pour une =E9ventuelle programmation :<BR>Jour - Mois - Ann=E9e ? :<BR><BR>L= es dates que vous nous proposez ne vous engagent nulleme= nt mais nous permettent  de v=E9rifier la faisabili= t=E9 de votre projet sur le planning de tourn=E9e.</STRONG></SPAN></FONT></P> <HR> <P align=3Dcenter><STRONG><FONT style=3D"BACKGROUND-COLOR: #ffffff"><FONT style=3D"BACKGROUND-COLOR: #ffffff"><STRONG>Lochness Production</STRONG></FONT><BR>83 rue Michel Ange - 75016 Paris<BR></FONT></STRONG><STRONG><FONT style=3D"BACKGROUND-COLOR: #ffffff">tel : 01 48 58 13 21 -= fax : 01 48 58 97 12<BR></FONT></STRONG> <HR id=3D0> <P></P> <P align=3Dcenter><SPAN style=3D"FONT-FAMILY: Arial; COLOR: black; FONT-SIZE: 10pt= "><FONT style=3D"BACKGROUND-COLOR: #ffffff"><BR><STRONG>Si vous ne= souhaitez plus recevoir d=92emails sur ce spectacle, cliqu= ez sur :<BR><A href=3D"http://www.lochnessprod.com/desabonnement1= =2Ephp?3&565-186&6&sLlkUa5BKqbSrSWAhgChqA">D=E9sabonnement</A></STRONG></FONT></SPAN></P>= </SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></FONT></TD></TR></TBODY></TABLE><= /DIV> <P style=3D"MARGIN: 0cm 0cm 0pt" class=3DMsoNormal align=3Dcente= r><FONT size=3D2></FONT> </P></TD></TR> <CENTER> </CENTER></TBODY></TABLE></CENTER></DIV> <P align=3Dcenter><FONT color=3D#ffffff size=3D1><MPCT_FOOTER></MPCT_FOOTER></FONT></P></TD></TR></TBODY></TAB= LE></FONT></DIV></FONT></DIV><img src=3D"http://www.lochnessprod.com/desabon= nement1.php?3&565-186&-1&sLlkUa5BKqbSrSWAhgChqA" border=3D"0" width=3D"1" height=3D"1"> </BODY></HTML> ------=_Part_349_2910481946.1242804871446-- ------=_Part_095_0725482484.1242804871428 Content-Type: image/jpeg; name="=?iso-8859-1?Q?Cocons-1-2=2Ejpg?=" Content-Transfer-Encoding: Base64 Content-ID: <B8E7C2B456623520D99708157E3BE588@Emailing6> Content-Location: B8E7C2B456623520D99708157E3BE588@Emailing6 /9j/4AAQSkZJRgABAgEASABIAAD/4SMuRXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEAAAEaAAUA AAABAAAAYgEbAAUAAAABAAAAagEoAAMAAAABAAIAAAExAAIAAAAbAAAAcgEyAAIAAAAUAAAAjYdp AAQAAAABAAAApAAAANAAAABIAAAAAQAAAEgAAAABQWRvYmUgUGhvdG9zaG9wIENTIFdpbmRvd3MA MjAwODoxMDozMSAxNToyMjo1MwAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAABkqADAAQAAAAB AAACNwAAAAAAAAAGAQMAAwAAAAEABgAAARoABQAAAAEAAAEeARsABQAAAAEAAAEmASgAAwAAAAEA AgAAAgEABAAAAAEAAAEuAgIABAAAAAEAACH4AAAAAAAAAEgAAAABAAAASAAAAAH/2P/gABBKRklG AAECAQBIAEgAAP/tAAxBZG9iZV9DTQAB/+4ADkFkb2JlAGSAAAAAAf/bAIQADAgICAkIDAkJDBEL CgsRFQ8MDA8VGBMTFRMTGBEMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAENCwsN Dg0QDg4QFA4ODhQUDg4ODhQRDAwMDAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM DAwM/8AAEQgAoABxAwEiAAIRAQMRAf/dAAQACP/EAT8AAAEFAQEBAQEBAAAAAAAAAAMAAQIEBQYH CAkKCwEAAQUBAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAABBAEDAgQCBQcGCAUDDDMBAAIRAwQh EjEFQVFhEyJxgTIGFJGhsUIjJBVSwWIzNHKC0UMHJZJT8OHxY3M1FqKygyZEk1RkRcKjdDYX0lXi ZfKzhMPTdePzRieUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm9jdHV2d3h5ent8fX5/cRAAICAQIE BAMEBQYHBwYFNQEAAhEDITESBEFRYXEiEwUygZEUobFCI8FS0fAzJGLhcoKSQ1MVY3M08SUGFqKy gwcmNcLSRJNUoxdkRVU2dGXi8rOEw9N14/NGlKSFtJXE1OT0pbXF1eX1VmZ2hpamtsbW5vYnN0dX Z3eHl6e3x//aAAwDAQACEQMRAD8A5uqgVHcVoVZV+yGM0WVYbbGS06909WVk1M2krfjImhGPpc6Q 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 +8IEfajobPqPq9X73+N/fa94CSTxFHZ0HrlOK/LvwLqsequu2yx7QA1lv808+7d/X2/zP+H9NUg+ AQ4bhEAHsfFaFv1i67dTfRflvtrymCq9tjWOJa1rafpPZvqdsrbv9L0/0n6X+eWap8XukH3hC79P t8VV/hMc+AEcF+PEy3D90fj/AHpKKSkrxP2lZfl9j//S5pgOp5lYDGNtuf6rtu0kyfjwujbjOL4B jwWX1Tprq99zB7HH9KPD+UP5O47ltc5AyEZgcUYXxRaPLzAlKJNGVUWzi23ZgAut9DGIJbENc7b+ fud7WV/8H/6LV92TQHNqqyN52++xjTZEab3OqD2/vexc907ZZa9+XjvyjXrZr9FrfaP0em/6K6Jw x8uig4z3spY4Ws9MDUs93t+lsez/AKCXLzM4318fmlS3NCMZV08Ng95TmYvTOl39QoqtsrMfaqaY ca8UvfTjbS72Ovqr2Xe7/ArmcjBr6d6d3U7PtGbfNtHTmN9zmOPsvz/Sbuqp2u9e/Fx99lnv/m6W W119F9TOuUjGt6Tf+jssLnY73NIY5pbHpfn++vZ+f/OLF6x9bOp42ZlY2NjHplrnH7TdU1luQ/Z+ h9R97fY706v3PU9D/BqDBHJjnOHDrvKfFw8Uf0f3v+YulwyETd3/AM1ysunreWx3UbsBuFU1v6dg HpMcW7t97Kshwd9DY/8AQ/oqv0dLP0ix7bi6Ax2yHbnhwkRH+e3ajZJszPUfbY/JNvNj/e7z/SWv e/8AsvQn1u/lDTwH+dz9JXBE1V6dwx+m7p0sHrPTMfomV0vqVOQ5uXa4vux9m9tb3dP9Wmv1Xtr3 ub0+7fvq/wC4/wDwyN+3vqYTa7p/S3Y9j33MNr8ep4bXdXmCt7KrMja708jJxf1f8zGxv0b/APBr H6f09uf1nAwbnPrry72UWOrgODXH3OZu3ta7+ytOv6qdMuxrs3pvWqX4c2mr1q37/wBC6nHe26yt tbNjbczE/WvRr/QX/abKalQywwjPWUyiJXORGvzf3YtuBn7fpo1oPos/q/1Y+2ZFlfRgMN2E2nGo cZeMpo/pNlu/9Hua99Vt9frW3ejRk/zlliuWfWP6sg2sxOnvx6JtOOw01Pa11rMEfaGVuyf1W9ju nPq/Q2P/AKR9t9b1P1dM/wCodtdr6H9QrY6q21ttz6nNpbXXjU9R3PJd6leU9mT/AEV3+AryMj/t NYp1fUGy7ErsZmtGQbGiw+m51DqXsxHi7CuZ/SvRfm/z381lf4D0/R/SOlLkZVeTJ2/S/wAbWKB7 4/Riw631X6q3Y2Q7GwGPzM6kWU3Ak2022X33XuzrfVs/XPTdj2f4d/8AOYmT6VS5aV0vUfqZdhdN yM1+TU37CxxuDi6bXfaMjFoFNe39W9SnHbs9R93q5H6JcyrfJHFwEYpymL142HmOPiHEANNKXlJM krVsNP8A/9PFo3OabSNrBy9xDWj+s9+1jUR2X0RwLL8qkgiCBvsHn7qq7Gf9Jc5lZd+XZ6mQ7dH0 WjRjR+7VWPZW1Xqek4TKa7erdRb092QxtlFDabMi01v1rvuZWaq8eqxvvq/S/aLK/wBJ6Hprenlo dh2riLnRwX1P/RdnEb0xztuA6qw87anDefjW4Nvdt/4tSbRjUOsNDdgscXuDYADg1zSW/wBbd71z OV059OZXi02V9QNwY7HfiE27/U+g1tW1uRVkbvZZi3VV5FT/AMxaNPUs3EtOF1pltNjRIsyGObcw Eez12WN9W6h3+k/nq/8Aha/0SUMkdLr6f96ieGWpBPiD/wB87eLc6u0PqearKfdW9sEh39ppQOq9 TtzMn7Vf77HAtJ0ZEH6MNZ5+1VbLsjF9O3Ix8jFqvP6KzIpfTXZI3AMtsbsd7fcmuubbh/azRkDB 3Q3MFLxQXT6e37Vt9L+c9ieTjsSuOvpEv+5WCOS6qXeqa5sHqEtaAXfSAjt+d9FLc0lDrbdkNe/G xL7Wsb6jzTVZY0Vgub6xe1vtq3VWe/8A4OxDLrn4tmRj1W201R62QytzqmbvoC64N9Ovdu/OTuOA B1BXHHM9CGn1R+6K26udoB5lWsTH6j1J2J0nFD8s0tsGJjbhDRDsjJNfqFlbfU2Ots/0n0P9ExZ9 QdY83u4Ehnx4e7/vq1OjdZy+i5wzsNtTrww1j1ml7Q1zmPs9rXM9z2V+j/xdtn+EUABkJ5oxEpnT Fxf1f0v8JmJETHGSREfPTWZhZTmV2sxbiy2HVPbVYQ7Rzw6t2z3+1lrvb+5ant6dlUvbXZjPDrKm XMDWl4dVbsfTaw1b2Pqs9Wv/AK9+h/nlt0/XrrVD6H0V49QoO51bBaGWEU14TPUqGRtZ6dOPTs+z +j/hP9Pems+vPWrcWzGsrxjvxHYQtFbw9jHtFNr6Xet+jda1lL30sb9l9Wiq30EOPmv8zD/GTWL9 +TkZPTM3DM5OO6p+0l4I9zA2w4v6xtn0N19eyr1f53/BKvK3cv66dXysLLwSyimjN3et6TX7vfbd l37X222+25+XezZ/g6/5n0lgqXBLKYn3YxjK/wBErMnBY4CT5rykmSUtsb//1PP3iWkeIhdB1Ppm Z9Zsz9rdKYzIF1VIyMZtlbbKLGVV41ldlN1lT/Q3Ub6Mhn6D0f5awFK3p2W3GZmPx7G4th213lh9 Nx9+ldhG1381b9H/AEVn7i2pxuiCARpq1IHcO30zFGE/P6dTl0Hq2VjVNxL6bvYx7rGWZnThnTVj NyrsZvpepVc/Gf8ApcL7T6lqu4F7elV9Pw+u2gZ2Nlvtxd5bf9jY+hzKrMgMst9Or9puw837J/g/ sd+R6P6X9NzDenZRrru9C30b3mqu0MJDnN/nK2fmuexv5ivHpPSW2GuzMdj2je70XVuisNl7A59j a3ussr2O/mt//B/palFKN7m73odvT/gsgPYJMnA+sWJhZV3UMqMbMDH3MdlMsOXFlbx6Larcj7U9 rnev9p/wTPU/Tf4Gzc/ygz6yHrf2yk/VtxLd4trNB6eRv/Y/2Anf632X9S/Zv2T1GZf6X/uyudyO ldIoqeft732+kLKmiqBaSdrRXuLXenub73Xe/wD0df8ANrMNWso8HEPtHy1ugyAdrI6pm04P1dx6 Mp7K8Wo3Ctj4DLjl5h9R23/C+i2n6f8Ag/8AjFr5zbLqusNaWUdOxsnqFmDnY19bA31HPD+mZWHX YH5OP1P0serG9nq/n/rGH+ir5GvHfY8MYNzjwJA4En3OhrdrW/ScivpqYBWwixw1daPH9yp2n6Jv /TTjisit7J+08ShMVqu14cBHDRA/1HtTqOvJ5OpSVmOgA7NeRsksxqQBqToArFnTsytzGGsm1/px S33WTcJx2+iP0m+78yv+c/m/31VaHlzfTbvskBjInc4kNrZt/lPXb3nI6j1PJ6xNhu6ZiPGUQ5xA dAyLcPp7qnU2VW5NNl9GRme/0a8n9HX6/wDMx5csoGNUf3vr8q+EBIEm3Au+reWzpVfUqt17H1ts ea2FzIcA52y36X6BtlbLX7PT+0faKP8AA/psgEHUGV6P9XetXnFbW9ryTkB1TTRvr9K2vZZjuxMT +aZVV6llVNb/APt7/CUvrD9S8W6crpOzHuseQ/HdaGNJPu0bn/YrKvd+7639tMhzBEjHIOHX0y6U UGFi4/WnhUlsf8zvrL/3DH/btf8A5NJT+5D96P8AjLOGXYv/1fPtyu9P651LprHtwrRUXkODy0Oe whl2Nupe7+Z/Q5V7fYsxxc1xa4EOaYcDoQR2ITbitkkEUaIaoiRto9tj/WE/se3Mb177H1XJsvys vDrx2ne95bhD07NtW2z7J+n9P1LPUt9O72X12WK+36w1tvhv1qqpabCK2nDGQWD1nWepZmeni7vX +z05GV+i/wAL6fpejVX6fne4qxiYr8ibHONdDDD7YnX/AEdTZZ6tv8jd7Pp2+mxRHDE/U/uwP0+V fxH+RepyT9W+rX229X6445VDq6qciujbXbjMqF21uOxpc21l3rYTLfW/0P6JVH9I+qtYfa7rjbob Y9mLS1wJht7sej7ZdW1u9zmYtb7fszP52xYzul5J1ofXc2YneK3f2q8g1/8AQ9RFo6JlvM3vZSwc hrm2vP8AVbUfS/7durTuCQ0EpD+rQ/71Fg60D9WNPpmzIyKWuZQwObUx7g9wNodXVU+wNZvsZT6t jn7GfzSGtN+K5lTa207aWEhkODzr9OyyI9S1239I7/rdbGVqk4vvt2tBe4z9Ea6Dw/qhWIaDVilq aH0REEJiCrVeMHgte6NJH5VXezY4g6R5p6xv9Cp3Z1eQ6z0aqra2G3aHkOsO1mytwe1/H7j/APSf mLtG5FFeJm4+Lc3MNmJY97RW5gElrHTe1jKH7/8AR1/pv+tLk/qu/Iv6hVVDX04wdYa3fQ32ezdx 7rHf4Pf9DYunflZF/RsnqNJAotPpVsI949+19jodtZ/M+ns/c9b/AK5Xn6pRO18Ppl5svyxPkdmj 9W8wU+oH2E22Wm2Q0j3NHp+7Y3cr2b9b+s2ZFNOLZZS2t7a78IgC2wfSse29zXNqZtb6Vb/+uKPQ H110M9La1z67xLYaG6ur9v8AZci/WHqV32S5/TmgOfU37Vaa697aW7WurcXH1HMuy7WtZ6bbLGJs 4RnzIMoWflHFL0cXy/J8n/M9xZHJYlEbHw1r/pf9w7Xpj/yky/wSXHft1/72V99P/pBJR/d5/wCa P8v+rNj3cv8Anh/jy/8AVb//1uC9Y2s25FQu9MAF5JD2jgfpmfm/m7bvWr/cQ9mC4kt9djRz9B8T +8+Kf+oRqXYuR0+vHbT6OVSLD6+pbdud9F+0bmPp3Naz6fqI3SMIZByKGv8ASyAwGtriW+o5hmyn +sz+d+z7PX/R/wDW1rAxlIRHzHpsw8JAsnTujZRgsILK3XEf6Z0N/wC2qfTd/n3f9bVqn1b7JfG1 jIAaIAAP0GsaGsYz+oxVKWgZFmPDm3VT6jXjaWxoWv8A5f8Awav4DRMFpL3RuOkQPHX2qxjliGxj xbHXiYZRyE6g02sbGeWEEAQJM9irHpW0seHlsgDbrzP5qbHyqfTMhwAaWkRrMn3OH0kDP69jhryx 36YNcQQyBu2+3n9H/VSlkgNTOIHmkQl2P2NnELrK7fVaTAAbBDTE/mgjc7/rahldLN261kVXEQNu jX/mubbH0P8AjED6u9J6zjbL7mA16uNVthEaeoy32z6XP7//AJ8WgeoVtJe+0EPI13cz3dtamY8n GOIRMb6G15jwiib/AAcVrmUZDRktjaYcx8mDH0nbPd/mKlc9tm3Ugge/w013SujysbG6hSGOaK3x tZcHOLgD4hrH/oWrOs6f0jEsa3PvybfzQKWMqERv3br3+6t257P9difKWmx+xjEKV0GnqjQaunsa 9/ULG1yf5xnpB1vrVT7LW7HWepX9P+bVvD6v1fp2Sfq3lNZ9k91lzXjdYS4eqbKrW+7bU8fm/meq tjonT8OpuL1nGxq6MhlLpDyXbA7c3e9m5j/5t/8AO1LHso6E3rLdnUL2Z7i59znse+omfU9GxtY9 VrfSe5vsd+j/APAlVlI6XKhxidXrwx7MvCCDoSAOEmv0j/6KtV1b0qmsra0NeXOse4naGvd7WQ0F /snfvq/7b9iKOq029VxrcBnrNqLKq6so1uDnkFll3q3B2PU99tn6H1Kf0P8AOIDunVYDXWPLL6i/ 06w4OFYeP0jWPsLGu3WU7bPTZbU/Y/8Anf5ylPe99+MHXU07GbKabaqwyxrah6hqqcz7P6rrfV9S 911Vj/8AhVfuB1o0bB+b9Lf+8wxjGMrAF993oNv12/8ALSn/ANiMf/0qkuZ/ZuF/oLf81iSi4If1 P/CP7V/F5/a//9fzXHFz3FtUHaC4hxEQBudo/wBrvo/Q/PRac26u2tzgLwz2hlg3Agjb6bvzv+L/ ANF/g1pj6sdbbD2dNsLgQRLo/wClLPoIg6F9ZGj2dOdUD2YGzx+85zvzlcjzHJkAS5nFptwziT/g /Ijg5gG44p/WPp/wvm4m5kdVs6jijFYwVMYWWNrI2vNwGz9I5rd2S+9zv6Tc/wDS22frH6WxY1LH 057ssabCQ6uSXM0LXNc2P5vd9D9z2K+/pf1ixywY+BkGwAA3Bm4D97aBO5EtZ1p9drbel5FZe42i 2uiwEP8AoWBzPoOqvr9tqA5jBHIeDNDLHGYy+eHT9D5v1nB+/wD+jplCU4C8ZxzlYMRE8P8Ae/q8 f+b/APYeMrbb3hpa02Bg+g0nj6b/AOW32jd7Ue77X9qF/U2v2Oc317KCw6Pbu9JrmB+N6/of4Kxv sVCum5lQG6/He4x6VlbhLRrUWvs+l/mo7sW2rHruOYyHbn2aN/R+702+u15Y9tln0vofza1oyE4i USJxIrijr+LRIMTRBB7Fs9Lz/s7H4Tnn7C8xXXZ2DjFTNzGuc/6b6v8AMVHqFD6rHV3CP0TrqvcG hzWEb2S7b+sMadzqv/SiqtzHOvbbXabaqHQXQG75LXekxn7j9jfVc/8AMU8/qgyMM4+TDbqiX0PD QWOJJ9tn+EbZsd6e7/CKlCU4SycI/UidQJH+NH+5CXH7bayCEo4xoMnBcwP3v/Qsft8f+sZYXUq6 cO5+4PurI245D9zmH6VvqA+m303bf0b/AKaudPrf1kutvbX6WPHtAPufO4tO+zb+jr/7dWAx73t0 2t9wYS4Bv0v33fR2f11fpznYvTXVU2Fl2S81yJDG7m7d0tG71Npapjk01umGMXW651xtbRhsmz02 SGPrbo4nbW/2j6H9Sz9L/wAGsHp9gp6g24l23Vr3P9xJdo/+256Ln5TbWfZ82S+lsYtwLSdp1rZk sqja7Z/0/wC2qFTbC1zrZlswAAP7f5rVXjE+7ksHil8sz+jGO0P6vDL1f6xmlk/VwAIEYk3ED5pS /T/r+n/EdjrDgzqJyDp61dW2e+1ope95bH51arP6pmux2Yrntfj1b/Ra5od6ZtLXXPoc73Vus9Nq FeXPZUXvY5ra2Fu0y73T+jf9H3V/ntahvtc9jWECGNgaRp/qVahKRiP0eteLBLQmtWXr5P8A3Is/ znf3pIe4eCSSNX//0LOSLWi20OfXVu2+q3eBLW+o+tjmN22WVt/nPZd7P5r9J/NCc6yuxwFn6QuE gG53Jfs9QM9N/wDwH+m/Q/8ABouTW4i9zai6xxADdhLXNDfY/wBRj99ljrP0VzNleyljP+C9UZa8 Qyuh9TQA5sMtO0ncN21lzW+psY13/XfS9T+esWRglAwhZj8sYy15P9zEfV7seP5v3/cdHKJCUqEv mJH+6P3p/uMZsDXuNrzrFloFrpADm7a/a1mxjv3/APBf8J6lqmz1K22H1DUwawX3NDddWbHs3/1t v0P3K1Cup4cHjHhztSdltcQd1dbdtjmfo/SZZ+5/M+n6lv8ANxqrIa1z6Wb9pDX7boJft3bdpf8A S2e99f8Agv36/U9J/pIIHCT6b/3AYf4P+LNZqDrYHqr/AHVxJmi1jo9QssklxJyBpu32uO9vt9ns 97v0X6L1PV9JSZdiPrbXlObkvadpsfUXNLySW1jcx36Tb+YhV47mtaXUD1P8IRW8jX3O9rn+/Y7Z Xt/w385/LTmuAZpJIaYAbbuIP0mBrbG+3c7b/wAJ/wCBqPJjxZd5fKfTwS5TFO+/FH2/QvhKePaO 414o55x/7r1LW9P6C9pdZg1NBO1zm0lnbdvd6LWPbX+69356p5H1X+r2QCfSvx3EalnqgtA53MuZ c1n0Vd2uBBOMZcZJDLTBO76R3/S/Sv37PU/w/wDOf4eHpE7pxfa1+5m5twI0aXv2Me/9M53/AKs3 p2MzgKjzGeI6Ac1g4P8AE93hVIiWpxYz/wBRy3/jcDi5H1OxGB1eLm3tD/e5ltDng7NNr3M9H979 xVMn6ndXbWaK3VZLqw13tOwkFrmMaBd6dbti6gUOZP6sNznTY6LYEnf+YXOvd7d+7b/ov0nq/wA0 sbfj7zRimtr9vs9J41A/O/SWM/t/9/VkfEeahA+3lGWhpHmJctwys8W+HJhy/JxsX3bFKXrgYWd8 Uc3p/wAeM4PAZPSeoYr32ZuLbj1tJdq1zma6/wA97mv/AM9AbaY0gsPLTqPESvS2ZeY0fQLhyHNr fLmk+32gtr9XZ77Pcyj/AIV/+DpZXTMTNIOTgV2F3uc9tL6rS4/4M2Uln9T1H2f8Z/LuYPjE46Zs WMd54s+L1eWPJKP/AKUYMnJQOuOcz4TxT0/woxfPwQRonBJC6/L+oWIQT0/JfSdSK7gLGk/8ZXss Y3+xasHO+rPW8IFzsU31j/CY59Qf1i1v6Vn9upXOW+L8nnA4c0YyP6GT9XL6cfz/AOAw5eR5jHvA kfvR9QcyfiklLv3T9ySv8TWo9n//2f/tJ9pQaG90b3Nob3AgMy4wADhCSU0EBAAAAAAABxwCAAAC AAIAOEJJTQQlAAAAAAAQRgzyiSa4VtqwnAGhsKeQdzhCSU0D7QAAAAAAEABIAAAAAQACAEgAAAAB AAI4QklNBCYAAAAAAA4AAAAAAAAAAAAAP4AAADhCSU0EDQAAAAAABAAAAB44QklNBBkAAAAAAAQA AAAeOEJJTQPzAAAAAAAJAAAAAAAAAAABADhCSU0ECgAAAAAAAQAAOEJJTScQAAAAAAAKAAEAAAAA AAAAAjhCSU0D9QAAAAAASAAvZmYAAQBsZmYABgAAAAAAAQAvZmYAAQChmZoABgAAAAAAAQAyAAAA AQBaAAAABgAAAAAAAQA1AAAAAQAtAAAABgAAAAAAAThCSU0D+AAAAAAAcAAA//////////////// /////////////wPoAAAAAP////////////////////////////8D6AAAAAD///////////////// ////////////A+gAAAAA/////////////////////////////wPoAAA4QklNBAgAAAAAABAAAAAB AAACQAAAAkAAAAAAOEJJTQQeAAAAAAAEAAAAADhCSU0EGgAAAAADRQAAAAYAAAAAAAAAAAAAAjcA AAGSAAAACABDAG8AYwBvAG4AcwAtADEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAA AZIAAAI3AAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAEAAAAAAABudWxs AAAAAgAAAAZib3VuZHNPYmpjAAAAAQAAAAAAAFJjdDEAAAAEAAAAAFRvcCBsb25nAAAAAAAAAABM ZWZ0bG9uZwAAAAAAAAAAQnRvbWxvbmcAAAI3AAAAAFJnaHRsb25nAAABkgAAAAZzbGljZXNWbExz AAAAAU9iamMAAAABAAAAAAAFc2xpY2UAAAASAAAAB3NsaWNlSURsb25nAAAAAAAAAAdncm91cElE bG9uZwAAAAAAAAAGb3JpZ2luZW51bQAAAAxFU2xpY2VPcmlnaW4AAAANYXV0b0dlbmVyYXRlZAAA AABUeXBlZW51bQAAAApFU2xpY2VUeXBlAAAAAEltZyAAAAAGYm91bmRzT2JqYwAAAAEAAAAAAABS Y3QxAAAABAAAAABUb3AgbG9uZwAAAAAAAAAATGVmdGxvbmcAAAAAAAAAAEJ0b21sb25nAAACNwAA AABSZ2h0bG9uZwAAAZIAAAADdXJsVEVYVAAAAAEAAAAAAABudWxsVEVYVAAAAAEAAAAAAABNc2dl VEVYVAAAAAEAAAAAAAZhbHRUYWdURVhUAAAAAQAAAAAADmNlbGxUZXh0SXNIVE1MYm9vbAEAAAAI Y2VsbFRleHRURVhUAAAAAQAAAAAACWhvcnpBbGlnbmVudW0AAAAPRVNsaWNlSG9yekFsaWduAAAA B2RlZmF1bHQAAAAJdmVydEFsaWduZW51bQAAAA9FU2xpY2VWZXJ0QWxpZ24AAAAHZGVmYXVsdAAA AAtiZ0NvbG9yVHlwZWVudW0AAAARRVNsaWNlQkdDb2xvclR5cGUAAAAATm9uZQAAAAl0b3BPdXRz ZXRsb25nAAAAAAAAAApsZWZ0T3V0c2V0bG9uZwAAAAAAAAAMYm90dG9tT3V0c2V0bG9uZwAAAAAA AAALcmlnaHRPdXRzZXRsb25nAAAAAAA4QklNBCgAAAAAAAwAAAABP/AAAAAAAAA4QklNBBQAAAAA AAQAAAAFOEJJTQQMAAAAACIUAAAAAQAAAHEAAACgAAABVAAA1IAAACH4ABgAAf/Y/+AAEEpGSUYA AQIBAEgASAAA/+0ADEFkb2JlX0NNAAH/7gAOQWRvYmUAZIAAAAAB/9sAhAAMCAgICQgMCQkMEQsK CxEVDwwMDxUYExMVExMYEQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAQ0LCw0O DRAODhAUDg4OFBQODg4OFBEMDAwMDBERDAwMDAwMEQwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM DAz/wAARCACgAHEDASIAAhEBAxEB/90ABAAI/8QBPwAAAQUBAQEBAQEAAAAAAAAAAwABAgQFBgcI CQoLAQABBQEBAQEBAQAAAAAAAAABAAIDBAUGBwgJCgsQAAEEAQMCBAIFBwYIBQMMMwEAAhEDBCES MQVBUWETInGBMgYUkaGxQiMkFVLBYjM0coLRQwclklPw4fFjczUWorKDJkSTVGRFwqN0NhfSVeJl 8rOEw9N14/NGJ5SkhbSVxNTk9KW1xdXl9VZmdoaWprbG1ub2N0dXZ3eHl6e3x9fn9xEAAgIBAgQE AwQFBgcHBgU1AQACEQMhMRIEQVFhcSITBTKBkRShsUIjwVLR8DMkYuFygpJDUxVjczTxJQYWorKD ByY1wtJEk1SjF2RFVTZ0ZeLys4TD03Xj80aUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm9ic3R1dn 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 3MFTmGra/d+5/N+nX9CtiZ31m666ypz8wufT6Rr3MrMGr1m47trq/c5jcm9m/wDwn+E9T0q1on77 wgR9qOhs+o+r1fvf4399r3gJJPEUdnQeuU4r8u/Auqx6q67bLHtADWW/zTz7t39fb/M/4f01SD4B DhuEQAex8VoW/WLrt1N9F+W+2vKYKr22NY4lrWtp+k9m+p2ytu/0vT/Sfpf55Zqnxe6QfeELv0+3 xVX+Exz4ARwX48TLcP3R+P8AekopKSvE/aVl+X2P/9LmmA6nmVgMY225/qu27STJ+PC6NuM4vgGP BZfVOmur33MHscf0o8P5Q/k7juW1zkDIRmBxRhfFFo8vMCUok0ZVRbOLbdmAC630MYglsQ1ztv5+ 53tZX/wf/otX3ZNAc2qrI3nb77GNNkRpvc6oPb+97Fz3Ttllr35eO/KNetmv0Wt9o/R6b/oronDH y6KDjPeyljhaz0wNSz3e36Wx7P8AoJcvMzjfXx+aVLc0IxlXTw2D3lOZi9M6Xf1Ciq2ysx9qpphx rxS99ONtLvY6+qvZd7v8CuZyMGvp3p3dTs+0Zt820dOY33OY4+y/P9Ju6qna7178XH32We/+bpZb XX0X1M65SMa3pN/6Oywudjvc0hjmlsel+f769n5/84sXrH1s6njZmVjY2MemWucftN1TWW5D9n6H 1H3t9jvTq/c9T0P8GoMEcmOc4cOu8p8XDxR/R/e/5i6XDIRN3f8AzXKy6et5bHdRuwG4VTW/p2Ae kxxbu33sqyHB30Nj/wBD+iq/R0s/SLHtuLoDHbIdueHCREf57dqNkmzM9R9tj8k282P97vP9Ja97 /wCy9CfW7+UNPAf53P0lcETVXp3DH6bunSwes9Mx+iZXS+pU5Dm5dri+7H2b21vd0/1aa/Ve2ve5 vT7t++r/ALj/APDI37e+phNrun9Ldj2Pfcw2vx6nhtd1eYK3sqsyNrvTyMnF/V/zMbG/Rv8A8Gsf p/T25/WcDBuc+uvLvZRY6uA4Ncfc5m7e1rv7K06/qp0y7Guzem9apfhzaavWrfv/AELqcd7brK21 s2NtzMT9a9Gv9Bf9pspqVDLDCM9ZTKIlc5Ea/N/di24Gft+mjWg+iz+r/Vj7ZkWV9GAw3YTacahx l4ymj+k2W7/0e5r31W31+tbd6NGT/OWWK5Z9Y/qyDazE6e/Hom047DTU9rXWswR9oZW7J/Vb2O6c +r9DY/8ApH231vU/V0z/AKh212vof1CtjqrbW23Pqc2ltdeNT1Hc8l3qV5T2ZP8ARXf4CvIyP+01 inV9QbLsSuxma0ZBsaLD6bnUOpezEeLsK5n9K9F+b/PfzWV/gPT9H9I6UuRlV5Mnb9L/ABtYoHvj 9GLDrfVfqrdjZDsbAY/MzqRZTcCTbTbZffde7Ot9Wz9c9N2PZ/h3/wA5iZPpVLlpXS9R+pl2F03I zX5NTfsLHG4OLptd9oyMWgU17f1b1Kcduz1H3erkfolzKt8kcXARinKYvXjYeY4+IcQA00peUkyS tWw0/wD/08Wjc5ptI2sHL3ENaP6z37WNRHZfRHAsvyqSCIIG+wefuqrsZ/0lzmVl35dnqZDt0fRa NGNH7tVY9lbVep6ThMprt6t1FvT3ZDG2UUNpsyLTW/Wu+5lZqrx6rG++r9L9osr/AEnoemt6eWh2 HauIudHBfU/9F2cRvTHO24DqrDztqcN5+Nbg2923/i1JtGNQ6w0N2Cxxe4NgAODXNJb/AFt3vXM5 XTn05leLTZX1A3Bjsd+ITbv9T6DW1bW5FWRu9lmLdVXkVP8AzFo09SzcS04XWmW02NEizIY5tzAR 7PXZY31bqHf6T+er/wCFr/RJQyR0uvp/3qJ4ZakE+IP/AHzt4tzq7Q+p5qsp91b2wSHf2mlA6r1O 3MyftV/vscC0nRkQfow1nn7VVsuyMX07cjHyMWq8/orMil9NdkjcAy2xux3t9ya65tuH9rNGQMHd DcwUvFBdPp7ftW30v5z2J5OOxK46+kS/7lYI5Lqpd6prmweoS1oBd9ICO3530UtzSUOtt2Q178bE vtaxvqPNNVljRWC5vrF7W+2rdVZ7/wDg7EMuufi2ZGPVbbTVHrZDK3OqZu+gLrg30692785O44AH UFcccz0IafVH7orbq52gHmVaxMfqPUnYnScUPyzS2wYmNuENEOyMk1+oWVt9TY62z/SfQ/0TFn1B 1jze7gSGfHh7v++rU6N1nL6LnDOw21OvDDWPWaXtDXOY+z2tcz3PZX6P/F22f4RQAGQnmjESmdMX F/V/S/wmYkRMcZJER89NZmFlOZXazFuLLYdU9tVhDtHPDq3bPf7WWu9v7lqe3p2VS9tdmM8OsqZc wNaXh1Vux9NrDVvY+qz1a/8Ar36H+eW3T9eutUPofRXj1Cg7nVsFoZYRTXhM9SoZG1np049Oz7P6 P+E/096az689atxbMayvGO/EdhC0VvD2Me0U2vpd636N1rWUvfSxv2X1aKrfQQ4+a/zMP8ZNYv35 ORk9MzcMzk47qn7SXgj3MDbDi/rG2fQ3X17KvV/nf8Eq8rdy/rp1fKwsvBLKKaM3d63pNfu99t2X ftfbbb7bn5d7Nn+Dr/mfSWCpcEspifdjGMr/AESsycFjgJPmvKSZJS2xv//U8/eJaR4iF0HU+mZn 1mzP2t0pjMgXVUjIxm2VtsosZVXjWV2U3WVP9DdRvoyGfoPR/lrAUrenZbcZmY/Hsbi2HbXeWH03 H36V2EbXfzVv0f8ARWfuLanG6IIBGmrUgdw7fTMUYT8/p1OXQerZWNU3Evpu9jHusZZmdOGdNWM3 Kuxm+l6lVz8Z/wClwvtPqWq7gXt6VX0/D67aBnY2W+3F3lt/2Nj6HMqsyAyy306v2m7Dzfsn+D+x 35Ho/pf03MN6dlGuu70LfRveaq7QwkOc3+crZ+a57G/mK8ek9JbYa7Mx2PaN7vRdW6Kw2XsDn2Nr e6yyvY7+a3/8H+lqUUo3ubveh29P+CyA9gkycD6xYmFlXdQyoxswMfcx2Uyw5cWVvHotqtyPtT2u d6/2n/BM9T9N/gbNz/KDPrIet/bKT9W3Et3i2s0Hp5G/9j/YCd/rfZf1L9m/ZPUZl/pf+7K53I6V 0iip5+3vfb6QsqaKoFpJ2tFe4td6e5vvdd7/APR1/wA2sw1ayjwcQ+0fLW6DIB2sjqmbTg/V3Hoy nsrxajcK2PgMuOXmH1Hbf8L6Lafp/wCD/wCMWvnNsuq6w1pZR07GyeoWYOdjX1sDfUc8P6ZlYddg fk4/U/Sx6sb2er+f+sYf6Kvka8d9jwxg3OPAkDgSfc6Gt2tb9JyK+mpgFbCLHDV1o8f3Knafom/9 NOOKyK3sn7TxKExWq7XhwEcNED/Ue1Oo68nk6lJWY6ADs15GySzGpAGpOgCsWdOzK3MYaybX+nFL fdZNwnHb6I/Sb7vzK/5z+b/fVVoeXN9Nu+yQGMidziQ2tm3+U9dvecjqPU8nrE2G7pmI8ZRDnEB0 DItw+nuqdTZVbk02X0ZGZ7/Rryf0dfr/AMzHlyygY1R/e+vyr4QEgSbcC76t5bOlV9Sq3XsfW2x5 rYXMhwDnbLfpfoG2Vstfs9P7R9oo/wAD+myAQdQZXo/1d61ecVtb2vJOQHVNNG+v0ra9lmO7ExP5 plVXqWVU1v8A+3v8JS+sP1Lxbpyuk7Me6x5D8d1oY0k+7Ruf9isq937vrf20yHMESMcg4dfTLpRQ YWLj9aeFSWx/zO+sv/cMf9u1/wDk0lP7kP3o/wCMs4Zdi//V8+3K70/rnUumse3CtFReQ4PLQ57C GXY26l7v5n9DlXt9izHFzXFrgQ5phwOhBHYhNuK2SQRRohqiJG2j22P9YT+x7cxvXvsfVcmy/Ky8 OvHad73luEPTs21bbPsn6f0/Us9S307vZfXZYr7frDW2+G/WqqlpsIracMZBYPWdZ6lmZ6eLu9f7 PTkZX6L/AAvp+l6NVfp+d7irGJivyJsc410MMPtidf8AR1Nlnq2/yN3s+nb6bFEcMT9T+7A/T5V/ Ef5F6nJP1b6tfbb1frjjlUOrqpyK6NtduMyoXbW47GlzbWXethMt9b/Q/olUf0j6q1h9ruuNuhtj 2YtLXAmG3ux6Ptl1bW73OZi1vt+zM/nbFjO6XknWh9dzZid4rd/aryDX/wBD1EWjomW8ze9lLByG uba8/wBVtR9L/t26tO4JDQSkP6tD/vUWDrQP1Y0+mbMjIpa5lDA5tTHuD3A2h1dVT7A1m+xlPq2O fsZ/NIa034rmVNrbTtpYSGQ4POv07LIj1LXbf0jv+t1sZWqTi++3a0F7jP0RroPD+qFYhoNWKWpo fREQQmIKtV4weC17o0kflVd7NjiDpHmnrG/0KndnV5DrPRqqtrYbdoeQ6w7WbK3B7X8fuP8A9J+Y u0bkUV4mbj4tzcw2Ylj3tFbmASWsdN7WMofv/wBHX+m/60uT+q78i/qFVUNfTjB1hrd9DfZ7N3Hu sd/g9/0Ni6d+VkX9Gyeo0kCi0+lWwj3j37X2Oh21n8z6ez9z1v8ArlefqlE7Xw+mXmy/LE+R2aP1 bzBT6gfYTbZabZDSPc0en7tjdyvZv1v6zZkU04tllLa3trvwiALbB9Kx7b3Nc2pm1vpVv/64o9Af XXQz0trXPrvEthobq6v2/wBlyL9YepXfZLn9OaA59TftVprr3tpbta6txcfUcy7Lta1nptssYmzh GfMgyhZ+UcUvRxfL8nyf8z3FkcliURsfDWv+l/3DtemP/KTL/BJcd+3X/vZX30/+kElH93n/AJo/ y/6s2Pdy/wCeH+PL/wBVv//W4L1jazbkVC70wAXkkPaOB+mZ+b+btu9av9xD2YLiS312NHP0HxP7 z4p/6hGpdi5HT68dtPo5VIsPr6lt2530X7RuY+nc1rPp+ojdIwhkHIoa/wBLIDAa2uJb6jmGbKf6 zP537Ps9f9H/ANbWsDGUhEfMemzDwkCydO6NlGCwgsrdcR/pnQ3/ALap9N3+fd/1tWqfVvsl8bWM gBogAA/QaxoaxjP6jFUpaBkWY8ObdVPqNeNpbGha/wDl/wDBq/gNEwWkvdG46RA8dfarGOWIbGPF sdeJhlHITqDTaxsZ5YQQBAkz2KselbSx4eWyANuvM/mpsfKp9MyHABpaRGsyfc4fSQM/r2OGvLHf pg1xBDIG7b7ef0f9VKWSA1M4geaRCXY/Y2cQusrt9VpMABsENMT+aCNzv+tqGV0s3brWRVcRA26N f+a5tsfQ/wCMQPq70nrONsvuYDXq41W2ERp6jLfbPpc/v/8AnxaB6hW0l77QQ8jXdzPd21qZjycY 4hExvobXmPCKJv8ABxWuZRkNGS2NphzHyYMfSds93+YqVz22bdSCB7/DTXdK6PKxsbqFIY5orfG1 lwc4uAPiGsf+has6zp/SMSxrc+/Jt/NApYyoRG/duvf7q3bns/12J8pabH7GMQpXQaeqNBq6exr3 9QsbXJ/nGekHW+tVPstbsdZ6lf0/5tW8Pq/V+nZJ+reU1n2T3WXNeN1hLh6psqtb7ttTx+b+Z6q2 OidPw6m4vWcbGroyGUukPJdsDtzd72bmP/m3/wA7UseyjoTest2dQvZnuLn3Oex76iZ9T0bG1j1W t9J7m+x36P8A8CVWUjpcqHGJ1evDHsy8IIOhIA4Sa/SP/oq1XVvSqaytrQ15c6x7idoa93tZDQX+ yd++r/tv2Io6rTb1XGtwGes2osqrqyjW4OeQWWXercHY9T322fofUp/Q/wA4gO6dVgNdY8svqL/T rDg4Vh4/SNY+wsa7dZTts9NltT9j/wCd/nKU97334wddTTsZspptqrDLGtqHqGqpzPs/qut9X1L3 XVWP/wCFV+4HWjRsH5v0t/7zDGMYysAX33eg2/Xb/wAtKf8A2Ix//SqS5n9m4X+gt/zWJKLgh/U/ 8I/tX8Xn9r//1/NccXPcW1QdoLiHERAG52j/AGu+j9D89Fpzbq7a3OAvDPaGWDcCCNvpu/O/4v8A 0X+DWmPqx1tsPZ02wuBBEuj/AKUs+giDoX1kaPZ051QPZgbPH7znO/OVyPMcmQBLmcWm3DOJP+D8 iODmAbjin9Y+n/C+bibmR1WzqOKMVjBUxhZY2sja83AbP0jmt3ZL73O/pNz/ANLbZ+sfpbFjUsfT nuyxpsJDq5JczQtc1zY/m930P3PYr7+l/WLHLBj4GQbAADcGbgP3toE7kS1nWn12tt6XkVl7jaLa 6LAQ/wChYHM+g6q+v22oDmMEch4M0MscZjL54dP0Pm/WcH7/AP6OmUJTgLxnHOVgxETw/wB7+rx/ 5v8A9h4yttveGlrTYGD6DSePpv8A5bfaN3tR7vtf2oX9Ta/Y5zfXsoLDo9u70muYH43r+h/grG+x UK6bmVAbr8d7jHpWVuEtGtRa+z6X+ajuxbaseu45jIdufZo39H7vTb67Xlj22WfS+h/NrWjITiJR InEiuKOv4tEgxNEEHsWz0vP+zsfhOefsLzFddnYOMVM3Ma5z/pvq/wAxUeoUPqsdXcI/ROuq9waH NYRvZLtv6wxp3Oq/9KKq3Mc69ttdptqodBdAbvktd6TGfuP2N9Vz/wAxTz+qDIwzj5MNuqJfQ8NB Y4kn22f4Rtmx3p7v8IqUJThLJwj9SJ1Akf40f7kJcfttrIISjjGgycFzA/e/9Cx+3x/6xlhdSrpw 7n7g+6sjbjkP3OYfpW+oD6bfTdt/Rv8Apq50+t/WS629tfpY8e0A+587i077Nv6Ov/t1YDHve3Ta 33BhLgG/S/fd9HZ/XV+nOdi9NdVTYWXZLzXIkMbubt3S0bvU2lqmOTTW6YYxdbrnXG1tGGybPTZI Y+tujidtb/aPof1LP0v/AAawen2CnqDbiXbdWvc/3El2j/7bnouflNtZ9nzZL6Wxi3AtJ2nWtmSy qNrtn/T/ALaoVNsLXOtmWzAAA/t/mtVeMT7uSweKXyzP6MY7Q/q8MvV/rGaWT9XAAgRiTcQPmlL9 P+v6f8R2OsODOonIOnrV1bZ77Wil73lsfnVqs/qma7HZiue1+PVv9Frmh3pm0tdc+hzvdW6z02oV 5c9lRe9jmtrYW7TLvdP6N/0fdX+e1qG+1z2NYQIY2BpGn+pVqEpGI/R614sEtCa1Zevk/wDciz/O d/ekh7h4JJI1f//Qs5ItaLbQ59dW7b6rd4Etb6j62OY3bZZW3+c9l3s/mv0n80JzrK7HAWfpC4SA bncl+z1Az03/APAf6b9D/wAGi5NbiL3NqLrHEAN2Etc0N9j/AFGP32WOs/RXM2V7KWM/4L1RlrxD K6H1NADmwy07Sdw3bWXNb6mxjXf9d9L1P56xZGCUDCFmPyxjLXk/3MR9Xux4/m/f9x0cokJSoS+Y kf7o/en+4xmwNe42vOsWWgWukAObtr9rWbGO/f8A8F/wnqWqbPUrbYfUNTBrBfc0N11Zsezf/W2/ Q/crUK6nhweMeHO1J2W1xB3V1t22OZ+j9Jln7n8z6fqW/wA3GqshrXPpZv2kNftugl+3dt2l/wBL Z731/wCC/fr9T0n+kggcJPpv/cBh/g/4s1moOtgeqv8AdXEmaLWOj1CyySXEnIGm7fa472+32ez3 u/RfovU9X0lJl2I+tteU5uS9p2mx9Rc0vJJbWNzHfpNv5iFXjua1pdQPU/whFbyNfc72uf79jtle 3/Dfzn8tOa4BmkkhpgBtu4g/SYGtsb7dztv/AAn/AIGo8mPFl3l8p9PBLlMU778Ufb9C+Ep49o7j XijnnH/uvUtb0/oL2l1mDU0E7XObSWdt293otY9tf7r3fnqnkfVf6vZAJ9K/HcRqWeqC0Dncy5lz WfRV3a4EE4xlxkkMtME7vpHf9L9K/fs9T/D/AM5/h4ekTunF9rX7mbm3AjRpe/Yx7/0znf8Aqzen YzOAqPMZ4joBzWDg/wAT3eFUiJanFjP/AFHLf+NwOLkfU7EYHV4ube0P97mW0OeDs02vcz0f3v3F Uyfqd1dtZordVkurDXe07CQWuYxoF3p1u2LqBQ5k/qw3OdNjotgSd/5hc693t37tv+i/Ser/ADSx t+PvNGKa2v2+z0njUD879JYz+3/39WR8R5qED7eUZaGkeYly3DKzxb4cmHL8nGxfdsUpeuBhZ3xR zen/AB4zg8Bk9J6hivfZm4tuPW0l2rXOZrr/AD3ua/8Az0BtpjSCw8tOo8RK9LZl5jR9AuHIc2t8 uaT7faC2v1dnvs9zKP8AhX/4OlldMxM0g5OBXYXe5z20vqtLj/gzZSWf1PUfZ/xn8u5g+MTjpmxY x3niz4vV5Y8ko/8ApRgyclA645zPhPFPT/CjF8/BBGicEkLr8v6hYhBPT8l9J1IruAsaT/xleyxj f7Fqwc76s9bwgXOxTfWP8Jjn1B/WLW/pWf26lc5b4vyecDhzRjI/oZP1cvpx/P8A4DDl5HmMe8CR +9H1BzJ+KSUu/dP3JK/xNaj2f//ZOEJJTQQhAAAAAABTAAAAAQEAAAAPAEEAZABvAGIAZQAgAFAA aABvAHQAbwBzAGgAbwBwAAAAEgBBAGQAbwBiAGUAIABQAGgAbwB0AG8AcwBoAG8AcAAgAEMAUwAA AAEAOEJJTQQGAAAAAAAHAAEBAQADAQD/4Rk0aHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8 P3hwYWNrZXQgYmVnaW49J++7vycgaWQ9J1c1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCc/Pgo8eDp4 bXBtZXRhIHhtbG5zOng9J2Fkb2JlOm5zOm1ldGEvJyB4OnhtcHRrPSdYTVAgdG9vbGtpdCAzLjAt MjgsIGZyYW1ld29yayAxLjYnPgo8cmRmOlJERiB4bWxuczpyZGY9J2h0dHA6Ly93d3cudzMub3Jn LzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMnIHhtbG5zOmlYPSdodHRwOi8vbnMuYWRvYmUuY29t L2lYLzEuMC8nPgoKIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSd1dWlkOjU5NTBiNDNlLWE3 NTctMTFkZC05NjFiLWZmYTZkOThmNzlmZCcKICB4bWxuczpleGlmPSdodHRwOi8vbnMuYWRvYmUu Y29tL2V4aWYvMS4wLyc+CiAgPGV4aWY6Q29sb3JTcGFjZT4xPC9leGlmOkNvbG9yU3BhY2U+CiAg PGV4aWY6UGl4ZWxYRGltZW5zaW9uPjQwMjwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgPGV4aWY6 UGl4ZWxZRGltZW5zaW9uPjU2NzwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiA8L3JkZjpEZXNjcmlw dGlvbj4KCiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0ndXVpZDo1OTUwYjQzZS1hNzU3LTEx ZGQtOTYxYi1mZmE2ZDk4Zjc5ZmQnCiAgeG1sbnM6cGRmPSdodHRwOi8vbnMuYWRvYmUuY29tL3Bk Zi8xLjMvJz4KIDwvcmRmOkRlc2NyaXB0aW9uPgoKIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0 PSd1dWlkOjU5NTBiNDNlLWE3NTctMTFkZC05NjFiLWZmYTZkOThmNzlmZCcKICB4bWxuczpwaG90 b3Nob3A9J2h0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8nPgogIDxwaG90b3Nob3A6 SGlzdG9yeT48L3Bob3Rvc2hvcDpIaXN0b3J5PgogPC9yZGY6RGVzY3JpcHRpb24+CgogPHJkZjpE ZXNjcmlwdGlvbiByZGY6YWJvdXQ9J3V1aWQ6NTk1MGI0M2UtYTc1Ny0xMWRkLTk2MWItZmZhNmQ5 OGY3OWZkJwogIHhtbG5zOnRpZmY9J2h0dHA6Ly9ucy5hZG9iZS5jb20vdGlmZi8xLjAvJz4KICA8 dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogIDx0aWZmOlhSZXNvbHV0aW9u PjcyLzE8L3RpZmY6WFJlc29sdXRpb24+CiAgPHRpZmY6WVJlc29sdXRpb24+NzIvMTwvdGlmZjpZ UmVzb2x1dGlvbj4KICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0 PgogPC9yZGY6RGVzY3JpcHRpb24+CgogPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9J3V1aWQ6 NTk1MGI0M2UtYTc1Ny0xMWRkLTk2MWItZmZhNmQ5OGY3OWZkJwogIHhtbG5zOnhhcD0naHR0cDov L25zLmFkb2JlLmNvbS94YXAvMS4wLyc+CiAgPHhhcDpDcmVhdGVEYXRlPjIwMDgtMTAtMzFUMTU6 MjI6NTMrMDE6MDA8L3hhcDpDcmVhdGVEYXRlPgogIDx4YXA6TW9kaWZ5RGF0ZT4yMDA4LTEwLTMx VDE1OjIyOjUzKzAxOjAwPC94YXA6TW9kaWZ5RGF0ZT4KICA8eGFwOk1ldGFkYXRhRGF0ZT4yMDA4 LTEwLTMxVDE1OjIyOjUzKzAxOjAwPC94YXA6TWV0YWRhdGFEYXRlPgogIDx4YXA6Q3JlYXRvclRv b2w+QWRvYmUgUGhvdG9zaG9wIENTIFdpbmRvd3M8L3hhcDpDcmVhdG9yVG9vbD4KIDwvcmRmOkRl c2NyaXB0aW9uPgoKIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSd1dWlkOjU5NTBiNDNlLWE3 NTctMTFkZC05NjFiLWZmYTZkOThmNzlmZCcKICB4bWxuczpzdFJlZj0naHR0cDovL25zLmFkb2Jl LmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIycKICB4bWxuczp4YXBNTT0naHR0cDovL25z LmFkb2JlLmNvbS94YXAvMS4wL21tLyc+CiAgPHhhcE1NOkRlcml2ZWRGcm9tIHJkZjpwYXJzZVR5 cGU9J1Jlc291cmNlJz4KICAgPHN0UmVmOmluc3RhbmNlSUQ+dXVpZDoxMTkwN2UzZS1hNzQzLTEx ZGQtOTYxYi1mZmE2ZDk4Zjc5ZmQ8L3N0UmVmOmluc3RhbmNlSUQ+CiAgIDxzdFJlZjpkb2N1bWVu dElEPmFkb2JlOmRvY2lkOnBob3Rvc2hvcDoxMTkwN2UzZC1hNzQzLTExZGQtOTYxYi1mZmE2ZDk4 Zjc5ZmQ8L3N0UmVmOmRvY3VtZW50SUQ+CiAgPC94YXBNTTpEZXJpdmVkRnJvbT4KICA8eGFwTU06 RG9jdW1lbnRJRD5hZG9iZTpkb2NpZDpwaG90b3Nob3A6NTk1MGI0M2QtYTc1Ny0xMWRkLTk2MWIt ZmZhNmQ5OGY3OWZkPC94YXBNTTpEb2N1bWVudElEPgogPC9yZGY6RGVzY3JpcHRpb24+CgogPHJk ZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9J3V1aWQ6NTk1MGI0M2UtYTc1Ny0xMWRkLTk2MWItZmZh NmQ5OGY3OWZkJwogIHhtbG5zOmRjPSdodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyc+ CiAgPGRjOmZvcm1hdD5pbWFnZS9qcGVnPC9kYzpmb3JtYXQ+CiA8L3JkZjpEZXNjcmlwdGlvbj4K CjwvcmRmOlJERj4KPC94OnhtcG1ldGE+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAog ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAK ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgIAo8P3hwYWNrZXQgZW5kPSd3Jz8+/+IMWElDQ19QUk9GSUxFAAEBAAAM SExpbm8CEAAAbW50clJHQiBYWVogB84AAgAJAAYAMQAAYWNzcE1TRlQAAAAASUVDIHNSR0IAAAAA AAAAAAAAAAAAAPbWAAEAAAAA0y1IUCAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAARY3BydAAAAVAAAAAzZGVzYwAAAYQAAABsd3RwdAAAAfAAAAAUYmtwdAAA AgQAAAAUclhZWgAAAhgAAAAUZ1hZWgAAAiwAAAAUYlhZWgAAAkAAAAAUZG1uZAAAAlQAAABwZG1k ZAAAAsQAAACIdnVlZAAAA0wAAACGdmlldwAAA9QAAAAkbHVtaQAAA/gAAAAUbWVhcwAABAwAAAAk dGVjaAAABDAAAAAMclRSQwAABDwAAAgMZ1RSQwAABDwAAAgMYlRSQwAABDwAAAgMdGV4dAAAAABD b3B5cmlnaHQgKGMpIDE5OTggSGV3bGV0dC1QYWNrYXJkIENvbXBhbnkAAGRlc2MAAAAAAAAAEnNS R0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAASc1JHQiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAADzUQABAAAAARbM WFlaIAAAAAAAAAAAAAAAAAAAAABYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UA ABjaWFlaIAAAAAAAACSgAAAPhAAAts9kZXNjAAAAAAAAABZJRUMgaHR0cDovL3d3dy5pZWMuY2gA AAAAAAAAAAAAABZJRUMgaHR0cDovL3d3dy5pZWMuY2gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAZGVzYwAAAAAAAAAuSUVDIDYxOTY2LTIuMSBEZWZhdWx0IFJH QiBjb2xvdXIgc3BhY2UgLSBzUkdCAAAAAAAAAAAAAAAuSUVDIDYxOTY2LTIuMSBEZWZhdWx0IFJH QiBjb2xvdXIgc3BhY2UgLSBzUkdCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGRlc2MAAAAAAAAALFJl ZmVyZW5jZSBWaWV3aW5nIENvbmRpdGlvbiBpbiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAACxSZWZl cmVuY2UgVmlld2luZyBDb25kaXRpb24gaW4gSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAB2aWV3AAAAAAATpP4AFF8uABDPFAAD7cwABBMLAANcngAAAAFYWVogAAAAAABMCVYA UAAAAFcf521lYXMAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAKPAAAAAnNpZyAAAAAAQ1JUIGN1 cnYAAAAAAAAEAAAAAAUACgAPABQAGQAeACMAKAAtADIANwA7AEAARQBKAE8AVABZAF4AYwBoAG0A cgB3AHwAgQCGAIsAkACVAJoAnwCkAKkArgCyALcAvADBAMYAywDQANUA2wDgAOUA6wDwAPYA+wEB AQcBDQETARkBHwElASsBMgE4AT4BRQFMAVIBWQFgAWcBbgF1AXwBgwGLAZIBmgGhAakBsQG5AcEB yQHRAdkB4QHpAfIB+gIDAgwCFAIdAiYCLwI4AkECSwJUAl0CZwJxAnoChAKOApgCogKsArYCwQLL AtUC4ALrAvUDAAMLAxYDIQMtAzgDQwNPA1oDZgNyA34DigOWA6IDrgO6A8cD0wPgA+wD+QQGBBME IAQtBDsESARVBGMEcQR+BIwEmgSoBLYExATTBOEE8AT+BQ0FHAUrBToFSQVYBWcFdwWGBZYFpgW1 BcUF1QXlBfYGBgYWBicGNwZIBlkGagZ7BowGnQavBsAG0QbjBvUHBwcZBysHPQdPB2EHdAeGB5kH rAe/B9IH5Qf4CAsIHwgyCEYIWghuCIIIlgiqCL4I0gjnCPsJEAklCToJTwlkCXkJjwmkCboJzwnl CfsKEQonCj0KVApqCoEKmAquCsUK3ArzCwsLIgs5C1ELaQuAC5gLsAvIC+EL+QwSDCoMQwxcDHUM jgynDMAM2QzzDQ0NJg1ADVoNdA2ODakNww3eDfgOEw4uDkkOZA5/DpsOtg7SDu4PCQ8lD0EPXg96 D5YPsw/PD+wQCRAmEEMQYRB+EJsQuRDXEPURExExEU8RbRGMEaoRyRHoEgcSJhJFEmQShBKjEsMS 4xMDEyMTQxNjE4MTpBPFE+UUBhQnFEkUahSLFK0UzhTwFRIVNBVWFXgVmxW9FeAWAxYmFkkWbBaP FrIW1hb6Fx0XQRdlF4kXrhfSF/cYGxhAGGUYihivGNUY+hkgGUUZaxmRGbcZ3RoEGioaURp3Gp4a xRrsGxQbOxtjG4obshvaHAIcKhxSHHscoxzMHPUdHh1HHXAdmR3DHeweFh5AHmoelB6+HukfEx8+ H2kflB+/H+ogFSBBIGwgmCDEIPAhHCFIIXUhoSHOIfsiJyJVIoIiryLdIwojOCNmI5QjwiPwJB8k TSR8JKsk2iUJJTglaCWXJccl9yYnJlcmhya3JugnGCdJJ3onqyfcKA0oPyhxKKIo1CkGKTgpaymd KdAqAio1KmgqmyrPKwIrNitpK50r0SwFLDksbiyiLNctDC1BLXYtqy3hLhYuTC6CLrcu7i8kL1ov kS/HL/4wNTBsMKQw2zESMUoxgjG6MfIyKjJjMpsy1DMNM0YzfzO4M/E0KzRlNJ402DUTNU01hzXC Nf02NzZyNq426TckN2A3nDfXOBQ4UDiMOMg5BTlCOX85vDn5OjY6dDqyOu87LTtrO6o76DwnPGU8 pDzjPSI9YT2hPeA+ID5gPqA+4D8hP2E/oj/iQCNAZECmQOdBKUFqQaxB7kIwQnJCtUL3QzpDfUPA RANER0SKRM5FEkVVRZpF3kYiRmdGq0bwRzVHe0fASAVIS0iRSNdJHUljSalJ8Eo3Sn1KxEsMS1NL mkviTCpMcky6TQJNSk2TTdxOJU5uTrdPAE9JT5NP3VAnUHFQu1EGUVBRm1HmUjFSfFLHUxNTX1Oq U/ZUQlSPVNtVKFV1VcJWD1ZcVqlW91dEV5JX4FgvWH1Yy1kaWWlZuFoHWlZaplr1W0VblVvlXDVc hlzWXSddeF3JXhpebF69Xw9fYV+zYAVgV2CqYPxhT2GiYfViSWKcYvBjQ2OXY+tkQGSUZOllPWWS ZedmPWaSZuhnPWeTZ+loP2iWaOxpQ2maafFqSGqfavdrT2una/9sV2yvbQhtYG25bhJua27Ebx5v eG/RcCtwhnDgcTpxlXHwcktypnMBc11zuHQUdHB0zHUodYV14XY+dpt2+HdWd7N4EXhueMx5KnmJ eed6RnqlewR7Y3vCfCF8gXzhfUF9oX4BfmJ+wn8jf4R/5YBHgKiBCoFrgc2CMIKSgvSDV4O6hB2E gITjhUeFq4YOhnKG14c7h5+IBIhpiM6JM4mZif6KZIrKizCLlov8jGOMyo0xjZiN/45mjs6PNo+e kAaQbpDWkT+RqJIRknqS45NNk7aUIJSKlPSVX5XJljSWn5cKl3WX4JhMmLiZJJmQmfyaaJrVm0Kb r5wcnImc951kndKeQJ6unx2fi5/6oGmg2KFHobaiJqKWowajdqPmpFakx6U4pammGqaLpv2nbqfg qFKoxKk3qamqHKqPqwKrdavprFys0K1ErbiuLa6hrxavi7AAsHWw6rFgsdayS7LCszizrrQltJy1 E7WKtgG2ebbwt2i34LhZuNG5SrnCuju6tbsuu6e8IbybvRW9j74KvoS+/796v/XAcMDswWfB48Jf wtvDWMPUxFHEzsVLxcjGRsbDx0HHv8g9yLzJOsm5yjjKt8s2y7bMNcy1zTXNtc42zrbPN8+40DnQ utE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp22vvbgNwF3IrdEN2W3hzeot8p 36/gNuC94UThzOJT4tvjY+Pr5HPk/OWE5g3mlucf56noMui86Ubp0Opb6uXrcOv77IbtEe2c7iju tO9A78zwWPDl8XLx//KM8xnzp/Q09ML1UPXe9m32+/eK+Bn4qPk4+cf6V/rn+3f8B/yY/Sn9uv5L /tz/bf///+4AJkFkb2JlAGSAAAAAAQMAFQQDBgoNAAAAAAAAAAAAAAAAAAAAAP/bAIQADAgICAkI DAkJDBELCgsRFQ8MDA8VGBMTFRMTGBEMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM DAENCwsNDg0QDg4QFA4ODhQUDg4ODhQRDAwMDAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwM DAwMDAwMDAwM/8IAEQgCNwGSAwEiAAIRAQMRAf/EAPgAAAIDAQEAAAAAAAAAAAAAAAADAQIEBQYB AAMBAQEBAAAAAAAAAAAAAAABAgMEBQYQAAICAQMDBQACAQQDAQEAAAECAAMREBIEICETMDEiFAVA QTJCIyQVMzQ1UCURAAEDAQQFCgQEBAUEAwAAAAEAEQIhMVESAxBBYXEiIDDwgZGhwdEyE7HhQgRA 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 F+kTWH4oYmGGOHozG3X3fonun//Z ------=_Part_095_0725482484.1242804871428 Content-Type: image/jpeg; name="=?iso-8859-1?Q?Cocons-2-3=2Ejpg?=" Content-Transfer-Encoding: Base64 Content-ID: <758EFCDAD96D5FC81402DB20D9135D7E@Emailing6> Content-Location: 758EFCDAD96D5FC81402DB20D9135D7E@Emailing6 /9j/4AAQSkZJRgABAgEASABIAAD/4SYERXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEAAAEaAAUA AAABAAAAYgEbAAUAAAABAAAAagEoAAMAAAABAAIAAAExAAIAAAAbAAAAcgEyAAIAAAAUAAAAjYdp AAQAAAABAAAApAAAANAAAABIAAAAAQAAAEgAAAABQWRvYmUgUGhvdG9zaG9wIENTIFdpbmRvd3MA MjAwODoxMDozMSAxNToxNzozNgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAABkqADAAQAAAAB AAABagAAAAAAAAAGAQMAAwAAAAEABgAAARoABQAAAAEAAAEeARsABQAAAAEAAAEmASgAAwAAAAEA AgAAAgEABAAAAAEAAAEuAgIABAAAAAEAACTOAAAAAAAAAEgAAAABAAAASAAAAAH/2P/gABBKRklG AAECAQBIAEgAAP/tAAxBZG9iZV9DTQAB/+4ADkFkb2JlAGSAAAAAAf/bAIQADAgICAkIDAkJDBEL CgsRFQ8MDA8VGBMTFRMTGBEMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAENCwsN Dg0QDg4QFA4ODhQUDg4ODhQRDAwMDAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM DAwM/8AAEQgAkACgAwEiAAIRAQMRAf/dAAQACv/EAT8AAAEFAQEBAQEBAAAAAAAAAAMAAQIEBQYH CAkKCwEAAQUBAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAABBAEDAgQCBQcGCAUDDDMBAAIRAwQh EjEFQVFhEyJxgTIGFJGhsUIjJBVSwWIzNHKC0UMHJZJT8OHxY3M1FqKygyZEk1RkRcKjdDYX0lXi ZfKzhMPTdePzRieUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm9jdHV2d3h5ent8fX5/cRAAICAQIE BAMEBQYHBwYFNQEAAhEDITESBEFRYXEiEwUygZEUobFCI8FS0fAzJGLhcoKSQ1MVY3M08SUGFqKy gwcmNcLSRJNUoxdkRVU2dGXi8rOEw9N14/NGlKSFtJXE1OT0pbXF1eX1VmZ2hpamtsbW5vYnN0dX Z3eHl6e3x//aAAwDAQACEQMRAD8A9VSSSSUpJJJJSkklAXUuY54e0srJD3AiGlv0w4/m7Pz0lM0l j9R+s/TsLHxsxj25eHkvc024zxaWsrDvXymMq3+tj4mx32xzH/oP+Es/RKhb9Zc3PxDldGocBj51 eK43t/RXMsecFzmur9S2r7Pk2Muu9nqsZV/wiSnp0lyjOs/WzNeXUdNtxqRXVY6tzWNt3vZsyqa7 cx1dFno3ZNd9LnMr/wCTsqu9n6xjeq+D0P6yHIxLszOtDK73ZOTWMhxJdazHufS39F6TsbHyqsrE Zh/zP2PI9am2i9JT1DntZBcQ0EgAkxqdGhZlf1m6JaK3V5LSLGte7cdhrY5l17LMhl3pvpY5mLb9 Jqzcz6jY2X6wfl2BtlpdUC1rzVQ5tm7Gq9be31Kb8rMyMHL2+vhet6Nf6Gv9JYd9TOlvc822ZFrH b9tbrAA3cctzNllbGXN9D9qZtdP6T6Fn6T1PRqSU3avrF0O0WOrzanCmj7VYd3FMb3Xf1a2uZ6v+ h9Wn1f56pCr+tPRrW5NrbH+hh0NyLrjVZtDC62pzfoep69VmPbXbj7PW9T9H/OMsQ+l/VbAxMS6v JYzJvzaRVn2BgrZadoqveyhvsx/tLWM9dtP876fqfzqPk/VzpmRi3Yzm2NbkYrcG14se55oYXFjH m51rbLGerb+nt33/AKWz9IkpE763/V9tZssyH17QS9jqbg9u37R6m6r0vU/Ruwslj/b9Nn/DUeq7 vrV0YXjHFljrDaKCBTbAP6Vtlm91bW+hjvx7qsy9v6LDtZsyvSUz9WulOsl9ZsqFL6BS4kti20Zu VY5/8/bdlZFdNl1l1tn817P53I9aTvq30R11l7sYGy2wWvO58bgXudtZv2Mqudff9qoZ+hy/Xv8A tNdvrWJKQWfXH6vtwn5lWUMhrKbr/SrBNhZjt9S79G/Z6ft/mvW9Jl2+v0/pq2OudGdX6tebRa30 nZDfSsbY51Ve4WXV11F9lrGOrsZ+jb9NVT9Uujel6LGW11Gj7K9jbbIspBc+qu/c93rej6lnpWWf pf0j0HJ+pnTL/Vd6lrH3WWWPILXfzozxbV76/wCad+2M1JTvAynWV0HoNfRmZO25+RZlXOusseXa kucWOexz3s+0bHbL72en9o2fza1UlP8A/9D1VJJYP1gGa7Oxmux8nL6W+q1j6cJwa85DtrKvte62 jdiuodfs3WfZWXf0z/tP6aU7dt1NLDZc9tbACS55DQA0F7jud+6xrnrMf9ZemjqNHTqRbkXXuc1x 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 AAAAAQAtAAAABgAAAAAAAThCSU0D+AAAAAAAcAAA/////////////////////////////wPoAAAA AP////////////////////////////8D6AAAAAD/////////////////////////////A+gAAAAA /////////////////////////////wPoAAA4QklNBAgAAAAAABAAAAABAAACQAAAAkAAAAAAOEJJ TQQeAAAAAAAEAAAAADhCSU0EGgAAAAADSQAAAAYAAAAAAAAAAAAAAWoAAAGSAAAACgBDAG8AYwBv AG4AcwAtADIALQAyAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAGSAAABagAAAAAA AAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAABAAAAABAAAAAAAAbnVsbAAAAAIAAAAGYm91 bmRzT2JqYwAAAAEAAAAAAABSY3QxAAAABAAAAABUb3AgbG9uZwAAAAAAAAAATGVmdGxvbmcAAAAA AAAAAEJ0b21sb25nAAABagAAAABSZ2h0bG9uZwAAAZIAAAAGc2xpY2VzVmxMcwAAAAFPYmpjAAAA AQAAAAAABXNsaWNlAAAAEgAAAAdzbGljZUlEbG9uZwAAAAAAAAAHZ3JvdXBJRGxvbmcAAAAAAAAA Bm9yaWdpbmVudW0AAAAMRVNsaWNlT3JpZ2luAAAADWF1dG9HZW5lcmF0ZWQAAAAAVHlwZWVudW0A AAAKRVNsaWNlVHlwZQAAAABJbWcgAAAABmJvdW5kc09iamMAAAABAAAAAAAAUmN0MQAAAAQAAAAA VG9wIGxvbmcAAAAAAAAAAExlZnRsb25nAAAAAAAAAABCdG9tbG9uZwAAAWoAAAAAUmdodGxvbmcA AAGSAAAAA3VybFRFWFQAAAABAAAAAAAAbnVsbFRFWFQAAAABAAAAAAAATXNnZVRFWFQAAAABAAAA AAAGYWx0VGFnVEVYVAAAAAEAAAAAAA5jZWxsVGV4dElzSFRNTGJvb2wBAAAACGNlbGxUZXh0VEVY VAAAAAEAAAAAAAlob3J6QWxpZ25lbnVtAAAAD0VTbGljZUhvcnpBbGlnbgAAAAdkZWZhdWx0AAAA CXZlcnRBbGlnbmVudW0AAAAPRVNsaWNlVmVydEFsaWduAAAAB2RlZmF1bHQAAAALYmdDb2xvclR5 cGVlbnVtAAAAEUVTbGljZUJHQ29sb3JUeXBlAAAAAE5vbmUAAAAJdG9wT3V0c2V0bG9uZwAAAAAA AAAKbGVmdE91dHNldGxvbmcAAAAAAAAADGJvdHRvbU91dHNldGxvbmcAAAAAAAAAC3JpZ2h0T3V0 c2V0bG9uZwAAAAAAOEJJTQQoAAAAAAAMAAAAAT/wAAAAAAAAOEJJTQQUAAAAAAAEAAAABjhCSU0E DAAAAAAk6gAAAAEAAACgAAAAkAAAAeAAAQ4AAAAkzgAYAAH/2P/gABBKRklGAAECAQBIAEgAAP/t AAxBZG9iZV9DTQAB/+4ADkFkb2JlAGSAAAAAAf/bAIQADAgICAkIDAkJDBELCgsRFQ8MDA8VGBMT FRMTGBEMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAENCwsNDg0QDg4QFA4ODhQU Dg4ODhQRDAwMDAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM/8AAEQgAkACg AwEiAAIRAQMRAf/dAAQACv/EAT8AAAEFAQEBAQEBAAAAAAAAAAMAAQIEBQYHCAkKCwEAAQUBAQEB AQEAAAAAAAAAAQACAwQFBgcICQoLEAABBAEDAgQCBQcGCAUDDDMBAAIRAwQhEjEFQVFhEyJxgTIG FJGhsUIjJBVSwWIzNHKC0UMHJZJT8OHxY3M1FqKygyZEk1RkRcKjdDYX0lXiZfKzhMPTdePzRieU pIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm9jdHV2d3h5ent8fX5/cRAAICAQIEBAMEBQYHBwYFNQEA AhEDITESBEFRYXEiEwUygZEUobFCI8FS0fAzJGLhcoKSQ1MVY3M08SUGFqKygwcmNcLSRJNUoxdk RVU2dGXi8rOEw9N14/NGlKSFtJXE1OT0pbXF1eX1VmZ2hpamtsbW5vYnN0dXZ3eHl6e3x//aAAwD AQACEQMRAD8A9VSSSSUpJJJJSkklAXUuY54e0srJD3AiGlv0w4/m7Pz0lM0lj9R+s/TsLHxsxj25 eHkvc024zxaWsrDvXymMq3+tj4mx32xzH/oP+Es/RKhb9Zc3PxDldGocBj51eK43t/RXMsecFzmu r9S2r7Pk2Muu9nqsZV/wiSnp0lyjOs/WzNeXUdNtxqRXVY6tzWNt3vZsyqa7cx1dFno3ZNd9LnMr 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 l4jgNifD+s4P3fcbqx83qFTw1xspr9J2/ZkNe17XN3Dc19Tv+p/MWwgPxA4z6trdSdHcEiPbu3fR Vpt6dXJi7Jx3Mt6iyrFe6wWtxqIMucfVqtuyzlMY13qf9x6bP3FcwD0jDZ6eK6HXOBe9xe+yx7tG uuut3232bf8ASP8A0dWz/BK23FAIPqWGBGryfmk3FAc13qWnbGheYMfvNQoqPmm7LCp2V07K8m9s OsvkOxt032fanbyHbfRbZY/2f6P/AEn6N63VH0qojY37gnA0kODTjdMax1LqnPoyBY11Bdj7JyXl +RbVtt3M3/u1u/8ABvUsR34XTrMf0ruoC239DZTlOdV6rTjljqrGv27X/pafUt3M2PfZkf4Oz01r +jVO7Y2fGBKXpV8bG6acDhHiVa7SHAEGQdQRwuL6r9WOl3Z1+QH3vfdc83zjUQ17ju9llnSMt9tH 5vrPu/64u1AAEDQIeRj0ZNLqMitt1L9H1vAc0xr7muQjKUflNIeGf9TcEEEsvdubvcfs2OYLfa1n /IW76P0V1n1d6fV03ouJg0h4roZtaLCS/lzvfNWL4/8AcepUr/qd02y51le2hhILamUYxa2APaDb jWWO/SN9X3v/AOD/AJn9EtjCxRh4lWK129tLQxrtrGaD6P6OhlVLP+t1oyySkKkbVQf/2ThCSU0E IQAAAAAAUwAAAAEBAAAADwBBAGQAbwBiAGUAIABQAGgAbwB0AG8AcwBoAG8AcAAAABIAQQBkAG8A YgBlACAAUABoAG8AdABvAHMAaABvAHAAIABDAFMAAAABADhCSU0EBgAAAAAAB//+AQEAAwEA/+EZ NGh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8APD94cGFja2V0IGJlZ2luPSfvu78nIGlkPSdX NU0wTXBDZWhpSHpyZVN6TlRjemtjOWQnPz4KPHg6eG1wbWV0YSB4bWxuczp4PSdhZG9iZTpuczpt ZXRhLycgeDp4bXB0az0nWE1QIHRvb2xraXQgMy4wLTI4LCBmcmFtZXdvcmsgMS42Jz4KPHJkZjpS REYgeG1sbnM6cmRmPSdodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMj JyB4bWxuczppWD0naHR0cDovL25zLmFkb2JlLmNvbS9pWC8xLjAvJz4KCiA8cmRmOkRlc2NyaXB0 aW9uIHJkZjphYm91dD0ndXVpZDo4NmJiZTExNS1hNzU2LTExZGQtOTYxYi1mZmE2ZDk4Zjc5ZmQn CiAgeG1sbnM6ZXhpZj0naHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8nPgogIDxleGlmOkNv bG9yU3BhY2U+MTwvZXhpZjpDb2xvclNwYWNlPgogIDxleGlmOlBpeGVsWERpbWVuc2lvbj40MDI8 L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogIDxleGlmOlBpeGVsWURpbWVuc2lvbj4zNjI8L2V4aWY6 UGl4ZWxZRGltZW5zaW9uPgogPC9yZGY6RGVzY3JpcHRpb24+CgogPHJkZjpEZXNjcmlwdGlvbiBy ZGY6YWJvdXQ9J3V1aWQ6ODZiYmUxMTUtYTc1Ni0xMWRkLTk2MWItZmZhNmQ5OGY3OWZkJwogIHht bG5zOnBkZj0naHR0cDovL25zLmFkb2JlLmNvbS9wZGYvMS4zLyc+CiA8L3JkZjpEZXNjcmlwdGlv bj4KCiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0ndXVpZDo4NmJiZTExNS1hNzU2LTExZGQt OTYxYi1mZmE2ZDk4Zjc5ZmQnCiAgeG1sbnM6cGhvdG9zaG9wPSdodHRwOi8vbnMuYWRvYmUuY29t L3Bob3Rvc2hvcC8xLjAvJz4KICA8cGhvdG9zaG9wOkhpc3Rvcnk+PC9waG90b3Nob3A6SGlzdG9y eT4KIDwvcmRmOkRlc2NyaXB0aW9uPgoKIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSd1dWlk Ojg2YmJlMTE1LWE3NTYtMTFkZC05NjFiLWZmYTZkOThmNzlmZCcKICB4bWxuczp0aWZmPSdodHRw Oi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyc+CiAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpP cmllbnRhdGlvbj4KICA8dGlmZjpYUmVzb2x1dGlvbj43Mi8xPC90aWZmOlhSZXNvbHV0aW9uPgog IDx0aWZmOllSZXNvbHV0aW9uPjcyLzE8L3RpZmY6WVJlc29sdXRpb24+CiAgPHRpZmY6UmVzb2x1 dGlvblVuaXQ+MjwvdGlmZjpSZXNvbHV0aW9uVW5pdD4KIDwvcmRmOkRlc2NyaXB0aW9uPgoKIDxy ZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSd1dWlkOjg2YmJlMTE1LWE3NTYtMTFkZC05NjFiLWZm YTZkOThmNzlmZCcKICB4bWxuczp4YXA9J2h0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8nPgog IDx4YXA6Q3JlYXRlRGF0ZT4yMDA4LTEwLTMxVDE1OjE3OjM2KzAxOjAwPC94YXA6Q3JlYXRlRGF0 ZT4KICA8eGFwOk1vZGlmeURhdGU+MjAwOC0xMC0zMVQxNToxNzozNiswMTowMDwveGFwOk1vZGlm eURhdGU+CiAgPHhhcDpNZXRhZGF0YURhdGU+MjAwOC0xMC0zMVQxNToxNzozNiswMTowMDwveGFw Ok1ldGFkYXRhRGF0ZT4KICA8eGFwOkNyZWF0b3JUb29sPkFkb2JlIFBob3Rvc2hvcCBDUyBXaW5k b3dzPC94YXA6Q3JlYXRvclRvb2w+CiA8L3JkZjpEZXNjcmlwdGlvbj4KCiA8cmRmOkRlc2NyaXB0 aW9uIHJkZjphYm91dD0ndXVpZDo4NmJiZTExNS1hNzU2LTExZGQtOTYxYi1mZmE2ZDk4Zjc5ZmQn CiAgeG1sbnM6c3RSZWY9J2h0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJj ZVJlZiMnCiAgeG1sbnM6eGFwTU09J2h0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8nPgog IDx4YXBNTTpEZXJpdmVkRnJvbSByZGY6cGFyc2VUeXBlPSdSZXNvdXJjZSc+CiAgIDxzdFJlZjpp bnN0YW5jZUlEPnV1aWQ6ODZiYmUxMTEtYTc1Ni0xMWRkLTk2MWItZmZhNmQ5OGY3OWZkPC9zdFJl ZjppbnN0YW5jZUlEPgogICA8c3RSZWY6ZG9jdW1lbnRJRD5hZG9iZTpkb2NpZDpwaG90b3Nob3A6 MDc3MGQzZjAtYTc1Ni0xMWRkLTk2MWItZmZhNmQ5OGY3OWZkPC9zdFJlZjpkb2N1bWVudElEPgog IDwveGFwTU06RGVyaXZlZEZyb20+CiAgPHhhcE1NOkRvY3VtZW50SUQ+YWRvYmU6ZG9jaWQ6cGhv dG9zaG9wOjg2YmJlMTE0LWE3NTYtMTFkZC05NjFiLWZmYTZkOThmNzlmZDwveGFwTU06RG9jdW1l bnRJRD4KIDwvcmRmOkRlc2NyaXB0aW9uPgoKIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSd1 dWlkOjg2YmJlMTE1LWE3NTYtMTFkZC05NjFiLWZmYTZkOThmNzlmZCcKICB4bWxuczpkYz0naHR0 cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8nPgogIDxkYzpmb3JtYXQ+aW1hZ2UvanBlZzwv ZGM6Zm9ybWF0PgogPC9yZGY6RGVzY3JpcHRpb24+Cgo8L3JkZjpSREY+CjwveDp4bXBtZXRhPgog ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAK ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0 IGVuZD0ndyc/Pv/iDFhJQ0NfUFJPRklMRQABAQAADEhMaW5vAhAAAG1udHJSR0IgWFlaIAfOAAIA CQAGADEAAGFjc3BNU0ZUAAAAAElFQyBzUkdCAAAAAAAAAAAAAAAAAAD21gABAAAAANMtSFAgIAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEWNwcnQAAAFQAAAA M2Rlc2MAAAGEAAAAbHd0cHQAAAHwAAAAFGJrcHQAAAIEAAAAFHJYWVoAAAIYAAAAFGdYWVoAAAIs AAAAFGJYWVoAAAJAAAAAFGRtbmQAAAJUAAAAcGRtZGQAAALEAAAAiHZ1ZWQAAANMAAAAhnZpZXcA AAPUAAAAJGx1bWkAAAP4AAAAFG1lYXMAAAQMAAAAJHRlY2gAAAQwAAAADHJUUkMAAAQ8AAAIDGdU UkMAAAQ8AAAIDGJUUkMAAAQ8AAAIDHRleHQAAAAAQ29weXJpZ2h0IChjKSAxOTk4IEhld2xldHQt UGFja2FyZCBDb21wYW55AABkZXNjAAAAAAAAABJzUkdCIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAA EnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAABYWVogAAAAAAAA81EAAQAAAAEWzFhZWiAAAAAAAAAAAAAAAAAAAAAAWFlaIAAA AAAAAG+iAAA49QAAA5BYWVogAAAAAAAAYpkAALeFAAAY2lhZWiAAAAAAAAAkoAAAD4QAALbPZGVz YwAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAAAAAAAAAAAAAWSUVDIGh0dHA6Ly93d3cu aWVjLmNoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGRlc2MA AAAAAAAALklFQyA2MTk2Ni0yLjEgRGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAA AAAAAAAALklFQyA2MTk2Ni0yLjEgRGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAA AAAAAAAAAAAAAAAAAAAAAABkZXNjAAAAAAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25kaXRpb24g aW4gSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAsUmVmZXJlbmNlIFZpZXdpbmcgQ29uZGl0aW9uIGlu IElFQzYxOTY2LTIuMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdmlldwAAAAAAE6T+ABRfLgAQ zxQAA+3MAAQTCwADXJ4AAAABWFlaIAAAAAAATAlWAFAAAABXH+dtZWFzAAAAAAAAAAEAAAAAAAAA AAAAAAAAAAAAAAACjwAAAAJzaWcgAAAAAENSVCBjdXJ2AAAAAAAABAAAAAAFAAoADwAUABkAHgAj ACgALQAyADcAOwBAAEUASgBPAFQAWQBeAGMAaABtAHIAdwB8AIEAhgCLAJAAlQCaAJ8ApACpAK4A sgC3ALwAwQDGAMsA0ADVANsA4ADlAOsA8AD2APsBAQEHAQ0BEwEZAR8BJQErATIBOAE+AUUBTAFS AVkBYAFnAW4BdQF8AYMBiwGSAZoBoQGpAbEBuQHBAckB0QHZAeEB6QHyAfoCAwIMAhQCHQImAi8C OAJBAksCVAJdAmcCcQJ6AoQCjgKYAqICrAK2AsECywLVAuAC6wL1AwADCwMWAyEDLQM4A0MDTwNa A2YDcgN+A4oDlgOiA64DugPHA9MD4APsA/kEBgQTBCAELQQ7BEgEVQRjBHEEfgSMBJoEqAS2BMQE 0wThBPAE/gUNBRwFKwU6BUkFWAVnBXcFhgWWBaYFtQXFBdUF5QX2BgYGFgYnBjcGSAZZBmoGewaM Bp0GrwbABtEG4wb1BwcHGQcrBz0HTwdhB3QHhgeZB6wHvwfSB+UH+AgLCB8IMghGCFoIbgiCCJYI qgi+CNII5wj7CRAJJQk6CU8JZAl5CY8JpAm6Cc8J5Qn7ChEKJwo9ClQKagqBCpgKrgrFCtwK8wsL CyILOQtRC2kLgAuYC7ALyAvhC/kMEgwqDEMMXAx1DI4MpwzADNkM8w0NDSYNQA1aDXQNjg2pDcMN 3g34DhMOLg5JDmQOfw6bDrYO0g7uDwkPJQ9BD14Peg+WD7MPzw/sEAkQJhBDEGEQfhCbELkQ1xD1 ERMRMRFPEW0RjBGqEckR6BIHEiYSRRJkEoQSoxLDEuMTAxMjE0MTYxODE6QTxRPlFAYUJxRJFGoU ixStFM4U8BUSFTQVVhV4FZsVvRXgFgMWJhZJFmwWjxayFtYW+hcdF0EXZReJF64X0hf3GBsYQBhl GIoYrxjVGPoZIBlFGWsZkRm3Gd0aBBoqGlEadxqeGsUa7BsUGzsbYxuKG7Ib2hwCHCocUhx7HKMc zBz1HR4dRx1wHZkdwx3sHhYeQB5qHpQevh7pHxMfPh9pH5Qfvx/qIBUgQSBsIJggxCDwIRwhSCF1 IaEhziH7IiciVSKCIq8i3SMKIzgjZiOUI8Ij8CQfJE0kfCSrJNolCSU4JWgllyXHJfcmJyZXJocm tyboJxgnSSd6J6sn3CgNKD8ocSiiKNQpBik4KWspnSnQKgIqNSpoKpsqzysCKzYraSudK9EsBSw5 LG4soizXLQwtQS12Last4S4WLkwugi63Lu4vJC9aL5Evxy/+MDUwbDCkMNsxEjFKMYIxujHyMioy YzKbMtQzDTNGM38zuDPxNCs0ZTSeNNg1EzVNNYc1wjX9Njc2cjauNuk3JDdgN5w31zgUOFA4jDjI OQU5Qjl/Obw5+To2OnQ6sjrvOy07azuqO+g8JzxlPKQ84z0iPWE9oT3gPiA+YD6gPuA/IT9hP6I/ 4kAjQGRApkDnQSlBakGsQe5CMEJyQrVC90M6Q31DwEQDREdEikTORRJFVUWaRd5GIkZnRqtG8Ec1 R3tHwEgFSEtIkUjXSR1JY0mpSfBKN0p9SsRLDEtTS5pL4kwqTHJMuk0CTUpNk03cTiVObk63TwBP SU+TT91QJ1BxULtRBlFQUZtR5lIxUnxSx1MTU19TqlP2VEJUj1TbVShVdVXCVg9WXFapVvdXRFeS V+BYL1h9WMtZGllpWbhaB1pWWqZa9VtFW5Vb5Vw1XIZc1l0nXXhdyV4aXmxevV8PX2Ffs2AFYFdg qmD8YU9homH1YklinGLwY0Njl2PrZEBklGTpZT1lkmXnZj1mkmboZz1nk2fpaD9olmjsaUNpmmnx akhqn2r3a09rp2v/bFdsr20IbWBtuW4SbmtuxG8eb3hv0XArcIZw4HE6cZVx8HJLcqZzAXNdc7h0 FHRwdMx1KHWFdeF2Pnabdvh3VnezeBF4bnjMeSp5iXnnekZ6pXsEe2N7wnwhfIF84X1BfaF+AX5i fsJ/I3+Ef+WAR4CogQqBa4HNgjCCkoL0g1eDuoQdhICE44VHhauGDoZyhteHO4efiASIaYjOiTOJ mYn+imSKyoswi5aL/IxjjMqNMY2Yjf+OZo7OjzaPnpAGkG6Q1pE/kaiSEZJ6kuOTTZO2lCCUipT0 lV+VyZY0lp+XCpd1l+CYTJi4mSSZkJn8mmia1ZtCm6+cHJyJnPedZJ3SnkCerp8dn4uf+qBpoNih R6G2oiailqMGo3aj5qRWpMelOKWpphqmi6b9p26n4KhSqMSpN6mpqhyqj6sCq3Wr6axcrNCtRK24 ri2uoa8Wr4uwALB1sOqxYLHWskuywrM4s660JbSctRO1irYBtnm28Ldot+C4WbjRuUq5wro7urW7 LrunvCG8m70VvY++Cr6Evv+/er/1wHDA7MFnwePCX8Lbw1jD1MRRxM7FS8XIxkbGw8dBx7/IPci8 yTrJuco4yrfLNsu2zDXMtc01zbXONs62zzfPuNA50LrRPNG+0j/SwdNE08bUSdTL1U7V0dZV1tjX XNfg2GTY6Nls2fHadtr724DcBdyK3RDdlt4c3qLfKd+v4DbgveFE4cziU+Lb42Pj6+Rz5PzlhOYN 5pbnH+ep6DLovOlG6dDqW+rl63Dr++yG7RHtnO4o7rTvQO/M8Fjw5fFy8f/yjPMZ86f0NPTC9VD1 3vZt9vv3ivgZ+Kj5OPnH+lf65/t3/Af8mP0p/br+S/7c/23////uACZBZG9iZQBkgAAAAAEDABUE AwYKDQAAAAAAAAAAAAAAAAAAAAD/2wCEABQRERoSGikYGCkzJyAnMyccHBwcJyIXFxcXFyIRDAwM DAwMEQwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwBFRoaIR0hIhgYIhQODg4UFA4ODg4UEQwM DAwMEREMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDP/CABEIAWoBkgMBIgACEQED EQH/xADcAAEAAwEBAQAAAAAAAAAAAAAAAgMEAQUGAQEBAQEBAAAAAAAAAAAAAAAAAQIDBBAAAQMD AwQCAwADAQAAAAAAAQARAhASAyAhMTBAEwQiMlBBFGBwMyMRAAADAwoEBQQCAwADAAAAAAABEfAh MRAgQVFhcYGRAhIwobHRQMHhIjJQ8UJiUnJggpLi8hMSAAAEAwcFAAAAAAAAAAAAAABAYXFQ8CEQ IGBwUYGxMDFBkcETAQACAgEDAwMEAwEBAQAAAAEAESExQRBRYSBxkTCBoUDwscFQ4fHRYHD/2gAM AwEDAhEDEQAAAfZAAAAAAAAAAAAAIknIFgDlRcjEsQE0IlrnQpuAAAAAAAAAAAADnQ5hN7PkPThi zHqPP1EabZGbt9p5umWo8+HqyMmT0rDyLtWg8LR6nDxdO+Bi56NJVyyk221WgAAAAAAAyGuObKep ThF+b0ImW/RYebdsGPTMAEenWTQTUi5TadVC1m0HUJHQAAAAAAAFXSxkoN0PM2FVW+8xaLxTdCsv jmsLo00l9ue0VymVxstMmifTH3R0rr1jHdOZjtvGK6+JlbKymGysq5fEQ70t7ikapZ7zoAGTXUQ8 3ZpMjfETz8NNdUDVmsmZrL5GeywQ7IV2AAAAAAAQ8w9av57PX0VXjwPan4HD6e75/RHsvK1mquwU 3AAKi1XQaIVxLYXWGay0QmAAzmjL4uE9fJjF3Kho0+cPf9D5Gw+ted6EdFCBPysONJw4JdW6vJT5 VGqr3YytXkzUc0+XGj2vnJx9Oya5QGbTEzXWiMgAAAGA58+iAAASup7NSae41KNluN+pd4Hs9uU/ m54bmXOdO952yzRRq1ZzjlZ9D0vnfQzqGLXn3mFWjPzxLVRZO0fV8bVHvPLL6g1kRJMtF16LzJy+ gzXzMhZT8vu844XS1ctqsNFubk76DLF3az05f1y6LqdNYcG7P154k4deTvOne8lZZqonprzyjOOT s2Ono5rKuuq+y7y50ro51K7ks+it1d+7yPj9eWrBBv0u8W97HPnG6fn7pNujyOZx5vJccbdFmPG6 bo67mNldnPcuxnmysjLO7LYX6Ze9iZ4bKMseP0fO78neS3jso9s0Id00R5ZOVFirnL+ZrevXttGr nLabO41V1VntFxWrN3nq9HOgnyyOeftwY4Xboyu3edu8+bexxphbHGI9srzJS7HKfY2yrI2Y6W2x t65z1aKs67DmUs8q/N0w7zvTnJztlllS5ssxbefNPPJnnJV3psvya7bKrq8dqaLK82aA649Xq6SJ dQzMtcuc/Pfpwa9dbexa0RiXU2U+fz950zbKGnnrkpz47z1a8m2nRk09Kln6nPH9PxekDpyd50sn TYzzlvFnKvTeOflufDRVKRzf5+rfbTTPNz3F2ObxxcdHp9vbK0lmTt+cU1W1YzdKMLvUq503bUim mufPN5I9jInqy3ct3zony3LDqy9Vs6I238zyK8Flffi7zusu86JA7xZ3Vm2OVOfRVi2yy6Gu21ae u559WbhuKPY6E5yL0+vvHElzlOcy5GeOU5V2Tqc50Sg7Gmu6vz+ePZLJ6Md/PVl2e3n07ltydEnK 95tx1x64DWXedHeEnzsV7KMrJa8+vXCFFubm7PtefTovhZ3l+Lfl47yWWdxqDqMvEeupVRXnfGvu Xew1NabG/Pbx77bU8jRo3Ofjw2+NeWuqhW30fB9Pk1ZY+c1uxcds94WC8rh9J4q5Qg6S46LK9NxK dMs8a4dnPRKjVRd7LqdHbOnH6GXjrLbbHMqWK55X1fl3fhraWbIxkndWa50v9bxdeO11tkZz0WO6 4sG9ufJ0/YeaeC25CIBeUPU9A831bbVjRqJ8dz3vBEoyOSjaLMuhiVEq42s97rKVcuuLtOPauvNO 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 fy1ho6OoFeu+iX0V9IHSQWSTVr6NSv8ADf/Z ------=_Part_095_0725482484.1242804871428-- From matthieu.fertre@kerlabs.com Tue May 26 03:10:31 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-2.2 required=5.0 tests=BAYES_00,J_CHICKENPOX_62, MIME_8BIT_HEADER autolearn=no version=3.3.0-rupdated Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n4Q8AVff132227 for <kdb@oss.sgi.com>; Tue, 26 May 2009 03:10:31 -0500 X-ASG-Debug-ID: 1243325441-4f1201d70000-sLlkUa X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi Received: from bohort.kerlabs.com (localhost [127.0.0.1]) by cuda.sgi.com (Spam Firewall) with ESMTP id 8F04E17C0350 for <kdb@oss.sgi.com>; Tue, 26 May 2009 01:10:42 -0700 (PDT) Received: from bohort.kerlabs.com (bohort.kerlabs.com [62.160.40.57]) by cuda.sgi.com with ESMTP id jl4yPPBPR1oir9Qq for <kdb@oss.sgi.com>; Tue, 26 May 2009 01:10:42 -0700 (PDT) Received: from localhost.localdomain (arlesienne.kerlabs.com [::ffff:10.3.0.18]) (AUTH: LOGIN matthieu, SSL: TLSv1/SSLv3,256bits,AES256-SHA) by bohort.kerlabs.com with esmtp; Tue, 26 May 2009 10:10:19 +0200 id 0000000000968250.000000004A1BA3EB.000006F2 From: =?utf-8?q?Matthieu=20Fertr=C3=A9?= <matthieu.fertre@kerlabs.com> To: kdb@oss.sgi.com Cc: =?utf-8?q?Matthieu=20Fertr=C3=A9?= <matthieu.fertre@kerlabs.com> X-ASG-Orig-Subj: [PATCH] Add support for USB Keyboard attached to UHCI in KDB Subject: [PATCH] Add support for USB Keyboard attached to UHCI in KDB Date: Tue, 26 May 2009 10:10:38 +0200 Message-Id: <1243325438-11715-1-git-send-email-matthieu.fertre@kerlabs.com> X-Mailer: git-send-email 1.5.6.3 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: bohort.kerlabs.com[62.160.40.57] X-Barracuda-Start-Time: 1243325443 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com X-Barracuda-Spam-Score: -1.52 X-Barracuda-Spam-Status: No, SCORE=-1.52 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests=BSF_RULE7568M X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.1.26769 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.50 BSF_RULE7568M Custom Rule 7568M X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean Building as a module has not been tested. Update of patch from Konstantin Baydarov <kbaidarov@ru.mvista.com>. The patch was originally posted here: http://oss.sgi.com/archives/kdb/2008-02/msg00006.html Signed-off-by: Matthieu Fertré <matthieu.fertre@kerlabs.com> --- arch/x86/Kconfig.debug | 4 +- arch/x86/kdb/kdba_io.c | 89 ++++++++++++++--- drivers/hid/usbhid/hid-core.c | 13 +++- drivers/usb/core/hcd.c | 60 +++++++++++- drivers/usb/core/hcd.h | 6 + drivers/usb/host/uhci-hcd.c | 218 +++++++++++++++++++++++++++++++++++++++++ drivers/usb/host/uhci-q.c | 164 +++++++++++++++++++++++++++++++ 7 files changed, 535 insertions(+), 19 deletions(-) diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index c9216a7..51ed359 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -342,8 +342,8 @@ config KDB_CONTINUE_CATASTROPHIC setting to 2. config KDB_USB - bool "Support for USB Keyboard in KDB (OHCI and/or EHCI only)" - depends on KDB && (USB_OHCI_HCD || USB_EHCI_HCD) + bool "Support for USB Keyboard in KDB" + depends on KDB && (USB_OHCI_HCD || USB_EHCI_HCD || USB_UHCI_HCD) help If you want to use kdb from USB keyboards then say Y here. If you say N then kdb can only be used from a PC (AT) keyboard or a serial diff --git a/arch/x86/kdb/kdba_io.c b/arch/x86/kdb/kdba_io.c index 087d468..e754dd4 100644 --- a/arch/x86/kdb/kdba_io.c +++ b/arch/x86/kdb/kdba_io.c @@ -30,9 +30,8 @@ #ifdef CONFIG_KDB_USB -/* support up to 8 USB keyboards (probably excessive, but...) */ -#define KDB_USB_NUM_KEYBOARDS 8 struct kdb_usb_kbd_info kdb_usb_kbds[KDB_USB_NUM_KEYBOARDS]; +EXPORT_SYMBOL(kdb_usb_kbds); extern int kdb_no_usb; @@ -60,7 +59,12 @@ static unsigned char kdb_usb_keycode[256] = { * Attach a USB keyboard to kdb. */ int -kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func) +kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, + void *poll_func, void *compl_func, + kdb_hc_keyboard_attach_t kdb_hc_keyboard_attach, + kdb_hc_keyboard_detach_t kdb_hc_keyboard_detach, + unsigned int bufsize, + struct urb *hid_urb) { int i; int rc = -1; @@ -83,6 +87,16 @@ kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func) kdb_usb_kbds[i].buffer = buffer; kdb_usb_kbds[i].poll_func = poll_func; + kdb_usb_kbds[i].kdb_hc_urb_complete = compl_func; + kdb_usb_kbds[i].kdb_hc_keyboard_attach = kdb_hc_keyboard_attach; + kdb_usb_kbds[i].kdb_hc_keyboard_detach = kdb_hc_keyboard_detach; + + /* USB Host Controller specific Keyboadr attach callback. + * Currently only UHCI has this callback. + */ + if (kdb_usb_kbds[i].kdb_hc_keyboard_attach) + kdb_usb_kbds[i].kdb_hc_keyboard_attach(i, bufsize); + rc = 0; /* success */ break; @@ -112,14 +126,23 @@ kdb_usb_keyboard_detach(struct urb *urb) */ for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { - if (kdb_usb_kbds[i].urb != urb) + if ((kdb_usb_kbds[i].urb != urb) && + (kdb_usb_kbds[i].hid_urb != urb)) continue; /* found it, clear the index */ + + /* USB Host Controller specific Keyboard detach callback. + * Currently only UHCI has this callback. + */ + if (kdb_usb_kbds[i].kdb_hc_keyboard_detach) + kdb_usb_kbds[i].kdb_hc_keyboard_detach(urb, i); + kdb_usb_kbds[i].urb = NULL; kdb_usb_kbds[i].buffer = NULL; kdb_usb_kbds[i].poll_func = NULL; kdb_usb_kbds[i].caps_lock = 0; + kdb_usb_kbds[i].hid_urb = NULL; rc = 0; /* success */ @@ -142,6 +165,9 @@ get_usb_char(void) int ret; unsigned char keycode, spec; extern u_short plain_map[], shift_map[], ctrl_map[]; + int ret_key = -1, j, max; + + ret = 1; if (kdb_no_usb) return -1; @@ -168,15 +194,24 @@ get_usb_char(void) if (ret < 0) /* error or no characters, try the next kbd */ continue; + /* If 2 keys was pressed simultaneously, + * both keycodes will be in buffer. + * Last pressed key will be last non + * zero byte. + */ + for (j=0; j<4; j++){ + if (!kdb_usb_kbds[i].buffer[2+j]) + break; + } + /* Last pressed key */ + max = j + 1; + spec = kdb_usb_kbds[i].buffer[0]; keycode = kdb_usb_kbds[i].buffer[2]; kdb_usb_kbds[i].buffer[0] = (char)0; kdb_usb_kbds[i].buffer[2] = (char)0; - if(kdb_usb_kbds[i].buffer[3]) { - kdb_usb_kbds[i].buffer[3] = (char)0; - continue; - } + ret_key = -1; /* A normal key is pressed, decode it */ if(keycode) @@ -188,10 +223,12 @@ get_usb_char(void) { case 0x2: case 0x20: /* Shift */ - return shift_map[keycode]; + ret_key = shift_map[keycode]; + break; case 0x1: case 0x10: /* Ctrl */ - return ctrl_map[keycode]; + ret_key = ctrl_map[keycode]; + break; case 0x4: case 0x40: /* Alt */ break; @@ -200,28 +237,50 @@ get_usb_char(void) switch(keycode) { case 0x1C: /* Enter */ - return 13; + ret_key = 13; + break; case 0x3A: /* Capslock */ kdb_usb_kbds[i].caps_lock = !(kdb_usb_kbds[i].caps_lock); break; case 0x0E: /* Backspace */ - return 8; + ret_key = 8; + break; case 0x0F: /* TAB */ - return 9; + ret_key = 9; + break; case 0x77: /* Pause */ break ; default: if(!kdb_usb_kbds[i].caps_lock) { - return plain_map[keycode]; + ret_key = plain_map[keycode]; } else { - return shift_map[keycode]; + ret_key = shift_map[keycode]; } } } + + if (ret_key != 1) { + /* Key was pressed, return keycode */ + + /* Clear buffer before urb resending */ + if (kdb_usb_kbds[i].buffer) + for(j=0; j<8; j++) + kdb_usb_kbds[i].buffer[j] = (char)0; + + /* USB Host Controller specific Urb complete callback. + * Currently only UHCI has this callback. + */ + if (kdb_usb_kbds[i].kdb_hc_urb_complete) + (*kdb_usb_kbds[i].kdb_hc_urb_complete)((struct urb *)kdb_usb_kbds[i].urb); + + return ret_key; + } } + + /* no chars were returned from any of the USB keyboards */ return -1; diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 8c55733..8c342d1 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -1195,9 +1195,20 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) int ret; struct usbhid_device *usbhid = hid->driver_data; extern void *usb_hcd_get_kdb_poll_func(struct usb_device *udev); + extern void * usb_hcd_get_kdb_completion_func(struct usb_device *udev); + extern int usb_hcd_check_uhci(struct usb_device *udev); + extern kdb_hc_keyboard_attach_t + usb_hcd_get_hc_keyboard_attach(struct usb_device *udev); + extern kdb_hc_keyboard_detach_t + usb_hcd_get_hc_keyboard_detach(struct usb_device *udev); ret = kdb_usb_keyboard_attach(usbhid->urbin, usbhid->inbuf, - usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf))); + usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf)), + usb_hcd_get_kdb_completion_func(interface_to_usbdev(intf)), + usb_hcd_get_hc_keyboard_attach(interface_to_usbdev(intf)), + usb_hcd_get_hc_keyboard_detach(interface_to_usbdev(intf)), + usbhid->bufsize, + NULL); if (ret == -1) printk(": FAILED to register keyboard (%s) " diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 5af2a35..f9d7c97 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -38,6 +38,9 @@ #include <asm/unaligned.h> #include <linux/platform_device.h> #include <linux/workqueue.h> +#ifdef CONFIG_KDB_USB +#include <linux/kdb.h> +#endif #include <linux/usb.h> @@ -2023,7 +2026,7 @@ EXPORT_SYMBOL_GPL(usb_hcd_platform_shutdown); void * usb_hcd_get_kdb_poll_func(struct usb_device *udev) { - struct usb_hcd *hcd = bus_to_hcd(udev->bus); + struct usb_hcd *hcd = bus_to_hcd(udev->bus); if (hcd && hcd->driver) return (void *)(hcd->driver->kdb_poll_char); @@ -2031,8 +2034,63 @@ usb_hcd_get_kdb_poll_func(struct usb_device *udev) return NULL; } EXPORT_SYMBOL_GPL (usb_hcd_get_kdb_poll_func); + +void * +usb_hcd_get_kdb_completion_func(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + if (hcd && hcd->driver) + return (void *)(hcd->driver->kdb_completion); + + return NULL; +} +EXPORT_SYMBOL_GPL (usb_hcd_get_kdb_completion_func); + +int +usb_hcd_check_uhci(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + if (hcd && hcd->driver){ + if (!(strcmp(hcd->driver->description, "uhci_hcd"))) + return 1; + } + + return 0; +} +EXPORT_SYMBOL_GPL (usb_hcd_check_uhci); + +kdb_hc_keyboard_attach_t +usb_hcd_get_hc_keyboard_attach(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + if (hcd && hcd->driver){ + return hcd->driver->kdb_hc_keyboard_attach; + } + + return 0; +} +EXPORT_SYMBOL_GPL (usb_hcd_get_hc_keyboard_attach); + +kdb_hc_keyboard_detach_t +usb_hcd_get_hc_keyboard_detach(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + if (hcd && hcd->driver){ + return hcd->driver->kdb_hc_keyboard_detach; + } + + return 0; +} +EXPORT_SYMBOL_GPL (usb_hcd_get_hc_keyboard_detach); + + #endif /* CONFIG_KDB_USB */ + /*-------------------------------------------------------------------------*/ #if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE) diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index d2e9e35..65b4e96 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -22,6 +22,9 @@ #ifdef __KERNEL__ #include <linux/rwsem.h> +#ifdef CONFIG_KDB_USB +#include <linux/kdb.h> +#endif #define MAX_TOPO_LEVEL 6 @@ -222,6 +225,9 @@ struct hc_driver { #ifdef CONFIG_KDB_USB /* KDB poll function for this HC */ int (*kdb_poll_char)(struct urb *urb); + void (*kdb_completion)(struct urb *urb); + kdb_hc_keyboard_attach_t kdb_hc_keyboard_attach; + kdb_hc_keyboard_detach_t kdb_hc_keyboard_detach; #endif /* CONFIG_KDB_USB */ }; diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index cf5e4cf..3e52775 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -50,6 +50,11 @@ #include "uhci-hcd.h" #include "pci-quirks.h" +#ifdef CONFIG_KDB_USB +#include <linux/kdb.h> +#include <linux/kdbprivate.h> +#endif + /* * Version Information */ @@ -461,6 +466,213 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) return IRQ_HANDLED; } +#ifdef CONFIG_KDB_USB +/* Unlink KDB QH from hardware and software scheduler */ +static void kdb_unlink_uhci_qh(struct urb *urb, struct uhci_qh *qh) +{ + unsigned long flags; + struct uhci_hcd *uhci; + + uhci = (struct uhci_hcd *) hcd_to_uhci(bus_to_hcd(urb->dev->bus)); + + spin_lock_irqsave(&uhci->lock, flags); + unlink_interrupt(NULL, qh); + list_del(&(qh->node)); + spin_unlock_irqrestore(&uhci->lock, flags); + +} + +static int uhci_kdb_poll_char(struct urb *urb) +{ + if (!urb) /* can happen if no keyboard attached */ + return -1; + + return uhci_check_kdb_uhci_qh(kdb_uhci_keyboard_get_qh(urb)); +} + +/* Only 1 UHCI Keyboard supported */ +static inline void kdb_usb_fill_int_urb (struct urb *urb, + struct usb_device *dev, + unsigned int pipe, + void *transfer_buffer, + int buffer_length, + usb_complete_t complete_fn, + void *context, + int interval) +{ + urb->dev = dev; + urb->pipe = pipe; + urb->transfer_buffer = transfer_buffer; + urb->transfer_buffer_length = buffer_length; + urb->complete = complete_fn; + urb->context = context; + urb->interval = interval; + urb->start_frame = -1; +} + +static int kdb_uhci_keyboard_attach(int i, unsigned int usbhid_bufsize) +{ + struct urb *kdb_urb; + unsigned char *kdb_buffer; + dma_addr_t uhci_inbuf_dma; + struct urb *hid_inurb = kdb_usb_kbds[i].urb; + int ret = -1; + + kdb_usb_kbds[i].hid_urb = hid_inurb; + + kdb_urb = NULL; + kdb_buffer = NULL; + if (!(kdb_buffer = usb_buffer_alloc(hid_inurb->dev, + usbhid_bufsize, GFP_ATOMIC, + &uhci_inbuf_dma))) + goto out; + + if (!(kdb_urb = usb_alloc_urb(0, GFP_KERNEL))) + goto out; + + kdb_usb_fill_int_urb(kdb_urb, + hid_inurb->dev, + hid_inurb->pipe, + kdb_buffer, + hid_inurb->transfer_buffer_length, + hid_inurb->complete, + hid_inurb->context, + hid_inurb->interval + ); + + (kdb_urb)->transfer_dma = uhci_inbuf_dma; + (kdb_urb)->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + kdb_usb_kbds[i].urb = kdb_urb; + kdb_usb_kbds[i].buffer = kdb_buffer; + + if (usb_submit_urb(kdb_urb, GFP_ATOMIC)){ + kdb_usb_keyboard_detach(hid_inurb); + goto out; + } + /* Remove KDB special URB from endpoin queue to + * prevent hang during hid_disconnect(). + */ + list_del(&(kdb_urb->urb_list)); + + ret = 0; + return ret; +out: + /* Some Error Cleanup */ + ret = -1; + printk("KDB: Error, UHCI Keyboard HID won't work!\n"); + + if (kdb_buffer) + usb_buffer_free(hid_inurb->dev, + usbhid_bufsize, kdb_buffer, + uhci_inbuf_dma); + + if (kdb_urb) + usb_free_urb(kdb_urb); + + return ret; +} + +static int kdb_uhci_keyboard_detach(struct urb *urb, int i) +{ + int ret; + + if (kdb_usb_kbds[i].qh && (kdb_usb_kbds[i].hid_urb == urb)) { + /* UHCI keyboard */ + kdb_unlink_uhci_qh(kdb_usb_kbds[i].urb, kdb_usb_kbds[i].qh); + ret = 0; + } + ret = -1; + + return ret; +} + +/* Check if URB is managed by KDB code */ +static int kdb_uhci_keyboard_urb(struct urb *urb) +{ + int i; + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].urb == urb) + return i; + } + return -1; +} + +/* Check if UHCI QH is managed by KDB code */ +static int kdb_uhci_keyboard_check_uhci_qh(struct uhci_qh *qh) +{ + int i; + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh) + return i; + } + return -1; +} + +/* Set UHCI QH using URB pointer */ +static int kdb_uhci_keyboard_set_qh(struct urb *urb, struct uhci_qh *qh) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1) + kdb_usb_kbds[i].qh = qh; + + return 0; +} + +/* Get UHCI QH using URB pointer */ +static struct uhci_qh *kdb_uhci_keyboard_get_qh(struct urb *urb) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1) + return kdb_usb_kbds[i].qh; + + return NULL; +} + +/* Set UHCI hid_event using URB pointer */ +static int kdb_uhci_keyboard_set_hid_event(struct urb *urb, int hid_event) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1) + kdb_usb_kbds[i].kdb_hid_event = hid_event; + + return 0; +} +/* Get UHCI hid_event using URB pointer */ +static int kdb_uhci_keyboard_get_hid_event(struct urb *urb) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1) + return kdb_usb_kbds[i].kdb_hid_event; + + return 0; +} + +/* Set UHCI hid_event using UHCI QH pointer */ +static int kdb_uhci_keyboard_set_hid_event_qh(struct uhci_qh *qh, int hid_event) +{ + int i; + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh){ + kdb_usb_kbds[i].kdb_hid_event = hid_event; + return i; + } + } + return -1; +} +#endif + /* * Store the current frame number in uhci->frame_number if the controller * is runnning. Expand from 11 bits (of which we use only 10) to a @@ -921,6 +1133,12 @@ static const struct hc_driver uhci_driver = { .hub_status_data = uhci_hub_status_data, .hub_control = uhci_hub_control, +#ifdef CONFIG_KDB_USB + .kdb_poll_char = uhci_kdb_poll_char, + .kdb_completion = kdb_uhci_urb_complete, + .kdb_hc_keyboard_attach = kdb_uhci_keyboard_attach, + .kdb_hc_keyboard_detach = kdb_uhci_keyboard_detach, +#endif }; static const struct pci_device_id uhci_pci_ids[] = { { diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 3e5807d..13def8f 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -25,6 +25,17 @@ * games with the FSBR code to make sure we get the correct order in all * the cases. I don't think it's worth the effort */ +#ifdef CONFIG_KDB_USB +/* KDB HID QH, managed by KDB code */ +static int kdb_uhci_keyboard_check_uhci_qh(struct uhci_qh *qh); +static int kdb_uhci_keyboard_set_qh(struct urb *urb, struct uhci_qh *qh); +static struct uhci_qh *kdb_uhci_keyboard_get_qh(struct urb *urb); +static int kdb_uhci_keyboard_set_hid_event(struct urb *urb, int hid_event); +static int kdb_uhci_keyboard_get_hid_event(struct urb *urb); +static int kdb_uhci_keyboard_set_hid_event_qh(struct uhci_qh *qh, int hid_event); +static int kdb_uhci_keyboard_urb(struct urb *urb); +#endif + static void uhci_set_next_interrupt(struct uhci_hcd *uhci) { if (uhci->is_stopped) @@ -288,6 +299,58 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, return qh; } +#ifdef CONFIG_KDB_USB +/* + * Same as uhci_alloc_qh execpt it doesn't change to hep->hcpriv + */ +static struct uhci_qh *kdb_uhci_alloc_qh(struct uhci_hcd *uhci, + struct usb_device *udev, struct usb_host_endpoint *hep) +{ + dma_addr_t dma_handle; + struct uhci_qh *qh; + + qh = dma_pool_alloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle); + if (!qh) + return NULL; + + memset(qh, 0, sizeof(*qh)); + qh->dma_handle = dma_handle; + + qh->element = UHCI_PTR_TERM; + qh->link = UHCI_PTR_TERM; + + INIT_LIST_HEAD(&qh->queue); + INIT_LIST_HEAD(&qh->node); + + if (udev) { /* Normal QH */ + qh->type = hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + if (qh->type != USB_ENDPOINT_XFER_ISOC) { + qh->dummy_td = uhci_alloc_td(uhci); + if (!qh->dummy_td) { + dma_pool_free(uhci->qh_pool, qh, dma_handle); + return NULL; + } + } + qh->state = QH_STATE_IDLE; + qh->hep = hep; + qh->udev = udev; + + if (qh->type == USB_ENDPOINT_XFER_INT || + qh->type == USB_ENDPOINT_XFER_ISOC) + qh->load = usb_calc_bus_time(udev->speed, + usb_endpoint_dir_in(&hep->desc), + qh->type == USB_ENDPOINT_XFER_ISOC, + le16_to_cpu(hep->desc.wMaxPacketSize)) + / 1000 + 1; + + } else { /* Skeleton QH */ + qh->state = QH_STATE_ACTIVE; + qh->type = -1; + } + return qh; +} +#endif + static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) { WARN_ON(qh->state != QH_STATE_IDLE && qh->udev); @@ -1394,6 +1457,21 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, if (!urbp) goto done; +#ifdef CONFIG_KDB_USB + /* Always allocate new QH for KDB URB. + * KDB HQ will be managed by KDB poll code not by + * UHCI HCD Driver. + */ + if (kdb_uhci_keyboard_urb(urb) != -1){ + /* KDB urb will be enqued only once */ + kdb_uhci_keyboard_set_qh(urb, NULL); + qh = kdb_uhci_alloc_qh(uhci, urb->dev, urb->ep); + if (!qh) + goto err_no_qh; + kdb_uhci_keyboard_set_qh(urb, qh); + } else +#endif + if (urb->ep->hcpriv) qh = urb->ep->hcpriv; else { @@ -1642,6 +1720,14 @@ static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh) int ret = 1; unsigned status; +#ifdef CONFIG_KDB_USB + /* Don't manage KDB QH */ + if(kdb_uhci_keyboard_check_uhci_qh(qh) != -1){ + ret = 0; + goto done; + } +#endif + if (qh->type == USB_ENDPOINT_XFER_ISOC) goto done; @@ -1734,6 +1820,11 @@ rescan: uhci->next_qh = list_entry(qh->node.next, struct uhci_qh, node); +#ifdef CONFIG_KDB_USB + /* Don't manage KDB QH */ + if(kdb_uhci_keyboard_check_uhci_qh(qh) != -1) + continue; +#endif if (uhci_advance_check(uhci, qh)) { uhci_scan_qh(uhci, qh); if (qh->state == QH_STATE_ACTIVE) { @@ -1760,3 +1851,76 @@ rescan: else uhci_set_next_interrupt(uhci); } + +#ifdef CONFIG_KDB_USB +/* + * Activate KDB UHCI QH, called by KDB poll code. + */ +static void kdb_activate_uhci_qh(struct uhci_qh *qh) +{ + struct urb_priv *urbp; + struct uhci_td *td; + __le32 status, token; + + urbp = list_entry(qh->queue.next, struct urb_priv, node); + + list_for_each_entry(td, &urbp->td_list, list){ + status = td->status; + token = td->token; + barrier(); + /* Clear Status and ActLen */ + status &= cpu_to_le32(0xff000000); + /* Make TD Active */ + status |= cpu_to_le32(TD_CTRL_ACTIVE); + /* Clear TD Interrupt */ + status &= cpu_to_le32(~TD_CTRL_IOC); + /* Toggle Data Sycronization Bit */ + if (token & cpu_to_le32(TD_TOKEN_TOGGLE)) + token &= cpu_to_le32(~TD_TOKEN_TOGGLE); + else + token |= cpu_to_le32(TD_TOKEN_TOGGLE); + + td->token = token; + td->status = status; + barrier(); + } + /* Activate KDB UHCI Keyboard HID QH */ + td = list_entry(urbp->td_list.next, struct uhci_td, list); + qh->element = LINK_TO_TD(td); + barrier(); +} + +/* + * Called when KDB finishes process key press/release event. + */ +static void +kdb_uhci_urb_complete (struct urb *urb) +{ + if (!kdb_uhci_keyboard_get_hid_event(urb)) + return; + + /* Activate KDB TD */ + kdb_activate_uhci_qh(kdb_uhci_keyboard_get_qh(urb)); + kdb_uhci_keyboard_set_hid_event(urb, 0); +} + +/* + * Check if state of KDB URB changed (key was pressed/released). + */ +static int uhci_check_kdb_uhci_qh(struct uhci_qh *qh) +{ + struct urb_priv *urbp = NULL; + struct uhci_td *td; + unsigned status; + + urbp = list_entry(qh->queue.next, struct urb_priv, node); + td = list_entry(urbp->td_list.next, struct uhci_td, list); + status = td_status(td); + if (!(status & TD_CTRL_ACTIVE)){ + /* We're okay, the queue has advanced */ + kdb_uhci_keyboard_set_hid_event_qh(qh, 1); + return 0; + } + return -1; +} +#endif -- 1.5.6.3 From matthieu.fertre@kerlabs.com Tue May 26 03:32:30 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-2.2 required=5.0 tests=BAYES_00,J_CHICKENPOX_62, MIME_8BIT_HEADER autolearn=no version=3.3.0-rupdated Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n4Q8WTW3132760 for <kdb@oss.sgi.com>; Tue, 26 May 2009 03:32:29 -0500 X-ASG-Debug-ID: 1243327108-0939018e0000-sLlkUa X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi Received: from bohort.kerlabs.com (localhost [127.0.0.1]) by cuda.sgi.com (Spam Firewall) with ESMTP id 2604FF540E5 for <kdb@oss.sgi.com>; Tue, 26 May 2009 01:38:28 -0700 (PDT) Received: from bohort.kerlabs.com (bohort.kerlabs.com [62.160.40.57]) by cuda.sgi.com with ESMTP id UHDT7iFug8Xk8aC6 for <kdb@oss.sgi.com>; Tue, 26 May 2009 01:38:28 -0700 (PDT) Received: from localhost.localdomain (arlesienne.kerlabs.com [::ffff:10.3.0.18]) (AUTH: LOGIN matthieu, SSL: TLSv1/SSLv3,256bits,AES256-SHA) by bohort.kerlabs.com with esmtp; Tue, 26 May 2009 10:32:19 +0200 id 0000000000968252.000000004A1BA913.00000953 From: =?utf-8?q?Matthieu=20Fertr=C3=A9?= <matthieu.fertre@kerlabs.com> To: kdb@oss.sgi.com Cc: =?utf-8?q?Matthieu=20Fertr=C3=A9?= <matthieu.fertre@kerlabs.com> X-ASG-Orig-Subj: [PATCH] Add support for USB Keyboard attached to UHCI in KDB Subject: [PATCH] Add support for USB Keyboard attached to UHCI in KDB Date: Tue, 26 May 2009 10:32:38 +0200 Message-Id: <1243326758-13746-1-git-send-email-matthieu.fertre@kerlabs.com> X-Mailer: git-send-email 1.5.6.3 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: bohort.kerlabs.com[62.160.40.57] X-Barracuda-Start-Time: 1243327111 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com X-Barracuda-Spam-Score: -1.52 X-Barracuda-Spam-Status: No, SCORE=-1.52 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests=BSF_RULE7568M X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.1.26772 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.50 BSF_RULE7568M Custom Rule 7568M X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean Hi, here is an update of patch from Konstantin Baydarov <kbaidarov@ru.mvista.com>. The patch was originally posted here: http://oss.sgi.com/archives/kdb/2008-02/msg00006.html This version has been tested over kdb-v4.4-2.6.30-rc2-*-2.patch and works for me :-) I have not testing building it as a module nor with keyboard attached with EHCI or OHCI, thus it may be broken by the patch. I had previously tried to port the UHCI part of the patch sent here: http://oss.sgi.com/archives/kdb/2009-05/msg00010.html It was realy easy to port but did not work: #ifdef CONFIG_KDB_USB int uhci_kdb_poll_char(struct urb *urb) { struct uhci_hcd *uhci; struct urb_priv *urbp; struct uhci_qh *qh; /* just to make sure */ if (!urb || !urb->dev || !urb->dev->bus || !urb->hcpriv) return -1; urb->hcpriv is always NULL. I did not manage to find why (I don't know at all how USB is working). The port of patch from Konstatin Baydarov is far more intrusive but works. I hope it will help other KDB users. Regards, Matthieu Fertré Signed-off-by: Matthieu Fertré <matthieu.fertre@kerlabs.com> --- arch/x86/Kconfig.debug | 4 +- arch/x86/kdb/kdba_io.c | 89 ++++++++++++++--- drivers/hid/usbhid/hid-core.c | 13 +++- drivers/usb/core/hcd.c | 60 +++++++++++- drivers/usb/core/hcd.h | 6 + drivers/usb/host/uhci-hcd.c | 218 +++++++++++++++++++++++++++++++++++++++++ drivers/usb/host/uhci-q.c | 164 +++++++++++++++++++++++++++++++ 7 files changed, 535 insertions(+), 19 deletions(-) diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index c9216a7..51ed359 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -342,8 +342,8 @@ config KDB_CONTINUE_CATASTROPHIC setting to 2. config KDB_USB - bool "Support for USB Keyboard in KDB (OHCI and/or EHCI only)" - depends on KDB && (USB_OHCI_HCD || USB_EHCI_HCD) + bool "Support for USB Keyboard in KDB" + depends on KDB && (USB_OHCI_HCD || USB_EHCI_HCD || USB_UHCI_HCD) help If you want to use kdb from USB keyboards then say Y here. If you say N then kdb can only be used from a PC (AT) keyboard or a serial diff --git a/arch/x86/kdb/kdba_io.c b/arch/x86/kdb/kdba_io.c index 087d468..e754dd4 100644 --- a/arch/x86/kdb/kdba_io.c +++ b/arch/x86/kdb/kdba_io.c @@ -30,9 +30,8 @@ #ifdef CONFIG_KDB_USB -/* support up to 8 USB keyboards (probably excessive, but...) */ -#define KDB_USB_NUM_KEYBOARDS 8 struct kdb_usb_kbd_info kdb_usb_kbds[KDB_USB_NUM_KEYBOARDS]; +EXPORT_SYMBOL(kdb_usb_kbds); extern int kdb_no_usb; @@ -60,7 +59,12 @@ static unsigned char kdb_usb_keycode[256] = { * Attach a USB keyboard to kdb. */ int -kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func) +kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, + void *poll_func, void *compl_func, + kdb_hc_keyboard_attach_t kdb_hc_keyboard_attach, + kdb_hc_keyboard_detach_t kdb_hc_keyboard_detach, + unsigned int bufsize, + struct urb *hid_urb) { int i; int rc = -1; @@ -83,6 +87,16 @@ kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func) kdb_usb_kbds[i].buffer = buffer; kdb_usb_kbds[i].poll_func = poll_func; + kdb_usb_kbds[i].kdb_hc_urb_complete = compl_func; + kdb_usb_kbds[i].kdb_hc_keyboard_attach = kdb_hc_keyboard_attach; + kdb_usb_kbds[i].kdb_hc_keyboard_detach = kdb_hc_keyboard_detach; + + /* USB Host Controller specific Keyboadr attach callback. + * Currently only UHCI has this callback. + */ + if (kdb_usb_kbds[i].kdb_hc_keyboard_attach) + kdb_usb_kbds[i].kdb_hc_keyboard_attach(i, bufsize); + rc = 0; /* success */ break; @@ -112,14 +126,23 @@ kdb_usb_keyboard_detach(struct urb *urb) */ for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { - if (kdb_usb_kbds[i].urb != urb) + if ((kdb_usb_kbds[i].urb != urb) && + (kdb_usb_kbds[i].hid_urb != urb)) continue; /* found it, clear the index */ + + /* USB Host Controller specific Keyboard detach callback. + * Currently only UHCI has this callback. + */ + if (kdb_usb_kbds[i].kdb_hc_keyboard_detach) + kdb_usb_kbds[i].kdb_hc_keyboard_detach(urb, i); + kdb_usb_kbds[i].urb = NULL; kdb_usb_kbds[i].buffer = NULL; kdb_usb_kbds[i].poll_func = NULL; kdb_usb_kbds[i].caps_lock = 0; + kdb_usb_kbds[i].hid_urb = NULL; rc = 0; /* success */ @@ -142,6 +165,9 @@ get_usb_char(void) int ret; unsigned char keycode, spec; extern u_short plain_map[], shift_map[], ctrl_map[]; + int ret_key = -1, j, max; + + ret = 1; if (kdb_no_usb) return -1; @@ -168,15 +194,24 @@ get_usb_char(void) if (ret < 0) /* error or no characters, try the next kbd */ continue; + /* If 2 keys was pressed simultaneously, + * both keycodes will be in buffer. + * Last pressed key will be last non + * zero byte. + */ + for (j=0; j<4; j++){ + if (!kdb_usb_kbds[i].buffer[2+j]) + break; + } + /* Last pressed key */ + max = j + 1; + spec = kdb_usb_kbds[i].buffer[0]; keycode = kdb_usb_kbds[i].buffer[2]; kdb_usb_kbds[i].buffer[0] = (char)0; kdb_usb_kbds[i].buffer[2] = (char)0; - if(kdb_usb_kbds[i].buffer[3]) { - kdb_usb_kbds[i].buffer[3] = (char)0; - continue; - } + ret_key = -1; /* A normal key is pressed, decode it */ if(keycode) @@ -188,10 +223,12 @@ get_usb_char(void) { case 0x2: case 0x20: /* Shift */ - return shift_map[keycode]; + ret_key = shift_map[keycode]; + break; case 0x1: case 0x10: /* Ctrl */ - return ctrl_map[keycode]; + ret_key = ctrl_map[keycode]; + break; case 0x4: case 0x40: /* Alt */ break; @@ -200,28 +237,50 @@ get_usb_char(void) switch(keycode) { case 0x1C: /* Enter */ - return 13; + ret_key = 13; + break; case 0x3A: /* Capslock */ kdb_usb_kbds[i].caps_lock = !(kdb_usb_kbds[i].caps_lock); break; case 0x0E: /* Backspace */ - return 8; + ret_key = 8; + break; case 0x0F: /* TAB */ - return 9; + ret_key = 9; + break; case 0x77: /* Pause */ break ; default: if(!kdb_usb_kbds[i].caps_lock) { - return plain_map[keycode]; + ret_key = plain_map[keycode]; } else { - return shift_map[keycode]; + ret_key = shift_map[keycode]; } } } + + if (ret_key != 1) { + /* Key was pressed, return keycode */ + + /* Clear buffer before urb resending */ + if (kdb_usb_kbds[i].buffer) + for(j=0; j<8; j++) + kdb_usb_kbds[i].buffer[j] = (char)0; + + /* USB Host Controller specific Urb complete callback. + * Currently only UHCI has this callback. + */ + if (kdb_usb_kbds[i].kdb_hc_urb_complete) + (*kdb_usb_kbds[i].kdb_hc_urb_complete)((struct urb *)kdb_usb_kbds[i].urb); + + return ret_key; + } } + + /* no chars were returned from any of the USB keyboards */ return -1; diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 8c55733..8c342d1 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -1195,9 +1195,20 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) int ret; struct usbhid_device *usbhid = hid->driver_data; extern void *usb_hcd_get_kdb_poll_func(struct usb_device *udev); + extern void * usb_hcd_get_kdb_completion_func(struct usb_device *udev); + extern int usb_hcd_check_uhci(struct usb_device *udev); + extern kdb_hc_keyboard_attach_t + usb_hcd_get_hc_keyboard_attach(struct usb_device *udev); + extern kdb_hc_keyboard_detach_t + usb_hcd_get_hc_keyboard_detach(struct usb_device *udev); ret = kdb_usb_keyboard_attach(usbhid->urbin, usbhid->inbuf, - usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf))); + usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf)), + usb_hcd_get_kdb_completion_func(interface_to_usbdev(intf)), + usb_hcd_get_hc_keyboard_attach(interface_to_usbdev(intf)), + usb_hcd_get_hc_keyboard_detach(interface_to_usbdev(intf)), + usbhid->bufsize, + NULL); if (ret == -1) printk(": FAILED to register keyboard (%s) " diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 5af2a35..f9d7c97 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -38,6 +38,9 @@ #include <asm/unaligned.h> #include <linux/platform_device.h> #include <linux/workqueue.h> +#ifdef CONFIG_KDB_USB +#include <linux/kdb.h> +#endif #include <linux/usb.h> @@ -2023,7 +2026,7 @@ EXPORT_SYMBOL_GPL(usb_hcd_platform_shutdown); void * usb_hcd_get_kdb_poll_func(struct usb_device *udev) { - struct usb_hcd *hcd = bus_to_hcd(udev->bus); + struct usb_hcd *hcd = bus_to_hcd(udev->bus); if (hcd && hcd->driver) return (void *)(hcd->driver->kdb_poll_char); @@ -2031,8 +2034,63 @@ usb_hcd_get_kdb_poll_func(struct usb_device *udev) return NULL; } EXPORT_SYMBOL_GPL (usb_hcd_get_kdb_poll_func); + +void * +usb_hcd_get_kdb_completion_func(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + if (hcd && hcd->driver) + return (void *)(hcd->driver->kdb_completion); + + return NULL; +} +EXPORT_SYMBOL_GPL (usb_hcd_get_kdb_completion_func); + +int +usb_hcd_check_uhci(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + if (hcd && hcd->driver){ + if (!(strcmp(hcd->driver->description, "uhci_hcd"))) + return 1; + } + + return 0; +} +EXPORT_SYMBOL_GPL (usb_hcd_check_uhci); + +kdb_hc_keyboard_attach_t +usb_hcd_get_hc_keyboard_attach(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + if (hcd && hcd->driver){ + return hcd->driver->kdb_hc_keyboard_attach; + } + + return 0; +} +EXPORT_SYMBOL_GPL (usb_hcd_get_hc_keyboard_attach); + +kdb_hc_keyboard_detach_t +usb_hcd_get_hc_keyboard_detach(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + if (hcd && hcd->driver){ + return hcd->driver->kdb_hc_keyboard_detach; + } + + return 0; +} +EXPORT_SYMBOL_GPL (usb_hcd_get_hc_keyboard_detach); + + #endif /* CONFIG_KDB_USB */ + /*-------------------------------------------------------------------------*/ #if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE) diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index d2e9e35..65b4e96 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -22,6 +22,9 @@ #ifdef __KERNEL__ #include <linux/rwsem.h> +#ifdef CONFIG_KDB_USB +#include <linux/kdb.h> +#endif #define MAX_TOPO_LEVEL 6 @@ -222,6 +225,9 @@ struct hc_driver { #ifdef CONFIG_KDB_USB /* KDB poll function for this HC */ int (*kdb_poll_char)(struct urb *urb); + void (*kdb_completion)(struct urb *urb); + kdb_hc_keyboard_attach_t kdb_hc_keyboard_attach; + kdb_hc_keyboard_detach_t kdb_hc_keyboard_detach; #endif /* CONFIG_KDB_USB */ }; diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index cf5e4cf..3e52775 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -50,6 +50,11 @@ #include "uhci-hcd.h" #include "pci-quirks.h" +#ifdef CONFIG_KDB_USB +#include <linux/kdb.h> +#include <linux/kdbprivate.h> +#endif + /* * Version Information */ @@ -461,6 +466,213 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) return IRQ_HANDLED; } +#ifdef CONFIG_KDB_USB +/* Unlink KDB QH from hardware and software scheduler */ +static void kdb_unlink_uhci_qh(struct urb *urb, struct uhci_qh *qh) +{ + unsigned long flags; + struct uhci_hcd *uhci; + + uhci = (struct uhci_hcd *) hcd_to_uhci(bus_to_hcd(urb->dev->bus)); + + spin_lock_irqsave(&uhci->lock, flags); + unlink_interrupt(NULL, qh); + list_del(&(qh->node)); + spin_unlock_irqrestore(&uhci->lock, flags); + +} + +static int uhci_kdb_poll_char(struct urb *urb) +{ + if (!urb) /* can happen if no keyboard attached */ + return -1; + + return uhci_check_kdb_uhci_qh(kdb_uhci_keyboard_get_qh(urb)); +} + +/* Only 1 UHCI Keyboard supported */ +static inline void kdb_usb_fill_int_urb (struct urb *urb, + struct usb_device *dev, + unsigned int pipe, + void *transfer_buffer, + int buffer_length, + usb_complete_t complete_fn, + void *context, + int interval) +{ + urb->dev = dev; + urb->pipe = pipe; + urb->transfer_buffer = transfer_buffer; + urb->transfer_buffer_length = buffer_length; + urb->complete = complete_fn; + urb->context = context; + urb->interval = interval; + urb->start_frame = -1; +} + +static int kdb_uhci_keyboard_attach(int i, unsigned int usbhid_bufsize) +{ + struct urb *kdb_urb; + unsigned char *kdb_buffer; + dma_addr_t uhci_inbuf_dma; + struct urb *hid_inurb = kdb_usb_kbds[i].urb; + int ret = -1; + + kdb_usb_kbds[i].hid_urb = hid_inurb; + + kdb_urb = NULL; + kdb_buffer = NULL; + if (!(kdb_buffer = usb_buffer_alloc(hid_inurb->dev, + usbhid_bufsize, GFP_ATOMIC, + &uhci_inbuf_dma))) + goto out; + + if (!(kdb_urb = usb_alloc_urb(0, GFP_KERNEL))) + goto out; + + kdb_usb_fill_int_urb(kdb_urb, + hid_inurb->dev, + hid_inurb->pipe, + kdb_buffer, + hid_inurb->transfer_buffer_length, + hid_inurb->complete, + hid_inurb->context, + hid_inurb->interval + ); + + (kdb_urb)->transfer_dma = uhci_inbuf_dma; + (kdb_urb)->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + kdb_usb_kbds[i].urb = kdb_urb; + kdb_usb_kbds[i].buffer = kdb_buffer; + + if (usb_submit_urb(kdb_urb, GFP_ATOMIC)){ + kdb_usb_keyboard_detach(hid_inurb); + goto out; + } + /* Remove KDB special URB from endpoin queue to + * prevent hang during hid_disconnect(). + */ + list_del(&(kdb_urb->urb_list)); + + ret = 0; + return ret; +out: + /* Some Error Cleanup */ + ret = -1; + printk("KDB: Error, UHCI Keyboard HID won't work!\n"); + + if (kdb_buffer) + usb_buffer_free(hid_inurb->dev, + usbhid_bufsize, kdb_buffer, + uhci_inbuf_dma); + + if (kdb_urb) + usb_free_urb(kdb_urb); + + return ret; +} + +static int kdb_uhci_keyboard_detach(struct urb *urb, int i) +{ + int ret; + + if (kdb_usb_kbds[i].qh && (kdb_usb_kbds[i].hid_urb == urb)) { + /* UHCI keyboard */ + kdb_unlink_uhci_qh(kdb_usb_kbds[i].urb, kdb_usb_kbds[i].qh); + ret = 0; + } + ret = -1; + + return ret; +} + +/* Check if URB is managed by KDB code */ +static int kdb_uhci_keyboard_urb(struct urb *urb) +{ + int i; + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].urb == urb) + return i; + } + return -1; +} + +/* Check if UHCI QH is managed by KDB code */ +static int kdb_uhci_keyboard_check_uhci_qh(struct uhci_qh *qh) +{ + int i; + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh) + return i; + } + return -1; +} + +/* Set UHCI QH using URB pointer */ +static int kdb_uhci_keyboard_set_qh(struct urb *urb, struct uhci_qh *qh) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1) + kdb_usb_kbds[i].qh = qh; + + return 0; +} + +/* Get UHCI QH using URB pointer */ +static struct uhci_qh *kdb_uhci_keyboard_get_qh(struct urb *urb) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1) + return kdb_usb_kbds[i].qh; + + return NULL; +} + +/* Set UHCI hid_event using URB pointer */ +static int kdb_uhci_keyboard_set_hid_event(struct urb *urb, int hid_event) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1) + kdb_usb_kbds[i].kdb_hid_event = hid_event; + + return 0; +} +/* Get UHCI hid_event using URB pointer */ +static int kdb_uhci_keyboard_get_hid_event(struct urb *urb) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1) + return kdb_usb_kbds[i].kdb_hid_event; + + return 0; +} + +/* Set UHCI hid_event using UHCI QH pointer */ +static int kdb_uhci_keyboard_set_hid_event_qh(struct uhci_qh *qh, int hid_event) +{ + int i; + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh){ + kdb_usb_kbds[i].kdb_hid_event = hid_event; + return i; + } + } + return -1; +} +#endif + /* * Store the current frame number in uhci->frame_number if the controller * is runnning. Expand from 11 bits (of which we use only 10) to a @@ -921,6 +1133,12 @@ static const struct hc_driver uhci_driver = { .hub_status_data = uhci_hub_status_data, .hub_control = uhci_hub_control, +#ifdef CONFIG_KDB_USB + .kdb_poll_char = uhci_kdb_poll_char, + .kdb_completion = kdb_uhci_urb_complete, + .kdb_hc_keyboard_attach = kdb_uhci_keyboard_attach, + .kdb_hc_keyboard_detach = kdb_uhci_keyboard_detach, +#endif }; static const struct pci_device_id uhci_pci_ids[] = { { diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 3e5807d..13def8f 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -25,6 +25,17 @@ * games with the FSBR code to make sure we get the correct order in all * the cases. I don't think it's worth the effort */ +#ifdef CONFIG_KDB_USB +/* KDB HID QH, managed by KDB code */ +static int kdb_uhci_keyboard_check_uhci_qh(struct uhci_qh *qh); +static int kdb_uhci_keyboard_set_qh(struct urb *urb, struct uhci_qh *qh); +static struct uhci_qh *kdb_uhci_keyboard_get_qh(struct urb *urb); +static int kdb_uhci_keyboard_set_hid_event(struct urb *urb, int hid_event); +static int kdb_uhci_keyboard_get_hid_event(struct urb *urb); +static int kdb_uhci_keyboard_set_hid_event_qh(struct uhci_qh *qh, int hid_event); +static int kdb_uhci_keyboard_urb(struct urb *urb); +#endif + static void uhci_set_next_interrupt(struct uhci_hcd *uhci) { if (uhci->is_stopped) @@ -288,6 +299,58 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, return qh; } +#ifdef CONFIG_KDB_USB +/* + * Same as uhci_alloc_qh execpt it doesn't change to hep->hcpriv + */ +static struct uhci_qh *kdb_uhci_alloc_qh(struct uhci_hcd *uhci, + struct usb_device *udev, struct usb_host_endpoint *hep) +{ + dma_addr_t dma_handle; + struct uhci_qh *qh; + + qh = dma_pool_alloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle); + if (!qh) + return NULL; + + memset(qh, 0, sizeof(*qh)); + qh->dma_handle = dma_handle; + + qh->element = UHCI_PTR_TERM; + qh->link = UHCI_PTR_TERM; + + INIT_LIST_HEAD(&qh->queue); + INIT_LIST_HEAD(&qh->node); + + if (udev) { /* Normal QH */ + qh->type = hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + if (qh->type != USB_ENDPOINT_XFER_ISOC) { + qh->dummy_td = uhci_alloc_td(uhci); + if (!qh->dummy_td) { + dma_pool_free(uhci->qh_pool, qh, dma_handle); + return NULL; + } + } + qh->state = QH_STATE_IDLE; + qh->hep = hep; + qh->udev = udev; + + if (qh->type == USB_ENDPOINT_XFER_INT || + qh->type == USB_ENDPOINT_XFER_ISOC) + qh->load = usb_calc_bus_time(udev->speed, + usb_endpoint_dir_in(&hep->desc), + qh->type == USB_ENDPOINT_XFER_ISOC, + le16_to_cpu(hep->desc.wMaxPacketSize)) + / 1000 + 1; + + } else { /* Skeleton QH */ + qh->state = QH_STATE_ACTIVE; + qh->type = -1; + } + return qh; +} +#endif + static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) { WARN_ON(qh->state != QH_STATE_IDLE && qh->udev); @@ -1394,6 +1457,21 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, if (!urbp) goto done; +#ifdef CONFIG_KDB_USB + /* Always allocate new QH for KDB URB. + * KDB HQ will be managed by KDB poll code not by + * UHCI HCD Driver. + */ + if (kdb_uhci_keyboard_urb(urb) != -1){ + /* KDB urb will be enqued only once */ + kdb_uhci_keyboard_set_qh(urb, NULL); + qh = kdb_uhci_alloc_qh(uhci, urb->dev, urb->ep); + if (!qh) + goto err_no_qh; + kdb_uhci_keyboard_set_qh(urb, qh); + } else +#endif + if (urb->ep->hcpriv) qh = urb->ep->hcpriv; else { @@ -1642,6 +1720,14 @@ static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh) int ret = 1; unsigned status; +#ifdef CONFIG_KDB_USB + /* Don't manage KDB QH */ + if(kdb_uhci_keyboard_check_uhci_qh(qh) != -1){ + ret = 0; + goto done; + } +#endif + if (qh->type == USB_ENDPOINT_XFER_ISOC) goto done; @@ -1734,6 +1820,11 @@ rescan: uhci->next_qh = list_entry(qh->node.next, struct uhci_qh, node); +#ifdef CONFIG_KDB_USB + /* Don't manage KDB QH */ + if(kdb_uhci_keyboard_check_uhci_qh(qh) != -1) + continue; +#endif if (uhci_advance_check(uhci, qh)) { uhci_scan_qh(uhci, qh); if (qh->state == QH_STATE_ACTIVE) { @@ -1760,3 +1851,76 @@ rescan: else uhci_set_next_interrupt(uhci); } + +#ifdef CONFIG_KDB_USB +/* + * Activate KDB UHCI QH, called by KDB poll code. + */ +static void kdb_activate_uhci_qh(struct uhci_qh *qh) +{ + struct urb_priv *urbp; + struct uhci_td *td; + __le32 status, token; + + urbp = list_entry(qh->queue.next, struct urb_priv, node); + + list_for_each_entry(td, &urbp->td_list, list){ + status = td->status; + token = td->token; + barrier(); + /* Clear Status and ActLen */ + status &= cpu_to_le32(0xff000000); + /* Make TD Active */ + status |= cpu_to_le32(TD_CTRL_ACTIVE); + /* Clear TD Interrupt */ + status &= cpu_to_le32(~TD_CTRL_IOC); + /* Toggle Data Sycronization Bit */ + if (token & cpu_to_le32(TD_TOKEN_TOGGLE)) + token &= cpu_to_le32(~TD_TOKEN_TOGGLE); + else + token |= cpu_to_le32(TD_TOKEN_TOGGLE); + + td->token = token; + td->status = status; + barrier(); + } + /* Activate KDB UHCI Keyboard HID QH */ + td = list_entry(urbp->td_list.next, struct uhci_td, list); + qh->element = LINK_TO_TD(td); + barrier(); +} + +/* + * Called when KDB finishes process key press/release event. + */ +static void +kdb_uhci_urb_complete (struct urb *urb) +{ + if (!kdb_uhci_keyboard_get_hid_event(urb)) + return; + + /* Activate KDB TD */ + kdb_activate_uhci_qh(kdb_uhci_keyboard_get_qh(urb)); + kdb_uhci_keyboard_set_hid_event(urb, 0); +} + +/* + * Check if state of KDB URB changed (key was pressed/released). + */ +static int uhci_check_kdb_uhci_qh(struct uhci_qh *qh) +{ + struct urb_priv *urbp = NULL; + struct uhci_td *td; + unsigned status; + + urbp = list_entry(qh->queue.next, struct urb_priv, node); + td = list_entry(urbp->td_list.next, struct uhci_td, list); + status = td_status(td); + if (!(status & TD_CTRL_ACTIVE)){ + /* We're okay, the queue has advanced */ + kdb_uhci_keyboard_set_hid_event_qh(qh, 1); + return 0; + } + return -1; +} +#endif -- 1.5.6.3 From mort@sgi.com Wed May 27 10:13:15 2009 X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=AWL,BAYES_00,J_CHICKENPOX_62, MIME_8BIT_HEADER autolearn=no version=3.3.0-rupdated Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id n4RFDFw9196327 for <kdb@oss.sgi.com>; Wed, 27 May 2009 10:13:15 -0500 Received: from attica.americas.sgi.com (attica.americas.sgi.com [128.162.236.44]) by relay2.corp.sgi.com (Postfix) with ESMTP id 717B1304051; Wed, 27 May 2009 08:13:26 -0700 (PDT) Received: by attica.americas.sgi.com (Postfix, from userid 44682) id 73885A1FAB93; Wed, 27 May 2009 10:13:25 -0500 (CDT) Date: Wed, 27 May 2009 10:13:25 -0500 From: Martin Hicks <mort@sgi.com> To: Matthieu =?iso-8859-1?Q?Fertr=E9?= <matthieu.fertre@kerlabs.com> Cc: kdb@oss.sgi.com Subject: Re: [kdb] [PATCH] Add support for USB Keyboard attached to UHCI in KDB Message-ID: <20090527151325.GG28779@alcatraz.americas.sgi.com> References: <1243325438-11715-1-git-send-email-matthieu.fertre@kerlabs.com> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <1243325438-11715-1-git-send-email-matthieu.fertre@kerlabs.com> User-Agent: Mutt/1.5.17 (2007-11-01) X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean Thanks Matthieu, I'll give people a little longer to review. I have never used the USB keyboard support in KDB so I'm definitely not the best reviewer... mh On Tue, May 26, 2009 at 10:10:38AM +0200, Matthieu Fertré wrote: > Building as a module has not been tested. > > Update of patch from Konstantin Baydarov <kbaidarov@ru.mvista.com>. > > The patch was originally posted here: > http://oss.sgi.com/archives/kdb/2008-02/msg00006.html > > Signed-off-by: Matthieu Fertré <matthieu.fertre@kerlabs.com> > --- > arch/x86/Kconfig.debug | 4 +- > arch/x86/kdb/kdba_io.c | 89 ++++++++++++++--- > drivers/hid/usbhid/hid-core.c | 13 +++- > drivers/usb/core/hcd.c | 60 +++++++++++- > drivers/usb/core/hcd.h | 6 + > drivers/usb/host/uhci-hcd.c | 218 +++++++++++++++++++++++++++++++++++++++++ > drivers/usb/host/uhci-q.c | 164 +++++++++++++++++++++++++++++++ > 7 files changed, 535 insertions(+), 19 deletions(-) > > diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug > index c9216a7..51ed359 100644 > --- a/arch/x86/Kconfig.debug > +++ b/arch/x86/Kconfig.debug > @@ -342,8 +342,8 @@ config KDB_CONTINUE_CATASTROPHIC > setting to 2. > > config KDB_USB > - bool "Support for USB Keyboard in KDB (OHCI and/or EHCI only)" > - depends on KDB && (USB_OHCI_HCD || USB_EHCI_HCD) > + bool "Support for USB Keyboard in KDB" > + depends on KDB && (USB_OHCI_HCD || USB_EHCI_HCD || USB_UHCI_HCD) > help > If you want to use kdb from USB keyboards then say Y here. If you > say N then kdb can only be used from a PC (AT) keyboard or a serial > diff --git a/arch/x86/kdb/kdba_io.c b/arch/x86/kdb/kdba_io.c > index 087d468..e754dd4 100644 > --- a/arch/x86/kdb/kdba_io.c > +++ b/arch/x86/kdb/kdba_io.c > @@ -30,9 +30,8 @@ > > #ifdef CONFIG_KDB_USB > > -/* support up to 8 USB keyboards (probably excessive, but...) */ > -#define KDB_USB_NUM_KEYBOARDS 8 > struct kdb_usb_kbd_info kdb_usb_kbds[KDB_USB_NUM_KEYBOARDS]; > +EXPORT_SYMBOL(kdb_usb_kbds); > > extern int kdb_no_usb; > > @@ -60,7 +59,12 @@ static unsigned char kdb_usb_keycode[256] = { > * Attach a USB keyboard to kdb. > */ > int > -kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func) > +kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, > + void *poll_func, void *compl_func, > + kdb_hc_keyboard_attach_t kdb_hc_keyboard_attach, > + kdb_hc_keyboard_detach_t kdb_hc_keyboard_detach, > + unsigned int bufsize, > + struct urb *hid_urb) > { > int i; > int rc = -1; > @@ -83,6 +87,16 @@ kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func) > kdb_usb_kbds[i].buffer = buffer; > kdb_usb_kbds[i].poll_func = poll_func; > > + kdb_usb_kbds[i].kdb_hc_urb_complete = compl_func; > + kdb_usb_kbds[i].kdb_hc_keyboard_attach = kdb_hc_keyboard_attach; > + kdb_usb_kbds[i].kdb_hc_keyboard_detach = kdb_hc_keyboard_detach; > + > + /* USB Host Controller specific Keyboadr attach callback. > + * Currently only UHCI has this callback. > + */ > + if (kdb_usb_kbds[i].kdb_hc_keyboard_attach) > + kdb_usb_kbds[i].kdb_hc_keyboard_attach(i, bufsize); > + > rc = 0; /* success */ > > break; > @@ -112,14 +126,23 @@ kdb_usb_keyboard_detach(struct urb *urb) > */ > > for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > - if (kdb_usb_kbds[i].urb != urb) > + if ((kdb_usb_kbds[i].urb != urb) && > + (kdb_usb_kbds[i].hid_urb != urb)) > continue; > > /* found it, clear the index */ > + > + /* USB Host Controller specific Keyboard detach callback. > + * Currently only UHCI has this callback. > + */ > + if (kdb_usb_kbds[i].kdb_hc_keyboard_detach) > + kdb_usb_kbds[i].kdb_hc_keyboard_detach(urb, i); > + > kdb_usb_kbds[i].urb = NULL; > kdb_usb_kbds[i].buffer = NULL; > kdb_usb_kbds[i].poll_func = NULL; > kdb_usb_kbds[i].caps_lock = 0; > + kdb_usb_kbds[i].hid_urb = NULL; > > rc = 0; /* success */ > > @@ -142,6 +165,9 @@ get_usb_char(void) > int ret; > unsigned char keycode, spec; > extern u_short plain_map[], shift_map[], ctrl_map[]; > + int ret_key = -1, j, max; > + > + ret = 1; > > if (kdb_no_usb) > return -1; > @@ -168,15 +194,24 @@ get_usb_char(void) > if (ret < 0) /* error or no characters, try the next kbd */ > continue; > > + /* If 2 keys was pressed simultaneously, > + * both keycodes will be in buffer. > + * Last pressed key will be last non > + * zero byte. > + */ > + for (j=0; j<4; j++){ > + if (!kdb_usb_kbds[i].buffer[2+j]) > + break; > + } > + /* Last pressed key */ > + max = j + 1; > + > spec = kdb_usb_kbds[i].buffer[0]; > keycode = kdb_usb_kbds[i].buffer[2]; > kdb_usb_kbds[i].buffer[0] = (char)0; > kdb_usb_kbds[i].buffer[2] = (char)0; > > - if(kdb_usb_kbds[i].buffer[3]) { > - kdb_usb_kbds[i].buffer[3] = (char)0; > - continue; > - } > + ret_key = -1; > > /* A normal key is pressed, decode it */ > if(keycode) > @@ -188,10 +223,12 @@ get_usb_char(void) > { > case 0x2: > case 0x20: /* Shift */ > - return shift_map[keycode]; > + ret_key = shift_map[keycode]; > + break; > case 0x1: > case 0x10: /* Ctrl */ > - return ctrl_map[keycode]; > + ret_key = ctrl_map[keycode]; > + break; > case 0x4: > case 0x40: /* Alt */ > break; > @@ -200,28 +237,50 @@ get_usb_char(void) > switch(keycode) > { > case 0x1C: /* Enter */ > - return 13; > + ret_key = 13; > + break; > > case 0x3A: /* Capslock */ > kdb_usb_kbds[i].caps_lock = !(kdb_usb_kbds[i].caps_lock); > break; > case 0x0E: /* Backspace */ > - return 8; > + ret_key = 8; > + break; > case 0x0F: /* TAB */ > - return 9; > + ret_key = 9; > + break; > case 0x77: /* Pause */ > break ; > default: > if(!kdb_usb_kbds[i].caps_lock) { > - return plain_map[keycode]; > + ret_key = plain_map[keycode]; > } > else { > - return shift_map[keycode]; > + ret_key = shift_map[keycode]; > } > } > } > + > + if (ret_key != 1) { > + /* Key was pressed, return keycode */ > + > + /* Clear buffer before urb resending */ > + if (kdb_usb_kbds[i].buffer) > + for(j=0; j<8; j++) > + kdb_usb_kbds[i].buffer[j] = (char)0; > + > + /* USB Host Controller specific Urb complete callback. > + * Currently only UHCI has this callback. > + */ > + if (kdb_usb_kbds[i].kdb_hc_urb_complete) > + (*kdb_usb_kbds[i].kdb_hc_urb_complete)((struct urb *)kdb_usb_kbds[i].urb); > + > + return ret_key; > + } > } > > + > + > /* no chars were returned from any of the USB keyboards */ > > return -1; > diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c > index 8c55733..8c342d1 100644 > --- a/drivers/hid/usbhid/hid-core.c > +++ b/drivers/hid/usbhid/hid-core.c > @@ -1195,9 +1195,20 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) > int ret; > struct usbhid_device *usbhid = hid->driver_data; > extern void *usb_hcd_get_kdb_poll_func(struct usb_device *udev); > + extern void * usb_hcd_get_kdb_completion_func(struct usb_device *udev); > + extern int usb_hcd_check_uhci(struct usb_device *udev); > + extern kdb_hc_keyboard_attach_t > + usb_hcd_get_hc_keyboard_attach(struct usb_device *udev); > + extern kdb_hc_keyboard_detach_t > + usb_hcd_get_hc_keyboard_detach(struct usb_device *udev); > > ret = kdb_usb_keyboard_attach(usbhid->urbin, usbhid->inbuf, > - usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf))); > + usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf)), > + usb_hcd_get_kdb_completion_func(interface_to_usbdev(intf)), > + usb_hcd_get_hc_keyboard_attach(interface_to_usbdev(intf)), > + usb_hcd_get_hc_keyboard_detach(interface_to_usbdev(intf)), > + usbhid->bufsize, > + NULL); > > if (ret == -1) > printk(": FAILED to register keyboard (%s) " > diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c > index 5af2a35..f9d7c97 100644 > --- a/drivers/usb/core/hcd.c > +++ b/drivers/usb/core/hcd.c > @@ -38,6 +38,9 @@ > #include <asm/unaligned.h> > #include <linux/platform_device.h> > #include <linux/workqueue.h> > +#ifdef CONFIG_KDB_USB > +#include <linux/kdb.h> > +#endif > > #include <linux/usb.h> > > @@ -2023,7 +2026,7 @@ EXPORT_SYMBOL_GPL(usb_hcd_platform_shutdown); > void * > usb_hcd_get_kdb_poll_func(struct usb_device *udev) > { > - struct usb_hcd *hcd = bus_to_hcd(udev->bus); > + struct usb_hcd *hcd = bus_to_hcd(udev->bus); > > if (hcd && hcd->driver) > return (void *)(hcd->driver->kdb_poll_char); > @@ -2031,8 +2034,63 @@ usb_hcd_get_kdb_poll_func(struct usb_device *udev) > return NULL; > } > EXPORT_SYMBOL_GPL (usb_hcd_get_kdb_poll_func); > + > +void * > +usb_hcd_get_kdb_completion_func(struct usb_device *udev) > +{ > + struct usb_hcd *hcd = bus_to_hcd(udev->bus); > + > + if (hcd && hcd->driver) > + return (void *)(hcd->driver->kdb_completion); > + > + return NULL; > +} > +EXPORT_SYMBOL_GPL (usb_hcd_get_kdb_completion_func); > + > +int > +usb_hcd_check_uhci(struct usb_device *udev) > +{ > + struct usb_hcd *hcd = bus_to_hcd(udev->bus); > + > + if (hcd && hcd->driver){ > + if (!(strcmp(hcd->driver->description, "uhci_hcd"))) > + return 1; > + } > + > + return 0; > +} > +EXPORT_SYMBOL_GPL (usb_hcd_check_uhci); > + > +kdb_hc_keyboard_attach_t > +usb_hcd_get_hc_keyboard_attach(struct usb_device *udev) > +{ > + struct usb_hcd *hcd = bus_to_hcd(udev->bus); > + > + if (hcd && hcd->driver){ > + return hcd->driver->kdb_hc_keyboard_attach; > + } > + > + return 0; > +} > +EXPORT_SYMBOL_GPL (usb_hcd_get_hc_keyboard_attach); > + > +kdb_hc_keyboard_detach_t > +usb_hcd_get_hc_keyboard_detach(struct usb_device *udev) > +{ > + struct usb_hcd *hcd = bus_to_hcd(udev->bus); > + > + if (hcd && hcd->driver){ > + return hcd->driver->kdb_hc_keyboard_detach; > + } > + > + return 0; > +} > +EXPORT_SYMBOL_GPL (usb_hcd_get_hc_keyboard_detach); > + > + > #endif /* CONFIG_KDB_USB */ > > + > /*-------------------------------------------------------------------------*/ > > #if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE) > diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h > index d2e9e35..65b4e96 100644 > --- a/drivers/usb/core/hcd.h > +++ b/drivers/usb/core/hcd.h > @@ -22,6 +22,9 @@ > #ifdef __KERNEL__ > > #include <linux/rwsem.h> > +#ifdef CONFIG_KDB_USB > +#include <linux/kdb.h> > +#endif > > #define MAX_TOPO_LEVEL 6 > > @@ -222,6 +225,9 @@ struct hc_driver { > #ifdef CONFIG_KDB_USB > /* KDB poll function for this HC */ > int (*kdb_poll_char)(struct urb *urb); > + void (*kdb_completion)(struct urb *urb); > + kdb_hc_keyboard_attach_t kdb_hc_keyboard_attach; > + kdb_hc_keyboard_detach_t kdb_hc_keyboard_detach; > #endif /* CONFIG_KDB_USB */ > }; > > diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c > index cf5e4cf..3e52775 100644 > --- a/drivers/usb/host/uhci-hcd.c > +++ b/drivers/usb/host/uhci-hcd.c > @@ -50,6 +50,11 @@ > #include "uhci-hcd.h" > #include "pci-quirks.h" > > +#ifdef CONFIG_KDB_USB > +#include <linux/kdb.h> > +#include <linux/kdbprivate.h> > +#endif > + > /* > * Version Information > */ > @@ -461,6 +466,213 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) > return IRQ_HANDLED; > } > > +#ifdef CONFIG_KDB_USB > +/* Unlink KDB QH from hardware and software scheduler */ > +static void kdb_unlink_uhci_qh(struct urb *urb, struct uhci_qh *qh) > +{ > + unsigned long flags; > + struct uhci_hcd *uhci; > + > + uhci = (struct uhci_hcd *) hcd_to_uhci(bus_to_hcd(urb->dev->bus)); > + > + spin_lock_irqsave(&uhci->lock, flags); > + unlink_interrupt(NULL, qh); > + list_del(&(qh->node)); > + spin_unlock_irqrestore(&uhci->lock, flags); > + > +} > + > +static int uhci_kdb_poll_char(struct urb *urb) > +{ > + if (!urb) /* can happen if no keyboard attached */ > + return -1; > + > + return uhci_check_kdb_uhci_qh(kdb_uhci_keyboard_get_qh(urb)); > +} > + > +/* Only 1 UHCI Keyboard supported */ > +static inline void kdb_usb_fill_int_urb (struct urb *urb, > + struct usb_device *dev, > + unsigned int pipe, > + void *transfer_buffer, > + int buffer_length, > + usb_complete_t complete_fn, > + void *context, > + int interval) > +{ > + urb->dev = dev; > + urb->pipe = pipe; > + urb->transfer_buffer = transfer_buffer; > + urb->transfer_buffer_length = buffer_length; > + urb->complete = complete_fn; > + urb->context = context; > + urb->interval = interval; > + urb->start_frame = -1; > +} > + > +static int kdb_uhci_keyboard_attach(int i, unsigned int usbhid_bufsize) > +{ > + struct urb *kdb_urb; > + unsigned char *kdb_buffer; > + dma_addr_t uhci_inbuf_dma; > + struct urb *hid_inurb = kdb_usb_kbds[i].urb; > + int ret = -1; > + > + kdb_usb_kbds[i].hid_urb = hid_inurb; > + > + kdb_urb = NULL; > + kdb_buffer = NULL; > + if (!(kdb_buffer = usb_buffer_alloc(hid_inurb->dev, > + usbhid_bufsize, GFP_ATOMIC, > + &uhci_inbuf_dma))) > + goto out; > + > + if (!(kdb_urb = usb_alloc_urb(0, GFP_KERNEL))) > + goto out; > + > + kdb_usb_fill_int_urb(kdb_urb, > + hid_inurb->dev, > + hid_inurb->pipe, > + kdb_buffer, > + hid_inurb->transfer_buffer_length, > + hid_inurb->complete, > + hid_inurb->context, > + hid_inurb->interval > + ); > + > + (kdb_urb)->transfer_dma = uhci_inbuf_dma; > + (kdb_urb)->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; > + > + kdb_usb_kbds[i].urb = kdb_urb; > + kdb_usb_kbds[i].buffer = kdb_buffer; > + > + if (usb_submit_urb(kdb_urb, GFP_ATOMIC)){ > + kdb_usb_keyboard_detach(hid_inurb); > + goto out; > + } > + /* Remove KDB special URB from endpoin queue to > + * prevent hang during hid_disconnect(). > + */ > + list_del(&(kdb_urb->urb_list)); > + > + ret = 0; > + return ret; > +out: > + /* Some Error Cleanup */ > + ret = -1; > + printk("KDB: Error, UHCI Keyboard HID won't work!\n"); > + > + if (kdb_buffer) > + usb_buffer_free(hid_inurb->dev, > + usbhid_bufsize, kdb_buffer, > + uhci_inbuf_dma); > + > + if (kdb_urb) > + usb_free_urb(kdb_urb); > + > + return ret; > +} > + > +static int kdb_uhci_keyboard_detach(struct urb *urb, int i) > +{ > + int ret; > + > + if (kdb_usb_kbds[i].qh && (kdb_usb_kbds[i].hid_urb == urb)) { > + /* UHCI keyboard */ > + kdb_unlink_uhci_qh(kdb_usb_kbds[i].urb, kdb_usb_kbds[i].qh); > + ret = 0; > + } > + ret = -1; > + > + return ret; > +} > + > +/* Check if URB is managed by KDB code */ > +static int kdb_uhci_keyboard_urb(struct urb *urb) > +{ > + int i; > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].urb == urb) > + return i; > + } > + return -1; > +} > + > +/* Check if UHCI QH is managed by KDB code */ > +static int kdb_uhci_keyboard_check_uhci_qh(struct uhci_qh *qh) > +{ > + int i; > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh) > + return i; > + } > + return -1; > +} > + > +/* Set UHCI QH using URB pointer */ > +static int kdb_uhci_keyboard_set_qh(struct urb *urb, struct uhci_qh *qh) > +{ > + int i; > + > + i = kdb_uhci_keyboard_urb(urb); > + if (i != -1) > + kdb_usb_kbds[i].qh = qh; > + > + return 0; > +} > + > +/* Get UHCI QH using URB pointer */ > +static struct uhci_qh *kdb_uhci_keyboard_get_qh(struct urb *urb) > +{ > + int i; > + > + i = kdb_uhci_keyboard_urb(urb); > + if (i != -1) > + return kdb_usb_kbds[i].qh; > + > + return NULL; > +} > + > +/* Set UHCI hid_event using URB pointer */ > +static int kdb_uhci_keyboard_set_hid_event(struct urb *urb, int hid_event) > +{ > + int i; > + > + i = kdb_uhci_keyboard_urb(urb); > + if (i != -1) > + kdb_usb_kbds[i].kdb_hid_event = hid_event; > + > + return 0; > +} > +/* Get UHCI hid_event using URB pointer */ > +static int kdb_uhci_keyboard_get_hid_event(struct urb *urb) > +{ > + int i; > + > + i = kdb_uhci_keyboard_urb(urb); > + if (i != -1) > + return kdb_usb_kbds[i].kdb_hid_event; > + > + return 0; > +} > + > +/* Set UHCI hid_event using UHCI QH pointer */ > +static int kdb_uhci_keyboard_set_hid_event_qh(struct uhci_qh *qh, int hid_event) > +{ > + int i; > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh){ > + kdb_usb_kbds[i].kdb_hid_event = hid_event; > + return i; > + } > + } > + return -1; > +} > +#endif > + > /* > * Store the current frame number in uhci->frame_number if the controller > * is runnning. Expand from 11 bits (of which we use only 10) to a > @@ -921,6 +1133,12 @@ static const struct hc_driver uhci_driver = { > > .hub_status_data = uhci_hub_status_data, > .hub_control = uhci_hub_control, > +#ifdef CONFIG_KDB_USB > + .kdb_poll_char = uhci_kdb_poll_char, > + .kdb_completion = kdb_uhci_urb_complete, > + .kdb_hc_keyboard_attach = kdb_uhci_keyboard_attach, > + .kdb_hc_keyboard_detach = kdb_uhci_keyboard_detach, > +#endif > }; > > static const struct pci_device_id uhci_pci_ids[] = { { > diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c > index 3e5807d..13def8f 100644 > --- a/drivers/usb/host/uhci-q.c > +++ b/drivers/usb/host/uhci-q.c > @@ -25,6 +25,17 @@ > * games with the FSBR code to make sure we get the correct order in all > * the cases. I don't think it's worth the effort > */ > +#ifdef CONFIG_KDB_USB > +/* KDB HID QH, managed by KDB code */ > +static int kdb_uhci_keyboard_check_uhci_qh(struct uhci_qh *qh); > +static int kdb_uhci_keyboard_set_qh(struct urb *urb, struct uhci_qh *qh); > +static struct uhci_qh *kdb_uhci_keyboard_get_qh(struct urb *urb); > +static int kdb_uhci_keyboard_set_hid_event(struct urb *urb, int hid_event); > +static int kdb_uhci_keyboard_get_hid_event(struct urb *urb); > +static int kdb_uhci_keyboard_set_hid_event_qh(struct uhci_qh *qh, int hid_event); > +static int kdb_uhci_keyboard_urb(struct urb *urb); > +#endif > + > static void uhci_set_next_interrupt(struct uhci_hcd *uhci) > { > if (uhci->is_stopped) > @@ -288,6 +299,58 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, > return qh; > } > > +#ifdef CONFIG_KDB_USB > +/* > + * Same as uhci_alloc_qh execpt it doesn't change to hep->hcpriv > + */ > +static struct uhci_qh *kdb_uhci_alloc_qh(struct uhci_hcd *uhci, > + struct usb_device *udev, struct usb_host_endpoint *hep) > +{ > + dma_addr_t dma_handle; > + struct uhci_qh *qh; > + > + qh = dma_pool_alloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle); > + if (!qh) > + return NULL; > + > + memset(qh, 0, sizeof(*qh)); > + qh->dma_handle = dma_handle; > + > + qh->element = UHCI_PTR_TERM; > + qh->link = UHCI_PTR_TERM; > + > + INIT_LIST_HEAD(&qh->queue); > + INIT_LIST_HEAD(&qh->node); > + > + if (udev) { /* Normal QH */ > + qh->type = hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; > + if (qh->type != USB_ENDPOINT_XFER_ISOC) { > + qh->dummy_td = uhci_alloc_td(uhci); > + if (!qh->dummy_td) { > + dma_pool_free(uhci->qh_pool, qh, dma_handle); > + return NULL; > + } > + } > + qh->state = QH_STATE_IDLE; > + qh->hep = hep; > + qh->udev = udev; > + > + if (qh->type == USB_ENDPOINT_XFER_INT || > + qh->type == USB_ENDPOINT_XFER_ISOC) > + qh->load = usb_calc_bus_time(udev->speed, > + usb_endpoint_dir_in(&hep->desc), > + qh->type == USB_ENDPOINT_XFER_ISOC, > + le16_to_cpu(hep->desc.wMaxPacketSize)) > + / 1000 + 1; > + > + } else { /* Skeleton QH */ > + qh->state = QH_STATE_ACTIVE; > + qh->type = -1; > + } > + return qh; > +} > +#endif > + > static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) > { > WARN_ON(qh->state != QH_STATE_IDLE && qh->udev); > @@ -1394,6 +1457,21 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, > if (!urbp) > goto done; > > +#ifdef CONFIG_KDB_USB > + /* Always allocate new QH for KDB URB. > + * KDB HQ will be managed by KDB poll code not by > + * UHCI HCD Driver. > + */ > + if (kdb_uhci_keyboard_urb(urb) != -1){ > + /* KDB urb will be enqued only once */ > + kdb_uhci_keyboard_set_qh(urb, NULL); > + qh = kdb_uhci_alloc_qh(uhci, urb->dev, urb->ep); > + if (!qh) > + goto err_no_qh; > + kdb_uhci_keyboard_set_qh(urb, qh); > + } else > +#endif > + > if (urb->ep->hcpriv) > qh = urb->ep->hcpriv; > else { > @@ -1642,6 +1720,14 @@ static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh) > int ret = 1; > unsigned status; > > +#ifdef CONFIG_KDB_USB > + /* Don't manage KDB QH */ > + if(kdb_uhci_keyboard_check_uhci_qh(qh) != -1){ > + ret = 0; > + goto done; > + } > +#endif > + > if (qh->type == USB_ENDPOINT_XFER_ISOC) > goto done; > > @@ -1734,6 +1820,11 @@ rescan: > uhci->next_qh = list_entry(qh->node.next, > struct uhci_qh, node); > > +#ifdef CONFIG_KDB_USB > + /* Don't manage KDB QH */ > + if(kdb_uhci_keyboard_check_uhci_qh(qh) != -1) > + continue; > +#endif > if (uhci_advance_check(uhci, qh)) { > uhci_scan_qh(uhci, qh); > if (qh->state == QH_STATE_ACTIVE) { > @@ -1760,3 +1851,76 @@ rescan: > else > uhci_set_next_interrupt(uhci); > } > + > +#ifdef CONFIG_KDB_USB > +/* > + * Activate KDB UHCI QH, called by KDB poll code. > + */ > +static void kdb_activate_uhci_qh(struct uhci_qh *qh) > +{ > + struct urb_priv *urbp; > + struct uhci_td *td; > + __le32 status, token; > + > + urbp = list_entry(qh->queue.next, struct urb_priv, node); > + > + list_for_each_entry(td, &urbp->td_list, list){ > + status = td->status; > + token = td->token; > + barrier(); > + /* Clear Status and ActLen */ > + status &= cpu_to_le32(0xff000000); > + /* Make TD Active */ > + status |= cpu_to_le32(TD_CTRL_ACTIVE); > + /* Clear TD Interrupt */ > + status &= cpu_to_le32(~TD_CTRL_IOC); > + /* Toggle Data Sycronization Bit */ > + if (token & cpu_to_le32(TD_TOKEN_TOGGLE)) > + token &= cpu_to_le32(~TD_TOKEN_TOGGLE); > + else > + token |= cpu_to_le32(TD_TOKEN_TOGGLE); > + > + td->token = token; > + td->status = status; > + barrier(); > + } > + /* Activate KDB UHCI Keyboard HID QH */ > + td = list_entry(urbp->td_list.next, struct uhci_td, list); > + qh->element = LINK_TO_TD(td); > + barrier(); > +} > + > +/* > + * Called when KDB finishes process key press/release event. > + */ > +static void > +kdb_uhci_urb_complete (struct urb *urb) > +{ > + if (!kdb_uhci_keyboard_get_hid_event(urb)) > + return; > + > + /* Activate KDB TD */ > + kdb_activate_uhci_qh(kdb_uhci_keyboard_get_qh(urb)); > + kdb_uhci_keyboard_set_hid_event(urb, 0); > +} > + > +/* > + * Check if state of KDB URB changed (key was pressed/released). > + */ > +static int uhci_check_kdb_uhci_qh(struct uhci_qh *qh) > +{ > + struct urb_priv *urbp = NULL; > + struct uhci_td *td; > + unsigned status; > + > + urbp = list_entry(qh->queue.next, struct urb_priv, node); > + td = list_entry(urbp->td_list.next, struct uhci_td, list); > + status = td_status(td); > + if (!(status & TD_CTRL_ACTIVE)){ > + /* We're okay, the queue has advanced */ > + kdb_uhci_keyboard_set_hid_event_qh(qh, 1); > + return 0; > + } > + return -1; > +} > +#endif > -- > 1.5.6.3 > > _______________________________________________ > kdb mailing list > kdb@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/kdb