diff options
Diffstat (limited to 'hw/ppc')
-rw-r--r-- | hw/ppc/Makefile.objs | 2 | ||||
-rw-r--r-- | hw/ppc/e500.c | 34 | ||||
-rw-r--r-- | hw/ppc/mac.h | 3 | ||||
-rw-r--r-- | hw/ppc/mac_newworld.c | 15 | ||||
-rw-r--r-- | hw/ppc/mac_oldworld.c | 28 | ||||
-rw-r--r-- | hw/ppc/mpc8544_guts.c | 5 | ||||
-rw-r--r-- | hw/ppc/ppc.c | 12 | ||||
-rw-r--r-- | hw/ppc/ppc405_boards.c | 18 | ||||
-rw-r--r-- | hw/ppc/ppc405_uc.c | 12 | ||||
-rw-r--r-- | hw/ppc/ppc4xx_devs.c | 4 | ||||
-rw-r--r-- | hw/ppc/ppc4xx_pci.c | 8 | ||||
-rw-r--r-- | hw/ppc/ppce500_spin.c | 4 | ||||
-rw-r--r-- | hw/ppc/prep.c | 43 | ||||
-rw-r--r-- | hw/ppc/spapr.c | 62 | ||||
-rw-r--r-- | hw/ppc/spapr_hcall.c | 10 | ||||
-rw-r--r-- | hw/ppc/spapr_iommu.c | 4 | ||||
-rw-r--r-- | hw/ppc/spapr_pci.c | 19 | ||||
-rw-r--r-- | hw/ppc/spapr_vio.c | 2 | ||||
-rw-r--r-- | hw/ppc/virtex_ml507.c | 2 | ||||
-rw-r--r-- | hw/ppc/xics.c | 587 |
20 files changed, 142 insertions, 732 deletions
diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs index be00d1da3b..7a1cd5d89e 100644 --- a/hw/ppc/Makefile.objs +++ b/hw/ppc/Makefile.objs @@ -1,7 +1,7 @@ # shared objects obj-y += ppc.o ppc_booke.o # IBM pSeries (sPAPR) -obj-$(CONFIG_PSERIES) += spapr.o xics.o spapr_vio.o spapr_events.o +obj-$(CONFIG_PSERIES) += spapr.o spapr_vio.o spapr_events.o obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o obj-$(CONFIG_PSERIES) += spapr_pci.o # PowerPC 4xx boards diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 75b05a21fc..f00a62a1ca 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -137,7 +137,6 @@ static int ppce500_load_device_tree(CPUPPCState *env, uint32_t clock_freq = 400000000; uint32_t tb_freq = 400000000; int i; - const char *toplevel_compat = NULL; /* user override */ char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus"; char soc[128]; char mpic[128]; @@ -158,14 +157,9 @@ static int ppce500_load_device_tree(CPUPPCState *env, 0x0, 0xe1000000, 0x0, 0x10000, }; - QemuOpts *machine_opts; - const char *dtb_file = NULL; - - machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); - if (machine_opts) { - dtb_file = qemu_opt_get(machine_opts, "dtb"); - toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible"); - } + QemuOpts *machine_opts = qemu_get_machine_opts(); + const char *dtb_file = qemu_opt_get(machine_opts, "dtb"); + const char *toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible"); if (dtb_file) { char *filename; @@ -500,7 +494,6 @@ static DeviceState *ppce500_init_mpic_kvm(PPCE500Params *params, qemu_irq **irqs) { DeviceState *dev; - CPUPPCState *env; CPUState *cs; int r; @@ -512,9 +505,7 @@ static DeviceState *ppce500_init_mpic_kvm(PPCE500Params *params, return NULL; } - for (env = first_cpu; env != NULL; env = env->next_cpu) { - cs = ENV_GET_CPU(env); - + for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) { if (kvm_openpic_connect_vcpu(dev, cs)) { fprintf(stderr, "%s: failed to connect vcpu to irqchip\n", __func__); @@ -528,7 +519,6 @@ static DeviceState *ppce500_init_mpic_kvm(PPCE500Params *params, static qemu_irq *ppce500_init_mpic(PPCE500Params *params, MemoryRegion *ccsr, qemu_irq **irqs) { - QemuOptsList *list; qemu_irq *mpic; DeviceState *dev = NULL; SysBusDevice *s; @@ -537,15 +527,11 @@ static qemu_irq *ppce500_init_mpic(PPCE500Params *params, MemoryRegion *ccsr, mpic = g_new(qemu_irq, 256); if (kvm_enabled()) { - bool irqchip_allowed = true, irqchip_required = false; - - list = qemu_find_opts("machine"); - if (!QTAILQ_EMPTY(&list->head)) { - irqchip_allowed = qemu_opt_get_bool(QTAILQ_FIRST(&list->head), + QemuOpts *machine_opts = qemu_get_machine_opts(); + bool irqchip_allowed = qemu_opt_get_bool(machine_opts, "kernel_irqchip", true); - irqchip_required = qemu_opt_get_bool(QTAILQ_FIRST(&list->head), - "kernel_irqchip", false); - } + bool irqchip_required = qemu_opt_get_bool(machine_opts, + "kernel_irqchip", false); if (irqchip_allowed) { dev = ppce500_init_mpic_kvm(params, irqs); @@ -651,7 +637,7 @@ void ppce500_init(PPCE500Params *params) params->ram_size = ram_size; /* Register Memory */ - memory_region_init_ram(ram, "mpc8544ds.ram", ram_size); + memory_region_init_ram(ram, NULL, "mpc8544ds.ram", ram_size); vmstate_register_ram_global(ram); memory_region_add_subregion(address_space_mem, 0, ram); @@ -783,7 +769,7 @@ static int e500_ccsr_initfn(SysBusDevice *dev) PPCE500CCSRState *ccsr; ccsr = CCSR(dev); - memory_region_init(&ccsr->ccsr_space, "e500-ccsr", + memory_region_init(&ccsr->ccsr_space, OBJECT(ccsr), "e500-ccsr", MPC8544_CCSRBAR_SIZE); return 0; } diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h index 54efaed627..1e578dd59d 100644 --- a/hw/ppc/mac.h +++ b/hw/ppc/mac.h @@ -131,6 +131,9 @@ typedef struct MACIOIDEState { MemoryRegion mem; IDEBus bus; BlockDriverAIOCB *aiocb; + IDEDMA dma; + void *dbdma; + bool dma_active; } MACIOIDEState; void macio_ide_init_drives(MACIOIDEState *ide, DriveInfo **hd_table); diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index 98b902e5af..fe803480a7 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -71,6 +71,7 @@ #define MAX_IDE_BUS 2 #define CFG_ADDR 0xf0000510 +#define TBFREQ (100UL * 1000UL * 1000UL) /* debug UniNorth */ //#define DEBUG_UNIN @@ -191,17 +192,17 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) env = &cpu->env; /* Set time-base frequency to 100 Mhz */ - cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL); + cpu_ppc_tb_init(env, TBFREQ); qemu_register_reset(ppc_core99_reset, cpu); } /* allocate RAM */ - memory_region_init_ram(ram, "ppc_core99.ram", ram_size); + memory_region_init_ram(ram, NULL, "ppc_core99.ram", ram_size); vmstate_register_ram_global(ram); memory_region_add_subregion(get_system_memory(), 0, ram); /* allocate and load BIOS */ - memory_region_init_ram(bios, "ppc_core99.bios", BIOS_SIZE); + memory_region_init_ram(bios, NULL, "ppc_core99.bios", BIOS_SIZE); vmstate_register_ram_global(bios); if (bios_name == NULL) bios_name = PROM_FILENAME; @@ -290,10 +291,10 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) isa_mmio_init(0xf2000000, 0x00800000); /* UniN init: XXX should be a real device */ - memory_region_init_io(unin_memory, &unin_ops, token, "unin", 0x1000); + memory_region_init_io(unin_memory, NULL, &unin_ops, token, "unin", 0x1000); memory_region_add_subregion(get_system_memory(), 0xf8000000, unin_memory); - memory_region_init_io(unin2_memory, &unin_ops, token, "unin", 0x1000); + memory_region_init_io(unin2_memory, NULL, &unin_ops, token, "unin", 0x1000); memory_region_add_subregion(get_system_memory(), 0xf3000000, unin2_memory); openpic_irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *)); @@ -371,7 +372,7 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) escc_mem = escc_init(0, pic[0x25], pic[0x24], serial_hds[0], serial_hds[1], ESCC_CLOCK, 4); - memory_region_init_alias(escc_bar, "escc-bar", + memory_region_init_alias(escc_bar, NULL, "escc-bar", escc_mem, 0, memory_region_size(escc_mem)); for(i = 0; i < nb_nics; i++) @@ -460,7 +461,7 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid()); #endif } else { - fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, get_ticks_per_sec()); + fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, TBFREQ); } /* Mac OS X requires a "known good" clock-frequency value; pass it one. */ fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CLOCKFREQ, 266000000); diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index 1d73a73e94..8b8c6b93a5 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -45,6 +45,7 @@ #define MAX_IDE_BUS 2 #define CFG_ADDR 0xf0000510 +#define TBFREQ 16600000UL static int fw_cfg_boot_set(void *opaque, const char *boot_device) { @@ -114,7 +115,7 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) env = &cpu->env; /* Set time-base frequency to 16.6 Mhz */ - cpu_ppc_tb_init(env, 16600000UL); + cpu_ppc_tb_init(env, TBFREQ); qemu_register_reset(ppc_heathrow_reset, cpu); } @@ -126,12 +127,12 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) exit(1); } - memory_region_init_ram(ram, "ppc_heathrow.ram", ram_size); + memory_region_init_ram(ram, NULL, "ppc_heathrow.ram", ram_size); vmstate_register_ram_global(ram); memory_region_add_subregion(sysmem, 0, ram); /* allocate and load BIOS */ - memory_region_init_ram(bios, "ppc_heathrow.bios", BIOS_SIZE); + memory_region_init_ram(bios, NULL, "ppc_heathrow.bios", BIOS_SIZE); vmstate_register_ram_global(bios); if (bios_name == NULL) bios_name = PROM_FILENAME; @@ -255,7 +256,7 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) escc_mem = escc_init(0, pic[0x0f], pic[0x10], serial_hds[0], serial_hds[1], ESCC_CLOCK, 4); - memory_region_init_alias(escc_bar, "escc-bar", + memory_region_init_alias(escc_bar, NULL, "escc-bar", escc_mem, 0, memory_region_size(escc_mem)); for(i = 0; i < nb_nics; i++) @@ -267,20 +268,19 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) macio = pci_create(pci_bus, -1, TYPE_OLDWORLD_MACIO); dev = DEVICE(macio); qdev_connect_gpio_out(dev, 0, pic[0x12]); /* CUDA */ - qdev_connect_gpio_out(dev, 1, pic[0x0D]); /* IDE */ - qdev_connect_gpio_out(dev, 2, pic[0x02]); /* IDE DMA */ + qdev_connect_gpio_out(dev, 1, pic[0x0D]); /* IDE-0 */ + qdev_connect_gpio_out(dev, 2, pic[0x02]); /* IDE-0 DMA */ + qdev_connect_gpio_out(dev, 3, pic[0x0E]); /* IDE-1 */ + qdev_connect_gpio_out(dev, 4, pic[0x03]); /* IDE-1 DMA */ macio_init(macio, pic_mem, escc_bar); - /* First IDE channel is a MAC IDE on the MacIO bus */ macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), - "ide")); + "ide[0]")); macio_ide_init_drives(macio_ide, hd); - /* Second IDE channel is a CMD646 on the PCI bus */ - hd[0] = hd[MAX_IDE_DEVS]; - hd[1] = hd[MAX_IDE_DEVS + 1]; - hd[3] = hd[2] = NULL; - pci_cmd646_ide_init(pci_bus, hd, 0); + macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), + "ide[1]")); + macio_ide_init_drives(macio_ide, &hd[MAX_IDE_DEVS]); dev = DEVICE(object_resolve_path_component(OBJECT(macio), "cuda")); adb_bus = qdev_get_child_bus(dev, "adb.0"); @@ -331,7 +331,7 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid()); #endif } else { - fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, get_ticks_per_sec()); + fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, TBFREQ); } /* Mac OS X requires a "known good" clock-frequency value; pass it one. */ fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CLOCKFREQ, 266000000); diff --git a/hw/ppc/mpc8544_guts.c b/hw/ppc/mpc8544_guts.c index d41f615522..a10abe9789 100644 --- a/hw/ppc/mpc8544_guts.c +++ b/hw/ppc/mpc8544_guts.c @@ -68,7 +68,8 @@ static uint64_t mpc8544_guts_read(void *opaque, hwaddr addr, unsigned size) { uint32_t value = 0; - CPUPPCState *env = cpu_single_env; + PowerPCCPU *cpu = POWERPC_CPU(current_cpu); + CPUPPCState *env = &cpu->env; addr &= MPC8544_GUTS_MMIO_SIZE - 1; switch (addr) { @@ -119,7 +120,7 @@ static void mpc8544_guts_initfn(Object *obj) SysBusDevice *d = SYS_BUS_DEVICE(obj); GutsState *s = MPC8544_GUTS(obj); - memory_region_init_io(&s->iomem, &mpc8544_guts_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &mpc8544_guts_ops, s, "mpc8544.guts", MPC8544_GUTS_MMIO_SIZE); sysbus_init_mmio(d, &s->iomem); } diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c index fb57b42ea0..e1c095c7e2 100644 --- a/hw/ppc/ppc.c +++ b/hw/ppc/ppc.c @@ -23,6 +23,7 @@ */ #include "hw/hw.h" #include "hw/ppc/ppc.h" +#include "hw/ppc/ppc_e500.h" #include "qemu/timer.h" #include "sysemu/sysemu.h" #include "hw/timer/m48t59.h" @@ -440,15 +441,14 @@ void ppce500_irq_init(CPUPPCState *env) /* Enable or Disable the E500 EPR capability */ void ppce500_set_mpic_proxy(bool enabled) { - CPUPPCState *env; + CPUState *cs; - for (env = first_cpu; env != NULL; env = env->next_cpu) { - PowerPCCPU *cpu = ppc_env_get_cpu(env); - CPUState *cs = CPU(cpu); + for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) { + PowerPCCPU *cpu = POWERPC_CPU(cs); - env->mpic_proxy = enabled; + cpu->env.mpic_proxy = enabled; if (kvm_enabled()) { - kvmppc_set_mpic_proxy(POWERPC_CPU(cs), enabled); + kvmppc_set_mpic_proxy(cpu, enabled); } } } diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c index f0c7ee9abd..f74e5e52c2 100644 --- a/hw/ppc/ppc405_boards.c +++ b/hw/ppc/ppc405_boards.c @@ -164,7 +164,7 @@ static void ref405ep_fpga_init(MemoryRegion *sysmem, uint32_t base) MemoryRegion *fpga_memory = g_new(MemoryRegion, 1); fpga = g_malloc0(sizeof(ref405ep_fpga_t)); - memory_region_init_io(fpga_memory, &ref405ep_fpga_ops, fpga, + memory_region_init_io(fpga_memory, NULL, &ref405ep_fpga_ops, fpga, "fpga", 0x00000100); memory_region_add_subregion(sysmem, base, fpga_memory); qemu_register_reset(&ref405ep_fpga_reset, fpga); @@ -197,11 +197,11 @@ static void ref405ep_init(QEMUMachineInitArgs *args) MemoryRegion *sysmem = get_system_memory(); /* XXX: fix this */ - memory_region_init_ram(&ram_memories[0], "ef405ep.ram", 0x08000000); + memory_region_init_ram(&ram_memories[0], NULL, "ef405ep.ram", 0x08000000); vmstate_register_ram_global(&ram_memories[0]); ram_bases[0] = 0; ram_sizes[0] = 0x08000000; - memory_region_init(&ram_memories[1], "ef405ep.ram1", 0); + memory_region_init(&ram_memories[1], NULL, "ef405ep.ram1", 0); ram_bases[1] = 0x00000000; ram_sizes[1] = 0x00000000; ram_size = 128 * 1024 * 1024; @@ -212,7 +212,7 @@ static void ref405ep_init(QEMUMachineInitArgs *args) 33333333, &pic, kernel_filename == NULL ? 0 : 1); /* allocate SRAM */ sram_size = 512 * 1024; - memory_region_init_ram(sram, "ef405ep.sram", sram_size); + memory_region_init_ram(sram, NULL, "ef405ep.sram", sram_size); vmstate_register_ram_global(sram); memory_region_add_subregion(sysmem, 0xFFF00000, sram); /* allocate and load BIOS */ @@ -244,7 +244,7 @@ static void ref405ep_init(QEMUMachineInitArgs *args) printf("Load BIOS from file\n"); #endif bios = g_new(MemoryRegion, 1); - memory_region_init_ram(bios, "ef405ep.bios", BIOS_SIZE); + memory_region_init_ram(bios, NULL, "ef405ep.bios", BIOS_SIZE); vmstate_register_ram_global(bios); if (bios_name == NULL) bios_name = BIOS_FILENAME; @@ -490,7 +490,7 @@ static void taihu_cpld_init(MemoryRegion *sysmem, uint32_t base) MemoryRegion *cpld_memory = g_new(MemoryRegion, 1); cpld = g_malloc0(sizeof(taihu_cpld_t)); - memory_region_init_io(cpld_memory, &taihu_cpld_ops, cpld, "cpld", 0x100); + memory_region_init_io(cpld_memory, NULL, &taihu_cpld_ops, cpld, "cpld", 0x100); memory_region_add_subregion(sysmem, base, cpld_memory); qemu_register_reset(&taihu_cpld_reset, cpld); } @@ -514,12 +514,12 @@ static void taihu_405ep_init(QEMUMachineInitArgs *args) DriveInfo *dinfo; /* RAM is soldered to the board so the size cannot be changed */ - memory_region_init_ram(&ram_memories[0], + memory_region_init_ram(&ram_memories[0], NULL, "taihu_405ep.ram-0", 0x04000000); vmstate_register_ram_global(&ram_memories[0]); ram_bases[0] = 0; ram_sizes[0] = 0x04000000; - memory_region_init_ram(&ram_memories[1], + memory_region_init_ram(&ram_memories[1], NULL, "taihu_405ep.ram-1", 0x04000000); vmstate_register_ram_global(&ram_memories[1]); ram_bases[1] = 0x04000000; @@ -563,7 +563,7 @@ static void taihu_405ep_init(QEMUMachineInitArgs *args) if (bios_name == NULL) bios_name = BIOS_FILENAME; bios = g_new(MemoryRegion, 1); - memory_region_init_ram(bios, "taihu_405ep.bios", BIOS_SIZE); + memory_region_init_ram(bios, NULL, "taihu_405ep.bios", BIOS_SIZE); vmstate_register_ram_global(bios); filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (filename) { diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index c6c909e05e..290f71ab69 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -390,7 +390,7 @@ static void ppc4xx_opba_init(hwaddr base) #ifdef DEBUG_OPBA printf("%s: offset " TARGET_FMT_plx "\n", __func__, base); #endif - memory_region_init_io(&opba->io, &opba_ops, opba, "opba", 0x002); + memory_region_init_io(&opba->io, NULL, &opba_ops, opba, "opba", 0x002); memory_region_add_subregion(get_system_memory(), base, &opba->io); qemu_register_reset(ppc4xx_opba_reset, opba); } @@ -812,7 +812,7 @@ static void ppc405_gpio_init(hwaddr base) #ifdef DEBUG_GPIO printf("%s: offset " TARGET_FMT_plx "\n", __func__, base); #endif - memory_region_init_io(&gpio->io, &ppc405_gpio_ops, gpio, "pgio", 0x038); + memory_region_init_io(&gpio->io, NULL, &ppc405_gpio_ops, gpio, "pgio", 0x038); memory_region_add_subregion(get_system_memory(), base, &gpio->io); qemu_register_reset(&ppc405_gpio_reset, gpio); } @@ -972,9 +972,9 @@ static void ppc405_ocm_init(CPUPPCState *env) ocm = g_malloc0(sizeof(ppc405_ocm_t)); /* XXX: Size is 4096 or 0x04000000 */ - memory_region_init_ram(&ocm->isarc_ram, "ppc405.ocm", 4096); + memory_region_init_ram(&ocm->isarc_ram, NULL, "ppc405.ocm", 4096); vmstate_register_ram_global(&ocm->isarc_ram); - memory_region_init_alias(&ocm->dsarc_ram, "ppc405.dsarc", &ocm->isarc_ram, + memory_region_init_alias(&ocm->dsarc_ram, NULL, "ppc405.dsarc", &ocm->isarc_ram, 0, 4096); qemu_register_reset(&ocm_reset, ocm); ppc_dcr_register(env, OCM0_ISARC, @@ -1222,7 +1222,7 @@ static void ppc405_i2c_init(hwaddr base, qemu_irq irq) #ifdef DEBUG_I2C printf("%s: offset " TARGET_FMT_plx "\n", __func__, base); #endif - memory_region_init_io(&i2c->iomem, &i2c_ops, i2c, "i2c", 0x011); + memory_region_init_io(&i2c->iomem, NULL, &i2c_ops, i2c, "i2c", 0x011); memory_region_add_subregion(get_system_memory(), base, &i2c->iomem); qemu_register_reset(ppc4xx_i2c_reset, i2c); } @@ -1501,7 +1501,7 @@ static void ppc4xx_gpt_init(hwaddr base, qemu_irq irqs[5]) #ifdef DEBUG_GPT printf("%s: offset " TARGET_FMT_plx "\n", __func__, base); #endif - memory_region_init_io(&gpt->iomem, &gpt_ops, gpt, "gpt", 0x0d4); + memory_region_init_io(&gpt->iomem, NULL, &gpt_ops, gpt, "gpt", 0x0d4); memory_region_add_subregion(get_system_memory(), base, &gpt->iomem); qemu_register_reset(ppc4xx_gpt_reset, gpt); } diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c index d8e3dae25c..239aada193 100644 --- a/hw/ppc/ppc4xx_devs.c +++ b/hw/ppc/ppc4xx_devs.c @@ -431,7 +431,7 @@ static void sdram_set_bcr(ppc4xx_sdram_t *sdram, printf("%s: Map RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n", __func__, sdram_base(bcr), sdram_size(bcr)); #endif - memory_region_init(&sdram->containers[n], "sdram-containers", + memory_region_init(&sdram->containers[n], NULL, "sdram-containers", sdram_size(bcr)); memory_region_add_subregion(&sdram->containers[n], 0, &sdram->ram_memories[n]); @@ -696,7 +696,7 @@ ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks, if (bank_size <= size_left) { char name[32]; snprintf(name, sizeof(name), "ppc4xx.sdram%d", i); - memory_region_init_ram(&ram_memories[i], name, bank_size); + memory_region_init_ram(&ram_memories[i], NULL, name, bank_size); vmstate_register_ram_global(&ram_memories[i]); ram_bases[i] = base; ram_sizes[i] = bank_size; diff --git a/hw/ppc/ppc4xx_pci.c b/hw/ppc/ppc4xx_pci.c index 599539bc1d..d2d6f65e6c 100644 --- a/hw/ppc/ppc4xx_pci.c +++ b/hw/ppc/ppc4xx_pci.c @@ -355,12 +355,12 @@ static int ppc4xx_pcihost_initfn(SysBusDevice *dev) pci_create_simple(b, 0, "ppc4xx-host-bridge"); /* XXX split into 2 memory regions, one for config space, one for regs */ - memory_region_init(&s->container, "pci-container", PCI_ALL_SIZE); - memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops, h, + memory_region_init(&s->container, OBJECT(s), "pci-container", PCI_ALL_SIZE); + memory_region_init_io(&h->conf_mem, OBJECT(s), &pci_host_conf_le_ops, h, "pci-conf-idx", 4); - memory_region_init_io(&h->data_mem, &pci_host_data_le_ops, h, + memory_region_init_io(&h->data_mem, OBJECT(s), &pci_host_data_le_ops, h, "pci-conf-data", 4); - memory_region_init_io(&s->iomem, &pci_reg_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &pci_reg_ops, s, "pci.reg", PCI_REG_SIZE); memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem); memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem); diff --git a/hw/ppc/ppce500_spin.c b/hw/ppc/ppce500_spin.c index ea6541413f..11b7de2f30 100644 --- a/hw/ppc/ppce500_spin.c +++ b/hw/ppc/ppce500_spin.c @@ -191,8 +191,8 @@ static int ppce500_spin_initfn(SysBusDevice *dev) s = FROM_SYSBUS(SpinState, SYS_BUS_DEVICE(dev)); - memory_region_init_io(&s->iomem, &spin_rw_ops, s, "e500 spin pv device", - sizeof(SpinInfo) * MAX_CPUS); + memory_region_init_io(&s->iomem, OBJECT(s), &spin_rw_ops, s, + "e500 spin pv device", sizeof(SpinInfo) * MAX_CPUS); sysbus_init_mmio(dev, &s->iomem); qemu_register_reset(spin_reset, s); diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c index f674ab7079..19f2442482 100644 --- a/hw/ppc/prep.c +++ b/hw/ppc/prep.c @@ -417,10 +417,10 @@ static const MemoryRegionOps PPC_prep_io_ops = { static void cpu_request_exit(void *opaque, int irq, int level) { - CPUPPCState *env = cpu_single_env; + CPUState *cpu = current_cpu; - if (env && level) { - cpu_exit(CPU(ppc_env_get_cpu(env))); + if (cpu && level) { + cpu_exit(cpu); } } @@ -434,6 +434,16 @@ static void ppc_prep_reset(void *opaque) cpu->env.nip = 0xfffffffc; } +static const MemoryRegionPortio prep_portio_list[] = { + /* System control ports */ + { 0x0092, 1, 1, .read = PREP_io_800_readb, .write = PREP_io_800_writeb, }, + { 0x0800, 0x52, 1, + .read = PREP_io_800_readb, .write = PREP_io_800_writeb, }, + /* Special port to get debug messages from Open-Firmware */ + { 0x0F00, 4, 1, .write = PPC_debug_write, }, + PORTIO_END_OF_LIST(), +}; + /* PowerPC PREP hardware initialisation */ static void ppc_prep_init(QEMUMachineInitArgs *args) { @@ -450,6 +460,7 @@ static void ppc_prep_init(QEMUMachineInitArgs *args) nvram_t nvram; M48t59State *m48t59; MemoryRegion *PPC_io_memory = g_new(MemoryRegion, 1); + PortioList *port_list = g_new(PortioList, 1); #if 0 MemoryRegion *xcsr = g_new(MemoryRegion, 1); #endif @@ -494,12 +505,12 @@ static void ppc_prep_init(QEMUMachineInitArgs *args) } /* allocate RAM */ - memory_region_init_ram(ram, "ppc_prep.ram", ram_size); + memory_region_init_ram(ram, NULL, "ppc_prep.ram", ram_size); vmstate_register_ram_global(ram); memory_region_add_subregion(sysmem, 0, ram); /* allocate and load BIOS */ - memory_region_init_ram(bios, "ppc_prep.bios", BIOS_SIZE); + memory_region_init_ram(bios, NULL, "ppc_prep.bios", BIOS_SIZE); memory_region_set_readonly(bios, true); memory_region_add_subregion(sysmem, (uint32_t)(-BIOS_SIZE), bios); vmstate_register_ram_global(bios); @@ -594,8 +605,9 @@ static void ppc_prep_init(QEMUMachineInitArgs *args) /* PCI -> ISA bridge */ pci = pci_create_simple(pci_bus, PCI_DEVFN(1, 0), "i82378"); cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1); + cpu = POWERPC_CPU(first_cpu); qdev_connect_gpio_out(&pci->qdev, 0, - first_cpu->irq_inputs[PPC6xx_INPUT_INT]); + cpu->env.irq_inputs[PPC6xx_INPUT_INT]); qdev_connect_gpio_out(&pci->qdev, 1, *cpu_exit_irq); sysbus_connect_irq(&pcihost->busdev, 0, qdev_get_gpio_in(&pci->qdev, 9)); sysbus_connect_irq(&pcihost->busdev, 1, qdev_get_gpio_in(&pci->qdev, 11)); @@ -610,7 +622,7 @@ static void ppc_prep_init(QEMUMachineInitArgs *args) qdev_init_nofail(dev); /* Register 8 MB of ISA IO space (needed for non-contiguous map) */ - memory_region_init_io(PPC_io_memory, &PPC_prep_io_ops, sysctrl, + memory_region_init_io(PPC_io_memory, NULL, &PPC_prep_io_ops, sysctrl, "ppc-io", 0x00800000); memory_region_add_subregion(sysmem, 0x80000000, PPC_io_memory); @@ -640,15 +652,15 @@ static void ppc_prep_init(QEMUMachineInitArgs *args) } isa_create_simple(isa_bus, "i8042"); - sysctrl->reset_irq = first_cpu->irq_inputs[PPC6xx_INPUT_HRESET]; - /* System control ports */ - register_ioport_read(0x0092, 0x01, 1, &PREP_io_800_readb, sysctrl); - register_ioport_write(0x0092, 0x01, 1, &PREP_io_800_writeb, sysctrl); - register_ioport_read(0x0800, 0x52, 1, &PREP_io_800_readb, sysctrl); - register_ioport_write(0x0800, 0x52, 1, &PREP_io_800_writeb, sysctrl); + cpu = POWERPC_CPU(first_cpu); + sysctrl->reset_irq = cpu->env.irq_inputs[PPC6xx_INPUT_HRESET]; + + portio_list_init(port_list, NULL, prep_portio_list, sysctrl, "prep"); + portio_list_add(port_list, get_system_io(), 0x0); + /* PowerPC control and status register group */ #if 0 - memory_region_init_io(xcsr, &PPC_XCSR_ops, NULL, "ppc-xcsr", 0x1000); + memory_region_init_io(xcsr, NULL, &PPC_XCSR_ops, NULL, "ppc-xcsr", 0x1000); memory_region_add_subregion(sysmem, 0xFEFF0000, xcsr); #endif @@ -672,9 +684,6 @@ static void ppc_prep_init(QEMUMachineInitArgs *args) /* XXX: need an option to load a NVRAM image */ 0, graphic_width, graphic_height, graphic_depth); - - /* Special port to get debug messages from Open-Firmware */ - register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL); } static QEMUMachine prep_machine = { diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index e2183d34a9..48ae09283d 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -131,7 +131,6 @@ int spapr_allocate_irq_block(int num, bool lsi) static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr) { int ret = 0, offset; - CPUPPCState *env; CPUState *cpu; char cpu_model[32]; int smt = kvmppc_smt_threads(); @@ -139,8 +138,7 @@ static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr) assert(spapr->cpu_model); - for (env = first_cpu; env != NULL; env = env->next_cpu) { - cpu = CPU(ppc_env_get_cpu(env)); + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { uint32_t associativity[] = {cpu_to_be32(0x5), cpu_to_be32(0x0), cpu_to_be32(0x0), @@ -231,7 +229,7 @@ static void *spapr_create_fdt_skel(const char *cpu_model, uint32_t epow_irq) { void *fdt; - CPUPPCState *env; + CPUState *cs; uint32_t start_prop = cpu_to_be32(initrd_base); uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size); char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt" @@ -304,10 +302,11 @@ static void *spapr_create_fdt_skel(const char *cpu_model, /* This is needed during FDT finalization */ spapr->cpu_model = g_strdup(modelname); - for (env = first_cpu; env != NULL; env = env->next_cpu) { - CPUState *cpu = CPU(ppc_env_get_cpu(env)); - PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); - int index = cpu->cpu_index; + for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) { + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; + PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); + int index = cs->cpu_index; uint32_t servers_prop[smp_threads]; uint32_t gservers_prop[smp_threads * 2]; char *nodename; @@ -632,7 +631,7 @@ static void spapr_reset_htab(sPAPREnvironment *spapr) static void ppc_spapr_reset(void) { - CPUState *first_cpu_cpu; + PowerPCCPU *first_ppc_cpu; /* Reset the hash table & recalc the RMA */ spapr_reset_htab(spapr); @@ -644,11 +643,11 @@ static void ppc_spapr_reset(void) spapr->rtas_size); /* Set up the entry state */ - first_cpu_cpu = ENV_GET_CPU(first_cpu); - first_cpu->gpr[3] = spapr->fdt_addr; - first_cpu->gpr[5] = 0; - first_cpu_cpu->halted = 0; - first_cpu->nip = spapr->entry_point; + first_ppc_cpu = POWERPC_CPU(first_cpu); + first_ppc_cpu->env.gpr[3] = spapr->fdt_addr; + first_ppc_cpu->env.gpr[5] = 0; + first_cpu->halted = 0; + first_ppc_cpu->env.nip = spapr->entry_point; } @@ -676,27 +675,19 @@ static void spapr_cpu_reset(void *opaque) static void spapr_create_nvram(sPAPREnvironment *spapr) { - QemuOpts *machine_opts; - DeviceState *dev; - - dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram"); - - machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); - if (machine_opts) { - const char *drivename; + DeviceState *dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram"); + const char *drivename = qemu_opt_get(qemu_get_machine_opts(), "nvram"); - drivename = qemu_opt_get(machine_opts, "nvram"); - if (drivename) { - BlockDriverState *bs; + if (drivename) { + BlockDriverState *bs; - bs = bdrv_find(drivename); - if (!bs) { - fprintf(stderr, "No such block device \"%s\" for nvram\n", - drivename); - exit(1); - } - qdev_prop_set_drive_nofail(dev, "drive", bs); + bs = bdrv_find(drivename); + if (!bs) { + fprintf(stderr, "No such block device \"%s\" for nvram\n", + drivename); + exit(1); } + qdev_prop_set_drive_nofail(dev, "drive", bs); } qdev_init_nofail(dev); @@ -835,7 +826,7 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args) ram_addr_t nonrma_base = rma_alloc_size; ram_addr_t nonrma_size = spapr->ram_limit - rma_alloc_size; - memory_region_init_ram(ram, "ppc_spapr.ram", nonrma_size); + memory_region_init_ram(ram, NULL, "ppc_spapr.ram", nonrma_size); vmstate_register_ram_global(ram); memory_region_add_subregion(sysmem, nonrma_base, ram); } @@ -949,7 +940,10 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args) } } - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, FW_FILE_NAME); + if (bios_name == NULL) { + bios_name = FW_FILE_NAME; + } + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE); if (fw_size < 0) { hw_error("qemu: could not load LPAR rtas '%s'\n", filename); diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index e6f321d538..ed32decebf 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -121,14 +121,14 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr, return H_SUCCESS; } -enum { +typedef enum { REMOVE_SUCCESS = 0, REMOVE_NOT_FOUND = 1, REMOVE_PARM = 2, REMOVE_HW = 3, -}; +} RemoveResult; -static target_ulong remove_hpte(CPUPPCState *env, target_ulong ptex, +static RemoveResult remove_hpte(CPUPPCState *env, target_ulong ptex, target_ulong avpn, target_ulong flags, target_ulong *vp, target_ulong *rp) @@ -165,7 +165,7 @@ static target_ulong h_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong flags = args[0]; target_ulong pte_index = args[1]; target_ulong avpn = args[2]; - int ret; + RemoveResult ret; ret = remove_hpte(env, pte_index, avpn, flags, &args[0], &args[1]); @@ -184,7 +184,7 @@ static target_ulong h_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr, return H_HARDWARE; } - assert(0); + g_assert_not_reached(); } #define H_BULK_REMOVE_TYPE 0xc000000000000000ULL diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c index 91bc8e488e..89b33a5478 100644 --- a/hw/ppc/spapr_iommu.c +++ b/hw/ppc/spapr_iommu.c @@ -116,7 +116,7 @@ static MemoryRegionIOMMUOps spapr_iommu_ops = { .translate = spapr_tce_translate_iommu, }; -sPAPRTCETable *spapr_tce_new_table(uint32_t liobn, size_t window_size) +sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn, size_t window_size) { sPAPRTCETable *tcet; @@ -151,7 +151,7 @@ sPAPRTCETable *spapr_tce_new_table(uint32_t liobn, size_t window_size) "table @ %p, fd=%d\n", tcet, liobn, tcet->table, tcet->fd); #endif - memory_region_init_iommu(&tcet->iommu, &spapr_iommu_ops, + memory_region_init_iommu(&tcet->iommu, OBJECT(owner), &spapr_iommu_ops, "iommu-spapr", UINT64_MAX); QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list); diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index f7be24c755..318bc9d6ef 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -451,7 +451,7 @@ static uint64_t spapr_io_read(void *opaque, hwaddr addr, case 4: return cpu_inl(addr); } - assert(0); + g_assert_not_reached(); } static void spapr_io_write(void *opaque, hwaddr addr, @@ -468,7 +468,7 @@ static void spapr_io_write(void *opaque, hwaddr addr, cpu_outl(addr, data); return; } - assert(0); + g_assert_not_reached(); } static const MemoryRegionOps spapr_io_ops = { @@ -581,10 +581,11 @@ static int spapr_phb_init(SysBusDevice *s) /* Initialize memory regions */ sprintf(namebuf, "%s.mmio", sphb->dtbusname); - memory_region_init(&sphb->memspace, namebuf, INT64_MAX); + memory_region_init(&sphb->memspace, OBJECT(sphb), namebuf, INT64_MAX); sprintf(namebuf, "%s.mmio-alias", sphb->dtbusname); - memory_region_init_alias(&sphb->memwindow, namebuf, &sphb->memspace, + memory_region_init_alias(&sphb->memwindow, OBJECT(sphb), + namebuf, &sphb->memspace, SPAPR_PCI_MEM_WIN_BUS_OFFSET, sphb->mem_win_size); memory_region_add_subregion(get_system_memory(), sphb->mem_win_addr, &sphb->memwindow); @@ -598,12 +599,13 @@ static int spapr_phb_init(SysBusDevice *s) * system_io works around the problem until all the users of * old_portion are updated */ sprintf(namebuf, "%s.io", sphb->dtbusname); - memory_region_init(&sphb->iospace, namebuf, SPAPR_PCI_IO_WIN_SIZE); + memory_region_init(&sphb->iospace, OBJECT(sphb), + namebuf, SPAPR_PCI_IO_WIN_SIZE); /* FIXME: fix to support multiple PHBs */ memory_region_add_subregion(get_system_io(), 0, &sphb->iospace); sprintf(namebuf, "%s.io-alias", sphb->dtbusname); - memory_region_init_io(&sphb->iowindow, &spapr_io_ops, sphb, + memory_region_init_io(&sphb->iowindow, OBJECT(sphb), &spapr_io_ops, sphb, namebuf, SPAPR_PCI_IO_WIN_SIZE); memory_region_add_subregion(get_system_memory(), sphb->io_win_addr, &sphb->iowindow); @@ -613,7 +615,7 @@ static int spapr_phb_init(SysBusDevice *s) * from msi_notify()/msix_notify() */ if (msi_supported) { sprintf(namebuf, "%s.msi", sphb->dtbusname); - memory_region_init_io(&sphb->msiwindow, &spapr_msi_ops, sphb, + memory_region_init_io(&sphb->msiwindow, OBJECT(sphb), &spapr_msi_ops, sphb, namebuf, SPAPR_MSIX_MAX_DEVS * 0x10000); memory_region_add_subregion(get_system_memory(), sphb->msi_win_addr, &sphb->msiwindow); @@ -646,7 +648,8 @@ static int spapr_phb_init(SysBusDevice *s) sphb->dma_window_start = 0; sphb->dma_window_size = 0x40000000; - sphb->tcet = spapr_tce_new_table(sphb->dma_liobn, sphb->dma_window_size); + sphb->tcet = spapr_tce_new_table(DEVICE(sphb), sphb->dma_liobn, + sphb->dma_window_size); if (!sphb->tcet) { fprintf(stderr, "Unable to create TCE table for %s\n", sphb->dtbusname); return -1; diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c index 9c18741cea..7c6f6e4275 100644 --- a/hw/ppc/spapr_vio.c +++ b/hw/ppc/spapr_vio.c @@ -455,7 +455,7 @@ static int spapr_vio_busdev_init(DeviceState *qdev) if (pc->rtce_window_size) { uint32_t liobn = SPAPR_VIO_BASE_LIOBN | dev->reg; - dev->tcet = spapr_tce_new_table(liobn, pc->rtce_window_size); + dev->tcet = spapr_tce_new_table(qdev, liobn, pc->rtce_window_size); address_space_init(&dev->as, spapr_tce_get_iommu(dev->tcet), qdev->id); } diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c index 709a707243..08e77fbef5 100644 --- a/hw/ppc/virtex_ml507.c +++ b/hw/ppc/virtex_ml507.c @@ -190,7 +190,7 @@ static void virtex_init(QEMUMachineInitArgs *args) env = &cpu->env; qemu_register_reset(main_cpu_reset, cpu); - memory_region_init_ram(phys_ram, "ram", ram_size); + memory_region_init_ram(phys_ram, NULL, "ram", ram_size); vmstate_register_ram_global(phys_ram); memory_region_add_subregion(address_space_mem, ram_base, phys_ram); diff --git a/hw/ppc/xics.c b/hw/ppc/xics.c deleted file mode 100644 index 091912e2ca..0000000000 --- a/hw/ppc/xics.c +++ /dev/null @@ -1,587 +0,0 @@ -/* - * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator - * - * PAPR Virtualized Interrupt System, aka ICS/ICP aka xics - * - * Copyright (c) 2010,2011 David Gibson, IBM Corporation. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ - -#include "hw/hw.h" -#include "trace.h" -#include "hw/ppc/spapr.h" -#include "hw/ppc/xics.h" - -/* - * ICP: Presentation layer - */ - -struct icp_server_state { - uint32_t xirr; - uint8_t pending_priority; - uint8_t mfrr; - qemu_irq output; -}; - -#define XISR_MASK 0x00ffffff -#define CPPR_MASK 0xff000000 - -#define XISR(ss) (((ss)->xirr) & XISR_MASK) -#define CPPR(ss) (((ss)->xirr) >> 24) - -struct ics_state; - -struct icp_state { - long nr_servers; - struct icp_server_state *ss; - struct ics_state *ics; -}; - -static void ics_reject(struct ics_state *ics, int nr); -static void ics_resend(struct ics_state *ics); -static void ics_eoi(struct ics_state *ics, int nr); - -static void icp_check_ipi(struct icp_state *icp, int server) -{ - struct icp_server_state *ss = icp->ss + server; - - if (XISR(ss) && (ss->pending_priority <= ss->mfrr)) { - return; - } - - trace_xics_icp_check_ipi(server, ss->mfrr); - - if (XISR(ss)) { - ics_reject(icp->ics, XISR(ss)); - } - - ss->xirr = (ss->xirr & ~XISR_MASK) | XICS_IPI; - ss->pending_priority = ss->mfrr; - qemu_irq_raise(ss->output); -} - -static void icp_resend(struct icp_state *icp, int server) -{ - struct icp_server_state *ss = icp->ss + server; - - if (ss->mfrr < CPPR(ss)) { - icp_check_ipi(icp, server); - } - ics_resend(icp->ics); -} - -static void icp_set_cppr(struct icp_state *icp, int server, uint8_t cppr) -{ - struct icp_server_state *ss = icp->ss + server; - uint8_t old_cppr; - uint32_t old_xisr; - - old_cppr = CPPR(ss); - ss->xirr = (ss->xirr & ~CPPR_MASK) | (cppr << 24); - - if (cppr < old_cppr) { - if (XISR(ss) && (cppr <= ss->pending_priority)) { - old_xisr = XISR(ss); - ss->xirr &= ~XISR_MASK; /* Clear XISR */ - ss->pending_priority = 0xff; - qemu_irq_lower(ss->output); - ics_reject(icp->ics, old_xisr); - } - } else { - if (!XISR(ss)) { - icp_resend(icp, server); - } - } -} - -static void icp_set_mfrr(struct icp_state *icp, int server, uint8_t mfrr) -{ - struct icp_server_state *ss = icp->ss + server; - - ss->mfrr = mfrr; - if (mfrr < CPPR(ss)) { - icp_check_ipi(icp, server); - } -} - -static uint32_t icp_accept(struct icp_server_state *ss) -{ - uint32_t xirr = ss->xirr; - - qemu_irq_lower(ss->output); - ss->xirr = ss->pending_priority << 24; - ss->pending_priority = 0xff; - - trace_xics_icp_accept(xirr, ss->xirr); - - return xirr; -} - -static void icp_eoi(struct icp_state *icp, int server, uint32_t xirr) -{ - struct icp_server_state *ss = icp->ss + server; - - /* Send EOI -> ICS */ - ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK); - trace_xics_icp_eoi(server, xirr, ss->xirr); - ics_eoi(icp->ics, xirr & XISR_MASK); - if (!XISR(ss)) { - icp_resend(icp, server); - } -} - -static void icp_irq(struct icp_state *icp, int server, int nr, uint8_t priority) -{ - struct icp_server_state *ss = icp->ss + server; - - trace_xics_icp_irq(server, nr, priority); - - if ((priority >= CPPR(ss)) - || (XISR(ss) && (ss->pending_priority <= priority))) { - ics_reject(icp->ics, nr); - } else { - if (XISR(ss)) { - ics_reject(icp->ics, XISR(ss)); - } - ss->xirr = (ss->xirr & ~XISR_MASK) | (nr & XISR_MASK); - ss->pending_priority = priority; - trace_xics_icp_raise(ss->xirr, ss->pending_priority); - qemu_irq_raise(ss->output); - } -} - -/* - * ICS: Source layer - */ - -struct ics_irq_state { - int server; - uint8_t priority; - uint8_t saved_priority; -#define XICS_STATUS_ASSERTED 0x1 -#define XICS_STATUS_SENT 0x2 -#define XICS_STATUS_REJECTED 0x4 -#define XICS_STATUS_MASKED_PENDING 0x8 - uint8_t status; -}; - -struct ics_state { - int nr_irqs; - int offset; - qemu_irq *qirqs; - bool *islsi; - struct ics_irq_state *irqs; - struct icp_state *icp; -}; - -static int ics_valid_irq(struct ics_state *ics, uint32_t nr) -{ - return (nr >= ics->offset) - && (nr < (ics->offset + ics->nr_irqs)); -} - -static void resend_msi(struct ics_state *ics, int srcno) -{ - struct ics_irq_state *irq = ics->irqs + srcno; - - /* FIXME: filter by server#? */ - if (irq->status & XICS_STATUS_REJECTED) { - irq->status &= ~XICS_STATUS_REJECTED; - if (irq->priority != 0xff) { - icp_irq(ics->icp, irq->server, srcno + ics->offset, - irq->priority); - } - } -} - -static void resend_lsi(struct ics_state *ics, int srcno) -{ - struct ics_irq_state *irq = ics->irqs + srcno; - - if ((irq->priority != 0xff) - && (irq->status & XICS_STATUS_ASSERTED) - && !(irq->status & XICS_STATUS_SENT)) { - irq->status |= XICS_STATUS_SENT; - icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority); - } -} - -static void set_irq_msi(struct ics_state *ics, int srcno, int val) -{ - struct ics_irq_state *irq = ics->irqs + srcno; - - trace_xics_set_irq_msi(srcno, srcno + ics->offset); - - if (val) { - if (irq->priority == 0xff) { - irq->status |= XICS_STATUS_MASKED_PENDING; - trace_xics_masked_pending(); - } else { - icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority); - } - } -} - -static void set_irq_lsi(struct ics_state *ics, int srcno, int val) -{ - struct ics_irq_state *irq = ics->irqs + srcno; - - trace_xics_set_irq_lsi(srcno, srcno + ics->offset); - if (val) { - irq->status |= XICS_STATUS_ASSERTED; - } else { - irq->status &= ~XICS_STATUS_ASSERTED; - } - resend_lsi(ics, srcno); -} - -static void ics_set_irq(void *opaque, int srcno, int val) -{ - struct ics_state *ics = (struct ics_state *)opaque; - - if (ics->islsi[srcno]) { - set_irq_lsi(ics, srcno, val); - } else { - set_irq_msi(ics, srcno, val); - } -} - -static void write_xive_msi(struct ics_state *ics, int srcno) -{ - struct ics_irq_state *irq = ics->irqs + srcno; - - if (!(irq->status & XICS_STATUS_MASKED_PENDING) - || (irq->priority == 0xff)) { - return; - } - - irq->status &= ~XICS_STATUS_MASKED_PENDING; - icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority); -} - -static void write_xive_lsi(struct ics_state *ics, int srcno) -{ - resend_lsi(ics, srcno); -} - -static void ics_write_xive(struct ics_state *ics, int nr, int server, - uint8_t priority, uint8_t saved_priority) -{ - int srcno = nr - ics->offset; - struct ics_irq_state *irq = ics->irqs + srcno; - - irq->server = server; - irq->priority = priority; - irq->saved_priority = saved_priority; - - trace_xics_ics_write_xive(nr, srcno, server, priority); - - if (ics->islsi[srcno]) { - write_xive_lsi(ics, srcno); - } else { - write_xive_msi(ics, srcno); - } -} - -static void ics_reject(struct ics_state *ics, int nr) -{ - struct ics_irq_state *irq = ics->irqs + nr - ics->offset; - - trace_xics_ics_reject(nr, nr - ics->offset); - irq->status |= XICS_STATUS_REJECTED; /* Irrelevant but harmless for LSI */ - irq->status &= ~XICS_STATUS_SENT; /* Irrelevant but harmless for MSI */ -} - -static void ics_resend(struct ics_state *ics) -{ - int i; - - for (i = 0; i < ics->nr_irqs; i++) { - /* FIXME: filter by server#? */ - if (ics->islsi[i]) { - resend_lsi(ics, i); - } else { - resend_msi(ics, i); - } - } -} - -static void ics_eoi(struct ics_state *ics, int nr) -{ - int srcno = nr - ics->offset; - struct ics_irq_state *irq = ics->irqs + srcno; - - trace_xics_ics_eoi(nr); - - if (ics->islsi[srcno]) { - irq->status &= ~XICS_STATUS_SENT; - } -} - -/* - * Exported functions - */ - -qemu_irq xics_get_qirq(struct icp_state *icp, int irq) -{ - if (!ics_valid_irq(icp->ics, irq)) { - return NULL; - } - - return icp->ics->qirqs[irq - icp->ics->offset]; -} - -void xics_set_irq_type(struct icp_state *icp, int irq, bool lsi) -{ - assert(ics_valid_irq(icp->ics, irq)); - - icp->ics->islsi[irq - icp->ics->offset] = lsi; -} - -static target_ulong h_cppr(PowerPCCPU *cpu, sPAPREnvironment *spapr, - target_ulong opcode, target_ulong *args) -{ - CPUState *cs = CPU(cpu); - target_ulong cppr = args[0]; - - icp_set_cppr(spapr->icp, cs->cpu_index, cppr); - return H_SUCCESS; -} - -static target_ulong h_ipi(PowerPCCPU *cpu, sPAPREnvironment *spapr, - target_ulong opcode, target_ulong *args) -{ - target_ulong server = args[0]; - target_ulong mfrr = args[1]; - - if (server >= spapr->icp->nr_servers) { - return H_PARAMETER; - } - - icp_set_mfrr(spapr->icp, server, mfrr); - return H_SUCCESS; -} - -static target_ulong h_xirr(PowerPCCPU *cpu, sPAPREnvironment *spapr, - target_ulong opcode, target_ulong *args) -{ - CPUState *cs = CPU(cpu); - uint32_t xirr = icp_accept(spapr->icp->ss + cs->cpu_index); - - args[0] = xirr; - return H_SUCCESS; -} - -static target_ulong h_eoi(PowerPCCPU *cpu, sPAPREnvironment *spapr, - target_ulong opcode, target_ulong *args) -{ - CPUState *cs = CPU(cpu); - target_ulong xirr = args[0]; - - icp_eoi(spapr->icp, cs->cpu_index, xirr); - return H_SUCCESS; -} - -static void rtas_set_xive(PowerPCCPU *cpu, sPAPREnvironment *spapr, - uint32_t token, - uint32_t nargs, target_ulong args, - uint32_t nret, target_ulong rets) -{ - struct ics_state *ics = spapr->icp->ics; - uint32_t nr, server, priority; - - if ((nargs != 3) || (nret != 1)) { - rtas_st(rets, 0, -3); - return; - } - - nr = rtas_ld(args, 0); - server = rtas_ld(args, 1); - priority = rtas_ld(args, 2); - - if (!ics_valid_irq(ics, nr) || (server >= ics->icp->nr_servers) - || (priority > 0xff)) { - rtas_st(rets, 0, -3); - return; - } - - ics_write_xive(ics, nr, server, priority, priority); - - rtas_st(rets, 0, 0); /* Success */ -} - -static void rtas_get_xive(PowerPCCPU *cpu, sPAPREnvironment *spapr, - uint32_t token, - uint32_t nargs, target_ulong args, - uint32_t nret, target_ulong rets) -{ - struct ics_state *ics = spapr->icp->ics; - uint32_t nr; - - if ((nargs != 1) || (nret != 3)) { - rtas_st(rets, 0, -3); - return; - } - - nr = rtas_ld(args, 0); - - if (!ics_valid_irq(ics, nr)) { - rtas_st(rets, 0, -3); - return; - } - - rtas_st(rets, 0, 0); /* Success */ - rtas_st(rets, 1, ics->irqs[nr - ics->offset].server); - rtas_st(rets, 2, ics->irqs[nr - ics->offset].priority); -} - -static void rtas_int_off(PowerPCCPU *cpu, sPAPREnvironment *spapr, - uint32_t token, - uint32_t nargs, target_ulong args, - uint32_t nret, target_ulong rets) -{ - struct ics_state *ics = spapr->icp->ics; - uint32_t nr; - - if ((nargs != 1) || (nret != 1)) { - rtas_st(rets, 0, -3); - return; - } - - nr = rtas_ld(args, 0); - - if (!ics_valid_irq(ics, nr)) { - rtas_st(rets, 0, -3); - return; - } - - ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, 0xff, - ics->irqs[nr - ics->offset].priority); - - rtas_st(rets, 0, 0); /* Success */ -} - -static void rtas_int_on(PowerPCCPU *cpu, sPAPREnvironment *spapr, - uint32_t token, - uint32_t nargs, target_ulong args, - uint32_t nret, target_ulong rets) -{ - struct ics_state *ics = spapr->icp->ics; - uint32_t nr; - - if ((nargs != 1) || (nret != 1)) { - rtas_st(rets, 0, -3); - return; - } - - nr = rtas_ld(args, 0); - - if (!ics_valid_irq(ics, nr)) { - rtas_st(rets, 0, -3); - return; - } - - ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, - ics->irqs[nr - ics->offset].saved_priority, - ics->irqs[nr - ics->offset].saved_priority); - - rtas_st(rets, 0, 0); /* Success */ -} - -static void xics_reset(void *opaque) -{ - struct icp_state *icp = (struct icp_state *)opaque; - struct ics_state *ics = icp->ics; - int i; - - for (i = 0; i < icp->nr_servers; i++) { - icp->ss[i].xirr = 0; - icp->ss[i].pending_priority = 0xff; - icp->ss[i].mfrr = 0xff; - /* Make all outputs are deasserted */ - qemu_set_irq(icp->ss[i].output, 0); - } - - memset(ics->irqs, 0, sizeof(struct ics_irq_state) * ics->nr_irqs); - for (i = 0; i < ics->nr_irqs; i++) { - ics->irqs[i].priority = 0xff; - ics->irqs[i].saved_priority = 0xff; - } -} - -void xics_cpu_setup(struct icp_state *icp, PowerPCCPU *cpu) -{ - CPUState *cs = CPU(cpu); - CPUPPCState *env = &cpu->env; - struct icp_server_state *ss = &icp->ss[cs->cpu_index]; - - assert(cs->cpu_index < icp->nr_servers); - - switch (PPC_INPUT(env)) { - case PPC_FLAGS_INPUT_POWER7: - ss->output = env->irq_inputs[POWER7_INPUT_INT]; - break; - - case PPC_FLAGS_INPUT_970: - ss->output = env->irq_inputs[PPC970_INPUT_INT]; - break; - - default: - fprintf(stderr, "XICS interrupt controller does not support this CPU " - "bus model\n"); - abort(); - } -} - -struct icp_state *xics_system_init(int nr_servers, int nr_irqs) -{ - struct icp_state *icp; - struct ics_state *ics; - - icp = g_malloc0(sizeof(*icp)); - icp->nr_servers = nr_servers; - icp->ss = g_malloc0(icp->nr_servers*sizeof(struct icp_server_state)); - - ics = g_malloc0(sizeof(*ics)); - ics->nr_irqs = nr_irqs; - ics->offset = XICS_IRQ_BASE; - ics->irqs = g_malloc0(nr_irqs * sizeof(struct ics_irq_state)); - ics->islsi = g_malloc0(nr_irqs * sizeof(bool)); - - icp->ics = ics; - ics->icp = icp; - - ics->qirqs = qemu_allocate_irqs(ics_set_irq, ics, nr_irqs); - - spapr_register_hypercall(H_CPPR, h_cppr); - spapr_register_hypercall(H_IPI, h_ipi); - spapr_register_hypercall(H_XIRR, h_xirr); - spapr_register_hypercall(H_EOI, h_eoi); - - spapr_rtas_register("ibm,set-xive", rtas_set_xive); - spapr_rtas_register("ibm,get-xive", rtas_get_xive); - spapr_rtas_register("ibm,int-off", rtas_int_off); - spapr_rtas_register("ibm,int-on", rtas_int_on); - - qemu_register_reset(xics_reset, icp); - - return icp; -} |