* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
+
#include "qemu/osdep.h"
+#include "qemu-common.h"
#include "qapi/error.h"
#include "qemu/cutils.h"
#endif
#include "sysemu/kvm.h"
#include "sysemu/sysemu.h"
+#include "sysemu/tcg.h"
#include "qemu/timer.h"
#include "qemu/config-file.h"
#include "qemu/error-report.h"
+#include "qemu/qemu-print.h"
#if defined(CONFIG_USER_ONLY)
#include "qemu.h"
#else /* !CONFIG_USER_ONLY */
#endif
}
-const char *parse_cpu_model(const char *cpu_model)
+const char *parse_cpu_option(const char *cpu_option)
{
ObjectClass *oc;
CPUClass *cc;
gchar **model_pieces;
const char *cpu_type;
- model_pieces = g_strsplit(cpu_model, ",", 2);
+ model_pieces = g_strsplit(cpu_option, ",", 2);
+ if (!model_pieces[0]) {
+ error_report("-cpu option cannot be empty");
+ exit(1);
+ }
oc = cpu_class_by_name(CPU_RESOLVING_TYPE, model_pieces[0]);
if (oc == NULL) {
fprintf(stderr, "qemu: fatal: ");
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
- cpu_dump_state(cpu, stderr, fprintf, CPU_DUMP_FPU | CPU_DUMP_CCOP);
+ cpu_dump_state(cpu, stderr, CPU_DUMP_FPU | CPU_DUMP_CCOP);
if (qemu_log_separate()) {
qemu_log_lock();
qemu_log("qemu: fatal: ");
phys_page_set(d, start_addr >> TARGET_PAGE_BITS, num_pages, section_index);
}
+/*
+ * The range in *section* may look like this:
+ *
+ * |s|PPPPPPP|s|
+ *
+ * where s stands for subpage and P for page.
+ */
void flatview_add_to_dispatch(FlatView *fv, MemoryRegionSection *section)
{
- MemoryRegionSection now = *section, remain = *section;
+ MemoryRegionSection remain = *section;
Int128 page_size = int128_make64(TARGET_PAGE_SIZE);
- if (now.offset_within_address_space & ~TARGET_PAGE_MASK) {
- uint64_t left = TARGET_PAGE_ALIGN(now.offset_within_address_space)
- - now.offset_within_address_space;
+ /* register first subpage */
+ if (remain.offset_within_address_space & ~TARGET_PAGE_MASK) {
+ uint64_t left = TARGET_PAGE_ALIGN(remain.offset_within_address_space)
+ - remain.offset_within_address_space;
+ MemoryRegionSection now = remain;
now.size = int128_min(int128_make64(left), now.size);
register_subpage(fv, &now);
- } else {
- now.size = int128_zero();
- }
- while (int128_ne(remain.size, now.size)) {
+ if (int128_eq(remain.size, now.size)) {
+ return;
+ }
remain.size = int128_sub(remain.size, now.size);
remain.offset_within_address_space += int128_get64(now.size);
remain.offset_within_region += int128_get64(now.size);
- now = remain;
- if (int128_lt(remain.size, page_size)) {
- register_subpage(fv, &now);
- } else if (remain.offset_within_address_space & ~TARGET_PAGE_MASK) {
- now.size = page_size;
- register_subpage(fv, &now);
- } else {
- now.size = int128_and(now.size, int128_neg(page_size));
- register_multipage(fv, &now);
+ }
+
+ /* register whole pages */
+ if (int128_ge(remain.size, page_size)) {
+ MemoryRegionSection now = remain;
+ now.size = int128_and(now.size, int128_neg(page_size));
+ register_multipage(fv, &now);
+ if (int128_eq(remain.size, now.size)) {
+ return;
}
+ remain.size = int128_sub(remain.size, now.size);
+ remain.offset_within_address_space += int128_get64(now.size);
+ remain.offset_within_region += int128_get64(now.size);
}
+
+ /* register last subpage */
+ register_subpage(fv, &remain);
}
void qemu_flush_coalesced_mmio_buffer(void)
* when we actually open and map them. Iterate over the file
* descriptors instead, and use qemu_fd_getpagesize().
*/
-static int find_max_supported_pagesize(Object *obj, void *opaque)
+static int find_min_backend_pagesize(Object *obj, void *opaque)
{
long *hpsize_min = opaque;
if (object_dynamic_cast(obj, TYPE_MEMORY_BACKEND)) {
- long hpsize = host_memory_backend_pagesize(MEMORY_BACKEND(obj));
+ HostMemoryBackend *backend = MEMORY_BACKEND(obj);
+ long hpsize = host_memory_backend_pagesize(backend);
- if (hpsize < *hpsize_min) {
+ if (host_memory_backend_is_mapped(backend) && (hpsize < *hpsize_min)) {
*hpsize_min = hpsize;
}
}
return 0;
}
-long qemu_getrampagesize(void)
+static int find_max_backend_pagesize(Object *obj, void *opaque)
+{
+ long *hpsize_max = opaque;
+
+ if (object_dynamic_cast(obj, TYPE_MEMORY_BACKEND)) {
+ HostMemoryBackend *backend = MEMORY_BACKEND(obj);
+ long hpsize = host_memory_backend_pagesize(backend);
+
+ if (host_memory_backend_is_mapped(backend) && (hpsize > *hpsize_max)) {
+ *hpsize_max = hpsize;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * TODO: We assume right now that all mapped host memory backends are
+ * used as RAM, however some might be used for different purposes.
+ */
+long qemu_minrampagesize(void)
{
long hpsize = LONG_MAX;
long mainrampagesize;
*/
memdev_root = object_resolve_path("/objects", NULL);
if (memdev_root) {
- object_child_foreach(memdev_root, find_max_supported_pagesize, &hpsize);
+ object_child_foreach(memdev_root, find_min_backend_pagesize, &hpsize);
}
if (hpsize == LONG_MAX) {
/* No additional memory regions found ==> Report main RAM page size */
return hpsize;
}
+
+long qemu_maxrampagesize(void)
+{
+ long pagesize = qemu_mempath_getpagesize(mem_path);
+ Object *memdev_root = object_resolve_path("/objects", NULL);
+
+ if (memdev_root) {
+ object_child_foreach(memdev_root, find_max_backend_pagesize,
+ &pagesize);
+ }
+ return pagesize;
+}
#else
-long qemu_getrampagesize(void)
+long qemu_minrampagesize(void)
+{
+ return getpagesize();
+}
+long qemu_maxrampagesize(void)
{
return getpagesize();
}
}
area = qemu_ram_mmap(fd, memory, block->mr->align,
- block->flags & RAM_SHARED);
+ block->flags & RAM_SHARED, block->flags & RAM_PMEM);
if (area == MAP_FAILED) {
error_setg_errno(errp, errno,
"unable to map backing store for guest RAM");
return rb->idstr;
}
+void *qemu_ram_get_host_addr(RAMBlock *rb)
+{
+ return rb->host;
+}
+
+ram_addr_t qemu_ram_get_offset(RAMBlock *rb)
+{
+ return rb->offset;
+}
+
+ram_addr_t qemu_ram_get_used_length(RAMBlock *rb)
+{
+ return rb->used_length;
+}
+
bool qemu_ram_is_shared(RAMBlock *rb)
{
return rb->flags & RAM_SHARED;
rcu_read_lock();
RAMBLOCK_FOREACH(block) {
- ret = func(block->idstr, block->host, block->offset,
- block->used_length, opaque);
- if (ret) {
- break;
- }
- }
- rcu_read_unlock();
- return ret;
-}
-
-int qemu_ram_foreach_migratable_block(RAMBlockIterFunc func, void *opaque)
-{
- RAMBlock *block;
- int ret = 0;
-
- rcu_read_lock();
- RAMBLOCK_FOREACH(block) {
- if (!qemu_ram_is_migratable(block)) {
- continue;
- }
- ret = func(block->idstr, block->host, block->offset,
- block->used_length, opaque);
+ ret = func(block, opaque);
if (ret) {
break;
}
#if !defined(CONFIG_USER_ONLY)
-static void mtree_print_phys_entries(fprintf_function mon, void *f,
- int start, int end, int skip, int ptr)
+static void mtree_print_phys_entries(int start, int end, int skip, int ptr)
{
if (start == end - 1) {
- mon(f, "\t%3d ", start);
+ qemu_printf("\t%3d ", start);
} else {
- mon(f, "\t%3d..%-3d ", start, end - 1);
+ qemu_printf("\t%3d..%-3d ", start, end - 1);
}
- mon(f, " skip=%d ", skip);
+ qemu_printf(" skip=%d ", skip);
if (ptr == PHYS_MAP_NODE_NIL) {
- mon(f, " ptr=NIL");
+ qemu_printf(" ptr=NIL");
} else if (!skip) {
- mon(f, " ptr=#%d", ptr);
+ qemu_printf(" ptr=#%d", ptr);
} else {
- mon(f, " ptr=[%d]", ptr);
+ qemu_printf(" ptr=[%d]", ptr);
}
- mon(f, "\n");
+ qemu_printf("\n");
}
#define MR_SIZE(size) (int128_nz(size) ? (hwaddr)int128_get64( \
int128_sub((size), int128_one())) : 0)
-void mtree_print_dispatch(fprintf_function mon, void *f,
- AddressSpaceDispatch *d, MemoryRegion *root)
+void mtree_print_dispatch(AddressSpaceDispatch *d, MemoryRegion *root)
{
int i;
- mon(f, " Dispatch\n");
- mon(f, " Physical sections\n");
+ qemu_printf(" Dispatch\n");
+ qemu_printf(" Physical sections\n");
for (i = 0; i < d->map.sections_nb; ++i) {
MemoryRegionSection *s = d->map.sections + i;
const char *names[] = { " [unassigned]", " [not dirty]",
" [ROM]", " [watch]" };
- mon(f, " #%d @" TARGET_FMT_plx ".." TARGET_FMT_plx " %s%s%s%s%s",
+ qemu_printf(" #%d @" TARGET_FMT_plx ".." TARGET_FMT_plx
+ " %s%s%s%s%s",
i,
s->offset_within_address_space,
s->offset_within_address_space + MR_SIZE(s->mr->size),
s->mr->is_iommu ? " [iommu]" : "");
if (s->mr->alias) {
- mon(f, " alias=%s", s->mr->alias->name ?
+ qemu_printf(" alias=%s", s->mr->alias->name ?
s->mr->alias->name : "noname");
}
- mon(f, "\n");
+ qemu_printf("\n");
}
- mon(f, " Nodes (%d bits per level, %d levels) ptr=[%d] skip=%d\n",
+ qemu_printf(" Nodes (%d bits per level, %d levels) ptr=[%d] skip=%d\n",
P_L2_BITS, P_L2_LEVELS, d->phys_map.ptr, d->phys_map.skip);
for (i = 0; i < d->map.nodes_nb; ++i) {
int j, jprev;
PhysPageEntry prev;
Node *n = d->map.nodes + i;
- mon(f, " [%d]\n", i);
+ qemu_printf(" [%d]\n", i);
for (j = 0, jprev = 0, prev = *n[0]; j < ARRAY_SIZE(*n); ++j) {
PhysPageEntry *pe = *n + j;
continue;
}
- mtree_print_phys_entries(mon, f, jprev, j, prev.skip, prev.ptr);
+ mtree_print_phys_entries(jprev, j, prev.skip, prev.ptr);
jprev = j;
prev = *pe;
}
if (jprev != ARRAY_SIZE(*n)) {
- mtree_print_phys_entries(mon, f, jprev, j, prev.skip, prev.ptr);
+ mtree_print_phys_entries(jprev, j, prev.skip, prev.ptr);
}
}
}