顯示具有 linux 標籤的文章。 顯示所有文章
顯示具有 linux 標籤的文章。 顯示所有文章

2012年12月6日 星期四

Performance of Unaligned Memory Access in Raspberry Pi

SoC of Raspberry pi is a Broadcom BCM2835. This contains an ARM1176JZFS, ARMv6 architecture.

ARMv6 adds unaligned word(4 bytes) and halfword load and store data access support.
For detail, please check.
I would like to test performance when a user space process invokes a unaligned memory access (only load).
Here is my test environment and cases.

[Environment]

Kernel: Linux xbian 3.6.1 #4 PREEMPT Thu Nov 8 18:54:20 CET 2012 armv6l GNU/Linux
GCC: gcc version 4.6.3 (Debian 4.6.3-12+rpi1)

# cat /proc/cpuinfo
Processor       : ARMv6-compatible processor rev 7
                  (v6l)
BogoMIPS        : 697.95
Features        : swp half thumb fastmult vfp edsp

                  java tls
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part        : 0xb76
CPU revision    : 7

Hardware        : BCM2708
Revision        : 0002
Serial          : 0000000009b752ff


[Program]

unaligned.c
#include <stdio.h>
#include <stdint.h>

#ifdef USE_GCC_FIXUP
struct __una_u32 {
    uint32_t x;  
} __attribute__((packed));

static inline uint32_t get_unaligned_32(const void *p)
{
    const struct __una_u32 *ptr = 
        (const struct __una_u32 *)p;
    return ptr->x;
}
#endif

int main()
{
    uint8_t buf[16];
    uint32_t i, j;

    for (i = 0; i < sizeof(buf); i++)
        buf[i] = i;

    for (j = 0; j < 100000000; j++) {
        /* unaligned access */
#ifndef USE_GCC_FIXUP
        i = *(unsigned int*)(&buf[1]);
#else
        i = get_unaligned_32(&buf[1]);
#endif
    }

    printf("0x%X\n", i);

    return 0;
}

[Case]

  1. unaligned word access
    • fix up by hardware
      # gcc -c unaligned.c
      # time ./unaligned
      0x4030201

      real    0m2.053s
      user    0m2.040s
      sys     0m0.010s

    • fix up by software (gcc)
      # gcc -DUSE_GCC_FIXUP -o unaligned_gcc unaligned.c
      # time ./unaligned_gcc
      0x4030201

      real    0m6.384s
      user    0m6.370s
      sys     0m0.010s

    The result is very clear.

    Here I add a case is aligned access.
    Only modify:
    #ifndef USE_GCC_FIXUP
            i = *(unsigned int*)(&buf[0]);
    #else
    
    # time ./aligned
    0x3020100

    real    0m1.934s
    user    0m1.920s
    sys     0m0.000s

  2. unaligned double words access
    Modify unaligned.c to support double words access
    • fix up by kernel
      # time ./unaligned64
      0x807060504030201

      real    1m8.754s
      user    0m7.800s
      sys     1m0.830s


    • fix up by software (gcc)
      # time ./unaligned64_gcc
      0x807060504030201

      real    0m9.753s
      user    0m9.700s
      sys     0m0.030s

    Also add a case for aligned access.
    # time ./aligned64
    0x706050403020100

    real    0m2.413s
    user    0m2.400s
    sys     0m0.000s
So, to avoid unaligned memory access if possible!

2012年12月3日 星期一

Note about Linux Kernel char Device Driver

There are two ways to create a struct cdev:
  1. static way
    • declare
      • embedded in your device structure statically
        struct dummy_device {
            struct cdev cdev;
        };
    • initialize
      •  use cdev_init() function to initialize the cdev structure
        struct dummy_device dev;
        ...
        cdev_init(&dev.cdev, &dummy_fops);
    • remove
      • call cdev_del()
  2. dynamic way
    • declare
      • memory of cdev structure is allocated dynamically
        struct dummy_device {
            struct cdev *cdev;
        };
        ...
        struct dymmy_device dev;
        dev->cdev = cdev_alloc();
    • initialize
      • dev->cdev.fops = &dummy_fops;
    • remove
      • call cdev_del()
      • You don't need to call kfree() to free memory. Kernel releases the memory automatically. (talk this later)  
There is one thing you need to know about the dynamic way. 
If you use dynamic way to create a cdev structure, you should better not use cdev_init() to initialize the structure.

Let's check source code.

void cdev_init(struct cdev *cdev, 
               const struct file_operations *fops)
{
    memset(cdev, 0, sizeof *cdev);
    INIT_LIST_HEAD(&cdev->list);
    kobject_init(&cdev->kobj, &ktype_cdev_default);

    cdev->ops = fops;
}

struct cdev *cdev_alloc(void)
{

    /* cdev is allocated here! */
    struct cdev *p = kzalloc(sizeof(struct cdev),
                     GFP_KERNEL);
    if (p) {
        INIT_LIST_HEAD(&p->list);
        kobject_init(&p->kobj, &ktype_cdev_dynamic);
    }
    return p;
}

If you use dynamic way to create the cdev structure, ktype_cdev_dynamic() is used to release cdev kobject.
If you use cdev_init() to initialize cdev structure that is created in dynamic way, release function of kobject is replaced with ktype_cdev_default().
In this case, after you invoke cdev_del() to remove a cdev device from kernel, this causes a memory leak.
You need to free memory manually and it is not recommended.

static void cdev_default_release(struct kobject *kobj)
{
    struct cdev *p = container_of(kobj, struct cdev, kobj);
    cdev_purge(p);
}

static void cdev_dynamic_release(struct kobject *kobj)
{
    struct cdev *p = container_of(kobj, struct cdev, kobj);
    cdev_purge(p);
    kfree(p);    /* cdev is freed here! */
}

static struct kobj_type ktype_cdev_default = {
    .release        = cdev_default_release,
};

static struct kobj_type ktype_cdev_dynamic = {
    .release        = cdev_dynamic_release,
};

2012年7月30日 星期一

Manage Partitions of the Disk Image with loop device

loop device is a pseudo-device that makes a file accessible as a block device.
We can use loop device to manage partitions of the disk image.

Make sure you loop device driver is configured to support loop device partitions.
In my FC16 box, I manually add kernel command:
loop.max_part=63
Here is an example when I attach a disk image with losetup.

$ cat /proc/partitions
major minor  #blocks  name

   8        0   33554432 sda
   8        1     512000 sda1
   8        2   33041408 sda2
  11        0    1048575 sr0
   8       16  104857600 sdb
   8       17  104856576 sdb1
 253        0    4128768 dm-0
 253        1   28901376 dm-1

$ losetup -f disk_image
$ cat /proc/partitions
major minor  #blocks  name

   7        0    1048576 loop0
   7        1      10240 loop0p1
   7        2    1037312 loop0p2

   8        0   33554432 sda
   8        1     512000 sda1
   8        2   33041408 sda2
  11        0    1048575 sr0
   8       16  104857600 sdb
   8       17  104856576 sdb1
 253        0    4128768 dm-0
 253        1   28901376 dm-1

$ losetup -d /dev/loop0


2012年7月26日 星期四

Raspberry Pi is Arrived!!

Wait for a long time and finally arrived!! Raspberry Pi !!

Box (cute)
Raspberry pi is a credit-card sized computer.
Running Raspbian “wheezy” (2012-07-15)
My USB keyboard/mouse works in Raspberry pi.
I think I have to buy a USB Wifi dongle and USB hub.

Todo List
  • As a media center
    • Watch DVB (I have a unused DVB USB dongle)
    • Play DVD (attach a USB DVD-ROM)
    • Play video/audio file
  • As a download server
    • Attach a USB HDD
    • Run p2p clients
  • Create a customized image
    • boot, kernel, ... ,etc.
    • HW optimization
  • Run Android
    •  RAM is too small?
  • More....
[Ref]








2012年7月18日 星期三

Android: modify partition layouts

Storage is never enough!
Fortunately, we can pass partition layouts via kernel command line without kernel modification.
lbcoder, Thanks for post this! Custom partition layouts, ZERO brick risk!

My Nexus One default partition layouts:

# cat /proc/mtd
dev:    size   erasesize  name          size
mtd0: 000e0000 00020000 "misc"          896K
mtd1: 00400000 00020000 "recovery"      4M
mtd2: 00380000 00020000 "boot"          3M
mtd3: 09100000 00020000 "system"        145M
mtd4: 05f00000 00020000 "cache"         95M
mtd5: 0c440000 00020000 "userdata"      196M

# msm_nand MTD info during kernel booting
[   13.353302] msm_nand: DEV_CMD1: f00f3000
[   13.357299] msm_nand: NAND_EBI2_ECC_BUF_CFG: 1ff
[   13.361724] Creating 6 MTD partitions on "msm_nand":
[   13.366790] 0x000003ee0000-0x000003fc0000 : "misc"
[   13.373260] 0x000004240000-0x000004640000 : "recovery"
[   13.381561] 0x000004640000-0x0000049c0000 : "boot"
[   13.386108] 0x0000049c0000-0x00000dac0000 : "system"
[   13.538635] 0x00000dac0000-0x0000139c0000 : "cache"
[   13.637023] 0x0000139c0000-0x00001fe00000 : "userdata"
 
cache partition is too large to me.
I would like to change partition layouts to

dev:    size   erasesize  name          size
mtd0: 000e0000 00020000 "misc"          896K
mtd1: 00400000 00020000 "recovery"      4M
mtd2: 00380000 00020000 "boot"          3M
mtd3: 09100000 00020000 "system"        145M
mtd4: 02800000 00020000 "cache"         95M->40M
mtd5: 0FB00000 00020000 "userdata"      196M->251M

userdata partition up to 251M!

So, I need add kernel command line like below
mtdparts=msm_nand:896k@0x3ee0000(misc),4M@0x4240000(recovery),3M@0x4640000(boot),145M@0x49c0000(system),40M@0xdac0000(cache),251M@0x102C0000(userdata)
But how?
I do it manually. We need to modify both recovery and boot images.
  1. Boot to recovery mode
  2. Extract recovery image from recovery partition and use hex editor to add kernel command line into recovery image
  3. Flash back modified recovery image then boot to recovery again
  4. Check MTD information, we are done.
    [    9.726074] msm_nand: DEV_CMD1: f00f3000
    [    9.726257] msm_nand: NAND_EBI2_ECC_BUF_CFG: 1ff
    [    9.726440] 6 cmdlinepart partitions found on MTD device msm_nand
    [    9.726684] Creating 6 MTD partitions on "msm_nand":
    [    9.726837] 0x000003ee0000-0x000003fc0000 : "misc"
    [    9.728668] 0x000004240000-0x000004640000 : "recovery"
    [    9.733581] 0x000004640000-0x000004940000 : "boot"
    [    9.737548] 0x0000049c0000-0x00000dac0000 : "system"
    [    9.893493] 0x00000dac0000-0x0000102c0000 : "cache"
    [    9.937652] 0x0000102c0000-0x00001fdc0000 : "userdata"
     
  5. Flash zip from SD (I use CM7.2)
  6. Extract boot image from boot partition and use hex editor to add kernel command line into boot image
  7. Flash back modified boot image then reboot
  8. Boot to CM, then check MTD information.

2010年5月27日 星期四

2010年4月14日 星期三

Convert Binary File as a Normal Object File

objcopy -I binary -O elf32-i386 -B i386 your_bin_file your_bin_file.o

Then you can use nm to check your_bin_file.o

01000000 D _binary_your_bin_file_end
01000000 A _binary_your_bin_file_size
00000000 D _binary_your_bin_file_start

Use this in your code
extern char _binary_your_bin_file_end[];
extern char _binary_your_bin_file_size[];
extern char _binary_your_bin_file_start[];

2010年3月4日 星期四

POSIX IO Must Die!

喔喔~好驚悚的 subject..請看下面 link
POSIX IO Must Die!

2010年2月21日 星期日

My First Linux Kernel Patch

看到自己的 patch 被加到其它 kernel hacker 的 git tree 中...
還蠻感動的...
http://git.kernel.org/?p=linux/kernel/git/sarah/xhci.git;a=commit;h=583f156bde78f678bad42ddd815b43bab89309e1

ps: 不知道什麼時候才會真的進 mainline

不過 patch 有兩個地方有點錯誤..
1. Subject line 的 subsystem
USB: xhci: 應該為 xhci: 比較正確
2. Body of the explanation 有 typo
最後一行的 legacy sup support. 應該是 legacy support.

呼~下次會多注意這些小地方..
希望末來還有機會能 submit kernel patch .. :)

2010年2月11日 星期四

git send-email 簡單用法紀錄

試了好久..總算用 git format-patch 和 git send-email 把 patch 送出..@@

[Create patch for git-send-email]
git format-patch master

[Send patch with git-send-email]
git send-email -to xxx@xxx -cc xxx@xxx -cc xxx@xxx --suppress-from 0001-xxx.patch

ps: --suppress-from 加這個 option 就不會把 patch 中 From: 的 email 加到 cc: 中
--dry-run try git-send-email 的 option 時..好用~

2010年2月10日 星期三

git send-email 相關的設定 (for gmail)

git config --global sendemail.smtpencryption tls
git config --global sendemail.smtpserver smtp.gmail.com
git config --global sendemail.smtpuser laface.tw
git config --global sendemail.smptserverport 587

2010年2月1日 星期一

在 RedHat 7.2 上裝 git

RedHat 7.2 太舊了..需要加 NO_NSEC

./configure CFLAGS=-DNO_NSEC --prefix=/usr

記錄一下..不然又會忘~@@

2010年1月6日 星期三

GNU cflow

GNU cflow
一個可以用來 trace code 的工具..
有機會再來試看看~~

2010年1月5日 星期二

GNOME, GTK, GDK, XLib, GLib

這幾個名詞總是記不太起來..可能是太少接觸了吧..^^"
把一個link記下來..以後要回憶比較快~~

2009年10月6日 星期二

Linux Kernel netconsole

[Server]
./netcat -u -l -p 6666 | tee /tmp/123.log

[Client]
ifconfig eth0 up
ifconfig eth0 192.168.19.183 netmask 255.255.255.0 up

insmode netconsole.ko netconsole=@/eth0,@192.168.19.43/

記錄一下下~~

2009年9月15日 星期二

Work with a git remote branch

git checkout --track -b my/master-dev2 origin/master-dev

Just keep a record~~