From 49ae50888966c1f8bb8834e53c4cb7cdcab41cc6 Mon Sep 17 00:00:00 2001 From: Sebastian Sumpf Date: Thu, 2 Jul 2015 14:20:20 +0200 Subject: [PATCH] usb_drv: use heap for vmalloc allocations Do not use slabs for allocations above 64KB, this seems to lead to memory corruptions and the error described in issue #1613 under certain circumstances. fixes #1613 --- repos/dde_linux/src/lib/usb/include/lx_emul.h | 2 +- repos/dde_linux/src/lib/usb/include/routine.h | 2 -- repos/dde_linux/src/lib/usb/include/signal.h | 2 ++ repos/dde_linux/src/lib/usb/lx_emul.cc | 29 ++++++++++++++----- 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/repos/dde_linux/src/lib/usb/include/lx_emul.h b/repos/dde_linux/src/lib/usb/include/lx_emul.h index 32a9bd6a90..d21880c62a 100644 --- a/repos/dde_linux/src/lib/usb/include/lx_emul.h +++ b/repos/dde_linux/src/lib/usb/include/lx_emul.h @@ -1269,7 +1269,7 @@ void __wait_event(void); #define _wait_event_timeout(condition, timeout) \ ({ \ - unsigned long _j = jiffies + (timeout / HZ); \ + unsigned long _j = jiffies + timeout; \ while(1) { \ __wait_event(); \ if (condition || _j <= jiffies) \ diff --git a/repos/dde_linux/src/lib/usb/include/routine.h b/repos/dde_linux/src/lib/usb/include/routine.h index 4f3524e765..8adc4d9d2a 100644 --- a/repos/dde_linux/src/lib/usb/include/routine.h +++ b/repos/dde_linux/src/lib/usb/include/routine.h @@ -135,8 +135,6 @@ class Routine : public Genode::List::Element if (!_list()->first() && !_main) return; - Timer::update_jiffies(); - if (_current == _main) all = true; diff --git a/repos/dde_linux/src/lib/usb/include/signal.h b/repos/dde_linux/src/lib/usb/include/signal.h index c5b6665833..6cef43f059 100644 --- a/repos/dde_linux/src/lib/usb/include/signal.h +++ b/repos/dde_linux/src/lib/usb/include/signal.h @@ -43,6 +43,8 @@ class Service_handler */ void process() { + Timer::update_jiffies(); + if (Routine::all()) { Routine::schedule(); return; diff --git a/repos/dde_linux/src/lib/usb/lx_emul.cc b/repos/dde_linux/src/lib/usb/lx_emul.cc index e64acf9782..03c60c0b61 100644 --- a/repos/dde_linux/src/lib/usb/lx_emul.cc +++ b/repos/dde_linux/src/lib/usb/lx_emul.cc @@ -193,7 +193,7 @@ class Malloc enum { SLAB_START_LOG2 = 3, /* 8 B */ - SLAB_STOP_LOG2 = 17, /* 128 KB */ + SLAB_STOP_LOG2 = 16, /* 64 KB */ NUM_SLABS = (SLAB_STOP_LOG2 - SLAB_START_LOG2) + 1, }; @@ -410,6 +410,9 @@ void *kcalloc(size_t n, size_t size, gfp_t flags) void kfree(const void *p) { + if (!p) + return; + if (Malloc::mem()->inside((Genode::addr_t)p)) Malloc::mem()->free(p); @@ -422,17 +425,27 @@ void kfree(const void *p) ** linux/vmalloc.h ** *********************/ -void *vzalloc(unsigned long size) +void *vzalloc(unsigned long size) { - if (size > Malloc::max_alloc()) { - PERR("vzalloc: size %lu > %lu", size, Malloc::max_alloc()); - return 0; - } + size_t real_size = size + sizeof(size_t); + size_t *addr; + try { addr = (size_t *)Genode::env()->heap()->alloc(real_size); } + catch (...) { return 0; } - return kmalloc(size, 0); + *addr = real_size; + memset(addr + 1, 0, size); + + return addr + 1; } -void vfree(void *addr) { kfree(addr); } + +void vfree(void *addr) +{ + if (!addr) return; + + size_t size = *(((size_t *)addr) - 1); + Genode::env()->heap()->free(const_cast(addr), size); +} /******************