aboutsummaryrefslogtreecommitdiff
path: root/hw/sparc64
diff options
context:
space:
mode:
Diffstat (limited to 'hw/sparc64')
-rw-r--r--hw/sparc64/sparc64.c85
-rw-r--r--hw/sparc64/sun4u.c109
-rw-r--r--hw/sparc64/trace-events18
3 files changed, 138 insertions, 74 deletions
diff --git a/hw/sparc64/sparc64.c b/hw/sparc64/sparc64.c
index 95a06f00b2..408388945e 100644
--- a/hw/sparc64/sparc64.c
+++ b/hw/sparc64/sparc64.c
@@ -28,25 +28,9 @@
#include "hw/char/serial.h"
#include "hw/sparc/sparc64.h"
#include "qemu/timer.h"
+#include "trace.h"
-//#define DEBUG_IRQ
-//#define DEBUG_TIMER
-
-#ifdef DEBUG_IRQ
-#define CPUIRQ_DPRINTF(fmt, ...) \
- do { printf("CPUIRQ: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define CPUIRQ_DPRINTF(fmt, ...)
-#endif
-
-#ifdef DEBUG_TIMER
-#define TIMER_DPRINTF(fmt, ...) \
- do { printf("TIMER: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define TIMER_DPRINTF(fmt, ...)
-#endif
-
#define TICK_MAX 0x7fffffffffffffffULL
void cpu_check_irqs(CPUSPARCState *env)
@@ -73,8 +57,7 @@ void cpu_check_irqs(CPUSPARCState *env)
is (2 << psrpil). */
if (pil < (2 << env->psrpil)) {
if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
- CPUIRQ_DPRINTF("Reset CPU IRQ (current interrupt %x)\n",
- env->interrupt_index);
+ trace_sparc64_cpu_check_irqs_reset_irq(env->interrupt_index);
env->interrupt_index = 0;
cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
}
@@ -92,22 +75,21 @@ void cpu_check_irqs(CPUSPARCState *env)
if (unlikely(env->tl > 0 && cpu_tsptr(env)->tt > new_interrupt
&& ((cpu_tsptr(env)->tt & 0x1f0) == TT_EXTINT))) {
- CPUIRQ_DPRINTF("Not setting CPU IRQ: TL=%d "
- "current %x >= pending %x\n",
- env->tl, cpu_tsptr(env)->tt, new_interrupt);
+ trace_sparc64_cpu_check_irqs_noset_irq(env->tl,
+ cpu_tsptr(env)->tt,
+ new_interrupt);
} else if (old_interrupt != new_interrupt) {
env->interrupt_index = new_interrupt;
- CPUIRQ_DPRINTF("Set CPU IRQ %d old=%x new=%x\n", i,
- old_interrupt, new_interrupt);
+ trace_sparc64_cpu_check_irqs_set_irq(i, old_interrupt,
+ new_interrupt);
cpu_interrupt(cs, CPU_INTERRUPT_HARD);
}
break;
}
}
} else if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
- CPUIRQ_DPRINTF("Interrupts disabled, pil=%08x pil_in=%08x softint=%08x "
- "current interrupt %x\n",
- pil, env->pil_in, env->softint, env->interrupt_index);
+ trace_sparc64_cpu_check_irqs_disabled(pil, env->pil_in, env->softint,
+ env->interrupt_index);
env->interrupt_index = 0;
cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
}
@@ -131,7 +113,7 @@ void sparc64_cpu_set_ivec_irq(void *opaque, int irq, int level)
if (level) {
if (!(env->ivec_status & 0x20)) {
- CPUIRQ_DPRINTF("Raise IVEC IRQ %d\n", irq);
+ trace_sparc64_cpu_ivec_raise_irq(irq);
cs = CPU(cpu);
cs->halted = 0;
env->interrupt_index = TT_IVEC;
@@ -143,7 +125,7 @@ void sparc64_cpu_set_ivec_irq(void *opaque, int irq, int level)
}
} else {
if (env->ivec_status & 0x20) {
- CPUIRQ_DPRINTF("Lower IVEC IRQ %d\n", irq);
+ trace_sparc64_cpu_ivec_lower_irq(irq);
cs = CPU(cpu);
env->ivec_status &= ~0x20;
cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
@@ -216,10 +198,10 @@ static void tick_irq(void *opaque)
CPUTimer *timer = env->tick;
if (timer->disabled) {
- CPUIRQ_DPRINTF("tick_irq: softint disabled\n");
+ trace_sparc64_cpu_tick_irq_disabled();
return;
} else {
- CPUIRQ_DPRINTF("tick: fire\n");
+ trace_sparc64_cpu_tick_irq_fire();
}
env->softint |= SOFTINT_TIMER;
@@ -234,10 +216,10 @@ static void stick_irq(void *opaque)
CPUTimer *timer = env->stick;
if (timer->disabled) {
- CPUIRQ_DPRINTF("stick_irq: softint disabled\n");
+ trace_sparc64_cpu_stick_irq_disabled();
return;
} else {
- CPUIRQ_DPRINTF("stick: fire\n");
+ trace_sparc64_cpu_stick_irq_fire();
}
env->softint |= SOFTINT_STIMER;
@@ -252,10 +234,10 @@ static void hstick_irq(void *opaque)
CPUTimer *timer = env->hstick;
if (timer->disabled) {
- CPUIRQ_DPRINTF("hstick_irq: softint disabled\n");
+ trace_sparc64_cpu_hstick_irq_disabled();
return;
} else {
- CPUIRQ_DPRINTF("hstick: fire\n");
+ trace_sparc64_cpu_hstick_irq_fire();
}
env->softint |= SOFTINT_STIMER;
@@ -280,9 +262,9 @@ void cpu_tick_set_count(CPUTimer *timer, uint64_t count)
int64_t vm_clock_offset = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) -
cpu_to_timer_ticks(real_count, timer->frequency);
- TIMER_DPRINTF("%s set_count count=0x%016lx (npt %s) p=%p\n",
- timer->name, real_count,
- timer->npt ? "disabled" : "enabled", timer);
+ trace_sparc64_cpu_tick_set_count(timer->name, real_count,
+ timer->npt ? "disabled" : "enabled",
+ timer);
timer->npt = npt_bit ? 1 : 0;
timer->clock_offset = vm_clock_offset;
@@ -294,9 +276,9 @@ uint64_t cpu_tick_get_count(CPUTimer *timer)
qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - timer->clock_offset,
timer->frequency);
- TIMER_DPRINTF("%s get_count count=0x%016lx (npt %s) p=%p\n",
- timer->name, real_count,
- timer->npt ? "disabled" : "enabled", timer);
+ trace_sparc64_cpu_tick_get_count(timer->name, real_count,
+ timer->npt ? "disabled" : "enabled",
+ timer);
if (timer->npt) {
real_count |= timer->npt_mask;
@@ -319,18 +301,19 @@ void cpu_tick_set_limit(CPUTimer *timer, uint64_t limit)
expires = now + 1;
}
- TIMER_DPRINTF("%s set_limit limit=0x%016lx (%s) p=%p "
- "called with limit=0x%016lx at 0x%016lx (delta=0x%016lx)\n",
- timer->name, real_limit,
- timer->disabled ? "disabled" : "enabled",
- timer, limit,
- timer_to_cpu_ticks(now - timer->clock_offset,
- timer->frequency),
- timer_to_cpu_ticks(expires - now, timer->frequency));
+ trace_sparc64_cpu_tick_set_limit(timer->name, real_limit,
+ timer->disabled ? "disabled" : "enabled",
+ timer, limit,
+ timer_to_cpu_ticks(
+ now - timer->clock_offset,
+ timer->frequency
+ ),
+ timer_to_cpu_ticks(
+ expires - now, timer->frequency
+ ));
if (!real_limit) {
- TIMER_DPRINTF("%s set_limit limit=ZERO - not starting timer\n",
- timer->name);
+ trace_sparc64_cpu_tick_set_limit_zero(timer->name);
timer_del(timer->qtimer);
} else if (timer->disabled) {
timer_del(timer->qtimer);
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index ec45ec2801..a23cb26b0d 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -30,7 +30,7 @@
#include "hw/pci/pci_bridge.h"
#include "hw/pci/pci_bus.h"
#include "hw/pci/pci_host.h"
-#include "hw/pci-host/apb.h"
+#include "hw/pci-host/sabre.h"
#include "hw/i386/pc.h"
#include "hw/char/serial.h"
#include "hw/timer/m48t59.h"
@@ -55,9 +55,9 @@
#define CMDLINE_ADDR 0x003ff000
#define PROM_SIZE_MAX (4 * 1024 * 1024)
#define PROM_VADDR 0x000ffd00000ULL
-#define APB_SPECIAL_BASE 0x1fe00000000ULL
-#define APB_MEM_BASE 0x1ff00000000ULL
-#define APB_PCI_IO_BASE (APB_SPECIAL_BASE + 0x02000000ULL)
+#define PBM_SPECIAL_BASE 0x1fe00000000ULL
+#define PBM_MEM_BASE 0x1ff00000000ULL
+#define PBM_PCI_IO_BASE (PBM_SPECIAL_BASE + 0x02000000ULL)
#define PROM_FILENAME "openbios-sparc64"
#define NVRAM_SIZE 0x2000
#define MAX_IDE_BUS 2
@@ -205,6 +205,59 @@ typedef struct ResetData {
uint64_t prom_addr;
} ResetData;
+#define TYPE_SUN4U_POWER "power"
+#define SUN4U_POWER(obj) OBJECT_CHECK(PowerDevice, (obj), TYPE_SUN4U_POWER)
+
+typedef struct PowerDevice {
+ SysBusDevice parent_obj;
+
+ MemoryRegion power_mmio;
+} PowerDevice;
+
+/* Power */
+static void power_mem_write(void *opaque, hwaddr addr,
+ uint64_t val, unsigned size)
+{
+ /* According to a real Ultra 5, bit 24 controls the power */
+ if (val & 0x1000000) {
+ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
+ }
+}
+
+static const MemoryRegionOps power_mem_ops = {
+ .write = power_mem_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+};
+
+static void power_realize(DeviceState *dev, Error **errp)
+{
+ PowerDevice *d = SUN4U_POWER(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+ memory_region_init_io(&d->power_mmio, OBJECT(dev), &power_mem_ops, d,
+ "power", sizeof(uint32_t));
+
+ sysbus_init_mmio(sbd, &d->power_mmio);
+}
+
+static void power_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->realize = power_realize;
+}
+
+static const TypeInfo power_info = {
+ .name = TYPE_SUN4U_POWER,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(PowerDevice),
+ .class_init = power_class_init,
+};
+
static void ebus_isa_irq_handler(void *opaque, int n, int level)
{
EbusState *s = EBUS(opaque);
@@ -221,6 +274,7 @@ static void ebus_isa_irq_handler(void *opaque, int n, int level)
static void ebus_realize(PCIDevice *pci_dev, Error **errp)
{
EbusState *s = EBUS(pci_dev);
+ SysBusDevice *sbd;
DeviceState *dev;
qemu_irq *isa_irq;
DriveInfo *fd[MAX_FD];
@@ -270,6 +324,13 @@ static void ebus_realize(PCIDevice *pci_dev, Error **errp)
qdev_prop_set_uint32(dev, "dma", -1);
qdev_init_nofail(dev);
+ /* Power */
+ dev = qdev_create(NULL, TYPE_SUN4U_POWER);
+ qdev_init_nofail(dev);
+ sbd = SYS_BUS_DEVICE(dev);
+ memory_region_add_subregion(pci_address_space_io(pci_dev), 0x7240,
+ sysbus_mmio_get_region(sbd, 0));
+
/* PCI */
pci_dev->config[0x04] = 0x06; // command = bus master, pci mem
pci_dev->config[0x05] = 0x00;
@@ -282,7 +343,7 @@ static void ebus_realize(PCIDevice *pci_dev, Error **errp)
0, 0x1000000);
pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar0);
memory_region_init_alias(&s->bar1, OBJECT(s), "bar1", get_system_io(),
- 0, 0x4000);
+ 0, 0x8000);
pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->bar1);
}
@@ -465,7 +526,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
Nvram *nvram;
unsigned int i;
uint64_t initrd_addr, initrd_size, kernel_addr, kernel_size, kernel_entry;
- APBState *apb;
+ SabreState *sabre;
PCIBus *pci_bus, *pci_busA, *pci_busB;
PCIDevice *ebus, *pci_dev;
SysBusDevice *s;
@@ -488,24 +549,25 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
prom_init(hwdef->prom_addr, bios_name);
- /* Init APB (PCI host bridge) */
- apb = APB_DEVICE(qdev_create(NULL, TYPE_APB));
- qdev_prop_set_uint64(DEVICE(apb), "special-base", APB_SPECIAL_BASE);
- qdev_prop_set_uint64(DEVICE(apb), "mem-base", APB_MEM_BASE);
- object_property_set_link(OBJECT(apb), OBJECT(iommu), "iommu", &error_abort);
- qdev_init_nofail(DEVICE(apb));
+ /* Init sabre (PCI host bridge) */
+ sabre = SABRE_DEVICE(qdev_create(NULL, TYPE_SABRE));
+ qdev_prop_set_uint64(DEVICE(sabre), "special-base", PBM_SPECIAL_BASE);
+ qdev_prop_set_uint64(DEVICE(sabre), "mem-base", PBM_MEM_BASE);
+ object_property_set_link(OBJECT(sabre), OBJECT(iommu), "iommu",
+ &error_abort);
+ qdev_init_nofail(DEVICE(sabre));
/* Wire up PCI interrupts to CPU */
for (i = 0; i < IVEC_MAX; i++) {
- qdev_connect_gpio_out_named(DEVICE(apb), "ivec-irq", i,
+ qdev_connect_gpio_out_named(DEVICE(sabre), "ivec-irq", i,
qdev_get_gpio_in_named(DEVICE(cpu), "ivec-irq", i));
}
- pci_bus = PCI_HOST_BRIDGE(apb)->bus;
- pci_busA = pci_bridge_get_sec_bus(apb->bridgeA);
- pci_busB = pci_bridge_get_sec_bus(apb->bridgeB);
+ pci_bus = PCI_HOST_BRIDGE(sabre)->bus;
+ pci_busA = pci_bridge_get_sec_bus(sabre->bridgeA);
+ pci_busB = pci_bridge_get_sec_bus(sabre->bridgeB);
- /* Only in-built Simba PBMs can exist on the root bus, slot 0 on busA is
+ /* Only in-built Simba APBs can exist on the root bus, slot 0 on busA is
reserved (leaving no slots free after on-board devices) however slots
0-3 are free on busB */
pci_bus->slot_reserved_mask = 0xfffffffc;
@@ -517,17 +579,17 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
hwdef->console_serial_base);
qdev_init_nofail(DEVICE(ebus));
- /* Wire up "well-known" ISA IRQs to APB legacy obio IRQs */
+ /* Wire up "well-known" ISA IRQs to PBM legacy obio IRQs */
qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 7,
- qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_LPT_IRQ));
+ qdev_get_gpio_in_named(DEVICE(sabre), "pbm-irq", OBIO_LPT_IRQ));
qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 6,
- qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_FDD_IRQ));
+ qdev_get_gpio_in_named(DEVICE(sabre), "pbm-irq", OBIO_FDD_IRQ));
qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 1,
- qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_KBD_IRQ));
+ qdev_get_gpio_in_named(DEVICE(sabre), "pbm-irq", OBIO_KBD_IRQ));
qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 12,
- qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_MSE_IRQ));
+ qdev_get_gpio_in_named(DEVICE(sabre), "pbm-irq", OBIO_MSE_IRQ));
qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 4,
- qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_SER_IRQ));
+ qdev_get_gpio_in_named(DEVICE(sabre), "pbm-irq", OBIO_SER_IRQ));
pci_dev = pci_create_simple(pci_busA, PCI_DEVFN(2, 0), "VGA");
@@ -693,6 +755,7 @@ static const TypeInfo sun4v_type = {
static void sun4u_register_types(void)
{
+ type_register_static(&power_info);
type_register_static(&ebus_info);
type_register_static(&prom_info);
type_register_static(&ram_info);
diff --git a/hw/sparc64/trace-events b/hw/sparc64/trace-events
index 2ee2d75f70..ce597a6e9d 100644
--- a/hw/sparc64/trace-events
+++ b/hw/sparc64/trace-events
@@ -7,3 +7,21 @@ ebus_isa_irq_handler(int n, int level) "Set ISA IRQ %d level %d"
sun4u_iommu_mem_read(uint64_t addr, uint64_t val, int size) "addr: 0x%"PRIx64" val: 0x%"PRIx64" size: %d"
sun4u_iommu_mem_write(uint64_t addr, uint64_t val, int size) "addr: 0x%"PRIx64" val: 0x%"PRIx64" size: %d"
sun4u_iommu_translate(uint64_t addr, uint64_t trans_addr, uint64_t tte) "xlate 0x%"PRIx64" => pa 0x%"PRIx64" tte: 0x%"PRIx64
+
+# hw/sparc64/sparc64.c
+sparc64_cpu_check_irqs_reset_irq(int intno) "Reset CPU IRQ (current interrupt 0x%x)"
+sparc64_cpu_check_irqs_noset_irq(uint32_t tl, uint32_t tt, int intno) "Not setting CPU IRQ: TL=%d current 0x%x >= pending 0x%x"
+sparc64_cpu_check_irqs_set_irq(unsigned int i, int old, int new) "Set CPU IRQ %d old=0x%x new=0x%x"
+sparc64_cpu_check_irqs_disabled(uint32_t pil, uint32_t pil_in, uint32_t softint, int intno) "Interrupts disabled, pil=0x%08x pil_in=0x%08x softint=0x%08x current interrupt 0x%x"
+sparc64_cpu_ivec_raise_irq(int irq) "Raise IVEC IRQ %d"
+sparc64_cpu_ivec_lower_irq(int irq) "Lower IVEC IRQ %d"
+sparc64_cpu_tick_irq_disabled(void) "tick_irq: softint disabled"
+sparc64_cpu_tick_irq_fire(void) "tick_irq: fire"
+sparc64_cpu_stick_irq_disabled(void) "stick_irq: softint disabled"
+sparc64_cpu_stick_irq_fire(void) "stick_irq: fire"
+sparc64_cpu_hstick_irq_disabled(void) "hstick_irq: softint disabled"
+sparc64_cpu_hstick_irq_fire(void) "hstick_irq: fire"
+sparc64_cpu_tick_set_count(const char *name, uint64_t real_count, const char *npt, void *p) "%s set_count count=0x%"PRIx64" (npt %s) p=%p"
+sparc64_cpu_tick_get_count(const char *name, uint64_t real_count, const char *npt, void *p) "%s get_count count=0x%"PRIx64" (npt %s) p=%p"
+sparc64_cpu_tick_set_limit(const char *name, uint64_t real_limit, const char *dis, void *p, uint64_t limit, uint64_t t, uint64_t dt) "%s set_limit limit=0x%"PRIx64 " (%s) p=%p called with limit=0x%"PRIx64" at 0x%"PRIx64" (delta=0x%"PRIx64")"
+sparc64_cpu_tick_set_limit_zero(const char *name) "%s set_limit limit=ZERO - not starting timer"