wip
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
# Known Issues
|
||||
|
||||
## SD reads can corrupt guest memory
|
||||
|
||||
Opening `/Test/example.txt` can panic consistently:
|
||||
|
||||
```text
|
||||
Invalid read at addr 0x253D7474, size 4, region '(null)'
|
||||
Guru Meditation Error: Core 0 panic'ed (Load access fault)
|
||||
```
|
||||
|
||||
The fault occurs in `spiTransferByteNL()` after the `SdSpiCard` SPI pointer at `0x3fc94b40` becomes `0x253D7474`, which resembles file data. The crash is deterministic with the directory-backed `vvfat` card. A raw FAT32 diagnostic image fails to mount, so it has not yet provided a clean backend comparison.
|
||||
|
||||
The crash dump also shows `SdSpiCard::readData()` reaching its CRC reads while its destination pointer and end pointer differ. Keeping conditional translation blocks on TCI did not fix the corruption. The next diagnostic build keeps guest-store TBs on TCI and watches writes to `0x3fc94b40`–`0x3fc94b57`.
|
||||
|
||||
## SD card can remain in `receivingdata`
|
||||
|
||||
The SD model can become stuck after an incomplete `CMD24` write:
|
||||
|
||||
```text
|
||||
SPI: CMD17 in a wrong state: receivingdata (spec v3.01)
|
||||
SPI: CMD24 in a wrong state: receivingdata (spec v3.01)
|
||||
```
|
||||
|
||||
Subsequent reads and writes then fail. This may be related to the guest-memory corruption, but remains tracked separately until the first incomplete transfer is identified.
|
||||
|
||||
## Reader page can render completely black
|
||||
|
||||
Opening a generated crash report can appear to work—the Back button returns normally and the file is marked as read—but the reader page is entirely black.
|
||||
|
||||
This is likely an e-ink model issue where an intermediate all-black waveform phase is exposed instead of the completed frame. It is separate from the SD pointer panic.
|
||||
|
||||
## Cold boot requires a manual power-button hold
|
||||
|
||||
If the power button is not held until the Booting icon appears, the firmware can enter an unwanted watchdog reboot path:
|
||||
|
||||
```text
|
||||
Guru Meditation Error: Core 0 panic'ed (Interrupt wdt timeout on CPU0)
|
||||
```
|
||||
|
||||
The emulator should model a cold-boot power hold and release automatically rather than requiring precisely timed user input. The preceding NVS `NOT_FOUND` messages are expected first-boot initialization noise.
|
||||
|
||||
## WASM heap balloons after watchdog reboot
|
||||
|
||||
The committed WASM heap starts near 176.3 MiB but can grow to approximately 631.8 MiB after the watchdog reboot described above.
|
||||
|
||||
This indicates translated-block or dynamic WebAssembly module state is retained across guest reboot. TB cleanup must release old dynamic instances during reset; reboot-time growth should remain bounded.
|
||||
@@ -6,10 +6,14 @@ SD_SRC ?= $(FIRMWARE_REPO)/sdcard
|
||||
QEMU_SRC ?= _scratch/qemu-src
|
||||
QEMU_BIN = $(QEMU_SRC)/build/qemu-system-riscv32
|
||||
QEMU_WASM_SRC ?= _scratch/qemu-wasm-src
|
||||
# Working tree for the fast dev loop: edit here, `make web-dev` compiles it incrementally.
|
||||
DEV_SRC ?= _scratch/qemu-fix-src
|
||||
# Commit the 0002 patch is diffed against when running `make patch`.
|
||||
PATCH_BASE ?= 610f8c69bc91dcb4ba81de1b7d2e74cc2adfb31e
|
||||
WASM_OUT ?= dist/wasm
|
||||
VARIANT ?= x3
|
||||
|
||||
.PHONY: firmware sdimage qemu qemu-wasm web web-test run run-upstream chip clean
|
||||
.PHONY: firmware sdimage qemu qemu-wasm qemu-wasm-dev web web-dev web-test patch run run-upstream chip clean
|
||||
|
||||
firmware:
|
||||
esptool --chip esp32c3 merge-bin -o flash.bin \
|
||||
@@ -29,11 +33,23 @@ qemu:
|
||||
qemu-wasm:
|
||||
QEMU_WASM_SRC=$(QEMU_WASM_SRC) WASM_OUT=$(WASM_OUT) scripts/build-qemu-wasm.sh
|
||||
|
||||
# Incremental build straight from $(DEV_SRC); no patch reset, so edits compile fast.
|
||||
qemu-wasm-dev:
|
||||
QEMU_WASM_DEV=1 QEMU_WASM_SRC=$(DEV_SRC) WASM_OUT=$(WASM_OUT) scripts/build-qemu-wasm.sh
|
||||
|
||||
# Regenerate the wasm patch from $(DEV_SRC) once the dev tree is where you want it.
|
||||
patch:
|
||||
cd $(DEV_SRC) && git diff --binary $(PATCH_BASE) > $(CURDIR)/qemu/patches/0002-qemu-wasm.patch
|
||||
|
||||
# Serve over HTTPS by default so headless/LAN access is cross-origin isolated. Override with WEB_TLS=.
|
||||
WEB_TLS ?= --tls
|
||||
web: qemu-wasm
|
||||
python3 scripts/serve-web.py $(WEB_TLS)
|
||||
|
||||
# Fast iteration: incremental compile from $(DEV_SRC), then serve. Run `make patch` before committing.
|
||||
web-dev: qemu-wasm-dev
|
||||
python3 scripts/serve-web.py $(WEB_TLS)
|
||||
|
||||
web-test:
|
||||
node scripts/test-web.mjs
|
||||
|
||||
|
||||
@@ -303,7 +303,7 @@ index 90fa54352c..0fa9cc31b6 100644
|
||||
/*
|
||||
* parse_zone - Fill a zone descriptor
|
||||
diff --git c/block/vvfat.c w/block/vvfat.c
|
||||
index 8ffe8b3b9b..4cf02d9a55 100644
|
||||
index 8ffe8b3b9b..3c0ab6c228 100644
|
||||
--- c/block/vvfat.c
|
||||
+++ w/block/vvfat.c
|
||||
@@ -749,6 +749,7 @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
|
||||
@@ -353,7 +353,7 @@ index 8ffe8b3b9b..4cf02d9a55 100644
|
||||
s->directory.next < s->root_entries) {
|
||||
/* root directory */
|
||||
int cur = s->directory.next;
|
||||
@@ -877,20 +878,24 @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
|
||||
@@ -877,20 +878,29 @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
|
||||
* 0x20 / s->cluster_size;
|
||||
mapping->end = first_cluster;
|
||||
|
||||
@@ -370,7 +370,12 @@ index 8ffe8b3b9b..4cf02d9a55 100644
|
||||
static inline int32_t sector2cluster(BDRVVVFATState* s,off_t sector_num)
|
||||
{
|
||||
- return (sector_num - s->offset_to_root_dir) / s->sectors_per_cluster;
|
||||
+ return (sector_num - s->offset_to_root_dir) / s->sectors_per_cluster
|
||||
+ off_t relative_sector = sector_num - s->offset_to_root_dir;
|
||||
+
|
||||
+ if (relative_sector < 0) {
|
||||
+ return -1 - (-relative_sector - 1) / s->sectors_per_cluster;
|
||||
+ }
|
||||
+ return relative_sector / s->sectors_per_cluster
|
||||
+ + (s->fat_type == 32 ? 2 : 0);
|
||||
}
|
||||
|
||||
@@ -382,7 +387,7 @@ index 8ffe8b3b9b..4cf02d9a55 100644
|
||||
}
|
||||
|
||||
static int init_directories(BDRVVVFATState* s,
|
||||
@@ -934,11 +939,12 @@ static int init_directories(BDRVVVFATState* s,
|
||||
@@ -934,11 +944,12 @@ static int init_directories(BDRVVVFATState* s,
|
||||
init_fat(s);
|
||||
|
||||
/* TODO: if there are more entries, bootsector has to be adjusted! */
|
||||
@@ -397,7 +402,7 @@ index 8ffe8b3b9b..4cf02d9a55 100644
|
||||
mapping->dir_index = 0;
|
||||
mapping->info.dir.parent_mapping_index = -1;
|
||||
mapping->first_mapping_index = -1;
|
||||
@@ -950,11 +956,10 @@ static int init_directories(BDRVVVFATState* s,
|
||||
@@ -950,11 +961,10 @@ static int init_directories(BDRVVVFATState* s,
|
||||
mapping->read_only = 0;
|
||||
s->path = mapping->path;
|
||||
|
||||
@@ -413,7 +418,7 @@ index 8ffe8b3b9b..4cf02d9a55 100644
|
||||
mapping = array_get(&(s->mapping), i);
|
||||
|
||||
if (mapping->mode & MODE_DIRECTORY) {
|
||||
@@ -1026,22 +1031,35 @@ static int init_directories(BDRVVVFATState* s,
|
||||
@@ -1026,22 +1036,35 @@ static int init_directories(BDRVVVFATState* s,
|
||||
/* media descriptor: hard disk=0xf8, floppy=0xf0 */
|
||||
bootsector->media_type = (s->offset_to_bootsector > 0 ? 0xf8 : 0xf0);
|
||||
s->fat.pointer[0] = bootsector->media_type;
|
||||
@@ -460,7 +465,7 @@ index 8ffe8b3b9b..4cf02d9a55 100644
|
||||
bootsector->magic[0]=0x55; bootsector->magic[1]=0xaa;
|
||||
|
||||
return 0;
|
||||
@@ -1139,6 +1157,7 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
@@ -1139,6 +1162,7 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
{
|
||||
BDRVVVFATState *s = bs->opaque;
|
||||
int cyls, heads, secs;
|
||||
@@ -468,7 +473,7 @@ index 8ffe8b3b9b..4cf02d9a55 100644
|
||||
bool floppy;
|
||||
const char *dirname, *label;
|
||||
QemuOpts *opts;
|
||||
@@ -1205,7 +1224,9 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
@@ -1205,7 +1229,9 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
|
||||
switch (s->fat_type) {
|
||||
case 32:
|
||||
@@ -478,7 +483,7 @@ index 8ffe8b3b9b..4cf02d9a55 100644
|
||||
break;
|
||||
case 16:
|
||||
case 12:
|
||||
@@ -1219,8 +1240,17 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
@@ -1219,8 +1245,17 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
|
||||
s->bs = bs;
|
||||
|
||||
@@ -498,7 +503,7 @@ index 8ffe8b3b9b..4cf02d9a55 100644
|
||||
|
||||
s->current_cluster=0xffffffff;
|
||||
|
||||
@@ -1232,8 +1262,8 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
@@ -1232,8 +1267,8 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
DLOG(fprintf(stderr, "vvfat %s chs %d,%d,%d\n",
|
||||
dirname, cyls, heads, secs));
|
||||
|
||||
@@ -509,16 +514,123 @@ index 8ffe8b3b9b..4cf02d9a55 100644
|
||||
|
||||
if (qemu_opt_get_bool(opts, "rw", false)) {
|
||||
if (!bdrv_is_read_only(bs)) {
|
||||
@@ -1523,7 +1553,8 @@ vvfat_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sector
|
||||
@@ -1259,8 +1294,7 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
- s->sector_count = s->offset_to_root_dir
|
||||
- + s->sectors_per_cluster * s->cluster_count;
|
||||
+ s->sector_count = cluster2sector(s, s->cluster_count);
|
||||
|
||||
/* Disable migration when vvfat is used rw */
|
||||
if (s->qcow) {
|
||||
@@ -1415,6 +1449,7 @@ read_cluster_directory:
|
||||
if(lseek(s->current_fd, offset, SEEK_SET)!=offset)
|
||||
return -3;
|
||||
s->cluster=s->cluster_buffer;
|
||||
+ memset(s->cluster, 0, s->cluster_size);
|
||||
result=read(s->current_fd,s->cluster,s->cluster_size);
|
||||
if(result<0) {
|
||||
s->current_cluster = -1;
|
||||
@@ -1523,8 +1558,9 @@ vvfat_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sector
|
||||
} else {
|
||||
uint32_t sector = sector_num - s->offset_to_root_dir,
|
||||
sector_offset_in_cluster=(sector%s->sectors_per_cluster),
|
||||
- cluster_num=sector/s->sectors_per_cluster;
|
||||
- if(cluster_num > s->cluster_count || read_cluster(s, cluster_num) != 0) {
|
||||
+ cluster_num=sector/s->sectors_per_cluster
|
||||
+ + (s->fat_type == 32 ? 2 : 0);
|
||||
if(cluster_num > s->cluster_count || read_cluster(s, cluster_num) != 0) {
|
||||
+ if(cluster_num >= s->cluster_count || read_cluster(s, cluster_num) != 0) {
|
||||
/* LATER TODO: strict: return -1; */
|
||||
memset(buf+i*0x200,0,0x200);
|
||||
continue;
|
||||
@@ -1780,7 +1816,8 @@ static int parse_short_name(BDRVVVFATState* s,
|
||||
static inline uint32_t modified_fat_get(BDRVVVFATState* s,
|
||||
unsigned int cluster)
|
||||
{
|
||||
- if (cluster < s->last_cluster_of_root_directory) {
|
||||
+ if (s->fat_type != 32 &&
|
||||
+ cluster < s->last_cluster_of_root_directory) {
|
||||
if (cluster + 1 == s->last_cluster_of_root_directory)
|
||||
return s->max_fat_value;
|
||||
else
|
||||
@@ -2182,14 +2219,17 @@ DLOG(checkpoint());
|
||||
mapping->mode |= MODE_DELETED;
|
||||
}
|
||||
|
||||
- used_clusters_count = check_directory_consistency(s, 0, s->path);
|
||||
+ mapping_t *root_mapping = array_get(&(s->mapping), 0);
|
||||
+ used_clusters_count = check_directory_consistency(s,
|
||||
+ root_mapping->begin, s->path);
|
||||
if (used_clusters_count <= 0) {
|
||||
DLOG(fprintf(stderr, "problem in directory\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
- check = s->last_cluster_of_root_directory;
|
||||
- for (i = check; i < sector2cluster(s, s->sector_count); i++) {
|
||||
+ check = s->fat_type == 32 ? 0 : s->last_cluster_of_root_directory;
|
||||
+ for (i = s->fat_type == 32 ? 2 : check;
|
||||
+ i < sector2cluster(s, s->sector_count); i++) {
|
||||
if (modified_fat_get(s, i)) {
|
||||
if(!s->used_clusters[i]) {
|
||||
DLOG(fprintf(stderr, "FAT was modified (%d), but cluster is not used?\n", i));
|
||||
@@ -2417,7 +2457,10 @@ static int coroutine_fn GRAPH_RDLOCK
|
||||
commit_direntries(BDRVVVFATState* s, int dir_index, int parent_mapping_index)
|
||||
{
|
||||
direntry_t* direntry = array_get(&(s->directory), dir_index);
|
||||
- uint32_t first_cluster = dir_index == 0 ? 0 : begin_of_direntry(direntry);
|
||||
+ bool is_root = dir_index == 0;
|
||||
+ mapping_t *root_mapping = array_get(&(s->mapping), 0);
|
||||
+ uint32_t first_cluster = is_root ? root_mapping->begin :
|
||||
+ begin_of_direntry(direntry);
|
||||
mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
|
||||
int factor = 0x10 * s->sectors_per_cluster;
|
||||
int old_cluster_count, new_cluster_count;
|
||||
@@ -2440,7 +2483,7 @@ commit_direntries(BDRVVVFATState* s, int dir_index, int parent_mapping_index)
|
||||
first_dir_index = current_dir_index;
|
||||
mapping->info.dir.parent_mapping_index = parent_mapping_index;
|
||||
|
||||
- if (first_cluster == 0) {
|
||||
+ if (is_root && s->fat_type != 32) {
|
||||
old_cluster_count = new_cluster_count =
|
||||
s->last_cluster_of_root_directory;
|
||||
} else {
|
||||
@@ -2998,11 +3041,9 @@ DLOG(checkpoint());
|
||||
*/
|
||||
unsigned char *bootsector = s->first_sectors
|
||||
+ s->offset_to_bootsector * 0x200;
|
||||
- /*
|
||||
- * LATER TODO: if FAT32, this is wrong (see init_directories(),
|
||||
- * which always creates a FAT16 bootsector)
|
||||
- */
|
||||
- const int reserved1_offset = offsetof(bootsector_t, u.fat16.reserved1);
|
||||
+ const int reserved1_offset = s->fat_type == 32 ?
|
||||
+ offsetof(bootsector_t, u.fat32.reserved1) :
|
||||
+ offsetof(bootsector_t, u.fat16.reserved1);
|
||||
|
||||
for (i = 0; i < 0x200; i++) {
|
||||
if (i != reserved1_offset && bootsector[i] != buf[i]) {
|
||||
@@ -3057,8 +3098,8 @@ DLOG(checkpoint());
|
||||
begin = sector_num;
|
||||
if (end > sector_num + nb_sectors)
|
||||
end = sector_num + nb_sectors;
|
||||
- dir_index = mapping->dir_index +
|
||||
- 0x10 * (begin - mapping->begin * s->sectors_per_cluster);
|
||||
+ dir_index = mapping->info.dir.first_dir_index +
|
||||
+ 0x10 * (begin - cluster2sector(s, mapping->begin));
|
||||
direntries = (direntry_t*)(buf + 0x200 * (begin - sector_num));
|
||||
|
||||
for (k = 0; k < (end - begin) * 0x10; k++) {
|
||||
@@ -3093,7 +3134,7 @@ DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sec
|
||||
}
|
||||
|
||||
for (i = first_cluster; i <= last_cluster; i++) {
|
||||
- if (i >= 0) {
|
||||
+ if (i >= 0 && i < sector2cluster(s, s->sector_count)) {
|
||||
s->used_clusters[i] |= USED_ALLOCATED;
|
||||
}
|
||||
}
|
||||
diff --git c/configs/devices/riscv32-softmmu/xteink.mak w/configs/devices/riscv32-softmmu/xteink.mak
|
||||
new file mode 100644
|
||||
index 0000000000..a9179b4119
|
||||
@@ -1135,6 +1247,21 @@ index c1376b7299..1275808dc0 100644
|
||||
{
|
||||
level_shared |= 1;
|
||||
}
|
||||
diff --git c/hw/sd/ssi-sd.c w/hw/sd/ssi-sd.c
|
||||
index 552dc2c8ea..eb12207897 100644
|
||||
--- c/hw/sd/ssi-sd.c
|
||||
+++ w/hw/sd/ssi-sd.c
|
||||
@@ -162,6 +162,10 @@ static uint32_t ssi_sd_transfer(SSIPeripheral *dev, uint32_t val)
|
||||
return SSI_DUMMY;
|
||||
}
|
||||
|
||||
+ if ((val & 0xc0) != 0x40) {
|
||||
+ DPRINTF("Ignore non-command byte 0x%02x\n", val);
|
||||
+ return SSI_DUMMY;
|
||||
+ }
|
||||
s->cmd = val & 0x3f;
|
||||
s->mode = SSI_SD_CMDARG;
|
||||
s->arglen = 0;
|
||||
diff --git c/include/exec/exec-all.h w/include/exec/exec-all.h
|
||||
index 2e4c4cc4b4..99e6da08c9 100644
|
||||
--- c/include/exec/exec-all.h
|
||||
@@ -1616,7 +1743,7 @@ index 478ec051c4..41895c68fa 100644
|
||||
need_prot |= host_prot_read_exec();
|
||||
}
|
||||
diff --git c/tcg/tcg.c w/tcg/tcg.c
|
||||
index 6dc3072f92..214e66e9d6 100644
|
||||
index 6dc3072f92..0f6c0f5082 100644
|
||||
--- c/tcg/tcg.c
|
||||
+++ w/tcg/tcg.c
|
||||
@@ -131,6 +131,10 @@ static void tcg_out_goto_tb(TCGContext *s, int which);
|
||||
@@ -2027,7 +2154,7 @@ index 6dc3072f92..214e66e9d6 100644
|
||||
#ifdef TCG_TARGET_NEED_LDST_LABELS
|
||||
QSIMPLEQ_INIT(&s->ldst_labels);
|
||||
#endif
|
||||
@@ -6286,13 +6599,88 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start)
|
||||
@@ -6286,13 +6599,94 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start)
|
||||
return -2;
|
||||
}
|
||||
|
||||
@@ -2040,6 +2167,12 @@ index 6dc3072f92..214e66e9d6 100644
|
||||
#endif
|
||||
|
||||
+#if defined(EMSCRIPTEN) && !defined(CONFIG_TCG_INTERPRETER)
|
||||
+ if (wasm_tci_only_tb) {
|
||||
+ for (int i = 0; i < get_core_nums(); i++) {
|
||||
+ export_vec_base[i] = WASM_TCI_ONLY_ENTRY;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ tcg_sub_out8(s, 0x0b); //end if
|
||||
+ tcg_sub_out8(s, 0x0b); //end loop
|
||||
+ tcg_sub_out8(s, 0x0); // unreachable
|
||||
@@ -2119,10 +2252,10 @@ index 6dc3072f92..214e66e9d6 100644
|
||||
|
||||
diff --git c/tcg/wasm32.c w/tcg/wasm32.c
|
||||
new file mode 100644
|
||||
index 0000000000..55ad790f17
|
||||
index 0000000000..19b31ed4df
|
||||
--- /dev/null
|
||||
+++ w/tcg/wasm32.c
|
||||
@@ -0,0 +1,1246 @@
|
||||
@@ -0,0 +1,1275 @@
|
||||
+/*
|
||||
+ * Tiny Code Generator for QEMU
|
||||
+ *
|
||||
@@ -2154,8 +2287,10 @@ index 0000000000..55ad790f17
|
||||
+#include <emscripten.h>
|
||||
+#include <emscripten/threading.h>
|
||||
+#include "wasm32.h"
|
||||
+#include "exec/translation-block.h"
|
||||
+
|
||||
+__thread uintptr_t tci_tb_ptr;
|
||||
+__thread bool wasm_tci_only_tb;
|
||||
+
|
||||
+/* Disassemble TCI bytecode. */
|
||||
+int print_insn_tci(bfd_vma addr, disassemble_info *info)
|
||||
@@ -2191,12 +2326,16 @@ index 0000000000..55ad790f17
|
||||
+ });
|
||||
+ var ptr = export_vec_begin + 4 * Module.__wasm32_tb.cur_core_num;
|
||||
+ const fidx = addFunction(inst.exports.start, 'ii');
|
||||
+ Module.__wasm32_tb.dynamic_functions.add(fidx);
|
||||
+ memory_v.setUint32(ptr, fidx, true);
|
||||
+
|
||||
+ const remove_n = memory_v.getInt32(Module.__wasm32_tb.to_remove_instance_idx_ptr, true);
|
||||
+ if (remove_n > 500) {
|
||||
+ for (var i = 0; i < remove_n * 4; i += 4) {
|
||||
+ removeFunction(memory_v.getInt32(Module.__wasm32_tb.to_remove_instance_ptr + i, true));
|
||||
+ const fidx = memory_v.getInt32(Module.__wasm32_tb.to_remove_instance_ptr + i, true);
|
||||
+ if (Module.__wasm32_tb.dynamic_functions.delete(fidx)) {
|
||||
+ removeFunction(fidx);
|
||||
+ }
|
||||
+ }
|
||||
+ memory_v.setInt32(Module.__wasm32_tb.to_remove_instance_idx_ptr, 0, true);
|
||||
+ }
|
||||
@@ -2212,7 +2351,10 @@ index 0000000000..55ad790f17
|
||||
+ const memory_v = new DataView(HEAP8.buffer);
|
||||
+ const remove_n = memory_v.getInt32(tb.to_remove_instance_idx_ptr, true);
|
||||
+ for (var i = 0; i < remove_n * 4; i += 4) {
|
||||
+ removeFunction(memory_v.getInt32(tb.to_remove_instance_ptr + i, true));
|
||||
+ const fidx = memory_v.getInt32(tb.to_remove_instance_ptr + i, true);
|
||||
+ if (tb.dynamic_functions.delete(fidx)) {
|
||||
+ removeFunction(fidx);
|
||||
+ }
|
||||
+ }
|
||||
+ memory_v.setInt32(tb.to_remove_instance_idx_ptr, 0, true);
|
||||
+});
|
||||
@@ -2272,6 +2414,7 @@ index 0000000000..55ad790f17
|
||||
+ cur_core_num: cur_core_num,
|
||||
+ to_remove_instance_ptr: to_remove_instance_ptr,
|
||||
+ to_remove_instance_idx_ptr: to_remove_instance_idx_ptr,
|
||||
+ dynamic_functions: new Set(),
|
||||
+ };
|
||||
+});
|
||||
+
|
||||
@@ -2627,6 +2770,19 @@ index 0000000000..55ad790f17
|
||||
+
|
||||
+ uint64_t target_addr = tlb_load(env, taddr, mop, ptr, false);
|
||||
+ if (target_addr != 0) {
|
||||
+ uint64_t mem_bytes = (uint64_t)__builtin_wasm_memory_size(0) << 16;
|
||||
+ if (target_addr + (1u << (mop & MO_SIZE)) > mem_bytes) {
|
||||
+ TranslationBlock *tb = tcg_tb_lookup(ra);
|
||||
+ fprintf(stderr,
|
||||
+ "[sd-watch] OOB store pc=%08llx gaddr=%08llx haddr=%08llx size=%u value=%08llx membytes=%08llx\n",
|
||||
+ (unsigned long long)(tb ? tb->pc : 0),
|
||||
+ (unsigned long long)taddr, (unsigned long long)target_addr,
|
||||
+ 1u << (mop & MO_SIZE), (unsigned long long)val,
|
||||
+ (unsigned long long)mem_bytes);
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ if (target_addr != 0) {
|
||||
+ switch (mop & MO_SIZE) {
|
||||
+ case MO_UB:
|
||||
+ *(uint8_t*)target_addr = (uint8_t)val;
|
||||
@@ -3252,7 +3408,9 @@ index 0000000000..55ad790f17
|
||||
+ tb_ptr = *(uint32_t **)ptr;
|
||||
+ ctx.tb_ptr = tb_ptr;
|
||||
+ int tb_entry_ptr = (uint32_t)tb_ptr + export_vec_off;
|
||||
+ if ((*(int32_t*)tb_entry_ptr <= 0) && (*(int32_t*)tb_entry_ptr > (-1 * INSTANTIATE_NUM))) {
|
||||
+ if (*(int32_t *)tb_entry_ptr == WASM_TCI_ONLY_ENTRY) {
|
||||
+ /* ponytail: Store TBs use TCI while tracing SD object corruption. */
|
||||
+ } else if ((*(int32_t*)tb_entry_ptr <= 0) && (*(int32_t*)tb_entry_ptr > (-1 * INSTANTIATE_NUM))) {
|
||||
+ *(int32_t*)tb_entry_ptr -= 1;
|
||||
+ } else {
|
||||
+ // enter to wasm TB
|
||||
@@ -3273,7 +3431,9 @@ index 0000000000..55ad790f17
|
||||
+
|
||||
+ ctx.tb_ptr = tb_ptr;
|
||||
+ int tb_entry_ptr = (uint32_t)tb_ptr + export_vec_off;
|
||||
+ if ((*(int32_t*)tb_entry_ptr <= 0) && (*(int32_t*)tb_entry_ptr > (-1 * INSTANTIATE_NUM))) {
|
||||
+ if (*(int32_t *)tb_entry_ptr == WASM_TCI_ONLY_ENTRY) {
|
||||
+ /* Continue in TCI. */
|
||||
+ } else if ((*(int32_t*)tb_entry_ptr <= 0) && (*(int32_t*)tb_entry_ptr > (-1 * INSTANTIATE_NUM))) {
|
||||
+ *(int32_t*)tb_entry_ptr -= 1;
|
||||
+ } else {
|
||||
+ // enter to wasm TB
|
||||
@@ -3355,6 +3515,8 @@ index 0000000000..55ad790f17
|
||||
+ uint32_t res;
|
||||
+ if (*(int32_t*)tb_entry_ptr > 0) {
|
||||
+ res = ((wasm_func_ptr)(*(uint32_t*)tb_entry_ptr))(&ctx);
|
||||
+ } else if (*(int32_t *)tb_entry_ptr == WASM_TCI_ONLY_ENTRY) {
|
||||
+ res = tcg_qemu_tb_exec_tci(env);
|
||||
+ } else if (*(int32_t*)tb_entry_ptr > (-1 * INSTANTIATE_NUM)) {
|
||||
+ *(int32_t*)tb_entry_ptr -= 1;
|
||||
+ res = tcg_qemu_tb_exec_tci(env);
|
||||
@@ -3371,10 +3533,10 @@ index 0000000000..55ad790f17
|
||||
+#endif
|
||||
diff --git c/tcg/wasm32.h w/tcg/wasm32.h
|
||||
new file mode 100644
|
||||
index 0000000000..1527bf4875
|
||||
index 0000000000..a8b525abe3
|
||||
--- /dev/null
|
||||
+++ w/tcg/wasm32.h
|
||||
@@ -0,0 +1,46 @@
|
||||
@@ -0,0 +1,49 @@
|
||||
+#ifndef TCG_WASM32_H
|
||||
+#define TCG_WASM32_H
|
||||
+
|
||||
@@ -3418,7 +3580,10 @@ index 0000000000..1527bf4875
|
||||
+
|
||||
+void init_wasm32();
|
||||
+
|
||||
+extern __thread bool wasm_tci_only_tb;
|
||||
+
|
||||
+#define INSTANTIATE_NUM 1500
|
||||
+#define WASM_TCI_ONLY_ENTRY (-2147483647 - 1)
|
||||
+
|
||||
+#endif
|
||||
diff --git c/tcg/wasm32/tcg-target-con-set.h w/tcg/wasm32/tcg-target-con-set.h
|
||||
@@ -3467,10 +3632,10 @@ index 0000000000..196395aef9
|
||||
+#endif
|
||||
diff --git c/tcg/wasm32/tcg-target.c.inc w/tcg/wasm32/tcg-target.c.inc
|
||||
new file mode 100644
|
||||
index 0000000000..9e82297a3f
|
||||
index 0000000000..053c941f99
|
||||
--- /dev/null
|
||||
+++ w/tcg/wasm32/tcg-target.c.inc
|
||||
@@ -0,0 +1,3824 @@
|
||||
@@ -0,0 +1,3826 @@
|
||||
+/*
|
||||
+ * Tiny Code Generator for QEMU
|
||||
+ *
|
||||
@@ -6843,6 +7008,7 @@ index 0000000000..9e82297a3f
|
||||
+}
|
||||
+static void tcg_out_qemu_st(TCGContext *s, TCGOpcode opc, const TCGArg *args, bool is_64)
|
||||
+{
|
||||
+ wasm_tci_only_tb = true;
|
||||
+ tcg_tci_out_qemu_ldst(s, opc, args);
|
||||
+ tcg_wasm_out_qemu_st(s, args, is_64);
|
||||
+}
|
||||
@@ -7246,6 +7412,7 @@ index 0000000000..9e82297a3f
|
||||
+void tcg_out_init() {
|
||||
+ current_label_pos = 0;
|
||||
+ env_cached = false;
|
||||
+ wasm_tci_only_tb = false;
|
||||
+}
|
||||
+
|
||||
+/* Test if a constant matches the constraint. */
|
||||
|
||||
+24
-18
@@ -20,26 +20,32 @@ else
|
||||
ENGINE=docker
|
||||
fi
|
||||
|
||||
if [ ! -d "$SRC/.git" ]; then
|
||||
git clone --depth 1 --branch "$TAG" https://github.com/espressif/qemu "$SRC"
|
||||
fi
|
||||
# Dev Mode - Build directly out of an already-patched working tree (e.g. _scratch/qemu-fix-src);
|
||||
# skip clone/commit-check/patch so edits compile incrementally without the patch round-trip.
|
||||
if [ -n "${QEMU_WASM_DEV:-}" ]; then
|
||||
cd "$SRC"
|
||||
else
|
||||
if [ ! -d "$SRC/.git" ]; then
|
||||
git clone --depth 1 --branch "$TAG" https://github.com/espressif/qemu "$SRC"
|
||||
fi
|
||||
|
||||
cd "$SRC"
|
||||
if [ "$(git rev-parse HEAD)" != "$COMMIT" ]; then
|
||||
echo "QEMU source must be $COMMIT ($TAG)" >&2
|
||||
exit 1
|
||||
fi
|
||||
cd "$SRC"
|
||||
if [ "$(git rev-parse HEAD)" != "$COMMIT" ]; then
|
||||
echo "QEMU source must be $COMMIT ($TAG)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Re-apply Patches On Drift - The source tree is a build artifact of the patches; reset and re-apply whenever a patch is newer than the last apply so `make web` never silently rebuilds stale sources.
|
||||
STAMP=".xteink-patch-stamp"
|
||||
if [ ! -f hw/display/xteink_x3_eink.c ] || [ ! -f tcg/wasm32.c ] \
|
||||
|| [ "$ROOT/qemu/patches/0001-xteink-machine.patch" -nt "$STAMP" ] \
|
||||
|| [ "$ROOT/qemu/patches/0002-qemu-wasm.patch" -nt "$STAMP" ]; then
|
||||
git reset --hard "$COMMIT"
|
||||
git clean -fdx -e build
|
||||
git apply "$ROOT/qemu/patches/0001-xteink-machine.patch"
|
||||
git apply --whitespace=nowarn "$ROOT/qemu/patches/0002-qemu-wasm.patch"
|
||||
touch "$STAMP"
|
||||
# Re-apply Patches On Drift - The source tree is a build artifact of the patches; reset and re-apply whenever a patch is newer than the last apply so `make web` never silently rebuilds stale sources.
|
||||
STAMP=".xteink-patch-stamp"
|
||||
if [ ! -f hw/display/xteink_x3_eink.c ] || [ ! -f tcg/wasm32.c ] \
|
||||
|| [ "$ROOT/qemu/patches/0001-xteink-machine.patch" -nt "$STAMP" ] \
|
||||
|| [ "$ROOT/qemu/patches/0002-qemu-wasm.patch" -nt "$STAMP" ]; then
|
||||
git reset --hard "$COMMIT"
|
||||
git clean -fdx -e build
|
||||
git apply "$ROOT/qemu/patches/0001-xteink-machine.patch"
|
||||
git apply --whitespace=nowarn "$ROOT/qemu/patches/0002-qemu-wasm.patch"
|
||||
touch "$STAMP"
|
||||
fi
|
||||
fi
|
||||
|
||||
printf 'Building Emscripten environment (qemu-wasm %s)\n' "$QEMU_WASM_COMMIT"
|
||||
|
||||
Reference in New Issue
Block a user