linux EHCI DRIVER之中断处理函数ehci_irq()分析(二)

本文详细解释了 EHCI 异步传输机制中的 qh 和 qtd 如何协作完成数据传输,以及 scan_async 函数如何通过遍历和处理 qh 上的 qtd 链表,实现数据传输的扫尾工作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先上代码,

1. static void scan_async (struct ehci_hcd *ehci)

2. {

3.  struct ehci_qh *qh;

4.  bool check_unlinks_later = false;

5. 

6.  ehci->qh_scan_next = ehci->async->qh_next.qh;

7.  while (ehci->qh_scan_next) {

8.  qh = ehci->qh_scan_next;

9.  ehci->qh_scan_next = qh->qh_next.qh;

10. 

11.  /* clean any finished work for this qh */

12.  if (!list_empty(&qh->qtd_list)) {

13.  int temp;

14. 

15.  /*

16.   * Unlinks could happen here; completion reporting

17.   * drops the lock.  That's why ehci->qh_scan_next

18.   * always holds the next qh to scan; if the next qh

19.   * gets unlinked then ehci->qh_scan_next is adjusted

20.   * in single_unlink_async().

21.   */

22.  temp = qh_completions(ehci, qh);

23.  if (unlikely(temp)) {

24.  start_unlink_async(ehci, qh);

25.  } else if (list_empty(&qh->qtd_list)

26.  && qh->qh_state == QH_STATE_LINKED) {

27.  qh->unlink_cycle = ehci->async_unlink_cycle;

28.  check_unlinks_later = true;

29.  }

30.  }

31.  }

32. 

33.  /*

34.   * Unlink empty entries, reducing DMA usage as well

35.   * as HCD schedule-scanning costs.  Delay for any qh

36.   * we just scanned, there's a not-unusual case that it

37.   * doesn't stay idle for long.

38.   */

39.  if (check_unlinks_later && ehci->rh_state == EHCI_RH_RUNNING &&

40.  !(ehci->enabled_hrtimer_events &

41.  BIT(EHCI_HRTIMER_ASYNC_UNLINKS))) {

42.  ehci_enable_event(ehci, EHCI_HRTIMER_ASYNC_UNLINKS, true);

43.  ++ehci->async_unlink_cycle;

44.  }

45. }

46. 

    Asynchronous传输在EHCI中由qhqtd来完成的,从通信模型的抽象层面上来说,qhqtd分别代表了通信的一方,qh代表USB device方(准确的说是device上的endpoint),qtd代表CPU方(实际上是某块DMA内存区域)。分配给device endpointqh是伴随deviceHCD中一直存在的,只要device没有被拔出,为device endpoint分配的qh就是固定的;相对而言CPU方的用于数据传输的内存区域却是变化的,这也是显而易见的,所以在完成数据传输后分配的qtd会被回收。而scan_async()函数的工作就是去check传输的状况,并回收qtd

    首先了解一下EHCI asynchronous传输是怎样利用qhqtd来完成数据传输的。如图1所示,CPU通过由EHCI HC提供的一组register来与之交互,qhqtd是存在于内存中的数据段,HC需要从内存中将之读取到它的缓存中,HC正是通过EHCI提供的这组register中的AsyncListAddr获取到内存中qh的地址的。具体的过程是,CPU先把多个qh组成的一个循环队列头qh的物理地址写入AsyncListAddr中,HC再根据AsyncListAddr的值去内存寻址qh的所在位置。构成一个qh循环队列是通过qh结构体中的头四个字节,去指向下一个qh的物理地址实现的,并且最后一个qh将指回首个qh,而qtd则使依附在qh中的,即HC通过AsyncListAddr找到qh,在通过qh找到qtd。更详细的细节可参考EHCI spec

 

1

    Linuxehci driverqh的组织方式是先分配一个不依附于任何endpointqh数据结构,作为qh循环队列的头,这个qh不用于实际的数据传输,只用于寻址下一个qh,这个qh的物理地址写入AsyncListAddr,如图1所示,并把qh的虚拟地址保存在ehci->async中。

    回到qtd回收的讨论中来,scan_async()函数中第25行的qh_completions()函数完成了真正的qtd扫尾工作,那就先从这个qh_completions()说起,代码如下。

1. /*

2.  * Process and free completed qtds for a qh, returning URBs to drivers.

3.  * Chases up to qh->hw_current.  Returns nonzero if the caller should

4.  * unlink qh.

5.  */

6. static unsigned

7. qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)

8. {

9.  struct ehci_qtd *last, *end = qh->dummy;

10.  struct list_head *entry, *tmp;

11.  int last_status;

12.  int stopped;

13.  u8 state;

14.  struct ehci_qh_hw *hw = qh->hw;

15. 

16.  /* completions (or tasks on other cpus) must never clobber HALT

17.   * till we've gone through and cleaned everything up, even when

18.   * they add urbs to this qh's queue or mark them for unlinking.

19.   *

20.   * NOTE:  unlinking expects to be done in queue order.

21.   *

22.   * It's a bug for qh->qh_state to be anything other than

23.   * QH_STATE_IDLE, unless our caller is scan_async() or

24.   * scan_intr().

25.   */

26.  state = qh->qh_state;

27.  qh->qh_state = QH_STATE_COMPLETING;

28.  stopped = (state == QH_STATE_IDLE);

29. 

30.  rescan:

31.  last = NULL;

32.  last_status = -EINPROGRESS;

33.  qh->dequeue_during_giveback = 0;

34. 

35.  /* remove de-activated QTDs from front of queue.

36.   * after faults (including short reads), cleanup this urb

37.   * then let the queue advance.

38.   * if queue is stopped, handles unlinks.

39.   */

40.  list_for_each_safe (entry, tmp, &qh->qtd_list) {

41.  struct ehci_qtd *qtd;

42.  struct urb *urb;

43.  u32 token = 0;

44. 

45.  qtd = list_entry (entry, struct ehci_qtd, qtd_list);

46.  urb = qtd->urb;

47. 

48.  /* clean up any state from previous QTD ...*/

49.  if (last) {

50.  if (likely (last->urb != urb)) {

51.  ehci_urb_done(ehci, last->urb, last_status);

52.  last_status = -EINPROGRESS;

53.  }

54.  ehci_qtd_free (ehci, last);

55.  last = NULL;

56.  }

57. 

58.  /* ignore urbs submitted during completions we reported */

59.  if (qtd == end)

60.  break;

61. 

62.  /* hardware copies qtd out of qh overlay */

63.  rmb ();

64.  token = hc32_to_cpu(ehci, qtd->hw_token);

65. 

66.  /* always clean up qtds the hc de-activated */

67.  retry_xacterr:

68.  if ((token & QTD_STS_ACTIVE) == 0) {

69. 

70.  /* Report Data Buffer Error: non-fatal but useful */

71.  if (token & QTD_STS_DBE)

72.  ehci_dbg(ehci,

73.  "detected DataBufferErr for urb %p ep%d%s len %d, qtd %p [qh %p]\n",

74.  urb,

75.  usb_endpoint_num(&urb->ep->desc),

76.  usb_endpoint_dir_in(&urb->ep->desc) ? "in" : "out",

77.  urb->transfer_buffer_length,

78.  qtd,

79.  qh);

80. 

81.  /* on STALL, error, and short reads this urb must

82.   * complete and all its qtds must be recycled.

83.   */

84.  if ((token & QTD_STS_HALT) != 0) {

85. 

86.  /* retry transaction errors until we

87.   * reach the software xacterr limit

88.   */

89.  if ((token & QTD_STS_XACT) &&

90.  QTD_CERR(token) == 0 &&

91.  ++qh->xacterrs < QH_XACTERR_MAX &&

92.  !urb->unlinked) {

93.  ehci_dbg(ehci,

94.  "detected XactErr len %zu/%zu retry %d\n",

95.  qtd->length - QTD_LENGTH(token), qtd->length, qh->xacterrs);

96. 

97.  /* reset the token in the qtd and the

98.   * qh overlay (which still contains

99.   * the qtd) so that we pick up from

100.   * where we left off

101.   */

102.  token &= ~QTD_STS_HALT;

103.  token |= QTD_STS_ACTIVE |

104.  (EHCI_TUNE_CERR << 10);

105.  qtd->hw_token = cpu_to_hc32(ehci,

106.  token);

107.  wmb();

108.  hw->hw_token = cpu_to_hc32(ehci,

109.  token);

110.  goto retry_xacterr;

111.  }

112.  stopped = 1;

113. 

114.  /* magic dummy for some short reads; qh won't advance.

115.   * that silicon quirk can kick in with this dummy too.

116.   *

117.   * other short reads won't stop the queue, including

118.   * control transfers (status stage handles that) or

119.   * most other single-qtd reads ... the queue stops if

120.   * URB_SHORT_NOT_OK was set so the driver submitting

121.   * the urbs could clean it up.

122.   */

123.  } else if (IS_SHORT_READ (token)

124.  && !(qtd->hw_alt_next

125.  & EHCI_LIST_END(ehci))) {

126.  stopped = 1;

127.  }

128. 

129.  /* stop scanning when we reach qtds the hc is using */

130.  } else if (likely (!stopped

131.  && ehci->rh_state >= EHCI_RH_RUNNING)) {

132.  break;

133. 

134.  /* scan the whole queue for unlinks whenever it stops */

135.  } else {

136.  stopped = 1;

137. 

138.  /* cancel everything if we halt, suspend, etc */

139.  if (ehci->rh_state < EHCI_RH_RUNNING)

140.  last_status = -ESHUTDOWN;

141. 

142.  /* this qtd is active; skip it unless a previous qtd

143.   * for its urb faulted, or its urb was canceled.

144.   */

145.  else if (last_status == -EINPROGRESS && !urb->unlinked)

146.  continue;

147. 

148.  /*

149.   * If this was the active qtd when the qh was unlinked

150.   * and the overlay's token is active, then the overlay

151.   * hasn't been written back to the qtd yet so use its

152.   * token instead of the qtd's.  After the qtd is

153.   * processed and removed, the overlay won't be valid

154.   * any more.

155.   */

156.  if (state == QH_STATE_IDLE &&

157.  qh->qtd_list.next == &qtd->qtd_list &&

158.  (hw->hw_token & ACTIVE_BIT(ehci))) {

159.  token = hc32_to_cpu(ehci, hw->hw_token);

160.  hw->hw_token &= ~ACTIVE_BIT(ehci);

161. 

162.  /* An unlink may leave an incomplete

163.   * async transaction in the TT buffer.

164.   * We have to clear it.

165.   */

166.  ehci_clear_tt_buffer(ehci, qh, urb, token);

167.  }

168.  }

169. 

170.  /* unless we already know the urb's status, collect qtd status

171.   * and update count of bytes transferred.  in common short read

172.   * cases with only one data qtd (including control transfers),

173.   * queue processing won't halt.  but with two or more qtds (for

174.   * example, with a 32 KB transfer), when the first qtd gets a

175.   * short read the second must be removed by hand.

176.   */

177.  if (last_status == -EINPROGRESS) {

178.  last_status = qtd_copy_status(ehci, urb,

179.  qtd->length, token);

180.  if (last_status == -EREMOTEIO

181.  && (qtd->hw_alt_next

182.  & EHCI_LIST_END(ehci)))

183.  last_status = -EINPROGRESS;

184. 

185.  /* As part of low/full-speed endpoint-halt processing

186.   * we must clear the TT buffer (11.17.5).

187.   */

188.  if (unlikely(last_status != -EINPROGRESS &&

189.  last_status != -EREMOTEIO)) {

190.  /* The TT's in some hubs malfunction when they

191.   * receive this request following a STALL (they

192.   * stop sending isochronous packets).  Since a

193.   * STALL can't leave the TT buffer in a busy

194.   * state (if you believe Figures 11-48 - 11-51

195.   * in the USB 2.0 spec), we won't clear the TT

196.   * buffer in this case.  Strictly speaking this

197.   * is a violation of the spec.

198.   */

199.  if (last_status != -EPIPE)

200.  ehci_clear_tt_buffer(ehci, qh, urb,

201.  token);

202.  }

203.  }

204. 

205.  /* if we're removing something not at the queue head,

206.   * patch the hardware queue pointer.

207.   */

208.  if (stopped && qtd->qtd_list.prev != &qh->qtd_list) {

209.  last = list_entry (qtd->qtd_list.prev,

210.  struct ehci_qtd, qtd_list);

211.  last->hw_next = qtd->hw_next;

212.  }

213. 

214.  /* remove qtd; it's recycled after possible urb completion */

215.  list_del (&qtd->qtd_list);

216.  last = qtd;

217. 

218.  /* reinit the xacterr counter for the next qtd */

219.  qh->xacterrs = 0;

220.  }

221. 

222.  /* last urb's completion might still need calling */

223.  if (likely (last != NULL)) {

224.  ehci_urb_done(ehci, last->urb, last_status);

225.  ehci_qtd_free (ehci, last);

226.  }

227. 

228.  /* Do we need to rescan for URBs dequeued during a giveback? */

229.  if (unlikely(qh->dequeue_during_giveback)) {

230.  /* If the QH is already unlinked, do the rescan now. */

231.  if (state == QH_STATE_IDLE)

232.  goto rescan;

233. 

234.  /* Otherwise the caller must unlink the QH. */

235.  }

236. 

237.  /* restore original state; caller must unlink or relink */

238.  qh->qh_state = state;

239. 

240.  /* be sure the hardware's done with the qh before refreshing

241.   * it after fault cleanup, or recovering from silicon wrongly

242.   * overlaying the dummy qtd (which reduces DMA chatter).

243.   *

244.   * We won't refresh a QH that's linked (after the HC

245.   * stopped the queue).  That avoids a race:

246.   *  - HC reads first part of QH;

247.   *  - CPU updates that first part and the token;

248.   *  - HC reads rest of that QH, including token

249.   * Result:  HC gets an inconsistent image, and then

250.   * DMAs to/from the wrong memory (corrupting it).

251.   *

252.   * That should be rare for interrupt transfers,

253.   * except maybe high bandwidth ...

254.   */

255.  if (stopped != 0 || hw->hw_qtd_next == EHCI_LIST_END(ehci))

256.  qh->exception = 1;

257. 

258.  /* Let the caller know if the QH needs to be unlinked. */

259.  return qh->exception;

260. }

    函数qh_completions()比较长,但几个if-else的判断语句占了大部分,qh_completions()中通过对qh下链接的qtd进行逐个遍历,来判断传输的情况,HC会把传输的实际状况值回写到qtd中的token字段的status中,Status共有8位,每一位都单独代表一种传输状态,除第7位外均代表了一种出错状态。所以对这样的一段if-else语句,如果数据传输中没有出错,大部分的代码都是会被bypass掉的。

    还是从头讲起吧,第40行的list_for_each_safe中对qtd_list进行遍历,其中函数qh_completions()的参数qh上关联了一个qtd队列,list_for_each_safe逐个的把qh上的qtd取出放在指针entry中,list_for_each_safe的特点是可以中途删除entry,通过指针tmp去找到下一个entry

    第44行,list_entry得到entry所指qtd的指针地址,放在指针变量qtd,通过这样几步就找出了qtd的数据结构实际在内存中的地址。得到这些qtd的实际所在后,就要根据其的实际情况进行处理。

    第47行,指针last的初始值为NULL,首次执行到这里时,直接跳过整个if语句,当再一次执行到此处时,如果前一次的处理中有qtd是执行完传输的(包括传输出错),last此时就会指向了前一个qtd,并在if语句中的ehci_qtd_free()函数中把分配的qtd空间释放掉。由多个qtd形成的队列是一个单向链表,链表的末尾的qtd被设置成不可用的状态,表示传输的完结点,可以通过qh->dummy指针找到这个qtd,即这个qtd是一个dummy,实际的内容为空,用于标记qtd链表的结束。一个qtd链表中的urb指针的指向都是相同的,除了最末这一个dummy qtd,所以在遍历到最后的qtd时“last->urb != urb”满足。49ehci_urb_done()会被调用,ehci_urb_done()要做的一件事是回调urb->complete()函数指针,从而使控制权回到USB device Driver中,这就是我们填充一个urb的回调函数的触发处。57行的判断遍历到最后的dummy qtd,就跳出循环,表明整个qtd链表已被处理完了。

    前面讲过,HC在处理完一个qtd后,反映处理结果的值会回写到当前qtdtoken字段中,HCD读取这个tokenStatus值后,可以获知HC的传输情况。第61行把qtdtoken值暂存到变量token中。Token[7:0]位是状态值,其中第7位为Active位,由HCD1,表明qtd处于激活状态,这样HC可能正在处理该qtd,或准备处理。当传输完成或出错后,Active位由HC0。如果执行该段代码是由中断触发的,那么Active位一定为0,即有一次传输结束。如果是由timer polling执行到此处,那么Active位的值就可能为01,即不一定有传输完成。这里假设捕获到一次qtd的传输完成了,即Active位等于0,看看接下来的处理。

    第66行处,是对Data Buffer Error的处理,token5位被置1,表明发生了这样的错误。这样的错误,在EHCI SPEC里说,不被视作传输错误,会强制endpoint重发一次,所以代码也只是做了打印。

    如果有一次qtd的传输完成,Active位被置为0,进入64行的if语句内部。接下来就是一个检测处理了,token的第6位为Halted位,当该位被HC1时,就表明当前qtd的传输出现了错误,而且与该endpoint的传输都被停掉,同时Active位会被置0Halted位被置1,不能确切的知道错误的类型和原因,token3位进一步指明了halted的原因。Token的第3XactErr当被HC1时,表明HC没有收到device发回的有效应答包,这时HC的传输已经停下来了,传输出错的qtd依然保留在qhoverlay中,出现这样的错误HCD的处理方式是,由软件把Halted位清零,token[11:10] CERR位设为0x3Active位置1再次使能该qtd,让HC重新传输这个qtd。第102行的goto语句返回到retry_xacterr处,重复以上动作,直到传输成功为止。

    如前面的假设Active位为1,那么接下来的else-if-else代码段,就可以忽略了,这两段代码checkHC的运行状态,120-122行检测到HC正在running,所以什么都不做,跳出循环。

    第153行,变量last_status通过qtd_copy_status()获取到,前面代码对一次qtd的传输后的状态处理是针对halted的,在函数qtd_copy_status()中会把实际传输的数据长度更新到urb->actual_length中,如果一个qtd上的数据只完成了部分的传输,即实际传输的数据量小于要求的传输量,那么会被视为一个SHORT错误,qtd_copy_status()会返回这些错误值。

    在182行处的变量stopped104行赋值为1,指针qtd如果指向qtd链表的首个qtd,那么qtd->qtd_list.prev 就指向了qh->qtd_list,qtd链表上的传输要按这样的链表上的顺序依次传输,一旦qtd上的传输完成了,也应该是依次被从链表上remove,被移除的qtd的下一个qtd就被挪到链表首,如果将要从链表上移除的qtd的前一项未指向链表头,而是另一个qtd,这里要把这前一个qtd-> hw_next等于当前要被移除qtd-> hw_next的值。由多个qtd构成的链表,在HC看来是通过物理地址相连的单向链表,在HCD看来是一个双向的链表。

    在188行处把qtd从链表队列中删除,指针last此时就指向这个被移除的qtd,如果qtd不是链表的末项,再一次的循环时47行处qtd被真正的回收。

    前面讲过整个遍历会从58break语句退出,即遍历到dummy qtd后,结束退出。从193行开始,如果指针last非空,那么一定是指向一个qtd链表队列的末尾处(非dummy qtd,前面提到过一个qtd链表队列,构成了一个完整的逻辑传输,整个qtd list被传输完毕后,就可以通知usb device driver即调用urb->complete()回调函数了。最再将这个qtd的空间回收。

    在这里整个qh_completions()函数就差不多讲完了,后面的两个if判断语句,一个是关于再次遍历的问题,另一个是对qh进行refresh。关于qh_refresh()函数可以参考前面的文章。最后qh_completions()函数返回count值,如果成功的完成了一次qtd队列的处理,count返回1

    对qh_completions()做一个小结,对qh上连接的qtd队列,在完成传输后,对qtd项做后续的处理。

 

    现在回到函数scan_async()中,刚才把最长的qh_completions()函数讲完了,现在来讲scan_async()函数就轻松多了。在贴一次scan_async()的代码。

static void scan_async (struct ehci_hcd *ehci)

{

bool stopped;

struct ehci_qh *qh;

enum ehci_timer_action action = TIMER_IO_WATCHDOG;

 

timer_action_done (ehci, TIMER_ASYNC_SHRINK);

stopped = (ehci->rh_state != EHCI_RH_RUNNING);

 

ehci->qh_scan_next = ehci->async->qh_next.qh;

while (ehci->qh_scan_next) {

qh = ehci->qh_scan_next;

ehci->qh_scan_next = qh->qh_next.qh;

 rescan:

/* clean any finished work for this qh */

if (!list_empty(&qh->qtd_list)) {

int temp;

 

/*

 * Unlinks could happen here; completion reporting

 * drops the lock.  That's why ehci->qh_scan_next

 * always holds the next qh to scan; if the next qh

 * gets unlinked then ehci->qh_scan_next is adjusted

 * in start_unlink_async().

 */

qh = qh_get(qh);

temp = qh_completions(ehci, qh);

if (qh->needs_rescan)

unlink_async(ehci, qh);

qh->unlink_time = jiffies + EHCI_SHRINK_JIFFIES;

qh_put(qh);

if (temp != 0)

goto rescan;

}

 

/* unlink idle entries, reducing DMA usage as well

 * as HCD schedule-scanning costs.  delay for any qh

 * we just scanned, there's a not-unusual case that it

 * doesn't stay idle for long.

 * (plus, avoids some kind of re-activation race.)

 */

if (list_empty(&qh->qtd_list)

&& qh->qh_state == QH_STATE_LINKED) {

if (!ehci->reclaim && (stopped ||

time_after_eq(jiffies, qh->unlink_time)))

start_unlink_async(ehci, qh);

else

action = TIMER_ASYNC_SHRINK;

}

}

if (action == TIMER_ASYNC_SHRINK)

timer_action (ehci, TIMER_ASYNC_SHRINK);

}

    前面在分析qh_completions()时,知道其是对qtd链表队列进行遍历逐项处理,而这些qtd队列是与某个qh相关联的。类似scan_async()是对qh构成的队列进行遍历,逐个处理qh。如图1右侧所示,即是qh构成的链表。在内存中qhqtd的组成的数据结构,应是图2所示的连接结构,最后的一个qhnext应该指向头个qh,形成一个循环,如图1,这里没有画出来。图中的scan_async箭头,表明了scan_async()函数负责qh的处理,箭头qh_completions是对qtd的处理。

2

    结合图2来表述scan_async()的流程,来qh的循环队列中,依次取出各个qh,并把qh上的qtd_list交给qh_completions()处理。

    函数scan_async()的代码分析就到此为止了。

 

原文:http://blog.youkuaiyun.com/yaongtime/article/details/19755143

[ 38.584592][ C7] SError Interrupt on CPU7, code 0xbe000011 -- SError [ 38.584593][ C7] CPU: 7 PID: 417 Comm: provider@2.4-ex Not tainted 5.10.160 #421 [ 38.584594][ C7] Hardware name: Embedfire LubanCat-5IO (DT) [ 38.584595][ C7] pstate: 60400009 (nZCv daif +PAN -UAO -TCO BTYPE=--) [ 38.584595][ C7] pc : rkcif_write_register_and+0x104/0x134 [ 38.584596][ C7] lr : rkcif_csi_channel_set_v1+0x84/0xc80 [ 38.584597][ C7] sp : ffffffc00bd23810 [ 38.584597][ C7] x29: ffffffc00bd23810 x28: 0000000000000003 [ 38.584599][ C7] x27: ffffff81013d8880 x26: 000000000000bbf4 [ 38.584601][ C7] x25: ffffff810373ce70 x24: 0000000000000005 [ 38.584602][ C7] x23: ffffff8103730080 x22: 0000000000000000 [ 38.584603][ C7] x21: 0000000000000001 x20: ffffff810373bbb8 [ 38.584605][ C7] x19: ffffff8103733ec8 x18: ffffffc00b5d5090 [ 38.584606][ C7] x17: ffffff810373bbbe x16: ffffff810373bbbf [ 38.584608][ C7] x15: 000000000000b915 x14: 0000000000000000 [ 38.584609][ C7] x13: ffffff810373bbd8 x12: 0000000000000000 [ 38.584610][ C7] x11: 0000000000000000 x10: 000000000000005b [ 38.584611][ C7] x9 : ffffffc009843478 x8 : ffffffc00c9f7000 [ 38.584613][ C7] x7 : 205d373134542020 x6 : ffffffc00a253dd8 [ 38.584614][ C7] x5 : ffffffffffffffff x4 : 0000000000000000 [ 38.584616][ C7] x3 : 00000000ff7f3f3f x2 : 000000000000005b [ 38.584617][ C7] x1 : 000000000000005b x0 : ffffff8103730080 [ 38.584618][ C7] Kernel panic - not syncing: Asynchronous SError Interrupt [ 38.584619][ C7] CPU: 7 PID: 417 Comm: provider@2.4-ex Not tainted 5.10.160 #421 [ 38.584620][ C7] Hardware name: Embedfire LubanCat-5IO (DT) [ 38.584621][ C7] Call trace: [ 38.584621][ C7] dump_backtrace+0x0/0x1c8 [ 38.584622][ C7] show_stack+0x18/0x24 [ 38.584622][ C7] dump_stack_lvl+0xcc/0x114 [ 38.584623][ C7] dump_stack+0x18/0x5c [ 38.584624][ C7] panic+0x154/0x39c [ 38.584624][ C7] test_taint+0x0/0x28 [ 38.584625][ C7] arm64_serror_panic+0x74/0x80 [ 38.584625][ C7] do_serror+0xd0/0xf0 [ 38.584626][ C7] el1_error+0x90/0x114 [ 38.584627][ C7] rkcif_write_register_and+0x104/0x134 [ 38.584627][ C7] rkcif_csi_channel_set_v1+0x84/0xc80 [ 38.584628][ C7] rkcif_csi_stream_start+0x9ac/0xd98 [ 38.584629][ C7] rkcif_do_start_stream+0xa98/0x1120 [ 38.584629][ C7] rkcif_start_streaming+0x18/0x24 [ 38.584630][ C7] vb2_start_streaming+0x60/0x134 [ 38.584631][ C7] vb2_core_streamon+0x10c/0x150 [ 38.584631][ C7] vb2_ioctl_streamon+0x5c/0x8c [ 38.584632][ C7] v4l_streamon+0x24/0x30 [ 38.584633][ C7] __video_do_ioctl+0x2d0/0x3e8 [ 38.584633][ C7] video_usercopy+0x3d4/0x80c [ 38.584634][ C7] video_ioctl2+0x18/0x24 [ 38.584635][ C7] v4l2_ioctl+0x4c/0x5c [ 38.584635][ C7] __arm64_sys_ioctl+0x90/0xc8 [ 38.584636][ C7] el0_svc_common+0xac/0x1ac [ 38.584636][ C7] do_el0_svc+0x1c/0x28 [ 38.584637][ C7] el0_svc+0x10/0x1c [ 38.584638][ C7] el0_sync_handler+0x68/0xac [ 38.584638][ C7] el0_sync+0x160/0x180 [ 38.584643][ C6] CPU6: stopping [ 38.584645][ C0] CPU0: stopping [ 38.584647][ C3] CPU3: stopping [ 38.584649][ C2] CPU2: stopping [ 38.584654][ C0] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.10.160 #421 [ 38.584696][ C4] CPU4: stopping [ 38.584698][ C1] CPU1: stopping [ 38.584704][ C5] CPU5: stopping [ 38.689741][ C0] Hardware name: Embedfire LubanCat-5IO (DT) [ 38.690252][ C0] Call trace: [ 38.690539][ C0] dump_backtrace+0x0/0x1c8 [ 38.690923][ C0] show_stack+0x18/0x24 [ 38.691284][ C0] dump_stack_lvl+0xcc/0x114 [ 38.691678][ C0] dump_stack+0x18/0x5c [ 38.692029][ C0] local_cpu_stop+0x68/0x84 [ 38.692413][ C0] smp_send_reschedule+0x0/0x3c [ 38.692830][ C0] handle_percpu_devid_fasteoi_ipi+0x78/0x194 [ 38.693354][ C0] __handle_domain_irq+0x7c/0xc8 [ 38.693782][ C0] gic_handle_irq+0x70/0x130 [ 38.694175][ C0] el1_irq+0xe0/0x1c0 [ 38.694517][ C0] cpuidle_enter_state+0x17c/0x3a0 [ 38.694953][ C0] cpuidle_enter+0x38/0x50 [ 38.695338][ C0] cpuidle_idle_call+0x14c/0x220 [ 38.695764][ C0] do_idle+0xa8/0xf0 [ 38.696093][ C0] cpu_startup_entry+0x24/0x28 [ 38.696498][ C0] rest_init+0xd4/0xe4 [ 38.696850][ C0] arch_call_rest_init+0x10/0x1c [ 38.697276][ C0] start_kernel+0x3a8/0x43c [ 38.697660][ C6] CPU: 6 PID: 424 Comm: allocator@4.0-s Not tainted 5.10.160 #421 [ 38.698328][ C6] Hardware name: Embedfire LubanCat-5IO (DT) [ 38.698841][ C6] Call trace: [ 38.699118][ C6] dump_backtrace+0x0/0x1c8 [ 38.699502][ C6] show_stack+0x18/0x24 [ 38.699853][ C6] dump_stack_lvl+0xcc/0x114 [ 38.700246][ C6] dump_stack+0x18/0x5c [ 38.700597][ C6] local_cpu_stop+0x68/0x84 [ 38.700982][ C6] smp_send_reschedule+0x0/0x3c [ 38.701399][ C6] handle_percpu_devid_fasteoi_ipi+0x78/0x194 [ 38.701913][ C6] __handle_domain_irq+0x7c/0xc8 [ 38.702339][ C6] gic_handle_irq+0x70/0x130 [ 38.702733][ C6] el1_irq+0xe0/0x1c0 [ 38.703074][ C6] _raw_spin_lock+0x3c/0x70 [ 38.703460][ C6] remap_pfn_range+0x174/0x270 [ 38.703867][ C6] system_heap_mmap+0xc0/0x108 [ 38.704272][ C6] dma_buf_mmap_internal+0x60/0x64 [ 38.704710][ C6] mmap_region+0x3e0/0x87c [ 38.705083][ C6] do_mmap+0x42c/0x510 [ 38.705433][ C6] vm_mmap_pgoff+0xac/0x114 [ 38.705816][ C6] ksys_mmap_pgoff+0x78/0xf0 [ 38.706211][ C6] __arm64_sys_mmap+0x34/0x40 [ 38.706605][ C6] el0_svc_common+0xac/0x1ac [ 38.707000][ C6] do_el0_svc+0x1c/0x28 [ 38.707351][ C6] el0_svc+0x10/0x1c [ 38.707680][ C6] el0_sync_handler+0x68/0xac [ 38.708074][ C6] el0_sync+0x160/0x180 [ 38.708426][ C1] CPU: 1 PID: 0 Comm: swapper/1 Not tainted 5.10.160 #421 [ 38.709038][ C1] Hardware name: Embedfire LubanCat-5IO (DT) [ 38.709550][ C1] Call trace: [ 38.709837][ C1] dump_backtrace+0x0/0x1c8 [ 38.710220][ C1] show_stack+0x18/0x24 [ 38.710582][ C1] dump_stack_lvl+0xcc/0x114 [ 38.710975][ C1] dump_stack+0x18/0x5c [ 38.711326][ C1] local_cpu_stop+0x68/0x84 [ 38.711710][ C1] smp_send_reschedule+0x0/0x3c [ 38.712126][ C1] handle_percpu_devid_fasteoi_ipi+0x78/0x194 [ 38.712649][ C1] __handle_domain_irq+0x7c/0xc8 [ 38.713075][ C1] gic_handle_irq+0x70/0x130 [ 38.713469][ C1] el1_irq+0xe0/0x1c0 [ 38.713810][ C1] cpuidle_enter_state+0x17c/0x3a0 [ 38.714246][ C1] cpuidle_enter+0x38/0x50 [ 38.714630][ C1] cpuidle_idle_call+0x14c/0x220 [ 38.715056][ C1] do_idle+0xa8/0xf0 [ 38.715386][ C1] cpu_startup_entry+0x24/0x28 [ 38.715791][ C1] secondary_start_kernel+0x1a8/0x24c [ 38.716251][ C2] CPU: 2 PID: 0 Comm: swapper/2 Not tainted 5.10.160 #421 [ 38.716863][ C2] Hardware name: Embedfire LubanCat-5IO (DT) [ 38.717375][ C2] Call trace: [ 38.717662][ C2] dump_backtrace+0x0/0x1c8 [ 38.718045][ C2] show_stack+0x18/0x24 [ 38.718397][ C2] dump_stack_lvl+0xcc/0x114 [ 38.718790][ C2] dump_stack+0x18/0x5c [ 38.719151][ C2] local_cpu_stop+0x68/0x84 [ 38.719535][ C2] smp_send_reschedule+0x0/0x3c [ 38.719951][ C2] handle_percpu_devid_fasteoi_ipi+0x78/0x194 [ 38.720474][ C2] __handle_domain_irq+0x7c/0xc8 [ 38.720900][ C2] gic_handle_irq+0x70/0x130 [ 38.721294][ C2] el1_irq+0xe0/0x1c0 [ 38.721634][ C2] cpuidle_enter_state+0x17c/0x3a0 [ 38.722071][ C2] cpuidle_enter+0x38/0x50 [ 38.722454][ C2] cpuidle_idle_call+0x14c/0x220 [ 38.722880][ C2] do_idle+0xa8/0xf0 [ 38.723209][ C2] cpu_startup_entry+0x24/0x28 [ 38.723614][ C2] secondary_start_kernel+0x1a8/0x24c [ 38.724074][ C3] CPU: 3 PID: 0 Comm: swapper/3 Not tainted 5.10.160 #421 [ 38.724686][ C3] Hardware name: Embedfire LubanCat-5IO (DT) [ 38.725198][ C3] Call trace: [ 38.725485][ C3] dump_backtrace+0x0/0x1c8 [ 38.725868][ C3] show_stack+0x18/0x24 [ 38.726230][ C3] dump_stack_lvl+0xcc/0x114 [ 38.726623][ C3] dump_stack+0x18/0x5c [ 38.726985][ C3] local_cpu_stop+0x68/0x84 [ 38.727368][ C3] smp_send_reschedule+0x0/0x3c [ 38.727784][ C3] handle_percpu_devid_fasteoi_ipi+0x78/0x194 [ 38.728308][ C3] __handle_domain_irq+0x7c/0xc8 [ 38.728734][ C3] gic_handle_irq+0x70/0x130 [ 38.729128][ C3] el1_irq+0xe0/0x1c0 [ 38.729468][ C3] cpuidle_enter_state+0x17c/0x3a0 [ 38.729905][ C3] cpuidle_enter+0x38/0x50 [ 38.730288][ C3] cpuidle_idle_call+0x14c/0x220 [ 38.730714][ C3] do_idle+0xa8/0xf0 [ 38.731043][ C3] cpu_startup_entry+0x24/0x28 [ 38.731448][ C3] secondary_start_kernel+0x1a8/0x24c [ 38.731908][ C4] CPU: 4 PID: 0 Comm: swapper/4 Not tainted 5.10.160 #421 [ 38.732519][ C4] Hardware name: Embedfire LubanCat-5IO (DT) [ 38.733031][ C4] Call trace: [ 38.733313][ C4] dump_backtrace+0x0/0x1c8 [ 38.733703][ C4] show_stack+0x18/0x24 [ 38.734060][ C4] dump_stack_lvl+0xcc/0x114 [ 38.734450][ C4] dump_stack+0x18/0x5c [ 38.734808][ C4] local_cpu_stop+0x68/0x84 [ 38.735198][ C4] smp_send_reschedule+0x0/0x3c [ 38.735612][ C4] handle_percpu_devid_fasteoi_ipi+0x78/0x194 [ 38.736136][ C4] __handle_domain_irq+0x7c/0xc8 [ 38.736560][ C4] gic_handle_irq+0x70/0x130 [ 38.736950][ C4] el1_irq+0xe0/0x1c0 [ 38.737286][ C4] cpuidle_enter_state+0x17c/0x3a0 [ 38.737721][ C4] cpuidle_enter+0x38/0x50 [ 38.738099][ C4] cpuidle_idle_call+0x14c/0x220 [ 38.738524][ C4] do_idle+0xa8/0xf0 [ 38.738859][ C4] cpu_startup_entry+0x24/0x28 [ 38.739261][ C4] secondary_start_kernel+0x1a8/0x24c [ 38.739721][ C5] CPU: 5 PID: 0 Comm: swapper/5 Not tainted 5.10.160 #421 [ 38.740331][ C5] Hardware name: Embedfire LubanCat-5IO (DT) [ 38.740843][ C5] Call trace: [ 38.741124][ C5] dump_backtrace+0x0/0x1c8 [ 38.741514][ C5] show_stack+0x18/0x24 [ 38.741871][ C5] dump_stack_lvl+0xcc/0x114 [ 38.742262][ C5] dump_stack+0x18/0x5c [ 38.742619][ C5] local_cpu_stop+0x68/0x84 [ 38.742999][ C5] smp_send_reschedule+0x0/0x3c [ 38.743412][ C5] handle_percpu_devid_fasteoi_ipi+0x78/0x194 [ 38.743935][ C5] __handle_domain_irq+0x7c/0xc8 [ 38.744358][ C5] gic_handle_irq+0x70/0x130 [ 38.744747][ C5] el1_irq+0xe0/0x1c0 [ 38.745082][ C5] cpuidle_enter_state+0x17c/0x3a0 [ 38.745517][ C5] cpuidle_enter+0x38/0x50 [ 38.745897][ C5] cpuidle_idle_call+0x14c/0x220 [ 38.746320][ C5] do_idle+0xa8/0xf0 [ 38.746656][ C5] cpu_startup_entry+0x24/0x28 [ 38.747067][ C5] secondary_start_kernel+0x1a8/0x24c [ 39.749199][ C7] rockchip-thermal fec00000.tsadc: channal 0: temperature(40 C) [ 39.749874][ C7] cpu cpu6: cur_freq: 1608000000 Hz, volt_vdd: 700000 uV, volt_mem: 700000 uV [ 39.750630][ C7] cpu cpu4: cur_freq: 1200000000 Hz, volt_vdd: 675000 uV, volt_mem: 675000 uV [ 39.751384][ C7] cpu cpu0: cur_freq: 1800000000 Hz, volt_vdd: 875000 uV, volt_mem: 875000 uV [ 39.752141][ C7] rockchip-dmc dmc: cur_freq: 1560000000 Hz, volt_vdd: 725000 uV, volt_mem: 700000 uV [ 39.752962][ C7] SMP: stopping secondary CPUs [ 39.752963][ C7] CRU REGS: [ 39.752963][ C7] LPLL 0x58040: 00000110 00002082 00000000 00000000 00000002 000007e0 00004000 00000000 [ 39.752965][ C7] B0PLL 0x50000: 00000110 00002082 00000000 00000000 00000002 000007e0 00004000 00000000 [ 39.752966][ C7] B1PLL 0x52020: 00000110 00002082 00000000 00000000 00000002 000007e0 00004000 00000000 [ 39.752968][ C7] GPLL 0x001c0: 000000c6 00000042 00000000 00000000 00000000 00000000 00009400 00000000 [ 39.752969][ C7] CPLL 0x001a0: 000000fa 00000042 00000000 00000000 00000000 00000000 00009c00 00000000 [ 39.752970][ C7] V0PLL 0x00160: 000000c6 00002042 00000000 00000000 00000000 00000000 00004000 00000000 [ 39.752972][ C7] AUPLL 0x00180: 00000106 00000082 ffff24dd 00000000 00000000 00000000 0000a000 00000000 [ 39.752973][ C7] PPLL 0x08200: 00000226 00002083 00000000 00000000 00000000 00000000 00004000 00000000 [ 39.752974][ C7] DSUCRU_SEL 0x58300: 0000b0c0 00001083 00000843 00000063 00000665 0000403f 000020c1 0000e0c1 [ 39.752976][ C7] DSUCRU_GATE 0x58800: 00000000 00000000 00000063 00000000 00000000 00000000 00000000 00000000 [ 39.752977][ C7] BIG0CRU_SEL 0x50300: 00004240 00005fc2 00000005 00000000 00000000 00000000 00000000 00000000 [ 39.752978][ C7] BIG0CRU_GATE 0x50800: 00003400 00000001 00000000 00000000 00000000 00000000 00000000 00000000 [ 39.752980][ C7] BIG1CRU_SEL 0x52300: 00004240 00005fc2 00000005 00000000 00000000 00000000 00000000 00000000 [ 39.752981][ C7] BIG1CRU_GATE 0x52800: 00003400 00000001 00000000 00000000 00000000 00000000 00000000 00000000 [ 39.752983][ C7] CRU_SEL 0x00300: 00000bbd 00000169 00000925 000000a1 00000881 00000881 00000820 00000020 [ 39.752984][ C7] CRU_SEL 0x00320: 00000881 00000881 00000820 00000020 00000421 00000000 000030ff 00000000 [ 39.752985][ C7] CRU_SEL 0x00340: 00000421 00000000 000030ff 00000000 00000000 00000000 00000000 0000bb9d [ 39.752987][ C7] CRU_SEL 0x00360: 00000000 00000000 00000000 0000bb9d 000000bb 00000200 00000000 00000000 [ 39.752988][ C7] CRU_SEL 0x00380: 000000bb 00000200 00000000 00000000 00000000 00000000 00000000 00000000 [ 39.752990][ C7] CRU_SEL 0x003a0: 00000000 00000000 00000000 00000000 00000010 03355460 00000007 03355460 [ 39.752991][ C7] CRU_SEL 0x003c0: 00000010 03355460 00000007 03355460 0000001b 03355460 0000000f 03355460 [ 39.752992][ C7] CRU_SEL 0x003e0: 0000001b 03355460 0000000f 03355460 0000000f 03355460 00000006 03355460 [ 39.752994][ C7] CRU_SEL 0x00400: 0000000f 03355460 00000006 03355460 00000092 00000000 00000023 000002cb [ 39.752995][ C7] CRU_SEL 0x00420: 00000092 00000000 00000023 000002cb 000045cb 0000030b 001403de 00000006 [ 39.752996][ C7] CRU_SEL 0x00440: 000045cb 0000030b 001403de 00000006 001403de 00000006 001403de 00000006 [ 39.752998][ C7] CRU_SEL 0x00460: 001403de 00000006 001403de 00000006 001403de 00000006 001403de 00000006 [ 39.752999][ C7] CRU_SEL 0x00480: 001403de 00000006 001403de 00000006 001403de 00000006 001403de 00000006 [ 39.753001][ C7] CRU_SEL 0x004a0: 001403de 00000006 001403de 00000006 001403de 00000006 001403de 00008002 [ 39.753002][ C7] CRU_SEL 0x004c0: 001403de 00000006 001403de 00008002 0000020a 00000041 000003ff 0000003f [ 39.753003][ C7] CRU_SEL 0x004e0: 0000020a 00000041 000003ff 0000003f 00000000 0000003f 00000000 0000c021 [ 39.753005][ C7] CRU_SEL 0x00500: 00000000 0000003f 00000000 0000c021 00000000 00000000 00000000 00000000 [ 39.753006][ C7] CRU_SEL 0x00520: 00000000 00000000 00000000 00000000 00000000 00007c14 00001010 00000000 [ 39.753007][ C7] CRU_SEL 0x00540: 00000000 00007c14 00001010 00000000 00000000 00000590 00000385 00000000 [ 39.753009][ C7] CRU_SEL 0x00560: 00000000 00000590 00000385 00000000 00000288 0000070e 00009d9d 00008b9d [ 39.753010][ C7] CRU_SEL 0x00580: 00000288 0000070e 00009d9d 00008b9d 0000049d 00000000 00000000 00000000 [ 39.753012][ C7] CRU_SEL 0x005a0: 0000049d 00000000 00000000 00000000 00000000 00000300 00001801 00000001 [ 39.753013][ C7] CRU_SEL 0x005c0: 00000000 00000300 00001801 00000001 00000000 00000300 000000e0 00000000 [ 39.753015][ C7] CRU_GATE 0x00800: 00000900 00000140 00000050 00004000 00000008 00003e78 00000000 0000fff3 [ 39.753016][ C7] CRU_GATE 0x00820: 00000008 00003e78 00000000 0000fff3 0000c01f 000000ff 0000ffe0 00003fff [ 39.753017][ C7] CRU_GATE 0x00840: 0000c01f 000000ff 0000ffe0 00003fff 0000fff4 0000fffe 0000ffff 00002ff8 [ 39.753019][ C7] CRU_GATE 0x00860: 0000fff4 0000fffe 0000ffff 00002ff8 00003fff 000001c0 00003e00 00000000 [ 39.753020][ C7] CRU_GATE 0x00880: 00003fff 000001c0 00003e00 00000000 0000aa05 000000a0 00000263 0000aa05 [ 39.753022][ C7] CRU_GATE 0x008a0: 0000aa05 000000a0 00000263 0000aa05 000000a0 00000263 000001ff 00000005 [ 39.753023][ C7] CRU_GATE 0x008c0: 000000a0 00000263 000001ff 00000005 00000005 0000ffd7 0000016a 00000e00 [ 39.753024][ C7] CRU_GATE 0x008e0: 00000005 0000ffd7 0000016a 00000e00 0000ed19 0000ffff 00000dbf 000007e0 [ 39.753026][ C7] CRU_GATE 0x00900: 0000ed19 0000ffff 00000dbf 000007e0 00000000 00001ff7 0000e3f8 00000003 [ 39.753027][ C7] CRU_GATE 0x00920: 00000000 00001ff7 0000e3f8 00000003 000003ff 000001ff 00003000 00000000 [ 39.753028][ C7] PMUCRU_SEL 0x30300: 000000b7 00000400 00000020 00000080 001403de 00000006 03355460 00000007 [ 39.753030][ C7] PMUCRU_SEL 0x30320: 001403de 00000006 03355460 00000007 03355460 0000000b 00000000 00000000 [ 39.753031][ C7] PMUCRU_SEL 0x30340: 03355460 0000000b 00000000 00000000 00000000 00000000 00000000 00000000 [ 39.753033][ C7] PMUCRU_GATE 0x30800: 00000009 00005fc0 0000fff8 00000001 00000800 00000000 00000000 00000000 [ 39.753034][ C7] CPU0 online:0 [ 39.753035][ C7] EL2(NS) PC: <0xffffffc00801b8d8> local_cpu_stop+0x44/0x84 [ 39.753035][ C7] [ 39.753036][ C7] CPU1 online:0 [ 39.753037][ C7] EL2(NS) PC: <0xffffffc00801b8d8> local_cpu_stop+0x44/0x84 [ 39.753037][ C7] [ 39.753038][ C7] CPU2 online:0 [ 39.753039][ C7] EL2(NS) PC: <0xffffffc00801b8d8> local_cpu_stop+0x44/0x84 [ 39.753039][ C7] [ 39.753040][ C7] CPU3 online:0 [ 39.753041][ C7] EL2(NS) PC: <0xffffffc00801b8d8> local_cpu_stop+0x44/0x84 [ 39.753041][ C7] [ 39.753041][ C7] CPU4 online:0 [ 39.753042][ C7] EL2(NS) PC: <0xffffffc00801b8d8> local_cpu_stop+0x44/0x84 [ 39.753043][ C7] [ 39.753043][ C7] CPU5 online:0 [ 39.753044][ C7] EL2(NS) PC: <0xffffffc00801b8d8> local_cpu_stop+0x44/0x84 [ 39.753044][ C7] [ 39.753045][ C7] CPU6 online:0 [ 39.753046][ C7] EL2(NS) PC: <0xffffffc00801b8d8> local_cpu_stop+0x44/0x84 [ 39.753046][ C7] [ 39.753047][ C7] CPU7 online:1 [ 39.753048][ C7] EL2(NS) PC: <0xffffffc0086de410> rockchip_panic_notify+0x274/0x394 [ 39.753048][ C7] [ 39.753049][ C7] CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 CPU6 CPU7 [ 39.753050][ C7] 13: 7751 4759 12010 40210 6869 9433 4670 4697 GICv3 26 Level arch_timer [ 39.753052][ C7] 14: 1007 1341 3548 1383 328 531 198 228 GICv3 321 Level rk_timer [ 39.753053][ C7] 15: 0 0 0 0 0 0 0 0 GICv3 23 Level arm-pmu [ 39.753054][ C7] 16: 2 0 0 0 0 0 0 0 GICv3 105 Level dmc [ 39.753055][ C7] 17: 6158 0 0 0 0 0 0 0 GICv3 126 Level fb000000.gpu [ 39.753056][ C7] 18: 1 0 0 0 0 0 0 0 GICv3 125 Level fb000000.gpu [ 39.753057][ C7] 19: 8762 0 0 0 0 0 0 0 GICv3 124 Level fb000000.gpu [ 39.753059][ C7] 20: 0 0 0 0 0 0 0 0 GICv3 247 Level ehci_hcd:usb1 [ 39.753060][ C7] 21: 0 0 0 0 0 0 0 0 GICv3 248 Level ohci_hcd:usb2 [ 39.753061][ C7] 24: 0 0 0 0 0 0 0 0 GICv3 425 Level rockchip_usb2phy [ 39.753062][ C7] 25: 0 0 0 0 0 0 0 0 GICv3 423 Level rockchip_usb2phy [ 39.753064][ C7] 26: 6704 0 0 0 0 0 0 0 GICv3 349 Level fd880000.i2c [ 39.753065][ C7] 29: 0 0 0 0 0 0 0 0 GICv3 142 Level fdab9000.iommu, fdab0000.npu [ 39.753066][ C7] 30: 0 0 0 0 0 0 0 0 GICv3 143 Level fdab9000.iommu, fdab0000.npu [ 39.753067][ C7] 31: 0 0 0 0 0 0 0 0 GICv3 144 Level fdab9000.iommu, fdab0000.npu [ 39.753069][ C7] 32: 0 0 0 0 0 0 0 0 GICv3 152 Level fdb50000.vepu [ 39.753069][ C7] 33: 0 0 0 0 0 0 0 0 GICv3 151 Level fdb50400.vdpu [ 39.753071][ C7] 34: 0 0 0 0 0 0 0 0 GICv3 150 Level fd [ 39.753072][ C7] Lost 223 message(s)!
最新发布
07-23
<think>首先,用户的问题是:“我想分析并调试Linux内核崩溃日志(Kernel Panic) 请问Linux kernel panic SError Interrupt code 0xbe000011 on CPU7 rkcif_write_register_and crash debug”。这看起来像是一个具体的错误日志片段。 用户提到了“SError Interrupt code 0xbe000011 on CPU7”,这涉及到Linux内核中的SError(System Error)中断。SError是ARM架构中的一种异步异常,通常由硬件错误引起,如内存错误或总线错误。 在引用中,有一些相关的信息: - 引用[1]:显示了一个内核BUG,在list_debug.c文件中的70行。这表示一个调试相关的错误。 - 引用[2]:解释了Linux内核如何处理SError:它捕获SError,设置中断向量,但不做实际处理,只是上报异常并终止进程或内核,因为SError是致命的。 - 引用[3]:讨论了如果异常没有导致panic,系统如何恢复。 - 引用[4]:提供了如何通过反汇编vmlinux来查找错误地址的方法。 用户的问题包括“rkcif_write_register_and”,这似乎是Rockchip Camera Interface(rkcif)相关的函数。Rockchip是SoC制造商,rkcif可能涉及摄像头驱动。 我的任务是: - 回答用户的问题,帮助分析并调试这个内核panic。 - 遵循系统级指令:使用$...$和$$...$$格式,中文回答,生成相关问题。 - 回答结构清晰,逐步解决问题。 结构化回答: 1. **理解问题**:解释SError和panic的基本概念。 2. **分析错误日志**:基于提供的错误代码0xbe000011和位置。 3. **调试步骤**:提供调试方法,包括查看日志、反汇编、检查硬件等。 4. **生成相关问题**:在最后添加相关问题。 关键点: - 错误代码0xbe000011:在ARM架构中,SError中断代码可能有特定含义。0xbe000011可能是一个具体的错误类型。我需要回忆或推断。 - 在ARMv8中,SError中断的ESR(Exception Syndrome Register)值定义了错误类型。0xbe000011可能是一个ESR值。 - 分解ESR:高位是EC(Exception Class),低位是ISS(Instruction Specific Syndrome)。 - 0xbe000011:EC是0x2E(SError中断),但标准EC是6位,所以可能需要检查。0x2E是101110进制,但ESR是32位。 - 通常,ESR_ELx for SError:EC (bits [31:26]) 和 ISS (bits [24:0])。 - 0xbe000011 in hex: 1011 1110 0000 0000 0000 0000 0001 0001 binary. - EC = bits 31:26 = 101111 (0x2F? 但0x2E是SError). 标准EC for SError is 0x2F (101111) for asynchronous SError. - 确认:在ARMv8,SError的EC是0x2F (101111 binary). - 0xbe000011: 0xbe000011 = 1011 1110 0000 0000 0000 0000 0001 0001 - EC = bits [31:26] = 101111 (0x2F), which is SError interrupt. - ISS = bits [24:0] = 0000 0000 0000 0000 0001 0001 (0x11) - ISS的细节取决于EC。对于SError,ISS提供更多错误信息,如AET (Asynchronous Error Type)。 - AET在ISS[9:8]:这里ISS=0x11,所以bits [9:8] = 00? ISS=0x11 is 0000 0000 0000 0000 0001 0001, so bits [9:8] are bits 9 and 8 from left? 通常,ISS是低25位。 - 更好地:ISS = 0x11, 所以进制000000000000000000010001。AET在ISS[9:8],即bit 9和8。从右数,bit 0是最低有效位。 - ISS bit numbering: bit 0 is LSB, so for 0x11 (binary 10001), bits are: bit4=1, bit3=0, bit2=0, bit1=0, bit0=1. But ISS is 25 bits, 0x11 is small, so it's 0...00010001. - AET is ISS[9:8], which are bits 9 and 8. Since ISS=0x11, it's 0 in higher bits, so bits 9:8 = 00, meaning "Uncontainable" or something. - 在ARM ARM中,对于SError,AET定义: - 00: Uncontainable - 01: Unrecoverable state - 10: Restartable state - 11: Corrected - 这里AET=00, Uncontainable error, which is severe. - 位置:CPU7, and function "rkcif_write_register_and". This suggests the error occurred in the Rockchip Camera Interface driver, specifically in a function related to writing registers. - 用户提到“crash debug”,所以我需要提供调试方法。 调试步骤: 1. **收集日志**:获取完整的kernel panic日志,包括堆栈跟踪。 2. **分析错误代码**:解释0xbe000011。 3. **检查代码位置**:基于函数名,查找相关驱动代码。 4. **反汇编vmlinux**:如引用[4]所述,使用objdump反汇编vmlinux,找到错误地址。 5. **硬件检查**:SError often indicates hardware issues, like bad memory or peripheral errors. 6. **驱动调试**:检查rkcif驱动是否有bug,或更新驱动。 生成相关问题: - 如何获取完整的kernel panic日志? - 如何解读ARM SError中断代码? - 如何调试Rockchip特定驱动问题? - 等等。 回答结构: 1. 介绍:解释SError和panic。 2. 分析给定错误。 3. 调试步骤。 4. 相关问题。</think>### 分析并调试Linux内核崩溃日志(Kernel Panic SError Interrupt) 针对您的问题,我将逐步分析 Linux 内核崩溃日志中的 `SError Interrupt code 0xbe000011 on CPU7` 错误,并结合 `rkcif_write_register_and` 函数调用进行调试。SError(System Error)是 ARM 架构中的一种异步异常,通常由硬件错误(如内存访问违规、总线错误)或严重的软件缺陷引起。内核无法修复此类错误时,会触发 panic 并终止系统[^2]。错误代码 `0xbe000011` 和函数名 `rkcif_write_register_and` 表明问题可能发生在 Rockchip Camera Interface (rkcif) 驱动中,涉及寄存器写入操作。以下是我的分析和调试建议。 #### 1. **理解错误代码和上下文** - **SError Interrupt code 0xbe000011**: - 在 ARMv8 架构中,此代码是 ESR(Exception Syndrome Register)值,用于诊断异常原因。分解后: - EC(Exception Class, 高6位):$0x2F$(进制 $101111$),表示 SError 中断[^2]。 - ISS(Instruction Specific Syndrome, 低26位):$0x11$(进制 $000000000000000000010001$)。 - 关键字段 AET(Asynchronous Error Type, ISS[9:8]):$00$(进制 $00$),表示 **Uncontainable Error**(不可控错误),通常由严重硬件问题引起,如内存损坏或总线超时[^2]。 - 错误发生在 **CPU7**,表明是多核系统中的特定核心,可能与并发访问或核心间同步问题相关。 - **rkcif_write_register_and**: - 这是 Rockchip SoC 的摄像头接口驱动函数,用于向硬件寄存器写入数据。错误表明在写入寄存器时触发了 SError,可能原因包括: - 访问无效或未映射的寄存器地址。 - 硬件外设(如摄像头模块)故障或不稳定。 - 驱动代码缺陷(如竞态条件或内存越界)[^4]。 结合引用[2],SError 是致命的,内核会终止进程或触发 panic,因为它无法自行修复。如果 panic 未发生,系统可能通过异常恢复机制继续运行,但错误日志仍会记录[^3]。 #### 2. **调试步骤** 以下是系统化的调试方法,基于内核日志分析和代码级检查。假设您已有完整的 panic 日志(如 `dmesg` 输出或 `/var/log/kern.log`)。 1. **提取完整错误日志**: - 从日志中定位以下关键信息: - 堆栈跟踪(stack trace):显示函数调用链,确认 `rkcif_write_register_and` 的调用路径。 - 错误地址:如引用[1]所示的内核 BUG 地址(例如 `/home/USS/src/...`),用于代码定位。 - 寄存器状态:如程序计数器(PC)值,帮助反汇编分析。 - 示例:如果日志包含类似 `kernel BUG at .../list_debug.c:70` 的信息,可直接查看对应源码[^1]。 2. **反汇编 vmlinux 查找错误地址**: - 如果日志提供了错误虚拟地址(如 PC 值),使用 objdump 反汇编内核镜像: ```bash arm-poky-linux-gnueabi-objdump -D vmlinux > vmlinux.dis ``` 在 `vmlinux.dis` 中搜索错误地址或函数名(如 `rkcif_write_register_and`),定位汇编指令并分析上下文[^4]。 - **针对 0xbe000011 的专项分析**: - SError 的 ISS=0x11 可能表示具体错误类型(如对齐错误或访问权限问题)。使用 ARM 文档(如 ARM Architecture Reference Manual)或内核头文件(`arch/arm64/include/asm/esr.h`)解码: ```c // 示例:检查 ESR 定义(内核源码) #define ESR_ELx_EC_SHIFT 26 #define ESR_ELx_EC_SERROR 0x2F ``` - 如果 ISS 低比特位指示内存错误,结合硬件检查(如内存测试)。 3. **检查 rkcif 驱动代码**: - 获取内核源码(与崩溃版本一致),定位 `rkcif_write_register_and` 函数(通常在 `drivers/media/platform/rockchip/rkcif/` 目录)。 - 常见问题点: - 寄存器地址计算错误(如指针溢出)。 - 未处理并发访问(多核下需锁机制)。 - 硬件状态未检查(如寄存器忙等待)。 - 修复建议: - 添加调试打印:在函数中插入 `pr_debug()` 输出寄存器地址和值。 - 使用内核调试工具:如 KASAN(检测内存错误)或 lockdep(检查锁竞争)。 4. **硬件和系统检查**: - **硬件诊断**:SError 常由硬件引起。测试步骤: - 检查摄像头模块连接和电源。 - 运行内存测试(如 `memtester`)。 - 降低 CPU 频率或关闭超频,排除稳定性问题。 - **内核配置**: - 启用更多调试选项:如 `CONFIG_DEBUG_KERNEL`、`CONFIG_DEBUG_LIST`(引用[1]涉及 list_debug)。 - 更新驱动:确保使用最新 rkcif 驱动(Rockchip 常修复硬件兼容性问题)。 5. **复现和捕获现场**: - 使用 QEMU 模拟器或 JTAG 调试器复现错误。 - 启用内核崩溃转储(kdump),获取 vmcore 文件分析。 - 监控工具:`perf` 记录事件,或 `trace-cmd` 跟踪函数调用。 #### 3. **常见解决路径** - 如果问题在驱动:修补代码后重新编译内核。 - 如果硬件问题:更换外设或调整时钟设置。 - 临时规避:在启动参数添加 `nosmp`(禁用多核),测试是否与 CPU7 相关。 如果提供完整日志,我可进一步分析。SError 调试需结合软件日志和硬件诊断,但通过上述步骤,多数问题可定位到驱动或硬件层[^2][^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值