cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

numa.c (6685B)


      1/*
      2 * QEMU RISC-V NUMA Helper
      3 *
      4 * Copyright (c) 2020 Western Digital Corporation or its affiliates.
      5 *
      6 * This program is free software; you can redistribute it and/or modify it
      7 * under the terms and conditions of the GNU General Public License,
      8 * version 2 or later, as published by the Free Software Foundation.
      9 *
     10 * This program is distributed in the hope it will be useful, but WITHOUT
     11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     12 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     13 * more details.
     14 *
     15 * You should have received a copy of the GNU General Public License along with
     16 * this program.  If not, see <http://www.gnu.org/licenses/>.
     17 */
     18
     19#include "qemu/osdep.h"
     20#include "qemu/units.h"
     21#include "qemu/error-report.h"
     22#include "qapi/error.h"
     23#include "hw/boards.h"
     24#include "hw/qdev-properties.h"
     25#include "hw/riscv/numa.h"
     26#include "sysemu/device_tree.h"
     27
     28static bool numa_enabled(const MachineState *ms)
     29{
     30    return (ms->numa_state && ms->numa_state->num_nodes) ? true : false;
     31}
     32
     33int riscv_socket_count(const MachineState *ms)
     34{
     35    return (numa_enabled(ms)) ? ms->numa_state->num_nodes : 1;
     36}
     37
     38int riscv_socket_first_hartid(const MachineState *ms, int socket_id)
     39{
     40    int i, first_hartid = ms->smp.cpus;
     41
     42    if (!numa_enabled(ms)) {
     43        return (!socket_id) ? 0 : -1;
     44    }
     45
     46    for (i = 0; i < ms->smp.cpus; i++) {
     47        if (ms->possible_cpus->cpus[i].props.node_id != socket_id) {
     48            continue;
     49        }
     50        if (i < first_hartid) {
     51            first_hartid = i;
     52        }
     53    }
     54
     55    return (first_hartid < ms->smp.cpus) ? first_hartid : -1;
     56}
     57
     58int riscv_socket_last_hartid(const MachineState *ms, int socket_id)
     59{
     60    int i, last_hartid = -1;
     61
     62    if (!numa_enabled(ms)) {
     63        return (!socket_id) ? ms->smp.cpus - 1 : -1;
     64    }
     65
     66    for (i = 0; i < ms->smp.cpus; i++) {
     67        if (ms->possible_cpus->cpus[i].props.node_id != socket_id) {
     68            continue;
     69        }
     70        if (i > last_hartid) {
     71            last_hartid = i;
     72        }
     73    }
     74
     75    return (last_hartid < ms->smp.cpus) ? last_hartid : -1;
     76}
     77
     78int riscv_socket_hart_count(const MachineState *ms, int socket_id)
     79{
     80    int first_hartid, last_hartid;
     81
     82    if (!numa_enabled(ms)) {
     83        return (!socket_id) ? ms->smp.cpus : -1;
     84    }
     85
     86    first_hartid = riscv_socket_first_hartid(ms, socket_id);
     87    if (first_hartid < 0) {
     88        return -1;
     89    }
     90
     91    last_hartid = riscv_socket_last_hartid(ms, socket_id);
     92    if (last_hartid < 0) {
     93        return -1;
     94    }
     95
     96    if (first_hartid > last_hartid) {
     97        return -1;
     98    }
     99
    100    return last_hartid - first_hartid + 1;
    101}
    102
    103bool riscv_socket_check_hartids(const MachineState *ms, int socket_id)
    104{
    105    int i, first_hartid, last_hartid;
    106
    107    if (!numa_enabled(ms)) {
    108        return (!socket_id) ? true : false;
    109    }
    110
    111    first_hartid = riscv_socket_first_hartid(ms, socket_id);
    112    if (first_hartid < 0) {
    113        return false;
    114    }
    115
    116    last_hartid = riscv_socket_last_hartid(ms, socket_id);
    117    if (last_hartid < 0) {
    118        return false;
    119    }
    120
    121    for (i = first_hartid; i <= last_hartid; i++) {
    122        if (ms->possible_cpus->cpus[i].props.node_id != socket_id) {
    123            return false;
    124        }
    125    }
    126
    127    return true;
    128}
    129
    130uint64_t riscv_socket_mem_offset(const MachineState *ms, int socket_id)
    131{
    132    int i;
    133    uint64_t mem_offset = 0;
    134
    135    if (!numa_enabled(ms)) {
    136        return 0;
    137    }
    138
    139    for (i = 0; i < ms->numa_state->num_nodes; i++) {
    140        if (i == socket_id) {
    141            break;
    142        }
    143        mem_offset += ms->numa_state->nodes[i].node_mem;
    144    }
    145
    146    return (i == socket_id) ? mem_offset : 0;
    147}
    148
    149uint64_t riscv_socket_mem_size(const MachineState *ms, int socket_id)
    150{
    151    if (!numa_enabled(ms)) {
    152        return (!socket_id) ? ms->ram_size : 0;
    153    }
    154
    155    return (socket_id < ms->numa_state->num_nodes) ?
    156            ms->numa_state->nodes[socket_id].node_mem : 0;
    157}
    158
    159void riscv_socket_fdt_write_id(const MachineState *ms, void *fdt,
    160                               const char *node_name, int socket_id)
    161{
    162    if (numa_enabled(ms)) {
    163        qemu_fdt_setprop_cell(fdt, node_name, "numa-node-id", socket_id);
    164    }
    165}
    166
    167void riscv_socket_fdt_write_distance_matrix(const MachineState *ms, void *fdt)
    168{
    169    int i, j, idx;
    170    uint32_t *dist_matrix, dist_matrix_size;
    171
    172    if (numa_enabled(ms) && ms->numa_state->have_numa_distance) {
    173        dist_matrix_size = riscv_socket_count(ms) * riscv_socket_count(ms);
    174        dist_matrix_size *= (3 * sizeof(uint32_t));
    175        dist_matrix = g_malloc0(dist_matrix_size);
    176
    177        for (i = 0; i < riscv_socket_count(ms); i++) {
    178            for (j = 0; j < riscv_socket_count(ms); j++) {
    179                idx = (i * riscv_socket_count(ms) + j) * 3;
    180                dist_matrix[idx + 0] = cpu_to_be32(i);
    181                dist_matrix[idx + 1] = cpu_to_be32(j);
    182                dist_matrix[idx + 2] =
    183                    cpu_to_be32(ms->numa_state->nodes[i].distance[j]);
    184            }
    185        }
    186
    187        qemu_fdt_add_subnode(fdt, "/distance-map");
    188        qemu_fdt_setprop_string(fdt, "/distance-map", "compatible",
    189                                "numa-distance-map-v1");
    190        qemu_fdt_setprop(fdt, "/distance-map", "distance-matrix",
    191                         dist_matrix, dist_matrix_size);
    192        g_free(dist_matrix);
    193    }
    194}
    195
    196CpuInstanceProperties
    197riscv_numa_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
    198{
    199    MachineClass *mc = MACHINE_GET_CLASS(ms);
    200    const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms);
    201
    202    assert(cpu_index < possible_cpus->len);
    203    return possible_cpus->cpus[cpu_index].props;
    204}
    205
    206int64_t riscv_numa_get_default_cpu_node_id(const MachineState *ms, int idx)
    207{
    208    int64_t nidx = 0;
    209
    210    if (ms->numa_state->num_nodes) {
    211        nidx = idx / (ms->smp.cpus / ms->numa_state->num_nodes);
    212        if (ms->numa_state->num_nodes <= nidx) {
    213            nidx = ms->numa_state->num_nodes - 1;
    214        }
    215    }
    216
    217    return nidx;
    218}
    219
    220const CPUArchIdList *riscv_numa_possible_cpu_arch_ids(MachineState *ms)
    221{
    222    int n;
    223    unsigned int max_cpus = ms->smp.max_cpus;
    224
    225    if (ms->possible_cpus) {
    226        assert(ms->possible_cpus->len == max_cpus);
    227        return ms->possible_cpus;
    228    }
    229
    230    ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) +
    231                                  sizeof(CPUArchId) * max_cpus);
    232    ms->possible_cpus->len = max_cpus;
    233    for (n = 0; n < ms->possible_cpus->len; n++) {
    234        ms->possible_cpus->cpus[n].type = ms->cpu_type;
    235        ms->possible_cpus->cpus[n].arch_id = n;
    236        ms->possible_cpus->cpus[n].props.has_core_id = true;
    237        ms->possible_cpus->cpus[n].props.core_id = n;
    238    }
    239
    240    return ms->possible_cpus;
    241}