diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index b6d9f92f1513..f93a152f95ee 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -2425,6 +2425,85 @@ static void kvm_eat_signals(CPUState *cpu) } while (sigismember(&chkset, SIG_IPI)); } +#define KVM_HC_ENABLE_MEM_PROTECTED 12 +#define KVM_HC_MEM_SHARE 13 + +#define PROT_GUEST 0x04000000 + +static int kvm_protect_memory(void) +{ + KVMState *kvm = kvm_state; + KVMSlot *slot = NULL; + int i; + + for (i = 0; i < kvm->nr_slots; i++, slot = NULL) { + slot = &kvm->as[0].ml->slots[i]; + if (!slot->memory_size) + continue; + + if (mprotect(slot->ram, slot->memory_size, + PROT_GUEST | PROT_READ | PROT_WRITE)) { + perror("mprotect"); + return -1; + } + } + + return 0; +} + +static int kvm_share_memory(hwaddr start, hwaddr size) +{ + KVMState *kvm = kvm_state; + KVMSlot *slot = NULL; + int i; + void *p; + + for (i = 0; i < kvm->nr_slots; i++, slot = NULL) { + slot = &kvm->as[0].ml->slots[i]; + if (!slot->memory_size) + continue; + + if (start >= slot->start_addr && + start < slot->start_addr + slot->memory_size) + break; + } + + if (!slot) + return -1; + + /* XXX: Share range across memory slots? */ + if (start + size > slot->start_addr + slot->memory_size) + return -1; + + p = mmap(slot->ram + (start - slot->start_addr), size, + PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); + + if (p == MAP_FAILED) { + printf("mmap failed\n"); + return -1; + } + + return 0; +} + +static int kvm_handle_hypercall(CPUState *cpu, struct kvm_run *run) +{ + + switch (run->hypercall.nr) { + case KVM_HC_ENABLE_MEM_PROTECTED: + return kvm_protect_memory(); + case KVM_HC_MEM_SHARE: + return kvm_share_memory(run->hypercall.args[0] << 12, + run->hypercall.args[1] << 12); + default: + fprintf(stderr, "KVM: unexpected hypercall %lld\n", run->hypercall.nr); + return -1; + } + + return 0; +} + int kvm_cpu_exec(CPUState *cpu) { struct kvm_run *run = cpu->kvm_run; @@ -2561,6 +2640,9 @@ int kvm_cpu_exec(CPUState *cpu) break; } break; + case KVM_EXIT_HYPERCALL: + ret = kvm_handle_hypercall(cpu, run); + break; default: DPRINTF("kvm_arch_handle_exit\n"); ret = kvm_arch_handle_exit(cpu, run); diff --git a/softmmu/memory.c b/softmmu/memory.c index d4493ef9e430..fed346f84a67 100644 --- a/softmmu/memory.c +++ b/softmmu/memory.c @@ -1533,7 +1533,7 @@ void memory_region_init_ram_nomigrate(MemoryRegion *mr, uint64_t size, Error **errp) { - memory_region_init_ram_shared_nomigrate(mr, owner, name, size, false, errp); + memory_region_init_ram_shared_nomigrate(mr, owner, name, size, true, errp); } void memory_region_init_ram_shared_nomigrate(MemoryRegion *mr, diff --git a/target/i386/cpu.c b/target/i386/cpu.c index ad99cad0e7ce..5e486f3e7482 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -804,7 +804,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { "kvm-asyncpf", "kvm-steal-time", "kvm-pv-eoi", "kvm-pv-unhalt", NULL, "kvm-pv-tlb-flush", NULL, "kvm-pv-ipi", "kvm-poll-control", "kvm-pv-sched-yield", "kvm-asyncpf-int", "kvm-msi-ext-dest-id", - NULL, NULL, NULL, NULL, + "kvm-mem-protected", NULL, NULL, NULL, NULL, NULL, NULL, NULL, "kvmclock-stable-bit", NULL, NULL, NULL, NULL, NULL, NULL, NULL,