coverage-reporting:  Add OP-TEE SPMC coverage support
diff --git a/coverage-tool/coverage-plugin/coverage_trace.cc b/coverage-tool/coverage-plugin/coverage_trace.cc
index 4dc72ee..d2b13fd 100644
--- a/coverage-tool/coverage-plugin/coverage_trace.cc
+++ b/coverage-tool/coverage-plugin/coverage_trace.cc
@@ -1,6 +1,6 @@
 /*!
 ##############################################################################
-# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 ##############################################################################
@@ -12,6 +12,7 @@
 #include "MTI/PluginFactory.h"
 #include "MTI/PluginInstance.h"
 #include "MTI/ModelTraceInterface.h"
+#include "MTI/ParameterInterface.h"
 
 #include "plugin_utils.h"
 #include "trace_sources.h"
@@ -26,6 +27,7 @@
 #include <typeinfo>
 #include <typeindex>
 #include <utility>
+#include "SimpleCADI.h"
 
 #ifdef SG_MODEL_BUILD
     #include "builddata.h"
@@ -34,19 +36,58 @@
     #define PLUGIN_VERSION "unreleased"
 #endif
 
+enum plugin_param_t
+{
+TRACE_FILE_PREFIX,
+TRACE_MODE,
+TOTAL_PARAMETERS
+};
 using namespace eslapi;
 using namespace MTI;
 using namespace std;
 
 // Implements the plugin interface for trace coverage
-class CoverageTrace :public PluginInstance
+
+// Class used to return a static object CAInterface. CAInterface provides a
+// basis for a software model built around ’components’ and ’interfaces’.
+// A component provides concrete implementations of one or more interfaces.
+// Interfaces are identified by a string name (of type if_name_t), and an
+// integer revision (type if_rev_t). A higher revision number indicates a newer
+// revision of the same interface.
+class ThePluginFactory :public PluginFactory
+{
+public:
+    virtual CAInterface *ObtainInterface(if_name_t    ifName,
+                                          if_rev_t     minRev,
+                                          if_rev_t *   actualRev);
+
+    virtual uint32_t GetNumberOfParameters();
+
+    virtual eslapi::CADIReturn_t
+    GetParameterInfos(eslapi::CADIParameterInfo_t *parameter_info_list);
+
+    virtual CAInterface *Instantiate(const char *instance_name,
+                                     uint32_t number_of_parameters,
+                                     eslapi::CADIParameterValue_t *parameter_values);
+
+    virtual void Release();
+
+    virtual const char *GetType() const { return "CoverageTrace"; }
+    virtual const char *GetVersion() const { return PLUGIN_VERSION; }
+};
+
+static ThePluginFactory *GetThePluginFactory();
+class CoverageTrace :
+        public ParameterInterface,
+        public PluginInstance
 {
 public:
     virtual CAInterface * ObtainInterface(if_name_t    ifName,
                                           if_rev_t     minRev,
                                           if_rev_t *   actualRev);
 
-    CoverageTrace(const char *instance_name, const char *trace_file_prefix);
+    CoverageTrace(const char *instance_name, const char *trace_file_prefix,
+                  int _mode);
     ~CoverageTrace();
 
     /** This is to associate a plugin with a simulation instance. Exactly one
@@ -58,9 +99,24 @@
     // This is called before the plugin .dll/.so is unloaded and should allow
     // the plugin to do it's cleanup.
     virtual void Release();
+    void Save(void);
 
     virtual const char *GetName() const;
+    virtual eslapi::CADIReturn_t GetParameterInfos(uint32_t start_index,
+                                               uint32_t desired_num_of_params,
+                                               uint32_t* actual_num_of_params,
+                                               eslapi::CADIParameterInfo_t* params);
 
+    virtual eslapi::CADIReturn_t GetParameterInfo(const char* parameterName,
+                                              eslapi::CADIParameterInfo_t* param);
+
+    virtual eslapi::CADIReturn_t GetParameterValues(uint32_t parameter_count,
+                                                uint32_t* actual_num_of_params_read,
+                                                eslapi::CADIParameterValue_t* param_values_out);
+    virtual eslapi::CADIReturn_t SetParameterValues(uint32_t parameter_count,
+                                                eslapi::CADIParameterValue_t* parameters,
+                                                eslapi::CADIFactoryErrorMessage_t* error);
+    ModeChangeTraceContext *mode_change;
 private:
     std::string instance_name;
 
@@ -68,6 +124,7 @@
 
     vector<TraceComponentContext*> trace_components;
     std::string trace_file_prefix;
+    int trace_mode;
 };
 
 CAInterface *CoverageTrace::ObtainInterface(if_name_t ifName,
@@ -76,14 +133,14 @@
 {
   printf("CoverageTrace::ObtainInterface\n");
     // If someone is asking for the matching interface
-    if((strcmp(ifName,IFNAME()) == 0) &&
+    if((strcmp(ifName,PluginInstance::IFNAME()) == 0) &&
     // and the revision of this interface implementation is
-       (minRev <= IFREVISION()))
+       (minRev <= PluginInstance::IFREVISION()))
         // at least what is being asked for
     {
         if (actualRev) // Make sure this is not a NULL pointer
-            *actualRev = IFREVISION();
-        return this;
+            *actualRev = PluginInstance::IFREVISION();
+        return dynamic_cast<PluginInstance *>(this);
     }
 
     if((strcmp(ifName, CAInterface::IFNAME()) == 0) &&
@@ -91,16 +148,25 @@
     {
         if (actualRev != NULL)
             *actualRev = CAInterface::IFREVISION();
-        return this;// Dynamic_cast<TracePluginInterface *>(this);
+        return dynamic_cast<CAInterface *>(dynamic_cast<PluginInstance *>(this));
     }
+    if((strcmp(ifName, ParameterInterface::IFNAME()) == 0) &&
+       minRev <= ParameterInterface::IFREVISION())
+    {
+        if (actualRev != NULL)
+            *actualRev = ParameterInterface::IFREVISION();
+        return dynamic_cast<ParameterInterface *>(this);
+    }
+     printf("CoverageTrace::ObtainInterface Failed!\n");
     return NULL;
 }
 
 
 CoverageTrace::CoverageTrace(const char *instance_name_,
-                             const char *trace_file_prefix_) :
+                             const char *trace_file_prefix_, int _mode) :
     instance_name(instance_name_),
-    trace_file_prefix(trace_file_prefix_)
+    trace_file_prefix(trace_file_prefix_),
+    trace_mode(_mode)
 {
   printf("CoverageTrace::CoverageTrace\n");
 }
@@ -142,6 +208,9 @@
         CAInterface *caif = sys_if->GetComponentTrace(tci);
         ComponentTraceInterface *cti =
                                  caif->ObtainPointer<ComponentTraceInterface>();
+        InstructionTraceContext *inst_cont = NULL;
+        MTI::EventClass * event = NULL;
+
         if (cti == 0) {
             Error("Could not get TraceInterface for component.");
             continue;
@@ -154,16 +223,39 @@
             // To register a new trace source the arguments are the
             // name of the trace source followed by a vector of
             // pairs of (field name,field type).
-            InstructionTraceContext *inst_cont = new InstructionTraceContext(
-                                            "INST",
-                                            { {"PC", u32},
-                                            {"SIZE", u32}}
-                                        );
+            inst_cont = new InstructionTraceContext(
+                    "INST",
+                    { {"PC", u32},
+                    {"SIZE", u32}}
+                    );
             inst_cont->nb_insts = 0;
-            inst_cont->CreateEvent(&cti, inst_cont->Callback);
+            event = inst_cont->CreateEvent(&cti, inst_cont->Callback);
+            event->UnregisterCallback(inst_cont->Callback, inst_cont);
             trace_component->AddTraceSource(inst_cont);
             trace_components.push_back(trace_component);
         }
+        if (cti->GetTraceSource("MODE_CHANGE") != 0) {
+            MTI::EventClass * mode_event = NULL;
+            if(!event) {
+                Error("Could not set mode_change event");
+                continue;
+            }
+            // To register a new trace source the arguments are the
+            // name of the trace source followed by a vector of
+            // pairs of (field name,field type).
+           this->mode_change = new ModeChangeTraceContext(
+                    "MODE_CHANGE",
+                    { {"MODE", u8},
+                    {"NON_SECURE", u8}
+                    }
+                    );
+           mode_event = this->mode_change->CreateEvent(&cti, this->mode_change->Callback);
+           this->mode_change->event = event;
+           this->mode_change->itc = inst_cont;
+           this->mode_change->mode_mask = trace_mode;
+           mode_event->RegisterCallback(this->mode_change->Callback, mode_change);
+        }
+
     }
 
     return CADI_STATUS_OK;
@@ -174,8 +266,14 @@
 void
 CoverageTrace::Release()
 {
-  printf("CoverageTrace::Release\n");
+    printf("CoverageTrace::Release\n");
     // We can dump our data now
+    this->Save();
+}
+
+void
+CoverageTrace::Save(void)
+{
     int error = 0;
     char* fname;
     int ret;
@@ -191,7 +289,7 @@
         int status = asprintf(&fname, "%s-%s.log",
                               this->trace_file_prefix.c_str(),
                               tcont->trace_path.c_str());
-        if ( status != 0)
+        if ( status == -1)
         {
             printf("Error in asprintf: %d\n", status);
             printf("Error description is : %s\n", strerror(errno));
@@ -223,8 +321,9 @@
 
         free(fname);
     }
-if (error != 0)
-    delete this;
+    printf("Everything saved\n");
+    if (error != 0)
+        delete this;
 }
 
 const char *
@@ -234,33 +333,103 @@
     return instance_name.c_str();
 }
 
-// Class used to return a static object CAInterface. CAInterface provides a
-// basis for a software model built around ’components’ and ’interfaces’.
-// A component provides concrete implementations of one or more interfaces.
-// Interfaces are identified by a string name (of type if_name_t), and an
-// integer revision (type if_rev_t). A higher revision number indicates a newer
-// revision of the same interface.
-class ThePluginFactory :public PluginFactory
+CADIReturn_t CoverageTrace::GetParameterInfos(uint32_t start_index,
+                uint32_t desired_num_of_params,
+                uint32_t* actual_num_of_params,
+                CADIParameterInfo_t* params)
 {
-public:
-    virtual CAInterface *ObtainInterface(if_name_t    ifName,
-                                          if_rev_t     minRev,
-                                          if_rev_t *   actualRev);
 
-    virtual uint32_t GetNumberOfParameters();
+        *actual_num_of_params = GetThePluginFactory()->GetNumberOfParameters();
+        return GetThePluginFactory()->GetParameterInfos(params);
 
-    virtual eslapi::CADIReturn_t
-        GetParameterInfos(eslapi::CADIParameterInfo_t *parameter_info_list);
+}
 
-    virtual CAInterface *Instantiate(const char *instance_name,
-                                     uint32_t number_of_parameters,
-                                     eslapi::CADIParameterValue_t *parameter_values);
+CADIReturn_t CoverageTrace::GetParameterInfo(const char* parameterName,
+                CADIParameterInfo_t* param)
+{
+        uint32_t num_of_params = GetThePluginFactory()->GetNumberOfParameters();
+        CADIParameterInfo_t* plugin_parameters = NULL;
 
-    virtual void Release();
+        GetThePluginFactory()->GetParameterInfos(plugin_parameters);
 
-    virtual const char *GetType() const { return "CoverageTrace"; }
-    virtual const char *GetVersion() const { return PLUGIN_VERSION; }
-};
+        if (param == nullptr)
+        {
+                return CADI_STATUS_IllegalArgument;
+        }
+
+        printf("Reading parameter info %s \n", parameterName);
+        for (uint32_t i = 0; i <  num_of_params; ++i)
+        {
+                if (strcmp(plugin_parameters[i].name, parameterName) == 0)
+                {
+                        *param = plugin_parameters[i];
+                        return CADI_STATUS_OK;
+                }
+        }
+        *param = plugin_parameters[0];
+        return CADI_STATUS_OK;
+
+}
+
+CADIReturn_t CoverageTrace::GetParameterValues(uint32_t parameter_count,
+                uint32_t* actual_num_of_params_read,
+                CADIParameterValue_t *param_values_out)
+{
+        if (param_values_out == nullptr || actual_num_of_params_read == nullptr)
+        {
+                return CADI_STATUS_IllegalArgument;
+        }
+
+        *actual_num_of_params_read = 0;
+        for (uint32_t i = 0; i < parameter_count; ++i)
+        {
+                CADIParameterValue_t &param_value = param_values_out[i];
+
+                switch (param_value.parameterID)
+                {
+                        case TRACE_FILE_PREFIX:
+                                strncpy(param_value.stringValue,
+                                        this->trace_file_prefix.c_str(),
+                                        sizeof(param_value.stringValue));
+                                break;
+
+                        case TRACE_MODE:
+                                param_value.intValue = this->mode_change->mode_mask;
+                                break;
+                        default: // unknown ID
+
+                                *actual_num_of_params_read = i;
+                                return CADI_STATUS_IllegalArgument;
+                }
+        }
+
+        *actual_num_of_params_read = parameter_count;
+        return CADI_STATUS_OK;
+}
+
+CADIReturn_t CoverageTrace::SetParameterValues(uint32_t parameter_count,
+                                            CADIParameterValue_t* parameters,
+                                            CADIFactoryErrorMessage_t* error)
+{
+        for (uint32_t i = 0; i < parameter_count; ++i)
+        {
+            CADIParameterValue_t &parameter = parameters[i];
+            switch(parameter.parameterID)
+            {
+                case TRACE_FILE_PREFIX:
+                        this->trace_file_prefix =  parameter.stringValue;
+                        this->Save();
+                        break;
+                case TRACE_MODE:
+                        this->mode_change->mode_mask =  parameter.intValue;
+                        break;
+            default:
+                ;
+                break;
+            }
+        }
+    return CADI_STATUS_OK;
+}
 
 // Allows a client to obtain a reference to any of the interfaces that the
 // component implements. The client specifies the id and revision of the
@@ -296,7 +465,7 @@
 uint32_t ThePluginFactory::GetNumberOfParameters()
 {
   printf("ThePluginFactory::GetNumberOfParameters\n");
-  return 1;
+  return TOTAL_PARAMETERS;
 }
 
 eslapi::CADIReturn_t
@@ -304,10 +473,12 @@
 eslapi::CADIParameterInfo_t *parameter_info_list)
 {
     printf("ThePluginFactory::GetParameterInfos\n");
-    *parameter_info_list = CADIParameterInfo_t(
-        0, "trace-file-prefix", CADI_PARAM_STRING,
-        "Prefix of the trace files.", 0, 0, 0, 0, "covtrace"
-    );
+    parameter_info_list[0] = CADIParameterInfo_t(
+        TRACE_FILE_PREFIX, "trace-file-prefix", CADI_PARAM_STRING,
+        "Prefix of the trace files.", true, 0, 0, 0, "covtrace");
+    parameter_info_list[1] = CADIParameterInfo_t(
+        TRACE_MODE, "trace-mode", CADI_PARAM_INT,
+        "Selects which modes to trace.", true, 0, 0xffffffff, 0xffffffff, 0);
     return CADI_STATUS_OK;
 }
 
@@ -318,16 +489,21 @@
 {
     printf("ThePluginFactory::Instantiate\n");
     const char *trace_file_prefix = 0;
+    int mode_value = 0xffffffff;
+
     printf("CoverageTrace: number of params: %d\n", param_nb);
     for (uint32_t i = 0; i < param_nb; ++i) {
-        if (values[i].parameterID == 0) {
+        if (values[i].parameterID == TRACE_FILE_PREFIX) {
             trace_file_prefix = values[i].stringValue;
+        } else if (values[i].parameterID == TRACE_MODE) {
+            mode_value = values[i].intValue;
         } else {
             printf("\tCoverageTrace: got unexpected param %d\n",
                    values[i].parameterID);
         }
     }
-    return new CoverageTrace(instance_name, trace_file_prefix);
+    return (PluginInstance*)new CoverageTrace(instance_name, trace_file_prefix,
+            mode_value);
 }
 
 void ThePluginFactory::Release()
@@ -345,5 +521,9 @@
     printf("********->GetCAInterface\n");
     return &factory_instance;
 }
+static ThePluginFactory *GetThePluginFactory()
+{
+    return &factory_instance;
+}
 
 // End of file CoverageTrace.cpp
diff --git a/coverage-tool/coverage-plugin/coverage_trace_parameters_change.py b/coverage-tool/coverage-plugin/coverage_trace_parameters_change.py
new file mode 100644
index 0000000..73841c5
--- /dev/null
+++ b/coverage-tool/coverage-plugin/coverage_trace_parameters_change.py
@@ -0,0 +1,78 @@
+# !/usr/bin/env python
+##############################################################################
+# Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+##############################################################################
+import iris.debug as debug
+import iris.iris as iris
+import argparse
+import textwrap
+
+def arg_parser():
+    parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
+        description  = textwrap.dedent('''\
+                Tool to change the plugin parameters of the FVP coverage-plugin.
+
+                To be able to connect to the model, the model needs to have the iris-servier active.
+                The -p of the model can be used to show the port to connect to.
+                When starting a model with the iris-server, the model will wait until a debugger
+                is connect and ran. We can start the model automatically by using the -R option.
+                Example:
+                MODEL --iris-server -R -p
+            '''))
+    parser.add_argument(
+            "-p",
+            "--port",
+            type=int,
+            default=7100,
+            help="set the port of the running model"
+            )
+    parser.add_argument(
+            "-m",
+            "--mode",
+            type=lambda x: int(x,0),
+            default=-1,
+            help="set the mode to trace as a hex number."
+            )
+    parser.add_argument(
+            "-f",
+            "--file",
+            default="",
+            help="set the file-prefix of the trace files"
+            )
+    parser.add_argument(
+            "-s",
+            "--save",
+            action='store_true',
+            help="Save the current trace"
+            )
+    return parser.parse_args()
+
+def main():
+    parsed_args = arg_parser()
+    model = debug.NetworkModel("localhost", parsed_args.port)
+
+    components = model.get_targets()
+    for component in components:
+        if "coverage_trace" in component.instName:
+            trace_component = component
+
+    if trace_component:
+        if parsed_args.mode != -1:
+            trace_component.parameters['trace-mode'] = parsed_args.mode
+            print("Changed trace mode to " + hex(parsed_args.mode))
+        elif parsed_args.file != "":
+            trace_component.parameters['trace-file-prefix'] = parsed_args.file
+            print("Changed trace prefix to" +  parsed_args.file)
+        elif parsed_args.save:
+            trace_component.parameters['trace-file-prefix'] = trace_component.parameters['trace-file-prefix']
+            print("Saved trace files to " + trace_component.parameters['trace-file-prefix'])
+        else:
+            print("Nothing to do")
+    else:
+        print("Could not find plugin component")
+
+
+if __name__ == "__main__":
+    main()
diff --git a/coverage-tool/coverage-plugin/trace_sources.h b/coverage-tool/coverage-plugin/trace_sources.h
index 57f6462..e200bc5 100644
--- a/coverage-tool/coverage-plugin/trace_sources.h
+++ b/coverage-tool/coverage-plugin/trace_sources.h
@@ -26,7 +26,7 @@
 typedef std::map<uint32_t, InstStat> InstStatMap;
 
 //Defining types for fields
-enum enum_types {u32, boolT};
+enum enum_types {u32, boolT, u8};
 typedef enum_types ValueTypes;
 
 /*
@@ -108,6 +108,9 @@
             case boolT: it->second.value = new bool(
                 record->GetBool(event_class, it->second.index));
                 break;
+            case u8: it->second.value = new uint8_t(
+                record->Get<uint8_t>(event_class, it->second.index));
+                break;
         }
     }
     return tc;
@@ -137,6 +140,10 @@
                     target->params[it->first].value =
                         new bool(*((bool*)it->second.value));
                     break;
+                case u8:
+                    target->params[it->first].value =
+                        new uint8_t(*((uint8_t*)it->second.value));
+                    break;
             }
         }
 }
@@ -226,4 +233,91 @@
     };
 };
 
+struct mode_change_type {
+    uint8_t mode_value;
+    char name[5];
+};
+const struct mode_change_type types[] = {
+    {0x0 , "EL0t"}, //0
+    {0x4 , "EL1t"}, //1
+    {0x5 , "EL1h"}, //2
+    {0x8 , "EL2t"}, //3
+    {0x9 , "EL2h"}, //4
+    {0xc , "EL3t"}, //5
+    {0xd , "EL3h"}, //6
+    {0x10 , "usr"}, //7
+    {0x11 , "fiq"}, //8
+    {0x12 , "irq"}, //9
+    {0x13 , "svc"}, //10
+    {0x16 , "mon"}, //11
+    {0x17 , "abt"}, //12
+    {0x1a , "hyp"}, //13
+    {0x1b , "und"}, //14
+    {0x1f , "sys"},  //15
+    /* Secure modes */
+    {0x0 , "EL0t"}, //16
+    {0x4 , "EL1t"}, //17
+    {0x5 , "EL1h"}, //18
+    {0x8 , "EL2t"}, //19
+    {0x9 , "EL2h"}, //20
+    {0xc , "EL3t"}, //21
+    {0xd , "EL3h"}, //22
+    {0x10 , "usr"}, //23
+    {0x11 , "fiq"}, //24
+    {0x12 , "irq"}, //25
+    {0x13 , "svc"}, //26
+    {0x16 , "mon"}, //27
+    {0x17 , "abt"}, //28
+    {0x1a , "hyp"}, //29
+    {0x1b , "und"}, //30
+    {0x1f , "sys"}  //31
+};
+
+class ModeChangeTraceContext: public TraceSourceContext {
+    public:
+        using TraceSourceContext::TraceSourceContext;
+        MTI::EventClass *event;
+        uint32_t mode_mask;
+        InstructionTraceContext* itc;
+
+
+        static void Callback(void* user_data,
+                             const MTI::EventClass *event_class,
+                             const MTI::EventRecord *record)
+        {
+            ModeChangeTraceContext* mtc = static_cast<ModeChangeTraceContext*>
+                (user_data);
+            static bool trace = false;
+            bool new_trace = false;
+            uint8_t mode = record->GetAs<char>(event_class,
+                    mtc->fields["MODE"].index);
+            uint8_t nsecure = record->Get<char>(event_class,
+                    mtc->fields["NON_SECURE"].index);
+            int start_mask  = 0;
+
+            if(nsecure) {
+                start_mask = 0;
+            } else {
+                start_mask = 16;
+            }
+
+            for (int i = start_mask; i < start_mask + 16; i++) {
+                if (types[i].mode_value == mode) {
+                    new_trace = new_trace || (mtc->mode_mask & (1 << i));
+                    break;
+                }
+            }
+
+            if (new_trace && !trace) {
+                mtc->event->RegisterCallback(InstructionTraceContext::Callback,
+                                             mtc->itc);
+            } else if (!new_trace && trace){
+                mtc->event->UnregisterCallback(
+                        InstructionTraceContext::Callback,
+                        mtc->itc);
+            }
+            trace = new_trace;
+        };
+
+};
 #endif // _COVERAGE_TOOL_COVERAGE_PLUGIN_TRACE_SOURCES_H_