s390: autodetect map private
By default qemu will use MAP_PRIVATE for guest pages. This will write protect pages and thus break on s390 systems that dont support this feature. Therefore qemu has a hack to always use MAP_SHARED for s390. But MAP_SHARED has other problems (no dirty pages tracking, a lot more swap overhead etc.) Newer systems allow the distinction via KVM_CAP_S390_COW. With this feature qemu can use the standard qemu alloc if available, otherwise it will use the old s390 hack. Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com> Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com> Acked-by: Jan Kiszka <jan.kiszka@siemens.com> Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
parent
9233685597
commit
fdec991857
18
exec.c
18
exec.c
@ -2536,26 +2536,14 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
|
||||
exit(1);
|
||||
#endif
|
||||
} else {
|
||||
#if defined(TARGET_S390X) && defined(CONFIG_KVM)
|
||||
/* S390 KVM requires the topmost vma of the RAM to be smaller than
|
||||
an system defined value, which is at least 256GB. Larger systems
|
||||
have larger values. We put the guest between the end of data
|
||||
segment (system break) and this value. We use 32GB as a base to
|
||||
have enough room for the system break to grow. */
|
||||
new_block->host = mmap((void*)0x800000000, size,
|
||||
PROT_EXEC|PROT_READ|PROT_WRITE,
|
||||
MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
|
||||
if (new_block->host == MAP_FAILED) {
|
||||
fprintf(stderr, "Allocating RAM failed\n");
|
||||
abort();
|
||||
}
|
||||
#else
|
||||
if (xen_enabled()) {
|
||||
xen_ram_alloc(new_block->offset, size, mr);
|
||||
} else if (kvm_enabled()) {
|
||||
/* some s390/kvm configurations have special constraints */
|
||||
new_block->host = kvm_vmalloc(size);
|
||||
} else {
|
||||
new_block->host = qemu_vmalloc(size);
|
||||
}
|
||||
#endif
|
||||
qemu_madvise(new_block->host, size, QEMU_MADV_MERGEABLE);
|
||||
}
|
||||
}
|
||||
|
13
kvm-all.c
13
kvm-all.c
@ -1655,6 +1655,19 @@ int kvm_allows_irq0_override(void)
|
||||
return !kvm_irqchip_in_kernel() || kvm_has_gsi_routing();
|
||||
}
|
||||
|
||||
void *kvm_vmalloc(ram_addr_t size)
|
||||
{
|
||||
#ifdef TARGET_S390X
|
||||
void *mem;
|
||||
|
||||
mem = kvm_arch_vmalloc(size);
|
||||
if (mem) {
|
||||
return mem;
|
||||
}
|
||||
#endif
|
||||
return qemu_vmalloc(size);
|
||||
}
|
||||
|
||||
void kvm_setup_guest_memory(void *start, size_t size)
|
||||
{
|
||||
if (!kvm_has_sync_mmu()) {
|
||||
|
2
kvm.h
2
kvm.h
@ -70,6 +70,8 @@ int kvm_init_vcpu(CPUArchState *env);
|
||||
int kvm_cpu_exec(CPUArchState *env);
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
void *kvm_vmalloc(ram_addr_t size);
|
||||
void *kvm_arch_vmalloc(ram_addr_t size);
|
||||
void kvm_setup_guest_memory(void *start, size_t size);
|
||||
|
||||
int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size);
|
||||
|
@ -41,6 +41,9 @@ extern int daemon(int, int);
|
||||
therefore we need special code which handles running on Valgrind. */
|
||||
# define QEMU_VMALLOC_ALIGN (512 * 4096)
|
||||
# define CONFIG_VALGRIND
|
||||
#elif defined(__linux__) && defined(__s390x__)
|
||||
/* Use 1 MiB (segment size) alignment so gmap can be used by KVM. */
|
||||
# define QEMU_VMALLOC_ALIGN (256 * 4096)
|
||||
#else
|
||||
# define QEMU_VMALLOC_ALIGN getpagesize()
|
||||
#endif
|
||||
|
@ -135,6 +135,41 @@ int kvm_arch_get_registers(CPUS390XState *env)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Legacy layout for s390:
|
||||
* Older S390 KVM requires the topmost vma of the RAM to be
|
||||
* smaller than an system defined value, which is at least 256GB.
|
||||
* Larger systems have larger values. We put the guest between
|
||||
* the end of data segment (system break) and this value. We
|
||||
* use 32GB as a base to have enough room for the system break
|
||||
* to grow. We also have to use MAP parameters that avoid
|
||||
* read-only mapping of guest pages.
|
||||
*/
|
||||
static void *legacy_s390_alloc(ram_addr_t size)
|
||||
{
|
||||
void *mem;
|
||||
|
||||
mem = mmap((void *) 0x800000000ULL, size,
|
||||
PROT_EXEC|PROT_READ|PROT_WRITE,
|
||||
MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
|
||||
if (mem == MAP_FAILED) {
|
||||
fprintf(stderr, "Allocating RAM failed\n");
|
||||
abort();
|
||||
}
|
||||
return mem;
|
||||
}
|
||||
|
||||
void *kvm_arch_vmalloc(ram_addr_t size)
|
||||
{
|
||||
/* Can we use the standard allocation ? */
|
||||
if (kvm_check_extension(kvm_state, KVM_CAP_S390_GMAP) &&
|
||||
kvm_check_extension(kvm_state, KVM_CAP_S390_COW)) {
|
||||
return NULL;
|
||||
} else {
|
||||
return legacy_s390_alloc(size);
|
||||
}
|
||||
}
|
||||
|
||||
int kvm_arch_insert_sw_breakpoint(CPUS390XState *env, struct kvm_sw_breakpoint *bp)
|
||||
{
|
||||
static const uint8_t diag_501[] = {0x83, 0x24, 0x05, 0x01};
|
||||
|
Loading…
Reference in New Issue
Block a user