Bug 193649 - ring->nr_buf_size will be calculated wrongly on PPC machine
Summary: ring->nr_buf_size will be calculated wrongly on PPC machine
Status: New
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 10.0-STABLE
Hardware: powerpc Any
: --- Affects Some People
Assignee: freebsd-bugs mailing list
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-09-15 06:16 UTC by dongshan
Modified: 2014-09-23 16:16 UTC (History)
1 user (show)

See Also:


Attachments
the first part log contains the bug with TX nr_buf_size = 0x8000000, the second part log is the correct one without bug (23.80 KB, text/enhanced)
2014-09-15 06:16 UTC, dongshan
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
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