diff --git a/configs/targets/hexagon-linux-user.mak
b/configs/targets/hexagon-linux-user.mak
index 51fde5d60e..10ae1943a5 100644
--- a/configs/targets/hexagon-linux-user.mak
+++ b/configs/targets/hexagon-linux-user.mak
@@ -1,5 +1,5 @@
TARGET_ARCH=hexagon
-TARGET_XML_FILES=hexagon-core.xml hexagon-hvx.xml
+TARGET_XML_FILES=hexagon-core.xml hexagon-hvx.xml hexagon-hlx.xml
TARGET_SYSTBL=syscall.tbl
TARGET_SYSTBL_ABI=common,32,hexagon,time32,stat64,rlimit,renameat
TARGET_LONG_BITS=32
diff --git a/configs/targets/hexagon-softmmu.mak
b/configs/targets/hexagon-softmmu.mak
index 1ba6420d20..8c3a9cd4b1 100644
--- a/configs/targets/hexagon-softmmu.mak
+++ b/configs/targets/hexagon-softmmu.mak
@@ -1,7 +1,7 @@
# Default configuration for hexagon-softmmu
TARGET_ARCH=hexagon
-TARGET_XML_FILES=hexagon-core.xml hexagon-hvx.xml hexagon-sys.xml
+TARGET_XML_FILES=hexagon-core.xml hexagon-hvx.xml hexagon-sys.xml
hexagon-hlx.xml
TARGET_LONG_BITS=32
TARGET_NOT_USING_LEGACY_LDST_PHYS_API=y
TARGET_NOT_USING_LEGACY_NATIVE_ENDIAN_API=y
diff --git a/gdbstub/gdb-xml/hexagon-hlx.xml b/gdbstub/gdb-xml/hexagon-hlx.xml
new file mode 100644
index 0000000000..91040762ea
--- /dev/null
+++ b/gdbstub/gdb-xml/hexagon-hlx.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+<!--
+ Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ SPDX-License-Identifier: GPL-2.0-or-later
+
+ LLDB uses fields that GDB can ignore. See:
+
https://github.com/llvm/llvm-project/blob/287aa6c4536408413b860e61fca0318a27214cf3/lldb/docs/lldb-gdb-remote.txt#L738-L860
+-->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.hexagon.hlx">
+
+ <!-- Sixteen 2048-byte HLX L-registers. -->
+ <vector id="hlx_ud" type="uint64" count="256"/>
+ <vector id="hlx_d" type="int64" count="256"/>
+ <vector id="hlx_uw" type="uint32" count="512"/>
+ <vector id="hlx_w" type="int32" count="512"/>
+ <vector id="hlx_uh" type="uint16" count="1024"/>
+ <vector id="hlx_h" type="int16" count="1024"/>
+ <vector id="hlx_ub" type="uint8" count="2048"/>
+ <vector id="hlx_b" type="int8" count="2048"/>
+ <union id="hlx_vec">
+ <field name="ud" type="hlx_ud"/>
+ <field name="d" type="hlx_d"/>
+ <field name="uw" type="hlx_uw"/>
+ <field name="w" type="hlx_w"/>
+ <field name="uh" type="hlx_uh"/>
+ <field name="h" type="hlx_h"/>
+ <field name="ub" type="hlx_ub"/>
+ <field name="b" type="hlx_b"/>
+ </union>
+
+ <!-- dwarf_regnums 124-139 follow HVX q0-q3. -->
+ <reg name="l0" bitsize="16384" offset="0" encoding="vector" format="hex" group="HLX
Vector Registers" dwarf_regnum="124"/>
+ <reg name="l1" bitsize="16384" offset="2048" encoding="vector" format="hex" group="HLX
Vector Registers" dwarf_regnum="125"/>
+ <reg name="l2" bitsize="16384" offset="4096" encoding="vector" format="hex" group="HLX
Vector Registers" dwarf_regnum="126"/>
+ <reg name="l3" bitsize="16384" offset="6144" encoding="vector" format="hex" group="HLX
Vector Registers" dwarf_regnum="127"/>
+ <reg name="l4" bitsize="16384" offset="8192" encoding="vector" format="hex" group="HLX
Vector Registers" dwarf_regnum="128"/>
+ <reg name="l5" bitsize="16384" offset="10240" encoding="vector" format="hex" group="HLX
Vector Registers" dwarf_regnum="129"/>
+ <reg name="l6" bitsize="16384" offset="12288" encoding="vector" format="hex" group="HLX
Vector Registers" dwarf_regnum="130"/>
+ <reg name="l7" bitsize="16384" offset="14336" encoding="vector" format="hex" group="HLX
Vector Registers" dwarf_regnum="131"/>
+ <reg name="l8" bitsize="16384" offset="16384" encoding="vector" format="hex" group="HLX
Vector Registers" dwarf_regnum="132"/>
+ <reg name="l9" bitsize="16384" offset="18432" encoding="vector" format="hex" group="HLX
Vector Registers" dwarf_regnum="133"/>
+ <reg name="l10" bitsize="16384" offset="20480" encoding="vector" format="hex" group="HLX
Vector Registers" dwarf_regnum="134"/>
+ <reg name="l11" bitsize="16384" offset="22528" encoding="vector" format="hex" group="HLX
Vector Registers" dwarf_regnum="135"/>
+ <reg name="l12" bitsize="16384" offset="24576" encoding="vector" format="hex" group="HLX
Vector Registers" dwarf_regnum="136"/>
+ <reg name="l13" bitsize="16384" offset="26624" encoding="vector" format="hex" group="HLX
Vector Registers" dwarf_regnum="137"/>
+ <reg name="l14" bitsize="16384" offset="28672" encoding="vector" format="hex" group="HLX
Vector Registers" dwarf_regnum="138"/>
+ <reg name="l15" bitsize="16384" offset="30720" encoding="vector" format="hex" group="HLX
Vector Registers" dwarf_regnum="139"/>
+
+</feature>
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index c3930ab4e4..dfa9e1d3af 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -540,6 +540,18 @@ static void hexagon_cpu_disas_set_info(const CPUState *cs,
info->target_info = &cpu->cfg;
}
+static bool hexagon_cpu_has_hlx(HexagonCPU *cpu)
+{
+ if (cpu->cfg.hex_def->hex_version < HEX_VER_V85) {
+ return false;
+ }
+#ifdef CONFIG_USER_ONLY
+ return true;
+#else
+ return cpu->hlx && cpu->hlx->num_contexts > 0;
+#endif
+}
+
static void hexagon_cpu_realize(DeviceState *dev, Error **errp)
{
CPUState *cs = CPU(dev);
@@ -559,6 +571,12 @@ static void hexagon_cpu_realize(DeviceState *dev, Error
**errp)
hexagon_hvx_gdb_write_register,
gdb_find_static_feature("hexagon-hvx.xml"));
+ if (hexagon_cpu_has_hlx(cpu)) {
+ gdb_register_coprocessor(cs, hexagon_hlx_gdb_read_register,
+ hexagon_hlx_gdb_write_register,
+ gdb_find_static_feature("hexagon-hlx.xml"));
+ }
+
#ifndef CONFIG_USER_ONLY
gdb_register_coprocessor(cs, hexagon_sys_gdb_read_register,
hexagon_sys_gdb_write_register,
diff --git a/target/hexagon/gdbstub.c b/target/hexagon/gdbstub.c
index 5b79e42c4d..1065f3a826 100644
--- a/target/hexagon/gdbstub.c
+++ b/target/hexagon/gdbstub.c
@@ -217,3 +217,49 @@ int hexagon_hvx_gdb_write_register(CPUState *cs, uint8_t
*mem_buf, int n)
g_assert_not_reached();
}
+
+int hexagon_hlx_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+{
+ CPUHexagonState *env = cpu_env(cs);
+ int total = 0;
+
+ BQL_LOCK_GUARD();
+
+ if (n < 0 || n >= NUM_LREGS) {
+ g_assert_not_reached();
+ }
+
+ /* Return zeroes when no HLX context is active. */
+ if (env->hlx_ctx == NULL) {
+ for (int i = 0; i < HLX_VEC_SIZE_BYTES; i++) {
+ g_byte_array_append(mem_buf, (const guint8 *)"\0", 1);
+ }
+ return HLX_VEC_SIZE_BYTES;
+ }
+
+ for (int i = 0; i < (int)ARRAY_SIZE(env->hlx_ctx->LRegs[n].uw); i++) {
+ total += gdb_get_reg32(mem_buf, env->hlx_ctx->LRegs[n].uw[i]);
+ }
+ return total;
+}
+
+int hexagon_hlx_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ CPUHexagonState *env = cpu_env(cs);
+ BQL_LOCK_GUARD();
+
+ if (n < 0 || n >= NUM_LREGS) {
+ g_assert_not_reached();
+ }
+
+ /* Ignore writes without an active context. */
+ if (env->hlx_ctx == NULL) {
+ return HLX_VEC_SIZE_BYTES;
+ }
+
+ for (int i = 0; i < (int)ARRAY_SIZE(env->hlx_ctx->LRegs[n].uw); i++) {
+ env->hlx_ctx->LRegs[n].uw[i] = ldl_le_p(mem_buf);
+ mem_buf += 4;
+ }
+ return HLX_VEC_SIZE_BYTES;
+}
diff --git a/target/hexagon/internal.h b/target/hexagon/internal.h
index 073de10284..6def331a83 100644
--- a/target/hexagon/internal.h
+++ b/target/hexagon/internal.h
@@ -24,6 +24,8 @@ int hexagon_gdb_read_register(CPUState *cpu, GByteArray *buf,
int reg);
int hexagon_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
int hexagon_hvx_gdb_read_register(CPUState *env, GByteArray *mem_buf, int n);
int hexagon_hvx_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n);
+int hexagon_hlx_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n);
+int hexagon_hlx_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n);
#ifndef CONFIG_USER_ONLY
int hexagon_sys_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n);
int hexagon_sys_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n);