1fcf5ef2aSThomas Huth /* 2fcf5ef2aSThomas Huth * ARM gdb server stub 3fcf5ef2aSThomas Huth * 4fcf5ef2aSThomas Huth * Copyright (c) 2003-2005 Fabrice Bellard 5fcf5ef2aSThomas Huth * Copyright (c) 2013 SUSE LINUX Products GmbH 6fcf5ef2aSThomas Huth * 7fcf5ef2aSThomas Huth * This library is free software; you can redistribute it and/or 8fcf5ef2aSThomas Huth * modify it under the terms of the GNU Lesser General Public 9fcf5ef2aSThomas Huth * License as published by the Free Software Foundation; either 10fcf5ef2aSThomas Huth * version 2 of the License, or (at your option) any later version. 11fcf5ef2aSThomas Huth * 12fcf5ef2aSThomas Huth * This library is distributed in the hope that it will be useful, 13fcf5ef2aSThomas Huth * but WITHOUT ANY WARRANTY; without even the implied warranty of 14fcf5ef2aSThomas Huth * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15fcf5ef2aSThomas Huth * Lesser General Public License for more details. 16fcf5ef2aSThomas Huth * 17fcf5ef2aSThomas Huth * You should have received a copy of the GNU Lesser General Public 18fcf5ef2aSThomas Huth * License along with this library; if not, see <http://www.gnu.org/licenses/>. 19fcf5ef2aSThomas Huth */ 20fcf5ef2aSThomas Huth #include "qemu/osdep.h" 21fcf5ef2aSThomas Huth #include "cpu.h" 22fcf5ef2aSThomas Huth #include "exec/gdbstub.h" 23fcf5ef2aSThomas Huth 24200bf5b7SAbdallah Bouassida typedef struct RegisterSysregXmlParam { 25200bf5b7SAbdallah Bouassida CPUState *cs; 26200bf5b7SAbdallah Bouassida GString *s; 2732d6e32aSAlex Bennée int n; 28200bf5b7SAbdallah Bouassida } RegisterSysregXmlParam; 29200bf5b7SAbdallah Bouassida 30fcf5ef2aSThomas Huth /* Old gdb always expect FPA registers. Newer (xml-aware) gdb only expect 31fcf5ef2aSThomas Huth whatever the target description contains. Due to a historical mishap 32fcf5ef2aSThomas Huth the FPA registers appear in between core integer regs and the CPSR. 33fcf5ef2aSThomas Huth We hack round this by giving the FPA regs zero size when talking to a 34fcf5ef2aSThomas Huth newer gdb. */ 35fcf5ef2aSThomas Huth 36a010bdbeSAlex Bennée int arm_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) 37fcf5ef2aSThomas Huth { 38fcf5ef2aSThomas Huth ARMCPU *cpu = ARM_CPU(cs); 39fcf5ef2aSThomas Huth CPUARMState *env = &cpu->env; 40fcf5ef2aSThomas Huth 41fcf5ef2aSThomas Huth if (n < 16) { 42fcf5ef2aSThomas Huth /* Core integer register. */ 43fcf5ef2aSThomas Huth return gdb_get_reg32(mem_buf, env->regs[n]); 44fcf5ef2aSThomas Huth } 45fcf5ef2aSThomas Huth if (n < 24) { 46fcf5ef2aSThomas Huth /* FPA registers. */ 47fcf5ef2aSThomas Huth if (gdb_has_xml) { 48fcf5ef2aSThomas Huth return 0; 49fcf5ef2aSThomas Huth } 50*7b8c1527SPhilippe Mathieu-Daudé return gdb_get_zeroes(mem_buf, 12); 51fcf5ef2aSThomas Huth } 52fcf5ef2aSThomas Huth switch (n) { 53fcf5ef2aSThomas Huth case 24: 54fcf5ef2aSThomas Huth /* FPA status register. */ 55fcf5ef2aSThomas Huth if (gdb_has_xml) { 56fcf5ef2aSThomas Huth return 0; 57fcf5ef2aSThomas Huth } 58fcf5ef2aSThomas Huth return gdb_get_reg32(mem_buf, 0); 59fcf5ef2aSThomas Huth case 25: 60fcf5ef2aSThomas Huth /* CPSR */ 61fcf5ef2aSThomas Huth return gdb_get_reg32(mem_buf, cpsr_read(env)); 62fcf5ef2aSThomas Huth } 63fcf5ef2aSThomas Huth /* Unknown register. */ 64fcf5ef2aSThomas Huth return 0; 65fcf5ef2aSThomas Huth } 66fcf5ef2aSThomas Huth 67fcf5ef2aSThomas Huth int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) 68fcf5ef2aSThomas Huth { 69fcf5ef2aSThomas Huth ARMCPU *cpu = ARM_CPU(cs); 70fcf5ef2aSThomas Huth CPUARMState *env = &cpu->env; 71fcf5ef2aSThomas Huth uint32_t tmp; 72fcf5ef2aSThomas Huth 73fcf5ef2aSThomas Huth tmp = ldl_p(mem_buf); 74fcf5ef2aSThomas Huth 75fcf5ef2aSThomas Huth /* Mask out low bit of PC to workaround gdb bugs. This will probably 76fcf5ef2aSThomas Huth cause problems if we ever implement the Jazelle DBX extensions. */ 77fcf5ef2aSThomas Huth if (n == 15) { 78fcf5ef2aSThomas Huth tmp &= ~1; 79fcf5ef2aSThomas Huth } 80fcf5ef2aSThomas Huth 81fcf5ef2aSThomas Huth if (n < 16) { 82fcf5ef2aSThomas Huth /* Core integer register. */ 83fcf5ef2aSThomas Huth env->regs[n] = tmp; 84fcf5ef2aSThomas Huth return 4; 85fcf5ef2aSThomas Huth } 86fcf5ef2aSThomas Huth if (n < 24) { /* 16-23 */ 87fcf5ef2aSThomas Huth /* FPA registers (ignored). */ 88fcf5ef2aSThomas Huth if (gdb_has_xml) { 89fcf5ef2aSThomas Huth return 0; 90fcf5ef2aSThomas Huth } 91fcf5ef2aSThomas Huth return 12; 92fcf5ef2aSThomas Huth } 93fcf5ef2aSThomas Huth switch (n) { 94fcf5ef2aSThomas Huth case 24: 95fcf5ef2aSThomas Huth /* FPA status register (ignored). */ 96fcf5ef2aSThomas Huth if (gdb_has_xml) { 97fcf5ef2aSThomas Huth return 0; 98fcf5ef2aSThomas Huth } 99fcf5ef2aSThomas Huth return 4; 100fcf5ef2aSThomas Huth case 25: 101fcf5ef2aSThomas Huth /* CPSR */ 102fcf5ef2aSThomas Huth cpsr_write(env, tmp, 0xffffffff, CPSRWriteByGDBStub); 103fcf5ef2aSThomas Huth return 4; 104fcf5ef2aSThomas Huth } 105fcf5ef2aSThomas Huth /* Unknown register. */ 106fcf5ef2aSThomas Huth return 0; 107fcf5ef2aSThomas Huth } 108200bf5b7SAbdallah Bouassida 109448d4d14SAlex Bennée static void arm_gen_one_xml_sysreg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml, 110200bf5b7SAbdallah Bouassida ARMCPRegInfo *ri, uint32_t ri_key, 11132d6e32aSAlex Bennée int bitsize, int regnum) 112200bf5b7SAbdallah Bouassida { 113200bf5b7SAbdallah Bouassida g_string_append_printf(s, "<reg name=\"%s\"", ri->name); 114200bf5b7SAbdallah Bouassida g_string_append_printf(s, " bitsize=\"%d\"", bitsize); 11532d6e32aSAlex Bennée g_string_append_printf(s, " regnum=\"%d\"", regnum); 116200bf5b7SAbdallah Bouassida g_string_append_printf(s, " group=\"cp_regs\"/>"); 117448d4d14SAlex Bennée dyn_xml->data.cpregs.keys[dyn_xml->num] = ri_key; 118448d4d14SAlex Bennée dyn_xml->num++; 119200bf5b7SAbdallah Bouassida } 120200bf5b7SAbdallah Bouassida 121200bf5b7SAbdallah Bouassida static void arm_register_sysreg_for_xml(gpointer key, gpointer value, 122200bf5b7SAbdallah Bouassida gpointer p) 123200bf5b7SAbdallah Bouassida { 124200bf5b7SAbdallah Bouassida uint32_t ri_key = *(uint32_t *)key; 125200bf5b7SAbdallah Bouassida ARMCPRegInfo *ri = value; 126200bf5b7SAbdallah Bouassida RegisterSysregXmlParam *param = (RegisterSysregXmlParam *)p; 127200bf5b7SAbdallah Bouassida GString *s = param->s; 128200bf5b7SAbdallah Bouassida ARMCPU *cpu = ARM_CPU(param->cs); 129200bf5b7SAbdallah Bouassida CPUARMState *env = &cpu->env; 130448d4d14SAlex Bennée DynamicGDBXMLInfo *dyn_xml = &cpu->dyn_sysreg_xml; 131200bf5b7SAbdallah Bouassida 132200bf5b7SAbdallah Bouassida if (!(ri->type & (ARM_CP_NO_RAW | ARM_CP_NO_GDB))) { 133200bf5b7SAbdallah Bouassida if (arm_feature(env, ARM_FEATURE_AARCH64)) { 134200bf5b7SAbdallah Bouassida if (ri->state == ARM_CP_STATE_AA64) { 13532d6e32aSAlex Bennée arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64, 13632d6e32aSAlex Bennée param->n++); 137200bf5b7SAbdallah Bouassida } 138200bf5b7SAbdallah Bouassida } else { 139200bf5b7SAbdallah Bouassida if (ri->state == ARM_CP_STATE_AA32) { 140200bf5b7SAbdallah Bouassida if (!arm_feature(env, ARM_FEATURE_EL3) && 141200bf5b7SAbdallah Bouassida (ri->secure & ARM_CP_SECSTATE_S)) { 142200bf5b7SAbdallah Bouassida return; 143200bf5b7SAbdallah Bouassida } 144200bf5b7SAbdallah Bouassida if (ri->type & ARM_CP_64BIT) { 14532d6e32aSAlex Bennée arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64, 14632d6e32aSAlex Bennée param->n++); 147200bf5b7SAbdallah Bouassida } else { 14832d6e32aSAlex Bennée arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 32, 14932d6e32aSAlex Bennée param->n++); 150200bf5b7SAbdallah Bouassida } 151200bf5b7SAbdallah Bouassida } 152200bf5b7SAbdallah Bouassida } 153200bf5b7SAbdallah Bouassida } 154200bf5b7SAbdallah Bouassida } 155200bf5b7SAbdallah Bouassida 15632d6e32aSAlex Bennée int arm_gen_dynamic_sysreg_xml(CPUState *cs, int base_reg) 157200bf5b7SAbdallah Bouassida { 158200bf5b7SAbdallah Bouassida ARMCPU *cpu = ARM_CPU(cs); 159200bf5b7SAbdallah Bouassida GString *s = g_string_new(NULL); 16032d6e32aSAlex Bennée RegisterSysregXmlParam param = {cs, s, base_reg}; 161200bf5b7SAbdallah Bouassida 162448d4d14SAlex Bennée cpu->dyn_sysreg_xml.num = 0; 163448d4d14SAlex Bennée cpu->dyn_sysreg_xml.data.cpregs.keys = g_new(uint32_t, g_hash_table_size(cpu->cp_regs)); 164200bf5b7SAbdallah Bouassida g_string_printf(s, "<?xml version=\"1.0\"?>"); 165200bf5b7SAbdallah Bouassida g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"); 166200bf5b7SAbdallah Bouassida g_string_append_printf(s, "<feature name=\"org.qemu.gdb.arm.sys.regs\">"); 167200bf5b7SAbdallah Bouassida g_hash_table_foreach(cpu->cp_regs, arm_register_sysreg_for_xml, ¶m); 168200bf5b7SAbdallah Bouassida g_string_append_printf(s, "</feature>"); 169448d4d14SAlex Bennée cpu->dyn_sysreg_xml.desc = g_string_free(s, false); 170448d4d14SAlex Bennée return cpu->dyn_sysreg_xml.num; 171200bf5b7SAbdallah Bouassida } 172200bf5b7SAbdallah Bouassida 173d12379c5SAlex Bennée struct TypeSize { 174d12379c5SAlex Bennée const char *gdb_type; 175d12379c5SAlex Bennée int size; 176d12379c5SAlex Bennée const char sz, suffix; 177d12379c5SAlex Bennée }; 178d12379c5SAlex Bennée 179d12379c5SAlex Bennée static const struct TypeSize vec_lanes[] = { 180d12379c5SAlex Bennée /* quads */ 181d12379c5SAlex Bennée { "uint128", 128, 'q', 'u' }, 182d12379c5SAlex Bennée { "int128", 128, 'q', 's' }, 183d12379c5SAlex Bennée /* 64 bit */ 184d12379c5SAlex Bennée { "uint64", 64, 'd', 'u' }, 185d12379c5SAlex Bennée { "int64", 64, 'd', 's' }, 186d12379c5SAlex Bennée { "ieee_double", 64, 'd', 'f' }, 187d12379c5SAlex Bennée /* 32 bit */ 188d12379c5SAlex Bennée { "uint32", 32, 's', 'u' }, 189d12379c5SAlex Bennée { "int32", 32, 's', 's' }, 190d12379c5SAlex Bennée { "ieee_single", 32, 's', 'f' }, 191d12379c5SAlex Bennée /* 16 bit */ 192d12379c5SAlex Bennée { "uint16", 16, 'h', 'u' }, 193d12379c5SAlex Bennée { "int16", 16, 'h', 's' }, 1949231951aSAlex Bennée /* 1959231951aSAlex Bennée * TODO: currently there is no reliable way of telling 1969231951aSAlex Bennée * if the remote gdb actually understands ieee_half so 1979231951aSAlex Bennée * we don't expose it in the target description for now. 1989231951aSAlex Bennée * { "ieee_half", 16, 'h', 'f' }, 1999231951aSAlex Bennée */ 200d12379c5SAlex Bennée /* bytes */ 201d12379c5SAlex Bennée { "uint8", 8, 'b', 'u' }, 202d12379c5SAlex Bennée { "int8", 8, 'b', 's' }, 203d12379c5SAlex Bennée }; 204d12379c5SAlex Bennée 205d12379c5SAlex Bennée 206d12379c5SAlex Bennée int arm_gen_dynamic_svereg_xml(CPUState *cs, int base_reg) 207d12379c5SAlex Bennée { 208d12379c5SAlex Bennée ARMCPU *cpu = ARM_CPU(cs); 209d12379c5SAlex Bennée GString *s = g_string_new(NULL); 210d12379c5SAlex Bennée DynamicGDBXMLInfo *info = &cpu->dyn_svereg_xml; 211d12379c5SAlex Bennée g_autoptr(GString) ts = g_string_new(""); 212d12379c5SAlex Bennée int i, bits, reg_width = (cpu->sve_max_vq * 128); 213d12379c5SAlex Bennée info->num = 0; 214d12379c5SAlex Bennée g_string_printf(s, "<?xml version=\"1.0\"?>"); 215d12379c5SAlex Bennée g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"); 216d12379c5SAlex Bennée g_string_append_printf(s, "<feature name=\"org.qemu.gdb.aarch64.sve\">"); 217d12379c5SAlex Bennée 218d12379c5SAlex Bennée /* First define types and totals in a whole VL */ 219d12379c5SAlex Bennée for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) { 220d12379c5SAlex Bennée int count = reg_width / vec_lanes[i].size; 221d12379c5SAlex Bennée g_string_printf(ts, "vq%d%c%c", count, 222d12379c5SAlex Bennée vec_lanes[i].sz, vec_lanes[i].suffix); 223d12379c5SAlex Bennée g_string_append_printf(s, 224d12379c5SAlex Bennée "<vector id=\"%s\" type=\"%s\" count=\"%d\"/>", 225d12379c5SAlex Bennée ts->str, vec_lanes[i].gdb_type, count); 226d12379c5SAlex Bennée } 227d12379c5SAlex Bennée /* 228d12379c5SAlex Bennée * Now define a union for each size group containing unsigned and 229d12379c5SAlex Bennée * signed and potentially float versions of each size from 128 to 230d12379c5SAlex Bennée * 8 bits. 231d12379c5SAlex Bennée */ 232d12379c5SAlex Bennée for (bits = 128; bits >= 8; bits /= 2) { 233d12379c5SAlex Bennée int count = reg_width / bits; 234d12379c5SAlex Bennée g_string_append_printf(s, "<union id=\"vq%dn\">", count); 235d12379c5SAlex Bennée for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) { 236d12379c5SAlex Bennée if (vec_lanes[i].size == bits) { 237d12379c5SAlex Bennée g_string_append_printf(s, "<field name=\"%c\" type=\"vq%d%c%c\"/>", 238d12379c5SAlex Bennée vec_lanes[i].suffix, 239d12379c5SAlex Bennée count, 240d12379c5SAlex Bennée vec_lanes[i].sz, vec_lanes[i].suffix); 241d12379c5SAlex Bennée } 242d12379c5SAlex Bennée } 243d12379c5SAlex Bennée g_string_append(s, "</union>"); 244d12379c5SAlex Bennée } 245d12379c5SAlex Bennée /* And now the final union of unions */ 246d12379c5SAlex Bennée g_string_append(s, "<union id=\"vq\">"); 247d12379c5SAlex Bennée for (bits = 128; bits >= 8; bits /= 2) { 248d12379c5SAlex Bennée int count = reg_width / bits; 249d12379c5SAlex Bennée for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) { 250d12379c5SAlex Bennée if (vec_lanes[i].size == bits) { 251d12379c5SAlex Bennée g_string_append_printf(s, "<field name=\"%c\" type=\"vq%dn\"/>", 252d12379c5SAlex Bennée vec_lanes[i].sz, count); 253d12379c5SAlex Bennée break; 254d12379c5SAlex Bennée } 255d12379c5SAlex Bennée } 256d12379c5SAlex Bennée } 257d12379c5SAlex Bennée g_string_append(s, "</union>"); 258d12379c5SAlex Bennée 259d12379c5SAlex Bennée /* Then define each register in parts for each vq */ 260d12379c5SAlex Bennée for (i = 0; i < 32; i++) { 261d12379c5SAlex Bennée g_string_append_printf(s, 262d12379c5SAlex Bennée "<reg name=\"z%d\" bitsize=\"%d\"" 263d12379c5SAlex Bennée " regnum=\"%d\" group=\"vector\"" 264d12379c5SAlex Bennée " type=\"vq\"/>", 265d12379c5SAlex Bennée i, reg_width, base_reg++); 266d12379c5SAlex Bennée info->num++; 267d12379c5SAlex Bennée } 268d12379c5SAlex Bennée /* fpscr & status registers */ 269d12379c5SAlex Bennée g_string_append_printf(s, "<reg name=\"fpsr\" bitsize=\"32\"" 270d12379c5SAlex Bennée " regnum=\"%d\" group=\"float\"" 271d12379c5SAlex Bennée " type=\"int\"/>", base_reg++); 272d12379c5SAlex Bennée g_string_append_printf(s, "<reg name=\"fpcr\" bitsize=\"32\"" 273d12379c5SAlex Bennée " regnum=\"%d\" group=\"float\"" 274d12379c5SAlex Bennée " type=\"int\"/>", base_reg++); 275d12379c5SAlex Bennée info->num += 2; 276d12379c5SAlex Bennée /* 277d12379c5SAlex Bennée * Predicate registers aren't so big they are worth splitting up 278d12379c5SAlex Bennée * but we do need to define a type to hold the array of quad 279d12379c5SAlex Bennée * references. 280d12379c5SAlex Bennée */ 281d12379c5SAlex Bennée g_string_append_printf(s, 282d12379c5SAlex Bennée "<vector id=\"vqp\" type=\"uint16\" count=\"%d\"/>", 283d12379c5SAlex Bennée cpu->sve_max_vq); 284d12379c5SAlex Bennée for (i = 0; i < 16; i++) { 285d12379c5SAlex Bennée g_string_append_printf(s, 286d12379c5SAlex Bennée "<reg name=\"p%d\" bitsize=\"%d\"" 287d12379c5SAlex Bennée " regnum=\"%d\" group=\"vector\"" 288d12379c5SAlex Bennée " type=\"vqp\"/>", 289d12379c5SAlex Bennée i, cpu->sve_max_vq * 16, base_reg++); 290d12379c5SAlex Bennée info->num++; 291d12379c5SAlex Bennée } 292d12379c5SAlex Bennée g_string_append_printf(s, 293d12379c5SAlex Bennée "<reg name=\"ffr\" bitsize=\"%d\"" 294d12379c5SAlex Bennée " regnum=\"%d\" group=\"vector\"" 295d12379c5SAlex Bennée " type=\"vqp\"/>", 296d12379c5SAlex Bennée cpu->sve_max_vq * 16, base_reg++); 297d12379c5SAlex Bennée g_string_append_printf(s, 298d12379c5SAlex Bennée "<reg name=\"vg\" bitsize=\"64\"" 299d12379c5SAlex Bennée " regnum=\"%d\" group=\"vector\"" 300d12379c5SAlex Bennée " type=\"uint32\"/>", 301d12379c5SAlex Bennée base_reg++); 302d12379c5SAlex Bennée info->num += 2; 303d12379c5SAlex Bennée g_string_append_printf(s, "</feature>"); 304d12379c5SAlex Bennée cpu->dyn_svereg_xml.desc = g_string_free(s, false); 305d12379c5SAlex Bennée 306d12379c5SAlex Bennée return cpu->dyn_svereg_xml.num; 307d12379c5SAlex Bennée } 308d12379c5SAlex Bennée 309d12379c5SAlex Bennée 310200bf5b7SAbdallah Bouassida const char *arm_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname) 311200bf5b7SAbdallah Bouassida { 312200bf5b7SAbdallah Bouassida ARMCPU *cpu = ARM_CPU(cs); 313200bf5b7SAbdallah Bouassida 314200bf5b7SAbdallah Bouassida if (strcmp(xmlname, "system-registers.xml") == 0) { 315448d4d14SAlex Bennée return cpu->dyn_sysreg_xml.desc; 316d12379c5SAlex Bennée } else if (strcmp(xmlname, "sve-registers.xml") == 0) { 317d12379c5SAlex Bennée return cpu->dyn_svereg_xml.desc; 318200bf5b7SAbdallah Bouassida } 319200bf5b7SAbdallah Bouassida return NULL; 320200bf5b7SAbdallah Bouassida } 321