Commit 500acc9c authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.7-20160531' into staging



ppc patch queue for 2016-05-31

Here's another ppc patch queue.  This batch is all preliminaries
towards two significant features:

1) Full hypervisor-mode support for POWER8
    Patches 1-8 start fixing various bugs with TCG's handling of
    hypervisor mode

2) CPU hotplug support
    Patches 9-12 make some preliminary fixes towards implementing CPU
    hotplug on ppc64 (and other non-x86 platforms).  These patches are
    actually to generic code, not ppc, but are included here with
    Paolo's ACK.

# gpg: Signature made Tue 31 May 2016 01:39:44 BST using RSA key ID 20D9B392
# gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>"
# gpg:                 aka "David Gibson (Red Hat) <dgibson@redhat.com>"
# gpg:                 aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg:          It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 75F4 6586 AE61 A66C C44E  87DC 6C38 CACA 20D9 B392

* remotes/dgibson/tags/ppc-for-2.7-20160531:
  cpu: Add a sync version of cpu_remove()
  cpu: Reclaim vCPU objects
  exec: Do vmstate unregistration from cpu_exec_exit()
  exec: Remove cpu from cpus list during cpu_exec_exit()
  ppc: Add PPC_64H instruction flag to POWER7 and POWER8
  ppc: Get out of emulation on SMT "OR" ops
  ppc: Fix sign extension issue in mtmsr(d) emulation
  ppc: Change 'invalid' bit mask of tlbiel and tlbie
  ppc: tlbie, tlbia and tlbisync are HV only
  ppc: Do some batching of TCG tlb flushes
  ppc: Use split I/D mmu modes to avoid flushes on interrupts
  ppc: Remove MMU_MODEn_SUFFIX definitions

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 07e070aa 2c579042
Loading
Loading
Loading
Loading
+49 −2
Original line number Diff line number Diff line
@@ -972,6 +972,18 @@ void async_run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data)
    qemu_cpu_kick(cpu);
}

static void qemu_kvm_destroy_vcpu(CPUState *cpu)
{
    if (kvm_destroy_vcpu(cpu) < 0) {
        error_report("kvm_destroy_vcpu failed");
        exit(EXIT_FAILURE);
    }
}

static void qemu_tcg_destroy_vcpu(CPUState *cpu)
{
}

static void flush_queued_work(CPUState *cpu)
{
    struct qemu_work_item *wi;
@@ -1061,7 +1073,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
    cpu->created = true;
    qemu_cond_signal(&qemu_cpu_cond);

    while (1) {
    do {
        if (cpu_can_run(cpu)) {
            r = kvm_cpu_exec(cpu);
            if (r == EXCP_DEBUG) {
@@ -1069,8 +1081,12 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
            }
        }
        qemu_kvm_wait_io_event(cpu);
    }
    } while (!cpu->unplug || cpu_can_run(cpu));

    qemu_kvm_destroy_vcpu(cpu);
    cpu->created = false;
    qemu_cond_signal(&qemu_cpu_cond);
    qemu_mutex_unlock_iothread();
    return NULL;
}

@@ -1124,6 +1140,7 @@ static void tcg_exec_all(void);
static void *qemu_tcg_cpu_thread_fn(void *arg)
{
    CPUState *cpu = arg;
    CPUState *remove_cpu = NULL;

    rcu_register_thread();

@@ -1161,6 +1178,18 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
            }
        }
        qemu_tcg_wait_io_event(QTAILQ_FIRST(&cpus));
        CPU_FOREACH(cpu) {
            if (cpu->unplug && !cpu_can_run(cpu)) {
                remove_cpu = cpu;
                break;
            }
        }
        if (remove_cpu) {
            qemu_tcg_destroy_vcpu(remove_cpu);
            cpu->created = false;
            qemu_cond_signal(&qemu_cpu_cond);
            remove_cpu = NULL;
        }
    }

    return NULL;
@@ -1317,6 +1346,21 @@ void resume_all_vcpus(void)
    }
}

void cpu_remove(CPUState *cpu)
{
    cpu->stop = true;
    cpu->unplug = true;
    qemu_cpu_kick(cpu);
}

void cpu_remove_sync(CPUState *cpu)
{
    cpu_remove(cpu);
    while (cpu->created) {
        qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
    }
}

/* For temporary buffers for forming a name */
#define VCPU_THREAD_NAME_SIZE 16

@@ -1533,6 +1577,9 @@ static void tcg_exec_all(void)
                break;
            }
        } else if (cpu->stop || cpu->stopped) {
            if (cpu->unplug) {
                next_cpu = CPU_NEXT(cpu);
            }
            break;
        }
    }
+35 −8
Original line number Diff line number Diff line
@@ -57,6 +57,8 @@
#include "exec/ram_addr.h"
#include "exec/log.h"

#include "migration/vmstate.h"

#include "qemu/range.h"
#ifndef _WIN32
#include "qemu/mmap-alloc.h"
@@ -612,15 +614,9 @@ static int cpu_get_free_index(Error **errp)
    return cpu;
}

void cpu_exec_exit(CPUState *cpu)
static void cpu_release_index(CPUState *cpu)
{
    if (cpu->cpu_index == -1) {
        /* cpu_index was never allocated by this @cpu or was already freed. */
        return;
    }

    bitmap_clear(cpu_index_map, cpu->cpu_index, 1);
    cpu->cpu_index = -1;
}
#else

@@ -635,11 +631,42 @@ static int cpu_get_free_index(Error **errp)
    return cpu_index;
}

static void cpu_release_index(CPUState *cpu)
{
    return;
}
#endif

void cpu_exec_exit(CPUState *cpu)
{
    CPUClass *cc = CPU_GET_CLASS(cpu);

#if defined(CONFIG_USER_ONLY)
    cpu_list_lock();
#endif
    if (cpu->cpu_index == -1) {
        /* cpu_index was never allocated by this @cpu or was already freed. */
#if defined(CONFIG_USER_ONLY)
        cpu_list_unlock();
#endif
        return;
    }

    QTAILQ_REMOVE(&cpus, cpu, node);
    cpu_release_index(cpu);
    cpu->cpu_index = -1;
#if defined(CONFIG_USER_ONLY)
    cpu_list_unlock();
#endif

    if (cc->vmsd != NULL) {
        vmstate_unregister(NULL, cc->vmsd, cpu);
    }
    if (qdev_get_vmsd(DEVICE(cpu)) == NULL) {
        vmstate_unregister(NULL, &vmstate_cpu_common, cpu);
    }
}

void cpu_exec_init(CPUState *cpu, Error **errp)
{
    CPUClass *cc = CPU_GET_CLASS(cpu);
+11 −3
Original line number Diff line number Diff line
@@ -186,6 +186,7 @@ static RemoveResult remove_hpte(PowerPCCPU *cpu, target_ulong ptex,
static target_ulong h_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr,
                             target_ulong opcode, target_ulong *args)
{
    CPUPPCState *env = &cpu->env;
    target_ulong flags = args[0];
    target_ulong pte_index = args[1];
    target_ulong avpn = args[2];
@@ -196,6 +197,7 @@ static target_ulong h_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr,

    switch (ret) {
    case REMOVE_SUCCESS:
        check_tlb_flush(env);
        return H_SUCCESS;

    case REMOVE_NOT_FOUND:
@@ -232,7 +234,9 @@ static target_ulong h_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr,
static target_ulong h_bulk_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr,
                                  target_ulong opcode, target_ulong *args)
{
    CPUPPCState *env = &cpu->env;
    int i;
    target_ulong rc = H_SUCCESS;

    for (i = 0; i < H_BULK_REMOVE_MAX_BATCH; i++) {
        target_ulong *tsh = &args[i*2];
@@ -265,14 +269,18 @@ static target_ulong h_bulk_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr,
            break;

        case REMOVE_PARM:
            return H_PARAMETER;
            rc = H_PARAMETER;
            goto exit;

        case REMOVE_HW:
            return H_HARDWARE;
            rc = H_HARDWARE;
            goto exit;
        }
    }
 exit:
    check_tlb_flush(env);

    return H_SUCCESS;
    return rc;
}

static target_ulong h_protect(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+18 −0
Original line number Diff line number Diff line
@@ -244,6 +244,7 @@ struct qemu_work_item {
 * @halted: Nonzero if the CPU is in suspended state.
 * @stop: Indicates a pending stop request.
 * @stopped: Indicates the CPU has been artificially stopped.
 * @unplug: Indicates a pending CPU unplug request.
 * @crash_occurred: Indicates the OS reported a crash (panic) for this CPU
 * @tcg_exit_req: Set to force TCG to stop executing linked TBs for this
 *           CPU and return to its top level loop.
@@ -296,6 +297,7 @@ struct CPUState {
    bool created;
    bool stop;
    bool stopped;
    bool unplug;
    bool crash_occurred;
    bool exit_request;
    bool tb_flushed;
@@ -762,6 +764,22 @@ void cpu_exit(CPUState *cpu);
 */
void cpu_resume(CPUState *cpu);

/**
 * cpu_remove:
 * @cpu: The CPU to remove.
 *
 * Requests the CPU to be removed.
 */
void cpu_remove(CPUState *cpu);

 /**
 * cpu_remove_sync:
 * @cpu: The CPU to remove.
 *
 * Requests the CPU to be removed and waits till it is removed.
 */
void cpu_remove_sync(CPUState *cpu);

/**
 * qemu_init_vcpu:
 * @cpu: The vCPU to initialize.
+1 −0
Original line number Diff line number Diff line
@@ -216,6 +216,7 @@ int kvm_has_intx_set_mask(void);

int kvm_init_vcpu(CPUState *cpu);
int kvm_cpu_exec(CPUState *cpu);
int kvm_destroy_vcpu(CPUState *cpu);

#ifdef NEED_CPU_H
#include "cpu.h"
Loading