Open ZLangJIT opened 1 month ago
hmm i think this may work
/*
should detect
1. A == B
|------------|
|------------|
2. A overlaps B
|------------|
|------------|
3. B overlaps A
|------------|
|------------|
4. B inside A
|-------------|
|-------|
5. A inside B
|-------|
|-------------|
6. A inside B
|-------|
|-------------|
7. B inside A
|-------------|
|-------|
8. A inside B
|-------|
|-------------|
9. B inside A
|-------------|
|-------|
*/
static inline bool rvvm_mmio_zone_check_overlap(rvvm_addr_t A_BEGIN, rvvm_addr_t A_END, rvvm_addr_t B_BEGIN, rvvm_addr_t B_END) {
return
(A_BEGIN >= B_BEGIN && ( // handle 1, 3, 5, 6, 7, 8, 9
(A_END <= B_END) // handle *1, 2, *5, *6, *8, *9
|| (A_END >= B_END) // handle 1, *3, 4, *7, 8, 9
))
|| (B_BEGIN >= A_BEGIN && ( // handle 1, 2, 4, 6, 7, 9
(B_END <= A_END) // handle *1, 3, *4, *7, 8, *9
|| (B_END >= A_END) // handle 1, *2, 5, *6, 8, 9
));
}
// Returns addr if zone is free
static rvvm_addr_t rvvm_mmio_zone_check(rvvm_machine_t* machine, rvvm_addr_t addr, size_t size)
{
if (rvvm_mmio_zone_check_overlap(addr, addr+size, machine->mem.begin, machine->mem.begin+machine->mem.size)) {
addr = machine->mem.begin + machine->mem.size;
}
vector_foreach(machine->mmio_devs, i) {
rvvm_mmio_dev_t* dev = vector_at(machine->mmio_devs, i);
if (rvvm_mmio_zone_check_overlap(addr, addr+size, dev->addr, dev->addr+dev->size)) {
addr = dev->addr + dev->size;
}
}
return addr;
}
Apparently not
-rw------- 1 u0_a150 u0_a150 100M 2024-10-17 04:43 disk.img
INFO: Attached MMIO device at 0xb2000000, type "aclint_mswi"
INFO: Attached MMIO device at 0xb2004000, type "aclint_mtimer"
INFO: Attached MMIO device at 0xb200c000, type "plic"
INFO: Attached MMIO device at 0xb600c000, type "pci_bus"
INFO: Attached MMIO device at 0xc600c000, type "i2c_opencores"
INFO: Attached MMIO device at 0xc600c014, type "rtc_goldfish"
INFO: Attached MMIO device at 0xc600c034, type "syscon"
INFO: Attached MMIO device at 0xc600d034, type "ns16550a"
ERROR: No suitable windowing backends found!
WARN: Cannot attach MMIO device "rtl8169" to occupied region 0x40000000
INFO: Removing MMIO device "rtl8169"
ok we now get this
u0_a150@dreamlte /data/data/linux.kernel/files $ cd ASSETS ; ./boot_rvvm_disk.sh "" "-shm_data images/android-logo-mask.png -shm_id foo -shm_data disk.img -shm_id foo -shm_data disk.img -shm_id foo"
removed disk.img
100+0 records in
100+0 records out
104857600 bytes transferred in 0.189 secs (554802116 bytes/sec)
-rw------- 1 u0_a150 u0_a150 100M 2024-10-17 13:13 disk.img
INFO: Attached MMIO device at 0x02000000, type "aclint_mswi"
INFO: Attached MMIO device at 0x02004000, type "aclint_mtimer"
INFO: Attached MMIO device at 0x0c000000, type "plic"
INFO: Attached MMIO device at 0x30000000, type "pci_bus"
INFO: Attached MMIO device at 0x10030000, type "i2c_opencores"
INFO: Attached MMIO device at 0x00101000, type "rtc_goldfish"
INFO: Attached MMIO device at 0x00100000, type "syscon"
INFO: Attached MMIO device at 0x10000000, type "ns16550a"
ERROR: No suitable windowing backends found!
INFO: Attached MMIO device at 0x40000000, type "rtl8169"
INFO: Attached MMIO device at 0x40004000, type "nvme"
INFO: mapping path 'images/android-logo-mask.png' via mmap
INFO: mapped path 'images/android-logo-mask.png' at address 0x72a1dbb000 with size 12104
INFO: Attached MMIO device at 0x00000000, type "rvvm_shm_data_file"
INFO: mapping path 'disk.img' via mmap
INFO: mapped path 'disk.img' at address 0x7268cce000 with size 104857600
WARN: MMIO device desired region 0x00000000-0x06400000 is inside of region 0x02000000-0x02004000 of device "aclint_mswi"
WARN: MMIO device desired region 0x02004000-0x08404000 is inside of region 0x02004000-0x0200c000 of device "aclint_mtimer"
INFO: Attached MMIO device at 0x0200c000, type "rvvm_shm_data_file"
INFO: mapping path 'disk.img' via mmap
INFO: mapped path 'disk.img' at address 0x72628ce000 with size 104857600
WARN: MMIO device desired region 0x00000000-0x06400000 is inside of region 0x02000000-0x02004000 of device "aclint_mswi"
WARN: MMIO device desired region 0x02004000-0x08404000 is inside of region 0x02004000-0x0200c000 of device "aclint_mtimer"
WARN: MMIO device desired region 0x0200c000-0x0840c000 is inside of region 0x0200c000-0x0840c000 of device "rvvm_shm_data_file"
WARN: MMIO device desired region 0x0840c000-0x0e80c000 is inside of region 0x0c000000-0x10000000 of device "plic"
WARN: MMIO device desired region 0x10000000-0x16400000 is inside of region 0x10030000-0x10030014 of device "i2c_opencores"
WARN: MMIO device "rvvm_shm_data_file" has misaligned mapping, expect lower perf
INFO: Attached MMIO device at 0x10030014, type "rvvm_shm_data_file"
INFO: Generated DTB at 0xb1ffee10, size 4588
INFO: Hart 0x72a1632000 started
OpenSBI v1.4
____ _____ ____ _____
/ __ \ / ____| _ \_ _|
| | | |_ __ ___ _ __ | (___ | |_) || |
| | | | '_ \ / _ \ '_ \ \___ \| _ < | |
| |__| | |_) | __/ | | |____) | |_) || |_
\____/| .__/ \___|_| |_|_____/|____/_____|
| |
|_|
Platform Name : RVVM v0.7-409a68b-dirty
Platform Features : medeleg
Platform HART Count : 1
Platform IPI Device : aclint-mswi
Platform Timer Device : aclint-mtimer @ 10000000Hz
Platform Console Device : uart8250
Platform HSM Device : ---
Platform PMU Device : ---
Platform Reboot Device : syscon-reboot
Platform Shutdown Device : syscon-poweroff
// https://stackoverflow.com/a/3269471
#define rvvm_mmio_zone_check_overlap(start1, size1, start2, size2) ((start1) < (start2+size2) && (start2) < (start1+size1))
// Returns addr if zone is free
static rvvm_addr_t rvvm_mmio_zone_check(rvvm_machine_t* machine, rvvm_addr_t addr, size_t size)
{
if (rvvm_mmio_zone_check_overlap(addr, size, machine->mem.begin, machine->mem.size)) {
rvvm_warn("MMIO device desired region 0x%08"PRIx64"-0x%08"PRIx64" is inside of region 0x%08"PRIx64"-0x%08"PRIx64" of \"<machine memory>\"", addr, (addr + size), machine->mem.begin, (machine->mem.begin + machine->mem.size));
addr = machine->mem.begin + machine->mem.size;
}
vector_foreach(machine->mmio_devs, i) {
rvvm_mmio_dev_t* dev = vector_at(machine->mmio_devs, i);
if (rvvm_mmio_zone_check_overlap(addr, size, dev->addr, dev->size)) {
rvvm_warn("MMIO device desired region 0x%08"PRIx64"-0x%08"PRIx64" is inside of region 0x%08"PRIx64"-0x%08"PRIx64" of device \"%s\"", addr, addr + size, dev->addr, dev->addr + dev->size, dev->type ? dev->type->name : "null");
addr = dev->addr + dev->size;
}
}
return addr;
}
// Regions of size 0 are ignored (those are non-IO placeholders)
PUBLIC rvvm_addr_t rvvm_mmio_zone_auto(rvvm_machine_t* machine, rvvm_addr_t addr, size_t size)
{
if (size) {
rvvm_addr_t tmp = addr;
do {
addr = tmp;
tmp = rvvm_mmio_zone_check(machine, addr, size);
} while (tmp != addr);
}
return addr;
}
and this should fix any misaligned addresses when relocating upon an address overlapping
// https://stackoverflow.com/a/3269471
#define rvvm_mmio_zone_check_overlap(start1, size1, start2, size2) ((start1) < (start2+size2) && (start2) < (start1+size1))
// Returns addr if zone is free
static rvvm_addr_t rvvm_mmio_zone_check(rvvm_machine_t* machine, rvvm_addr_t addr, size_t size)
{
if (rvvm_mmio_zone_check_overlap(addr, size, machine->mem.begin, machine->mem.size)) {
rvvm_warn("MMIO device desired region 0x%08"PRIx64"-0x%08"PRIx64" overlaps region 0x%08"PRIx64"-0x%08"PRIx64" of \"<machine memory>\"", addr, addr + size, machine->mem.begin, machine->mem.begin + machine->mem.size);
addr = machine->mem.begin + machine->mem.size;
if (addr & 0xFFF) {
rvvm_warn("MMIO device aligning new unaligned region 0x%08"PRIx64"-0x%08"PRIx64" to 0x%08"PRIx64"-0x%08"PRIx64"", addr, addr + size, addr + (0x1000 - (addr % 0x1000)), (addr + (0x1000 - (addr % 0x1000))) + size);
addr = addr + (0x1000 - (addr % 0x1000));
}
}
vector_foreach(machine->mmio_devs, i) {
rvvm_mmio_dev_t* dev = vector_at(machine->mmio_devs, i);
if (rvvm_mmio_zone_check_overlap(addr, size, dev->addr, dev->size)) {
rvvm_warn("MMIO device desired region 0x%08"PRIx64"-0x%08"PRIx64" overlaps region 0x%08"PRIx64"-0x%08"PRIx64" of device \"%s\"", addr, addr + size, dev->addr, dev->addr + dev->size, dev->type ? dev->type->name : "null");
addr = dev->addr + dev->size;
if (addr & 0xFFF) {
rvvm_warn("MMIO device aligning new unaligned region 0x%08"PRIx64"-0x%08"PRIx64" to 0x%08"PRIx64"-0x%08"PRIx64"", addr, addr + size, addr + (0x1000 - (addr % 0x1000)), (addr + (0x1000 - (addr % 0x1000))) + size);
addr = addr + (0x1000 - (addr % 0x1000));
}
}
}
return addr;
}
// Regions of size 0 are ignored (those are non-IO placeholders)
PUBLIC rvvm_addr_t rvvm_mmio_zone_auto(rvvm_machine_t* machine, rvvm_addr_t addr, size_t size)
{
if (size) {
rvvm_addr_t tmp = addr;
do {
addr = tmp;
tmp = rvvm_mmio_zone_check(machine, addr, size);
} while (tmp != addr);
}
return addr;
}
PUBLIC rvvm_mmio_dev_t* rvvm_attach_mmio(rvvm_machine_t* machine, const rvvm_mmio_dev_t* mmio_desc)
{
rvvm_mmio_dev_t* dev = safe_new_obj(rvvm_mmio_dev_t);
memcpy(dev, mmio_desc, sizeof(rvvm_mmio_dev_t));
dev->machine = machine;
// Normalize access properties: Power of two, default 1 - 8 bytes
dev->min_op_size = dev->min_op_size ? bit_next_pow2(dev->min_op_size) : 1;
dev->max_op_size = dev->max_op_size ? bit_next_pow2(dev->max_op_size) : 8;
if (dev->min_op_size > dev->max_op_size || dev->min_op_size > 8) {
rvvm_warn("MMIO device \"%s\" has invalid op sizes: min %u, max %u",
dev->type ? dev->type->name : "null", dev->min_op_size, dev->max_op_size);
rvvm_mmio_free(dev);
return NULL;
}
if (rvvm_mmio_zone_auto(machine, dev->addr, dev->size) != dev->addr) {
rvvm_warn("Cannot attach MMIO device \"%s\" to occupied region 0x%08"PRIx64"",
dev->type ? dev->type->name : "null", dev->addr);
rvvm_mmio_free(dev);
return NULL;
}
if (dev->mapping) {
if (dev->addr & 0xFFF) {
// Misaligned mappings harm performance when used with KVM or shadow pagetable accel
rvvm_warn("MMIO device \"%s\" has misaligned address, expect lower perf",
dev->type ? dev->type->name : "null");
} else if (((size_t)dev->mapping) & 0xFFF) {
// Misaligned mappings harm performance when used with KVM or shadow pagetable accel
rvvm_warn("MMIO device \"%s\" has misaligned mapping, expect lower perf",
dev->type ? dev->type->name : "null");
}
}
INFO: mapping path 'images/android-logo-mask.png' via mmap
INFO: mapped path 'images/android-logo-mask.png' at address 0x777b953000 with size 12104
INFO: Attached MMIO device at 0x00000000, type "rvvm_shm_data_file"
INFO: mapping path 'disk.img' via mmap
INFO: mapped path 'disk.img' at address 0x7742812000 with size 104857600
WARN: MMIO device desired region 0x00000000-0x06400000 overlaps region 0x02000000-0x02004000 of device "aclint_mswi"
WARN: MMIO device desired region 0x02004000-0x08404000 overlaps region 0x02004000-0x0200c000 of device "aclint_mtimer"
INFO: Attached MMIO device at 0x0200c000, type "rvvm_shm_data_file"
INFO: mapping path 'disk.img' via mmap
INFO: mapped path 'disk.img' at address 0x773c412000 with size 104857600
WARN: MMIO device desired region 0x00000000-0x06400000 overlaps region 0x02000000-0x02004000 of device "aclint_mswi"
WARN: MMIO device desired region 0x02004000-0x08404000 overlaps region 0x02004000-0x0200c000 of device "aclint_mtimer"
WARN: MMIO device desired region 0x0200c000-0x0840c000 overlaps region 0x0200c000-0x0840c000 of device "rvvm_shm_data_file"
WARN: MMIO device desired region 0x0840c000-0x0e80c000 overlaps region 0x0c000000-0x10000000 of device "plic"
WARN: MMIO device desired region 0x10000000-0x16400000 overlaps region 0x10030000-0x10030014 of device "i2c_opencores"
WARN: MMIO device aligning new unaligned region 0x10030014-0x16430014 to 0x10031000-0x16431000
INFO: Attached MMIO device at 0x10031000, type "rvvm_shm_data_file"
i should probably make this into a patch at some point
assuming minimal changes, the current patch is this
diff --git a/src/main.c b/src/main.c
index 7cbe407..45f0f7d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -263,6 +318,7 @@ static int rvvm_cli_main(int argc, const char** argv)
#endif
if (rvvm_cli_configure(machine, argc, argv, bootrom, tap)) {
+ rvvm_mmio_print_map(machine);
rvvm_start_machine(machine);
if (!rvvm_has_arg("noisolation")) {
diff --git a/src/rvvm.c b/src/rvvm.c
index 71f1dbf..79b4826 100644
--- a/src/rvvm.c
+++ b/src/rvvm.c
@@ -691,17 +691,30 @@ PUBLIC void rvvm_free_machine(rvvm_machine_t* machine)
free(machine);
}
+// https://stackoverflow.com/a/3269471
+#define rvvm_mmio_zone_check_overlap(start1, size1, start2, size2) ((start1) < (start2+size2) && (start2) < (start1+size1))
+
// Returns addr if zone is free
static rvvm_addr_t rvvm_mmio_zone_check(rvvm_machine_t* machine, rvvm_addr_t addr, size_t size)
{
- if (addr >= machine->mem.begin && (addr + size) <= (machine->mem.begin + machine->mem.size)) {
+ if (rvvm_mmio_zone_check_overlap(addr, size, machine->mem.begin, machine->mem.size)) {
addr = machine->mem.begin + machine->mem.size;
+ if (addr & 0xFFF) {
+ addr = addr + (0x1000 - (addr % 0x1000));
+ }
}
vector_foreach(machine->mmio_devs, i) {
rvvm_mmio_dev_t* dev = vector_at(machine->mmio_devs, i);
- if (addr >= dev->addr && (addr + size) <= (dev->addr + dev->size)) {
+ if (rvvm_mmio_zone_check_overlap(addr, size, dev->addr, dev->size)) {
addr = dev->addr + dev->size;
+ if (addr & 0xFFF) {
+ addr = addr + (0x1000 - (addr % 0x1000));
+ }
}
}
@@ -743,10 +756,16 @@ PUBLIC rvvm_mmio_dev_t* rvvm_attach_mmio(rvvm_machine_t* machine, const rvvm_mmi
rvvm_mmio_free(dev);
return NULL;
}
- if (dev->mapping && ((dev->addr & 0xFFF) || (((size_t)dev->mapping) & 0xFFF))) {
- // Misaligned mappings harm performance when used with KVM or shadow pagetable accel
- rvvm_warn("MMIO device \"%s\" has misaligned mapping, expect lower perf",
- dev->type ? dev->type->name : "null");
+ if (dev->mapping) {
+ if (dev->addr & 0xFFF) {
+ // Misaligned mappings harm performance when used with KVM or shadow pagetable accel
+ rvvm_warn("MMIO device \"%s\" has misaligned address, expect lower perf",
+ dev->type ? dev->type->name : "null");
+ } else if (((size_t)dev->mapping) & 0xFFF) {
+ // Misaligned mappings harm performance when used with KVM or shadow pagetable accel
+ rvvm_warn("MMIO device \"%s\" has misaligned mapping, expect lower perf",
+ dev->type ? dev->type->name : "null");
+ }
}
rvvm_info("Attached MMIO device at 0x%08"PRIx64", type \"%s\"",
@@ -913,3 +932,13 @@ PUBLIC void rvvm_write_cpu_reg(rvvm_hart_t* thread, size_t reg_id, rvvm_addr_t r
rvvm_warn("Unknown register %d in rvvm_write_cpu_reg()!", (uint32_t)reg_id);
}
}
+
+PUBLIC void rvvm_mmio_print_map(rvvm_machine_t* machine) {
+ // we currently do not sort the mapping by address
+ rvvm_info("MMIO Region Map:");
+ rvvm_info(" [0x%08"PRIx64"-0x%08"PRIx64"] - \"<machine memory>\"", machine->mem.begin, machine->mem.begin + machine->mem.size);
+
+ vector_foreach(machine->mmio_devs, i) {
+ rvvm_mmio_dev_t* dev = vector_at(machine->mmio_devs, i);
+ rvvm_info(" [0x%08"PRIx64"-0x%08"PRIx64"] - \"%s\"", dev->addr, dev->addr + dev->size, dev->type ? dev->type->name : "<null>");
+ }
+}
Are you trying to realign next auto zone to page boundary?
Are you trying to realign next auto zone to page boundary?
yes
but mainly realign next auto zone to a free zone that is currently unused
Does the commit 43846ef work as desired?
Hm actually I think 6d16e15 should fix the case where dev->addr + dev->size == addr
but a collision still exists
seems correct, i will check when i have time