Commit 339b665c authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.6-20160218' into staging



ppc patch queue for 2016-02-18

Currently accumulated patches for target-ppc, pseries machine type and
related devices.
  * Some cleanups to management of SDR1 and the hashed page table
  * Implementations of a number of simple PAPR hypercalls
  * Significant improvements to the Macintosh CUDA device
  * Several bugfixes

# gpg: Signature made Thu 18 Feb 2016 04:16:51 GMT 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.6-20160218: (26 commits)
  hw/ppc/spapr: Halt CPU when powering off via RTAS call
  pseries: Include missing pseries-2.5 compat properties in pseries-2.4
  cuda: remove CUDA_GET_SET_IIC/CUDA_COMBINED_FORMAT_IIC commands
  cuda: remove GET_6805_ADDR command
  cuda: port SET_TIME command to new framework
  cuda: port GET_TIME command to new framework
  cuda: port SET_POWER_MESSAGES command to new framework
  cuda: port FILE_SERVER_FLAG command to new framework
  cuda: port RESET_SYSTEM command to new framework
  cuda: port POWERDOWN command to new framework
  cuda: port SET_DEVICE_LIST command to new framework
  cuda: port SET_AUTO_RATE command to new framework
  cuda: port AUTOPOLL command to new framework
  cuda: move unknown commands reject out of switch
  cuda: add a framework to handle commands
  hw/ppc/spapr: Implement the h_set_xdabr hypercall
  hw/ppc/spapr: Implement h_set_dabr
  hw/ppc/spapr: Add h_set_sprg0 hypercall
  migration: ensure htab_save_first completes after timeout
  target-ppc: Remove hack for ppc_hash64_load_hpte*() with HV KVM
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 3fc63c3f 8a9c1b77
Loading
Loading
Loading
Loading
+10 −8
Original line number Diff line number Diff line
@@ -89,7 +89,7 @@ int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
}

/* XXX: move that to cuda ? */
int adb_poll(ADBBusState *s, uint8_t *obuf)
int adb_poll(ADBBusState *s, uint8_t *obuf, uint16_t poll_mask)
{
    ADBDevice *d;
    int olen, i;
@@ -100,6 +100,7 @@ int adb_poll(ADBBusState *s, uint8_t *obuf)
        if (s->poll_index >= s->nb_devices)
            s->poll_index = 0;
        d = s->devices[s->poll_index];
        if ((1 << d->devaddr) & poll_mask) {
            buf[0] = ADB_READREG | (d->devaddr << 4);
            olen = adb_request(s, obuf + 1, buf, 1);
            /* if there is data, we poll again the same device */
@@ -108,6 +109,7 @@ int adb_poll(ADBBusState *s, uint8_t *obuf)
                olen++;
                break;
            }
        }
        s->poll_index++;
    }
    return olen;
+204 −75
Original line number Diff line number Diff line
@@ -106,7 +106,6 @@
#define CUDA_COMBINED_FORMAT_IIC	0x25

#define CUDA_TIMER_FREQ (4700000 / 6)
#define CUDA_ADB_POLL_FREQ 50

/* CUDA returns time_t's offset from Jan 1, 1904, not 1970 */
#define RTC_OFFSET                      2082844800
@@ -524,7 +523,7 @@ static void cuda_adb_poll(void *opaque)
    uint8_t obuf[ADB_MAX_OUT_LEN + 2];
    int olen;

    olen = adb_poll(&s->adb_bus, obuf + 2);
    olen = adb_poll(&s->adb_bus, obuf + 2, s->adb_poll_mask);
    if (olen > 0) {
        obuf[0] = ADB_PACKET;
        obuf[1] = 0x40; /* polled data */
@@ -532,87 +531,213 @@ static void cuda_adb_poll(void *opaque)
    }
    timer_mod(s->adb_poll_timer,
                   qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
                   (get_ticks_per_sec() / CUDA_ADB_POLL_FREQ));
                   (get_ticks_per_sec() / (1000 / s->autopoll_rate_ms)));
}

static void cuda_receive_packet(CUDAState *s,
                                const uint8_t *data, int len)
/* description of commands */
typedef struct CudaCommand {
    uint8_t command;
    const char *name;
    bool (*handler)(CUDAState *s,
                    const uint8_t *in_args, int in_len,
                    uint8_t *out_args, int *out_len);
} CudaCommand;

static bool cuda_cmd_autopoll(CUDAState *s,
                              const uint8_t *in_data, int in_len,
                              uint8_t *out_data, int *out_len)
{
    uint8_t obuf[16] = { CUDA_PACKET, 0, data[0] };
    int autopoll;
    uint32_t ti;

    switch(data[0]) {
    case CUDA_AUTOPOLL:
        autopoll = (data[1] != 0);
    if (in_len != 1) {
        return false;
    }

    autopoll = (in_data[0] != 0);
    if (autopoll != s->autopoll) {
        s->autopoll = autopoll;
        if (autopoll) {
            timer_mod(s->adb_poll_timer,
                      qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
                               (get_ticks_per_sec() / CUDA_ADB_POLL_FREQ));
                      (get_ticks_per_sec() / (1000 / s->autopoll_rate_ms)));
        } else {
            timer_del(s->adb_poll_timer);
        }
    }
        cuda_send_packet_to_host(s, obuf, 3);
        break;
    case CUDA_GET_6805_ADDR:
        cuda_send_packet_to_host(s, obuf, 3);
        break;
    case CUDA_SET_TIME:
        ti = (((uint32_t)data[1]) << 24) + (((uint32_t)data[2]) << 16) + (((uint32_t)data[3]) << 8) + data[4];
        s->tick_offset = ti - (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / get_ticks_per_sec());
        cuda_send_packet_to_host(s, obuf, 3);
        break;
    case CUDA_GET_TIME:
        ti = s->tick_offset + (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / get_ticks_per_sec());
        obuf[3] = ti >> 24;
        obuf[4] = ti >> 16;
        obuf[5] = ti >> 8;
        obuf[6] = ti;
        cuda_send_packet_to_host(s, obuf, 7);
        break;
    case CUDA_FILE_SERVER_FLAG:
    case CUDA_SET_DEVICE_LIST:
    case CUDA_SET_AUTO_RATE:
    case CUDA_SET_POWER_MESSAGES:
        cuda_send_packet_to_host(s, obuf, 3);
        break;
    case CUDA_POWERDOWN:
        cuda_send_packet_to_host(s, obuf, 3);
    return true;
}

static bool cuda_cmd_set_autorate(CUDAState *s,
                                  const uint8_t *in_data, int in_len,
                                  uint8_t *out_data, int *out_len)
{
    if (in_len != 1) {
        return false;
    }

    /* we don't want a period of 0 ms */
    /* FIXME: check what real hardware does */
    if (in_data[0] == 0) {
        return false;
    }

    s->autopoll_rate_ms = in_data[0];
    if (s->autopoll) {
        timer_mod(s->adb_poll_timer,
                  qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
                  (get_ticks_per_sec() / (1000 / s->autopoll_rate_ms)));
    }
    return true;
}

static bool cuda_cmd_set_device_list(CUDAState *s,
                                     const uint8_t *in_data, int in_len,
                                     uint8_t *out_data, int *out_len)
{
    if (in_len != 2) {
        return false;
    }

    s->adb_poll_mask = (((uint16_t)in_data[0]) << 8) | in_data[1];
    return true;
}

static bool cuda_cmd_powerdown(CUDAState *s,
                               const uint8_t *in_data, int in_len,
                               uint8_t *out_data, int *out_len)
{
    if (in_len != 0) {
        return false;
    }

    qemu_system_shutdown_request();
        break;
    case CUDA_RESET_SYSTEM:
        cuda_send_packet_to_host(s, obuf, 3);
    return true;
}

static bool cuda_cmd_reset_system(CUDAState *s,
                                  const uint8_t *in_data, int in_len,
                                  uint8_t *out_data, int *out_len)
{
    if (in_len != 0) {
        return false;
    }

    qemu_system_reset_request();
        break;
    case CUDA_COMBINED_FORMAT_IIC:
        obuf[0] = ERROR_PACKET;
        obuf[1] = 0x5;
        obuf[2] = CUDA_PACKET;
        obuf[3] = data[0];
        cuda_send_packet_to_host(s, obuf, 4);
        break;
    case CUDA_GET_SET_IIC:
        if (len == 4) {
            cuda_send_packet_to_host(s, obuf, 3);
    return true;
}

static bool cuda_cmd_set_file_server_flag(CUDAState *s,
                                          const uint8_t *in_data, int in_len,
                                          uint8_t *out_data, int *out_len)
{
    if (in_len != 1) {
        return false;
    }

    qemu_log_mask(LOG_UNIMP,
                  "CUDA: unimplemented command FILE_SERVER_FLAG %d\n",
                  in_data[0]);
    return true;
}

static bool cuda_cmd_set_power_message(CUDAState *s,
                                       const uint8_t *in_data, int in_len,
                                       uint8_t *out_data, int *out_len)
{
    if (in_len != 1) {
        return false;
    }

    qemu_log_mask(LOG_UNIMP,
                  "CUDA: unimplemented command SET_POWER_MESSAGE %d\n",
                  in_data[0]);
    return true;
}

static bool cuda_cmd_get_time(CUDAState *s,
                              const uint8_t *in_data, int in_len,
                              uint8_t *out_data, int *out_len)
{
    uint32_t ti;

    if (in_len != 0) {
        return false;
    }

    ti = s->tick_offset + (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)
                           / get_ticks_per_sec());
    out_data[0] = ti >> 24;
    out_data[1] = ti >> 16;
    out_data[2] = ti >> 8;
    out_data[3] = ti;
    *out_len = 4;
    return true;
}

static bool cuda_cmd_set_time(CUDAState *s,
                              const uint8_t *in_data, int in_len,
                              uint8_t *out_data, int *out_len)
{
    uint32_t ti;

    if (in_len != 4) {
        return false;
    }

    ti = (((uint32_t)in_data[1]) << 24) + (((uint32_t)in_data[2]) << 16)
         + (((uint32_t)in_data[3]) << 8) + in_data[4];
    s->tick_offset = ti - (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)
                           / get_ticks_per_sec());
    return true;
}

static const CudaCommand handlers[] = {
    { CUDA_AUTOPOLL, "AUTOPOLL", cuda_cmd_autopoll },
    { CUDA_SET_AUTO_RATE, "SET_AUTO_RATE",  cuda_cmd_set_autorate },
    { CUDA_SET_DEVICE_LIST, "SET_DEVICE_LIST", cuda_cmd_set_device_list },
    { CUDA_POWERDOWN, "POWERDOWN", cuda_cmd_powerdown },
    { CUDA_RESET_SYSTEM, "RESET_SYSTEM", cuda_cmd_reset_system },
    { CUDA_FILE_SERVER_FLAG, "FILE_SERVER_FLAG",
      cuda_cmd_set_file_server_flag },
    { CUDA_SET_POWER_MESSAGES, "SET_POWER_MESSAGES",
      cuda_cmd_set_power_message },
    { CUDA_GET_TIME, "GET_TIME", cuda_cmd_get_time },
    { CUDA_SET_TIME, "SET_TIME", cuda_cmd_set_time },
};

static void cuda_receive_packet(CUDAState *s,
                                const uint8_t *data, int len)
{
    uint8_t obuf[16] = { CUDA_PACKET, 0, data[0] };
    int i, out_len = 0;

    for (i = 0; i < ARRAY_SIZE(handlers); i++) {
        const CudaCommand *desc = &handlers[i];
        if (desc->command == data[0]) {
            CUDA_DPRINTF("handling command %s\n", desc->name);
            out_len = 0;
            if (desc->handler(s, data + 1, len - 1, obuf + 3, &out_len)) {
                cuda_send_packet_to_host(s, obuf, 3 + out_len);
            } else {
                qemu_log_mask(LOG_GUEST_ERROR,
                              "CUDA: %s: wrong parameters %d\n",
                              desc->name, len);
                obuf[0] = ERROR_PACKET;
            obuf[1] = 0x2;
                obuf[1] = 0x5; /* bad parameters */
                obuf[2] = CUDA_PACKET;
                obuf[3] = data[0];
                cuda_send_packet_to_host(s, obuf, 4);
            }
        break;
    default:
            return;
        }
    }

    qemu_log_mask(LOG_GUEST_ERROR, "CUDA: unknown command 0x%02x\n", data[0]);
    obuf[0] = ERROR_PACKET;
        obuf[1] = 0x2;
    obuf[1] = 0x2; /* unknown command */
    obuf[2] = CUDA_PACKET;
    obuf[3] = data[0];
    cuda_send_packet_to_host(s, obuf, 4);
        break;
    }
}

static void cuda_receive_packet_from_host(CUDAState *s,
@@ -710,8 +835,8 @@ static const VMStateDescription vmstate_cuda_timer = {

static const VMStateDescription vmstate_cuda = {
    .name = "cuda",
    .version_id = 3,
    .minimum_version_id = 3,
    .version_id = 4,
    .minimum_version_id = 4,
    .fields = (VMStateField[]) {
        VMSTATE_UINT8(a, CUDAState),
        VMSTATE_UINT8(b, CUDAState),
@@ -729,6 +854,8 @@ static const VMStateDescription vmstate_cuda = {
        VMSTATE_INT32(data_in_index, CUDAState),
        VMSTATE_INT32(data_out_index, CUDAState),
        VMSTATE_UINT8(autopoll, CUDAState),
        VMSTATE_UINT8(autopoll_rate_ms, CUDAState),
        VMSTATE_UINT16(adb_poll_mask, CUDAState),
        VMSTATE_BUFFER(data_in, CUDAState),
        VMSTATE_BUFFER(data_out, CUDAState),
        VMSTATE_UINT32(tick_offset, CUDAState),
@@ -782,6 +909,8 @@ static void cuda_realizefn(DeviceState *dev, Error **errp)
    s->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET;

    s->adb_poll_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_adb_poll, s);
    s->autopoll_rate_ms = 20;
    s->adb_poll_mask = 0xffff;
}

static void cuda_initfn(Object *obj)
+4 −2
Original line number Diff line number Diff line
@@ -49,7 +49,8 @@ static void macio_nvram_writeb(void *opaque, hwaddr addr,

    addr = (addr >> s->it_shift) & (s->size - 1);
    s->data[addr] = value;
    NVR_DPRINTF("writeb addr %04" PHYS_PRIx " val %" PRIx64 "\n", addr, value);
    NVR_DPRINTF("writeb addr %04" HWADDR_PRIx " val %" PRIx64 "\n",
                addr, value);
}

static uint64_t macio_nvram_readb(void *opaque, hwaddr addr,
@@ -60,7 +61,8 @@ static uint64_t macio_nvram_readb(void *opaque, hwaddr addr,

    addr = (addr >> s->it_shift) & (s->size - 1);
    value = s->data[addr];
    NVR_DPRINTF("readb addr %04x val %x\n", (int)addr, value);
    NVR_DPRINTF("readb addr %04" HWADDR_PRIx " val %" PRIx32 "\n",
                addr, value);

    return value;
}
+2 −2
Original line number Diff line number Diff line
@@ -120,7 +120,7 @@ static void unin_data_write(void *opaque, hwaddr addr,
{
    UNINState *s = opaque;
    PCIHostState *phb = PCI_HOST_BRIDGE(s);
    UNIN_DPRINTF("write addr %" TARGET_FMT_plx " len %d val %"PRIx64"\n",
    UNIN_DPRINTF("write addr " TARGET_FMT_plx " len %d val %"PRIx64"\n",
                 addr, len, val);
    pci_data_write(phb->bus,
                   unin_get_config_reg(phb->config_reg, addr),
@@ -137,7 +137,7 @@ static uint64_t unin_data_read(void *opaque, hwaddr addr,
    val = pci_data_read(phb->bus,
                        unin_get_config_reg(phb->config_reg, addr),
                        len);
    UNIN_DPRINTF("read addr %" TARGET_FMT_plx " len %d val %x\n",
    UNIN_DPRINTF("read addr " TARGET_FMT_plx " len %d val %x\n",
                 addr, len, val);
    return val;
}
+2 −0
Original line number Diff line number Diff line
@@ -111,6 +111,8 @@ typedef struct CUDAState {
    int data_out_index;

    qemu_irq irq;
    uint16_t adb_poll_mask;
    uint8_t autopoll_rate_ms;
    uint8_t autopoll;
    uint8_t data_in[128];
    uint8_t data_out[16];
Loading