#ifndef _LVE_DEBUG_ #define _LVE_DEBUG_ #include #include #include #include "lve_os_compat.h" #include "lve_debug_events.h" #define safe_pid() (in_interrupt() ? -1 : current->pid) #define LVE_DEBUG_FAC_DBG 0 #define LVE_DEBUG_FAC_WARN 1 #define LVE_DEBUG_FAC_ERR 2 extern unsigned long lve_debug_mask; extern unsigned long fail_value; #define LVE_ERR(a, ...) \ do { \ if (lve_debug_mask & (1 << LVE_DEBUG_FAC_WARN)) { \ printk(KERN_ERR"LVE: [%d] %s: "a, safe_pid(), \ __FUNCTION__, ##__VA_ARGS__); \ } \ } while (0) #define LVE_WARN(a, ...) \ do { \ if (lve_debug_mask & (1 << LVE_DEBUG_FAC_ERR)) { \ printk(KERN_WARNING"LVE: [%d] %s: "a, safe_pid(), \ __FUNCTION__,##__VA_ARGS__); \ } \ } while (0) #define LVE_DBG(a, ...) \ do { \ if (lve_debug_mask & (1 << LVE_DEBUG_FAC_DBG)) { \ printk("LVE: [%d] %s: "a, safe_pid(), __FUNCTION__, \ ##__VA_ARGS__); \ } \ } while (0) #define LVE_ENTER(a,...) LVE_DBG("enter "a, ##__VA_ARGS__); #define LVE_LEAVE() LVE_DBG("leave\n"); /* printf specifiers for certain types, only valid for platforms we support */ #define LPU64 "%llu" #define LPD64 "%lld" #define LPX64 "%llx" /* access will result in NULL ptr dereference, but NULL ptr checks will fail */ #define LVE_POISON_PTR ((void *)0xded) /* fail type */ #define LVE_FAIL_CHECK_OP 0x01 #define LVE_FAIL_RACE_OP 0x02 #define LVE_FAIL_TIMEOUT_OP 0x04 #define LVE_FAIL_ONCE_OP 0x08 #define LVE_FAIL_VAL(type, loc) (((type) << 24) | (loc)) #define LVE_FAIL_TYPE(val) (((val) >> 24) & 0xf) #define LVE_FAIL_LOC(val) ((val) & 0xffffff) #define LVE_FAIL_ONCE_BIT 31 #define LVE_FAIL_RACE_BIT 30 enum { LVE_FAIL_ALLOC_VE = 0x100, LVE_FAIL_RDXT_PRELOAD = 0x101, LVE_FAIL_LVE_LOOKUP = 0x102, LVE_FAIL_LVE_INSRT = 0x103, LVE_FAIL_ALLOC_SWITCH = 0x104, LVE_FAIL_ALLOC_COOKIE = 0x105, /* limits (ubc, CGROUPS) specific */ LVE_FAIL_CGRP_OPEN = 0x200, /* need to split by groups */ LVE_FAIL_SETUBLIMIT = 0x201, /* legacy ?*/ LVE_FAIL_RES_ATTACH_TASK = 0x202, LVE_FAIL_CPU_ATTACH_TSK = 0x203, LVE_FAIL_CPUS_ATTACH_TSK = 0x204, LVE_FAIL_FREEZER_ATTACH_TSK = 0x205, LVE_FAIL_CGRP_PARAM_GET = 0x206, LVE_FAIL_GET_UB_BYUID = 0x207, /* cl5, cl6 */ LVE_FAIL_GET_SUB_UB_BYUID = 0x208, /* cl7 */ LVE_FAIL_SET_CPUS_LIM = 0x209, LVE_FAIL_SET_CPU_LIM = 0x20a, LVE_FAIL_SET_CPU_CHWT = 0x20b, LVE_FAIL_SET_IO_LIM = 0x20c, LVE_FAIL_SET_IOPS_LIM = 0x20d, /* don't exist */ LVE_FAIL_SET_LIM_MEM = 0x20e, LVE_FAIL_SET_LIM_PMEM = 0x20f, LVE_FAIL_SET_LIM_NPROC = 0x210, /* LVP <> LVE maping */ LVE_FAIL_MAP_ALLOC = 0x400, LVE_FAIL_MAP_MOVE_RACE_CREATE = 0x402, /* LVP cache/list itself */ LVE_FAIL_ALLOC_LVP = 0x500, LVE_FAIL_LVP_CREATE_RACE = 0x501, LVE_FAIL_LVP_DESTROY_RACE = 0x502, /* global init / fini */ LVE_FAIL_INIT_THRDS_INIT = 0x600, LVE_FAIL_INIT_LVP_PROC = 0x608, LVE_FAIL_MOUNT_CGROUP_ROOTFS = 0x601, LVE_FAIL_ALLOC_LVP_CACHE = 0x607, LVE_FAIL_ALLOC_LVE_CACHE = 0x602, LVE_FAIL_ALLOC_SWITCH_CACHE = 0x603, LVE_FAIL_ALLOC_COOKIE_CACHE = 0x604, /* char dev reg */ LVE_FAIL_MISC_REG = 0x605, /* LA thread start */ LVE_FAIL_STATS_CRT_THREAD = 0x606, /* MNT namespace specific*/ LVE_FAIL_DUP_NS = 0x700, /* enter faults */ LVE_FAIL_ENTER_BAD_PARAMS = 0x800, LVE_FAIL_ENTER_DISABLED = 0x801, LVE_FAIL_ENTER_FAULT = 0x802, LVE_FAIL_ENTER_EP = 0x803, LVE_FAIL_ENTER_UNLINK_RACE = 0x804, }; static inline bool LVE_FAIL_PRECHECK(unsigned int type, unsigned long loc) { if (likely(fail_value == 0)) return 0; if ((LVE_FAIL_LOC(fail_value) == loc) && LVE_FAIL_TYPE(fail_value) & type) return 1; return 0; } static inline bool LVE_CHECK_ONCE(void) { if (LVE_FAIL_TYPE(fail_value) & LVE_FAIL_ONCE_OP) return !test_and_set_bit(LVE_FAIL_ONCE_BIT, &fail_value); else return 1; } static inline bool lve_fail_check(unsigned long loc) { if (LVE_FAIL_PRECHECK(LVE_FAIL_CHECK_OP, loc) && LVE_CHECK_ONCE()) { LVE_DBG("fail %lx\n", LVE_FAIL_LOC(fail_value)); return 1; } return 0; } #define lve_call(call, val, err) (lve_fail_check(val) ? err : call) #define LVE_RACE_STATE() test_bit(LVE_FAIL_RACE_BIT, &fail_value) #include extern wait_queue_head_t lve_race_waitq; extern int lve_race_state; static inline void lve_fail_race(const char *file, unsigned int line, unsigned int id) { if (LVE_FAIL_PRECHECK(LVE_FAIL_RACE_OP, id)) { if (LVE_CHECK_ONCE() && !LVE_RACE_STATE()) { lve_race_state = 0; set_bit(LVE_FAIL_RACE_BIT, &fail_value); LVE_DBG("lve_fail_race: %s:%d id %x sleeping\n", file, line, id); wait_event_interruptible( lve_race_waitq, lve_race_state != 0); LVE_DBG("lve_fail_race: id %x awake\n", id); } else { LVE_DBG("lve_fail_race: %s:%d id %x waking\n", file, line, id); lve_race_state = 1; wake_up_interruptible(&lve_race_waitq); clear_bit(LVE_FAIL_RACE_BIT, &fail_value); } } LVE_DBG("exit\n"); } #define LVE_FAIL_RACE(id) \ lve_fail_race(__FILE__, __LINE__, id); static inline void lve_fail_timeout(unsigned int id, int ms) { if (LVE_FAIL_PRECHECK(LVE_FAIL_TIMEOUT_OP, id) && LVE_CHECK_ONCE()) { LVE_DBG("lve_fail_timeout id %x sleeping for %dms\n", id, ms); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(msecs_to_jiffies(ms)); LVE_DBG("lve_fail_timeout id %x awake\n", id); } } #define LVE_DEBUG_CGROUP_BREAK #ifdef LVE_DEBUG_CGROUP_BREAK extern DECLARE_BITMAP(lve_api_bitmap, PID_MAX_LIMIT); #define LVE_API_ENTER() set_bit(current->pid, lve_api_bitmap) #define LVE_API_EXIT() clear_bit(current->pid, lve_api_bitmap) #define LVE_API_ENTERED() test_bit(current->pid, lve_api_bitmap) #else #define LVE_API_ENTER() do {} while (0) #define LVE_API_EXIT() do {} while (0) #define LVE_API_ENTERED() do {} while (0) #endif #endif