2017-10-19 17 views
3

WIFI Marvell pcie 드라이버의 insmod에서 충돌이 발생합니다. ARCH = arc OS = linux 및 little endian에서 WIFI 드라이버를 실행하고 있습니다. 충돌 백 추적에 잘못 정렬 된 주소 액세스로 인해 충돌이 발생합니다. 몇 가지 조사를 수행했으며 충돌 장소를 찾았습니다. 아래 코드가 있습니다. psnmp_mib->value이 서명 숯불과 unsigned long int에 typecast'd 때문에arc 플랫폼의 리눅스 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);이다. 그러나 pdata_buf에서 할당하는 값은 1 바이트 값인 ul_temp = *((t_u32 *)pdata_buf);입니다.

이상한 동작은 ul_temp (unsigned long int variable)을 0 (모든 값)으로 초기화하면 실행하면 크래시가 표시되지 않습니다. 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/)는 커널 개발자가 거기에 매달려 비교적 친절하기 때문에 좋은 장소입니다. 이 사이트에는 [Found a Bug] (https://kernelnewbies.org/FoundBug) 섹션도 있습니다. 다음 단계는 적절한 메일 링리스트에보고하는 것입니다. – jww

답변

3

심플. 그냥 올바른 일을하십시오. C 표준은 behaviour is undefined when 그 상태를 않기 때문에 이것은 매우 걱정입니다

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

을 : 0andriy에 의해 지적

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

put_unaligned 여기에 사용될 수있다 : 일반적인 경우에, 하나는 memcpy 사용하는 것 :

두 포인터 유형간에 변환하면 결과가 잘못 정렬됩니다 (6.3.2.3).

따라서도 단순한 존재 포인터 psnmp_mib->value 어쨌든 t_u32의 정렬 요구에 정렬된다 "실현"컴파일러에 캐스팅 (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'가 정렬되지 않았 으면 캐스트가 유효하지 않습니다. –