|
@@ -1369,6 +1369,11 @@ static void *file_ram_alloc(RAMBlock *block,
|
|
error_setg(errp, "alignment 0x%" PRIx64
|
|
error_setg(errp, "alignment 0x%" PRIx64
|
|
" must be a power of two", block->mr->align);
|
|
" must be a power of two", block->mr->align);
|
|
return NULL;
|
|
return NULL;
|
|
|
|
+ } else if (offset % block->page_size) {
|
|
|
|
+ error_setg(errp, "offset 0x%" PRIx64
|
|
|
|
+ " must be multiples of page size 0x%zx",
|
|
|
|
+ offset, block->page_size);
|
|
|
|
+ return NULL;
|
|
}
|
|
}
|
|
block->mr->align = MAX(block->page_size, block->mr->align);
|
|
block->mr->align = MAX(block->page_size, block->mr->align);
|
|
#if defined(__s390x__)
|
|
#if defined(__s390x__)
|
|
@@ -1400,7 +1405,7 @@ static void *file_ram_alloc(RAMBlock *block,
|
|
* those labels. Therefore, extending the non-empty backend file
|
|
* those labels. Therefore, extending the non-empty backend file
|
|
* is disabled as well.
|
|
* is disabled as well.
|
|
*/
|
|
*/
|
|
- if (truncate && ftruncate(fd, memory)) {
|
|
|
|
|
|
+ if (truncate && ftruncate(fd, offset + memory)) {
|
|
perror("ftruncate");
|
|
perror("ftruncate");
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1416,6 +1421,7 @@ static void *file_ram_alloc(RAMBlock *block,
|
|
}
|
|
}
|
|
|
|
|
|
block->fd = fd;
|
|
block->fd = fd;
|
|
|
|
+ block->fd_offset = offset;
|
|
return area;
|
|
return area;
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
@@ -1889,7 +1895,7 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr,
|
|
|
|
|
|
size = HOST_PAGE_ALIGN(size);
|
|
size = HOST_PAGE_ALIGN(size);
|
|
file_size = get_file_size(fd);
|
|
file_size = get_file_size(fd);
|
|
- if (file_size > 0 && file_size < size) {
|
|
|
|
|
|
+ if (file_size > offset && file_size < (offset + size)) {
|
|
error_setg(errp, "backing store size 0x%" PRIx64
|
|
error_setg(errp, "backing store size 0x%" PRIx64
|
|
" does not match 'size' option 0x" RAM_ADDR_FMT,
|
|
" does not match 'size' option 0x" RAM_ADDR_FMT,
|
|
file_size, size);
|
|
file_size, size);
|
|
@@ -1929,7 +1935,7 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr,
|
|
|
|
|
|
RAMBlock *qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr,
|
|
RAMBlock *qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr,
|
|
uint32_t ram_flags, const char *mem_path,
|
|
uint32_t ram_flags, const char *mem_path,
|
|
- bool readonly, Error **errp)
|
|
|
|
|
|
+ off_t offset, bool readonly, Error **errp)
|
|
{
|
|
{
|
|
int fd;
|
|
int fd;
|
|
bool created;
|
|
bool created;
|
|
@@ -1941,7 +1947,8 @@ RAMBlock *qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr,
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
- block = qemu_ram_alloc_from_fd(size, mr, ram_flags, fd, 0, readonly, errp);
|
|
|
|
|
|
+ block = qemu_ram_alloc_from_fd(size, mr, ram_flags, fd, offset, readonly,
|
|
|
|
+ errp);
|
|
if (!block) {
|
|
if (!block) {
|
|
if (created) {
|
|
if (created) {
|
|
unlink(mem_path);
|
|
unlink(mem_path);
|
|
@@ -2075,7 +2082,7 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
|
|
flags |= block->flags & RAM_NORESERVE ? MAP_NORESERVE : 0;
|
|
flags |= block->flags & RAM_NORESERVE ? MAP_NORESERVE : 0;
|
|
if (block->fd >= 0) {
|
|
if (block->fd >= 0) {
|
|
area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
|
|
area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
|
|
- flags, block->fd, offset);
|
|
|
|
|
|
+ flags, block->fd, offset + block->fd_offset);
|
|
} else {
|
|
} else {
|
|
flags |= MAP_ANONYMOUS;
|
|
flags |= MAP_ANONYMOUS;
|
|
area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
|
|
area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
|