Skip to content

Commit 4f0de6e

Browse files
committed
CI: Add CI job for testing
1 parent 44cc457 commit 4f0de6e

File tree

3 files changed

+181
-25
lines changed

3 files changed

+181
-25
lines changed

.github/workflows/hexagon-ci.yml

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
name: Hexagon QEMU CI
2+
3+
on:
4+
push:
5+
branches: [ master, hex-next ]
6+
pull_request:
7+
branches: [ master, hex-next ]
8+
workflow_dispatch:
9+
10+
jobs:
11+
build-and-test:
12+
name: ${{ matrix.os }}
13+
runs-on: ${{ matrix.os }}
14+
strategy:
15+
fail-fast: false
16+
matrix:
17+
include:
18+
- os: ubuntu-22.04
19+
target_list: hexagon-linux-user,hexagon-softmmu
20+
target_list_master: hexagon-linux-user
21+
- os: windows-latest
22+
target_list: hexagon-softmmu
23+
target_list_master: hexagon-softmmu
24+
25+
steps:
26+
- name: Checkout QEMU
27+
uses: actions/checkout@v4
28+
29+
# Ubuntu setup
30+
- name: Install Ubuntu dependencies
31+
if: runner.os == 'Linux'
32+
run: |
33+
sudo apt-get update
34+
sudo apt-get install -y \
35+
build-essential \
36+
ninja-build \
37+
pkg-config \
38+
libglib2.0-dev \
39+
libfdt-dev \
40+
libpixman-1-dev \
41+
libslirp-dev \
42+
python3-venv \
43+
python3-pip
44+
45+
# Windows setup
46+
- name: Setup MSYS2 for Windows
47+
if: runner.os == 'Windows'
48+
run: |
49+
# GitHub Actions Windows runners come with MSYS2 pre-installed
50+
# Update package database
51+
C:\msys64\usr\bin\bash.exe -lc "pacman --noconfirm -Sy"
52+
53+
# Install required packages
54+
C:\msys64\usr\bin\bash.exe -lc "pacman --noconfirm -S mingw-w64-x86_64-toolchain mingw-w64-x86_64-glib2 mingw-w64-x86_64-pixman mingw-w64-x86_64-pkgconf mingw-w64-x86_64-libslirp mingw-w64-x86_64-dtc mingw-w64-x86_64-ninja mingw-w64-x86_64-python3"
55+
56+
# Add MSYS2 to PATH
57+
echo "C:\msys64\mingw64\bin" >> $env:GITHUB_PATH
58+
echo "C:\msys64\usr\bin" >> $env:GITHUB_PATH
59+
60+
# Configure and build
61+
- name: Configure QEMU (Ubuntu)
62+
if: runner.os == 'Linux'
63+
run: |
64+
mkdir build
65+
cd build
66+
TARGET_LIST=${{ github.ref == 'refs/heads/master' && matrix.target_list_master || matrix.target_list }}
67+
../configure \
68+
--target-list=$TARGET_LIST \
69+
--enable-slirp \
70+
--enable-fdt \
71+
--enable-plugins \
72+
--disable-docs
73+
74+
- name: Configure QEMU (Windows)
75+
if: runner.os == 'Windows'
76+
run: |
77+
C:\msys64\usr\bin\bash.exe -lc "export PATH=/mingw64/bin:\$PATH && cd '${{ github.workspace }}' && mkdir build && cd build && TARGET_LIST=${{ github.ref == 'refs/heads/master' && matrix.target_list_master || matrix.target_list }} && ../configure --target-list=\$TARGET_LIST --enable-slirp --enable-fdt --enable-plugins --disable-docs --cross-prefix=x86_64-w64-mingw32-"
78+
79+
- name: Build QEMU (Ubuntu)
80+
if: runner.os == 'Linux'
81+
run: |
82+
cd build
83+
ninja
84+
85+
- name: Build QEMU (Windows)
86+
if: runner.os == 'Windows'
87+
run: |
88+
C:\msys64\usr\bin\bash.exe -lc "export PATH=/mingw64/bin:\$PATH && cd '${{ github.workspace }}/build' && ninja"
89+
90+
# Test hexagon-linux-user (Ubuntu only)
91+
- name: Test hexagon-linux-user
92+
if: runner.os == 'Linux'
93+
run: |
94+
cd build
95+
make check-tcg
96+
97+
# Test hexagon-softmmu (Ubuntu)
98+
- name: Test hexagon-softmmu (Ubuntu)
99+
if: runner.os == 'Linux'
100+
run: |
101+
cd build
102+
make check-functional
103+
104+
# Test hexagon-softmmu (Windows)
105+
- name: Test hexagon-softmmu (Windows)
106+
if: runner.os == 'Windows'
107+
run: |
108+
C:\msys64\usr\bin\bash.exe -lc "export PATH=/mingw64/bin:\$PATH && cd '${{ github.workspace }}/build' && make check-functional"
109+
110+
# Upload test logs
111+
- name: Upload test logs
112+
if: always()
113+
uses: actions/upload-artifact@v4
114+
with:
115+
name: test-logs-${{ matrix.os }}
116+
path: |
117+
build/tests/results/
118+
build/meson-logs/
119+
build/**/*.log
120+
retention-days: 7

target/hexagon/cpu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ typedef struct CPUArchState {
144144
target_ulong k0_lock_count;
145145
CPUHexagonTLBContext *hex_tlb;
146146
GList *dir_list;
147+
GHashTable *dir_paths;
147148
#endif
148149
target_ulong next_PC;
149150
target_ulong new_value_usr;

target/hexagon/hexswi.c

Lines changed: 60 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -635,55 +635,87 @@ static void sim_handle_trap0(CPUHexagonState *env)
635635

636636
case HEX_SYS_OPENDIR:
637637
{
638-
DIR *dir;
639-
char buf[BUFSIZ];
638+
char dir_path[BUFSIZ];
639+
GDir *dir;
640+
GError *gerr = NULL;
640641
int rc = 0, err = 0;
641642

643+
/* Read directory path string, following arch-independent pattern */
642644
int i = 0;
643645
do {
644-
hexagon_read_memory(env, swi_info + i, 1, &buf[i], retaddr);
646+
hexagon_read_memory(env, swi_info + i, 1, &dir_path[i], retaddr);
645647
i++;
646-
} while (buf[i - 1]);
648+
if (i >= BUFSIZ - 1) {
649+
semi_cb(cs, -1, ENAMETOOLONG);
650+
return;
651+
}
652+
} while (dir_path[i - 1]);
647653

648-
dir = opendir(buf);
654+
dir = g_dir_open(dir_path, 0, &gerr);
649655
if (dir != NULL) {
656+
/* Initialize dir_paths hash table if not already done */
657+
if (!env->dir_paths) {
658+
env->dir_paths = g_hash_table_new_full(g_direct_hash, g_direct_equal,
659+
NULL, g_free);
660+
}
661+
/* Store the directory path for later use in readdir */
662+
g_hash_table_insert(env->dir_paths, dir, g_strdup(dir_path));
650663
env->dir_list = g_list_append(env->dir_list, dir);
651664
rc = g_list_index(env->dir_list, dir) + DIR_INDEX_OFFSET;
652665
} else {
653-
err = errno;
666+
err = gerr ? gerr->code : ENOENT;
667+
if (gerr) {
668+
g_error_free(gerr);
669+
}
654670
}
655671
semi_cb(cs, rc, rc != 0 ? 0 : err);
656672
break;
657673
}
658674

659675
case HEX_SYS_READDIR:
660676
{
661-
struct dirent *host_dir_entry = NULL;
677+
const gchar *entry_name = NULL;
662678
int dir_index = swi_info - DIR_INDEX_OFFSET;
663-
DIR *dir = g_list_nth_data(env->dir_list, dir_index);
679+
GDir *dir = g_list_nth_data(env->dir_list, dir_index);
664680
uint32_t rc = 0, err = 0;
665681

666682
if (dir) {
667-
errno = 0;
668-
host_dir_entry = readdir(dir);
669-
if (host_dir_entry == NULL) {
670-
err = errno;
683+
entry_name = g_dir_read_name(dir);
684+
if (entry_name == NULL) {
685+
err = 0; /* End of directory */
671686
}
672687
} else {
673688
err = EBADF;
674689
}
675690

676-
if (host_dir_entry) {
691+
if (entry_name) {
677692
uint32_t guest_dir_entry = arch_get_thread_reg(env, HEX_REG_R02);
678-
hexagon_write_memory(env, guest_dir_entry, 4, host_dir_entry->d_ino,
679-
retaddr);
680-
for (int i = 0; i < sizeof(host_dir_entry->d_name); i++) {
681-
hexagon_write_memory(env, guest_dir_entry + 4 + i, 1,
682-
host_dir_entry->d_name[i], retaddr);
683-
if (!host_dir_entry->d_name[i]) {
684-
break;
693+
uint32_t ino = 1; /* Default fallback */
694+
695+
const char *dir_path = g_hash_table_lookup(env->dir_paths, dir);
696+
if (dir_path) {
697+
char *full_path = g_build_filename(dir_path, entry_name, NULL);
698+
if (full_path) {
699+
struct stat st;
700+
if (stat(full_path, &st) == 0) {
701+
if (st.st_ino != (uint32_t)st.st_ino) {
702+
g_free(full_path);
703+
semi_cb(cs, -1, EOVERFLOW);
704+
break;
705+
}
706+
ino = (uint32_t)st.st_ino;
707+
}
708+
g_free(full_path);
685709
}
686710
}
711+
712+
hexagon_write_memory(env, guest_dir_entry, 4, ino, retaddr);
713+
714+
int name_len = strlen(entry_name) + 1;
715+
for (int i = 0; i < name_len; i++) {
716+
hexagon_write_memory(env, guest_dir_entry + 4 + i, 1,
717+
entry_name[i], retaddr);
718+
}
687719
rc = guest_dir_entry;
688720
}
689721
semi_cb(cs, rc, err);
@@ -692,16 +724,19 @@ static void sim_handle_trap0(CPUHexagonState *env)
692724

693725
case HEX_SYS_CLOSEDIR:
694726
{
695-
DIR *dir;
696-
int ret = -1, err;
727+
GDir *dir;
728+
int ret = -1, err = 0;
697729
int dir_index = swi_info - DIR_INDEX_OFFSET;
698730

699731
dir = g_list_nth_data(env->dir_list, dir_index);
700732
if (dir != NULL) {
701-
ret = closedir(dir);
702-
if (ret != 0) {
703-
err = errno;
733+
/* Remove from hash table before closing */
734+
if (env->dir_paths) {
735+
g_hash_table_remove(env->dir_paths, dir);
704736
}
737+
g_dir_close(dir);
738+
env->dir_list = g_list_remove(env->dir_list, dir);
739+
ret = 0;
705740
} else {
706741
err = EBADF;
707742
}

0 commit comments

Comments
 (0)