ppc patch queue 2017-09-27
Contains * a number of Mac machine type fixes * a number of embedded machine type fixes (preliminary to adding the Sam460ex board) * a important fix for handling of migration with KVM PR * assorted other minor fixes and cleanups -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEdfRlhq5hpmzETofcbDjKyiDZs5IFAlnLVgAACgkQbDjKyiDZ s5IKHw/+OO+VZOfQ7/OUKED1VwgYG51Z9roX1wkfx5lOmJRT38KZ0XpHKBw1gdV0 3UkqH4jqYBSWqjlIUS4vFreG6NbRrxAD1nmctGI1xDBL3Cjw8Xt28vwJ7MgOzaS9 VW+ga+1exH5x3svBaYPwoePEXI9YoFQkSh27+xAi8n+csB6D0AMquvY8iJsAf+kS IQY5m8QH5dlu1hJSEssQrfvY3s/zlxm41Mamm3n0i5rpl+a+vyu8jmZCBrKbhqjL XfiYCKssdknppW8FMmGbh7ycwf2yQuFG273KUQRXdJgiAdGp9gRObufbdblp4Q9u ZJCQn/MPBMVSAV5YIrMKwmgzlev26d5uFpFAyOlX+B4qZv5XRNnD3762Lv2LtSFU YYYMJNA3pnmrA6cQ9Q0fSXilZj+AblPdaGhc+HZeRL84K1A4RLx6wRi/axMsxoBb MBpF9Dm5wMLudybwLFIOlNdktQPcYCYzBsPb1V7lYITRL9PyoyMmIA4mRSGJ494T H1/dbUzqGBvKAQyx2Dk73V9aoBk03v1BUuCGKgF0e5THp6yWJytbxhzOq7MX6JkG Diwyzf7D7v2pvfZ5chdn79M01zsHFT6bnR+PBpGSmGavrT4E3qf/pRdhBcsBOc3n w/triA7Ae4sq2DHQqHXwQd+om70OBRxqQUkaa30dKA6+kj5fj5c= =NL90 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.11-20170927' into staging ppc patch queue 2017-09-27 Contains * a number of Mac machine type fixes * a number of embedded machine type fixes (preliminary to adding the Sam460ex board) * a important fix for handling of migration with KVM PR * assorted other minor fixes and cleanups # gpg: Signature made Wed 27 Sep 2017 08:40:48 BST # gpg: using RSA key 0x6C38CACA20D9B392 # 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: aka "David Gibson (kernel.org) <dwg@kernel.org>" # Primary key fingerprint: 75F4 6586 AE61 A66C C44E 87DC 6C38 CACA 20D9 B392 * remotes/dgibson/tags/ppc-for-2.11-20170927: (26 commits) macio: use object link between MACIO_IDE and MAC_DBDMA object macio: pass channel into MACIOIDEState via qdev property mac_dbdma: remove DBDMA_init() function mac_dbdma: QOMify mac_dbdma: remove unused IO fields from DBDMAState spapr: fix the value of SDR1 in kvmppc_put_books_sregs() ppc/pnv: check for OPAL firmware file presence ppc: remove all unused CPU definitions ppc: remove unused CPU definitions spapr_pci: make index property mandatory macio: convert pmac_ide_ops from old_mmio ppc/pnv: Improve macro parenthesization spapr: introduce helpers to migrate HPT chunks and the end marker ppc/kvm: generalize the use of kvmppc_get_htab_fd() ppc/kvm: change kvmppc_get_htab_fd() to return -errno on error ppc: Fix OpenPIC model ppc/ide/macio: Add missing registers ppc/mac: More rework of the DBDMA emulation ppc/mac: Advertise a high clock frequency for NewWorld Macs ppc: QOMify g3beige machine ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
1d89344081
208
hw/ide/macio.c
208
hw/ide/macio.c
@ -255,114 +255,100 @@ static void pmac_ide_flush(DBDMA_io *io)
|
||||
}
|
||||
|
||||
/* PowerMac IDE memory IO */
|
||||
static void pmac_ide_writeb (void *opaque,
|
||||
hwaddr addr, uint32_t val)
|
||||
static uint64_t pmac_ide_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
MACIOIDEState *d = opaque;
|
||||
uint64_t retval = 0xffffffff;
|
||||
int reg = addr >> 4;
|
||||
|
||||
addr = (addr & 0xFFF) >> 4;
|
||||
switch (addr) {
|
||||
case 1 ... 7:
|
||||
ide_ioport_write(&d->bus, addr, val);
|
||||
switch (reg) {
|
||||
case 0x0:
|
||||
if (size == 2) {
|
||||
retval = ide_data_readw(&d->bus, 0);
|
||||
} else if (size == 4) {
|
||||
retval = ide_data_readl(&d->bus, 0);
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
case 22:
|
||||
ide_cmd_write(&d->bus, 0, val);
|
||||
case 0x1 ... 0x7:
|
||||
if (size == 1) {
|
||||
retval = ide_ioport_read(&d->bus, reg);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
case 0x8:
|
||||
case 0x16:
|
||||
if (size == 1) {
|
||||
retval = ide_status_read(&d->bus, 0);
|
||||
}
|
||||
break;
|
||||
case 0x20:
|
||||
if (size == 4) {
|
||||
retval = d->timing_reg;
|
||||
}
|
||||
break;
|
||||
case 0x30:
|
||||
/* This is an interrupt state register that only exists
|
||||
* in the KeyLargo and later variants. Bit 0x8000_0000
|
||||
* latches the DMA interrupt and has to be written to
|
||||
* clear. Bit 0x4000_0000 is an image of the disk
|
||||
* interrupt. MacOS X relies on this and will hang if
|
||||
* we don't provide at least the disk interrupt
|
||||
*/
|
||||
if (size == 4) {
|
||||
retval = d->irq_reg;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t pmac_ide_readb (void *opaque,hwaddr addr)
|
||||
{
|
||||
uint8_t retval;
|
||||
MACIOIDEState *d = opaque;
|
||||
|
||||
addr = (addr & 0xFFF) >> 4;
|
||||
switch (addr) {
|
||||
case 1 ... 7:
|
||||
retval = ide_ioport_read(&d->bus, addr);
|
||||
break;
|
||||
case 8:
|
||||
case 22:
|
||||
retval = ide_status_read(&d->bus, 0);
|
||||
break;
|
||||
default:
|
||||
retval = 0xFF;
|
||||
break;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void pmac_ide_writew (void *opaque,
|
||||
hwaddr addr, uint32_t val)
|
||||
|
||||
static void pmac_ide_write(void *opaque, hwaddr addr, uint64_t val,
|
||||
unsigned size)
|
||||
{
|
||||
MACIOIDEState *d = opaque;
|
||||
int reg = addr >> 4;
|
||||
|
||||
addr = (addr & 0xFFF) >> 4;
|
||||
val = bswap16(val);
|
||||
if (addr == 0) {
|
||||
ide_data_writew(&d->bus, 0, val);
|
||||
switch (reg) {
|
||||
case 0x0:
|
||||
if (size == 2) {
|
||||
ide_data_writew(&d->bus, 0, val);
|
||||
} else if (size == 4) {
|
||||
ide_data_writel(&d->bus, 0, val);
|
||||
}
|
||||
break;
|
||||
case 0x1 ... 0x7:
|
||||
if (size == 1) {
|
||||
ide_ioport_write(&d->bus, reg, val);
|
||||
}
|
||||
break;
|
||||
case 0x8:
|
||||
case 0x16:
|
||||
if (size == 1) {
|
||||
ide_cmd_write(&d->bus, 0, val);
|
||||
}
|
||||
break;
|
||||
case 0x20:
|
||||
if (size == 4) {
|
||||
d->timing_reg = val;
|
||||
}
|
||||
break;
|
||||
case 0x30:
|
||||
if (size == 4) {
|
||||
if (val & 0x80000000u) {
|
||||
d->irq_reg &= 0x7fffffff;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t pmac_ide_readw (void *opaque,hwaddr addr)
|
||||
{
|
||||
uint16_t retval;
|
||||
MACIOIDEState *d = opaque;
|
||||
|
||||
addr = (addr & 0xFFF) >> 4;
|
||||
if (addr == 0) {
|
||||
retval = ide_data_readw(&d->bus, 0);
|
||||
} else {
|
||||
retval = 0xFFFF;
|
||||
}
|
||||
retval = bswap16(retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void pmac_ide_writel (void *opaque,
|
||||
hwaddr addr, uint32_t val)
|
||||
{
|
||||
MACIOIDEState *d = opaque;
|
||||
|
||||
addr = (addr & 0xFFF) >> 4;
|
||||
val = bswap32(val);
|
||||
if (addr == 0) {
|
||||
ide_data_writel(&d->bus, 0, val);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t pmac_ide_readl (void *opaque,hwaddr addr)
|
||||
{
|
||||
uint32_t retval;
|
||||
MACIOIDEState *d = opaque;
|
||||
|
||||
addr = (addr & 0xFFF) >> 4;
|
||||
if (addr == 0) {
|
||||
retval = ide_data_readl(&d->bus, 0);
|
||||
} else {
|
||||
retval = 0xFFFFFFFF;
|
||||
}
|
||||
retval = bswap32(retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static const MemoryRegionOps pmac_ide_ops = {
|
||||
.old_mmio = {
|
||||
.write = {
|
||||
pmac_ide_writeb,
|
||||
pmac_ide_writew,
|
||||
pmac_ide_writel,
|
||||
},
|
||||
.read = {
|
||||
pmac_ide_readb,
|
||||
pmac_ide_readw,
|
||||
pmac_ide_readl,
|
||||
},
|
||||
},
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
.read = pmac_ide_read,
|
||||
.write = pmac_ide_write,
|
||||
.valid.min_access_size = 1,
|
||||
.valid.max_access_size = 4,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_pmac = {
|
||||
@ -426,13 +412,32 @@ static void macio_ide_realizefn(DeviceState *dev, Error **errp)
|
||||
{
|
||||
MACIOIDEState *s = MACIO_IDE(dev);
|
||||
|
||||
ide_init2(&s->bus, s->irq);
|
||||
ide_init2(&s->bus, s->ide_irq);
|
||||
|
||||
/* Register DMA callbacks */
|
||||
s->dma.ops = &dbdma_ops;
|
||||
s->bus.dma = &s->dma;
|
||||
}
|
||||
|
||||
static void pmac_ide_irq(void *opaque, int n, int level)
|
||||
{
|
||||
MACIOIDEState *s = opaque;
|
||||
uint32_t mask = 0x80000000u >> n;
|
||||
|
||||
/* We need to reflect the IRQ state in the irq register */
|
||||
if (level) {
|
||||
s->irq_reg |= mask;
|
||||
} else {
|
||||
s->irq_reg &= ~mask;
|
||||
}
|
||||
|
||||
if (n) {
|
||||
qemu_set_irq(s->real_ide_irq, level);
|
||||
} else {
|
||||
qemu_set_irq(s->real_dma_irq, level);
|
||||
}
|
||||
}
|
||||
|
||||
static void macio_ide_initfn(Object *obj)
|
||||
{
|
||||
SysBusDevice *d = SYS_BUS_DEVICE(obj);
|
||||
@ -441,16 +446,28 @@ static void macio_ide_initfn(Object *obj)
|
||||
ide_bus_new(&s->bus, sizeof(s->bus), DEVICE(obj), 0, 2);
|
||||
memory_region_init_io(&s->mem, obj, &pmac_ide_ops, s, "pmac-ide", 0x1000);
|
||||
sysbus_init_mmio(d, &s->mem);
|
||||
sysbus_init_irq(d, &s->irq);
|
||||
sysbus_init_irq(d, &s->dma_irq);
|
||||
sysbus_init_irq(d, &s->real_ide_irq);
|
||||
sysbus_init_irq(d, &s->real_dma_irq);
|
||||
s->dma_irq = qemu_allocate_irq(pmac_ide_irq, s, 0);
|
||||
s->ide_irq = qemu_allocate_irq(pmac_ide_irq, s, 1);
|
||||
|
||||
object_property_add_link(obj, "dbdma", TYPE_MAC_DBDMA,
|
||||
(Object **) &s->dbdma,
|
||||
qdev_prop_allow_set_link_before_realize, 0, NULL);
|
||||
}
|
||||
|
||||
static Property macio_ide_properties[] = {
|
||||
DEFINE_PROP_UINT32("channel", MACIOIDEState, channel, 0),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void macio_ide_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
dc->realize = macio_ide_realizefn;
|
||||
dc->reset = macio_ide_reset;
|
||||
dc->props = macio_ide_properties;
|
||||
dc->vmsd = &vmstate_pmac;
|
||||
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
||||
}
|
||||
@ -480,10 +497,9 @@ void macio_ide_init_drives(MACIOIDEState *s, DriveInfo **hd_table)
|
||||
}
|
||||
}
|
||||
|
||||
void macio_ide_register_dma(MACIOIDEState *s, void *dbdma, int channel)
|
||||
void macio_ide_register_dma(MACIOIDEState *s)
|
||||
{
|
||||
s->dbdma = dbdma;
|
||||
DBDMA_register_channel(dbdma, channel, s->dma_irq,
|
||||
DBDMA_register_channel(s->dbdma, s->channel, s->dma_irq,
|
||||
pmac_ide_transfer, pmac_ide_flush, s);
|
||||
}
|
||||
|
||||
|
@ -92,6 +92,16 @@ static int get_current_cpu(void);
|
||||
#define RAVEN_MAX_TMR OPENPIC_MAX_TMR
|
||||
#define RAVEN_MAX_IPI OPENPIC_MAX_IPI
|
||||
|
||||
/* KeyLargo */
|
||||
#define KEYLARGO_MAX_CPU 4
|
||||
#define KEYLARGO_MAX_EXT 64
|
||||
#define KEYLARGO_MAX_IPI 4
|
||||
#define KEYLARGO_MAX_IRQ (64 + KEYLARGO_MAX_IPI)
|
||||
#define KEYLARGO_MAX_TMR 0
|
||||
#define KEYLARGO_IPI_IRQ (KEYLARGO_MAX_EXT) /* First IPI IRQ */
|
||||
/* Timers don't exist but this makes the code happy... */
|
||||
#define KEYLARGO_TMR_IRQ (KEYLARGO_IPI_IRQ + KEYLARGO_MAX_IPI)
|
||||
|
||||
/* Interrupt definitions */
|
||||
#define RAVEN_FE_IRQ (RAVEN_MAX_EXT) /* Internal functional IRQ */
|
||||
#define RAVEN_ERR_IRQ (RAVEN_MAX_EXT + 1) /* Error IRQ */
|
||||
@ -120,6 +130,7 @@ static FslMpicInfo fsl_mpic_42 = {
|
||||
#define VID_REVISION_1_3 3
|
||||
|
||||
#define VIR_GENERIC 0x00000000 /* Generic Vendor ID */
|
||||
#define VIR_MPIC2A 0x00004614 /* IBM MPIC-2A */
|
||||
|
||||
#define GCR_RESET 0x80000000
|
||||
#define GCR_MODE_PASS 0x00000000
|
||||
@ -329,6 +340,8 @@ typedef struct OpenPICState {
|
||||
uint32_t nb_cpus;
|
||||
/* Timer registers */
|
||||
OpenPICTimer timers[OPENPIC_MAX_TMR];
|
||||
uint32_t max_tmr;
|
||||
|
||||
/* Shared MSI registers */
|
||||
OpenPICMSI msi[MAX_MSI];
|
||||
uint32_t max_irq;
|
||||
@ -1715,6 +1728,28 @@ static void openpic_realize(DeviceState *dev, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
map_list(opp, list_le, &list_count);
|
||||
break;
|
||||
|
||||
case OPENPIC_MODEL_KEYLARGO:
|
||||
opp->nb_irqs = KEYLARGO_MAX_EXT;
|
||||
opp->vid = VID_REVISION_1_2;
|
||||
opp->vir = VIR_GENERIC;
|
||||
opp->vector_mask = 0xFF;
|
||||
opp->tfrr_reset = 4160000;
|
||||
opp->ivpr_reset = IVPR_MASK_MASK | IVPR_MODE_MASK;
|
||||
opp->idr_reset = 0;
|
||||
opp->max_irq = KEYLARGO_MAX_IRQ;
|
||||
opp->irq_ipi0 = KEYLARGO_IPI_IRQ;
|
||||
opp->irq_tim0 = KEYLARGO_TMR_IRQ;
|
||||
opp->brr1 = -1;
|
||||
opp->mpic_mode_mask = GCR_MODE_MIXED;
|
||||
|
||||
if (opp->nb_cpus != 1) {
|
||||
error_setg(errp, "Only UP supported today");
|
||||
return;
|
||||
}
|
||||
|
||||
map_list(opp, list_le, &list_count);
|
||||
break;
|
||||
}
|
||||
|
@ -96,9 +96,8 @@ static void dbdma_cmdptr_load(DBDMA_channel *ch)
|
||||
|
||||
static void dbdma_cmdptr_save(DBDMA_channel *ch)
|
||||
{
|
||||
DBDMA_DPRINTFCH(ch, "dbdma_cmdptr_save 0x%08x\n",
|
||||
ch->regs[DBDMA_CMDPTR_LO]);
|
||||
DBDMA_DPRINTFCH(ch, "xfer_status 0x%08x res_count 0x%04x\n",
|
||||
DBDMA_DPRINTFCH(ch, "-> update 0x%08x stat=0x%08x, res=0x%04x\n",
|
||||
ch->regs[DBDMA_CMDPTR_LO],
|
||||
le16_to_cpu(ch->current.xfer_status),
|
||||
le16_to_cpu(ch->current.res_count));
|
||||
dma_memory_write(&address_space_memory, ch->regs[DBDMA_CMDPTR_LO],
|
||||
@ -166,15 +165,14 @@ static int conditional_wait(DBDMA_channel *ch)
|
||||
uint16_t sel_mask, sel_value;
|
||||
uint32_t status;
|
||||
int cond;
|
||||
|
||||
DBDMA_DPRINTFCH(ch, "conditional_wait\n");
|
||||
int res = 0;
|
||||
|
||||
wait = le16_to_cpu(current->command) & WAIT_MASK;
|
||||
|
||||
switch(wait) {
|
||||
case WAIT_NEVER: /* don't wait */
|
||||
return 0;
|
||||
case WAIT_ALWAYS: /* always wait */
|
||||
DBDMA_DPRINTFCH(ch, " [WAIT_ALWAYS]\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -187,15 +185,19 @@ static int conditional_wait(DBDMA_channel *ch)
|
||||
|
||||
switch(wait) {
|
||||
case WAIT_IFSET: /* wait if condition bit is 1 */
|
||||
if (cond)
|
||||
return 1;
|
||||
return 0;
|
||||
if (cond) {
|
||||
res = 1;
|
||||
}
|
||||
DBDMA_DPRINTFCH(ch, " [WAIT_IFSET=%d]\n", res);
|
||||
break;
|
||||
case WAIT_IFCLR: /* wait if condition bit is 0 */
|
||||
if (!cond)
|
||||
return 1;
|
||||
return 0;
|
||||
if (!cond) {
|
||||
res = 1;
|
||||
}
|
||||
DBDMA_DPRINTFCH(ch, " [WAIT_IFCLR=%d]\n", res);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
static void next(DBDMA_channel *ch)
|
||||
@ -226,8 +228,6 @@ static void conditional_branch(DBDMA_channel *ch)
|
||||
uint32_t status;
|
||||
int cond;
|
||||
|
||||
DBDMA_DPRINTFCH(ch, "conditional_branch\n");
|
||||
|
||||
/* check if we must branch */
|
||||
|
||||
br = le16_to_cpu(current->command) & BR_MASK;
|
||||
@ -237,6 +237,7 @@ static void conditional_branch(DBDMA_channel *ch)
|
||||
next(ch);
|
||||
return;
|
||||
case BR_ALWAYS: /* always branch */
|
||||
DBDMA_DPRINTFCH(ch, " [BR_ALWAYS]\n");
|
||||
branch(ch);
|
||||
return;
|
||||
}
|
||||
@ -250,16 +251,22 @@ static void conditional_branch(DBDMA_channel *ch)
|
||||
|
||||
switch(br) {
|
||||
case BR_IFSET: /* branch if condition bit is 1 */
|
||||
if (cond)
|
||||
if (cond) {
|
||||
DBDMA_DPRINTFCH(ch, " [BR_IFSET = 1]\n");
|
||||
branch(ch);
|
||||
else
|
||||
} else {
|
||||
DBDMA_DPRINTFCH(ch, " [BR_IFSET = 0]\n");
|
||||
next(ch);
|
||||
}
|
||||
return;
|
||||
case BR_IFCLR: /* branch if condition bit is 0 */
|
||||
if (!cond)
|
||||
if (!cond) {
|
||||
DBDMA_DPRINTFCH(ch, " [BR_IFCLR = 1]\n");
|
||||
branch(ch);
|
||||
else
|
||||
} else {
|
||||
DBDMA_DPRINTFCH(ch, " [BR_IFCLR = 0]\n");
|
||||
next(ch);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -428,7 +435,7 @@ wait:
|
||||
|
||||
static void stop(DBDMA_channel *ch)
|
||||
{
|
||||
ch->regs[DBDMA_STATUS] &= ~(ACTIVE|DEAD|FLUSH);
|
||||
ch->regs[DBDMA_STATUS] &= ~(ACTIVE);
|
||||
|
||||
/* the stop command does not increment command pointer */
|
||||
}
|
||||
@ -471,18 +478,22 @@ static void channel_run(DBDMA_channel *ch)
|
||||
|
||||
switch (cmd) {
|
||||
case OUTPUT_MORE:
|
||||
DBDMA_DPRINTFCH(ch, "* OUTPUT_MORE *\n");
|
||||
start_output(ch, key, phy_addr, req_count, 0);
|
||||
return;
|
||||
|
||||
case OUTPUT_LAST:
|
||||
DBDMA_DPRINTFCH(ch, "* OUTPUT_LAST *\n");
|
||||
start_output(ch, key, phy_addr, req_count, 1);
|
||||
return;
|
||||
|
||||
case INPUT_MORE:
|
||||
DBDMA_DPRINTFCH(ch, "* INPUT_MORE *\n");
|
||||
start_input(ch, key, phy_addr, req_count, 0);
|
||||
return;
|
||||
|
||||
case INPUT_LAST:
|
||||
DBDMA_DPRINTFCH(ch, "* INPUT_LAST *\n");
|
||||
start_input(ch, key, phy_addr, req_count, 1);
|
||||
return;
|
||||
}
|
||||
@ -508,10 +519,12 @@ static void channel_run(DBDMA_channel *ch)
|
||||
|
||||
switch (cmd) {
|
||||
case LOAD_WORD:
|
||||
DBDMA_DPRINTFCH(ch, "* LOAD_WORD *\n");
|
||||
load_word(ch, key, phy_addr, req_count);
|
||||
return;
|
||||
|
||||
case STORE_WORD:
|
||||
DBDMA_DPRINTFCH(ch, "* STORE_WORD *\n");
|
||||
store_word(ch, key, phy_addr, req_count);
|
||||
return;
|
||||
}
|
||||
@ -562,43 +575,117 @@ void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq,
|
||||
ch->io.opaque = opaque;
|
||||
}
|
||||
|
||||
static void
|
||||
dbdma_control_write(DBDMA_channel *ch)
|
||||
static void dbdma_control_write(DBDMA_channel *ch)
|
||||
{
|
||||
uint16_t mask, value;
|
||||
uint32_t status;
|
||||
bool do_flush = false;
|
||||
|
||||
mask = (ch->regs[DBDMA_CONTROL] >> 16) & 0xffff;
|
||||
value = ch->regs[DBDMA_CONTROL] & 0xffff;
|
||||
|
||||
value &= (RUN | PAUSE | FLUSH | WAKE | DEVSTAT);
|
||||
|
||||
/* This is the status register which we'll update
|
||||
* appropriately and store back
|
||||
*/
|
||||
status = ch->regs[DBDMA_STATUS];
|
||||
|
||||
status = (value & mask) | (status & ~mask);
|
||||
/* RUN and PAUSE are bits under SW control only
|
||||
* FLUSH and WAKE are set by SW and cleared by HW
|
||||
* DEAD, ACTIVE and BT are only under HW control
|
||||
*
|
||||
* We handle ACTIVE separately at the end of the
|
||||
* logic to ensure all cases are covered.
|
||||
*/
|
||||
|
||||
if (status & WAKE)
|
||||
status |= ACTIVE;
|
||||
if (status & RUN) {
|
||||
status |= ACTIVE;
|
||||
status &= ~DEAD;
|
||||
/* Setting RUN will tentatively activate the channel
|
||||
*/
|
||||
if ((mask & RUN) && (value & RUN)) {
|
||||
status |= RUN;
|
||||
DBDMA_DPRINTFCH(ch, " Setting RUN !\n");
|
||||
}
|
||||
if (status & PAUSE)
|
||||
|
||||
/* Clearing RUN 1->0 will stop the channel */
|
||||
if ((mask & RUN) && !(value & RUN)) {
|
||||
/* This has the side effect of clearing the DEAD bit */
|
||||
status &= ~(DEAD | RUN);
|
||||
DBDMA_DPRINTFCH(ch, " Clearing RUN !\n");
|
||||
}
|
||||
|
||||
/* Setting WAKE wakes up an idle channel if it's running
|
||||
*
|
||||
* Note: The doc doesn't say so but assume that only works
|
||||
* on a channel whose RUN bit is set.
|
||||
*
|
||||
* We set WAKE in status, it's not terribly useful as it will
|
||||
* be cleared on the next command fetch but it seems to mimmic
|
||||
* the HW behaviour and is useful for the way we handle
|
||||
* ACTIVE further down.
|
||||
*/
|
||||
if ((mask & WAKE) && (value & WAKE) && (status & RUN)) {
|
||||
status |= WAKE;
|
||||
DBDMA_DPRINTFCH(ch, " Setting WAKE !\n");
|
||||
}
|
||||
|
||||
/* PAUSE being set will deactivate (or prevent activation)
|
||||
* of the channel. We just copy it over for now, ACTIVE will
|
||||
* be re-evaluated later.
|
||||
*/
|
||||
if (mask & PAUSE) {
|
||||
status = (status & ~PAUSE) | (value & PAUSE);
|
||||
DBDMA_DPRINTFCH(ch, " %sing PAUSE !\n",
|
||||
(value & PAUSE) ? "sett" : "clear");
|
||||
}
|
||||
|
||||
/* FLUSH is its own thing */
|
||||
if ((mask & FLUSH) && (value & FLUSH)) {
|
||||
DBDMA_DPRINTFCH(ch, " Setting FLUSH !\n");
|
||||
/* We set flush directly in the status register, we do *NOT*
|
||||
* set it in "status" so that it gets naturally cleared when
|
||||
* we update the status register further down. That way it
|
||||
* will be set only during the HW flush operation so it is
|
||||
* visible to any completions happening during that time.
|
||||
*/
|
||||
ch->regs[DBDMA_STATUS] |= FLUSH;
|
||||
do_flush = true;
|
||||
}
|
||||
|
||||
/* If either RUN or PAUSE is clear, so should ACTIVE be,
|
||||
* otherwise, ACTIVE will be set if we modified RUN, PAUSE or
|
||||
* set WAKE. That means that PAUSE was just cleared, RUN was
|
||||
* just set or WAKE was just set.
|
||||
*/
|
||||
if ((status & PAUSE) || !(status & RUN)) {
|
||||
status &= ~ACTIVE;
|
||||
if ((ch->regs[DBDMA_STATUS] & RUN) && !(status & RUN)) {
|
||||
/* RUN is cleared */
|
||||
status &= ~(ACTIVE|DEAD);
|
||||
DBDMA_DPRINTFCH(ch, " -> ACTIVE down !\n");
|
||||
|
||||
/* We stopped processing, we want the underlying HW command
|
||||
* to complete *before* we clear the ACTIVE bit. Otherwise
|
||||
* we can get into a situation where the command status will
|
||||
* have RUN or ACTIVE not set which is going to confuse the
|
||||
* MacOS driver.
|
||||
*/
|
||||
do_flush = true;
|
||||
} else if (mask & (RUN | PAUSE)) {
|
||||
status |= ACTIVE;
|
||||
DBDMA_DPRINTFCH(ch, " -> ACTIVE up !\n");
|
||||
} else if ((mask & WAKE) && (value & WAKE)) {
|
||||
status |= ACTIVE;
|
||||
DBDMA_DPRINTFCH(ch, " -> ACTIVE up !\n");
|
||||
}
|
||||
|
||||
if ((status & FLUSH) && ch->flush) {
|
||||
DBDMA_DPRINTFCH(ch, " new status=0x%08x\n", status);
|
||||
|
||||
/* If we need to flush the underlying HW, do it now, this happens
|
||||
* both on FLUSH commands and when stopping the channel for safety.
|
||||
*/
|
||||
if (do_flush && ch->flush) {
|
||||
ch->flush(&ch->io);
|
||||
status &= ~FLUSH;
|
||||
}
|
||||
|
||||
DBDMA_DPRINTFCH(ch, " status 0x%08x\n", status);
|
||||
|
||||
/* Finally update the status register image */
|
||||
ch->regs[DBDMA_STATUS] = status;
|
||||
|
||||
/* If active, make sure the BH gets to run */
|
||||
if (status & ACTIVE) {
|
||||
DBDMA_kick(dbdma_from_ch(ch));
|
||||
}
|
||||
@ -666,13 +753,9 @@ static uint64_t dbdma_read(void *opaque, hwaddr addr,
|
||||
|
||||
value = ch->regs[reg];
|
||||
|
||||
DBDMA_DPRINTFCH(ch, "readl 0x" TARGET_FMT_plx " => 0x%08x\n", addr, value);
|
||||
DBDMA_DPRINTFCH(ch, "channel 0x%x reg 0x%x\n",
|
||||
(uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);
|
||||
|
||||
switch(reg) {
|
||||
case DBDMA_CONTROL:
|
||||
value = 0;
|
||||
value = ch->regs[DBDMA_STATUS];
|
||||
break;
|
||||
case DBDMA_STATUS:
|
||||
case DBDMA_CMDPTR_LO:
|
||||
@ -698,6 +781,10 @@ static uint64_t dbdma_read(void *opaque, hwaddr addr,
|
||||
break;
|
||||
}
|
||||
|
||||
DBDMA_DPRINTFCH(ch, "readl 0x" TARGET_FMT_plx " => 0x%08x\n", addr, value);
|
||||
DBDMA_DPRINTFCH(ch, "channel 0x%x reg 0x%x\n",
|
||||
(uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -764,51 +851,49 @@ static const VMStateDescription vmstate_dbdma = {
|
||||
}
|
||||
};
|
||||
|
||||
static void dbdma_reset(void *opaque)
|
||||
static void mac_dbdma_reset(DeviceState *d)
|
||||
{
|
||||
DBDMAState *s = opaque;
|
||||
DBDMAState *s = MAC_DBDMA(d);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < DBDMA_CHANNELS; i++)
|
||||
for (i = 0; i < DBDMA_CHANNELS; i++) {
|
||||
memset(s->channels[i].regs, 0, DBDMA_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
static void dbdma_unassigned_rw(DBDMA_io *io)
|
||||
{
|
||||
DBDMA_channel *ch = io->channel;
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: use of unassigned channel %d\n",
|
||||
__func__, ch->channel);
|
||||
ch->io.processing = false;
|
||||
}
|
||||
|
||||
static void dbdma_unassigned_flush(DBDMA_io *io)
|
||||
{
|
||||
DBDMA_channel *ch = io->channel;
|
||||
dbdma_cmd *current = &ch->current;
|
||||
uint16_t cmd;
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: use of unassigned channel %d\n",
|
||||
__func__, ch->channel);
|
||||
ch->io.processing = false;
|
||||
|
||||
cmd = le16_to_cpu(current->command) & COMMAND_MASK;
|
||||
if (cmd == OUTPUT_MORE || cmd == OUTPUT_LAST ||
|
||||
cmd == INPUT_MORE || cmd == INPUT_LAST) {
|
||||
current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS] | FLUSH);
|
||||
current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]);
|
||||
current->res_count = cpu_to_le16(io->len);
|
||||
dbdma_cmdptr_save(ch);
|
||||
}
|
||||
}
|
||||
|
||||
void* DBDMA_init (MemoryRegion **dbdma_mem)
|
||||
static void dbdma_unassigned_flush(DBDMA_io *io)
|
||||
{
|
||||
DBDMAState *s;
|
||||
DBDMA_channel *ch = io->channel;
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: use of unassigned channel %d\n",
|
||||
__func__, ch->channel);
|
||||
}
|
||||
|
||||
static void mac_dbdma_init(Object *obj)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
DBDMAState *s = MAC_DBDMA(obj);
|
||||
int i;
|
||||
|
||||
s = g_malloc0(sizeof(DBDMAState));
|
||||
|
||||
for (i = 0; i < DBDMA_CHANNELS; i++) {
|
||||
DBDMA_io *io = &s->channels[i].io;
|
||||
DBDMA_channel *ch = &s->channels[i];
|
||||
qemu_iovec_init(&io->iov, 1);
|
||||
|
||||
ch->rw = dbdma_unassigned_rw;
|
||||
ch->flush = dbdma_unassigned_flush;
|
||||
@ -816,12 +901,37 @@ void* DBDMA_init (MemoryRegion **dbdma_mem)
|
||||
ch->io.channel = ch;
|
||||
}
|
||||
|
||||
memory_region_init_io(&s->mem, NULL, &dbdma_ops, s, "dbdma", 0x1000);
|
||||
*dbdma_mem = &s->mem;
|
||||
vmstate_register(NULL, -1, &vmstate_dbdma, s);
|
||||
qemu_register_reset(dbdma_reset, s);
|
||||
memory_region_init_io(&s->mem, obj, &dbdma_ops, s, "dbdma", 0x1000);
|
||||
sysbus_init_mmio(sbd, &s->mem);
|
||||
}
|
||||
|
||||
static void mac_dbdma_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
DBDMAState *s = MAC_DBDMA(dev);
|
||||
|
||||
s->bh = qemu_bh_new(DBDMA_run_bh, s);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static void mac_dbdma_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
dc->realize = mac_dbdma_realize;
|
||||
dc->reset = mac_dbdma_reset;
|
||||
dc->vmsd = &vmstate_dbdma;
|
||||
}
|
||||
|
||||
static const TypeInfo mac_dbdma_type_info = {
|
||||
.name = TYPE_MAC_DBDMA,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(DBDMAState),
|
||||
.instance_init = mac_dbdma_init,
|
||||
.class_init = mac_dbdma_class_init
|
||||
};
|
||||
|
||||
static void mac_dbdma_register_types(void)
|
||||
{
|
||||
type_register_static(&mac_dbdma_type_info);
|
||||
}
|
||||
|
||||
type_init(mac_dbdma_register_types)
|
||||
|
@ -41,7 +41,7 @@ typedef struct MacIOState
|
||||
|
||||
MemoryRegion bar;
|
||||
CUDAState cuda;
|
||||
void *dbdma;
|
||||
DBDMAState *dbdma;
|
||||
MemoryRegion *pic_mem;
|
||||
MemoryRegion *escc_mem;
|
||||
uint64_t frequency;
|
||||
@ -127,10 +127,15 @@ static void macio_common_realize(PCIDevice *d, Error **errp)
|
||||
MacIOState *s = MACIO(d);
|
||||
SysBusDevice *sysbus_dev;
|
||||
Error *err = NULL;
|
||||
MemoryRegion *dbdma_mem;
|
||||
|
||||
s->dbdma = DBDMA_init(&dbdma_mem);
|
||||
memory_region_add_subregion(&s->bar, 0x08000, dbdma_mem);
|
||||
object_property_set_bool(OBJECT(s->dbdma), true, "realized", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_dev = SYS_BUS_DEVICE(s->dbdma);
|
||||
memory_region_add_subregion(&s->bar, 0x08000,
|
||||
sysbus_mmio_get_region(sysbus_dev, 0));
|
||||
|
||||
object_property_set_bool(OBJECT(&s->cuda), true, "realized", &err);
|
||||
if (err) {
|
||||
@ -154,7 +159,10 @@ static void macio_realize_ide(MacIOState *s, MACIOIDEState *ide,
|
||||
sysbus_dev = SYS_BUS_DEVICE(ide);
|
||||
sysbus_connect_irq(sysbus_dev, 0, irq0);
|
||||
sysbus_connect_irq(sysbus_dev, 1, irq1);
|
||||
macio_ide_register_dma(ide, s->dbdma, dmaid);
|
||||
qdev_prop_set_uint32(DEVICE(ide), "channel", dmaid);
|
||||
object_property_set_link(OBJECT(ide), OBJECT(s->dbdma), "dbdma", errp);
|
||||
macio_ide_register_dma(ide);
|
||||
|
||||
object_property_set_bool(OBJECT(ide), true, "realized", errp);
|
||||
}
|
||||
|
||||
@ -334,6 +342,9 @@ static void macio_instance_init(Object *obj)
|
||||
object_initialize(&s->cuda, sizeof(s->cuda), TYPE_CUDA);
|
||||
qdev_set_parent_bus(DEVICE(&s->cuda), sysbus_get_default());
|
||||
object_property_add_child(obj, "cuda", OBJECT(&s->cuda), NULL);
|
||||
|
||||
s->dbdma = MAC_DBDMA(object_new(TYPE_MAC_DBDMA));
|
||||
object_property_add_child(obj, "dbdma", OBJECT(s->dbdma), NULL);
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_macio_oldworld = {
|
||||
|
10
hw/ppc/mac.h
10
hw/ppc/mac.h
@ -131,8 +131,10 @@ typedef struct MACIOIDEState {
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
qemu_irq irq;
|
||||
uint32_t channel;
|
||||
qemu_irq real_ide_irq;
|
||||
qemu_irq real_dma_irq;
|
||||
qemu_irq ide_irq;
|
||||
qemu_irq dma_irq;
|
||||
|
||||
MemoryRegion mem;
|
||||
@ -140,10 +142,12 @@ typedef struct MACIOIDEState {
|
||||
IDEDMA dma;
|
||||
void *dbdma;
|
||||
bool dma_active;
|
||||
uint32_t timing_reg;
|
||||
uint32_t irq_reg;
|
||||
} MACIOIDEState;
|
||||
|
||||
void macio_ide_init_drives(MACIOIDEState *ide, DriveInfo **hd_table);
|
||||
void macio_ide_register_dma(MACIOIDEState *ide, void *dbdma, int channel);
|
||||
void macio_ide_register_dma(MACIOIDEState *ide);
|
||||
|
||||
void macio_init(PCIDevice *dev,
|
||||
MemoryRegion *pic_mem,
|
||||
|
@ -77,7 +77,7 @@
|
||||
#define MAX_IDE_BUS 2
|
||||
#define CFG_ADDR 0xf0000510
|
||||
#define TBFREQ (100UL * 1000UL * 1000UL)
|
||||
#define CLOCKFREQ (266UL * 1000UL * 1000UL)
|
||||
#define CLOCKFREQ (900UL * 1000UL * 1000UL)
|
||||
#define BUSFREQ (100UL * 1000UL * 1000UL)
|
||||
|
||||
#define NDRV_VGA_FILENAME "qemu_vga.ndrv"
|
||||
@ -342,7 +342,7 @@ static void ppc_core99_init(MachineState *machine)
|
||||
pic = g_new0(qemu_irq, 64);
|
||||
|
||||
dev = qdev_create(NULL, TYPE_OPENPIC);
|
||||
qdev_prop_set_uint32(dev, "model", OPENPIC_MODEL_RAVEN);
|
||||
qdev_prop_set_uint32(dev, "model", OPENPIC_MODEL_KEYLARGO);
|
||||
qdev_init_nofail(dev);
|
||||
s = SYS_BUS_DEVICE(dev);
|
||||
pic_mem = s->mmio[0].memory;
|
||||
|
@ -371,8 +371,10 @@ static int heathrow_kvm_type(const char *arg)
|
||||
return 2;
|
||||
}
|
||||
|
||||
static void heathrow_machine_init(MachineClass *mc)
|
||||
static void heathrow_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
|
||||
mc->desc = "Heathrow based PowerMAC";
|
||||
mc->init = ppc_heathrow_init;
|
||||
mc->block_default_type = IF_IDE;
|
||||
@ -385,4 +387,15 @@ static void heathrow_machine_init(MachineClass *mc)
|
||||
mc->kvm_type = heathrow_kvm_type;
|
||||
}
|
||||
|
||||
DEFINE_MACHINE("g3beige", heathrow_machine_init)
|
||||
static const TypeInfo ppc_heathrow_machine_info = {
|
||||
.name = MACHINE_TYPE_NAME("g3beige"),
|
||||
.parent = TYPE_MACHINE,
|
||||
.class_init = heathrow_class_init
|
||||
};
|
||||
|
||||
static void ppc_heathrow_register_types(void)
|
||||
{
|
||||
type_register_static(&ppc_heathrow_machine_info);
|
||||
}
|
||||
|
||||
type_init(ppc_heathrow_register_types);
|
||||
|
@ -570,10 +570,14 @@ static void ppc_powernv_init(MachineState *machine)
|
||||
}
|
||||
|
||||
fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
|
||||
if (!fw_filename) {
|
||||
error_report("Could not find OPAL firmware '%s'", bios_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fw_size = load_image_targphys(fw_filename, FW_LOAD_ADDR, FW_MAX_SIZE);
|
||||
if (fw_size < 0) {
|
||||
error_report("Could not load OPAL '%s'", fw_filename);
|
||||
error_report("Could not load OPAL firmware '%s'", fw_filename);
|
||||
exit(1);
|
||||
}
|
||||
g_free(fw_filename);
|
||||
|
@ -105,9 +105,12 @@ ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
|
||||
/*****************************************************************************/
|
||||
/* Peripheral local bus arbitrer */
|
||||
enum {
|
||||
PLB0_BESR = 0x084,
|
||||
PLB0_BEAR = 0x086,
|
||||
PLB0_ACR = 0x087,
|
||||
PLB3A0_ACR = 0x077,
|
||||
PLB4A0_ACR = 0x081,
|
||||
PLB0_BESR = 0x084,
|
||||
PLB0_BEAR = 0x086,
|
||||
PLB0_ACR = 0x087,
|
||||
PLB4A1_ACR = 0x089,
|
||||
};
|
||||
|
||||
typedef struct ppc4xx_plb_t ppc4xx_plb_t;
|
||||
@ -179,9 +182,12 @@ void ppc4xx_plb_init(CPUPPCState *env)
|
||||
ppc4xx_plb_t *plb;
|
||||
|
||||
plb = g_malloc0(sizeof(ppc4xx_plb_t));
|
||||
ppc_dcr_register(env, PLB3A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
|
||||
ppc_dcr_register(env, PLB4A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
|
||||
ppc_dcr_register(env, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
|
||||
ppc_dcr_register(env, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb);
|
||||
ppc_dcr_register(env, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb);
|
||||
ppc_dcr_register(env, PLB4A1_ACR, plb, &dcr_read_plb, &dcr_write_plb);
|
||||
qemu_register_reset(ppc4xx_plb_reset, plb);
|
||||
}
|
||||
|
||||
|
@ -1211,14 +1211,15 @@ static uint64_t spapr_get_patbe(PPCVirtualHypervisor *vhyp)
|
||||
*/
|
||||
static int get_htab_fd(sPAPRMachineState *spapr)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (spapr->htab_fd >= 0) {
|
||||
return spapr->htab_fd;
|
||||
}
|
||||
|
||||
spapr->htab_fd = kvmppc_get_htab_fd(false);
|
||||
spapr->htab_fd = kvmppc_get_htab_fd(false, 0, &local_err);
|
||||
if (spapr->htab_fd < 0) {
|
||||
error_report("Unable to open fd for reading hash table from KVM: %s",
|
||||
strerror(errno));
|
||||
error_report_err(local_err);
|
||||
}
|
||||
|
||||
return spapr->htab_fd;
|
||||
@ -1239,6 +1240,19 @@ static hwaddr spapr_hpt_mask(PPCVirtualHypervisor *vhyp)
|
||||
return HTAB_SIZE(spapr) / HASH_PTEG_SIZE_64 - 1;
|
||||
}
|
||||
|
||||
static target_ulong spapr_encode_hpt_for_kvm_pr(PPCVirtualHypervisor *vhyp)
|
||||
{
|
||||
sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp);
|
||||
|
||||
assert(kvm_enabled());
|
||||
|
||||
if (!spapr->htab) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (target_ulong)(uintptr_t)spapr->htab | (spapr->htab_shift - 18);
|
||||
}
|
||||
|
||||
static const ppc_hash_pte64_t *spapr_map_hptes(PPCVirtualHypervisor *vhyp,
|
||||
hwaddr ptex, int n)
|
||||
{
|
||||
@ -1708,6 +1722,23 @@ static int htab_save_setup(QEMUFile *f, void *opaque)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void htab_save_chunk(QEMUFile *f, sPAPRMachineState *spapr,
|
||||
int chunkstart, int n_valid, int n_invalid)
|
||||
{
|
||||
qemu_put_be32(f, chunkstart);
|
||||
qemu_put_be16(f, n_valid);
|
||||
qemu_put_be16(f, n_invalid);
|
||||
qemu_put_buffer(f, HPTE(spapr->htab, chunkstart),
|
||||
HASH_PTE_SIZE_64 * n_valid);
|
||||
}
|
||||
|
||||
static void htab_save_end_marker(QEMUFile *f)
|
||||
{
|
||||
qemu_put_be32(f, 0);
|
||||
qemu_put_be16(f, 0);
|
||||
qemu_put_be16(f, 0);
|
||||
}
|
||||
|
||||
static void htab_save_first_pass(QEMUFile *f, sPAPRMachineState *spapr,
|
||||
int64_t max_ns)
|
||||
{
|
||||
@ -1739,11 +1770,7 @@ static void htab_save_first_pass(QEMUFile *f, sPAPRMachineState *spapr,
|
||||
if (index > chunkstart) {
|
||||
int n_valid = index - chunkstart;
|
||||
|
||||
qemu_put_be32(f, chunkstart);
|
||||
qemu_put_be16(f, n_valid);
|
||||
qemu_put_be16(f, 0);
|
||||
qemu_put_buffer(f, HPTE(spapr->htab, chunkstart),
|
||||
HASH_PTE_SIZE_64 * n_valid);
|
||||
htab_save_chunk(f, spapr, chunkstart, n_valid, 0);
|
||||
|
||||
if (has_timeout &&
|
||||
(qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) {
|
||||
@ -1805,11 +1832,7 @@ static int htab_save_later_pass(QEMUFile *f, sPAPRMachineState *spapr,
|
||||
int n_valid = invalidstart - chunkstart;
|
||||
int n_invalid = index - invalidstart;
|
||||
|
||||
qemu_put_be32(f, chunkstart);
|
||||
qemu_put_be16(f, n_valid);
|
||||
qemu_put_be16(f, n_invalid);
|
||||
qemu_put_buffer(f, HPTE(spapr->htab, chunkstart),
|
||||
HASH_PTE_SIZE_64 * n_valid);
|
||||
htab_save_chunk(f, spapr, chunkstart, n_valid, n_invalid);
|
||||
sent += index - chunkstart;
|
||||
|
||||
if (!final && (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) {
|
||||
@ -1872,10 +1895,7 @@ static int htab_save_iterate(QEMUFile *f, void *opaque)
|
||||
rc = htab_save_later_pass(f, spapr, MAX_ITERATION_NS);
|
||||
}
|
||||
|
||||
/* End marker */
|
||||
qemu_put_be32(f, 0);
|
||||
qemu_put_be16(f, 0);
|
||||
qemu_put_be16(f, 0);
|
||||
htab_save_end_marker(f);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -1915,9 +1935,7 @@ static int htab_save_complete(QEMUFile *f, void *opaque)
|
||||
}
|
||||
|
||||
/* End marker */
|
||||
qemu_put_be32(f, 0);
|
||||
qemu_put_be16(f, 0);
|
||||
qemu_put_be16(f, 0);
|
||||
htab_save_end_marker(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1927,6 +1945,7 @@ static int htab_load(QEMUFile *f, void *opaque, int version_id)
|
||||
sPAPRMachineState *spapr = opaque;
|
||||
uint32_t section_hdr;
|
||||
int fd = -1;
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (version_id < 1 || version_id > 1) {
|
||||
error_report("htab_load() bad version");
|
||||
@ -1941,8 +1960,6 @@ static int htab_load(QEMUFile *f, void *opaque, int version_id)
|
||||
}
|
||||
|
||||
if (section_hdr) {
|
||||
Error *local_err = NULL;
|
||||
|
||||
/* First section gives the htab size */
|
||||
spapr_reallocate_hpt(spapr, section_hdr, &local_err);
|
||||
if (local_err) {
|
||||
@ -1955,10 +1972,10 @@ static int htab_load(QEMUFile *f, void *opaque, int version_id)
|
||||
if (!spapr->htab) {
|
||||
assert(kvm_enabled());
|
||||
|
||||
fd = kvmppc_get_htab_fd(true);
|
||||
fd = kvmppc_get_htab_fd(true, 0, &local_err);
|
||||
if (fd < 0) {
|
||||
error_report("Unable to open fd to restore KVM hash table: %s",
|
||||
strerror(errno));
|
||||
error_report_err(local_err);
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3600,6 +3617,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
|
||||
vhc->unmap_hptes = spapr_unmap_hptes;
|
||||
vhc->store_hpte = spapr_store_hpte;
|
||||
vhc->get_patbe = spapr_get_patbe;
|
||||
vhc->encode_hpt_for_kvm_pr = spapr_encode_hpt_for_kvm_pr;
|
||||
xic->ics_get = spapr_ics_get;
|
||||
xic->ics_resend = spapr_ics_resend;
|
||||
xic->icp_get = spapr_icp_get;
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "hw/ppc/ppc.h"
|
||||
#include "target/ppc/mmu-hash64.h"
|
||||
#include "sysemu/numa.h"
|
||||
#include "sysemu/hw_accel.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
void spapr_cpu_parse_features(sPAPRMachineState *spapr)
|
||||
@ -73,7 +74,6 @@ void spapr_cpu_parse_features(sPAPRMachineState *spapr)
|
||||
|
||||
static void spapr_cpu_reset(void *opaque)
|
||||
{
|
||||
sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
|
||||
PowerPCCPU *cpu = opaque;
|
||||
CPUState *cs = CPU(cpu);
|
||||
CPUPPCState *env = &cpu->env;
|
||||
@ -86,20 +86,6 @@ static void spapr_cpu_reset(void *opaque)
|
||||
cs->halted = 1;
|
||||
|
||||
env->spr[SPR_HIOR] = 0;
|
||||
|
||||
/*
|
||||
* This is a hack for the benefit of KVM PR - it abuses the SDR1
|
||||
* slot in kvm_sregs to communicate the userspace address of the
|
||||
* HPT
|
||||
*/
|
||||
if (kvm_enabled()) {
|
||||
env->spr[SPR_SDR1] = (target_ulong)(uintptr_t)spapr->htab
|
||||
| (spapr->htab_shift - 18);
|
||||
if (kvmppc_put_books_sregs(cpu) < 0) {
|
||||
error_report("Unable to update SDR1 in KVM");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void spapr_cpu_destroy(PowerPCCPU *cpu)
|
||||
|
@ -686,6 +686,37 @@ static int rehash_hpt(PowerPCCPU *cpu,
|
||||
return H_SUCCESS;
|
||||
}
|
||||
|
||||
static void do_push_sregs_to_kvm_pr(CPUState *cs, run_on_cpu_data data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
cpu_synchronize_state(cs);
|
||||
|
||||
ret = kvmppc_put_books_sregs(POWERPC_CPU(cs));
|
||||
if (ret < 0) {
|
||||
error_report("failed to push sregs to KVM: %s", strerror(-ret));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void push_sregs_to_kvm_pr(sPAPRMachineState *spapr)
|
||||
{
|
||||
CPUState *cs;
|
||||
|
||||
/*
|
||||
* This is a hack for the benefit of KVM PR - it abuses the SDR1
|
||||
* slot in kvm_sregs to communicate the userspace address of the
|
||||
* HPT
|
||||
*/
|
||||
if (!kvm_enabled() || !spapr->htab) {
|
||||
return;
|
||||
}
|
||||
|
||||
CPU_FOREACH(cs) {
|
||||
run_on_cpu(cs, do_push_sregs_to_kvm_pr, RUN_ON_CPU_NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static target_ulong h_resize_hpt_commit(PowerPCCPU *cpu,
|
||||
sPAPRMachineState *spapr,
|
||||
target_ulong opcode,
|
||||
@ -733,12 +764,7 @@ static target_ulong h_resize_hpt_commit(PowerPCCPU *cpu,
|
||||
spapr->htab = pending->hpt;
|
||||
spapr->htab_shift = pending->shift;
|
||||
|
||||
if (kvm_enabled()) {
|
||||
/* For KVM PR, update the HPT pointer */
|
||||
target_ulong sdr1 = (target_ulong)(uintptr_t)spapr->htab
|
||||
| (spapr->htab_shift - 18);
|
||||
kvmppc_update_sdr1(sdr1);
|
||||
}
|
||||
push_sregs_to_kvm_pr(spapr);
|
||||
|
||||
pending->hpt = NULL; /* so it's not free()d */
|
||||
}
|
||||
@ -1564,12 +1590,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
|
||||
* the point this is called, nothing should have been
|
||||
* entered into the existing HPT */
|
||||
spapr_reallocate_hpt(spapr, maxshift, &error_fatal);
|
||||
if (kvm_enabled()) {
|
||||
/* For KVM PR, update the HPT pointer */
|
||||
target_ulong sdr1 = (target_ulong)(uintptr_t)spapr->htab
|
||||
| (spapr->htab_shift - 18);
|
||||
kvmppc_update_sdr1(sdr1);
|
||||
}
|
||||
push_sregs_to_kvm_pr(spapr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1523,16 +1523,6 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
|
||||
sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
|
||||
Error *local_err = NULL;
|
||||
|
||||
if ((sphb->buid != (uint64_t)-1) || (sphb->dma_liobn[0] != (uint32_t)-1)
|
||||
|| (sphb->dma_liobn[1] != (uint32_t)-1 && windows_supported == 2)
|
||||
|| (sphb->mem_win_addr != (hwaddr)-1)
|
||||
|| (sphb->mem64_win_addr != (hwaddr)-1)
|
||||
|| (sphb->io_win_addr != (hwaddr)-1)) {
|
||||
error_setg(errp, "Either \"index\" or other parameters must"
|
||||
" be specified for PAPR PHB, not both");
|
||||
return;
|
||||
}
|
||||
|
||||
smc->phb_placement(spapr, sphb->index,
|
||||
&sphb->buid, &sphb->io_win_addr,
|
||||
&sphb->mem_win_addr, &sphb->mem64_win_addr,
|
||||
@ -1541,46 +1531,20 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (sphb->buid == (uint64_t)-1) {
|
||||
error_setg(errp, "BUID not specified for PHB");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((sphb->dma_liobn[0] == (uint32_t)-1) ||
|
||||
((sphb->dma_liobn[1] == (uint32_t)-1) && (windows_supported > 1))) {
|
||||
error_setg(errp, "LIOBN(s) not specified for PHB");
|
||||
return;
|
||||
}
|
||||
|
||||
if (sphb->mem_win_addr == (hwaddr)-1) {
|
||||
error_setg(errp, "Memory window address not specified for PHB");
|
||||
return;
|
||||
}
|
||||
|
||||
if (sphb->io_win_addr == (hwaddr)-1) {
|
||||
error_setg(errp, "IO window address not specified for PHB");
|
||||
} else {
|
||||
error_setg(errp, "\"index\" for PAPR PHB is mandatory");
|
||||
return;
|
||||
}
|
||||
|
||||
if (sphb->mem64_win_size != 0) {
|
||||
if (sphb->mem64_win_addr == (hwaddr)-1) {
|
||||
error_setg(errp,
|
||||
"64-bit memory window address not specified for PHB");
|
||||
return;
|
||||
}
|
||||
|
||||
if (sphb->mem_win_size > SPAPR_PCI_MEM32_WIN_SIZE) {
|
||||
error_setg(errp, "32-bit memory window of size 0x%"HWADDR_PRIx
|
||||
" (max 2 GiB)", sphb->mem_win_size);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sphb->mem64_win_pciaddr == (hwaddr)-1) {
|
||||
/* 64-bit window defaults to identity mapping */
|
||||
sphb->mem64_win_pciaddr = sphb->mem64_win_addr;
|
||||
}
|
||||
/* 64-bit window defaults to identity mapping */
|
||||
sphb->mem64_win_pciaddr = sphb->mem64_win_addr;
|
||||
} else if (sphb->mem_win_size > SPAPR_PCI_MEM32_WIN_SIZE) {
|
||||
/*
|
||||
* For compatibility with old configuration, if no 64-bit MMIO
|
||||
@ -1622,18 +1586,16 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
|
||||
memory_region_add_subregion(get_system_memory(), sphb->mem_win_addr,
|
||||
&sphb->mem32window);
|
||||
|
||||
if (sphb->mem64_win_pciaddr != (hwaddr)-1) {
|
||||
if (sphb->mem64_win_size != 0) {
|
||||
namebuf = g_strdup_printf("%s.mmio64-alias", sphb->dtbusname);
|
||||
memory_region_init_alias(&sphb->mem64window, OBJECT(sphb),
|
||||
namebuf, &sphb->memspace,
|
||||
sphb->mem64_win_pciaddr, sphb->mem64_win_size);
|
||||
g_free(namebuf);
|
||||
|
||||
if (sphb->mem64_win_addr != (hwaddr)-1) {
|
||||
memory_region_add_subregion(get_system_memory(),
|
||||
sphb->mem64_win_addr,
|
||||
&sphb->mem64window);
|
||||
}
|
||||
memory_region_add_subregion(get_system_memory(),
|
||||
sphb->mem64_win_addr,
|
||||
&sphb->mem64window);
|
||||
}
|
||||
|
||||
/* Initialize IO regions */
|
||||
@ -1789,18 +1751,10 @@ static void spapr_phb_reset(DeviceState *qdev)
|
||||
|
||||
static Property spapr_phb_properties[] = {
|
||||
DEFINE_PROP_UINT32("index", sPAPRPHBState, index, -1),
|
||||
DEFINE_PROP_UINT64("buid", sPAPRPHBState, buid, -1),
|
||||
DEFINE_PROP_UINT32("liobn", sPAPRPHBState, dma_liobn[0], -1),
|
||||
DEFINE_PROP_UINT32("liobn64", sPAPRPHBState, dma_liobn[1], -1),
|
||||
DEFINE_PROP_UINT64("mem_win_addr", sPAPRPHBState, mem_win_addr, -1),
|
||||
DEFINE_PROP_UINT64("mem_win_size", sPAPRPHBState, mem_win_size,
|
||||
SPAPR_PCI_MEM32_WIN_SIZE),
|
||||
DEFINE_PROP_UINT64("mem64_win_addr", sPAPRPHBState, mem64_win_addr, -1),
|
||||
DEFINE_PROP_UINT64("mem64_win_size", sPAPRPHBState, mem64_win_size,
|
||||
SPAPR_PCI_MEM64_WIN_SIZE),
|
||||
DEFINE_PROP_UINT64("mem64_win_pciaddr", sPAPRPHBState, mem64_win_pciaddr,
|
||||
-1),
|
||||
DEFINE_PROP_UINT64("io_win_addr", sPAPRPHBState, io_win_addr, -1),
|
||||
DEFINE_PROP_UINT64("io_win_size", sPAPRPHBState, io_win_size,
|
||||
SPAPR_PCI_IO_WIN_SIZE),
|
||||
DEFINE_PROP_BOOL("dynamic-reconfiguration", sPAPRPHBState, dr_enabled,
|
||||
|
@ -142,6 +142,30 @@ static const TypeInfo ehci_tegra2_type_info = {
|
||||
.class_init = ehci_tegra2_class_init,
|
||||
};
|
||||
|
||||
static void ehci_ppc4xx_init(Object *o)
|
||||
{
|
||||
EHCISysBusState *s = SYS_BUS_EHCI(o);
|
||||
|
||||
s->ehci.companion_enable = true;
|
||||
}
|
||||
|
||||
static void ehci_ppc4xx_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
sec->capsbase = 0x0;
|
||||
sec->opregbase = 0x10;
|
||||
set_bit(DEVICE_CATEGORY_USB, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo ehci_ppc4xx_type_info = {
|
||||
.name = TYPE_PPC4xx_EHCI,
|
||||
.parent = TYPE_SYS_BUS_EHCI,
|
||||
.class_init = ehci_ppc4xx_class_init,
|
||||
.instance_init = ehci_ppc4xx_init,
|
||||
};
|
||||
|
||||
/*
|
||||
* Faraday FUSBH200 USB 2.0 EHCI
|
||||
*/
|
||||
@ -224,6 +248,7 @@ static void ehci_sysbus_register_types(void)
|
||||
type_register_static(&ehci_xlnx_type_info);
|
||||
type_register_static(&ehci_exynos4210_type_info);
|
||||
type_register_static(&ehci_tegra2_type_info);
|
||||
type_register_static(&ehci_ppc4xx_type_info);
|
||||
type_register_static(&ehci_fusbh200_type_info);
|
||||
}
|
||||
|
||||
|
@ -344,6 +344,7 @@ typedef struct EHCIPCIState {
|
||||
#define TYPE_SYS_BUS_EHCI "sysbus-ehci-usb"
|
||||
#define TYPE_EXYNOS4210_EHCI "exynos4210-ehci-usb"
|
||||
#define TYPE_TEGRA2_EHCI "tegra2-ehci-usb"
|
||||
#define TYPE_PPC4xx_EHCI "ppc4xx-ehci-usb"
|
||||
#define TYPE_FUSBH200_EHCI "fusbh200-ehci-usb"
|
||||
|
||||
#define SYS_BUS_EHCI(obj) \
|
||||
|
@ -1999,7 +1999,9 @@ typedef struct {
|
||||
/*< public >*/
|
||||
|
||||
OHCIState ohci;
|
||||
char *masterbus;
|
||||
uint32_t num_ports;
|
||||
uint32_t firstport;
|
||||
dma_addr_t dma_offset;
|
||||
} OHCISysBusState;
|
||||
|
||||
@ -2007,10 +2009,15 @@ static void ohci_realize_pxa(DeviceState *dev, Error **errp)
|
||||
{
|
||||
OHCISysBusState *s = SYSBUS_OHCI(dev);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
Error *err = NULL;
|
||||
|
||||
/* Cannot fail as we pass NULL for masterbus */
|
||||
usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset, NULL, 0,
|
||||
&address_space_memory, &error_abort);
|
||||
usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset,
|
||||
s->masterbus, s->firstport,
|
||||
&address_space_memory, &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_init_irq(sbd, &s->ohci.irq);
|
||||
sysbus_init_mmio(sbd, &s->ohci.mem);
|
||||
}
|
||||
@ -2142,7 +2149,9 @@ static const TypeInfo ohci_pci_info = {
|
||||
};
|
||||
|
||||
static Property ohci_sysbus_properties[] = {
|
||||
DEFINE_PROP_STRING("masterbus", OHCISysBusState, masterbus),
|
||||
DEFINE_PROP_UINT32("num-ports", OHCISysBusState, num_ports, 3),
|
||||
DEFINE_PROP_UINT32("firstport", OHCISysBusState, firstport, 0),
|
||||
DEFINE_PROP_DMAADDR("dma-offset", OHCISysBusState, dma_offset, 0),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "exec/memory.h"
|
||||
#include "qemu/iov.h"
|
||||
#include "sysemu/dma.h"
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
typedef struct DBDMA_io DBDMA_io;
|
||||
|
||||
@ -42,10 +43,6 @@ struct DBDMA_io {
|
||||
DBDMA_end dma_end;
|
||||
/* DMA is in progress, don't start another one */
|
||||
bool processing;
|
||||
/* unaligned last sector of a request */
|
||||
uint8_t head_remainder[0x200];
|
||||
uint8_t tail_remainder[0x200];
|
||||
QEMUIOVector iov;
|
||||
/* DMA request */
|
||||
void *dma_mem;
|
||||
dma_addr_t dma_len;
|
||||
@ -164,6 +161,8 @@ typedef struct DBDMA_channel {
|
||||
} DBDMA_channel;
|
||||
|
||||
typedef struct {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
MemoryRegion mem;
|
||||
DBDMA_channel channels[DBDMA_CHANNELS];
|
||||
QEMUBH *bh;
|
||||
@ -175,6 +174,8 @@ void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq,
|
||||
DBDMA_rw rw, DBDMA_flush flush,
|
||||
void *opaque);
|
||||
void DBDMA_kick(DBDMAState *dbdma);
|
||||
void* DBDMA_init (MemoryRegion **dbdma_mem);
|
||||
|
||||
#define TYPE_MAC_DBDMA "mac-dbdma"
|
||||
#define MAC_DBDMA(obj) OBJECT_CHECK(DBDMAState, (obj), TYPE_MAC_DBDMA)
|
||||
|
||||
#endif
|
||||
|
@ -20,6 +20,7 @@ enum {
|
||||
#define OPENPIC_MODEL_RAVEN 0
|
||||
#define OPENPIC_MODEL_FSL_MPIC_20 1
|
||||
#define OPENPIC_MODEL_FSL_MPIC_42 2
|
||||
#define OPENPIC_MODEL_KEYLARGO 3
|
||||
|
||||
#define OPENPIC_MAX_SRC 256
|
||||
#define OPENPIC_MAX_TMR 4
|
||||
|
@ -54,7 +54,7 @@ typedef struct PnvXScomInterfaceClass {
|
||||
* PCB SLAVE 0x110Fxxxx
|
||||
*/
|
||||
|
||||
#define PNV_XSCOM_EX_CORE_BASE(base, i) (base | (((uint64_t)i) << 24))
|
||||
#define PNV_XSCOM_EX_CORE_BASE(base, i) ((base) | ((uint64_t)(i) << 24))
|
||||
#define PNV_XSCOM_EX_CORE_SIZE 0x100000
|
||||
|
||||
#define PNV_XSCOM_LPC_BASE 0xb0020
|
||||
|
@ -167,6 +167,8 @@
|
||||
"PowerPC 440 EPb")
|
||||
POWERPC_DEF("440epx", CPU_POWERPC_440EPX, 440EP,
|
||||
"PowerPC 440 EPX")
|
||||
POWERPC_DEF("460exb", CPU_POWERPC_460EXb, 460EX,
|
||||
"PowerPC 460 EXb")
|
||||
#if defined(TODO_USER_ONLY)
|
||||
POWERPC_DEF("440gpb", CPU_POWERPC_440GPb, 440GP,
|
||||
"PowerPC 440 GPb")
|
||||
@ -786,6 +788,7 @@ PowerPCCPUAlias ppc_cpu_aliases[] = {
|
||||
{ "x2vp50", "x2vp20" },
|
||||
|
||||
{ "440ep", "440epb" },
|
||||
{ "460ex", "460exb" },
|
||||
#if defined(TODO_USER_ONLY)
|
||||
{ "440gp", "440gpc" },
|
||||
{ "440gr", "440gra" },
|
||||
|
@ -44,184 +44,55 @@ enum {
|
||||
/* PowerPC 401 cores */
|
||||
CPU_POWERPC_401A1 = 0x00210000,
|
||||
CPU_POWERPC_401B2 = 0x00220000,
|
||||
#if 0
|
||||
CPU_POWERPC_401B3 = xxx,
|
||||
#endif
|
||||
CPU_POWERPC_401C2 = 0x00230000,
|
||||
CPU_POWERPC_401D2 = 0x00240000,
|
||||
CPU_POWERPC_401E2 = 0x00250000,
|
||||
CPU_POWERPC_401F2 = 0x00260000,
|
||||
CPU_POWERPC_401G2 = 0x00270000,
|
||||
/* PowerPC 401 microcontrolers */
|
||||
#if 0
|
||||
CPU_POWERPC_401GF = xxx,
|
||||
#endif
|
||||
#define CPU_POWERPC_IOP480 CPU_POWERPC_401B2
|
||||
/* IBM Processor for Network Resources */
|
||||
CPU_POWERPC_COBRA = 0x10100000, /* XXX: 405 ? */
|
||||
#if 0
|
||||
CPU_POWERPC_XIPCHIP = xxx,
|
||||
#endif
|
||||
/* PowerPC 403 family */
|
||||
/* PowerPC 403 microcontrollers */
|
||||
CPU_POWERPC_403GA = 0x00200011,
|
||||
CPU_POWERPC_403GB = 0x00200100,
|
||||
CPU_POWERPC_403GC = 0x00200200,
|
||||
CPU_POWERPC_403GCX = 0x00201400,
|
||||
#if 0
|
||||
CPU_POWERPC_403GP = xxx,
|
||||
#endif
|
||||
/* PowerPC 405 family */
|
||||
/* PowerPC 405 cores */
|
||||
#if 0
|
||||
CPU_POWERPC_405A3 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWERPC_405A4 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWERPC_405B3 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWERPC_405B4 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWERPC_405C3 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWERPC_405C4 = xxx,
|
||||
#endif
|
||||
CPU_POWERPC_405D2 = 0x20010000,
|
||||
#if 0
|
||||
CPU_POWERPC_405D3 = xxx,
|
||||
#endif
|
||||
CPU_POWERPC_405D4 = 0x41810000,
|
||||
#if 0
|
||||
CPU_POWERPC_405D5 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWERPC_405E4 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWERPC_405F4 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWERPC_405F5 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWERPC_405F6 = xxx,
|
||||
#endif
|
||||
/* PowerPC 405 microcontrolers */
|
||||
/* XXX: missing 0x200108a0 */
|
||||
CPU_POWERPC_405CRa = 0x40110041,
|
||||
CPU_POWERPC_405CRb = 0x401100C5,
|
||||
CPU_POWERPC_405CRc = 0x40110145,
|
||||
CPU_POWERPC_405EP = 0x51210950,
|
||||
#if 0
|
||||
CPU_POWERPC_405EXr = xxx,
|
||||
#endif
|
||||
CPU_POWERPC_405EZ = 0x41511460, /* 0x51210950 ? */
|
||||
#if 0
|
||||
CPU_POWERPC_405FX = xxx,
|
||||
#endif
|
||||
CPU_POWERPC_405GPa = 0x40110000,
|
||||
CPU_POWERPC_405GPb = 0x40110040,
|
||||
CPU_POWERPC_405GPc = 0x40110082,
|
||||
CPU_POWERPC_405GPd = 0x401100C4,
|
||||
CPU_POWERPC_405GPR = 0x50910951,
|
||||
#if 0
|
||||
CPU_POWERPC_405H = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWERPC_405L = xxx,
|
||||
#endif
|
||||
CPU_POWERPC_405LP = 0x41F10000,
|
||||
#if 0
|
||||
CPU_POWERPC_405PM = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWERPC_405PS = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWERPC_405S = xxx,
|
||||
#endif
|
||||
/* IBM network processors */
|
||||
CPU_POWERPC_NPE405H = 0x414100C0,
|
||||
CPU_POWERPC_NPE405H2 = 0x41410140,
|
||||
CPU_POWERPC_NPE405L = 0x416100C0,
|
||||
CPU_POWERPC_NPE4GS3 = 0x40B10000,
|
||||
#if 0
|
||||
CPU_POWERPC_NPCxx1 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWERPC_NPR161 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWERPC_LC77700 = xxx,
|
||||
#endif
|
||||
/* IBM STBxxx (PowerPC 401/403/405 core based microcontrollers) */
|
||||
#if 0
|
||||
CPU_POWERPC_STB01000 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWERPC_STB01010 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWERPC_STB0210 = xxx, /* 401B3 */
|
||||
#endif
|
||||
CPU_POWERPC_STB03 = 0x40310000, /* 0x40130000 ? */
|
||||
#if 0
|
||||
CPU_POWERPC_STB043 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWERPC_STB045 = xxx,
|
||||
#endif
|
||||
CPU_POWERPC_STB04 = 0x41810000,
|
||||
CPU_POWERPC_STB25 = 0x51510950,
|
||||
#if 0
|
||||
CPU_POWERPC_STB130 = xxx,
|
||||
#endif
|
||||
/* Xilinx cores */
|
||||
CPU_POWERPC_X2VP4 = 0x20010820,
|
||||
CPU_POWERPC_X2VP20 = 0x20010860,
|
||||
#if 0
|
||||
CPU_POWERPC_ZL10310 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWERPC_ZL10311 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWERPC_ZL10320 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWERPC_ZL10321 = xxx,
|
||||
#endif
|
||||
/* PowerPC 440 family */
|
||||
/* Generic PowerPC 440 */
|
||||
#define CPU_POWERPC_440 CPU_POWERPC_440GXf
|
||||
/* PowerPC 440 cores */
|
||||
#if 0
|
||||
CPU_POWERPC_440A4 = xxx,
|
||||
#endif
|
||||
CPU_POWERPC_440_XILINX = 0x7ff21910,
|
||||
#if 0
|
||||
CPU_POWERPC_440A5 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWERPC_440B4 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWERPC_440F5 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWERPC_440G5 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWERPC_440H4 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWERPC_440H6 = xxx,
|
||||
#endif
|
||||
/* PowerPC 440 microcontrolers */
|
||||
CPU_POWERPC_440EPa = 0x42221850,
|
||||
CPU_POWERPC_440EPb = 0x422218D3,
|
||||
@ -234,24 +105,10 @@ enum {
|
||||
CPU_POWERPC_440GXb = 0x51B21851,
|
||||
CPU_POWERPC_440GXc = 0x51B21892,
|
||||
CPU_POWERPC_440GXf = 0x51B21894,
|
||||
#if 0
|
||||
CPU_POWERPC_440S = xxx,
|
||||
#endif
|
||||
CPU_POWERPC_440SP = 0x53221850,
|
||||
CPU_POWERPC_440SP2 = 0x53221891,
|
||||
CPU_POWERPC_440SPE = 0x53421890,
|
||||
/* PowerPC 460 family */
|
||||
#if 0
|
||||
/* Generic PowerPC 464 */
|
||||
#define CPU_POWERPC_464 CPU_POWERPC_464H90
|
||||
#endif
|
||||
/* PowerPC 464 microcontrolers */
|
||||
#if 0
|
||||
CPU_POWERPC_464H90 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWERPC_464H90FP = xxx,
|
||||
#endif
|
||||
CPU_POWERPC_460EXb = 0x130218A4, /* called 460 but 440 core */
|
||||
/* Freescale embedded PowerPC cores */
|
||||
/* PowerPC MPC 5xx cores (aka RCPU) */
|
||||
CPU_POWERPC_MPC5xx = 0x00020020,
|
||||
@ -280,45 +137,8 @@ enum {
|
||||
#define CPU_POWERPC_MPC5200B_v21 CPU_POWERPC_G2LEgp1
|
||||
/* e200 family */
|
||||
/* e200 cores */
|
||||
#if 0
|
||||
CPU_POWERPC_e200z0 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWERPC_e200z1 = xxx,
|
||||
#endif
|
||||
#if 0 /* ? */
|
||||
CPU_POWERPC_e200z3 = 0x81120000,
|
||||
#endif
|
||||
CPU_POWERPC_e200z5 = 0x81000000,
|
||||
CPU_POWERPC_e200z6 = 0x81120000,
|
||||
/* MPC55xx microcontrollers */
|
||||
#define CPU_POWERPC_MPC55xx CPU_POWERPC_MPC5567
|
||||
#if 0
|
||||
#define CPU_POWERPC_MPC5514E CPU_POWERPC_MPC5514E_v1
|
||||
#define CPU_POWERPC_MPC5514E_v0 CPU_POWERPC_e200z0
|
||||
#define CPU_POWERPC_MPC5514E_v1 CPU_POWERPC_e200z1
|
||||
#define CPU_POWERPC_MPC5514G CPU_POWERPC_MPC5514G_v1
|
||||
#define CPU_POWERPC_MPC5514G_v0 CPU_POWERPC_e200z0
|
||||
#define CPU_POWERPC_MPC5514G_v1 CPU_POWERPC_e200z1
|
||||
#define CPU_POWERPC_MPC5515S CPU_POWERPC_e200z1
|
||||
#define CPU_POWERPC_MPC5516E CPU_POWERPC_MPC5516E_v1
|
||||
#define CPU_POWERPC_MPC5516E_v0 CPU_POWERPC_e200z0
|
||||
#define CPU_POWERPC_MPC5516E_v1 CPU_POWERPC_e200z1
|
||||
#define CPU_POWERPC_MPC5516G CPU_POWERPC_MPC5516G_v1
|
||||
#define CPU_POWERPC_MPC5516G_v0 CPU_POWERPC_e200z0
|
||||
#define CPU_POWERPC_MPC5516G_v1 CPU_POWERPC_e200z1
|
||||
#define CPU_POWERPC_MPC5516S CPU_POWERPC_e200z1
|
||||
#endif
|
||||
#if 0
|
||||
#define CPU_POWERPC_MPC5533 CPU_POWERPC_e200z3
|
||||
#define CPU_POWERPC_MPC5534 CPU_POWERPC_e200z3
|
||||
#endif
|
||||
#define CPU_POWERPC_MPC5553 CPU_POWERPC_e200z6
|
||||
#define CPU_POWERPC_MPC5554 CPU_POWERPC_e200z6
|
||||
#define CPU_POWERPC_MPC5561 CPU_POWERPC_e200z6
|
||||
#define CPU_POWERPC_MPC5565 CPU_POWERPC_e200z6
|
||||
#define CPU_POWERPC_MPC5566 CPU_POWERPC_e200z6
|
||||
#define CPU_POWERPC_MPC5567 CPU_POWERPC_e200z6
|
||||
/* e300 family */
|
||||
/* e300 cores */
|
||||
CPU_POWERPC_e300c1 = 0x00830010,
|
||||
@ -326,11 +146,7 @@ enum {
|
||||
CPU_POWERPC_e300c3 = 0x00850010,
|
||||
CPU_POWERPC_e300c4 = 0x00860010,
|
||||
/* MPC83xx microcontrollers */
|
||||
#define CPU_POWERPC_MPC831x CPU_POWERPC_e300c3
|
||||
#define CPU_POWERPC_MPC832x CPU_POWERPC_e300c2
|
||||
#define CPU_POWERPC_MPC834x CPU_POWERPC_e300c1
|
||||
#define CPU_POWERPC_MPC835x CPU_POWERPC_e300c1
|
||||
#define CPU_POWERPC_MPC836x CPU_POWERPC_e300c1
|
||||
#define CPU_POWERPC_MPC837x CPU_POWERPC_e300c4
|
||||
/* e500 family */
|
||||
/* e500 cores */
|
||||
@ -438,9 +254,6 @@ enum {
|
||||
/* XXX: missing 0x000a0100 */
|
||||
/* XXX: missing 0x00093102 */
|
||||
CPU_POWERPC_604R = 0x000a0101,
|
||||
#if 0
|
||||
CPU_POWERPC_604EV = xxx, /* XXX: same as 604R ? */
|
||||
#endif
|
||||
/* PowerPC 740/750 cores (aka G3) */
|
||||
/* XXX: missing 0x00084202 */
|
||||
CPU_POWERPC_7x0_v10 = 0x00080100,
|
||||
@ -495,9 +308,6 @@ enum {
|
||||
CPU_POWERPC_7x5_v26 = 0x00083206,
|
||||
CPU_POWERPC_7x5_v27 = 0x00083207,
|
||||
CPU_POWERPC_7x5_v28 = 0x00083208,
|
||||
#if 0
|
||||
CPU_POWERPC_7x5P = xxx,
|
||||
#endif
|
||||
/* PowerPC 74xx cores (aka G4) */
|
||||
/* XXX: missing 0x000C1101 */
|
||||
CPU_POWERPC_7400_v10 = 0x000C0100,
|
||||
@ -585,12 +395,6 @@ enum {
|
||||
/* XXX: should be POWER (RIOS), RSC3308, RSC4608,
|
||||
* POWER2 (RIOS2) & RSC2 (P2SC) here
|
||||
*/
|
||||
#if 0
|
||||
CPU_POWER = xxx, /* 0x20000 ? 0x30000 for RSC ? */
|
||||
#endif
|
||||
#if 0
|
||||
CPU_POWER2 = xxx, /* 0x40000 ? */
|
||||
#endif
|
||||
/* PA Semi core */
|
||||
CPU_POWERPC_PA6T = 0x00900000,
|
||||
};
|
||||
@ -614,60 +418,6 @@ enum {
|
||||
POWERPC_SVR_5200B_v20 = 0x80110020,
|
||||
POWERPC_SVR_5200B_v21 = 0x80110021,
|
||||
#define POWERPC_SVR_55xx POWERPC_SVR_5567
|
||||
#if 0
|
||||
POWERPC_SVR_5533 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
POWERPC_SVR_5534 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
POWERPC_SVR_5553 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
POWERPC_SVR_5554 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
POWERPC_SVR_5561 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
POWERPC_SVR_5565 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
POWERPC_SVR_5566 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
POWERPC_SVR_5567 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
POWERPC_SVR_8313 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
POWERPC_SVR_8313E = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
POWERPC_SVR_8314 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
POWERPC_SVR_8314E = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
POWERPC_SVR_8315 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
POWERPC_SVR_8315E = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
POWERPC_SVR_8321 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
POWERPC_SVR_8321E = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
POWERPC_SVR_8323 = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
POWERPC_SVR_8323E = xxx,
|
||||
#endif
|
||||
POWERPC_SVR_8343 = 0x80570010,
|
||||
POWERPC_SVR_8343A = 0x80570030,
|
||||
POWERPC_SVR_8343E = 0x80560010,
|
||||
@ -684,12 +434,6 @@ enum {
|
||||
POWERPC_SVR_8349A = 0x80510030,
|
||||
POWERPC_SVR_8349E = 0x80500010,
|
||||
POWERPC_SVR_8349EA = 0x80500030,
|
||||
#if 0
|
||||
POWERPC_SVR_8358E = xxx,
|
||||
#endif
|
||||
#if 0
|
||||
POWERPC_SVR_8360E = xxx,
|
||||
#endif
|
||||
#define POWERPC_SVR_E500 0x40000000
|
||||
POWERPC_SVR_8377 = 0x80C70010 | POWERPC_SVR_E500,
|
||||
POWERPC_SVR_8377E = 0x80C60010 | POWERPC_SVR_E500,
|
||||
|
@ -1243,6 +1243,7 @@ struct PPCVirtualHypervisorClass {
|
||||
void (*store_hpte)(PPCVirtualHypervisor *vhyp, hwaddr ptex,
|
||||
uint64_t pte0, uint64_t pte1);
|
||||
uint64_t (*get_patbe)(PPCVirtualHypervisor *vhyp);
|
||||
target_ulong (*encode_hpt_for_kvm_pr)(PPCVirtualHypervisor *vhyp);
|
||||
};
|
||||
|
||||
#define TYPE_PPC_VIRTUAL_HYPERVISOR "ppc-virtual-hypervisor"
|
||||
|
@ -131,7 +131,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
|
||||
cap_interrupt_level = kvm_check_extension(s, KVM_CAP_PPC_IRQ_LEVEL);
|
||||
cap_segstate = kvm_check_extension(s, KVM_CAP_PPC_SEGSTATE);
|
||||
cap_booke_sregs = kvm_check_extension(s, KVM_CAP_PPC_BOOKE_SREGS);
|
||||
cap_ppc_smt_possible = kvm_check_extension(s, KVM_CAP_PPC_SMT_POSSIBLE);
|
||||
cap_ppc_smt_possible = kvm_vm_check_extension(s, KVM_CAP_PPC_SMT_POSSIBLE);
|
||||
cap_ppc_rma = kvm_check_extension(s, KVM_CAP_PPC_RMA);
|
||||
cap_spapr_tce = kvm_check_extension(s, KVM_CAP_SPAPR_TCE);
|
||||
cap_spapr_tce_64 = kvm_check_extension(s, KVM_CAP_SPAPR_TCE_64);
|
||||
@ -143,7 +143,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
|
||||
cap_ppc_watchdog = kvm_check_extension(s, KVM_CAP_PPC_BOOKE_WATCHDOG);
|
||||
/* Note: we don't set cap_papr here, because this capability is
|
||||
* only activated after this by kvmppc_set_papr() */
|
||||
cap_htab_fd = kvm_check_extension(s, KVM_CAP_PPC_HTAB_FD);
|
||||
cap_htab_fd = kvm_vm_check_extension(s, KVM_CAP_PPC_HTAB_FD);
|
||||
cap_fixup_hcalls = kvm_check_extension(s, KVM_CAP_PPC_FIXUP_HCALL);
|
||||
cap_ppc_smt = kvm_vm_check_extension(s, KVM_CAP_PPC_SMT);
|
||||
cap_htm = kvm_vm_check_extension(s, KVM_CAP_PPC_HTM);
|
||||
@ -941,7 +941,13 @@ int kvmppc_put_books_sregs(PowerPCCPU *cpu)
|
||||
|
||||
sregs.pvr = env->spr[SPR_PVR];
|
||||
|
||||
sregs.u.s.sdr1 = env->spr[SPR_SDR1];
|
||||
if (cpu->vhyp) {
|
||||
PPCVirtualHypervisorClass *vhc =
|
||||
PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
|
||||
sregs.u.s.sdr1 = vhc->encode_hpt_for_kvm_pr(cpu->vhyp);
|
||||
} else {
|
||||
sregs.u.s.sdr1 = env->spr[SPR_SDR1];
|
||||
}
|
||||
|
||||
/* Sync SLB */
|
||||
#ifdef TARGET_PPC64
|
||||
@ -2353,7 +2359,7 @@ int kvmppc_reset_htab(int shift_hint)
|
||||
/* Full emulation, tell caller to allocate htab itself */
|
||||
return 0;
|
||||
}
|
||||
if (kvm_check_extension(kvm_state, KVM_CAP_PPC_ALLOC_HTAB)) {
|
||||
if (kvm_vm_check_extension(kvm_state, KVM_CAP_PPC_ALLOC_HTAB)) {
|
||||
int ret;
|
||||
ret = kvm_vm_ioctl(kvm_state, KVM_PPC_ALLOCATE_HTAB, &shift);
|
||||
if (ret == -ENOTTY) {
|
||||
@ -2448,11 +2454,6 @@ bool kvmppc_has_cap_epr(void)
|
||||
return cap_epr;
|
||||
}
|
||||
|
||||
bool kvmppc_has_cap_htab_fd(void)
|
||||
{
|
||||
return cap_htab_fd;
|
||||
}
|
||||
|
||||
bool kvmppc_has_cap_fixup_hcalls(void)
|
||||
{
|
||||
return cap_fixup_hcalls;
|
||||
@ -2555,19 +2556,29 @@ int kvmppc_define_rtas_kernel_token(uint32_t token, const char *function)
|
||||
return kvm_vm_ioctl(kvm_state, KVM_PPC_RTAS_DEFINE_TOKEN, &args);
|
||||
}
|
||||
|
||||
int kvmppc_get_htab_fd(bool write)
|
||||
int kvmppc_get_htab_fd(bool write, uint64_t index, Error **errp)
|
||||
{
|
||||
struct kvm_get_htab_fd s = {
|
||||
.flags = write ? KVM_GET_HTAB_WRITE : 0,
|
||||
.start_index = 0,
|
||||
.start_index = index,
|
||||
};
|
||||
int ret;
|
||||
|
||||
if (!cap_htab_fd) {
|
||||
fprintf(stderr, "KVM version doesn't support saving the hash table\n");
|
||||
return -1;
|
||||
error_setg(errp, "KVM version doesn't support %s the HPT",
|
||||
write ? "writing" : "reading");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return kvm_vm_ioctl(kvm_state, KVM_PPC_GET_HTAB_FD, &s);
|
||||
ret = kvm_vm_ioctl(kvm_state, KVM_PPC_GET_HTAB_FD, &s);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Unable to open fd for %s HPT %s KVM: %s",
|
||||
write ? "writing" : "reading", write ? "to" : "from",
|
||||
strerror(errno));
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int kvmppc_save_htab(QEMUFile *f, int fd, size_t bufsize, int64_t max_ns)
|
||||
@ -2647,17 +2658,10 @@ void kvm_arch_init_irq_routing(KVMState *s)
|
||||
|
||||
void kvmppc_read_hptes(ppc_hash_pte64_t *hptes, hwaddr ptex, int n)
|
||||
{
|
||||
struct kvm_get_htab_fd ghf = {
|
||||
.flags = 0,
|
||||
.start_index = ptex,
|
||||
};
|
||||
int fd, rc;
|
||||
int i;
|
||||
|
||||
fd = kvm_vm_ioctl(kvm_state, KVM_PPC_GET_HTAB_FD, &ghf);
|
||||
if (fd < 0) {
|
||||
hw_error("kvmppc_read_hptes: Unable to open HPT fd");
|
||||
}
|
||||
fd = kvmppc_get_htab_fd(false, ptex, &error_abort);
|
||||
|
||||
i = 0;
|
||||
while (i < n) {
|
||||
@ -2699,19 +2703,13 @@ void kvmppc_read_hptes(ppc_hash_pte64_t *hptes, hwaddr ptex, int n)
|
||||
void kvmppc_write_hpte(hwaddr ptex, uint64_t pte0, uint64_t pte1)
|
||||
{
|
||||
int fd, rc;
|
||||
struct kvm_get_htab_fd ghf;
|
||||
struct {
|
||||
struct kvm_get_htab_header hdr;
|
||||
uint64_t pte0;
|
||||
uint64_t pte1;
|
||||
} buf;
|
||||
|
||||
ghf.flags = 0;
|
||||
ghf.start_index = 0; /* Ignored */
|
||||
fd = kvm_vm_ioctl(kvm_state, KVM_PPC_GET_HTAB_FD, &ghf);
|
||||
if (fd < 0) {
|
||||
hw_error("kvmppc_write_hpte: Unable to open HPT fd");
|
||||
}
|
||||
fd = kvmppc_get_htab_fd(true, 0 /* Ignored */, &error_abort);
|
||||
|
||||
buf.hdr.n_valid = 1;
|
||||
buf.hdr.n_invalid = 0;
|
||||
@ -2806,30 +2804,6 @@ int kvmppc_resize_hpt_commit(PowerPCCPU *cpu, target_ulong flags, int shift)
|
||||
return kvm_vm_ioctl(cs->kvm_state, KVM_PPC_RESIZE_HPT_COMMIT, &rhpt);
|
||||
}
|
||||
|
||||
static void kvmppc_pivot_hpt_cpu(CPUState *cs, run_on_cpu_data arg)
|
||||
{
|
||||
target_ulong sdr1 = arg.target_ptr;
|
||||
PowerPCCPU *cpu = POWERPC_CPU(cs);
|
||||
CPUPPCState *env = &cpu->env;
|
||||
|
||||
/* This is just for the benefit of PR KVM */
|
||||
cpu_synchronize_state(cs);
|
||||
env->spr[SPR_SDR1] = sdr1;
|
||||
if (kvmppc_put_books_sregs(cpu) < 0) {
|
||||
error_report("Unable to update SDR1 in KVM");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void kvmppc_update_sdr1(target_ulong sdr1)
|
||||
{
|
||||
CPUState *cs;
|
||||
|
||||
CPU_FOREACH(cs) {
|
||||
run_on_cpu(cs, kvmppc_pivot_hpt_cpu, RUN_ON_CPU_TARGET_PTR(sdr1));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a helper function to detect a post migration scenario
|
||||
* in which a guest, running as KVM-HV, freezes in cpu_post_load because
|
||||
|
@ -51,8 +51,7 @@ uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift);
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
bool kvmppc_has_cap_epr(void);
|
||||
int kvmppc_define_rtas_kernel_token(uint32_t token, const char *function);
|
||||
bool kvmppc_has_cap_htab_fd(void);
|
||||
int kvmppc_get_htab_fd(bool write);
|
||||
int kvmppc_get_htab_fd(bool write, uint64_t index, Error **errp);
|
||||
int kvmppc_save_htab(QEMUFile *f, int fd, size_t bufsize, int64_t max_ns);
|
||||
int kvmppc_load_htab_chunk(QEMUFile *f, int fd, uint32_t index,
|
||||
uint16_t n_valid, uint16_t n_invalid);
|
||||
@ -68,7 +67,6 @@ PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void);
|
||||
void kvmppc_check_papr_resize_hpt(Error **errp);
|
||||
int kvmppc_resize_hpt_prepare(PowerPCCPU *cpu, target_ulong flags, int shift);
|
||||
int kvmppc_resize_hpt_commit(PowerPCCPU *cpu, target_ulong flags, int shift);
|
||||
void kvmppc_update_sdr1(target_ulong sdr1);
|
||||
bool kvmppc_pvr_workaround_required(PowerPCCPU *cpu);
|
||||
|
||||
bool kvmppc_is_mem_backend_page_size_ok(const char *obj_path);
|
||||
@ -246,12 +244,7 @@ static inline int kvmppc_define_rtas_kernel_token(uint32_t token,
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline bool kvmppc_has_cap_htab_fd(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int kvmppc_get_htab_fd(bool write)
|
||||
static inline int kvmppc_get_htab_fd(bool write, uint64_t index, Error **errp)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
@ -331,11 +324,6 @@ static inline int kvmppc_resize_hpt_commit(PowerPCCPU *cpu,
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline void kvmppc_update_sdr1(target_ulong sdr1)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_KVM
|
||||
|
@ -3833,6 +3833,44 @@ POWERPC_FAMILY(440EP)(ObjectClass *oc, void *data)
|
||||
POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
|
||||
}
|
||||
|
||||
POWERPC_FAMILY(460EX)(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
|
||||
|
||||
dc->desc = "PowerPC 460 EX";
|
||||
pcc->init_proc = init_proc_440EP;
|
||||
pcc->check_pow = check_pow_nocheck;
|
||||
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
|
||||
PPC_FLOAT | PPC_FLOAT_FRES | PPC_FLOAT_FSEL |
|
||||
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
|
||||
PPC_FLOAT_STFIWX |
|
||||
PPC_DCR | PPC_DCRX | PPC_WRTEE | PPC_RFMCI |
|
||||
PPC_CACHE | PPC_CACHE_ICBI |
|
||||
PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
|
||||
PPC_MEM_TLBSYNC | PPC_MFTB |
|
||||
PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |
|
||||
PPC_440_SPEC;
|
||||
pcc->msr_mask = (1ull << MSR_POW) |
|
||||
(1ull << MSR_CE) |
|
||||
(1ull << MSR_EE) |
|
||||
(1ull << MSR_PR) |
|
||||
(1ull << MSR_FP) |
|
||||
(1ull << MSR_ME) |
|
||||
(1ull << MSR_FE0) |
|
||||
(1ull << MSR_DWE) |
|
||||
(1ull << MSR_DE) |
|
||||
(1ull << MSR_FE1) |
|
||||
(1ull << MSR_IR) |
|
||||
(1ull << MSR_DR);
|
||||
pcc->mmu_model = POWERPC_MMU_BOOKE;
|
||||
pcc->excp_model = POWERPC_EXCP_BOOKE;
|
||||
pcc->bus_model = PPC_FLAGS_INPUT_BookE;
|
||||
pcc->bfd_mach = bfd_mach_ppc_403;
|
||||
pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_DWE |
|
||||
POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
|
||||
}
|
||||
|
||||
static void init_proc_440GP(CPUPPCState *env)
|
||||
{
|
||||
/* Time base */
|
||||
|
Loading…
Reference in New Issue
Block a user