Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.6-201602…
Browse files Browse the repository at this point in the history
…18' 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: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed Feb 18, 2016
2 parents 3fc63c3 + 8a9c1b7 commit 339b665
Show file tree
Hide file tree
Showing 13 changed files with 393 additions and 232 deletions.
18 changes: 10 additions & 8 deletions hw/input/adb.c
Expand Up @@ -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;
Expand All @@ -100,13 +100,15 @@ 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];
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 */
if (olen > 0) {
obuf[0] = buf[0];
olen++;
break;
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 */
if (olen > 0) {
obuf[0] = buf[0];
olen++;
break;
}
}
s->poll_index++;
}
Expand Down
279 changes: 204 additions & 75 deletions hw/misc/macio/cuda.c
Expand Up @@ -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
Expand Down Expand Up @@ -524,95 +523,221 @@ 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 */
cuda_send_packet_to_host(s, obuf, olen + 2);
}
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;

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() / (1000 / s->autopoll_rate_ms)));
} else {
timer_del(s->adb_poll_timer);
}
}
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();
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();
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;

switch(data[0]) {
case CUDA_AUTOPOLL:
autopoll = (data[1] != 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));
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 {
timer_del(s->adb_poll_timer);
qemu_log_mask(LOG_GUEST_ERROR,
"CUDA: %s: wrong parameters %d\n",
desc->name, len);
obuf[0] = ERROR_PACKET;
obuf[1] = 0x5; /* bad parameters */
obuf[2] = CUDA_PACKET;
obuf[3] = data[0];
cuda_send_packet_to_host(s, obuf, 4);
}
return;
}
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);
qemu_system_shutdown_request();
break;
case CUDA_RESET_SYSTEM:
cuda_send_packet_to_host(s, obuf, 3);
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);
} else {
obuf[0] = ERROR_PACKET;
obuf[1] = 0x2;
obuf[2] = CUDA_PACKET;
obuf[3] = data[0];
cuda_send_packet_to_host(s, obuf, 4);
}
break;
default:
obuf[0] = ERROR_PACKET;
obuf[1] = 0x2;
obuf[2] = CUDA_PACKET;
obuf[3] = data[0];
cuda_send_packet_to_host(s, obuf, 4);
break;
}

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

static void cuda_receive_packet_from_host(CUDAState *s,
Expand Down Expand Up @@ -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),
Expand All @@ -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),
Expand Down Expand Up @@ -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)
Expand Down
6 changes: 4 additions & 2 deletions hw/nvram/mac_nvram.c
Expand Up @@ -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,
Expand All @@ -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;
}
Expand Down

0 comments on commit 339b665

Please sign in to comment.