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

gdbstub.c (4423B)


      1/*
      2 * MIPS gdb server stub
      3 *
      4 * Copyright (c) 2003-2005 Fabrice Bellard
      5 * Copyright (c) 2013 SUSE LINUX Products GmbH
      6 *
      7 * This library is free software; you can redistribute it and/or
      8 * modify it under the terms of the GNU Lesser General Public
      9 * License as published by the Free Software Foundation; either
     10 * version 2.1 of the License, or (at your option) any later version.
     11 *
     12 * This library is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15 * Lesser General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU Lesser General Public
     18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
     19 */
     20#include "qemu/osdep.h"
     21#include "cpu.h"
     22#include "internal.h"
     23#include "exec/gdbstub.h"
     24#include "fpu_helper.h"
     25
     26int mips_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
     27{
     28    MIPSCPU *cpu = MIPS_CPU(cs);
     29    CPUMIPSState *env = &cpu->env;
     30
     31    if (n < 32) {
     32        return gdb_get_regl(mem_buf, env->active_tc.gpr[n]);
     33    }
     34    if (env->CP0_Config1 & (1 << CP0C1_FP) && n >= 38 && n < 72) {
     35        switch (n) {
     36        case 70:
     37            return gdb_get_regl(mem_buf, (int32_t)env->active_fpu.fcr31);
     38        case 71:
     39            return gdb_get_regl(mem_buf, (int32_t)env->active_fpu.fcr0);
     40        default:
     41            if (env->CP0_Status & (1 << CP0St_FR)) {
     42                return gdb_get_regl(mem_buf,
     43                    env->active_fpu.fpr[n - 38].d);
     44            } else {
     45                return gdb_get_regl(mem_buf,
     46                    env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX]);
     47            }
     48        }
     49    }
     50    switch (n) {
     51    case 32:
     52        return gdb_get_regl(mem_buf, (int32_t)env->CP0_Status);
     53    case 33:
     54        return gdb_get_regl(mem_buf, env->active_tc.LO[0]);
     55    case 34:
     56        return gdb_get_regl(mem_buf, env->active_tc.HI[0]);
     57    case 35:
     58        return gdb_get_regl(mem_buf, env->CP0_BadVAddr);
     59    case 36:
     60        return gdb_get_regl(mem_buf, (int32_t)env->CP0_Cause);
     61    case 37:
     62        return gdb_get_regl(mem_buf, env->active_tc.PC |
     63                                     !!(env->hflags & MIPS_HFLAG_M16));
     64    case 72:
     65        return gdb_get_regl(mem_buf, 0); /* fp */
     66    case 89:
     67        return gdb_get_regl(mem_buf, (int32_t)env->CP0_PRid);
     68    default:
     69        if (n > 89) {
     70            return 0;
     71        }
     72        /* 16 embedded regs.  */
     73        return gdb_get_regl(mem_buf, 0);
     74    }
     75
     76    return 0;
     77}
     78
     79int mips_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
     80{
     81    MIPSCPU *cpu = MIPS_CPU(cs);
     82    CPUMIPSState *env = &cpu->env;
     83    target_ulong tmp;
     84
     85    tmp = ldtul_p(mem_buf);
     86
     87    if (n < 32) {
     88        env->active_tc.gpr[n] = tmp;
     89        return sizeof(target_ulong);
     90    }
     91    if (env->CP0_Config1 & (1 << CP0C1_FP) && n >= 38 && n < 72) {
     92        switch (n) {
     93        case 70:
     94            env->active_fpu.fcr31 = (tmp & env->active_fpu.fcr31_rw_bitmask) |
     95                  (env->active_fpu.fcr31 & ~(env->active_fpu.fcr31_rw_bitmask));
     96            restore_fp_status(env);
     97            break;
     98        case 71:
     99            /* FIR is read-only.  Ignore writes.  */
    100            break;
    101        default:
    102            if (env->CP0_Status & (1 << CP0St_FR)) {
    103                env->active_fpu.fpr[n - 38].d = tmp;
    104            } else {
    105                env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX] = tmp;
    106            }
    107            break;
    108        }
    109        return sizeof(target_ulong);
    110    }
    111    switch (n) {
    112    case 32:
    113#ifndef CONFIG_USER_ONLY
    114        cpu_mips_store_status(env, tmp);
    115#endif
    116        break;
    117    case 33:
    118        env->active_tc.LO[0] = tmp;
    119        break;
    120    case 34:
    121        env->active_tc.HI[0] = tmp;
    122        break;
    123    case 35:
    124        env->CP0_BadVAddr = tmp;
    125        break;
    126    case 36:
    127#ifndef CONFIG_USER_ONLY
    128        cpu_mips_store_cause(env, tmp);
    129#endif
    130        break;
    131    case 37:
    132        env->active_tc.PC = tmp & ~(target_ulong)1;
    133        if (tmp & 1) {
    134            env->hflags |= MIPS_HFLAG_M16;
    135        } else {
    136            env->hflags &= ~(MIPS_HFLAG_M16);
    137        }
    138        break;
    139    case 72: /* fp, ignored */
    140        break;
    141    default:
    142        if (n > 89) {
    143            return 0;
    144        }
    145        /* Other registers are readonly.  Ignore writes.  */
    146        break;
    147    }
    148
    149    return sizeof(target_ulong);
    150}