diff options
Diffstat (limited to 'lib/libutee/arch/arm')
-rw-r--r-- | lib/libutee/arch/arm/gprof/gmon.h | 201 | ||||
-rw-r--r-- | lib/libutee/arch/arm/gprof/gmon_out.h | 118 | ||||
-rw-r--r-- | lib/libutee/arch/arm/gprof/gprof.c | 407 | ||||
-rw-r--r-- | lib/libutee/arch/arm/gprof/gprof_a32.S | 76 | ||||
-rw-r--r-- | lib/libutee/arch/arm/gprof/gprof_a64.S | 77 | ||||
-rw-r--r-- | lib/libutee/arch/arm/gprof/gprof_pta.c | 113 | ||||
-rw-r--r-- | lib/libutee/arch/arm/gprof/gprof_pta.h | 41 | ||||
-rw-r--r-- | lib/libutee/arch/arm/gprof/sub.mk | 7 | ||||
-rw-r--r-- | lib/libutee/arch/arm/sub.mk | 8 | ||||
-rw-r--r-- | lib/libutee/arch/arm/user_ta_entry.c | 236 | ||||
-rw-r--r-- | lib/libutee/arch/arm/utee_misc.c | 72 | ||||
-rw-r--r-- | lib/libutee/arch/arm/utee_syscalls_a32.S | 58 | ||||
-rw-r--r-- | lib/libutee/arch/arm/utee_syscalls_a64.S | 46 | ||||
-rw-r--r-- | lib/libutee/arch/arm/utee_syscalls_asm.S | 189 |
14 files changed, 1649 insertions, 0 deletions
diff --git a/lib/libutee/arch/arm/gprof/gmon.h b/lib/libutee/arch/arm/gprof/gmon.h new file mode 100644 index 0000000..f4ab98d --- /dev/null +++ b/lib/libutee/arch/arm/gprof/gmon.h @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2016, Linaro Limited + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file is adapted from glibc' gmon/sys/gmon.h. + *- + * Copyright (c) 1982, 1986, 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * See gmon_out.h for gmon.out format. + */ + +#ifndef GMON_H +#define GMON_H + +#include <stdint.h> + +/* Exported by the TA linker script */ +extern uint8_t __text_start[]; +extern uint8_t __text_end[]; + +void __mcount_internal(unsigned long frompc, unsigned long selfpc); + + +/* + * Histogram counters are unsigned shorts (according to the kernel). + */ +#define HISTCOUNTER unsigned short + +/* + * Fraction of text space to allocate for histogram counters here, 1/2 + */ +#define HISTFRACTION 2 + +/* + * Fraction of text space to allocate for from hash buckets. + * The value of HASHFRACTION is based on the minimum number of bytes + * of separation between two subroutine call points in the object code. + * Given MIN_SUBR_SEPARATION bytes of separation the value of + * HASHFRACTION is calculated as: + * + * HASHFRACTION = MIN_SUBR_SEPARATION / (2 * sizeof(short) - 1); + * + * For example, on the VAX, the shortest two call sequence is: + * + * calls $0,(r0) + * calls $0,(r0) + * + * which is separated by only three bytes, thus HASHFRACTION is + * calculated as: + * + * HASHFRACTION = 3 / (2 * 2 - 1) = 1 + * + * Note that the division above rounds down, thus if MIN_SUBR_FRACTION + * is less than three, this algorithm will not work! + * + * In practice, however, call instructions are rarely at a minimal + * distance. Hence, we will define HASHFRACTION to be 2 across all + * architectures. This saves a reasonable amount of space for + * profiling data structures without (in practice) sacrificing + * any granularity. + */ +#define HASHFRACTION 2 + +/* + * Percent of text space to allocate for tostructs. + * This is a heuristic; we will fail with a warning when profiling programs + * with a very large number of very small functions, but that's + * normally OK. + * 2 is probably still a good value for normal programs. + * Profiling a test case with 64000 small functions will work if + * you raise this value to 3 and link statically (which bloats the + * text size, thus raising the number of arcs expected by the heuristic). + */ +#define ARCDENSITY 3 + +/* + * Always allocate at least this many tostructs. This + * hides the inadequacy of the ARCDENSITY heuristic, at least + * for small programs. + */ +#define MINARCS 50 + +/* + * The type used to represent indices into gmonparam.tos[]. + */ +#define ARCINDEX unsigned long + +/* + * Maximum number of arcs we want to allow. + * Used to be max representable value of ARCINDEX minus 2, but now + * that ARCINDEX is a long, that's too large; we don't really want + * to allow a 48 gigabyte table. + * The old value of 1<<16 wasn't high enough in practice for large C++ + * programs; will 1<<20 be adequate for long? FIXME + */ +#define MAXARCS (1 << 20) + +struct tostruct { + unsigned long selfpc; + long count; + ARCINDEX link; +}; + +/* + * A raw arc, with pointers to the calling site and the called site and a + * count. + */ +struct rawarc { + unsigned long raw_frompc; + unsigned long raw_selfpc; + long raw_count; +}; + +/* + * General rounding functions. + */ +#define ROUNDDOWN(x, y) (((x)/(y))*(y)) +#define ROUNDUP(x, y) ((((x)+(y)-1)/(y))*(y)) + +/* + * The profiling data structures are housed in this structure. + */ +struct gmonparam { + long int state; + unsigned short *kcount; + unsigned long kcountsize; + ARCINDEX *froms; + unsigned long fromssize; + struct tostruct *tos; + unsigned long tossize; + unsigned long tolimit; + unsigned long lowpc; + unsigned long highpc; + unsigned long textsize; + unsigned long hashfraction; + long log_hashfraction; + /* */ + uint32_t prof_rate; /* PC sampling frequency */ +}; + +/* + * Possible states of profiling. + */ +#define GMON_PROF_ON 0 +#define GMON_PROF_BUSY 1 +#define GMON_PROF_ERROR 2 +#define GMON_PROF_OFF 3 +#define GMON_PROF_OFF_EXITING 4 + +#endif /* GMON_H */ diff --git a/lib/libutee/arch/arm/gprof/gmon_out.h b/lib/libutee/arch/arm/gprof/gmon_out.h new file mode 100644 index 0000000..1f169da --- /dev/null +++ b/lib/libutee/arch/arm/gprof/gmon_out.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2016, Linaro Limited + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * gmon.out file format + * + * This file is adapted from glibc's gmon/sys/gmon_out.h + * Although gmon/sys/gmon_out.h is covered by the LGPL v2.1 license or later + * as stated below, please note the following: + * (https://www.gnu.org/licenses/lgpl-3.0.en.html#section3) + * + * "3. Object Code Incorporating Material from Library Header Files. + * The object code form of an Application may incorporate material from a + * header file that is part of the Library. You may convey such object code + * under terms of your choice, provided that, if the incorporated material + * is not limited to numerical parameters, data structure layouts and + * accessors, or small macros, inline functions and templates (ten or fewer + * lines in length), you do both of the following: [...]" + * + * The code below is indeed limited to data structure layouts. + */ + +/* + * Copyright (C) 1996-2016 Free Software Foundation, Inc. + * This file is part of the GNU C Library. + * Contributed by David Mosberger <davidm@cs.arizona.edu>. + * + * The GNU C Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * The GNU C Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the GNU C Library; if not, see + * <http://www.gnu.org/licenses/>. + */ + +/* + * This file specifies the format of gmon.out files. It should have + * as few external dependencies as possible as it is going to be included + * in many different programs. That is, minimize the number of #include's. + * + * A gmon.out file consists of a header (defined by gmon_hdr) followed by + * a sequence of records. Each record starts with a one-byte tag + * identifying the type of records, followed by records specific data. + */ + +#ifndef GMON_OUT_H +#define GMON_OUT_H + +#define GMON_MAGIC "gmon" /* magic cookie */ +#define GMON_VERSION 1 /* version number */ + +/* + * Raw header as it appears on file (without padding). This header + * always comes first in gmon.out and is then followed by a series + * records defined below. + * Virtual addresses are stored as uintptr_t, gprof knows which size to expect + * because the executable file is provided. + */ +struct gmon_hdr { + char cookie[4]; + int32_t version; + char spare[3 * 4]; +} __packed; + +/* types of records in this file: */ +enum gmon_record_tag { + GMON_TAG_TIME_HIST = 0, + GMON_TAG_CG_ARC = 1, + GMON_TAG_BB_COUNT = 2 +}; + +struct gmon_hist_hdr { + uintptr_t low_pc; /* base pc address of sample buffer */ + uintptr_t high_pc; /* max pc address of sampled buffer */ + uint32_t hist_size; /* size of sample buffer */ + uint32_t prof_rate; /* profiling clock rate */ + char dimen[15]; /* phys. dim., usually "seconds" */ + char dimen_abbrev; /* usually 's' for "seconds" */ +} __packed; + +struct gmon_cg_arc_record { + uintptr_t from_pc; /* address within caller's body */ + uintptr_t self_pc; /* address within callee's body */ + int32_t count; /* number of arc traversals */ +} __packed; + +#endif /* GMON_OUT_H */ diff --git a/lib/libutee/arch/arm/gprof/gprof.c b/lib/libutee/arch/arm/gprof/gprof.c new file mode 100644 index 0000000..cf43148 --- /dev/null +++ b/lib/libutee/arch/arm/gprof/gprof.c @@ -0,0 +1,407 @@ +/* + * Copyright (c) 2016, Linaro Limited + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Portions of this file are adapted from glibc: + * gmon/gmon.c + * gmon/mcount.c + * + *- + * Copyright (c) 1983, 1992, 1993, 2011 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <assert.h> +#include <compiler.h> +#include <inttypes.h> +#include <malloc.h> +#include <stdint.h> +#include <string.h> +#include <tee_api_private.h> +#include <trace.h> +#include <user_ta_header.h> +#include <utee_types.h> +#include "gmon.h" +#include "gmon_out.h" +#include "gprof_pta.h" + +/* Defined by the linker script */ +extern uint8_t __gprof_buf_end[]; +extern uint8_t __gprof_buf_start[]; + +static bool ta_instrumented(void) +{ + return (__gprof_buf_end != __gprof_buf_start); +} + +static void *gprof_alloc(size_t len) +{ + if (len > (size_t)(__gprof_buf_end - __gprof_buf_start)) + return NULL; + return __gprof_buf_start; +} + +static struct gmonparam _gmonparam = { GMON_PROF_OFF }; + +static uint32_t _gprof_file_id; /* File id returned by tee-supplicant */ + +static int _gprof_s_scale; +#define SCALE_1_TO_1 0x10000L + +/* Adjust PC so that gprof can locate it in the TA ELF file */ +static unsigned long __noprof adjust_pc(unsigned long pc) +{ + return pc - (unsigned long)__text_start + sizeof(struct ta_head); +} + +void __utee_gprof_init(void) +{ + unsigned long lowpc; + unsigned long highpc; + struct gmonparam *p = &_gmonparam; + size_t bufsize; + TEE_Result res; + char *cp; + + if (!ta_instrumented()) + return; + + lowpc = adjust_pc((unsigned long)__text_start); + highpc = adjust_pc((unsigned long)__text_end); + + /* + * Round lowpc and highpc to multiples of the density we're using + * so the rest of the scaling (here and in gprof) stays in ints. + */ + p->lowpc = ROUNDDOWN(lowpc, HISTFRACTION * sizeof(HISTCOUNTER)); + p->highpc = ROUNDUP(highpc, HISTFRACTION * sizeof(HISTCOUNTER)); + p->textsize = p->highpc - p->lowpc; + p->kcountsize = ROUNDUP(p->textsize / HISTFRACTION, sizeof(*p->froms)); + p->hashfraction = HASHFRACTION; + p->log_hashfraction = -1; + /* + * The following test must be kept in sync with the corresponding + * test in __mcount_internal + */ + if ((HASHFRACTION & (HASHFRACTION - 1)) == 0) { + /* + * If HASHFRACTION is a power of two, mcount can use shifting + * instead of integer division. Precompute shift amount. + */ + p->log_hashfraction = __builtin_ffs(p->hashfraction * + sizeof(*p->froms)) - 1; + } + p->fromssize = p->textsize / HASHFRACTION; + p->tolimit = p->textsize * ARCDENSITY / 100; + if (p->tolimit < MINARCS) + p->tolimit = MINARCS; + else if (p->tolimit > MAXARCS) + p->tolimit = MAXARCS; + p->tossize = p->tolimit * sizeof(struct tostruct); + + bufsize = p->kcountsize + p->fromssize + p->tossize; + + IMSG("gprof: initializing"); + DMSG("TA text size: %zu, gprof buffer size: %zu", + __text_end - __text_start, bufsize); + + cp = gprof_alloc(bufsize); + if (!cp) { + EMSG("gprof: could not allocate profiling buffer"); + p->tos = NULL; + p->state = GMON_PROF_ERROR; + return; + } + + p->tos = (struct tostruct *)cp; + cp += p->tossize; + p->kcount = (HISTCOUNTER *)cp; + cp += p->kcountsize; + p->froms = (ARCINDEX *)cp; + + p->tos[0].link = 0; + + if (p->kcountsize < p->textsize) + _gprof_s_scale = ((float)p->kcountsize / p->textsize) * + SCALE_1_TO_1; + else + _gprof_s_scale = SCALE_1_TO_1; + + res = __pta_gprof_pc_sampling_start(p->kcount, p->kcountsize, + p->lowpc + + ((unsigned long)__text_start - + sizeof(struct ta_head)), + _gprof_s_scale); + if (res != TEE_SUCCESS) + EMSG("gprof: could not start PC sampling (0x%08x)", res); + + p->state = GMON_PROF_ON; +} + +static void _gprof_write_buf(void *buf, size_t size) +{ + TEE_Result res; + + res = __pta_gprof_send(buf, size, &_gprof_file_id); + if (res != TEE_SUCCESS) + EMSG("gprof: could not send gprof data (0x%08x)", res); +} + +static void _gprof_write_header(void) +{ + struct gmon_hdr ghdr; + size_t size = sizeof(struct gmon_hdr); + + memcpy(&ghdr.cookie[0], GMON_MAGIC, sizeof(ghdr.cookie)); + ghdr.version = GMON_VERSION; + memset(ghdr.spare, '\0', sizeof(ghdr.spare)); + + _gprof_write_buf(&ghdr, size); +} + +static void _gprof_write_hist(void) +{ + struct out_record { + uint8_t tag; + struct gmon_hist_hdr hist_hdr; + } __packed out = { + .tag = GMON_TAG_TIME_HIST, + .hist_hdr = { + .low_pc = _gmonparam.lowpc, + .high_pc = _gmonparam.highpc, + .hist_size = _gmonparam.kcountsize/sizeof(HISTCOUNTER), + .prof_rate = _gmonparam.prof_rate, + .dimen = "seconds", + .dimen_abbrev = 's', + } + }; + + _gprof_write_buf(&out, sizeof(out)); + _gprof_write_buf(_gmonparam.kcount, _gmonparam.kcountsize); +} + +static void _gprof_write_call_graph(void) +{ +#define NARCS_PER_WRITE 16 + struct out_record { + uint8_t tag; + uint8_t data[sizeof(struct gmon_cg_arc_record)]; + } out[NARCS_PER_WRITE]; + struct gmon_cg_arc_record arc; + ARCINDEX from_index, to_index; + unsigned long from_len; + unsigned long frompc; + int nfilled = 0; + + from_len = _gmonparam.fromssize / sizeof(*_gmonparam.froms); + + for (from_index = 0; from_index < from_len; ++from_index) { + + if (_gmonparam.froms[from_index] == 0) + continue; + + frompc = _gmonparam.lowpc; + frompc += (from_index * _gmonparam.hashfraction + * sizeof(*_gmonparam.froms)); + for (to_index = _gmonparam.froms[from_index]; + to_index != 0; + to_index = _gmonparam.tos[to_index].link) { + + arc.from_pc = frompc; + arc.self_pc = _gmonparam.tos[to_index].selfpc; + arc.count = _gmonparam.tos[to_index].count; + + out[nfilled].tag = GMON_TAG_CG_ARC; + memcpy(out[nfilled].data, &arc, sizeof(arc)); + + if (++nfilled == NARCS_PER_WRITE) { + _gprof_write_buf(out, sizeof(out)); + nfilled = 0; + } + } + } + if (nfilled > 0) + _gprof_write_buf(out, nfilled * sizeof(out[0])); +} + +/* Stop profiling and send profile data in gmon.out format to Normal World */ +void __utee_gprof_fini(void) +{ + TEE_Result res; + + if (_gmonparam.state != GMON_PROF_ON) + return; + + /* Stop call graph tracing */ + _gmonparam.state = GMON_PROF_OFF_EXITING; + + /* Stop TA sampling */ + res = __pta_gprof_pc_sampling_stop(&_gmonparam.prof_rate); + + _gprof_write_header(); + if (res == TEE_SUCCESS) + _gprof_write_hist(); + _gprof_write_call_graph(); + + __pta_gprof_fini(); +} + +/* + * Called from the assembly stub (_mcount or __gnu_mcount_nc). + * + * __mcount_internal updates data structures that represent traversals of the + * program's call graph edges. frompc and selfpc are the return + * address and function address that represents the given call graph edge. + */ +void __noprof __mcount_internal(unsigned long frompc, unsigned long selfpc) +{ + ARCINDEX *frompcindex; + struct tostruct *top, *prevtop; + struct gmonparam *p; + ARCINDEX toindex; + int i; + + p = &_gmonparam; + + /* + * Check that we are profiling and that we aren't recursively invoked. + */ + if (p->state != GMON_PROF_ON) + return; + p->state = GMON_PROF_BUSY; + + frompc = adjust_pc(frompc); + selfpc = adjust_pc(selfpc); + + /* Check that frompcindex is a reasonable pc value. */ + frompc -= p->lowpc; + if (frompc > p->textsize) + goto done; + + /* Note: keep in sync. with the initialization function above */ + if ((HASHFRACTION & (HASHFRACTION - 1)) == 0) { + /* Avoid integer divide if possible */ + i = frompc >> p->log_hashfraction; + } else { + i = frompc / (p->hashfraction * sizeof(*p->froms)); + } + frompcindex = &p->froms[i]; + toindex = *frompcindex; + if (toindex == 0) { + /* First time traversing this arc */ + toindex = ++p->tos[0].link; + if (toindex >= p->tolimit) { + /* Halt further profiling */ + goto overflow; + } + + *frompcindex = toindex; + top = &p->tos[toindex]; + top->selfpc = selfpc; + top->count = 1; + top->link = 0; + goto done; + } + top = &p->tos[toindex]; + if (top->selfpc == selfpc) { + /* Arc at front of chain; usual case */ + top->count++; + goto done; + } + /* + * Have to go looking down chain for it. + * top points to what we are looking at, + * prevtop points to previous top. + * we know it is not at the head of the chain. + */ + for (;;) { + if (top->link == 0) { + /* + * top is end of the chain and none of the chain + * had top->selfpc == selfpc. + * so we allocate a new tostruct + * and link it to the head of the chain. + */ + toindex = ++p->tos[0].link; + if (toindex >= p->tolimit) + goto overflow; + + top = &p->tos[toindex]; + top->selfpc = selfpc; + top->count = 1; + top->link = *frompcindex; + *frompcindex = toindex; + goto done; + } + /* + * Otherwise, check the next arc on the chain. + */ + prevtop = top; + top = &p->tos[top->link]; + if (top->selfpc == selfpc) { + /* + * There it is. Increment its count, move it to the + * head of the chain. + */ + top->count++; + toindex = prevtop->link; + prevtop->link = top->link; + top->link = *frompcindex; + *frompcindex = toindex; + goto done; + } + } +done: + p->state = GMON_PROF_ON; + return; +overflow: + p->state = GMON_PROF_ERROR; +} diff --git a/lib/libutee/arch/arm/gprof/gprof_a32.S b/lib/libutee/arch/arm/gprof/gprof_a32.S new file mode 100644 index 0000000..f92387f --- /dev/null +++ b/lib/libutee/arch/arm/gprof/gprof_a32.S @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2016, Linaro Limited + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <asm.S> + +#ifdef CFG_TA_GPROF_SUPPORT + +/* + * Convert return address to call site address by subtracting the size of the + * mcount call instruction (blx __gnu_mcount_nc). + */ +.macro mcount_adj_pc rd, rn + bic \rd, \rn, #1 /* Clear thumb bit if present */ + sub \rd, \rd, #4 +.endm + +/* + * With the -pg option, GCC (4.4+) inserts a call to __gnu_mcount_nc into + * every function prologue. + * The caller of the instrumented function can be determined from the lr value + * stored on the top of the stack. The callee, i.e. the instrumented function + * itself, is determined from the current value of lr. Then we call: + * void __mcount_internal(void *frompc, void *selfpc); + * + * __gnu_mcount_nc is defined and set to the value of this function by the + * TA linker script, only if__gnu_mcount_nc is referenced + */ +FUNC __utee_mcount, : + stmdb sp!, {r0-r3, lr} + ldr r0, [sp, #20] /* lr of instrumented func */ + mcount_adj_pc r0, r0 + mcount_adj_pc r1, lr /* instrumented func */ + bl __mcount_internal + ldmia sp!, {r0-r3, ip, lr} + bx ip +END_FUNC __utee_mcount + +#else /* !CFG_TA_GPROF_SUPPORT */ + +/* + * The TA linker script always references __utee_mcount so provide a version + * that just pops one register (lr) off the stack, since that's the ABI we must + * follow. + */ + .weak __utee_mcount +FUNC __utee_mcount, : + push {lr} + pop {ip, lr} + bx ip +END_FUNC __utee_mcount + +#endif /* CFG_TA_GPROF_SUPPORT */ diff --git a/lib/libutee/arch/arm/gprof/gprof_a64.S b/lib/libutee/arch/arm/gprof/gprof_a64.S new file mode 100644 index 0000000..fd3b987 --- /dev/null +++ b/lib/libutee/arch/arm/gprof/gprof_a64.S @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2016, Linaro Limited + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <asm.S> + +#ifdef CFG_TA_GPROF_SUPPORT + + +/* + * Convert return address to call site address by subtracting the size of one + * instruction. + */ +.macro adjust_pc rd, rn + sub \rd, \rn, #4 +.endm + +/* + * void __utee_mcount(void *return_address) + * @return_address: return address to instrumented function + * + * With the -pg option, the compiler inserts a call to _mcount into + * every function prologue. + * x0 contains the value of lr (x30) before the call, that is the return + * address to the caller of the instrumented function. The callee, i.e. the + * instrumented function itself, is determined from the current value of x30. + * Then we call: + * void __mcount_internal(void *frompc, void *selfpc); + * + * _mcount is defined and set to the value of this function by the linker + * script if the TA is instrumented, i.e., if _mcount is referenced + */ +FUNC __utee_mcount, : + stp x29, x30, [sp, #-16]! + mov x29, sp + adjust_pc x0, x0 + adjust_pc x1, x30 + bl __mcount_internal + ldp x29, x30, [sp], #16 + ret +END_FUNC __utee_mcount + +#else /* !CFG_TA_GPROF_SUPPORT */ + +/* + * The TA linker script always references __utee_mcount so provide a version + * that does nothing + */ + .weak __utee_mcount +FUNC __utee_mcount, : + ret +END_FUNC __utee_mcount + +#endif /* CFG_TA_GPROF_SUPPORT */ diff --git a/lib/libutee/arch/arm/gprof/gprof_pta.c b/lib/libutee/arch/arm/gprof/gprof_pta.c new file mode 100644 index 0000000..7f54e8f --- /dev/null +++ b/lib/libutee/arch/arm/gprof/gprof_pta.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2016, Linaro Limited + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <pta_gprof.h> +#include <string.h> +#include <tee_api.h> +#include "gprof_pta.h" + +static TEE_TASessionHandle sess = TEE_HANDLE_NULL; + +static TEE_Result invoke_gprof_pta(uint32_t cmd_id, uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + static const TEE_UUID core_uuid = PTA_GPROF_UUID; + TEE_Result res; + + if (!sess) { + res = TEE_OpenTASession(&core_uuid, 0, 0, NULL, &sess, NULL); + if (res != TEE_SUCCESS) + return res; + } + res = TEE_InvokeTACommand(sess, 0, cmd_id, param_types, params, NULL); + return res; +} + +TEE_Result __pta_gprof_send(void *buf, size_t len, uint32_t *id) +{ + TEE_Param params[TEE_NUM_PARAMS]; + uint32_t param_types; + TEE_Result res; + + param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INOUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + memset(params, 0, sizeof(params)); + params[0].value.a = *id; + params[1].memref.buffer = buf; + params[1].memref.size = len; + res = invoke_gprof_pta(PTA_GPROF_SEND, param_types, params); + if (res == TEE_SUCCESS) + *id = params[0].value.a; + return res; +} + +TEE_Result __pta_gprof_pc_sampling_start(void *buf, size_t len, size_t offset, + size_t scale) +{ + TEE_Param params[TEE_NUM_PARAMS]; + uint32_t param_types; + + param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + memset(params, 0, sizeof(params)); + params[0].memref.buffer = buf; + params[0].memref.size = len; + params[1].value.a = offset; + params[1].value.b = scale; + return invoke_gprof_pta(PTA_GPROF_START_PC_SAMPLING, param_types, + params); +} + +TEE_Result __pta_gprof_pc_sampling_stop(uint32_t *rate) +{ + TEE_Param params[TEE_NUM_PARAMS]; + uint32_t param_types; + TEE_Result res; + + param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + memset(params, 0, sizeof(params)); + res = invoke_gprof_pta(PTA_GPROF_STOP_PC_SAMPLING, param_types, + params); + if (res != TEE_SUCCESS) + return res; + if (rate) + *rate = params[0].value.a; + return res; +} + +void __pta_gprof_fini(void) +{ + if (sess) + TEE_CloseTASession(sess); +} diff --git a/lib/libutee/arch/arm/gprof/gprof_pta.h b/lib/libutee/arch/arm/gprof/gprof_pta.h new file mode 100644 index 0000000..ff2e7a3 --- /dev/null +++ b/lib/libutee/arch/arm/gprof/gprof_pta.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016, Linaro Limited + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __GPROF_PTA_H +#define __GPROF_PTA_H + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <tee_api_types.h> + +TEE_Result __pta_gprof_send(void *buf, size_t len, uint32_t *id); +TEE_Result __pta_gprof_pc_sampling_start(void *buf, size_t len, size_t offset, + size_t scale); +TEE_Result __pta_gprof_pc_sampling_stop(uint32_t *rate); +void __pta_gprof_fini(void); +#endif /* __GPROF_PTA_H */ diff --git a/lib/libutee/arch/arm/gprof/sub.mk b/lib/libutee/arch/arm/gprof/sub.mk new file mode 100644 index 0000000..e46e37c --- /dev/null +++ b/lib/libutee/arch/arm/gprof/sub.mk @@ -0,0 +1,7 @@ +cppflags-y += -I$(sub-dir)/../../.. + +srcs-$(CFG_TA_GPROF_SUPPORT) += gprof.c +srcs-$(CFG_TA_GPROF_SUPPORT) += gprof_pta.c +cflags-remove-gprof.c-y += -Wcast-align +srcs-$(CFG_ARM32_$(sm)) += gprof_a32.S +srcs-$(CFG_ARM64_$(sm)) += gprof_a64.S diff --git a/lib/libutee/arch/arm/sub.mk b/lib/libutee/arch/arm/sub.mk new file mode 100644 index 0000000..f0c8e8a --- /dev/null +++ b/lib/libutee/arch/arm/sub.mk @@ -0,0 +1,8 @@ +cppflags-y += -I$(sub-dir)/../.. + +srcs-y += user_ta_entry.c +srcs-y += utee_misc.c +srcs-$(CFG_ARM32_$(sm)) += utee_syscalls_a32.S +srcs-$(CFG_ARM64_$(sm)) += utee_syscalls_a64.S + +subdirs-y += gprof diff --git a/lib/libutee/arch/arm/user_ta_entry.c b/lib/libutee/arch/arm/user_ta_entry.c new file mode 100644 index 0000000..08842c7 --- /dev/null +++ b/lib/libutee/arch/arm/user_ta_entry.c @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <compiler.h> +#include <stdbool.h> +#include <string.h> +#include <sys/queue.h> +#include <tee_api.h> +#include <tee_ta_api.h> +#include <tee_internal_api_extensions.h> +#include <user_ta_header.h> +#include <utee_syscalls.h> +#include "utee_misc.h" +#include <tee_arith_internal.h> +#include <malloc.h> +#include "tee_api_private.h" + +/* + * Pull in symbol __utee_mcount. + * This symbol is implemented in assembly in its own compilation unit, and is + * never referenced except by the linker script (in a PROVIDE() command). + * Because the compilation units are packed into an archive (libutee.a), the + * linker will discard the compilation units that are not explicitly + * referenced. AFAICT this occurs *before* the linker processes the PROVIDE() + * command, resulting in an "undefined symbol" error. We avoid this by + * adding an explicit reference here. + */ +extern uint8_t __utee_mcount[]; +void *_ref__utee_mcount __unused = &__utee_mcount; + +struct ta_session { + uint32_t session_id; + void *session_ctx; + TAILQ_ENTRY(ta_session) link; +}; + +static TAILQ_HEAD(ta_sessions, ta_session) ta_sessions = + TAILQ_HEAD_INITIALIZER(ta_sessions); + +static uint32_t ta_ref_count; +static bool context_init; + +/* From user_ta_header.c, built within TA */ +extern uint8_t ta_heap[]; +extern const size_t ta_heap_size; + +uint32_t ta_param_types; +TEE_Param ta_params[TEE_NUM_PARAMS]; + +static void ta_header_save_params(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + ta_param_types = param_types; + + if (params) + memcpy(ta_params, params, sizeof(ta_params)); + else + memset(ta_params, 0, sizeof(ta_params)); +} + +static struct ta_session *ta_header_get_session(uint32_t session_id) +{ + struct ta_session *itr; + + TAILQ_FOREACH(itr, &ta_sessions, link) { + if (itr->session_id == session_id) + return itr; + } + return NULL; +} + +static TEE_Result ta_header_add_session(uint32_t session_id) +{ + struct ta_session *itr = ta_header_get_session(session_id); + + if (itr) + return TEE_SUCCESS; + + ta_ref_count++; + + if (ta_ref_count == 1) { + TEE_Result res; + + if (!context_init) { + trace_set_level(tahead_get_trace_level()); + __utee_gprof_init(); + malloc_add_pool(ta_heap, ta_heap_size); + _TEE_MathAPI_Init(); + context_init = true; + } + + res = TA_CreateEntryPoint(); + if (res != TEE_SUCCESS) + return res; + } + + itr = TEE_Malloc(sizeof(struct ta_session), + TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (!itr) + return TEE_ERROR_OUT_OF_MEMORY; + itr->session_id = session_id; + itr->session_ctx = 0; + TAILQ_INSERT_TAIL(&ta_sessions, itr, link); + + return TEE_SUCCESS; +} + +static void ta_header_remove_session(uint32_t session_id) +{ + struct ta_session *itr; + + TAILQ_FOREACH(itr, &ta_sessions, link) { + if (itr->session_id == session_id) { + TAILQ_REMOVE(&ta_sessions, itr, link); + TEE_Free(itr); + + ta_ref_count--; + if (ta_ref_count == 0) { + __utee_gprof_fini(); + TA_DestroyEntryPoint(); + } + + return; + } + } +} + +static TEE_Result entry_open_session(unsigned long session_id, + struct utee_params *up) +{ + TEE_Result res; + struct ta_session *session; + uint32_t param_types; + TEE_Param params[TEE_NUM_PARAMS]; + + res = ta_header_add_session(session_id); + if (res != TEE_SUCCESS) + return res; + + session = ta_header_get_session(session_id); + if (!session) + return TEE_ERROR_BAD_STATE; + + __utee_to_param(params, ¶m_types, up); + ta_header_save_params(param_types, params); + + res = TA_OpenSessionEntryPoint(param_types, params, + &session->session_ctx); + + __utee_from_param(up, param_types, params); + + if (res != TEE_SUCCESS) + ta_header_remove_session(session_id); + return res; +} + +static TEE_Result entry_close_session(unsigned long session_id) +{ + struct ta_session *session = ta_header_get_session(session_id); + + if (!session) + return TEE_ERROR_BAD_STATE; + + TA_CloseSessionEntryPoint(session->session_ctx); + + ta_header_remove_session(session_id); + return TEE_SUCCESS; +} + +static TEE_Result entry_invoke_command(unsigned long session_id, + struct utee_params *up, unsigned long cmd_id) +{ + TEE_Result res; + uint32_t param_types; + TEE_Param params[TEE_NUM_PARAMS]; + struct ta_session *session = ta_header_get_session(session_id); + + if (!session) + return TEE_ERROR_BAD_STATE; + + __utee_to_param(params, ¶m_types, up); + ta_header_save_params(param_types, params); + + res = TA_InvokeCommandEntryPoint(session->session_ctx, cmd_id, + param_types, params); + + __utee_from_param(up, param_types, params); + return res; +} + +void __noreturn __utee_entry(unsigned long func, unsigned long session_id, + struct utee_params *up, unsigned long cmd_id) +{ + TEE_Result res; + + switch (func) { + case UTEE_ENTRY_FUNC_OPEN_SESSION: + res = entry_open_session(session_id, up); + break; + case UTEE_ENTRY_FUNC_CLOSE_SESSION: + res = entry_close_session(session_id); + break; + case UTEE_ENTRY_FUNC_INVOKE_COMMAND: + res = entry_invoke_command(session_id, up, cmd_id); + break; + default: + res = 0xffffffff; + TEE_Panic(0); + break; + } + ta_header_save_params(0, NULL); + utee_return(res); +} diff --git a/lib/libutee/arch/arm/utee_misc.c b/lib/libutee/arch/arm/utee_misc.c new file mode 100644 index 0000000..a68615b --- /dev/null +++ b/lib/libutee/arch/arm/utee_misc.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <stdlib.h> +#include <stdint.h> +#include <stdbool.h> + +#include <utee_misc.h> +#include "utee_syscalls.h" + +/* utee_get_ta_exec_id - get a process/thread id for the current sequence */ +unsigned int utee_get_ta_exec_id(void) +{ + /* no execution ID available */ + return 0; +} + +/* utee_malloc/realloc/free - call malloc lib support */ +void *utee_malloc(size_t len) +{ + return malloc(len); +} + +void *utee_realloc(void *buffer, size_t len) +{ + return realloc(buffer, len); +} + +void *utee_calloc(size_t nb, size_t len) +{ + return calloc(len, nb); +} + +void utee_free(void *buffer) +{ + free(buffer); +} + +/* + * This version of get_rng_array() is used by the libmpa, when used on user side + * This is why this function is not implemented in libutee for targets with + * trusted os not split into kernel / user side. In such case, only the + * get_rng_array() version from the kernel side is used. + */ +extern TEE_Result get_rng_array(void *buf, size_t blen); +TEE_Result get_rng_array(void *buf, size_t blen) +{ + return utee_cryp_random_number_generate(buf, blen); +} diff --git a/lib/libutee/arch/arm/utee_syscalls_a32.S b/lib/libutee/arch/arm/utee_syscalls_a32.S new file mode 100644 index 0000000..6046b3a --- /dev/null +++ b/lib/libutee/arch/arm/utee_syscalls_a32.S @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <tee_syscall_numbers.h> +#include <asm.S> + + .section .text + .balign 4 + .code 32 + + .macro UTEE_SYSCALL name, scn, num_args + FUNC \name , : + + push {r5-r7,lr} + mov r7, #(\scn) + .if \num_args > TEE_SVC_MAX_ARGS + .error "Too many arguments for syscall" + .endif + .if \num_args <= 4 + @ No arguments passed on stack + mov r6, #0 + .else + @ Tell number of arguments passed on the stack + mov r6, #(\num_args - 4) + @ Point just before the push (4 registers) above on the first argument + add r5, sp, #(4 * 4) + .endif + svc #0 + pop {r5-r7,pc} + END_FUNC \name + .endm + +#include "utee_syscalls_asm.S" diff --git a/lib/libutee/arch/arm/utee_syscalls_a64.S b/lib/libutee/arch/arm/utee_syscalls_a64.S new file mode 100644 index 0000000..44bfa4b --- /dev/null +++ b/lib/libutee/arch/arm/utee_syscalls_a64.S @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <tee_syscall_numbers.h> +#include <asm.S> + + .section .text + + .macro UTEE_SYSCALL name, scn, num_args + FUNC \name , : + + .if \num_args > TEE_SVC_MAX_ARGS || \num_args > 8 + .error "Too many arguments for syscall" + .endif + mov x8, #(\scn) + svc #0 + ret + END_FUNC \name + .endm + +#include "utee_syscalls_asm.S" + diff --git a/lib/libutee/arch/arm/utee_syscalls_asm.S b/lib/libutee/arch/arm/utee_syscalls_asm.S new file mode 100644 index 0000000..7148daa --- /dev/null +++ b/lib/libutee/arch/arm/utee_syscalls_asm.S @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2015, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + + UTEE_SYSCALL utee_return, TEE_SCN_RETURN, 1 + + UTEE_SYSCALL utee_log, TEE_SCN_LOG, 2 + + UTEE_SYSCALL utee_panic, TEE_SCN_PANIC, 1 + + UTEE_SYSCALL utee_get_property, TEE_SCN_GET_PROPERTY, 7 + + UTEE_SYSCALL utee_get_property_name_to_index, \ + TEE_SCN_GET_PROPERTY_NAME_TO_INDEX, 4 + + UTEE_SYSCALL utee_open_ta_session, TEE_SCN_OPEN_TA_SESSION, 5 + + UTEE_SYSCALL utee_close_ta_session, TEE_SCN_CLOSE_TA_SESSION, 1 + + UTEE_SYSCALL utee_invoke_ta_command, TEE_SCN_INVOKE_TA_COMMAND, 5 + + UTEE_SYSCALL utee_get_cancellation_flag, \ + TEE_SCN_GET_CANCELLATION_FLAG, 1 + + UTEE_SYSCALL utee_check_access_rights, TEE_SCN_CHECK_ACCESS_RIGHTS, 3 + + UTEE_SYSCALL utee_unmask_cancellation, TEE_SCN_UNMASK_CANCELLATION, 1 + + UTEE_SYSCALL utee_mask_cancellation, TEE_SCN_MASK_CANCELLATION, 1 + + UTEE_SYSCALL utee_wait, TEE_SCN_WAIT, 1 + + UTEE_SYSCALL utee_get_time, TEE_SCN_GET_TIME, 2 + + UTEE_SYSCALL utee_set_ta_time, TEE_SCN_SET_TA_TIME, 1 + + UTEE_SYSCALL utee_cryp_state_alloc, TEE_SCN_CRYP_STATE_ALLOC, 5 + + UTEE_SYSCALL utee_cryp_state_copy, TEE_SCN_CRYP_STATE_COPY, 2 + + UTEE_SYSCALL utee_cryp_state_free, TEE_SCN_CRYP_STATE_FREE, 1 + + UTEE_SYSCALL utee_hash_init, TEE_SCN_HASH_INIT, 3 + + UTEE_SYSCALL utee_hash_update, TEE_SCN_HASH_UPDATE, 3 + + UTEE_SYSCALL utee_hash_final, TEE_SCN_HASH_FINAL, 5 + + UTEE_SYSCALL utee_cipher_init, TEE_SCN_CIPHER_INIT, 3 + + UTEE_SYSCALL utee_cipher_update, TEE_SCN_CIPHER_UPDATE, 5 + + UTEE_SYSCALL utee_cipher_final, TEE_SCN_CIPHER_FINAL, 5 + + UTEE_SYSCALL utee_cryp_obj_get_info, TEE_SCN_CRYP_OBJ_GET_INFO, 2 + + UTEE_SYSCALL utee_cryp_obj_restrict_usage, \ + TEE_SCN_CRYP_OBJ_RESTRICT_USAGE, 2 + + UTEE_SYSCALL utee_cryp_obj_get_attr, TEE_SCN_CRYP_OBJ_GET_ATTR, 4 + + UTEE_SYSCALL utee_cryp_obj_alloc, TEE_SCN_CRYP_OBJ_ALLOC, 3 + + UTEE_SYSCALL utee_cryp_obj_close, TEE_SCN_CRYP_OBJ_CLOSE, 1 + + UTEE_SYSCALL utee_cryp_obj_reset, TEE_SCN_CRYP_OBJ_RESET, 1 + + UTEE_SYSCALL utee_cryp_obj_populate, TEE_SCN_CRYP_OBJ_POPULATE, 3 + + UTEE_SYSCALL utee_cryp_obj_copy, TEE_SCN_CRYP_OBJ_COPY, 2 + + UTEE_SYSCALL utee_cryp_derive_key, TEE_SCN_CRYP_DERIVE_KEY, 4 + + UTEE_SYSCALL utee_cryp_random_number_generate, \ + TEE_SCN_CRYP_RANDOM_NUMBER_GENERATE, 2 + + UTEE_SYSCALL utee_authenc_init, TEE_SCN_AUTHENC_INIT, 6 + + UTEE_SYSCALL utee_authenc_update_aad, TEE_SCN_AUTHENC_UPDATE_AAD, 3 + + UTEE_SYSCALL utee_authenc_update_payload, \ + TEE_SCN_AUTHENC_UPDATE_PAYLOAD, 5 + + UTEE_SYSCALL utee_authenc_enc_final, TEE_SCN_AUTHENC_ENC_FINAL, 7 + + UTEE_SYSCALL utee_authenc_dec_final, TEE_SCN_AUTHENC_DEC_FINAL, 7 + + UTEE_SYSCALL utee_asymm_operate, TEE_SCN_ASYMM_OPERATE, 7 + + UTEE_SYSCALL utee_asymm_verify, TEE_SCN_ASYMM_VERIFY, 7 + + UTEE_SYSCALL utee_storage_obj_open, TEE_SCN_STORAGE_OBJ_OPEN, 5 + + UTEE_SYSCALL utee_storage_obj_create, TEE_SCN_STORAGE_OBJ_CREATE, 8 + + UTEE_SYSCALL utee_storage_obj_del, TEE_SCN_STORAGE_OBJ_DEL, 1 + + UTEE_SYSCALL utee_storage_obj_rename, TEE_SCN_STORAGE_OBJ_RENAME, 3 + + UTEE_SYSCALL utee_storage_alloc_enum, TEE_SCN_STORAGE_ENUM_ALLOC, 1 + + UTEE_SYSCALL utee_storage_free_enum, TEE_SCN_STORAGE_ENUM_FREE, 1 + + UTEE_SYSCALL utee_storage_reset_enum, TEE_SCN_STORAGE_ENUM_RESET, 1 + + UTEE_SYSCALL utee_storage_start_enum, TEE_SCN_STORAGE_ENUM_START, 2 + + UTEE_SYSCALL utee_storage_next_enum, TEE_SCN_STORAGE_ENUM_NEXT, 4 + + UTEE_SYSCALL utee_storage_obj_read, TEE_SCN_STORAGE_OBJ_READ, 4 + + UTEE_SYSCALL utee_storage_obj_write, TEE_SCN_STORAGE_OBJ_WRITE, 3 + + UTEE_SYSCALL utee_storage_obj_trunc, TEE_SCN_STORAGE_OBJ_TRUNC, 2 + + UTEE_SYSCALL utee_storage_obj_seek, TEE_SCN_STORAGE_OBJ_SEEK, 3 + + UTEE_SYSCALL utee_cryp_obj_generate_key, \ + TEE_SCN_CRYP_OBJ_GENERATE_KEY, 4 + + UTEE_SYSCALL utee_se_service_open, TEE_SCN_SE_SERVICE_OPEN, 1 + + UTEE_SYSCALL utee_se_service_close, TEE_SCN_SE_SERVICE_CLOSE, 1 + + UTEE_SYSCALL utee_se_service_get_readers, \ + TEE_SCN_SE_SERVICE_GET_READERS, 3 + + UTEE_SYSCALL utee_se_reader_get_prop, \ + TEE_SCN_SE_READER_GET_PROP, 2 + + UTEE_SYSCALL utee_se_reader_get_name, \ + TEE_SCN_SE_READER_GET_NAME, 3 + + UTEE_SYSCALL utee_se_reader_open_session, \ + TEE_SCN_SE_READER_OPEN_SESSION, 2 + + UTEE_SYSCALL utee_se_reader_close_sessions, \ + TEE_SCN_SE_READER_CLOSE_SESSIONS, 1 + + UTEE_SYSCALL utee_se_session_is_closed, \ + TEE_SCN_SE_SESSION_IS_CLOSED, 1 + + UTEE_SYSCALL utee_se_session_get_atr, \ + TEE_SCN_SE_SESSION_GET_ATR, 3 + + UTEE_SYSCALL utee_se_session_open_channel, \ + TEE_SCN_SE_SESSION_OPEN_CHANNEL, 5 + + UTEE_SYSCALL utee_se_session_close, \ + TEE_SCN_SE_SESSION_CLOSE, 1 + + UTEE_SYSCALL utee_se_channel_select_next, \ + TEE_SCN_SE_CHANNEL_SELECT_NEXT, 1 + + UTEE_SYSCALL utee_se_channel_get_select_resp, \ + TEE_SCN_SE_CHANNEL_GET_SELECT_RESP, 3 + + UTEE_SYSCALL utee_se_channel_transmit, \ + TEE_SCN_SE_CHANNEL_TRANSMIT, 5 + + UTEE_SYSCALL utee_se_channel_close, \ + TEE_SCN_SE_CHANNEL_CLOSE, 1 + + UTEE_SYSCALL utee_cache_operation, TEE_SCN_CACHE_OPERATION, 3 |