Commit a9bcd1b8 authored by Thomas Huth's avatar Thomas Huth Committed by Cornelia Huck
Browse files

s390x/mmu: Use ioctl for reading and writing from/to guest memory



Add code to make use of the new ioctl for reading from / writing to
virtual guest memory. By using the ioctl, the memory accesses are now
protected with the so-called ipte-lock in the kernel.

[CH: moved error message into kvm_s390_mem_op()]
Signed-off-by: default avatarThomas Huth <thuth@linux.vnet.ibm.com>
Acked-by: default avatarChristian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
parent f07177a5
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -401,6 +401,8 @@ void kvm_s390_vcpu_interrupt(S390CPU *cpu, struct kvm_s390_irq *irq);
void kvm_s390_floating_interrupt(struct kvm_s390_irq *irq);
int kvm_s390_inject_flic(struct kvm_s390_irq *irq);
void kvm_s390_access_exception(S390CPU *cpu, uint16_t code, uint64_t te_code);
int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, void *hostbuf, int len,
                    bool is_write);
int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_clock);
int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_clock);
#else
@@ -418,6 +420,11 @@ static inline int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_low)
{
    return -ENOSYS;
}
static inline int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, void *hostbuf,
                                  int len, bool is_write)
{
    return -ENOSYS;
}
static inline void kvm_s390_access_exception(S390CPU *cpu, uint16_t code,
                                             uint64_t te_code)
{
+40 −0
Original line number Diff line number Diff line
@@ -123,6 +123,7 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {

static int cap_sync_regs;
static int cap_async_pf;
static int cap_mem_op;

static void *legacy_s390_alloc(size_t size, uint64_t *align);

@@ -247,6 +248,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
{
    cap_sync_regs = kvm_check_extension(s, KVM_CAP_SYNC_REGS);
    cap_async_pf = kvm_check_extension(s, KVM_CAP_ASYNC_PF);
    cap_mem_op = kvm_check_extension(s, KVM_CAP_S390_MEM_OP);

    kvm_s390_enable_cmma(s);

@@ -550,6 +552,44 @@ int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_low)
    return kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr);
}

/**
 * kvm_s390_mem_op:
 * @addr:      the logical start address in guest memory
 * @hostbuf:   buffer in host memory. NULL = do only checks w/o copying
 * @len:       length that should be transfered
 * @is_write:  true = write, false = read
 * Returns:    0 on success, non-zero if an exception or error occured
 *
 * Use KVM ioctl to read/write from/to guest memory. An access exception
 * is injected into the vCPU in case of translation errors.
 */
int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, void *hostbuf, int len,
                    bool is_write)
{
    struct kvm_s390_mem_op mem_op = {
        .gaddr = addr,
        .flags = KVM_S390_MEMOP_F_INJECT_EXCEPTION,
        .size = len,
        .op = is_write ? KVM_S390_MEMOP_LOGICAL_WRITE
                       : KVM_S390_MEMOP_LOGICAL_READ,
        .buf = (uint64_t)hostbuf,
    };
    int ret;

    if (!cap_mem_op) {
        return -ENOSYS;
    }
    if (!hostbuf) {
        mem_op.flags |= KVM_S390_MEMOP_F_CHECK_ONLY;
    }

    ret = kvm_vcpu_ioctl(CPU(cpu), KVM_S390_MEM_OP, &mem_op);
    if (ret < 0) {
        error_printf("KVM_S390_MEM_OP failed: %s\n", strerror(-ret));
    }
    return ret;
}

/*
 * Legacy layout for s390:
 * Older S390 KVM requires the topmost vma of the RAM to be
+7 −0
Original line number Diff line number Diff line
@@ -450,6 +450,13 @@ int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, void *hostbuf,
    target_ulong *pages;
    int ret;

    if (kvm_enabled()) {
        ret = kvm_s390_mem_op(cpu, laddr, hostbuf, len, is_write);
        if (ret >= 0) {
            return ret;
        }
    }

    nr_pages = (((laddr & ~TARGET_PAGE_MASK) + len - 1) >> TARGET_PAGE_BITS)
               + 1;
    pages = g_malloc(nr_pages * sizeof(*pages));