* [Qemu-devel] [PATCH for-2.8] dma/rc4030: translate memory accesses only when they occur
@ 2016-11-18 22:43 Hervé Poussineau
2017-02-22 6:19 ` Hervé Poussineau
0 siblings, 1 reply; 5+ messages in thread
From: Hervé Poussineau @ 2016-11-18 22:43 UTC (permalink / raw)
To: qemu-devel
Cc: Prasad J Pandit, Aurelien Jarno, Yongbok Kim, Hervé Poussineau
This simplifies the code a lot, and this fixes big memory leaks
introduced in a3d586f704609a45b6037534cb2f34da5dfd8895
Windows NT is now able to boot without using gigabytes of ram on the host.
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
---
hw/dma/rc4030.c | 158 +++++++++++++-------------------------------------------
1 file changed, 36 insertions(+), 122 deletions(-)
diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c
index 41fc043..5f10b9d 100644
--- a/hw/dma/rc4030.c
+++ b/hw/dma/rc4030.c
@@ -34,8 +34,6 @@
/********************************************************/
/* rc4030 emulation */
-#define MAX_TL_ENTRIES 512
-
typedef struct dma_pagetable_entry {
int32_t frame;
int32_t owner;
@@ -91,14 +89,8 @@ typedef struct rc4030State
qemu_irq timer_irq;
qemu_irq jazz_bus_irq;
- /* biggest translation table */
- MemoryRegion dma_tt;
- /* translation table memory region alias, added to system RAM */
- MemoryRegion dma_tt_alias;
/* whole DMA memory region, root of DMA address space */
MemoryRegion dma_mr;
- /* translation table entry aliases, added to DMA memory region */
- MemoryRegion dma_mrs[MAX_TL_ENTRIES];
AddressSpace dma_as;
MemoryRegion iomem_chipset;
@@ -256,96 +248,6 @@ static uint64_t rc4030_read(void *opaque, hwaddr addr, unsigned int size)
return val;
}
-static void rc4030_dma_as_update_one(rc4030State *s, int index, uint32_t frame)
-{
- if (index < MAX_TL_ENTRIES) {
- memory_region_set_enabled(&s->dma_mrs[index], false);
- }
-
- if (!frame) {
- return;
- }
-
- if (index >= MAX_TL_ENTRIES) {
- qemu_log_mask(LOG_UNIMP,
- "rc4030: trying to use too high "
- "translation table entry %d (max allowed=%d)",
- index, MAX_TL_ENTRIES);
- return;
- }
- memory_region_set_alias_offset(&s->dma_mrs[index], frame);
- memory_region_set_enabled(&s->dma_mrs[index], true);
-}
-
-static void rc4030_dma_tt_write(void *opaque, hwaddr addr, uint64_t data,
- unsigned int size)
-{
- rc4030State *s = opaque;
-
- /* write memory */
- memcpy(memory_region_get_ram_ptr(&s->dma_tt) + addr, &data, size);
-
- /* update dma address space (only if frame field has been written) */
- if (addr % sizeof(dma_pagetable_entry) == 0) {
- int index = addr / sizeof(dma_pagetable_entry);
- memory_region_transaction_begin();
- rc4030_dma_as_update_one(s, index, (uint32_t)data);
- memory_region_transaction_commit();
- }
-}
-
-static const MemoryRegionOps rc4030_dma_tt_ops = {
- .write = rc4030_dma_tt_write,
- .impl.min_access_size = 4,
- .impl.max_access_size = 4,
-};
-
-static void rc4030_dma_tt_update(rc4030State *s, uint32_t new_tl_base,
- uint32_t new_tl_limit)
-{
- int entries, i;
- dma_pagetable_entry *dma_tl_contents;
-
- if (s->dma_tl_limit) {
- /* write old dma tl table to physical memory */
- memory_region_del_subregion(get_system_memory(), &s->dma_tt_alias);
- cpu_physical_memory_write(s->dma_tl_limit & 0x7fffffff,
- memory_region_get_ram_ptr(&s->dma_tt),
- memory_region_size(&s->dma_tt_alias));
- }
- object_unparent(OBJECT(&s->dma_tt_alias));
-
- s->dma_tl_base = new_tl_base;
- s->dma_tl_limit = new_tl_limit;
- new_tl_base &= 0x7fffffff;
-
- if (s->dma_tl_limit) {
- uint64_t dma_tt_size;
- if (s->dma_tl_limit <= memory_region_size(&s->dma_tt)) {
- dma_tt_size = s->dma_tl_limit;
- } else {
- dma_tt_size = memory_region_size(&s->dma_tt);
- }
- memory_region_init_alias(&s->dma_tt_alias, OBJECT(s),
- "dma-table-alias",
- &s->dma_tt, 0, dma_tt_size);
- dma_tl_contents = memory_region_get_ram_ptr(&s->dma_tt);
- cpu_physical_memory_read(new_tl_base, dma_tl_contents, dma_tt_size);
-
- memory_region_transaction_begin();
- entries = dma_tt_size / sizeof(dma_pagetable_entry);
- for (i = 0; i < entries; i++) {
- rc4030_dma_as_update_one(s, i, dma_tl_contents[i].frame);
- }
- memory_region_add_subregion(get_system_memory(), new_tl_base,
- &s->dma_tt_alias);
- memory_region_transaction_commit();
- } else {
- memory_region_init(&s->dma_tt_alias, OBJECT(s),
- "dma-table-alias", 0);
- }
-}
-
static void rc4030_write(void *opaque, hwaddr addr, uint64_t data,
unsigned int size)
{
@@ -362,11 +264,11 @@ static void rc4030_write(void *opaque, hwaddr addr, uint64_t data,
break;
/* DMA transl. table base */
case 0x0018:
- rc4030_dma_tt_update(s, val, s->dma_tl_limit);
+ s->dma_tl_base = val;
break;
/* DMA transl. table limit */
case 0x0020:
- rc4030_dma_tt_update(s, s->dma_tl_base, val);
+ s->dma_tl_limit = val;
break;
/* DMA transl. table invalidated */
case 0x0028:
@@ -586,6 +488,38 @@ static const MemoryRegionOps jazzio_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
+static IOMMUTLBEntry rc4030_dma_translate(MemoryRegion *iommu, hwaddr addr,
+ bool is_write)
+{
+ rc4030State *s = container_of(iommu, rc4030State, dma_mr);
+ IOMMUTLBEntry ret = {
+ .target_as = &address_space_memory,
+ .iova = addr & ~(DMA_PAGESIZE - 1),
+ .translated_addr = 0,
+ .addr_mask = DMA_PAGESIZE - 1,
+ .perm = IOMMU_NONE,
+ };
+ uint64_t i, entry_address;
+ dma_pagetable_entry entry;
+
+ i = addr / DMA_PAGESIZE;
+ if (i < s->dma_tl_limit / sizeof(entry)) {
+ entry_address = (s->dma_tl_base & 0x7fffffff) + i * sizeof(entry);
+ if (address_space_read(ret.target_as, entry_address,
+ MEMTXATTRS_UNSPECIFIED, (unsigned char *)&entry,
+ sizeof(entry)) == MEMTX_OK) {
+ ret.translated_addr = entry.frame & ~(DMA_PAGESIZE - 1);
+ ret.perm = IOMMU_RW;
+ }
+ }
+
+ return ret;
+}
+
+static const MemoryRegionIOMMUOps rc4030_dma_ops = {
+ .translate = rc4030_dma_translate,
+};
+
static void rc4030_reset(DeviceState *dev)
{
rc4030State *s = RC4030(dev);
@@ -596,7 +530,6 @@ static void rc4030_reset(DeviceState *dev)
s->invalid_address_register = 0;
memset(s->dma_regs, 0, sizeof(s->dma_regs));
- rc4030_dma_tt_update(s, 0, 0);
s->remote_failed_address = s->memory_failed_address = 0;
s->cache_maint = 0;
@@ -735,7 +668,6 @@ static void rc4030_realize(DeviceState *dev, Error **errp)
{
rc4030State *s = RC4030(dev);
Object *o = OBJECT(dev);
- int i;
s->periodic_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
rc4030_periodic_timer, s);
@@ -745,37 +677,19 @@ static void rc4030_realize(DeviceState *dev, Error **errp)
memory_region_init_io(&s->iomem_jazzio, NULL, &jazzio_ops, s,
"rc4030.jazzio", 0x00001000);
- memory_region_init_rom_device(&s->dma_tt, o,
- &rc4030_dma_tt_ops, s, "dma-table",
- MAX_TL_ENTRIES * sizeof(dma_pagetable_entry),
- NULL);
- memory_region_init(&s->dma_tt_alias, o, "dma-table-alias", 0);
- memory_region_init(&s->dma_mr, o, "dma", INT32_MAX);
- for (i = 0; i < MAX_TL_ENTRIES; ++i) {
- memory_region_init_alias(&s->dma_mrs[i], o, "dma-alias",
- get_system_memory(), 0, DMA_PAGESIZE);
- memory_region_set_enabled(&s->dma_mrs[i], false);
- memory_region_add_subregion(&s->dma_mr, i * DMA_PAGESIZE,
- &s->dma_mrs[i]);
- }
+ memory_region_init_iommu(&s->dma_mr, o, &rc4030_dma_ops,
+ "rc4030.dma", UINT32_MAX);
address_space_init(&s->dma_as, &s->dma_mr, "rc4030-dma");
}
static void rc4030_unrealize(DeviceState *dev, Error **errp)
{
rc4030State *s = RC4030(dev);
- int i;
timer_free(s->periodic_timer);
address_space_destroy(&s->dma_as);
- object_unparent(OBJECT(&s->dma_tt));
- object_unparent(OBJECT(&s->dma_tt_alias));
object_unparent(OBJECT(&s->dma_mr));
- for (i = 0; i < MAX_TL_ENTRIES; ++i) {
- memory_region_del_subregion(&s->dma_mr, &s->dma_mrs[i]);
- object_unparent(OBJECT(&s->dma_mrs[i]));
- }
}
static void rc4030_class_init(ObjectClass *klass, void *class_data)
--
2.1.4
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH for-2.8] dma/rc4030: translate memory accesses only when they occur
2016-11-18 22:43 [Qemu-devel] [PATCH for-2.8] dma/rc4030: translate memory accesses only when they occur Hervé Poussineau
@ 2017-02-22 6:19 ` Hervé Poussineau
2017-02-26 19:19 ` Hervé Poussineau
0 siblings, 1 reply; 5+ messages in thread
From: Hervé Poussineau @ 2017-02-22 6:19 UTC (permalink / raw)
To: qemu-devel; +Cc: Prasad J Pandit, Aurelien Jarno, Yongbok Kim
Ping?
Le 18/11/2016 à 23:43, Hervé Poussineau a écrit :
> This simplifies the code a lot, and this fixes big memory leaks
> introduced in a3d586f704609a45b6037534cb2f34da5dfd8895
>
> Windows NT is now able to boot without using gigabytes of ram on the host.
>
> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
> ---
> hw/dma/rc4030.c | 158 +++++++++++++-------------------------------------------
> 1 file changed, 36 insertions(+), 122 deletions(-)
>
> diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c
> index 41fc043..5f10b9d 100644
> --- a/hw/dma/rc4030.c
> +++ b/hw/dma/rc4030.c
> @@ -34,8 +34,6 @@
> /********************************************************/
> /* rc4030 emulation */
>
> -#define MAX_TL_ENTRIES 512
> -
> typedef struct dma_pagetable_entry {
> int32_t frame;
> int32_t owner;
> @@ -91,14 +89,8 @@ typedef struct rc4030State
> qemu_irq timer_irq;
> qemu_irq jazz_bus_irq;
>
> - /* biggest translation table */
> - MemoryRegion dma_tt;
> - /* translation table memory region alias, added to system RAM */
> - MemoryRegion dma_tt_alias;
> /* whole DMA memory region, root of DMA address space */
> MemoryRegion dma_mr;
> - /* translation table entry aliases, added to DMA memory region */
> - MemoryRegion dma_mrs[MAX_TL_ENTRIES];
> AddressSpace dma_as;
>
> MemoryRegion iomem_chipset;
> @@ -256,96 +248,6 @@ static uint64_t rc4030_read(void *opaque, hwaddr addr, unsigned int size)
> return val;
> }
>
> -static void rc4030_dma_as_update_one(rc4030State *s, int index, uint32_t frame)
> -{
> - if (index < MAX_TL_ENTRIES) {
> - memory_region_set_enabled(&s->dma_mrs[index], false);
> - }
> -
> - if (!frame) {
> - return;
> - }
> -
> - if (index >= MAX_TL_ENTRIES) {
> - qemu_log_mask(LOG_UNIMP,
> - "rc4030: trying to use too high "
> - "translation table entry %d (max allowed=%d)",
> - index, MAX_TL_ENTRIES);
> - return;
> - }
> - memory_region_set_alias_offset(&s->dma_mrs[index], frame);
> - memory_region_set_enabled(&s->dma_mrs[index], true);
> -}
> -
> -static void rc4030_dma_tt_write(void *opaque, hwaddr addr, uint64_t data,
> - unsigned int size)
> -{
> - rc4030State *s = opaque;
> -
> - /* write memory */
> - memcpy(memory_region_get_ram_ptr(&s->dma_tt) + addr, &data, size);
> -
> - /* update dma address space (only if frame field has been written) */
> - if (addr % sizeof(dma_pagetable_entry) == 0) {
> - int index = addr / sizeof(dma_pagetable_entry);
> - memory_region_transaction_begin();
> - rc4030_dma_as_update_one(s, index, (uint32_t)data);
> - memory_region_transaction_commit();
> - }
> -}
> -
> -static const MemoryRegionOps rc4030_dma_tt_ops = {
> - .write = rc4030_dma_tt_write,
> - .impl.min_access_size = 4,
> - .impl.max_access_size = 4,
> -};
> -
> -static void rc4030_dma_tt_update(rc4030State *s, uint32_t new_tl_base,
> - uint32_t new_tl_limit)
> -{
> - int entries, i;
> - dma_pagetable_entry *dma_tl_contents;
> -
> - if (s->dma_tl_limit) {
> - /* write old dma tl table to physical memory */
> - memory_region_del_subregion(get_system_memory(), &s->dma_tt_alias);
> - cpu_physical_memory_write(s->dma_tl_limit & 0x7fffffff,
> - memory_region_get_ram_ptr(&s->dma_tt),
> - memory_region_size(&s->dma_tt_alias));
> - }
> - object_unparent(OBJECT(&s->dma_tt_alias));
> -
> - s->dma_tl_base = new_tl_base;
> - s->dma_tl_limit = new_tl_limit;
> - new_tl_base &= 0x7fffffff;
> -
> - if (s->dma_tl_limit) {
> - uint64_t dma_tt_size;
> - if (s->dma_tl_limit <= memory_region_size(&s->dma_tt)) {
> - dma_tt_size = s->dma_tl_limit;
> - } else {
> - dma_tt_size = memory_region_size(&s->dma_tt);
> - }
> - memory_region_init_alias(&s->dma_tt_alias, OBJECT(s),
> - "dma-table-alias",
> - &s->dma_tt, 0, dma_tt_size);
> - dma_tl_contents = memory_region_get_ram_ptr(&s->dma_tt);
> - cpu_physical_memory_read(new_tl_base, dma_tl_contents, dma_tt_size);
> -
> - memory_region_transaction_begin();
> - entries = dma_tt_size / sizeof(dma_pagetable_entry);
> - for (i = 0; i < entries; i++) {
> - rc4030_dma_as_update_one(s, i, dma_tl_contents[i].frame);
> - }
> - memory_region_add_subregion(get_system_memory(), new_tl_base,
> - &s->dma_tt_alias);
> - memory_region_transaction_commit();
> - } else {
> - memory_region_init(&s->dma_tt_alias, OBJECT(s),
> - "dma-table-alias", 0);
> - }
> -}
> -
> static void rc4030_write(void *opaque, hwaddr addr, uint64_t data,
> unsigned int size)
> {
> @@ -362,11 +264,11 @@ static void rc4030_write(void *opaque, hwaddr addr, uint64_t data,
> break;
> /* DMA transl. table base */
> case 0x0018:
> - rc4030_dma_tt_update(s, val, s->dma_tl_limit);
> + s->dma_tl_base = val;
> break;
> /* DMA transl. table limit */
> case 0x0020:
> - rc4030_dma_tt_update(s, s->dma_tl_base, val);
> + s->dma_tl_limit = val;
> break;
> /* DMA transl. table invalidated */
> case 0x0028:
> @@ -586,6 +488,38 @@ static const MemoryRegionOps jazzio_ops = {
> .endianness = DEVICE_NATIVE_ENDIAN,
> };
>
> +static IOMMUTLBEntry rc4030_dma_translate(MemoryRegion *iommu, hwaddr addr,
> + bool is_write)
> +{
> + rc4030State *s = container_of(iommu, rc4030State, dma_mr);
> + IOMMUTLBEntry ret = {
> + .target_as = &address_space_memory,
> + .iova = addr & ~(DMA_PAGESIZE - 1),
> + .translated_addr = 0,
> + .addr_mask = DMA_PAGESIZE - 1,
> + .perm = IOMMU_NONE,
> + };
> + uint64_t i, entry_address;
> + dma_pagetable_entry entry;
> +
> + i = addr / DMA_PAGESIZE;
> + if (i < s->dma_tl_limit / sizeof(entry)) {
> + entry_address = (s->dma_tl_base & 0x7fffffff) + i * sizeof(entry);
> + if (address_space_read(ret.target_as, entry_address,
> + MEMTXATTRS_UNSPECIFIED, (unsigned char *)&entry,
> + sizeof(entry)) == MEMTX_OK) {
> + ret.translated_addr = entry.frame & ~(DMA_PAGESIZE - 1);
> + ret.perm = IOMMU_RW;
> + }
> + }
> +
> + return ret;
> +}
> +
> +static const MemoryRegionIOMMUOps rc4030_dma_ops = {
> + .translate = rc4030_dma_translate,
> +};
> +
> static void rc4030_reset(DeviceState *dev)
> {
> rc4030State *s = RC4030(dev);
> @@ -596,7 +530,6 @@ static void rc4030_reset(DeviceState *dev)
> s->invalid_address_register = 0;
>
> memset(s->dma_regs, 0, sizeof(s->dma_regs));
> - rc4030_dma_tt_update(s, 0, 0);
>
> s->remote_failed_address = s->memory_failed_address = 0;
> s->cache_maint = 0;
> @@ -735,7 +668,6 @@ static void rc4030_realize(DeviceState *dev, Error **errp)
> {
> rc4030State *s = RC4030(dev);
> Object *o = OBJECT(dev);
> - int i;
>
> s->periodic_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
> rc4030_periodic_timer, s);
> @@ -745,37 +677,19 @@ static void rc4030_realize(DeviceState *dev, Error **errp)
> memory_region_init_io(&s->iomem_jazzio, NULL, &jazzio_ops, s,
> "rc4030.jazzio", 0x00001000);
>
> - memory_region_init_rom_device(&s->dma_tt, o,
> - &rc4030_dma_tt_ops, s, "dma-table",
> - MAX_TL_ENTRIES * sizeof(dma_pagetable_entry),
> - NULL);
> - memory_region_init(&s->dma_tt_alias, o, "dma-table-alias", 0);
> - memory_region_init(&s->dma_mr, o, "dma", INT32_MAX);
> - for (i = 0; i < MAX_TL_ENTRIES; ++i) {
> - memory_region_init_alias(&s->dma_mrs[i], o, "dma-alias",
> - get_system_memory(), 0, DMA_PAGESIZE);
> - memory_region_set_enabled(&s->dma_mrs[i], false);
> - memory_region_add_subregion(&s->dma_mr, i * DMA_PAGESIZE,
> - &s->dma_mrs[i]);
> - }
> + memory_region_init_iommu(&s->dma_mr, o, &rc4030_dma_ops,
> + "rc4030.dma", UINT32_MAX);
> address_space_init(&s->dma_as, &s->dma_mr, "rc4030-dma");
> }
>
> static void rc4030_unrealize(DeviceState *dev, Error **errp)
> {
> rc4030State *s = RC4030(dev);
> - int i;
>
> timer_free(s->periodic_timer);
>
> address_space_destroy(&s->dma_as);
> - object_unparent(OBJECT(&s->dma_tt));
> - object_unparent(OBJECT(&s->dma_tt_alias));
> object_unparent(OBJECT(&s->dma_mr));
> - for (i = 0; i < MAX_TL_ENTRIES; ++i) {
> - memory_region_del_subregion(&s->dma_mr, &s->dma_mrs[i]);
> - object_unparent(OBJECT(&s->dma_mrs[i]));
> - }
> }
>
> static void rc4030_class_init(ObjectClass *klass, void *class_data)
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH for-2.8] dma/rc4030: translate memory accesses only when they occur
2017-02-22 6:19 ` Hervé Poussineau
@ 2017-02-26 19:19 ` Hervé Poussineau
2017-03-10 18:31 ` Hervé Poussineau
0 siblings, 1 reply; 5+ messages in thread
From: Hervé Poussineau @ 2017-02-26 19:19 UTC (permalink / raw)
To: Hervé Poussineau, qemu-devel
Cc: Prasad J Pandit, Aurelien Jarno, Yongbok Kim
Ping again.
Le 22/02/2017 à 07:19, Hervé Poussineau a écrit :
> Ping?
>
> Le 18/11/2016 à 23:43, Hervé Poussineau a écrit :
>> This simplifies the code a lot, and this fixes big memory leaks
>> introduced in a3d586f704609a45b6037534cb2f34da5dfd8895
>>
>> Windows NT is now able to boot without using gigabytes of ram on the host.
>>
>> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
>> ---
>> hw/dma/rc4030.c | 158 +++++++++++++-------------------------------------------
>> 1 file changed, 36 insertions(+), 122 deletions(-)
>>
>> diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c
>> index 41fc043..5f10b9d 100644
>> --- a/hw/dma/rc4030.c
>> +++ b/hw/dma/rc4030.c
>> @@ -34,8 +34,6 @@
>> /********************************************************/
>> /* rc4030 emulation */
>>
>> -#define MAX_TL_ENTRIES 512
>> -
>> typedef struct dma_pagetable_entry {
>> int32_t frame;
>> int32_t owner;
>> @@ -91,14 +89,8 @@ typedef struct rc4030State
>> qemu_irq timer_irq;
>> qemu_irq jazz_bus_irq;
>>
>> - /* biggest translation table */
>> - MemoryRegion dma_tt;
>> - /* translation table memory region alias, added to system RAM */
>> - MemoryRegion dma_tt_alias;
>> /* whole DMA memory region, root of DMA address space */
>> MemoryRegion dma_mr;
>> - /* translation table entry aliases, added to DMA memory region */
>> - MemoryRegion dma_mrs[MAX_TL_ENTRIES];
>> AddressSpace dma_as;
>>
>> MemoryRegion iomem_chipset;
>> @@ -256,96 +248,6 @@ static uint64_t rc4030_read(void *opaque, hwaddr addr, unsigned int size)
>> return val;
>> }
>>
>> -static void rc4030_dma_as_update_one(rc4030State *s, int index, uint32_t frame)
>> -{
>> - if (index < MAX_TL_ENTRIES) {
>> - memory_region_set_enabled(&s->dma_mrs[index], false);
>> - }
>> -
>> - if (!frame) {
>> - return;
>> - }
>> -
>> - if (index >= MAX_TL_ENTRIES) {
>> - qemu_log_mask(LOG_UNIMP,
>> - "rc4030: trying to use too high "
>> - "translation table entry %d (max allowed=%d)",
>> - index, MAX_TL_ENTRIES);
>> - return;
>> - }
>> - memory_region_set_alias_offset(&s->dma_mrs[index], frame);
>> - memory_region_set_enabled(&s->dma_mrs[index], true);
>> -}
>> -
>> -static void rc4030_dma_tt_write(void *opaque, hwaddr addr, uint64_t data,
>> - unsigned int size)
>> -{
>> - rc4030State *s = opaque;
>> -
>> - /* write memory */
>> - memcpy(memory_region_get_ram_ptr(&s->dma_tt) + addr, &data, size);
>> -
>> - /* update dma address space (only if frame field has been written) */
>> - if (addr % sizeof(dma_pagetable_entry) == 0) {
>> - int index = addr / sizeof(dma_pagetable_entry);
>> - memory_region_transaction_begin();
>> - rc4030_dma_as_update_one(s, index, (uint32_t)data);
>> - memory_region_transaction_commit();
>> - }
>> -}
>> -
>> -static const MemoryRegionOps rc4030_dma_tt_ops = {
>> - .write = rc4030_dma_tt_write,
>> - .impl.min_access_size = 4,
>> - .impl.max_access_size = 4,
>> -};
>> -
>> -static void rc4030_dma_tt_update(rc4030State *s, uint32_t new_tl_base,
>> - uint32_t new_tl_limit)
>> -{
>> - int entries, i;
>> - dma_pagetable_entry *dma_tl_contents;
>> -
>> - if (s->dma_tl_limit) {
>> - /* write old dma tl table to physical memory */
>> - memory_region_del_subregion(get_system_memory(), &s->dma_tt_alias);
>> - cpu_physical_memory_write(s->dma_tl_limit & 0x7fffffff,
>> - memory_region_get_ram_ptr(&s->dma_tt),
>> - memory_region_size(&s->dma_tt_alias));
>> - }
>> - object_unparent(OBJECT(&s->dma_tt_alias));
>> -
>> - s->dma_tl_base = new_tl_base;
>> - s->dma_tl_limit = new_tl_limit;
>> - new_tl_base &= 0x7fffffff;
>> -
>> - if (s->dma_tl_limit) {
>> - uint64_t dma_tt_size;
>> - if (s->dma_tl_limit <= memory_region_size(&s->dma_tt)) {
>> - dma_tt_size = s->dma_tl_limit;
>> - } else {
>> - dma_tt_size = memory_region_size(&s->dma_tt);
>> - }
>> - memory_region_init_alias(&s->dma_tt_alias, OBJECT(s),
>> - "dma-table-alias",
>> - &s->dma_tt, 0, dma_tt_size);
>> - dma_tl_contents = memory_region_get_ram_ptr(&s->dma_tt);
>> - cpu_physical_memory_read(new_tl_base, dma_tl_contents, dma_tt_size);
>> -
>> - memory_region_transaction_begin();
>> - entries = dma_tt_size / sizeof(dma_pagetable_entry);
>> - for (i = 0; i < entries; i++) {
>> - rc4030_dma_as_update_one(s, i, dma_tl_contents[i].frame);
>> - }
>> - memory_region_add_subregion(get_system_memory(), new_tl_base,
>> - &s->dma_tt_alias);
>> - memory_region_transaction_commit();
>> - } else {
>> - memory_region_init(&s->dma_tt_alias, OBJECT(s),
>> - "dma-table-alias", 0);
>> - }
>> -}
>> -
>> static void rc4030_write(void *opaque, hwaddr addr, uint64_t data,
>> unsigned int size)
>> {
>> @@ -362,11 +264,11 @@ static void rc4030_write(void *opaque, hwaddr addr, uint64_t data,
>> break;
>> /* DMA transl. table base */
>> case 0x0018:
>> - rc4030_dma_tt_update(s, val, s->dma_tl_limit);
>> + s->dma_tl_base = val;
>> break;
>> /* DMA transl. table limit */
>> case 0x0020:
>> - rc4030_dma_tt_update(s, s->dma_tl_base, val);
>> + s->dma_tl_limit = val;
>> break;
>> /* DMA transl. table invalidated */
>> case 0x0028:
>> @@ -586,6 +488,38 @@ static const MemoryRegionOps jazzio_ops = {
>> .endianness = DEVICE_NATIVE_ENDIAN,
>> };
>>
>> +static IOMMUTLBEntry rc4030_dma_translate(MemoryRegion *iommu, hwaddr addr,
>> + bool is_write)
>> +{
>> + rc4030State *s = container_of(iommu, rc4030State, dma_mr);
>> + IOMMUTLBEntry ret = {
>> + .target_as = &address_space_memory,
>> + .iova = addr & ~(DMA_PAGESIZE - 1),
>> + .translated_addr = 0,
>> + .addr_mask = DMA_PAGESIZE - 1,
>> + .perm = IOMMU_NONE,
>> + };
>> + uint64_t i, entry_address;
>> + dma_pagetable_entry entry;
>> +
>> + i = addr / DMA_PAGESIZE;
>> + if (i < s->dma_tl_limit / sizeof(entry)) {
>> + entry_address = (s->dma_tl_base & 0x7fffffff) + i * sizeof(entry);
>> + if (address_space_read(ret.target_as, entry_address,
>> + MEMTXATTRS_UNSPECIFIED, (unsigned char *)&entry,
>> + sizeof(entry)) == MEMTX_OK) {
>> + ret.translated_addr = entry.frame & ~(DMA_PAGESIZE - 1);
>> + ret.perm = IOMMU_RW;
>> + }
>> + }
>> +
>> + return ret;
>> +}
>> +
>> +static const MemoryRegionIOMMUOps rc4030_dma_ops = {
>> + .translate = rc4030_dma_translate,
>> +};
>> +
>> static void rc4030_reset(DeviceState *dev)
>> {
>> rc4030State *s = RC4030(dev);
>> @@ -596,7 +530,6 @@ static void rc4030_reset(DeviceState *dev)
>> s->invalid_address_register = 0;
>>
>> memset(s->dma_regs, 0, sizeof(s->dma_regs));
>> - rc4030_dma_tt_update(s, 0, 0);
>>
>> s->remote_failed_address = s->memory_failed_address = 0;
>> s->cache_maint = 0;
>> @@ -735,7 +668,6 @@ static void rc4030_realize(DeviceState *dev, Error **errp)
>> {
>> rc4030State *s = RC4030(dev);
>> Object *o = OBJECT(dev);
>> - int i;
>>
>> s->periodic_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
>> rc4030_periodic_timer, s);
>> @@ -745,37 +677,19 @@ static void rc4030_realize(DeviceState *dev, Error **errp)
>> memory_region_init_io(&s->iomem_jazzio, NULL, &jazzio_ops, s,
>> "rc4030.jazzio", 0x00001000);
>>
>> - memory_region_init_rom_device(&s->dma_tt, o,
>> - &rc4030_dma_tt_ops, s, "dma-table",
>> - MAX_TL_ENTRIES * sizeof(dma_pagetable_entry),
>> - NULL);
>> - memory_region_init(&s->dma_tt_alias, o, "dma-table-alias", 0);
>> - memory_region_init(&s->dma_mr, o, "dma", INT32_MAX);
>> - for (i = 0; i < MAX_TL_ENTRIES; ++i) {
>> - memory_region_init_alias(&s->dma_mrs[i], o, "dma-alias",
>> - get_system_memory(), 0, DMA_PAGESIZE);
>> - memory_region_set_enabled(&s->dma_mrs[i], false);
>> - memory_region_add_subregion(&s->dma_mr, i * DMA_PAGESIZE,
>> - &s->dma_mrs[i]);
>> - }
>> + memory_region_init_iommu(&s->dma_mr, o, &rc4030_dma_ops,
>> + "rc4030.dma", UINT32_MAX);
>> address_space_init(&s->dma_as, &s->dma_mr, "rc4030-dma");
>> }
>>
>> static void rc4030_unrealize(DeviceState *dev, Error **errp)
>> {
>> rc4030State *s = RC4030(dev);
>> - int i;
>>
>> timer_free(s->periodic_timer);
>>
>> address_space_destroy(&s->dma_as);
>> - object_unparent(OBJECT(&s->dma_tt));
>> - object_unparent(OBJECT(&s->dma_tt_alias));
>> object_unparent(OBJECT(&s->dma_mr));
>> - for (i = 0; i < MAX_TL_ENTRIES; ++i) {
>> - memory_region_del_subregion(&s->dma_mr, &s->dma_mrs[i]);
>> - object_unparent(OBJECT(&s->dma_mrs[i]));
>> - }
>> }
>>
>> static void rc4030_class_init(ObjectClass *klass, void *class_data)
>>
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH for-2.8] dma/rc4030: translate memory accesses only when they occur
2017-02-26 19:19 ` Hervé Poussineau
@ 2017-03-10 18:31 ` Hervé Poussineau
2017-03-14 15:42 ` Yongbok Kim
0 siblings, 1 reply; 5+ messages in thread
From: Hervé Poussineau @ 2017-03-10 18:31 UTC (permalink / raw)
To: Hervé Poussineau, qemu-devel
Cc: Prasad J Pandit, Aurelien Jarno, Yongbok Kim, Peter Maydell
Ping again.
Le 26/02/2017 à 20:19, Hervé Poussineau a écrit :
> Ping again.
>
> Le 22/02/2017 à 07:19, Hervé Poussineau a écrit :
>> Ping?
>>
>> Le 18/11/2016 à 23:43, Hervé Poussineau a écrit :
>>> This simplifies the code a lot, and this fixes big memory leaks
>>> introduced in a3d586f704609a45b6037534cb2f34da5dfd8895
>>>
>>> Windows NT is now able to boot without using gigabytes of ram on the host.
>>>
>>> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
>>> ---
>>> hw/dma/rc4030.c | 158 +++++++++++++-------------------------------------------
>>> 1 file changed, 36 insertions(+), 122 deletions(-)
>>>
>>> diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c
>>> index 41fc043..5f10b9d 100644
>>> --- a/hw/dma/rc4030.c
>>> +++ b/hw/dma/rc4030.c
>>> @@ -34,8 +34,6 @@
>>> /********************************************************/
>>> /* rc4030 emulation */
>>>
>>> -#define MAX_TL_ENTRIES 512
>>> -
>>> typedef struct dma_pagetable_entry {
>>> int32_t frame;
>>> int32_t owner;
>>> @@ -91,14 +89,8 @@ typedef struct rc4030State
>>> qemu_irq timer_irq;
>>> qemu_irq jazz_bus_irq;
>>>
>>> - /* biggest translation table */
>>> - MemoryRegion dma_tt;
>>> - /* translation table memory region alias, added to system RAM */
>>> - MemoryRegion dma_tt_alias;
>>> /* whole DMA memory region, root of DMA address space */
>>> MemoryRegion dma_mr;
>>> - /* translation table entry aliases, added to DMA memory region */
>>> - MemoryRegion dma_mrs[MAX_TL_ENTRIES];
>>> AddressSpace dma_as;
>>>
>>> MemoryRegion iomem_chipset;
>>> @@ -256,96 +248,6 @@ static uint64_t rc4030_read(void *opaque, hwaddr addr, unsigned int size)
>>> return val;
>>> }
>>>
>>> -static void rc4030_dma_as_update_one(rc4030State *s, int index, uint32_t frame)
>>> -{
>>> - if (index < MAX_TL_ENTRIES) {
>>> - memory_region_set_enabled(&s->dma_mrs[index], false);
>>> - }
>>> -
>>> - if (!frame) {
>>> - return;
>>> - }
>>> -
>>> - if (index >= MAX_TL_ENTRIES) {
>>> - qemu_log_mask(LOG_UNIMP,
>>> - "rc4030: trying to use too high "
>>> - "translation table entry %d (max allowed=%d)",
>>> - index, MAX_TL_ENTRIES);
>>> - return;
>>> - }
>>> - memory_region_set_alias_offset(&s->dma_mrs[index], frame);
>>> - memory_region_set_enabled(&s->dma_mrs[index], true);
>>> -}
>>> -
>>> -static void rc4030_dma_tt_write(void *opaque, hwaddr addr, uint64_t data,
>>> - unsigned int size)
>>> -{
>>> - rc4030State *s = opaque;
>>> -
>>> - /* write memory */
>>> - memcpy(memory_region_get_ram_ptr(&s->dma_tt) + addr, &data, size);
>>> -
>>> - /* update dma address space (only if frame field has been written) */
>>> - if (addr % sizeof(dma_pagetable_entry) == 0) {
>>> - int index = addr / sizeof(dma_pagetable_entry);
>>> - memory_region_transaction_begin();
>>> - rc4030_dma_as_update_one(s, index, (uint32_t)data);
>>> - memory_region_transaction_commit();
>>> - }
>>> -}
>>> -
>>> -static const MemoryRegionOps rc4030_dma_tt_ops = {
>>> - .write = rc4030_dma_tt_write,
>>> - .impl.min_access_size = 4,
>>> - .impl.max_access_size = 4,
>>> -};
>>> -
>>> -static void rc4030_dma_tt_update(rc4030State *s, uint32_t new_tl_base,
>>> - uint32_t new_tl_limit)
>>> -{
>>> - int entries, i;
>>> - dma_pagetable_entry *dma_tl_contents;
>>> -
>>> - if (s->dma_tl_limit) {
>>> - /* write old dma tl table to physical memory */
>>> - memory_region_del_subregion(get_system_memory(), &s->dma_tt_alias);
>>> - cpu_physical_memory_write(s->dma_tl_limit & 0x7fffffff,
>>> - memory_region_get_ram_ptr(&s->dma_tt),
>>> - memory_region_size(&s->dma_tt_alias));
>>> - }
>>> - object_unparent(OBJECT(&s->dma_tt_alias));
>>> -
>>> - s->dma_tl_base = new_tl_base;
>>> - s->dma_tl_limit = new_tl_limit;
>>> - new_tl_base &= 0x7fffffff;
>>> -
>>> - if (s->dma_tl_limit) {
>>> - uint64_t dma_tt_size;
>>> - if (s->dma_tl_limit <= memory_region_size(&s->dma_tt)) {
>>> - dma_tt_size = s->dma_tl_limit;
>>> - } else {
>>> - dma_tt_size = memory_region_size(&s->dma_tt);
>>> - }
>>> - memory_region_init_alias(&s->dma_tt_alias, OBJECT(s),
>>> - "dma-table-alias",
>>> - &s->dma_tt, 0, dma_tt_size);
>>> - dma_tl_contents = memory_region_get_ram_ptr(&s->dma_tt);
>>> - cpu_physical_memory_read(new_tl_base, dma_tl_contents, dma_tt_size);
>>> -
>>> - memory_region_transaction_begin();
>>> - entries = dma_tt_size / sizeof(dma_pagetable_entry);
>>> - for (i = 0; i < entries; i++) {
>>> - rc4030_dma_as_update_one(s, i, dma_tl_contents[i].frame);
>>> - }
>>> - memory_region_add_subregion(get_system_memory(), new_tl_base,
>>> - &s->dma_tt_alias);
>>> - memory_region_transaction_commit();
>>> - } else {
>>> - memory_region_init(&s->dma_tt_alias, OBJECT(s),
>>> - "dma-table-alias", 0);
>>> - }
>>> -}
>>> -
>>> static void rc4030_write(void *opaque, hwaddr addr, uint64_t data,
>>> unsigned int size)
>>> {
>>> @@ -362,11 +264,11 @@ static void rc4030_write(void *opaque, hwaddr addr, uint64_t data,
>>> break;
>>> /* DMA transl. table base */
>>> case 0x0018:
>>> - rc4030_dma_tt_update(s, val, s->dma_tl_limit);
>>> + s->dma_tl_base = val;
>>> break;
>>> /* DMA transl. table limit */
>>> case 0x0020:
>>> - rc4030_dma_tt_update(s, s->dma_tl_base, val);
>>> + s->dma_tl_limit = val;
>>> break;
>>> /* DMA transl. table invalidated */
>>> case 0x0028:
>>> @@ -586,6 +488,38 @@ static const MemoryRegionOps jazzio_ops = {
>>> .endianness = DEVICE_NATIVE_ENDIAN,
>>> };
>>>
>>> +static IOMMUTLBEntry rc4030_dma_translate(MemoryRegion *iommu, hwaddr addr,
>>> + bool is_write)
>>> +{
>>> + rc4030State *s = container_of(iommu, rc4030State, dma_mr);
>>> + IOMMUTLBEntry ret = {
>>> + .target_as = &address_space_memory,
>>> + .iova = addr & ~(DMA_PAGESIZE - 1),
>>> + .translated_addr = 0,
>>> + .addr_mask = DMA_PAGESIZE - 1,
>>> + .perm = IOMMU_NONE,
>>> + };
>>> + uint64_t i, entry_address;
>>> + dma_pagetable_entry entry;
>>> +
>>> + i = addr / DMA_PAGESIZE;
>>> + if (i < s->dma_tl_limit / sizeof(entry)) {
>>> + entry_address = (s->dma_tl_base & 0x7fffffff) + i * sizeof(entry);
>>> + if (address_space_read(ret.target_as, entry_address,
>>> + MEMTXATTRS_UNSPECIFIED, (unsigned char *)&entry,
>>> + sizeof(entry)) == MEMTX_OK) {
>>> + ret.translated_addr = entry.frame & ~(DMA_PAGESIZE - 1);
>>> + ret.perm = IOMMU_RW;
>>> + }
>>> + }
>>> +
>>> + return ret;
>>> +}
>>> +
>>> +static const MemoryRegionIOMMUOps rc4030_dma_ops = {
>>> + .translate = rc4030_dma_translate,
>>> +};
>>> +
>>> static void rc4030_reset(DeviceState *dev)
>>> {
>>> rc4030State *s = RC4030(dev);
>>> @@ -596,7 +530,6 @@ static void rc4030_reset(DeviceState *dev)
>>> s->invalid_address_register = 0;
>>>
>>> memset(s->dma_regs, 0, sizeof(s->dma_regs));
>>> - rc4030_dma_tt_update(s, 0, 0);
>>>
>>> s->remote_failed_address = s->memory_failed_address = 0;
>>> s->cache_maint = 0;
>>> @@ -735,7 +668,6 @@ static void rc4030_realize(DeviceState *dev, Error **errp)
>>> {
>>> rc4030State *s = RC4030(dev);
>>> Object *o = OBJECT(dev);
>>> - int i;
>>>
>>> s->periodic_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
>>> rc4030_periodic_timer, s);
>>> @@ -745,37 +677,19 @@ static void rc4030_realize(DeviceState *dev, Error **errp)
>>> memory_region_init_io(&s->iomem_jazzio, NULL, &jazzio_ops, s,
>>> "rc4030.jazzio", 0x00001000);
>>>
>>> - memory_region_init_rom_device(&s->dma_tt, o,
>>> - &rc4030_dma_tt_ops, s, "dma-table",
>>> - MAX_TL_ENTRIES * sizeof(dma_pagetable_entry),
>>> - NULL);
>>> - memory_region_init(&s->dma_tt_alias, o, "dma-table-alias", 0);
>>> - memory_region_init(&s->dma_mr, o, "dma", INT32_MAX);
>>> - for (i = 0; i < MAX_TL_ENTRIES; ++i) {
>>> - memory_region_init_alias(&s->dma_mrs[i], o, "dma-alias",
>>> - get_system_memory(), 0, DMA_PAGESIZE);
>>> - memory_region_set_enabled(&s->dma_mrs[i], false);
>>> - memory_region_add_subregion(&s->dma_mr, i * DMA_PAGESIZE,
>>> - &s->dma_mrs[i]);
>>> - }
>>> + memory_region_init_iommu(&s->dma_mr, o, &rc4030_dma_ops,
>>> + "rc4030.dma", UINT32_MAX);
>>> address_space_init(&s->dma_as, &s->dma_mr, "rc4030-dma");
>>> }
>>>
>>> static void rc4030_unrealize(DeviceState *dev, Error **errp)
>>> {
>>> rc4030State *s = RC4030(dev);
>>> - int i;
>>>
>>> timer_free(s->periodic_timer);
>>>
>>> address_space_destroy(&s->dma_as);
>>> - object_unparent(OBJECT(&s->dma_tt));
>>> - object_unparent(OBJECT(&s->dma_tt_alias));
>>> object_unparent(OBJECT(&s->dma_mr));
>>> - for (i = 0; i < MAX_TL_ENTRIES; ++i) {
>>> - memory_region_del_subregion(&s->dma_mr, &s->dma_mrs[i]);
>>> - object_unparent(OBJECT(&s->dma_mrs[i]));
>>> - }
>>> }
>>>
>>> static void rc4030_class_init(ObjectClass *klass, void *class_data)
>>>
>>
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH for-2.8] dma/rc4030: translate memory accesses only when they occur
2017-03-10 18:31 ` Hervé Poussineau
@ 2017-03-14 15:42 ` Yongbok Kim
0 siblings, 0 replies; 5+ messages in thread
From: Yongbok Kim @ 2017-03-14 15:42 UTC (permalink / raw)
To: Hervé Poussineau, qemu-devel
Cc: Prasad J Pandit, Aurelien Jarno, Peter Maydell
On 10/03/2017 18:31, Hervé Poussineau wrote:
> Ping again.
>
> Le 26/02/2017 à 20:19, Hervé Poussineau a écrit :
>> Ping again.
>>
>> Le 22/02/2017 à 07:19, Hervé Poussineau a écrit :
>>> Ping?
>>>
>>> Le 18/11/2016 à 23:43, Hervé Poussineau a écrit :
>>>> This simplifies the code a lot, and this fixes big memory leaks
>>>> introduced in a3d586f704609a45b6037534cb2f34da5dfd8895
>>>>
>>>> Windows NT is now able to boot without using gigabytes of ram on the host.
>>>>
>>>> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
>>>> ---
>>>> hw/dma/rc4030.c | 158
>>>> +++++++++++++-------------------------------------------
>>>> 1 file changed, 36 insertions(+), 122 deletions(-)
>>>>
>>>> diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c
>>>> index 41fc043..5f10b9d 100644
>>>> --- a/hw/dma/rc4030.c
>>>> +++ b/hw/dma/rc4030.c
>>>> @@ -34,8 +34,6 @@
>>>> /********************************************************/
>>>> /* rc4030 emulation */
>>>>
>>>> -#define MAX_TL_ENTRIES 512
>>>> -
>>>> typedef struct dma_pagetable_entry {
>>>> int32_t frame;
>>>> int32_t owner;
>>>> @@ -91,14 +89,8 @@ typedef struct rc4030State
>>>> qemu_irq timer_irq;
>>>> qemu_irq jazz_bus_irq;
>>>>
>>>> - /* biggest translation table */
>>>> - MemoryRegion dma_tt;
>>>> - /* translation table memory region alias, added to system RAM */
>>>> - MemoryRegion dma_tt_alias;
>>>> /* whole DMA memory region, root of DMA address space */
>>>> MemoryRegion dma_mr;
>>>> - /* translation table entry aliases, added to DMA memory region */
>>>> - MemoryRegion dma_mrs[MAX_TL_ENTRIES];
>>>> AddressSpace dma_as;
>>>>
>>>> MemoryRegion iomem_chipset;
>>>> @@ -256,96 +248,6 @@ static uint64_t rc4030_read(void *opaque, hwaddr
>>>> addr, unsigned int size)
>>>> return val;
>>>> }
>>>>
>>>> -static void rc4030_dma_as_update_one(rc4030State *s, int index,
>>>> uint32_t frame)
>>>> -{
>>>> - if (index < MAX_TL_ENTRIES) {
>>>> - memory_region_set_enabled(&s->dma_mrs[index], false);
>>>> - }
>>>> -
>>>> - if (!frame) {
>>>> - return;
>>>> - }
>>>> -
>>>> - if (index >= MAX_TL_ENTRIES) {
>>>> - qemu_log_mask(LOG_UNIMP,
>>>> - "rc4030: trying to use too high "
>>>> - "translation table entry %d (max allowed=%d)",
>>>> - index, MAX_TL_ENTRIES);
>>>> - return;
>>>> - }
>>>> - memory_region_set_alias_offset(&s->dma_mrs[index], frame);
>>>> - memory_region_set_enabled(&s->dma_mrs[index], true);
>>>> -}
>>>> -
>>>> -static void rc4030_dma_tt_write(void *opaque, hwaddr addr, uint64_t data,
>>>> - unsigned int size)
>>>> -{
>>>> - rc4030State *s = opaque;
>>>> -
>>>> - /* write memory */
>>>> - memcpy(memory_region_get_ram_ptr(&s->dma_tt) + addr, &data, size);
>>>> -
>>>> - /* update dma address space (only if frame field has been written) */
>>>> - if (addr % sizeof(dma_pagetable_entry) == 0) {
>>>> - int index = addr / sizeof(dma_pagetable_entry);
>>>> - memory_region_transaction_begin();
>>>> - rc4030_dma_as_update_one(s, index, (uint32_t)data);
>>>> - memory_region_transaction_commit();
>>>> - }
>>>> -}
>>>> -
>>>> -static const MemoryRegionOps rc4030_dma_tt_ops = {
>>>> - .write = rc4030_dma_tt_write,
>>>> - .impl.min_access_size = 4,
>>>> - .impl.max_access_size = 4,
>>>> -};
>>>> -
>>>> -static void rc4030_dma_tt_update(rc4030State *s, uint32_t new_tl_base,
>>>> - uint32_t new_tl_limit)
>>>> -{
>>>> - int entries, i;
>>>> - dma_pagetable_entry *dma_tl_contents;
>>>> -
>>>> - if (s->dma_tl_limit) {
>>>> - /* write old dma tl table to physical memory */
>>>> - memory_region_del_subregion(get_system_memory(),
>>>> &s->dma_tt_alias);
>>>> - cpu_physical_memory_write(s->dma_tl_limit & 0x7fffffff,
>>>> - memory_region_get_ram_ptr(&s->dma_tt),
>>>> - memory_region_size(&s->dma_tt_alias));
>>>> - }
>>>> - object_unparent(OBJECT(&s->dma_tt_alias));
>>>> -
>>>> - s->dma_tl_base = new_tl_base;
>>>> - s->dma_tl_limit = new_tl_limit;
>>>> - new_tl_base &= 0x7fffffff;
>>>> -
>>>> - if (s->dma_tl_limit) {
>>>> - uint64_t dma_tt_size;
>>>> - if (s->dma_tl_limit <= memory_region_size(&s->dma_tt)) {
>>>> - dma_tt_size = s->dma_tl_limit;
>>>> - } else {
>>>> - dma_tt_size = memory_region_size(&s->dma_tt);
>>>> - }
>>>> - memory_region_init_alias(&s->dma_tt_alias, OBJECT(s),
>>>> - "dma-table-alias",
>>>> - &s->dma_tt, 0, dma_tt_size);
>>>> - dma_tl_contents = memory_region_get_ram_ptr(&s->dma_tt);
>>>> - cpu_physical_memory_read(new_tl_base, dma_tl_contents,
>>>> dma_tt_size);
>>>> -
>>>> - memory_region_transaction_begin();
>>>> - entries = dma_tt_size / sizeof(dma_pagetable_entry);
>>>> - for (i = 0; i < entries; i++) {
>>>> - rc4030_dma_as_update_one(s, i, dma_tl_contents[i].frame);
>>>> - }
>>>> - memory_region_add_subregion(get_system_memory(), new_tl_base,
>>>> - &s->dma_tt_alias);
>>>> - memory_region_transaction_commit();
>>>> - } else {
>>>> - memory_region_init(&s->dma_tt_alias, OBJECT(s),
>>>> - "dma-table-alias", 0);
>>>> - }
>>>> -}
>>>> -
>>>> static void rc4030_write(void *opaque, hwaddr addr, uint64_t data,
>>>> unsigned int size)
>>>> {
>>>> @@ -362,11 +264,11 @@ static void rc4030_write(void *opaque, hwaddr
>>>> addr, uint64_t data,
>>>> break;
>>>> /* DMA transl. table base */
>>>> case 0x0018:
>>>> - rc4030_dma_tt_update(s, val, s->dma_tl_limit);
>>>> + s->dma_tl_base = val;
>>>> break;
>>>> /* DMA transl. table limit */
>>>> case 0x0020:
>>>> - rc4030_dma_tt_update(s, s->dma_tl_base, val);
>>>> + s->dma_tl_limit = val;
>>>> break;
>>>> /* DMA transl. table invalidated */
>>>> case 0x0028:
>>>> @@ -586,6 +488,38 @@ static const MemoryRegionOps jazzio_ops = {
>>>> .endianness = DEVICE_NATIVE_ENDIAN,
>>>> };
>>>>
>>>> +static IOMMUTLBEntry rc4030_dma_translate(MemoryRegion *iommu, hwaddr
>>>> addr,
>>>> + bool is_write)
>>>> +{
>>>> + rc4030State *s = container_of(iommu, rc4030State, dma_mr);
>>>> + IOMMUTLBEntry ret = {
>>>> + .target_as = &address_space_memory,
>>>> + .iova = addr & ~(DMA_PAGESIZE - 1),
>>>> + .translated_addr = 0,
>>>> + .addr_mask = DMA_PAGESIZE - 1,
>>>> + .perm = IOMMU_NONE,
>>>> + };
>>>> + uint64_t i, entry_address;
>>>> + dma_pagetable_entry entry;
>>>> +
>>>> + i = addr / DMA_PAGESIZE;
>>>> + if (i < s->dma_tl_limit / sizeof(entry)) {
>>>> + entry_address = (s->dma_tl_base & 0x7fffffff) + i *
>>>> sizeof(entry);
>>>> + if (address_space_read(ret.target_as, entry_address,
>>>> + MEMTXATTRS_UNSPECIFIED, (unsigned char
>>>> *)&entry,
>>>> + sizeof(entry)) == MEMTX_OK) {
>>>> + ret.translated_addr = entry.frame & ~(DMA_PAGESIZE - 1);
>>>> + ret.perm = IOMMU_RW;
>>>> + }
>>>> + }
>>>> +
>>>> + return ret;
>>>> +}
>>>> +
>>>> +static const MemoryRegionIOMMUOps rc4030_dma_ops = {
>>>> + .translate = rc4030_dma_translate,
>>>> +};
>>>> +
>>>> static void rc4030_reset(DeviceState *dev)
>>>> {
>>>> rc4030State *s = RC4030(dev);
>>>> @@ -596,7 +530,6 @@ static void rc4030_reset(DeviceState *dev)
>>>> s->invalid_address_register = 0;
>>>>
>>>> memset(s->dma_regs, 0, sizeof(s->dma_regs));
>>>> - rc4030_dma_tt_update(s, 0, 0);
>>>>
>>>> s->remote_failed_address = s->memory_failed_address = 0;
>>>> s->cache_maint = 0;
>>>> @@ -735,7 +668,6 @@ static void rc4030_realize(DeviceState *dev, Error
>>>> **errp)
>>>> {
>>>> rc4030State *s = RC4030(dev);
>>>> Object *o = OBJECT(dev);
>>>> - int i;
>>>>
>>>> s->periodic_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
>>>> rc4030_periodic_timer, s);
>>>> @@ -745,37 +677,19 @@ static void rc4030_realize(DeviceState *dev,
>>>> Error **errp)
>>>> memory_region_init_io(&s->iomem_jazzio, NULL, &jazzio_ops, s,
>>>> "rc4030.jazzio", 0x00001000);
>>>>
>>>> - memory_region_init_rom_device(&s->dma_tt, o,
>>>> - &rc4030_dma_tt_ops, s, "dma-table",
>>>> - MAX_TL_ENTRIES *
>>>> sizeof(dma_pagetable_entry),
>>>> - NULL);
>>>> - memory_region_init(&s->dma_tt_alias, o, "dma-table-alias", 0);
>>>> - memory_region_init(&s->dma_mr, o, "dma", INT32_MAX);
>>>> - for (i = 0; i < MAX_TL_ENTRIES; ++i) {
>>>> - memory_region_init_alias(&s->dma_mrs[i], o, "dma-alias",
>>>> - get_system_memory(), 0, DMA_PAGESIZE);
>>>> - memory_region_set_enabled(&s->dma_mrs[i], false);
>>>> - memory_region_add_subregion(&s->dma_mr, i * DMA_PAGESIZE,
>>>> - &s->dma_mrs[i]);
>>>> - }
>>>> + memory_region_init_iommu(&s->dma_mr, o, &rc4030_dma_ops,
>>>> + "rc4030.dma", UINT32_MAX);
>>>> address_space_init(&s->dma_as, &s->dma_mr, "rc4030-dma");
>>>> }
>>>>
>>>> static void rc4030_unrealize(DeviceState *dev, Error **errp)
>>>> {
>>>> rc4030State *s = RC4030(dev);
>>>> - int i;
>>>>
>>>> timer_free(s->periodic_timer);
>>>>
>>>> address_space_destroy(&s->dma_as);
>>>> - object_unparent(OBJECT(&s->dma_tt));
>>>> - object_unparent(OBJECT(&s->dma_tt_alias));
>>>> object_unparent(OBJECT(&s->dma_mr));
>>>> - for (i = 0; i < MAX_TL_ENTRIES; ++i) {
>>>> - memory_region_del_subregion(&s->dma_mr, &s->dma_mrs[i]);
>>>> - object_unparent(OBJECT(&s->dma_mrs[i]));
>>>> - }
>>>> }
>>>>
>>>> static void rc4030_class_init(ObjectClass *klass, void *class_data)
>>>>
>>>
>>
>
Reviewed-by: Yongbok Kim <yongbok.kim@imgtec.com>
Regards,
Yongbok
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2017-03-14 15:42 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-18 22:43 [Qemu-devel] [PATCH for-2.8] dma/rc4030: translate memory accesses only when they occur Hervé Poussineau
2017-02-22 6:19 ` Hervé Poussineau
2017-02-26 19:19 ` Hervé Poussineau
2017-03-10 18:31 ` Hervé Poussineau
2017-03-14 15:42 ` Yongbok Kim
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.