@@ -98,14 +98,11 @@ static DeviceState *tlb_create(HexagonCommonMachineState *hms,
return tlb;
}
-static DeviceState *cluster_create(HexagonCommonMachineState *hms)
+static void cluster_create(HexagonCommonMachineState *hms)
{
- DeviceState *cluster = qdev_new(TYPE_CPU_CLUSTER);
-
- object_property_add_child(OBJECT(hms), "cluster", OBJECT(cluster));
- qdev_prop_set_uint32(cluster, "cluster-id", 0);
-
- return cluster;
+ object_initialize_child(OBJECT(hms), "cluster", &hms->cluster,
+ TYPE_HEXAGON_CLUSTER_STATE);
+ qdev_prop_set_uint32(DEVICE(&hms->cluster), "cluster-id", 0);
}
void hex_subsys_create(HexagonCommonMachineState *hms,
@@ -135,7 +132,7 @@ void hex_subsys_create(HexagonCommonMachineState *hms,
&hms->vtcm);
}
- hms->cluster = cluster_create(hms);
+ cluster_create(hms);
hms->l2vic = l2vic_create(hms, m_cfg);
hms->qtimer = qtimer_create(hms, m_cfg);
hms->glob_regs = globalreg_create(hms, m_cfg, rev);
@@ -144,7 +141,7 @@ void hex_subsys_create(HexagonCommonMachineState *hms,
void hex_subsys_add_cpu(HexagonCommonMachineState *hms, DeviceState *cpu)
{
- object_property_add_child(OBJECT(hms->cluster), "cpu[*]", OBJECT(cpu));
+ object_property_add_child(OBJECT(&hms->cluster), "cpu[*]", OBJECT(cpu));
object_property_set_link(OBJECT(cpu), "global-regs",
OBJECT(hms->glob_regs), &error_fatal);
object_property_set_link(OBJECT(cpu), "tlb", OBJECT(hms->tlb),
@@ -158,10 +155,10 @@ void hex_subsys_realize_cluster(HexagonCommonMachineState *hms)
/*
* The cluster must be realized after its CPUs have been parented into it
* (see hex_subsys_add_cpu()) but before any CPU is itself realized, since
- * qdev_realize_and_unref() on a CPU latches cluster_index into the TCG
+ * qdev_realize() on a CPU latches cluster_index into the TCG
* cflags at that point.
*/
- qdev_realize_and_unref(hms->cluster, NULL, &error_fatal);
+ qdev_realize(DEVICE(&hms->cluster), NULL, &error_fatal);
}
void hex_subsys_realize_cpu(HexagonCommonMachineState *hms, DeviceState *cpu,
@@ -173,3 +170,16 @@ void hex_subsys_realize_cpu(HexagonCommonMachineState *hms, DeviceState *cpu,
l2vic_connect_cpu(hms->l2vic, cpu);
}
}
+
+static const TypeInfo hexagon_cluster_type_info = {
+ .name = TYPE_HEXAGON_CLUSTER_STATE,
+ .parent = TYPE_CPU_CLUSTER,
+ .instance_size = sizeof(HexagonClusterState),
+};
+
+static void hexagon_cluster_register_types(void)
+{
+ type_register_static(&hexagon_cluster_type_info);
+}
+
+type_init(hexagon_cluster_register_types)
@@ -11,6 +11,7 @@
#include "system/memory.h"
#include "hw/core/boards.h"
+#include "hw/cpu/cluster.h"
struct hexagon_board_boot_info {
uint64_t ram_size;
@@ -148,6 +149,17 @@ struct hexagon_machine_config {
union hexagon_config_table cfgtable;
};
+#define TYPE_HEXAGON_CLUSTER_STATE "hexagon-cluster-state"
+OBJECT_DECLARE_SIMPLE_TYPE(HexagonClusterState, HEXAGON_CLUSTER_STATE)
+
+struct HexagonClusterState {
+ CPUClusterState parent_obj;
+
+ struct {
+ GList *dir_list;
+ } semihosting;
+};
+
#define TYPE_HEXAGON_COMMON_MACHINE "hexagon-common-machine"
OBJECT_DECLARE_SIMPLE_TYPE(HexagonCommonMachineState, HEXAGON_COMMON_MACHINE)
@@ -157,7 +169,7 @@ struct HexagonCommonMachineState {
MemoryRegion ram;
MemoryRegion cfgtable_rom;
MemoryRegion vtcm;
- DeviceState *cluster;
+ HexagonClusterState cluster;
DeviceState *l2vic;
DeviceState *qtimer;
DeviceState *glob_regs;
@@ -19,6 +19,7 @@
#include "hex_mmu.h"
#include "hexswi.h"
#include "hw/hexagon/hexagon_globalreg.h"
+#include "hw/hexagon/hexagon.h"
#ifdef CONFIG_USER_ONLY
#error "This file is only used in system emulation"
@@ -30,6 +31,9 @@
#include "semihosting/guestfd.h"
#include "system/runstate.h"
+/* We start from 1 as 0 is used to signal an error from opendir() */
+static const int DIR_INDEX_OFFSET = 1;
+
/* non-arm-compatible semihosting calls */
#define HEXAGON_SPECIFIC_SWI_FLAGS \
DEF_SWI_FLAG(OPEN, 0x01) \
@@ -375,6 +379,13 @@ static void coredump(CPUHexagonState *env)
qemu_log_unlock(f);
}
+static GList **hex_semihosting_dir_list(CPUHexagonState *env)
+{
+ HexagonCPU *cpu = env_archcpu(env);
+ HexagonClusterState *cluster = HEXAGON_CLUSTER_STATE(OBJECT(cpu)->parent);
+ return &cluster->semihosting.dir_list;
+}
+
static void sim_handle_trap0(CPUHexagonState *env)
{
target_ulong what_swi, swi_info;
@@ -644,6 +655,89 @@ static void sim_handle_trap0(CPUHexagonState *env)
}
break;
+ case HEX_SYS_OPENDIR:
+ {
+ DIR *dir;
+ char buf[BUFSIZ];
+ int rc = 0, err = 0;
+ int i = 0;
+
+ do {
+ hexagon_read_memory(env, swi_info + i, 1, &buf[i], retaddr);
+ i++;
+ } while ((i < BUFSIZ) && buf[i - 1]);
+
+ if (buf[i - 1]) {
+ err = ENAMETOOLONG;
+ } else {
+ GList **dir_list = hex_semihosting_dir_list(env);
+ dir = opendir(buf);
+ if (dir != NULL) {
+ *dir_list = g_list_append(*dir_list, dir);
+ rc = g_list_index(*dir_list, dir) + DIR_INDEX_OFFSET;
+ } else {
+ err = errno;
+ }
+ }
+ common_semi_cb(cs, rc, rc != 0 ? 0 : err);
+ break;
+ }
+
+ case HEX_SYS_READDIR:
+ {
+ struct dirent *host_dir_entry = NULL;
+ int dir_index = swi_info - DIR_INDEX_OFFSET;
+ GList **dir_list = hex_semihosting_dir_list(env);
+ DIR *dir = g_list_nth_data(*dir_list, dir_index);
+ uint32_t rc = 0, err = 0;
+
+ if (dir) {
+ errno = 0;
+ host_dir_entry = readdir(dir);
+ if (host_dir_entry == NULL) {
+ err = errno;
+ }
+ } else {
+ err = EBADF;
+ }
+
+ if (host_dir_entry) {
+ uint32_t guest_dir_entry = env->gpr[HEX_REG_R02];
+ hexagon_write_memory(env, guest_dir_entry, 4, host_dir_entry->d_ino,
+ retaddr);
+ for (int i = 0; i < sizeof(host_dir_entry->d_name); i++) {
+ hexagon_write_memory(env, guest_dir_entry + 4 + i, 1,
+ host_dir_entry->d_name[i], retaddr);
+ if (!host_dir_entry->d_name[i]) {
+ break;
+ }
+ }
+ rc = guest_dir_entry;
+ }
+ common_semi_cb(cs, rc, err);
+ break;
+ }
+
+ case HEX_SYS_CLOSEDIR:
+ {
+ DIR *dir;
+ int ret = -1, err = 0;
+ int dir_index = swi_info - DIR_INDEX_OFFSET;
+ GList **dir_list = hex_semihosting_dir_list(env);
+
+ dir = g_list_nth_data(*dir_list, dir_index);
+ if (dir != NULL) {
+ ret = closedir(dir);
+ if (ret != 0) {
+ err = errno;
+ }
+ } else {
+ err = EBADF;
+ }
+ common_semi_cb(cs, ret, ret == 0 ? 0 : err);
+ break;
+ }
+
case HEX_SYS_COREDUMP:
coredump(env);
break;
@@ -7,6 +7,7 @@
import re
import time
import unittest
+from pathlib import Path
from qemu_test import QemuSystemTest, Asset, wait_for_console_pattern
@@ -90,5 +91,13 @@ def test_access(self):
def test_semihost(self):
self.run_console_pattern("semihost", "PASS", "-append", "arg1", "arg2")
+ def test_dirent(self):
+ testdir = Path(self.scratch_file("_testdir_dirent"))
+ testdir.mkdir()
+ files = [".", "..", "file1", "file2"]
+ for f in files:
+ testdir.joinpath(f).touch()
+ self.run_console_pattern("dirent", " ".join(files), "-append", str(testdir))
+
if __name__ == "__main__":
QemuSystemTest.main()