From 36843634e70816801245699fa670b196300a6963 Mon Sep 17 00:00:00 2001 From: zhizhimeimei6 Date: Wed, 25 May 2022 21:40:05 +0800 Subject: [PATCH] rphone: support rProcess.ko ohos inclusion category: feature issue: #I599US CVE: NA ----------------- rProcess.ko is used to test Signed-off-by: zhizhimeimei6 --- drivers/staging/Makefile | 1 + drivers/staging/rphone/Makefile | 3 + drivers/staging/rphone/rasbase/rasbase.c | 873 +++++++++++++++++++ drivers/staging/rphone/rasbase/rasbase.h | 153 ++++ drivers/staging/rphone/rasbase/rasprobe.c | 114 +++ drivers/staging/rphone/rasbase/rasprobe.h | 69 ++ drivers/staging/rphone/rasbase/rasproc.c | 24 + drivers/staging/rphone/rasbase/rasproc.h | 34 + drivers/staging/rphone/rprocess/rasprocess.c | 444 ++++++++++ 9 files changed, 1715 insertions(+) create mode 100644 drivers/staging/rphone/Makefile create mode 100644 drivers/staging/rphone/rasbase/rasbase.c create mode 100644 drivers/staging/rphone/rasbase/rasbase.h create mode 100644 drivers/staging/rphone/rasbase/rasprobe.c create mode 100644 drivers/staging/rphone/rasbase/rasprobe.h create mode 100644 drivers/staging/rphone/rasbase/rasproc.c create mode 100644 drivers/staging/rphone/rasbase/rasproc.h create mode 100644 drivers/staging/rphone/rprocess/rasprocess.c diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 3883281dbe7a..ca4ef641fae7 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -54,3 +54,4 @@ obj-$(CONFIG_HIEVENT) += hievent/ obj-$(CONFIG_DFX_ZEROHUNG) += zerohung/ obj-$(CONFIG_DFX_HUNGTASK) += hungtask/ obj-$(CONFIG_BLACKBOX) += blackbox/ +obj-m += rphone/ diff --git a/drivers/staging/rphone/Makefile b/drivers/staging/rphone/Makefile new file mode 100644 index 000000000000..f6ab16863365 --- /dev/null +++ b/drivers/staging/rphone/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-m += rProcess.o +rProcess-objs := rprocess/rasprocess.o rasbase/rasbase.o rasbase/rasproc.o rasbase/rasprobe.o \ No newline at end of file diff --git a/drivers/staging/rphone/rasbase/rasbase.c b/drivers/staging/rphone/rasbase/rasbase.c new file mode 100644 index 000000000000..00e8c817fb10 --- /dev/null +++ b/drivers/staging/rphone/rasbase/rasbase.c @@ -0,0 +1,873 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022 Huawei Technologies Co., Ltd. All rights reserved. + */ + +#include +#include +#include +#include +long long ras_div(long long num, long long den) +{ +#define RAS_DIV +#ifndef RAS_DIV + return num / den; +#else + unsigned long long ret = 0; + + while (num >= den) { + ret++; + num -= den; + } + return ret; +#endif + /*return do_div(n, base); */ +} + +#if !defined(__VMKLNX__) +#include "rasbase.h" +#include +#include +#include +static int ras_readline(struct file *filp, char *buf, int len) +{ + int ret = 0; + int readlen = 0; + mm_segment_t oldfs; + + ras_retn_if(filp == 0, -ENOENT); + ras_retn_if(filp->f_op->read == 0, -ENOSYS); + ras_retn_if(((filp->f_flags & O_ACCMODE) & O_RDONLY), -EACCES); + oldfs = get_fs(); + set_fs(KERNEL_DS); + for (; readlen < len; buf++, readlen++) { + ret = filp->f_op->read(filp, buf, 1, &filp->f_pos); + if (ret <= 0) + break; + if ('\n' == *buf) { + *buf = 0; + readlen++; + break; + } + } + set_fs(oldfs); + return ret < 0 ? ret : readlen; +} + +int ras_read(const char *filename, int (*line) (void *, const char *), void *data) +{ + int ret = 0; + char buf[512]; + struct file *filp = filp_open(filename, O_RDONLY, 0); + + ras_retn_if(IS_ERR(filp), PTR_ERR(filp)); + while ((ret = ras_readline(filp, buf, sizeof(buf))) > 0) { + ret = line(data, buf); + if (ret != 0) + break; + } + fput(filp); + ras_retn(ret); +} +#endif +/*raslist */ + +struct RasList { + struct RasList *nxt; +}; + +/* rasmap*/ +struct RasMapElement { + struct RasMapElement *nxt; + struct RasMapElement *rme; + void *key; + void *val; + loff_t tm; +}; + +struct RasMap { + struct RasMapElement *nxt; /* valid RME*/ + struct RasMapElement *rme; /* destroyed RME*/ + rasmap_free_t *destroy; + rasmap_less_t *less; + void *data; +}; + +int rasmap_create(struct RasMap **rm, rasmap_less_t *less, rasmap_free_t *destroy, void *data) +{ + struct RasMap *m = 0; + + ras_retn_if(rm == 0, -EINVAL); + ras_retn_iferr(ras_malloc((void **)&m, sizeof(struct RasMap))); + m->less = less; + m->destroy = destroy; + m->data = data; + m->nxt = 0; + m->rme = 0; + *rm = m; + return 0; +} + +static struct RasMapElement *rasmap_findrme(struct RasMap *rm) +{ + struct RasMapElement *rme; + loff_t tm = ras_ms() - 60000; /* 1m*/ + + if (rm == 0) + return 0; + rme = rm->rme; + if (rme == 0) + return 0; + if (rme->tm < tm) { + rm->rme = rme->rme; + return rme; + } + for (; rme->rme != 0; rme = rme->rme) { + if (rme->rme->tm < tm) { + struct RasMapElement *ele = rme->rme; + + rme->rme = ele->rme; + ele->rme = 0; + return ele; + } + } + return 0; +} + +static inline int rasmap_desrme(void *data, void *key, void *val) +{ + struct RasMap *rm = data; + + if (rm->destroy != 0) + rm->destroy(rm->data, key, val); + return 0; +} + +int rasmap_add(struct RasMap *rm, void *key, void *val) +{ + struct RasMapElement *rme = rasmap_findrme(rm); + + if (rme != 0) + rasmap_desrme(rm, rme->key, rme->val); + else if (ras_malloc((void **)&rme, sizeof(struct RasMapElement)) != 0) + ras_retn(-ENOMEM); + rme->tm = 0; + rme->key = key; + rme->val = val; + rme->nxt = rm->nxt; + rm->nxt = rme; + return 0; +} + +static inline int rasmap_equals(struct RasMap *rm, void *k1, void *k2) +{ + if (rm->less != 0) { + return !rm->less(rm->data, k1, k2) + && !rm->less(rm->data, k2, k1); + } + + return k1 == k2; +} + +static struct RasMapElement *rasmap_find(struct RasMap *rm, void *key, int del) +{ + struct RasMapElement *rme; + + if (rm == 0) + return 0; + rme = rm->nxt; + if (rme == 0) + return 0; + if (rasmap_equals(rm, rme->key, key)) { + if (del != 0) + rm->nxt = rme->nxt; + return rme; + } + for (; rme->nxt != 0; rme = rme->nxt) { + if (rasmap_equals(rm, rme->nxt->key, key)) { + struct RasMapElement *tmp = rme->nxt; + + if (del != 0) + rme->nxt = tmp->nxt; + return tmp; + } + } + return 0; +} + +int rasmap_each(struct RasMap *rm, rasmap_each_t *each, void *data) +{ + struct RasMapElement *rme; + + ras_retn_if((rm == 0 || each == 0), -EINVAL); + for (rme = rm->nxt; rme != 0; rme = rme->nxt) + ras_retn_iferr(each(data, rme->key, rme->val)); + return 0; + +} + +int rasmap_size(struct RasMap *rm) +{ + int cnt = 0; + struct RasMapElement *rme; + + ras_retn_if(rm == 0, cnt); + for (rme = rm->nxt; rme != 0; rme = rme->nxt) + cnt++; + return cnt; +} + +static int rasmap_eachrme(struct RasMap *rm, int (*each)(void *data, void *key, void *val), void *data) +{ + struct RasMapElement *rme = rm->rme; + + for (; rme != 0; rme = rme->rme) + ras_retn_iferr(each(data, rme->key, rme->val)); + return 0; +} + +void *rasmap_get(struct RasMap *rm, void *key) +{ + struct RasMapElement *rme = rasmap_find(rm, key, 0); + + return (0 != rme && 0 == rme->tm) ? rme->val : 0; +} + +static inline void rasmap_addrme(struct RasMap *rm, struct RasMapElement *rme) +{ + rme->tm = ras_ms(); + rme->rme = rm->rme; + rm->rme = rme; +} + +void rasmap_del(struct RasMap *rm, void *key) +{ + struct RasMapElement *rme = rasmap_find(rm, key, 1); + + if (rme != 0) + rasmap_addrme(rm, rme); +} + +void rasmap_clear(struct RasMap *rm) +{ + struct RasMapElement *rme = rm->nxt; + + /* clear firstly */ + for (rm->nxt = 0; rme != 0; rme = rme->nxt) + rasmap_addrme(rm, rme); /* add to rme */ +} + +void rasmap_destroy(struct RasMap *rm) +{ + if (rm == 0) + return; + if (rm->destroy != 0) { + rasmap_clear(rm); + rasmap_eachrme(rm, rasmap_desrme, rm); + } + ras_free(rm); +} + +struct RasBff { + struct RasBff *prv; + struct RasBff *nxt; + int length; + char bff[1024 - sizeof(int) - 2 * sizeof(struct RasBff *)]; +}; + +struct RasVector { + int page; + int length; + rwlock_t rwk; + struct RasBff *bff; +}; + +int rasvector_create(struct RasVector **self) +{ + struct RasVector *vec = 0; + int len = sizeof(struct RasBff); + + ras_retn_iferr(ras_malloc((void **)&vec, sizeof(struct RasVector))); + ras_retn_iferr_then(ras_malloc((void **)&vec->bff, len), ras_free(vec)); + vec->bff->nxt = vec->bff; + vec->bff->prv = vec->bff; + rwlock_init(&vec->rwk); + *self = vec; + return 0; +} + +static inline struct RasBff *rasvector_tail(struct RasVector *vec) +{ + int len = vec->length; + struct RasBff *bff = vec->bff; + + while (len > bff->length) { + len -= bff->length; + bff = bff->nxt; + } + return bff; +} + +static inline int rasvector_grow(struct RasVector *vec, struct RasBff *trb, int length) +{ + while (trb->length + length >= sizeof(trb->bff)) { + length = length - sizeof(trb->bff) + trb->length; + if (trb->nxt == vec->bff) { + struct RasBff *nrb = 0; + + ras_retn_iferr(ras_malloc + ((void **)&nrb, sizeof(struct RasBff))); + vec->page++; + nrb->nxt = trb->nxt; + nrb->nxt->prv = nrb; + nrb->prv = trb; + trb->nxt = nrb; + } else { + trb = trb->nxt; + } + } + return 0; +} +static inline int rasvector_copy(struct RasVector *vec, struct RasBff *rb, const char *str) +{ + int i, len = strlen(str); + + ras_retn_iferr(rasvector_grow(vec, rb, len)); + for (i = 0; i < len; i++) { + if (rb->length == sizeof(rb->bff)) { + rb = rb->nxt; + rb->length = 0; + } + rb->bff[rb->length++] = str[i]; + } + vec->length += len; + return 0; +} + +int rasvector_append(struct RasVector *vec, const char *str) +{ + int ret; + + write_lock(&vec->rwk); + ret = rasvector_copy(vec, rasvector_tail(vec), str); + write_unlock(&vec->rwk); + ras_retn(ret); +} + +static inline int rasvector_sub(struct RasVector *vec, int idx, int len, char *buf) +{ + int i = 0; + struct RasBff *bff = vec->bff; + + if (idx + len > vec->length) + ras_retn(-ESPIPE); + while (idx - bff->length >= 0) { + idx -= bff->length; + bff = bff->nxt; + } + for (i = 0; i < len; i++) { + buf[i] = bff->bff[idx + i]; + if (idx + i + 1 == bff->length) { + bff = bff->nxt; + idx = -i - 1; + } + } + return 0; +} + +int rasvector_substr(struct RasVector *vec, int beginIndex, int length, char *savedbuf) +{ + int ret; + + read_lock(&vec->rwk); + ret = rasvector_sub(vec, beginIndex, length, savedbuf); + read_unlock(&vec->rwk); + return ret; +} + +int rasvector_reset(struct RasVector *vec) +{ + struct RasBff *nxt; + + write_lock(&vec->rwk); + for (nxt = vec->bff->nxt; nxt != vec->bff; nxt = nxt->nxt) + nxt->length = 0; + vec->length = 0; + vec->bff->length = 0; + write_unlock(&vec->rwk); + return 0; +} + +int rasvector_length(struct RasVector *vec) +{ + int len; + + read_lock(&vec->rwk); + len = vec->length; + read_unlock(&vec->rwk); + return len; +} + +int rasvector_destroy(struct RasVector *vec) +{ + struct RasBff *nxt; + struct RasBff *prv; + + write_lock(&vec->rwk); + nxt = vec->bff->nxt; + while (nxt != vec->bff) { + prv = nxt; + nxt = prv->nxt; + ras_free(prv); + } + ras_free(vec->bff); + write_unlock(&vec->rwk); + ras_free(vec); + return 0; +} + +void rasvector_display(struct RasVector *vec) +{ + char buf[128]; + int len = 0; + + snprintf(buf, sizeof(buf), "length=%d, bffsize=%d\n", + vec->length, vec->page + 1); + len = ras_debugset(0); + ras_info(buf); + ras_debugset(len); +} + +struct RasProc { + struct RasVector *vec; + struct proc_dir_entry *pde; + void *data; +}; + +int rasproc_read(struct RasProc *self, void (*update) (struct RasProc *), + char *buf, char **bl, off_t offset, int len, int *eof) +{ + int used; + + if (offset == 0) { + rasvector_reset(self->vec); + update(self); + /* rasvector_display(self->vec); */ + } + used = rasvector_length(self->vec); + if (offset >= used) { + *eof = 1; + return 0; + } + len--; /* TODO delete this */ + if (used - offset < len) + len = used - offset; + rasvector_substr(self->vec, offset, len, buf); + return len; + +} + +void *rasproc_data(struct RasProc *proc) +{ + return proc->data; +} + +int rasproc_append(struct RasProc *self, const char *str) +{ + return rasvector_append(self->vec, str); +} + +struct RasArgs { + int argc; + char **args; + char *arg; + int len; +}; + +static void rasargs_cut(struct RasArgs *rargs) +{ + const char *arg = rargs->arg; + + rargs->argc = 1; + while (1) { + arg = ras_skipnull(arg, rargs->len - (arg - rargs->arg)); + if (arg == 0) + return; + arg = ras_skipword(arg, rargs->len - (arg - rargs->arg)); + if (0 == arg || 0 == *arg) + return; + rargs->arg[arg - rargs->arg] = 0; + rargs->argc++; + } +} + +static char *rasargs_nextword(struct RasArgs *rargs, int *i) +{ + const char *tmp; + const char *arg = rargs->arg + *i; + + arg = ras_skipnull(arg, rargs->len - (arg - rargs->arg)); + tmp = ras_skipword(arg, rargs->len - (arg - rargs->arg)); + *i = tmp == 0 ? rargs->len : tmp - rargs->arg; + return (char *)arg; +} + +static int rasargs_ctor(struct RasArgs *rargs, const char *args, int len) +{ + int i, j; + + rargs->len = len + 1; + ras_retn_iferr(ras_malloc((void **)&rargs->arg, rargs->len)); + memcpy(rargs->arg, args, len); + rargs->arg[len] = 0; + rasargs_cut(rargs); + ras_retn_iferr_then(ras_malloc((void **)&rargs->args, + rargs->argc * sizeof(char *)), + ras_free(rargs->arg)); + for (i = 0, j = 0; j < rargs->argc && i < rargs->len; j++) + rargs->args[j] = rasargs_nextword(rargs, &i); + if (rargs->args[rargs->argc - 1] == 0) + rargs->argc--; + return 0; +} + +static void rasargs_dtor(struct RasArgs *rargs) +{ + ras_free(rargs->arg); + ras_free(rargs->args); +} + +int ras_args(const char *args, unsigned long len, + int (*process)(void *dt, int argc, char *args[]), void *dt) +{ + int ret; + struct RasArgs rargs; + + if (0 == args || 0 >= len || 0 == process) + ras_retn(-EINVAL); + ras_retn_iferr(rasargs_ctor(&rargs, args, len)); + ret = process(dt, rargs.argc, rargs.args); + rasargs_dtor(&rargs); + ras_retn(ret); +} + +unsigned long long ras_ns(void) +{ + struct timespec64 ts; + + ktime_get_coarse_real_ts64(&ts); + + return ts.tv_sec * 1000000000ULL + ts.tv_nsec; +} + +unsigned long long ras_ms(void) +{ + struct timespec64 ts; + + ktime_get_coarse_real_ts64(&ts); + + return ts.tv_sec * 1000ULL + ras_div(ts.tv_nsec, 1000000); +} + +static inline int ras_getbase(char c) +{ + return ('x' == c || 'X' == c) ? 16 : 8; +} +static inline int rfiler_isdigit(char c) +{ + return c >= '0' && c <= '9'; +} + +static inline int ras_isxdigit(char c) +{ + return (c >= '0' && c <= '9') || + (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); +} + +static inline int ras_xtoi(char c) +{ + if (rfiler_isdigit(c)) + return c - '0'; + return c - ((c >= 'a' && c <= 'f') ? 'a' : 'A') + 10; +} + +static inline int ras_invalidparam(const char *a, unsigned long pos) +{ + char bff[256]; + + snprintf(bff, sizeof(bff), "%s[%lu] is a invalid parameter", a, pos); + ras_fail(bff); + ras_retn(-EINVAL); +} + +static inline int ras_isxbyte(char c) +{ + static char bcs[] = { 'k', 'K', 'm', 'M', 'g', 'G', 't', 'T' }; + int i, len = ARRAY_SIZE(bcs); + + for (i = 0; i < len; i++) { + if (c == bcs[i]) + return 1 + i / 2; + } + return 0; +} +static inline long long ras_getbyte(int count) +{ + long long val = 1LL; + int i; + + for (i = 0; i < count; i++) + val *= 1024LL; + return val; +} + +int ras_equal(const char *exp, const char *act) +{ + while (*exp && *exp == *act) { + exp++; + act++; + } + return *exp == *act; +} + +int ras_atoll(long long *ll, const char *a, long len, long *ppos) +{ + char c = 0; + int cv = 0; + int base = 10; + long long rlt = 0LL; + unsigned long pos = 0; + char is_negative = 0; + + if (ll == 0 || a == 0 || len == 0) + ras_retn(-EINVAL); + + if (ppos != 0) + pos = *ppos; + + while (ras_isspace(a[pos])) { + if (++pos >= len) + ras_retn(-EPERM); + } + if (a[pos] == 0) + ras_retn(-EPERM); + /* init base */ + if ((a[pos] == '0') && (pos + 1 < len)) { + c = a[pos + 1]; + if (!ras_isspace(c)) { + base = ras_getbase(c); + pos += (base >> 3); + } + } + /* init signed */ + if (('-' == a[pos]) && (pos + 1 < len)) { + is_negative = 1; + pos++; + } else if (('+' == a[pos]) && (pos + 1 < len)) { + is_negative = 0; + pos++; + } + + for (; pos < len; pos++) { + c = a[pos]; + if (ras_isxdigit(c)) { + cv = ras_xtoi(c); + } else { + cv = ras_isxbyte(c); + if (cv != 0) { + rlt = rlt * ras_getbyte(cv); + c = a[pos + 1]; + if (c == 0 || ras_isspace(c)) + break; + ras_retn(ras_invalidparam(a, pos + 1)); + } else if (c == 0 || ras_isspace(c)) { + break; + } else { + ras_retn(ras_invalidparam(a, pos)); + } + } + if (cv >= base) + ras_retn(ras_invalidparam(a, pos)); + rlt = rlt * base + cv; + } + + *ll = is_negative ? -rlt : rlt; + if (ppos != 0) + *ppos = pos; + return 0; +} + +int ras_isspace(char c) +{ + static char cs[] = { ' ', '\t', '\r', '\n' }; + int i = 0; + int len = ARRAY_SIZE(cs); + + for (i = 0; i < len; i++) { + if (c == cs[i]) + return c; + } + return 0; +} + +char *ras_trim(char *s, int *n) +{ + int i, len = *n; + + for (i = 0; i < len; i++) { + if (!ras_isspace(s[i])) + break; + } + while (--len > 0) { + if (!ras_isspace(s[len])) + break; + s[len] = 0; + } + *n = len + 1 - i; + return s + i; +} + +const char *ras_skipword(const char *bff, unsigned long len) +{ + unsigned long idx; + + if (bff == 0) + return 0; + for (idx = 0; idx < len; idx++) { + if (bff[idx] == 0 || ras_isspace(bff[idx])) + break; + } + if (idx < len) + return bff + idx; + return 0; + +} + +const char *ras_skipnull(const char *bff, unsigned long len) +{ + unsigned long idx = 0; + + if (bff == 0) + return 0; + for (idx = 0; idx < len; idx++) { + if (bff[idx] == 0) + continue; + if (!ras_isspace(bff[idx])) + break; + } + if (idx < len) + return bff + idx; + return 0; +} + +int ras_malloc(void **m, long len) +{ + void *p; + + if (m == 0) + ras_retn(-EINVAL); + p = kmalloc(len, GFP_ATOMIC); + *m = p; + if (p == o) + ras_retn(-ENOMEM); + memset(*m, 0, len); + return 0; +} + +void ras_free(const void *p) +{ + if (p != 0) + kfree(p); +} + +enum RasDebugType { + RAS_DEBUG, + RAS_INFO, + RAS_WARN, + RAS_FAIL, + RAS_NULL, +}; + +#define DBG_SET 1 +static inline int ras_debug(const int op, int lvl) +{ + static int level = RAS_WARN; + + if (DBG_SET == op && -1 != lvl && lvl != level) { + int lev = level; + + level = lvl; + return lev; + } + return level; +} + +int ras_debugset(int lvl) +{ + lvl = 1; /* forbidden log for release */ + return ras_debug(DBG_SET, lvl); +} + +int __ras_retn(const char *filename, const char *func, int line, int ret) +{ + if (ras_debug(!DBG_SET, 0) <= RAS_DEBUG && ret) + pr_err("%-3d = %s:%d\n", ret, func, line); + return ret; +} + +int __ras_info(const char *file, const char *func, int line, const char *msg) +{ + if (ras_debug(!DBG_SET, 0) <= RAS_INFO) + pr_err("%s -> %s:%d\n", msg, func, line); + return 0; +} + +int __ras_warn(const char *file, const char *func, int line, const char *msg) +{ + if (ras_debug(!DBG_SET, 0) <= RAS_WARN) + pr_err("%s -> %s:%d\n", msg, func, line); + return 0; +} + +int __ras_fail(const char *file, const char *func, int line, const char *msg) +{ + if (ras_debug(!DBG_SET, 0) <= RAS_FAIL) + pr_err("%s -> %s:%d\n", msg, func, line); + return 0; +} + +#include +void ras_sleep(unsigned long long ms) +{ + long jffn = ras_div(ms * HZ, 1000); + + ms -= jffn * 1000 / HZ; + set_current_state(TASK_INTERRUPTIBLE); + while (jffn > 0) + jffn = schedule_timeout(jffn); + if (ms != 0) + udelay(ms * 1000); +} + +int ras_check(void) +{ + char path[] = "/mnt/.pipe_androidfire/check_license"; + int result = call_usermodehelper(path, NULL, NULL, UMH_WAIT_PROC); + + if (result) + return -1; + return 0; +} +void ras_delay(unsigned long long ms) +{ + while (ms) { + if (ms >= 2) { /* 2ms: udelay must less then 2ms */ + udelay(2000); /* 2000: udelay must less then 2ms */ + ms -= 2; /* 2ms: udelay must less then 2ms */ + } else { + udelay(ms * 1000); /* 1000: 1ms unit */ + ms = 0; + } + } +} + diff --git a/drivers/staging/rphone/rasbase/rasbase.h b/drivers/staging/rphone/rasbase/rasbase.h new file mode 100644 index 000000000000..04e1ef48e1eb --- /dev/null +++ b/drivers/staging/rphone/rasbase/rasbase.h @@ -0,0 +1,153 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022 Huawei Technologies Co., Ltd. All rights reserved. + */ + +#ifndef __RAS_BASE__ +#define __RAS_BASE__ + +#include +#include +#include +struct RasVector; +int rasvector_create(struct RasVector **); +int rasvector_append(struct RasVector *, const char *str); +int rasvector_substr(struct RasVector *, int idx, int len, char *savedbuf); +int rasvector_reset(struct RasVector *); +int rasvector_length(struct RasVector *); +int rasvector_destroy(struct RasVector *); +void rasvector_display(struct RasVector *vec); + +struct RasProc; +int rasproc_read(struct RasProc *, void (*update) (struct RasProc *), + char *buf, char **bl, off_t offset, int len, int *eof); +int rasproc_append(struct RasProc *, const char *str); +int rasproc_destroy(struct RasProc *); +void *rasproc_data(struct RasProc *); + +struct RasMap; +typedef int (rasmap_less_t) (void *data, void *k1, void *k2); +typedef int (rasmap_each_t) (void *data, void *key, void *val); +typedef void (rasmap_free_t) (void *data, void *key, void *val); +int rasmap_size(struct RasMap *rm); +int rasmap_each(struct RasMap *rm, rasmap_each_t *each, void *data); +int rasmap_add(struct RasMap *rm, void *key, void *val); +void *rasmap_get(struct RasMap *rm, void *key); +void rasmap_del(struct RasMap *rm, void *key); +void rasmap_clear(struct RasMap *rm); +void rasmap_destroy(struct RasMap *rm); +int rasmap_create(struct RasMap **rm, rasmap_less_t *less, + rasmap_free_t *freeKV, void *data); + +int ras_read(const char *filename, int (*line) (void *, const char *), void *); + +/* oct: 012345670 ; dec: 1234567890 ; hex: 0x1234567890abcdef*/ +int ras_atoll(long long *ll, const char *a, long len, long *ppos); +int ras_equal(const char *exp, const char *act); +const char *ras_skipword(const char *bff, unsigned long len); +const char *ras_skipnull(const char *bff, unsigned long len); +int ras_args(const char *args, unsigned long len, + int (*process)(void *dt, int argc, char *args[]), void *dt); +long long ras_div(long long n, long long base); + +char *ras_trim(char *s, int *n); +int ras_check(void); +int ras_isspace(char); +int ras_malloc(void **, long); +void ras_free(const void *); +#define RASTICK (3 * 1000 / HZ) +void ras_sleep(unsigned long long ms); + +unsigned long long ras_ns(void); +unsigned long long ras_ms(void); +void ras_delay(unsigned long long ms); + +int ras_debugset(int level); /* set level, return old level*/ +#define ras_info(msg) __ras_info(__FILE__, __func__, __LINE__, msg); +#define ras_warn(msg) __ras_warn(__FILE__, __func__, __LINE__, msg); +#define ras_fail(msg) __ras_fail(__FILE__, __func__, __LINE__, msg); +#define ras_retn(ret) do { \ + return __ras_retn(__FILE__, __func__, __LINE__, ret); \ +} while (0) +int __ras_info(const char *file, const char *func, int line, const char *); +int __ras_warn(const char *file, const char *func, int line, const char *); +int __ras_fail(const char *file, const char *func, int line, const char *); +int __ras_retn(const char *file, const char *func, int line, int ret); + +#define ras_retn_if(con, ret) do { \ + if (con) { \ + ras_retn(ret); \ + } \ +} while (0) + +#define ras_retn_iferr(ret) do { \ + int ____ret = (ret); \ + if (____ret) { \ + ras_retn(____ret); \ + } \ +} while (0) + +#define ras_retn_iferr_then(ret, op) do { \ + int ____ret = (ret); \ + if (____ret) { \ + (op); \ + ras_retn(____ret); \ + } \ +} while (0) + +#define ras_setllu_retn(rase, valu, flag, fld, arg) do { \ + int len = strlen(#fld"="); \ + if (strncmp(#fld"=", arg, len) == 0) { \ + long long val = 0; \ + char *cval = arg + len; \ + ras_retn_if(*cval == 0, (-EINVAL)); \ + ras_retn_iferr(ras_atoll(&val, cval, strlen(cval), 0)); \ + rase->flag.fld = 1; \ + rase->valu.fld = val; \ + return 0; \ + } \ +} while (0) + +#define ras_setstr_retn(rase, valu, flag, fld, arg) do { \ + int len = strlen(#fld"="); \ + if (strncmp(#fld"=", arg, len) == 0) { \ + char *cval = arg + len; \ + ras_retn_if(*cval == 0, (-EINVAL)); \ + rase->flag.fld[0] = 1; \ + strncpy(rase->valu.fld, cval, sizeof(rase->valu.fld)); \ + return 0; \ + } \ +} while (0) + +int rasfile_pathname(struct vfsmount *mnt, struct dentry *den, + int (*op)(void *, const char *), void *data); +#define rasbase_set(ins, fld, arg) do { \ + unsigned long long val = 0; \ + int len = strlen(#fld"="); \ + if (strncmp(#fld"=", arg, len) == 0) { \ + char *cval = arg + len; \ + ras_retn_if(*cval == 0, (-EINVAL)); \ + ras_retn_iferr(ras_atoll(&val, cval, strlen(cval), 0)); \ + ins->fld = val; \ + return 0; \ + } \ +} while (0); +#define rasbase_set_func(ins, fld, arg, func) do { \ + int len = strlen(#fld"="); \ + if (strncmp(#fld"=", arg, len) == 0) { \ + char *cval = arg + len; \ + ras_retn_if(*cval == 0, (-EINVAL)); \ + ins->fld = func(cval); \ + return 0; \ + } \ +} while (0); +#define rasbase_cset(ins, fld, arg) do { \ + int len = strlen(#fld"="); \ + if (strncmp(#fld"=", arg, len) == 0) { \ + char *cval = arg + len; \ + ras_retn_if(*cval == 0, (-EINVAL)); \ + snprintf(ins->fld, sizeof(ins->fld), cval); \ + return 0; \ + } \ +} while (0); +#endif diff --git a/drivers/staging/rphone/rasbase/rasprobe.c b/drivers/staging/rphone/rasbase/rasprobe.c new file mode 100644 index 000000000000..a0b10279283f --- /dev/null +++ b/drivers/staging/rphone/rasbase/rasprobe.c @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022 Huawei Technologies Co., Ltd. All rights reserved. + */ + +#include "rasprobe.h" + +#ifdef __ASM_PTRACE_H +/*ARM64bit arm arg's regs : r0-r3 */ +#define REG_RET(regs) regs->regs[0] +#define REG_ARG0(regs) regs->regs[0] +#define REG_ARG1(regs) regs->regs[1] +#define REG_ARG2(regs) regs->regs[2] +#define REG_ARG3(regs) regs->regs[3] + +#elif defined __ASM_ARM_PTRACE_H +/*ARM32bit arm arg's regs : r0-r3*/ +#define REG_RET(regs) regs->uregs[0] +#define REG_ARG0(regs) regs->uregs[0] +#define REG_ARG1(regs) regs->uregs[1] +#define REG_ARG2(regs) regs->uregs[2] +#define REG_ARG3(regs) regs->uregs[3] + +#else +/*x86 Linux 9 arg's regs : RDI,RSI,RDX,RCX,RAX,R8,R9,R10,R11*/ +#define REG_RET(regs) regs->ax +#define REG_ARG0(regs) regs->di +#define REG_ARG1(regs) regs->si +#define REG_ARG2(regs) regs->dx +#define REG_ARG3(regs) regs->cx +#endif + +int rasprobe_entry(struct rasprobe_instance *ri, struct pt_regs *regs) +{ + struct RasRegs *rd = (struct RasRegs *)ri->data; + /*arm arg's regs : r0-r3*/ + rd->args[0] = (void *)REG_ARG0(regs); + rd->args[1] = (void *)REG_ARG1(regs); + rd->args[2] = (void *)REG_ARG2(regs); + rd->args[3] = (void *)REG_ARG3(regs); + return 0; +} + +void rasprobe_seturn(struct pt_regs *regs, long val) +{ + REG_RET(regs) = val; +} + +void rasprobe_setarg(struct pt_regs *regs, int index, long val) +{ + switch (index) { + case 0: + REG_ARG0(regs) = val; + break; + case 1: + REG_ARG1(regs) = val; + break; + case 2: + REG_ARG2(regs) = val; + break; + case 3: + REG_ARG3(regs) = val; + break; + default: + break; + } +} + +#ifdef CONFIG_ARCH_HISI_RPHONE +void rasprobe_setargptr(struct pt_regs *regs, int index, void *val) +{ + switch (index) { + case 0: + REG_ARG0(regs) = (uintptr_t)val; + break; + case 1: + REG_ARG1(regs) = (uintptr_t)val; + break; + case 2: + REG_ARG2(regs) = (uintptr_t)val; + break; + case 3: + REG_ARG3(regs) = (uintptr_t)val; + break; + default: + break; + } +} +#endif + +int register_rasprobes(struct rasprobe **rps, int num) +{ + int i, ret; + + if (num <= 0) + return -EINVAL; + for (i = 0; i < num; i++) { + ret = register_kretprobe(rps[i]); + if (ret < 0) { + pr_err("rasprobes failed when registering %s, ret = %d\n", rps[i]->kp.symbol_name, ret); + unregister_rasprobes(rps, i); + break; + } + } + return ret; +} + +void unregister_rasprobes(struct rasprobe **rps, int num) +{ + int i; + + for (i = 0; i < num; i++) + unregister_kretprobe(rps[i]); +} diff --git a/drivers/staging/rphone/rasbase/rasprobe.h b/drivers/staging/rphone/rasbase/rasprobe.h new file mode 100644 index 000000000000..a782b4236dfb --- /dev/null +++ b/drivers/staging/rphone/rasbase/rasprobe.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022 Huawei Technologies Co., Ltd. All rights reserved. + */ + +#ifndef __RAS_PROBE__ +#define __RAS_PROBE__ + +#include +#include +#include +#include + +#define rasprobe_instance kretprobe_instance +#define rasprobe kretprobe + +struct RasRegs { + void *args[4]; +}; + +#define rasprobe_name(fun) rasprobe_##fun##_kretname +#define rasprobe_handler(fun) rasprobe_##fun##_handler + +#define rasprobe_init(fun) { \ + .kp.symbol_name = #fun, \ + .handler = rasprobe_handler(fun), \ + .entry_handler = rasprobe_entry, \ + .data_size = sizeof(struct RasRegs), \ +} + +#define rasprobe_define(fun) \ +static struct rasprobe rasprobe_name(fun) = rasprobe_init(fun) + +static inline int post_null_handler(struct rasprobe_instance *ri, + struct pt_regs *regs) +{ + return 0; +} + +#define rasprobe_handler_entry(fun) rasprobe_##fun##_handler_entry +#define rasprobe_init_entry(fun) { \ + .kp.symbol_name = #fun, \ + .handler = post_null_handler, \ + .entry_handler = rasprobe_handler_entry(fun), \ + .data_size = sizeof(struct RasRegs), \ +} + +#define rasprobe_entry_define(fun) \ +static struct rasprobe rasprobe_name(fun) = rasprobe_init_entry(fun) +/*both entry and exit was stubbed for the function*/ +#define rasprobe_init_entry_exit(fun) { \ + .kp.symbol_name = #fun, \ + .handler = rasprobe_handler(fun), \ + .entry_handler = rasprobe_handler_entry(fun), \ + .data_size = sizeof(struct RasRegs), \ +} +#define rasprobe_entry_exit_define(fun) \ +static struct rasprobe rasprobe_name(fun) = rasprobe_init_entry_exit(fun) +int rasprobe_entry(struct rasprobe_instance *ri, struct pt_regs *regs); +void rasprobe_seturn(struct pt_regs *regs, long val); +void rasprobe_setarg(struct pt_regs *regs, int index, long val); +#ifdef CONFIG_ARCH_HISI_RPHONE +void rasprobe_setargptr(struct pt_regs *regs, int index, void *val); +#endif +int register_rasprobes(struct rasprobe **rps, int num); +void unregister_rasprobes(struct rasprobe **rps, int num); + +#endif + diff --git a/drivers/staging/rphone/rasbase/rasproc.c b/drivers/staging/rphone/rasbase/rasproc.c new file mode 100644 index 000000000000..a698583a51d8 --- /dev/null +++ b/drivers/staging/rphone/rasbase/rasproc.c @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022 Huawei Technologies Co., Ltd. All rights reserved. + */ + +#include "../rasbase/rasbase.h" +#include "rasproc.h" + +int proc_init(char *name, const struct proc_ops *proc_ops, void *data) +{ + struct proc_dir_entry *pde = 0; + + if (name == 0) + ras_retn(-ENOMEM); + pde = proc_create_data(name, S_IFREG | 0666, 0, proc_ops, data); + if (unlikely(pde == 0)) + ras_retn(-ENOMEM); + return 0; +} + +void proc_exit(const char *name) +{ + remove_proc_entry(name, 0); +} diff --git a/drivers/staging/rphone/rasbase/rasproc.h b/drivers/staging/rphone/rasbase/rasproc.h new file mode 100644 index 000000000000..9e09a25c0a86 --- /dev/null +++ b/drivers/staging/rphone/rasbase/rasproc.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022 Huawei Technologies Co., Ltd. All rights reserved. + */ + +#ifndef _PROC_COM_H_ +#define _PROC_COM_H_ + +#include +#include +#include +#include + +#define FILE_NODE(file) file->f_path.dentry->d_inode +#define proc_ops_name(name) proc_ops_##name +#define proc_ops_open(name) proc_open_##name +#define proc_ops_show(name) proc_show_##name +#define proc_ops_write(name) proc_write_##name +#define proc_ops_init(name) { \ + .proc_open = proc_ops_open(name), \ + .proc_read = seq_read, \ + .proc_write = proc_ops_write(name), \ + .proc_lseek = seq_lseek, \ + .proc_release = single_release, \ +} + +#define proc_ops_define(name) \ +static struct proc_ops proc_ops_name(name) = proc_ops_init(name) + +int proc_init(char *name, const struct proc_ops *proc_ops, void *data); + +void proc_exit(const char *name); +#endif + diff --git a/drivers/staging/rphone/rprocess/rasprocess.c b/drivers/staging/rphone/rprocess/rasprocess.c new file mode 100644 index 000000000000..d0d857b63fb0 --- /dev/null +++ b/drivers/staging/rphone/rprocess/rasprocess.c @@ -0,0 +1,444 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022 Huawei Technologies Co., Ltd. All rights reserved. + */ + +#include "../rasbase/rasbase.h" +#include "../rasbase/rasprobe.h" +#include "../rasbase/rasproc.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define TOOL_NAME "rProcess" +#define FAULTS_MAX 16 + +#define PID_NS(proxy) proxy->pid_ns_for_children +#define SET_TASK_STATE(tsk, task_value) smp_store_mb((tsk)->state, (task_value)) + +enum FaultType { + PROCESS_D_STATE = 1, + PROCESS_Z_STATE, + PROCESS_T_STATE, + PROCESS_EXIT, + PROCESS_HANG, +}; + +struct FaultImpl { + pid_t pid; + pid_t tid; + enum FaultType fault; +}; + +struct FaultList { + struct FaultImpl impl[FAULTS_MAX]; + rwlock_t rwk; +}; + +static struct { + const char *op; + enum FaultType type; +} fault_ops[] = { + {.op = "D-state", PROCESS_D_STATE}, + {.op = "Z-state", PROCESS_Z_STATE}, + {.op = "T-state", PROCESS_T_STATE}, + {.op = "exit", PROCESS_EXIT}, + {.op = "hang", PROCESS_HANG}, +}; + +enum FaultType string2fault(const char *name) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(fault_ops); i++) { + if (strcmp(fault_ops[i].op, name) == 0) + return fault_ops[i].type; + } + return 0; +} + +const char *fault2string(enum FaultType fault) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(fault_ops); i++) { + if (fault_ops[i].type == fault) + return fault_ops[i].op; + } + return 0; +} + +static struct FaultList fault_list; + +static inline struct task_struct *find_process(pid_t pid) +{ + struct task_struct *tsk; + struct pid_namespace *ns = PID_NS(current->nsproxy); + struct pid *pd = find_pid_ns(pid, ns); + + rcu_read_lock(); + tsk = pid_task(pd, PIDTYPE_PID); + rcu_read_unlock(); + + return tsk; +} + +static inline struct task_struct *find_thread_from_group(struct task_struct *ts, + pid_t tid) +{ + struct task_struct *t = ts; + + do { + if (t == NULL) + break; + if (t->pid == tid) + return t; + t = next_thread(t); + } while (t != ts); + return NULL; +} +static inline struct task_struct *find_thread(pid_t tid) +{ + struct task_struct *t; + + t = find_process(tid); + t = find_thread_from_group(t, tid); + return t; +} + +void fail_thread(struct task_struct *tsk, struct FaultImpl *ft) +{ + switch (ft->fault) { + case PROCESS_D_STATE: + if (tsk->exit_state == EXIT_ZOMBIE) + tsk->exit_state = 0; + SET_TASK_STATE(tsk, TASK_UNINTERRUPTIBLE); + break; + case PROCESS_Z_STATE: + SET_TASK_STATE(tsk, TASK_DEAD); + tsk->exit_state = EXIT_ZOMBIE; + break; + case PROCESS_T_STATE: + case PROCESS_HANG: + if (tsk->exit_state == EXIT_ZOMBIE) + tsk->exit_state = 0; + SET_TASK_STATE(tsk, TASK_STOPPED); + break; + default: + break; + } +} + +void resume_thread(struct task_struct *tsk, struct FaultImpl *ft) +{ + switch (ft->fault) { + case PROCESS_D_STATE: + case PROCESS_T_STATE: + case PROCESS_HANG: + SET_TASK_STATE(tsk, TASK_INTERRUPTIBLE); + wake_up_process(tsk); + break; + case PROCESS_Z_STATE: + if (tsk->exit_state == EXIT_ZOMBIE) + tsk->exit_state = 0; + SET_TASK_STATE(tsk, TASK_INTERRUPTIBLE); + wake_up_process(tsk); + break; + case PROCESS_EXIT: + break; + default: + break; + } +} + +static void action_each_threads(struct task_struct *ts, struct FaultImpl *ft, + void (atction) (struct task_struct *, + struct FaultImpl *)) +{ + struct task_struct *t; + + t = find_process(ts->tgid); /*find the threads group leader */ + ts = t; + do { + if (t == NULL) + break; + + atction(t, ft); + t = next_thread(t); + } while (t != ts); + +} + +void fail_process(struct task_struct *tsk, struct FaultImpl *ft) +{ + switch (ft->fault) { + case PROCESS_D_STATE: + case PROCESS_Z_STATE: + case PROCESS_HANG: + action_each_threads(tsk, ft, fail_thread); + break; + case PROCESS_T_STATE: + kill_pid(find_vpid(tsk->pid), SIGSTOP, 1); + action_each_threads(tsk, ft, fail_thread); + break; + case PROCESS_EXIT: + kill_pid(find_vpid(tsk->pid), SIGQUIT, 1); + break; + default: + break; + } +} + +void resume_process(struct task_struct *tsk, struct FaultImpl *ft) +{ + switch (ft->fault) { + case PROCESS_D_STATE: + case PROCESS_Z_STATE: + case PROCESS_HANG: + action_each_threads(tsk, ft, resume_thread); + break; + case PROCESS_T_STATE: + action_each_threads(tsk, ft, resume_thread); + kill_pid(find_vpid(tsk->pid), SIGCONT, 1); + break; + case PROCESS_EXIT: + break; + default: + break; + } +} + +void fail(struct task_struct *tsk, struct FaultImpl *ft) +{ + if (ft->pid) + fail_process(tsk, ft); + else + fail_thread(tsk, ft); + +} + +void resume(struct task_struct *tsk, struct FaultImpl *ft) +{ + if (ft->pid) + resume_process(tsk, ft); + else + resume_thread(tsk, ft); +} + +static struct FaultImpl *find_fault(struct FaultImpl *ft) +{ + int i = 0; + int j = -1; + + for (i = 0; i < FAULTS_MAX; i++) { + if ((fault_list.impl[i].pid != 0 + && fault_list.impl[i].pid == ft->pid) + || (fault_list.impl[i].tid != 0 + && fault_list.impl[i].tid == ft->tid)) { + j = i; + break; + } + + if (fault_list.impl[i].fault == 0 && j == -1) + j = i; + } + if (j == -1) + return 0; + return &fault_list.impl[j]; +} + +static int fill_fault(struct FaultImpl *ft) +{ + struct FaultImpl *impl = find_fault(ft); + + if (impl == 0) + return -ENOENT; + memcpy(impl, ft, sizeof(struct FaultImpl)); + return 0; +} + +static struct task_struct *find_task(struct FaultImpl *ft) +{ + struct task_struct *tsk = NULL; + + if (ft->pid) + tsk = find_process(ft->pid); + else if (ft->tid) + tsk = find_thread(ft->tid); + return tsk; +} +static int check_fault(struct FaultImpl *ft) +{ + if (ft->fault == 0 || (ft->pid == 0 && ft->tid == 0) + || (ft->pid != 0 && ft->tid != 0) + || (ft->fault == PROCESS_EXIT && ft->tid != 0)) + return -EINVAL; + return 0; +} +static int resume_fault(struct FaultImpl *ft) +{ + struct task_struct *tsk; + + /*1. check the fault valid */ + ras_retn_iferr(check_fault(ft)); + ft = find_fault(ft); + if (ft == NULL) + return -EINVAL; + /*2.find the the tast_struct */ + tsk = find_task(ft); + if (tsk != NULL) + resume(tsk, ft); /*3.do resume */ + else + pr_err("process:%d,thread:%d not found.\n", ft->pid, ft->tid); + + /*4.resume the information anyway */ + memset(ft, 0, sizeof(struct FaultImpl)); + return 0; +} +static void resume_all(void) +{ + int i = 0; + + write_lock(&fault_list.rwk); + for (i = 0; i < FAULTS_MAX; i++) + resume_fault(&fault_list.impl[i]); + write_unlock(&fault_list.rwk); + +} +static int inject_fault(struct FaultImpl *ft) +{ + struct task_struct *tsk; + + /*1. check the fault valid */ + ras_retn_iferr(check_fault(ft)); + /*2.find the tast_struct */ + tsk = find_task(ft); + if (tsk == NULL) { + pr_err("can't find the task.\n"); + return -EINVAL; + } + + /*3.fill the information */ + ras_retn_iferr(fill_fault(ft)); + /*4.do injection */ + fail(tsk, ft); + return 0; +} + +static int args_set(struct FaultImpl *ft, char *prm) +{ + if (prm == NULL) + return 0; + rasbase_set(ft, pid, prm); + rasbase_set(ft, tid, prm); + rasbase_set_func(ft, fault, prm, string2fault); + return -EINVAL; +} + +static int args_check(struct FaultImpl *ft, int argc, char *argv[]) +{ + int i = 0; + + for (i = 0; i < argc; i++) + ras_retn_iferr(args_set(ft, argv[i])); + return 0; +} + +static int cmd_main(void *data, int argc, char *argv[]) +{ + int ret = -EINVAL; + struct FaultImpl ft; + + ras_retn_if(argc < 2, -EINVAL); + if (strcmp(argv[0], "clean") == 0) { + resume_all(); + return 0; + } + memset(&ft, 0, sizeof(struct FaultImpl)); + ras_retn_iferr(args_check(&ft, argc, argv)); + write_lock(&fault_list.rwk); + ret = inject_fault(&ft); + write_unlock(&fault_list.rwk); + return ret; +} + +static int proc_ops_show(rProcess) (struct seq_file *m, void *v) +{ + int i = 0; + + for (i = 0; i < FAULTS_MAX; i++) { + struct task_struct *tsk; + struct FaultImpl *ft = &fault_list.impl[i]; + + if (check_fault(ft)) + continue; + tsk = find_task(ft); + seq_printf(m, "%d\t", i); + seq_printf(m, "fault=%s\t", fault2string(ft->fault)); + if (ft->pid) + seq_printf(m, "pid=%d\t", ft->pid); + else if (ft->tid) + seq_printf(m, "tid=%d\t", ft->tid); + if (tsk) { + seq_printf(m, "[%s]", tsk->comm); + seq_printf(m, " [%d]", tsk->tgid); + } else { + seq_puts(m, " [already exit]"); + } + seq_puts(m, "\n"); + } + return 0; +} + +static int proc_ops_open(rProcess) (struct inode *inode, struct file *file) +{ + return single_open(file, proc_ops_show(rProcess), PDE_DATA(inode)); +} + +static ssize_t proc_ops_write(rProcess) (struct file *filp, + const char __user *bff, size_t count, + loff_t *data) { + char buf_cmd[256] = { 0 }; + + if (unlikely(count >= sizeof(buf_cmd))) + return -ENOMEM; + ras_retn_iferr(copy_from_user(buf_cmd, bff, count)); + ras_retn_iferr(ras_args(buf_cmd, count, cmd_main, NULL)); + return count; +} + +proc_ops_define(rProcess); +static int tool_init(void) +{ + // ras_debugset(1); + // ras_retn_iferr(ras_check()); + memset(&fault_list, 0, sizeof(fault_list)); + rwlock_init(&fault_list.rwk); + ras_retn_iferr(proc_init + (TOOL_NAME, &proc_ops_name(rProcess), &fault_list)); + return 0; +} +static void tool_exit(void) +{ + proc_exit(TOOL_NAME); + resume_all(); +} + +module_init(tool_init); +module_exit(tool_exit); +MODULE_AUTHOR("OHOS"); +MODULE_DESCRIPTION("Fault injection for both process and thread ."); +MODULE_LICENSE("GPL"); -- Gitee