一、下载kdb
kdb以补丁的形式打包到Linux内核源码中。
文件名:kdb-v4.4-2.6.32-common-6.bz2
kdb-v4.4-2.6.32-x86-6.bz2
下载地址:ftp://oss.sgi.com/www/projects/kdb/download
二、打包kdb补丁到内核源码
将kdb补丁包放到Linux内核源码目录下:/usr/src/linux-2.6.32
2.1 解压缩kdb文件
bzip2 -d kdb-v4.4-2.6.32-common-6.bz2
bzip2 -d kdb-v4.4-2.6.32-x86-6.bz2
2.2 打包kdb文件
patch -p1 < kdb-v4.4-2.6.32-common-6
patch -p1 < kdb-v4.4-2.6.32-x86-6
三、配置Linux内核参数(使用KDB)
3.1 进入内核参数配置页面
cd /usr/src/linux-2.6.32
make menuconfig
3.2 设置内核参数
Kernel hacking --->
保存退出,即可看到.config。
3.3 查看内核参数
vim .config
确保.config文件选项有如下:
CONFIG_KDB=y
CONFIG_KDB_MODULES=n
CONFIG_KDB_OFF=n (y、n均可)
CONFIG_KDB_CONTINUE_CATASTROPHIC=0
CONFIG_KDB_USB=y
CONFIG_KDB_KDUMP=y
CONFIG_KALLSYMS=y
CONFIG_FRAME_POINTER=y
四、编译中可能遇到的问题
以下错误是Linux 2.6.32内核中的错误。
(参考资料,Linux 2.6.3.32内核编译安装kdb-v4.4-2.6.32)
4.1 错误:/arch/x86/kernel/traps.c
错误:
解决办法:
去掉arch/x86/kernel/traps.c 文件中,415行的“}”。
4.2 错误:drivers/usb/host/ehci-hcd.c
错误:
解决办法:
打一个手写的补丁,自己取名:ehci-q--echi_qh--patch
patch -p1 < ehci-q--echi_qh--patch
补丁ehci-q--echi_qh--patch中的内容:
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index dca7b17..52b4651 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -594,6 +594,7 @@ qh_completions_kdb(struct ehci_hcd *ehci, struct ehci_qh *qh, struct urb *kdburb
int do_status = 0;
u8 state;
u32 halt = HALT_BIT(ehci);
+ struct ehci_qh_hw *hw = qh->hw;
/* verify params are valid */
if (!qh || !kdburb)
@@ -612,6 +613,11 @@ qh_completions_kdb(struct ehci_hcd *ehci, struct ehci_qh *qh, struct urb *kdburb
qh->qh_state = QH_STATE_COMPLETING;
stopped = (state == QH_STATE_IDLE);
+ rescan:
+ last = NULL;
+ last_status = -EINPROGRESS;
+ qh->needs_rescan = 0;
+
/* remove de-activated QTDs from front of queue.
* after faults (including short reads), cleanup this urb
* then let the queue advance.
@@ -621,7 +627,6 @@ qh_completions_kdb(struct ehci_hcd *ehci, struct ehci_qh *qh, struct urb *kdburb
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;
@@ -651,10 +656,10 @@ qh_completions_kdb(struct ehci_hcd *ehci, struct ehci_qh *qh, struct urb *kdburb
spin_unlock (&ehci->lock);
count++;
+ last_status = -EINPROGRESS;
}
ehci_qtd_free (ehci, last);
last = NULL;
- last_status = -EINPROGRESS;
}
/* ignore urbs submitted during completions we reported */
@@ -663,7 +668,7 @@ qh_completions_kdb(struct ehci_hcd *ehci, struct ehci_qh *qh, struct urb *kdburb
/* hardware copies qtd out of qh overlay */
rmb ();
- token = hc32_to_cpu(ehci, qtd->hw_token);
+ token = hc32_to_cpu(ehci, hw->hw_token);
/* always clean up qtds the hc de-activated */
if ((token & QTD_STS_ACTIVE) == 0) {
@@ -710,37 +715,60 @@ qh_completions_kdb(struct ehci_hcd *ehci, struct ehci_qh *qh, struct urb *kdburb
/* 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);
+ == hw->hw_current)
+ token = hc32_to_cpu(ehci, hw->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) {
+ if ((halt & hw->hw_token) == 0) {
halt:
- qh->hw_token |= halt;
+ hw->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_copy_status(ehci, urb,
+ qtd->length, token);
+ if (last_status == -EREMOTEIO
+ && (qtd->hw_alt_next
+ & EHCI_LIST_END(ehci)))
+ last_status = -EINPROGRESS;
+
+ /* As part of low/full-speed endpoint-halt processing
+ * we must clear the TT buffer (11.17.5).
+ */
+ if (unlikely(last_status != -EINPROGRESS &&
+ last_status != -EREMOTEIO)) {
+ /* The TT's in some hubs malfunction when they
+ * receive this request following a STALL (they
+ * stop sending isochronous packets). Since a
+ * STALL can't leave the TT buffer in a busy
+ * state (if you believe Figures 11-48 - 11-51
+ * in the USB 2.0 spec), we won't clear the TT
+ * buffer in this case. Strictly speaking this
+ * is a violation of the spec.
+ */
+ if (last_status != -EPIPE)
+ ehci_clear_tt_buffer(ehci, qh, urb,
+ token);
+ }
}
- 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;
}
+
+ /* remove qtd; it's recycled after possible urb completion */
list_del (&qtd->qtd_list);
last = qtd;
+
+ /* reinit the xacterr counter for the next qtd */
+ qh->xacterrs = 0;
}
/* last urb's completion might still need calling */
@@ -767,6 +795,21 @@ halt:
ehci_qtd_free (ehci, last);
}
+ /* Do we need to rescan for URBs dequeued during a giveback? */
+ if (unlikely(qh->needs_rescan)) {
+ /* If the QH is already unlinked, do the rescan now. */
+ if (state == QH_STATE_IDLE)
+ goto rescan;
+
+ /* Otherwise we have to wait until the QH is fully unlinked.
+ * Our caller will start an unlink if qh->needs_rescan is
+ * set. But if an unlink has already started, nothing needs
+ * to be done.
+ */
+ if (state != QH_STATE_LINKED)
+ qh->needs_rescan = 0;
+ }
+
/* restore original state; caller must unlink or relink */
qh->qh_state = state;
@@ -774,21 +817,26 @@ halt:
* 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)) {
+ if (stopped != 0 || hw->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);
+ /* We won't refresh a QH that's linked (after the HC
+ * stopped the queue). That avoids a race:
+ * - HC reads first part of QH;
+ * - CPU updates that first part and the token;
+ * - HC reads rest of that QH, including token
+ * Result: HC gets an inconsistent image, and then
+ * DMAs to/from the wrong memory (corrupting it).
+ *
+ * That should be rare for interrupt transfers,
+ * except maybe high bandwidth ...
+ */
+
+ /* Tell the caller to start an unlink */
+ qh->needs_rescan = 1;
break;
/* otherwise, unlink already started */
}
五、编译内核
参考:http://blog.csdn.net/guowenyan001/article/details/38704775
六、启动KDB
6.1 激活KDB
echo "1" >/proc/sys/kernel/kdb
6.2 启动KDB
1. KDB处于激活状态,内核中有紧急情况时,会自动调用KDB。
2. 按下Pause键,手动调用KDB。(需要在单用户模式下 ,sudo init 1进入单用户模式)(参考资料,KDB使用2)
参考资料:
Linux内核调试器内幕:http://www.ibm.com/developerworks/cn/linux/l-kdbug/
KDB使用2:http://blog.csdn.net/cybertan/article/details/6574023(单用户模式下,按下Pause,手动调用KDB)
Linux 2.6.3.32内核编译安装kdb-v4.4-2.6.32:http://babybandf.blog.163.com/blog/static/61993532010715990178/ (解决2个错误问题)