1 /* 2 * ARM 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 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 "exec/gdbstub.h" 23 24 typedef struct RegisterSysregXmlParam { 25 CPUState *cs; 26 GString *s; 27 } RegisterSysregXmlParam; 28 29 /* Old gdb always expect FPA registers. Newer (xml-aware) gdb only expect 30 whatever the target description contains. Due to a historical mishap 31 the FPA registers appear in between core integer regs and the CPSR. 32 We hack round this by giving the FPA regs zero size when talking to a 33 newer gdb. */ 34 35 int arm_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) 36 { 37 ARMCPU *cpu = ARM_CPU(cs); 38 CPUARMState *env = &cpu->env; 39 40 if (n < 16) { 41 /* Core integer register. */ 42 return gdb_get_reg32(mem_buf, env->regs[n]); 43 } 44 if (n < 24) { 45 /* FPA registers. */ 46 if (gdb_has_xml) { 47 return 0; 48 } 49 memset(mem_buf, 0, 12); 50 return 12; 51 } 52 switch (n) { 53 case 24: 54 /* FPA status register. */ 55 if (gdb_has_xml) { 56 return 0; 57 } 58 return gdb_get_reg32(mem_buf, 0); 59 case 25: 60 /* CPSR */ 61 return gdb_get_reg32(mem_buf, cpsr_read(env)); 62 } 63 /* Unknown register. */ 64 return 0; 65 } 66 67 int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) 68 { 69 ARMCPU *cpu = ARM_CPU(cs); 70 CPUARMState *env = &cpu->env; 71 uint32_t tmp; 72 73 tmp = ldl_p(mem_buf); 74 75 /* Mask out low bit of PC to workaround gdb bugs. This will probably 76 cause problems if we ever implement the Jazelle DBX extensions. */ 77 if (n == 15) { 78 tmp &= ~1; 79 } 80 81 if (n < 16) { 82 /* Core integer register. */ 83 env->regs[n] = tmp; 84 return 4; 85 } 86 if (n < 24) { /* 16-23 */ 87 /* FPA registers (ignored). */ 88 if (gdb_has_xml) { 89 return 0; 90 } 91 return 12; 92 } 93 switch (n) { 94 case 24: 95 /* FPA status register (ignored). */ 96 if (gdb_has_xml) { 97 return 0; 98 } 99 return 4; 100 case 25: 101 /* CPSR */ 102 cpsr_write(env, tmp, 0xffffffff, CPSRWriteByGDBStub); 103 return 4; 104 } 105 /* Unknown register. */ 106 return 0; 107 } 108 109 static void arm_gen_one_xml_reg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml, 110 ARMCPRegInfo *ri, uint32_t ri_key, 111 int bitsize) 112 { 113 g_string_append_printf(s, "<reg name=\"%s\"", ri->name); 114 g_string_append_printf(s, " bitsize=\"%d\"", bitsize); 115 g_string_append_printf(s, " group=\"cp_regs\"/>"); 116 dyn_xml->num_cpregs++; 117 dyn_xml->cpregs_keys[dyn_xml->num_cpregs - 1] = ri_key; 118 } 119 120 static void arm_register_sysreg_for_xml(gpointer key, gpointer value, 121 gpointer p) 122 { 123 uint32_t ri_key = *(uint32_t *)key; 124 ARMCPRegInfo *ri = value; 125 RegisterSysregXmlParam *param = (RegisterSysregXmlParam *)p; 126 GString *s = param->s; 127 ARMCPU *cpu = ARM_CPU(param->cs); 128 CPUARMState *env = &cpu->env; 129 DynamicGDBXMLInfo *dyn_xml = &cpu->dyn_xml; 130 131 if (!(ri->type & (ARM_CP_NO_RAW | ARM_CP_NO_GDB))) { 132 if (arm_feature(env, ARM_FEATURE_AARCH64)) { 133 if (ri->state == ARM_CP_STATE_AA64) { 134 arm_gen_one_xml_reg_tag(s , dyn_xml, ri, ri_key, 64); 135 } 136 } else { 137 if (ri->state == ARM_CP_STATE_AA32) { 138 if (!arm_feature(env, ARM_FEATURE_EL3) && 139 (ri->secure & ARM_CP_SECSTATE_S)) { 140 return; 141 } 142 if (ri->type & ARM_CP_64BIT) { 143 arm_gen_one_xml_reg_tag(s , dyn_xml, ri, ri_key, 64); 144 } else { 145 arm_gen_one_xml_reg_tag(s , dyn_xml, ri, ri_key, 32); 146 } 147 } 148 } 149 } 150 } 151 152 int arm_gen_dynamic_xml(CPUState *cs) 153 { 154 ARMCPU *cpu = ARM_CPU(cs); 155 GString *s = g_string_new(NULL); 156 RegisterSysregXmlParam param = {cs, s}; 157 158 cpu->dyn_xml.num_cpregs = 0; 159 cpu->dyn_xml.cpregs_keys = g_new(uint32_t, g_hash_table_size(cpu->cp_regs)); 160 g_string_printf(s, "<?xml version=\"1.0\"?>"); 161 g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"); 162 g_string_append_printf(s, "<feature name=\"org.qemu.gdb.arm.sys.regs\">"); 163 g_hash_table_foreach(cpu->cp_regs, arm_register_sysreg_for_xml, ¶m); 164 g_string_append_printf(s, "</feature>"); 165 cpu->dyn_xml.desc = g_string_free(s, false); 166 return cpu->dyn_xml.num_cpregs; 167 } 168 169 const char *arm_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname) 170 { 171 ARMCPU *cpu = ARM_CPU(cs); 172 173 if (strcmp(xmlname, "system-registers.xml") == 0) { 174 return cpu->dyn_xml.desc; 175 } 176 return NULL; 177 } 178