Merge remote-tracking branch 'rth/axp-next' into staging

# By Richard Henderson
# Via Richard Henderson
* rth/axp-next:
  hw/alpha: Use SRM epoch
  hw/alpha: Drop latch_tmp hack
  exec: Support 64-bit operations in address_space_rw
  hw/alpha: Don't machine check on missing pci i/o
  hw/alpha: Don't use get_system_io

Message-id: 1373840171-25556-1-git-send-email-rth@twiddle.net
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
Anthony Liguori 2013-07-15 14:00:57 -05:00
commit a34001fab5
5 changed files with 93 additions and 97 deletions

68
exec.c
View file

@ -1896,15 +1896,37 @@ static inline bool memory_access_is_direct(MemoryRegion *mr, bool is_write)
return false;
}
static inline int memory_access_size(MemoryRegion *mr, int l, hwaddr addr)
static int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr)
{
if (l >= 4 && (((addr & 3) == 0 || mr->ops->impl.unaligned))) {
return 4;
unsigned access_size_min = mr->ops->impl.min_access_size;
unsigned access_size_max = mr->ops->impl.max_access_size;
/* Regions are assumed to support 1-4 byte accesses unless
otherwise specified. */
if (access_size_min == 0) {
access_size_min = 1;
}
if (l >= 2 && (((addr & 1) == 0) || mr->ops->impl.unaligned)) {
return 2;
if (access_size_max == 0) {
access_size_max = 4;
}
return 1;
/* Bound the maximum access by the alignment of the address. */
if (!mr->ops->impl.unaligned) {
unsigned align_size_max = addr & -addr;
if (align_size_max != 0 && align_size_max < access_size_max) {
access_size_max = align_size_max;
}
}
/* Don't attempt accesses larger than the maximum. */
if (l > access_size_max) {
l = access_size_max;
}
/* ??? The users of this function are wrong, not supporting minimums larger
than the remaining length. C.f. memory.c:access_with_adjusted_size. */
assert(l >= access_size_min);
return l;
}
bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
@ -1926,18 +1948,29 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
l = memory_access_size(mr, l, addr1);
/* XXX: could force current_cpu to NULL to avoid
potential bugs */
if (l == 4) {
switch (l) {
case 8:
/* 64 bit write access */
val = ldq_p(buf);
error |= io_mem_write(mr, addr1, val, 8);
break;
case 4:
/* 32 bit write access */
val = ldl_p(buf);
error |= io_mem_write(mr, addr1, val, 4);
} else if (l == 2) {
break;
case 2:
/* 16 bit write access */
val = lduw_p(buf);
error |= io_mem_write(mr, addr1, val, 2);
} else {
break;
case 1:
/* 8 bit write access */
val = ldub_p(buf);
error |= io_mem_write(mr, addr1, val, 1);
break;
default:
abort();
}
} else {
addr1 += memory_region_get_ram_addr(mr);
@ -1950,18 +1983,29 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
if (!memory_access_is_direct(mr, is_write)) {
/* I/O case */
l = memory_access_size(mr, l, addr1);
if (l == 4) {
switch (l) {
case 8:
/* 64 bit read access */
error |= io_mem_read(mr, addr1, &val, 8);
stq_p(buf, val);
break;
case 4:
/* 32 bit read access */
error |= io_mem_read(mr, addr1, &val, 4);
stl_p(buf, val);
} else if (l == 2) {
break;
case 2:
/* 16 bit read access */
error |= io_mem_read(mr, addr1, &val, 2);
stw_p(buf, val);
} else {
break;
case 1:
/* 8 bit read access */
error |= io_mem_read(mr, addr1, &val, 1);
stb_p(buf, val);
break;
default:
abort();
}
} else {
/* RAM case */

View file

@ -14,7 +14,7 @@ PCIBus *typhoon_init(ram_addr_t, ISABus **, qemu_irq *, AlphaCPU *[4],
pci_map_irq_fn);
/* alpha_pci.c. */
extern const MemoryRegionOps alpha_pci_bw_io_ops;
extern const MemoryRegionOps alpha_pci_ignore_ops;
extern const MemoryRegionOps alpha_pci_conf1_ops;
extern const MemoryRegionOps alpha_pci_iack_ops;

View file

@ -73,7 +73,9 @@ static void clipper_init(QEMUMachineInitArgs *args)
pci_bus = typhoon_init(ram_size, &isa_bus, &rtc_irq, cpus,
clipper_pci_map_irq);
rtc_init(isa_bus, 1980, rtc_irq);
/* Since we have an SRM-compatible PALcode, use the SRM epoch. */
rtc_init(isa_bus, 1900, rtc_irq);
pit_init(isa_bus, 0x40, 0, NULL);
isa_create_simple(isa_bus, "i8042");

View file

@ -12,50 +12,32 @@
#include "sysemu/sysemu.h"
/* PCI IO reads/writes, to byte-word addressable memory. */
/* ??? Doesn't handle multiple PCI busses. */
/* Fallback for unassigned PCI I/O operations. Avoids MCHK. */
static uint64_t bw_io_read(void *opaque, hwaddr addr, unsigned size)
static uint64_t ignore_read(void *opaque, hwaddr addr, unsigned size)
{
switch (size) {
case 1:
return cpu_inb(addr);
case 2:
return cpu_inw(addr);
case 4:
return cpu_inl(addr);
}
abort();
return 0;
}
static void bw_io_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
static void ignore_write(void *opaque, hwaddr addr, uint64_t v, unsigned size)
{
switch (size) {
case 1:
cpu_outb(addr, val);
break;
case 2:
cpu_outw(addr, val);
break;
case 4:
cpu_outl(addr, val);
break;
default:
abort();
}
}
const MemoryRegionOps alpha_pci_bw_io_ops = {
.read = bw_io_read,
.write = bw_io_write,
const MemoryRegionOps alpha_pci_ignore_ops = {
.read = ignore_read,
.write = ignore_write,
.endianness = DEVICE_LITTLE_ENDIAN,
.valid = {
.min_access_size = 1,
.max_access_size = 8,
},
.impl = {
.min_access_size = 1,
.max_access_size = 4,
.max_access_size = 8,
},
};
/* PCI config space reads/writes, to byte-word addressable memory. */
static uint64_t bw_conf1_read(void *opaque, hwaddr addr,
unsigned size)

View file

@ -51,9 +51,6 @@ typedef struct TyphoonState {
TyphoonPchip pchip;
MemoryRegion dchip_region;
MemoryRegion ram_region;
/* QEMU emulation state. */
uint32_t latch_tmp;
} TyphoonState;
/* Called when one of DRIR or DIM changes. */
@ -76,10 +73,6 @@ static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size)
TyphoonState *s = opaque;
uint64_t ret = 0;
if (addr & 4) {
return s->latch_tmp;
}
switch (addr) {
case 0x0000:
/* CSC: Cchip System Configuration Register. */
@ -199,7 +192,6 @@ static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size)
return -1;
}
s->latch_tmp = ret >> 32;
return ret;
}
@ -214,10 +206,6 @@ static uint64_t pchip_read(void *opaque, hwaddr addr, unsigned size)
TyphoonState *s = opaque;
uint64_t ret = 0;
if (addr & 4) {
return s->latch_tmp;
}
switch (addr) {
case 0x0000:
/* WSBA0: Window Space Base Address Register. */
@ -302,23 +290,14 @@ static uint64_t pchip_read(void *opaque, hwaddr addr, unsigned size)
return -1;
}
s->latch_tmp = ret >> 32;
return ret;
}
static void cchip_write(void *opaque, hwaddr addr,
uint64_t v32, unsigned size)
uint64_t val, unsigned size)
{
TyphoonState *s = opaque;
uint64_t val, oldval, newval;
if (addr & 4) {
val = v32 << 32 | s->latch_tmp;
addr ^= 4;
} else {
s->latch_tmp = v32;
return;
}
uint64_t oldval, newval;
switch (addr) {
case 0x0000:
@ -471,18 +450,10 @@ static void dchip_write(void *opaque, hwaddr addr,
}
static void pchip_write(void *opaque, hwaddr addr,
uint64_t v32, unsigned size)
uint64_t val, unsigned size)
{
TyphoonState *s = opaque;
uint64_t val, oldval;
if (addr & 4) {
val = v32 << 32 | s->latch_tmp;
addr ^= 4;
} else {
s->latch_tmp = v32;
return;
}
uint64_t oldval;
switch (addr) {
case 0x0000:
@ -585,12 +556,12 @@ static const MemoryRegionOps cchip_ops = {
.write = cchip_write,
.endianness = DEVICE_LITTLE_ENDIAN,
.valid = {
.min_access_size = 4, /* ??? Should be 8. */
.min_access_size = 8,
.max_access_size = 8,
},
.impl = {
.min_access_size = 4,
.max_access_size = 4,
.min_access_size = 8,
.max_access_size = 8,
},
};
@ -599,11 +570,11 @@ static const MemoryRegionOps dchip_ops = {
.write = dchip_write,
.endianness = DEVICE_LITTLE_ENDIAN,
.valid = {
.min_access_size = 4, /* ??? Should be 8. */
.min_access_size = 8,
.max_access_size = 8,
},
.impl = {
.min_access_size = 4,
.min_access_size = 8,
.max_access_size = 8,
},
};
@ -613,12 +584,12 @@ static const MemoryRegionOps pchip_ops = {
.write = pchip_write,
.endianness = DEVICE_LITTLE_ENDIAN,
.valid = {
.min_access_size = 4, /* ??? Should be 8. */
.min_access_size = 8,
.max_access_size = 8,
},
.impl = {
.min_access_size = 4,
.max_access_size = 4,
.min_access_size = 8,
.max_access_size = 8,
},
};
@ -705,7 +676,6 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
const uint64_t MB = 1024 * 1024;
const uint64_t GB = 1024 * MB;
MemoryRegion *addr_space = get_system_memory();
MemoryRegion *addr_space_io = get_system_io();
DeviceState *dev;
TyphoonState *s;
PCIHostState *phb;
@ -765,28 +735,26 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
&s->pchip.reg_mem);
/* Pchip0 PCI I/O, 0x801.FC00.0000, 32MB. */
/* ??? Ideally we drop the "system" i/o space on the floor and give the
PCI subsystem the full address space reserved by the chipset.
We can't do that until the MEM and IO paths in memory.c are unified. */
memory_region_init_io(&s->pchip.reg_io, OBJECT(s), &alpha_pci_bw_io_ops,
memory_region_init_io(&s->pchip.reg_io, OBJECT(s), &alpha_pci_ignore_ops,
NULL, "pci0-io", 32*MB);
memory_region_add_subregion(addr_space, 0x801fc000000ULL,
&s->pchip.reg_io);
b = pci_register_bus(dev, "pci",
typhoon_set_irq, sys_map_irq, s,
&s->pchip.reg_mem, addr_space_io, 0, 64, TYPE_PCI_BUS);
&s->pchip.reg_mem, &s->pchip.reg_io,
0, 64, TYPE_PCI_BUS);
phb->bus = b;
/* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB. */
memory_region_init_io(&s->pchip.reg_iack, OBJECT(s), &alpha_pci_iack_ops, b,
"pci0-iack", 64*MB);
memory_region_init_io(&s->pchip.reg_iack, OBJECT(s), &alpha_pci_iack_ops,
b, "pci0-iack", 64*MB);
memory_region_add_subregion(addr_space, 0x801f8000000ULL,
&s->pchip.reg_iack);
/* Pchip0 PCI configuration, 0x801.FE00.0000, 16MB. */
memory_region_init_io(&s->pchip.reg_conf, OBJECT(s), &alpha_pci_conf1_ops, b,
"pci0-conf", 16*MB);
memory_region_init_io(&s->pchip.reg_conf, OBJECT(s), &alpha_pci_conf1_ops,
b, "pci0-conf", 16*MB);
memory_region_add_subregion(addr_space, 0x801fe000000ULL,
&s->pchip.reg_conf);
@ -804,7 +772,7 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
{
qemu_irq isa_pci_irq, *isa_irqs;
*isa_bus = isa_bus_new(NULL, addr_space_io);
*isa_bus = isa_bus_new(NULL, &s->pchip.reg_io);
isa_pci_irq = *qemu_allocate_irqs(typhoon_set_isa_irq, s, 1);
isa_irqs = i8259_init(*isa_bus, isa_pci_irq);
isa_bus_irqs(*isa_bus, isa_irqs);