Rate This Document
Findability
Accuracy
Completeness
Readability

Obtaining the Resource Usage of TAs in the TEE

Some monitor programs need to obtain the CPU and memory usage of TAs. To meet this need, the confidential OS grants TAs access to the /proc directory in the TEE. You can learn about the running status of the OS and TAs (such as the CPU usage of TAs).

File Access Permission

The confidential OS grants TAs the permission to access the following files. The file formats are basically the same as those in the Linux man manual.

  • /proc/stat provides statistics about the OS and each CPU core. You can learn about the running status and performance indicators of each CPU. The format is as follows:
    cpu <user> <nice> <system> <idle> <iowait> <irq> <softirq> <steal> <guest> <guest_nice>
    cpu0 <user> <nice> <system> <idle> <iowait> <irq> <softirq> <steal> <guest> <guest_nice>
    ...
    cpuN <user> <nice> <system> <idle> <iowait> <irq> <softirq> <steal> <guest> <guest_nice>
    intr <total> <num> ...
    ctxt <num>
    btime <num>
    processes <num>
    procs_running <num>
    procs_blocked <num>
    softirq <total> <num> ...

    N indicates the number of CPU cores. This file provides information about the total CPU usage and the usage of each CPU core. For example, calculate the user-mode CPU usage as follows:

    • Only the user, system, idle, and irq statistics are collected in the TEE OS, and statistics about other items are not collected.
    • Each CPU in the TEE is bound to an smcd thread by default. If there is no task running, the thread is in the wait state. When an OpenSession instruction comes from a CA, the thread releases the CPU and the CPU starts to process the session task. Therefore, when the TEE OS is idle, all CPU cores run the smcd thread and the system usage is 100%. When a thread in the TA is bound to a CPU core, the user-mode thread and the kernel-mode smcd thread of the TA evenly share the CPU. That is, the user-mode thread and kernel-mode smcd thread each occupy 50% of the CPU.
    • When a CA is bound to a CPU core, not all TAs run on the core. That is, the user-mode CPU usage of the core is not 100%.
  • /proc/uptime provides the running time and idle time calculated since the OS starts. The format is as follows:
    <uptime> <idle_time>

    The previous time unit is second. The time unit in other proc files is generally the core clock frequency. The ratio of the former unit to the latter unit is sysconf(_SC_CLK_TCK).

  • /proc/loadavg provides information about the average system load (number of active tasks in the system in a recent period). The format is as follows:
    <1min_avg> <5min_avg> <15min_avg>

    By default, each CPU core in the TEE is bound to an smcd thread. Therefore, if no TA is running, the load is the number of CPU cores by default.

  • /proc/self/* provides statistics about the current process, commonly in two files.
    • The /proc/self/statm file provides memory usage information about the current process.
      <size> <resident> <shared> <text> <lib> <data> <dt>

      The unit is page. You can obtain the page size in the TEE using the sysconf(_SC_PAGESIZE) API. To obtain the total memory size, call the int sysinfo(struct sysinfo *info) API.

    • The /proc/self/stat file provides running statistics about the current process.
      <pid> (<comm>) <state> <ppid> <pgrp> <session> <tty_nr> <tpgid> <flags> <minflt> <cminflt> <majflt> <cmajflt> <utime> <stime> <cutime> <cstime> <priority> <nice> <num_threads> <itrealvalue> <starttime> <vsize> <rss> <rsslim> <startcode> <endcode> <startstack> <kstkesp> <kstkeip> <signal> <blocked> <sigignore> <sigcatch> <wchan> <nswap> <cnswap> <exit_signal> <processor> <rt_priority> <policy> <delayacct_blkio_ticks> <guest_time> <cguest_time>

      The previous time unit is the core clock frequency. When calculating the CPU usage of a process based on /proc/uptime, pay attention to the difference between the two time units. Refer to the following formula:

      The numerator is the time slices occupied by the process in the statistical period, which can be obtained from /proc/self/stat. Generally, it is the sum of the user-mode time (utime) and kernel-mode time (stime). You can determine whether to add other time slices in other modes as required. The denominator is the time occupied by the system in the statistical period. sysconf(_SC_CLK_TCK) indicates the clock ticks per second.

Example of A TA's CPU usage

The following is a code snippet example of reading the CPU usage of a TA:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#define BUF_SIZE 1024
#define PROC_SELF_STAT "/proc/self/stat"
#define DELTA_TIME 1 // s

// Read the /proc file to obtain the original data.
int read_cpu_time(double *utime, double *stime) {
    int fd;
    char buf[BUF_SIZE];
    char *token;
    
    // Read the /proc/self/stat content.
    fd = open(PROC_SELF_STAT, O_RDONLY);
    if (fd == -1) {
        tloge("Failed to open %s\n", PROC_SELF_STAT);
        return -1;
    }
    if (read(fd, buf, BUF_SIZE) == -1) {
        tloge("Failed to read %s\n", PROC_SELF_STAT);
        close(fd);
    }
    close(fd);
    // Parse and obtain the utime and stime.
    token = strtok(buf, " ");
    for (int i = 1; i <= 17 && token != NULL; i++) {
        if (i == 14) *utime = atof(token);  // utime in jiffies
        if (i == 15) *stime = atof(token);  // stime in jiffies
        token = strtok(NULL, " ");
    }
    return 0;
}

// Calculate the CPU usage of a TA.
void calculate_cpu_usage() {
    double utime1, stime1;
    double utime2, stime2;
    double cpu_usage = 0;
    
    read_cpu_time(&utime1, &stime1);
    // or do other work
    sleep(DELTA_TIME);  
    read_cpu_time(&utime2, &stime2);

    cpu_usage = ((utime2 + stime2) - (utime1 + stime1)) / (DELTA_TIME * sysconf(_SC_CLK_TCK));
    tlogi("cpu usage is %lf %%\n", cpu_usage * 100);
}