Bug 193649

Summary: ring->nr_buf_size will be calculated wrongly on PPC machine
Product: Base System Reporter: dongshan <thomasyang1206>
Component: kernAssignee: Vincenzo Maffione <vmaffione>
Status: Closed FIXED    
Severity: Affects Some People CC: delphij, thomasyang1206
Priority: ---    
Version: 10.0-STABLE   
Hardware: powerpc   
OS: Any   
Attachments:
Description Flags
the first part log contains the bug with TX nr_buf_size = 0x8000000, the second part log is the correct one without bug none

Description dongshan 2014-09-15 06:16:21 UTC
Created attachment 147337 [details]
the first part log contains the bug with TX nr_buf_size = 0x8000000, the second part log is the correct one without bug

When run netmap APP pkt-gen on PPC machine, say Freescale P4080, the buf size of ring ring->nr_buf_size in "netmap_mem2.c, netmap_mem_rings_create()". The declaration of nr_buf_size in struct netmap_ring is uint32_t, however it is changed to uint16_t as following:
    *(uint16_t *)(uintptr_t)&ring->nr_buf_size = NETMAP_BDG_BUF_SIZE(na->nm_mem);

    Thus buffer size will be different as the desired, and will cause Segmentation fault. after changing it as:
    *(uint32_t *)(uintptr_t)&ring->nr_buf_size = NETMAP_BDG_BUF_SIZE(na->nm_mem);
it works well on PPC。
    
    The log is attached, please find it, pay attention to the buf_nr_size value between the two parts log section.
Comment 1 dongshan 2014-09-23 16:16:50 UTC
the bug is caused as following:
imaging a 32-bit integer 0x00000800, on little endian machine, the data in
memory is arranged like this:

[0000 0000]		0000
[0000 0001]		0000
[0000 0002]		1000
[0000 0003]		0000
[0000 0004]		0000
[0000 0005]		0000
[0000 0006]		0000
[0000 0007]		0000
However, on a big endian machine, the value in memory is:
[0000 0000]		0000      
[0000 0001]		0000
[0000 0002]		0000
[0000 0003]		0000
[0000 0004]		0000
[0000 0005]		1000
[0000 0006]		0000
[0000 0007]		0000
-------------------------------------------------------------------------------
Here is the trick:
	uint32_t foo; // let assume the address of foo is 0x0, as showed above.
	uint32_t *p = &foo;
	*(uint16_t *)p = 0x00000800;
	printf("foo: 0x%x", foo); // the output of foo will be 0x08000000
        printf("foo1:0x%x", (uint16_t)foo); // the output will be 0x00000800
Dump the memory on big endian machine:
[0000 0000]		0000      
[0000 0001]		1000
[0000 0002]		0000
[0000 0003]		0000
[0000 0004]		0000
[0000 0005]		0000
[0000 0006]		0000
[0000 0007]		0000
Comment 2 Xin LI freebsd_committer freebsd_triage 2024-04-15 22:22:50 UTC
This seems to have been fixed in 4f80b14ce2b17100b12dc3a346fb9e6e76764e11.