2017-10-19 118 views
3

我遇到了insmod的WIFI Marvell pcie驅動程序崩潰。 我在ARCH = arc OS = linux和little endian上運行WIFI驅動程序。 死機回溯表示錯位的地址訪問導致崩潰。 我已經做了一些調查,發現崩潰的地方,下面是代碼片段。錯誤的地址訪問崩潰在arc平臺上的linux wifi驅動程序

case NullPktPeriod_i: 
     /** keep alive null data pkt interval in full power mode */ 
     psnmp_mib->oid = wlan_cpu_to_le16((t_u16)NullPktPeriod_i); 
     if (cmd_action == HostCmd_ACT_GEN_SET) { 
      psnmp_mib->query_type = 
       wlan_cpu_to_le16(HostCmd_ACT_GEN_SET); 
      psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u32)); 
      ul_temp = *((t_u32 *)pdata_buf); 
      *((t_u32 *)(psnmp_mib->value)) = 
       wlan_cpu_to_le32((t_u32)ul_temp); 
      cmd->size += sizeof(t_u32); 
     } 
     break; 

崩潰是線*((t_u32 *)(psnmp_mib->value)) = wlan_cpu_to_le32((t_u32)ul_temp);因爲psnmp_mib->value是無符號的字符和typecast'd到unsigned long int。但是我們從pdata_buf分配的值僅爲1個字節的值,即ul_temp = *((t_u32 *)pdata_buf);

奇怪的行爲是,如果我將ul_temp (unsigned long int variable)初始化爲零(任何值),並且如果我運行,則看不到崩潰。但PCI命令超時發生在獲取get_hardware_spec命令和內核掛起時。

我不知道解決這個問題。請提供一些意見以進一步推動。

打擊更是我的崩潰日誌,

[ 29.920000] Path: (null) 
[ 29.930000] CPU: 0 PID: 1047 Comm: kworker/u3:1 Tainted: P   O 3.12.0 #103 
[ 29.930000] Workqueue: MOAL_WORK_QUEUE woal_main_work_queue [pcie8xxx] 
[ 29.940000] task: 9f0e02c0 ti: 9d192000 task.ti: 9d192000 
[ 29.940000] 
[ECR ]: 0x00230400 => Misaligned r/w from 0x9d451072 
[ 29.950000] [EFA ]: 0x9d451072 
[ 29.950000] [BLINK ]: wlan_prepare_cmd+0x1be/0x478 [mlan] 
[ 29.950000] [ERET ]: wlan_ops_sta_prepare_cmd+0x1fe0/0x37dc [mlan] 
[ 29.950000] [STAT32]: 0x00000a06 :   E2 E1 
[ 29.970000] BTA: 0x78571ccc SP: 0x9d193c34 FP: 0x00000000 
[ 29.980000] LPS: 0x982de26c LPE: 0x982de270 LPC: 0x00000000 
[ 29.980000] r00: 0x00000000 r01: 0x00000016 r02: 0x00000012 
r03: 0x0000001e r04: 0x00000000 r05: 0x9d193cb4 
r06: 0x9d451064 r07: 0x7857129c r08: 0xfffffffe 
r09: 0x00000000 r10: 0x000004cf r11: 0x00000002 
r12: 0x00000000 
[ 29.990000] 
[ 29.990000] Stack Trace: 

請幫助。

+0

*「我不知道解決這個問題的方法......」* - 您可能必須將其帶到內核郵件列表才能解決問題。 [Linux Kernel Newbies](https://kernelnewbies.org/)是一個很好的地方,因爲內核開發者在那裏掛着並且相對溫和。該網站還有[發現錯誤]部分(https://kernelnewbies.org/FoundBug)。您的下一步可能是在適當的郵件列表上報告。 – jww

回答

3

簡單。正確的做。在一般情況下,人們會使用memcpy

t_u32 value = wlan_cpu_to_le32((t_u32)ul_temp); 
memcpy(psnmp_mib->value, &value, sizeof (t_u32)); 

正如0andriy指出的那樣,put_unaligned可以用在這裏:

put_unaligned(wlan_cpu_to_le32((t_u32)ul_temp), (t_u32*)psnmp_mib->value); 

然而,這是非常令人擔憂的,因爲C標準確實狀態的behaviour is undefined when

兩種指針類型之間的轉換會產生不正確對齊的結果(6.3.2.3)。

因此,即使僅僅存在鑄造(t_u32*)可以導致編譯器「實現」指針psnmp_mib->value無論如何對準的t_u32對齊要求的


對齊訪問 - 甚至轉換指針未對齊的結構 - 已不確定偶的平臺上"supposedly" allow unaligned access "everywhere"行爲。

+1

我們在內核中有* get_unaligned()*和* put_unaligned()*助手。最好使用它們並向上遊發送補丁。 – 0andriy

+0

我再次閱讀帖子,現在甚至可以說* memcpy()*方法是開銷。 – 0andriy

+0

@ 0andriy我看了一下「put_unaligned」API ......非常*令人擔憂的是它*太*(在https://www.kernel.org/doc/Documentation/unaligned-memory-access。txt)有未定義的行爲; 'put_unaligned(value,(u32 *)data);' - 當'data'未對齊時,轉換無效。無論如何, –