Patchwork [v5,2/5] Support adding a file to qemu's ram allocation

login
register
mail settings
Submitter Cam Macdonell
Date April 21, 2010, 5:53 p.m.
Message ID <1271872408-22842-3-git-send-email-cam@cs.ualberta.ca>
Download mbox | patch
Permalink /patch/50669/
State New
Headers show

Comments

Cam Macdonell - April 21, 2010, 5:53 p.m.
This avoids the need of using qemu_ram_alloc and mmap with MAP_FIXED to map a
host file into guest RAM.  This function mmaps the opened file anywhere and adds
the memory to the ram blocks.

Usage is

qemu_ram_mmap(fd, size, MAP_SHARED, offset);
---
 cpu-common.h |    2 ++
 exec.c       |   36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+), 0 deletions(-)
Avi Kivity - May 10, 2010, 10:39 a.m.
On 04/21/2010 08:53 PM, Cam Macdonell wrote:
> This avoids the need of using qemu_ram_alloc and mmap with MAP_FIXED to map a
> host file into guest RAM.  This function mmaps the opened file anywhere and adds
> the memory to the ram blocks.
>
> Usage is
>
> qemu_ram_mmap(fd, size, MAP_SHARED, offset);
>    

Signoff?
>
> +ram_addr_t qemu_ram_mmap(int fd, ram_addr_t size, int flags, off_t offset)
> +{
> +    RAMBlock *new_block;
> +
> +    size = TARGET_PAGE_ALIGN(size);
> +    new_block = qemu_malloc(sizeof(*new_block));
> +
> +    /* map the file passed as a parameter to be this part of memory */
> +    new_block->host = mmap(0, size, PROT_READ|PROT_WRITE, flags, fd, offset);
> +
> +    if (new_block->host == MAP_FAILED)
> +        exit(1);
>    

Braces after if ()

> +    if (kvm_enabled())
> +        kvm_setup_guest_memory(new_block->host, size);
> +
>    

More braces.
Cam Macdonell - May 10, 2010, 3:32 p.m.
On Mon, May 10, 2010 at 4:39 AM, Avi Kivity <avi@redhat.com> wrote:
> On 04/21/2010 08:53 PM, Cam Macdonell wrote:
>>
>> This avoids the need of using qemu_ram_alloc and mmap with MAP_FIXED to
>> map a
>> host file into guest RAM.  This function mmaps the opened file anywhere
>> and adds
>> the memory to the ram blocks.
>>
>> Usage is
>>
>> qemu_ram_mmap(fd, size, MAP_SHARED, offset);
>>
>
> Signoff?
>>
>> +ram_addr_t qemu_ram_mmap(int fd, ram_addr_t size, int flags, off_t
>> offset)
>> +{
>> +    RAMBlock *new_block;
>> +
>> +    size = TARGET_PAGE_ALIGN(size);
>> +    new_block = qemu_malloc(sizeof(*new_block));
>> +
>> +    /* map the file passed as a parameter to be this part of memory */
>> +    new_block->host = mmap(0, size, PROT_READ|PROT_WRITE, flags, fd,
>> offset);
>> +
>> +    if (new_block->host == MAP_FAILED)
>> +        exit(1);
>>
>
> Braces after if ()
>
>> +    if (kvm_enabled())
>> +        kvm_setup_guest_memory(new_block->host, size);
>> +
>>
>
> More braces.
>

This function is possibly made redundant by Marcelo's patch for qemu_ram_map

http://kerneltrap.org/mailarchive/linux-kvm/2010/4/26/6261299

qemu_ram_map isn't merged yet either, but I'm fine with either one.
Marcelo's requires the device to map the memory and then pass the
pointer to be added to the memory allocation, so it gives the device
full mapping control.  Alternatively, I could add the protection flag
to my function (I think that's all that is missing).

Let me know and I'll change my patch if necessary.

> --
> error compiling committee.c: too many arguments to function
>
>

Patch

diff --git a/cpu-common.h b/cpu-common.h
index 49c7fb3..d7c7d3a 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -9,6 +9,7 @@ 
 
 #include "bswap.h"
 #include "qemu-queue.h"
+#include <sys/types.h>
 
 #if !defined(CONFIG_USER_ONLY)
 
@@ -32,6 +33,7 @@  static inline void cpu_register_physical_memory(target_phys_addr_t start_addr,
 }
 
 ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr);
+ram_addr_t qemu_ram_mmap(int fd, ram_addr_t addr, int flags, off_t offset);
 ram_addr_t qemu_ram_alloc(ram_addr_t);
 void qemu_ram_free(ram_addr_t addr);
 /* This should only be used for ram local to a device.  */
diff --git a/exec.c b/exec.c
index 467a0e7..702348e 100644
--- a/exec.c
+++ b/exec.c
@@ -2811,6 +2811,42 @@  static void *file_ram_alloc(ram_addr_t memory, const char *path)
 }
 #endif
 
+ram_addr_t qemu_ram_mmap(int fd, ram_addr_t size, int flags, off_t offset)
+{
+    RAMBlock *new_block;
+
+    size = TARGET_PAGE_ALIGN(size);
+    new_block = qemu_malloc(sizeof(*new_block));
+
+    /* map the file passed as a parameter to be this part of memory */
+    new_block->host = mmap(0, size, PROT_READ|PROT_WRITE, flags, fd, offset);
+
+    if (new_block->host == MAP_FAILED)
+        exit(1);
+
+#ifdef MADV_MERGEABLE
+    madvise(new_block->host, size, MADV_MERGEABLE);
+#endif
+
+    new_block->offset = last_ram_offset;
+    new_block->length = size;
+
+    new_block->next = ram_blocks;
+    ram_blocks = new_block;
+
+    phys_ram_dirty = qemu_realloc(phys_ram_dirty,
+        (last_ram_offset + size) >> TARGET_PAGE_BITS);
+    memset(phys_ram_dirty + (last_ram_offset >> TARGET_PAGE_BITS),
+           0xff, size >> TARGET_PAGE_BITS);
+
+    last_ram_offset += size;
+
+    if (kvm_enabled())
+        kvm_setup_guest_memory(new_block->host, size);
+
+    return new_block->offset;
+}
+
 ram_addr_t qemu_ram_alloc(ram_addr_t size)
 {
     RAMBlock *new_block;