-
Notifications
You must be signed in to change notification settings - Fork 66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
mmio auto zone doesnt seem to resolve initial conflicts #155
Comments
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
|
ok we now get this
// 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");
}
}
|
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? |
yes but mainly realign next auto zone to a free zone that is currently unused |
The text was updated successfully, but these errors were encountered: