What are the differences between kmalloc () kcalloc () vmalloc () and kzalloc ()?

Hi all, 

I am currently debugging a device driver and I am getting a kernel panic. After checking backtrace or error log, it seems the problem is related to kmalloc. I was thinking maybe I can change kmalloc with other distribution functions. What are their differences?

here is the error log:

 Unable to handle kernel NULL pointer dereference at virtual address 0000000d pgd = c7bdc000 [0000000d] *pgd=4785f031, *pte=00000000, *ppte=00000000 Internal error: Oops: 17 [#1] PREEMPT Modules linked in: bcm5892_secdom_fw(P) bcm5892_lcd snd_bcm5892 msr bcm5892_sci bcm589x_ohci_p12 bcm5892_skeypad hx_decoder(P) pinnacle hx_memalloc(P) bcm_udc_dwc scsi_mod g_serial sd_mod usb_storage CPU: 0 Tainted: P (2.6.27.39-WR3.0.2ax_standard #1) PC is at __kmalloc+0x70/0xdc LR is at __kmalloc+0x48/0xdc pc : [<c0098cc8>] lr : [<c0098ca0>] psr: 20000093 sp : c7a9fd50 ip : c03a4378 fp : c7a9fd7c r10: bf0708b4 r9 : c7a9e000 r8 : 00000040 r7 : bf06d03c r6 : 00000020 r5 : a0000093 r4 : 0000000d r3 : 00000000 r2 : 00000094 r1 : 00000020 r0 : c03a4378 Flags: nzCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user Control: 00c5387d Table: 47bdc008 DAC: 00000015 Process sh (pid: 1088, stack limit = 0xc7a9e260) Stack: (0xc7a9fd50 to 0xc7aa0000) fd40: c7a6a1d0 00000020 c7a9fd7c c7ba8fc0 fd60: 00000040 c7a6a1d0 00000020 c71598c0 c7a9fd9c c7a9fd80 bf06d03c c0098c64 fd80: c71598c0 00000003 c7a6a1d0 bf06c83c c7a9fdbc c7a9fda0 bf06d098 bf06d008 fda0: c7159880 00000000 c7a6a2d8 c7159898 c7a9fde4 c7a9fdc0 bf06d130 bf06d078 fdc0: c79ca000 c7159880 00000000 00000000 c7afbc00 c7a9e000 c7a9fe0c c7a9fde8 fde0: bf06d4b4 bf06d0f0 00000000 c79fd280 00000000 0f700000 c7a9e000 00000241 fe00: c7a9fe3c c7a9fe10 c01c37b4 bf06d300 00000000 c7afbc00 00000000 00000000 fe20: c79cba84 c7463c78 c79fd280 c7473b00 c7a9fe6c c7a9fe40 c00a184c c01c35e4 fe40: 00000000 c7bb0005 c7a9fe64 c79fd280 c7463c78 00000000 c00a1640 c785e380 fe60: c7a9fe94 c7a9fe70 c009c438 c00a164c c79fd280 c7a9fed8 c7a9fed8 00000003 fe80: 00000242 00000000 c7a9feb4 c7a9fe98 c009c614 c009c2a4 00000000 c7a9fed8 fea0: c7a9fed8 00000000 c7a9ff64 c7a9feb8 c00aa6bc c009c5e8 00000242 000001b6 fec0: 000001b6 00000241 00000022 00000000 00000000 c7a9fee0 c785e380 c7473b00 fee0: d8666b0d 00000006 c7bb0005 00000300 00000000 00000000 00000001 40002000 ff00: c7a9ff70 c79b10a0 c79b10a0 00005402 00000003 c78d69c0 ffffff9c 00000242 ff20: 000001b6 c79fd280 c7a9ff64 c7a9ff38 c785e380 c7473b00 00000000 00000241 ff40: 000001b6 ffffff9c 00000003 c7bb0000 c7a9e000 00000000 c7a9ff94 c7a9ff68 ff60: c009c128 c00aa380 4d18b5f0 08000000 00000000 00071214 0007128c 00071214 ff80: 00000005 c0027ee4 c7a9ffa4 c7a9ff98 c009c274 c009c0d8 00000000 c7a9ffa8 ffa0: c0027d40 c009c25c 00071214 0007128c 0007128c 00000241 000001b6 00000000 ffc0: 00071214 0007128c 00071214 00000005 00073580 00000003 000713e0 400010d0 ffe0: 00000001 bef0c7b8 000269cc 4d214fec 60000010 0007128c 00000000 00000000 Backtrace: [<c0098c58>] (__kmalloc+0x0/0xdc) from [<bf010a00>] (GadgetEpRequestAlloc+0x28/0x70 [bcm_udc_dwc]) r8:bf017c80 r7:c79de2d8 r6:c79de2d8 r5:00000000 r4:00000040 [<bf0109d8>] (GadgetEpRequestAlloc+0x0/0x70 [bcm_udc_dwc]) from [<bf0181d4>] (gs_alloc_req+0x44/0xf0 [g_serial]) r5:00000000 r4:00000040 [<bf018190>] (gs_alloc_req+0x0/0xf0 [g_serial]) from [<bf0182b4>] (gs_alloc_requests+0x34/0xb4 [g_serial]) r7:c79de2d8 r6:c79aa198 r5:00000000 r4:c79aa180 [<bf018280>] (gs_alloc_requests+0x0/0xb4 [g_serial]) from [<bf018368>] (gs_start_io+0x34/0xb8 [g_serial]) r9:c7b84000 r8:c7b48c00 r7:c79aa198 r6:c79de2d8 r5:c79aa180 r4:c79aa180 [<bf018334>] (gs_start_io+0x0/0xb8 [g_serial]) from [<bf018730>] (gs_open+0x1d0/0x23c [g_serial]) r9:c7b84000 r8:c7b48c00 r7:00000000 r6:00000000 r5:c79aa180 r4:c7924300 [<bf018560>] (gs_open+0x0/0x23c [g_serial]) from [<c01c3754>] (tty_open+0x1dc/0x314) [<c01c3578>] (tty_open+0x0/0x314) from [<c00a184c>] (chrdev_open+0x20c/0x22c) [<c00a1640>] (chrdev_open+0x0/0x22c) from [<c009c438>] (__dentry_open+0x1a0/0x2b8) r8:c79aa300 r7:c00a1640 r6:00000000 r5:c74685a8 r4:c7a9f5a0 [<c009c298>] (__dentry_open+0x0/0x2b8) from [<c009c614>] (nameidata_to_filp+0x38/0x50) [<c009c5dc>] (nameidata_to_filp+0x0/0x50) from [<c00aa6bc>] (do_filp_open+0x348/0x6f4) r4:00000000 [<c00aa374>] (do_filp_open+0x0/0x6f4) from [<c009c128>] (do_sys_open+0x5c/0x170) [<c009c0cc>] (do_sys_open+0x0/0x170) from [<c009c274>] (sys_open+0x24/0x28) r8:c0027ee4 r7:00000005 r6:0007121c r5:0007129c r4:0007121c [<c009c250>] (sys_open+0x0/0x28) from [<c0027d40>] (ret_fast_syscall+0x0/0x2c) Code: e59c4080 e59c8090 e3540000 159c308c (17943103) ---[ end trace b9a765ee07f8c06b ]--- 
+6
linux malloc linux-kernel driver
source share
3 answers

It is very unlikely that kmalloc is broken, as it is used everywhere in the kernel. However, kmalloc may fail. Assuming kmalloc is not broken, a code call is a good candidate:

  • What does the code around kmalloc look like? Maybe you could show us this part.
  • What part before returning? It may contain valuable information.

To answer more directly to the question asked:

  • kzalloc zeroes out memory before returning a pointer
  • kcmalloc allocates memory for the array, this is not a replacement for kmalloc:

    void * kcalloc (size_t n, size_t size, gfp_t flags)

  • vmalloc is the same as kmalloc, except that it allocates memory that only practically touches. Primary physical memory may be incompatible.

Thus, kmalloc can be replaced with a call to kzalloc, but this is unlikely to solve your problem.

+15
source share

I think the choice between kmalloc, vmalloc and other distribution methods is implementation. The failure of each of them is also a contingent. If you need multiple pages of memory, rather go to page allocation methods. They are simple and fast. However, if you need a certain amount of data (expressed in bytes), the choice remains between kmalloc (and its variants) and vmalloc. kmalloc is faster and provides contiguous memory allocation (especially useful with DMA). The algorithm that implements it is very fast. However, if your memory is highly fragmented, a problem may arise when you request more memory. If it cannot find enough adjacent space, if it does not work, even though the memory has enough space to accommodate. vmalloc, on the other hand, does not require contiguous memory allocation. However, it is rather slow. It works by appropriately setting up entries in the page table. In addition, the kernel usually does not allocate much space for vmalloc.

So, in your case, I think it depends on what types of applications you use. However, using vmalloc instead of kmalloc is not a solution for most of the time (with the exception of large memory allocations in highly fragmented memory). In such cases, you can directly select the page distribution.

+5
source share

kmalloc can only be the culprit when your memory is fragmented and does not allocate memory if it does not find continuous memory. So depending on how much memory you are trying to allocate.

In such cases, using vmalloc gives good results. In best practices

  • if you want to use kmalloc it is better to use kzmalloc.

  • If your distribution is much better, use vmalloc.

Now check what is best for you based on the error condition.

+2
source share

All Articles