diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/alpha_typhoon.c | 4 | ||||
-rw-r--r-- | hw/arm_gic.c | 3 | ||||
-rw-r--r-- | hw/arm_mptimer.c | 8 | ||||
-rw-r--r-- | hw/ide/core.c | 79 | ||||
-rw-r--r-- | hw/mips_malta.c | 9 | ||||
-rw-r--r-- | hw/openpic.c | 5 | ||||
-rw-r--r-- | hw/pc87312.c | 64 | ||||
-rw-r--r-- | hw/pc87312.h | 2 | ||||
-rw-r--r-- | hw/ppc/e500.c | 17 | ||||
-rw-r--r-- | hw/ppce500_spin.c | 8 | ||||
-rw-r--r-- | hw/pxa.h | 2 | ||||
-rw-r--r-- | hw/pxa2xx.c | 4 | ||||
-rw-r--r-- | hw/pxa2xx_gpio.c | 7 | ||||
-rw-r--r-- | hw/scsi-disk.c | 4 | ||||
-rw-r--r-- | hw/spapr.c | 13 | ||||
-rw-r--r-- | hw/spapr_hcall.c | 4 | ||||
-rw-r--r-- | hw/spapr_rtas.c | 8 | ||||
-rw-r--r-- | hw/xen_disk.c | 208 | ||||
-rw-r--r-- | hw/xics.c | 22 |
19 files changed, 351 insertions, 120 deletions
diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c index dafb35d..bf9aabf 100644 --- a/hw/alpha_typhoon.c +++ b/hw/alpha_typhoon.c @@ -75,6 +75,7 @@ static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size) { CPUAlphaState *env = cpu_single_env; TyphoonState *s = opaque; + CPUState *cpu; uint64_t ret = 0; if (addr & 4) { @@ -95,7 +96,8 @@ static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size) case 0x0080: /* MISC: Miscellaneous Register. */ - ret = s->cchip.misc | (env->cpu_index & 3); + cpu = ENV_GET_CPU(env); + ret = s->cchip.misc | (cpu->cpu_index & 3); break; case 0x00c0: diff --git a/hw/arm_gic.c b/hw/arm_gic.c index 466dbf7..90e43d0 100644 --- a/hw/arm_gic.c +++ b/hw/arm_gic.c @@ -39,7 +39,8 @@ static const uint8_t gic_id[] = { static inline int gic_get_current_cpu(GICState *s) { if (s->num_cpu > 1) { - return cpu_single_env->cpu_index; + CPUState *cpu = ENV_GET_CPU(cpu_single_env); + return cpu->cpu_index; } return 0; } diff --git a/hw/arm_mptimer.c b/hw/arm_mptimer.c index 0cd3853..cdfd623 100644 --- a/hw/arm_mptimer.c +++ b/hw/arm_mptimer.c @@ -49,11 +49,13 @@ typedef struct { static inline int get_current_cpu(arm_mptimer_state *s) { - if (cpu_single_env->cpu_index >= s->num_cpu) { + CPUState *cpu_single_cpu = ENV_GET_CPU(cpu_single_env); + + if (cpu_single_cpu->cpu_index >= s->num_cpu) { hw_error("arm_mptimer: num-cpu %d but this cpu is %d!\n", - s->num_cpu, cpu_single_env->cpu_index); + s->num_cpu, cpu_single_cpu->cpu_index); } - return cpu_single_env->cpu_index; + return cpu_single_cpu->cpu_index; } static inline void timerblock_update_irq(timerblock *tb) diff --git a/hw/ide/core.c b/hw/ide/core.c index 6f1938a..14ad079 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -325,14 +325,26 @@ typedef struct TrimAIOCB { BlockDriverAIOCB common; QEMUBH *bh; int ret; + QEMUIOVector *qiov; + BlockDriverAIOCB *aiocb; + int i, j; } TrimAIOCB; static void trim_aio_cancel(BlockDriverAIOCB *acb) { TrimAIOCB *iocb = container_of(acb, TrimAIOCB, common); + /* Exit the loop in case bdrv_aio_cancel calls ide_issue_trim_cb again. */ + iocb->j = iocb->qiov->niov - 1; + iocb->i = (iocb->qiov->iov[iocb->j].iov_len / 8) - 1; + + /* Tell ide_issue_trim_cb not to trigger the completion, too. */ qemu_bh_delete(iocb->bh); iocb->bh = NULL; + + if (iocb->aiocb) { + bdrv_aio_cancel(iocb->aiocb); + } qemu_aio_release(iocb); } @@ -349,43 +361,60 @@ static void ide_trim_bh_cb(void *opaque) qemu_bh_delete(iocb->bh); iocb->bh = NULL; - qemu_aio_release(iocb); } +static void ide_issue_trim_cb(void *opaque, int ret) +{ + TrimAIOCB *iocb = opaque; + if (ret >= 0) { + while (iocb->j < iocb->qiov->niov) { + int j = iocb->j; + while (++iocb->i < iocb->qiov->iov[j].iov_len / 8) { + int i = iocb->i; + uint64_t *buffer = iocb->qiov->iov[j].iov_base; + + /* 6-byte LBA + 2-byte range per entry */ + uint64_t entry = le64_to_cpu(buffer[i]); + uint64_t sector = entry & 0x0000ffffffffffffULL; + uint16_t count = entry >> 48; + + if (count == 0) { + continue; + } + + /* Got an entry! Submit and exit. */ + iocb->aiocb = bdrv_aio_discard(iocb->common.bs, sector, count, + ide_issue_trim_cb, opaque); + return; + } + + iocb->j++; + iocb->i = -1; + } + } else { + iocb->ret = ret; + } + + iocb->aiocb = NULL; + if (iocb->bh) { + qemu_bh_schedule(iocb->bh); + } +} + BlockDriverAIOCB *ide_issue_trim(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque) { TrimAIOCB *iocb; - int i, j, ret; iocb = qemu_aio_get(&trim_aiocb_info, bs, cb, opaque); iocb->bh = qemu_bh_new(ide_trim_bh_cb, iocb); iocb->ret = 0; - - for (j = 0; j < qiov->niov; j++) { - uint64_t *buffer = qiov->iov[j].iov_base; - - for (i = 0; i < qiov->iov[j].iov_len / 8; i++) { - /* 6-byte LBA + 2-byte range per entry */ - uint64_t entry = le64_to_cpu(buffer[i]); - uint64_t sector = entry & 0x0000ffffffffffffULL; - uint16_t count = entry >> 48; - - if (count == 0) { - break; - } - - ret = bdrv_discard(bs, sector, count); - if (!iocb->ret) { - iocb->ret = ret; - } - } - } - - qemu_bh_schedule(iocb->bh); - + iocb->qiov = qiov; + iocb->i = -1; + iocb->j = 0; + ide_issue_trim_cb(iocb, 0); return &iocb->common; } diff --git a/hw/mips_malta.c b/hw/mips_malta.c index 2250e67..771d125 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -743,10 +743,13 @@ static int64_t load_kernel (void) return kernel_entry; } -static void malta_mips_config(CPUMIPSState *env) +static void malta_mips_config(MIPSCPU *cpu) { + CPUMIPSState *env = &cpu->env; + CPUState *cs = CPU(cpu); + env->mvp->CP0_MVPConf0 |= ((smp_cpus - 1) << CP0MVPC0_PVPE) | - ((smp_cpus * env->nr_threads - 1) << CP0MVPC0_PTC); + ((smp_cpus * cs->nr_threads - 1) << CP0MVPC0_PTC); } static void main_cpu_reset(void *opaque) @@ -763,7 +766,7 @@ static void main_cpu_reset(void *opaque) env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL)); } - malta_mips_config(env); + malta_mips_config(cpu); } static void cpu_request_exit(void *opaque, int irq, int level) diff --git a/hw/openpic.c b/hw/openpic.c index 23fa8f9..f6cc07b 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -153,11 +153,14 @@ static const int debug_openpic = 0; static int get_current_cpu(void) { + CPUState *cpu_single_cpu; + if (!cpu_single_env) { return -1; } - return cpu_single_env->cpu_index; + cpu_single_cpu = ENV_GET_CPU(cpu_single_env); + return cpu_single_cpu->cpu_index; } static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr, diff --git a/hw/pc87312.c b/hw/pc87312.c index 6a17afd..38af4c1 100644 --- a/hw/pc87312.c +++ b/hw/pc87312.c @@ -34,10 +34,6 @@ #define REG_FAR 1 #define REG_PTR 2 -#define FER regs[REG_FER] -#define FAR regs[REG_FAR] -#define PTR regs[REG_PTR] - #define FER_PARALLEL_EN 0x01 #define FER_UART1_EN 0x02 #define FER_UART2_EN 0x04 @@ -66,14 +62,14 @@ static inline bool is_parallel_enabled(PC87312State *s) { - return s->FER & FER_PARALLEL_EN; + return s->regs[REG_FER] & FER_PARALLEL_EN; } static const uint32_t parallel_base[] = { 0x378, 0x3bc, 0x278, 0x00 }; static inline uint32_t get_parallel_iobase(PC87312State *s) { - return parallel_base[s->FAR & FAR_PARALLEL_ADDR]; + return parallel_base[s->regs[REG_FAR] & FAR_PARALLEL_ADDR]; } static const uint32_t parallel_irq[] = { 5, 7, 5, 0 }; @@ -81,9 +77,9 @@ static const uint32_t parallel_irq[] = { 5, 7, 5, 0 }; static inline uint32_t get_parallel_irq(PC87312State *s) { int idx; - idx = (s->FAR & FAR_PARALLEL_ADDR); + idx = (s->regs[REG_FAR] & FAR_PARALLEL_ADDR); if (idx == 0) { - return (s->PTR & PTR_IRQ_5_7) ? 7 : 5; + return (s->regs[REG_PTR] & PTR_IRQ_5_7) ? 7 : 5; } else { return parallel_irq[idx]; } @@ -91,7 +87,7 @@ static inline uint32_t get_parallel_irq(PC87312State *s) static inline bool is_parallel_epp(PC87312State *s) { - return s->PTR & PTR_EPP_MODE; + return s->regs[REG_PTR] & PTR_EPP_MODE; } @@ -105,26 +101,26 @@ static const uint32_t uart_base[2][4] = { static inline uint32_t get_uart_iobase(PC87312State *s, int i) { int idx; - idx = (s->FAR >> (2 * i + 2)) & 0x3; + idx = (s->regs[REG_FAR] >> (2 * i + 2)) & 0x3; if (idx == 0) { return 0x3f8; } else if (idx == 1) { return 0x2f8; } else { - return uart_base[idx & 1][(s->FAR & FAR_UART_3_4) >> 6]; + return uart_base[idx & 1][(s->regs[REG_FAR] & FAR_UART_3_4) >> 6]; } } static inline uint32_t get_uart_irq(PC87312State *s, int i) { int idx; - idx = (s->FAR >> (2 * i + 2)) & 0x3; + idx = (s->regs[REG_FAR] >> (2 * i + 2)) & 0x3; return (idx & 1) ? 3 : 4; } static inline bool is_uart_enabled(PC87312State *s, int i) { - return s->FER & (FER_UART1_EN << i); + return s->regs[REG_FER] & (FER_UART1_EN << i); } @@ -132,12 +128,12 @@ static inline bool is_uart_enabled(PC87312State *s, int i) static inline bool is_fdc_enabled(PC87312State *s) { - return s->FER & FER_FDC_EN; + return s->regs[REG_FER] & FER_FDC_EN; } static inline uint32_t get_fdc_iobase(PC87312State *s) { - return (s->FER & FER_FDC_ADDR) ? 0x370 : 0x3f0; + return (s->regs[REG_FER] & FER_FDC_ADDR) ? 0x370 : 0x3f0; } @@ -145,19 +141,19 @@ static inline uint32_t get_fdc_iobase(PC87312State *s) static inline bool is_ide_enabled(PC87312State *s) { - return s->FER & FER_IDE_EN; + return s->regs[REG_FER] & FER_IDE_EN; } static inline uint32_t get_ide_iobase(PC87312State *s) { - return (s->FER & FER_IDE_ADDR) ? 0x170 : 0x1f0; + return (s->regs[REG_FER] & FER_IDE_ADDR) ? 0x170 : 0x1f0; } static void reconfigure_devices(PC87312State *s) { error_report("pc87312: unsupported device reconfiguration (%02x %02x %02x)", - s->FER, s->FAR, s->PTR); + s->regs[REG_FER], s->regs[REG_FAR], s->regs[REG_PTR]); } static void pc87312_soft_reset(PC87312State *s) @@ -184,9 +180,9 @@ static void pc87312_soft_reset(PC87312State *s) s->read_id_step = 0; s->selected_index = REG_FER; - s->FER = fer_init[s->config & 0x1f]; - s->FAR = far_init[s->config & 0x1f]; - s->PTR = ptr_init[s->config & 0x1f]; + s->regs[REG_FER] = fer_init[s->config & 0x1f]; + s->regs[REG_FAR] = far_init[s->config & 0x1f]; + s->regs[REG_PTR] = ptr_init[s->config & 0x1f]; } static void pc87312_hard_reset(PC87312State *s) @@ -194,7 +190,8 @@ static void pc87312_hard_reset(PC87312State *s) pc87312_soft_reset(s); } -static void pc87312_ioport_write(void *opaque, uint32_t addr, uint32_t val) +static void pc87312_io_write(void *opaque, hwaddr addr, uint64_t val, + unsigned int size) { PC87312State *s = opaque; @@ -213,7 +210,7 @@ static void pc87312_ioport_write(void *opaque, uint32_t addr, uint32_t val) } } -static uint32_t pc87312_ioport_read(void *opaque, uint32_t addr) +static uint64_t pc87312_io_read(void *opaque, hwaddr addr, unsigned int size) { PC87312State *s = opaque; uint32_t val; @@ -241,6 +238,16 @@ static uint32_t pc87312_ioport_read(void *opaque, uint32_t addr) return val; } +static const MemoryRegionOps pc87312_io_ops = { + .read = pc87312_io_read, + .write = pc87312_io_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 1, + .max_access_size = 1, + }, +}; + static int pc87312_post_load(void *opaque, int version_id) { PC87312State *s = opaque; @@ -270,6 +277,7 @@ static int pc87312_init(ISADevice *dev) s = PC87312(dev); bus = isa_bus_from_device(dev); pc87312_hard_reset(s); + isa_register_ioport(dev, &s->io, s->iobase); if (is_parallel_enabled(s)) { chr = parallel_hds[0]; @@ -337,11 +345,16 @@ static int pc87312_init(ISADevice *dev) trace_pc87312_info_ide(get_ide_iobase(s)); } - register_ioport_write(s->iobase, 2, 1, pc87312_ioport_write, s); - register_ioport_read(s->iobase, 2, 1, pc87312_ioport_read, s); return 0; } +static void pc87312_initfn(Object *obj) +{ + PC87312State *s = PC87312(obj); + + memory_region_init_io(&s->io, &pc87312_io_ops, s, "pc87312", 2); +} + static const VMStateDescription vmstate_pc87312 = { .name = "pc87312", .version_id = 1, @@ -376,6 +389,7 @@ static const TypeInfo pc87312_type_info = { .name = TYPE_PC87312, .parent = TYPE_ISA_DEVICE, .instance_size = sizeof(PC87312State), + .instance_init = pc87312_initfn, .class_init = pc87312_class_init, }; diff --git a/hw/pc87312.h b/hw/pc87312.h index 7ca7912..7b9e6f6 100644 --- a/hw/pc87312.h +++ b/hw/pc87312.h @@ -56,6 +56,8 @@ typedef struct PC87312State { uint32_t base; } ide; + MemoryRegion io; + uint8_t read_id_step; uint8_t selected_index; diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 3a9e1c7..7b3e2e6 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -239,25 +239,28 @@ static int ppce500_load_device_tree(CPUPPCState *env, /* We need to generate the cpu nodes in reverse order, so Linux can pick the first node as boot node and be happy */ for (i = smp_cpus - 1; i >= 0; i--) { + CPUState *cpu = NULL; char cpu_name[128]; uint64_t cpu_release_addr = MPC8544_SPIN_BASE + (i * 0x20); for (env = first_cpu; env != NULL; env = env->next_cpu) { - if (env->cpu_index == i) { + cpu = ENV_GET_CPU(env); + if (cpu->cpu_index == i) { break; } } - if (!env) { + if (cpu == NULL) { continue; } - snprintf(cpu_name, sizeof(cpu_name), "/cpus/PowerPC,8544@%x", env->cpu_index); + snprintf(cpu_name, sizeof(cpu_name), "/cpus/PowerPC,8544@%x", + cpu->cpu_index); qemu_devtree_add_subnode(fdt, cpu_name); qemu_devtree_setprop_cell(fdt, cpu_name, "clock-frequency", clock_freq); qemu_devtree_setprop_cell(fdt, cpu_name, "timebase-frequency", tb_freq); qemu_devtree_setprop_string(fdt, cpu_name, "device_type", "cpu"); - qemu_devtree_setprop_cell(fdt, cpu_name, "reg", env->cpu_index); + qemu_devtree_setprop_cell(fdt, cpu_name, "reg", cpu->cpu_index); qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-line-size", env->dcache_line_size); qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-line-size", @@ -265,7 +268,7 @@ static int ppce500_load_device_tree(CPUPPCState *env, qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-size", 0x8000); qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-size", 0x8000); qemu_devtree_setprop_cell(fdt, cpu_name, "bus-frequency", 0); - if (env->cpu_index) { + if (cpu->cpu_index) { qemu_devtree_setprop_string(fdt, cpu_name, "status", "disabled"); qemu_devtree_setprop_string(fdt, cpu_name, "enable-method", "spin-table"); qemu_devtree_setprop_u64(fdt, cpu_name, "cpu-release-addr", @@ -479,6 +482,7 @@ void ppce500_init(PPCE500Params *params) irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB); for (i = 0; i < smp_cpus; i++) { PowerPCCPU *cpu; + CPUState *cs; qemu_irq *input; cpu = cpu_ppc_init(params->cpu_model); @@ -487,6 +491,7 @@ void ppce500_init(PPCE500Params *params) exit(1); } env = &cpu->env; + cs = CPU(cpu); if (!firstenv) { firstenv = env; @@ -496,7 +501,7 @@ void ppce500_init(PPCE500Params *params) input = (qemu_irq *)env->irq_inputs; irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT]; irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT]; - env->spr[SPR_BOOKE_PIR] = env->cpu_index = i; + env->spr[SPR_BOOKE_PIR] = cs->cpu_index = i; env->mpic_iack = MPC8544_CCSRBAR_BASE + MPC8544_MPIC_REGS_OFFSET + 0x200A0; diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c index 1b2c34f..4c206e2 100644 --- a/hw/ppce500_spin.c +++ b/hw/ppce500_spin.c @@ -124,21 +124,23 @@ static void spin_write(void *opaque, hwaddr addr, uint64_t value, SpinState *s = opaque; int env_idx = addr / sizeof(SpinInfo); CPUPPCState *env; + CPUState *cpu = NULL; SpinInfo *curspin = &s->spin[env_idx]; uint8_t *curspin_p = (uint8_t*)curspin; for (env = first_cpu; env != NULL; env = env->next_cpu) { - if (env->cpu_index == env_idx) { + cpu = CPU(ppc_env_get_cpu(env)); + if (cpu->cpu_index == env_idx) { break; } } - if (!env) { + if (cpu == NULL) { /* Unknown CPU */ return; } - if (!env->cpu_index) { + if (cpu->cpu_index == 0) { /* primary CPU doesn't spin */ return; } @@ -69,7 +69,7 @@ DeviceState *pxa2xx_pic_init(hwaddr base, ARMCPU *cpu); /* pxa2xx_gpio.c */ DeviceState *pxa2xx_gpio_init(hwaddr base, - CPUARMState *env, DeviceState *pic, int lines); + ARMCPU *cpu, DeviceState *pic, int lines); void pxa2xx_gpio_read_notifier(DeviceState *dev, qemu_irq handler); /* pxa2xx_dma.c */ diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c index f3dffef..492805f 100644 --- a/hw/pxa2xx.c +++ b/hw/pxa2xx.c @@ -2045,7 +2045,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space, qdev_get_gpio_in(s->pic, PXA27X_PIC_OST_4_11), NULL); - s->gpio = pxa2xx_gpio_init(0x40e00000, &s->cpu->env, s->pic, 121); + s->gpio = pxa2xx_gpio_init(0x40e00000, s->cpu, s->pic, 121); dinfo = drive_get(IF_SD, 0, 0); if (!dinfo) { @@ -2176,7 +2176,7 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size) qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 3), NULL); - s->gpio = pxa2xx_gpio_init(0x40e00000, &s->cpu->env, s->pic, 85); + s->gpio = pxa2xx_gpio_init(0x40e00000, s->cpu, s->pic, 85); dinfo = drive_get(IF_SD, 0, 0); if (!dinfo) { diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c index 016833d..eec2ea3 100644 --- a/hw/pxa2xx_gpio.c +++ b/hw/pxa2xx_gpio.c @@ -250,13 +250,14 @@ static const MemoryRegionOps pxa_gpio_ops = { }; DeviceState *pxa2xx_gpio_init(hwaddr base, - CPUARMState *env, DeviceState *pic, int lines) + ARMCPU *cpu, DeviceState *pic, int lines) { + CPUState *cs = CPU(cpu); DeviceState *dev; dev = qdev_create(NULL, "pxa2xx-gpio"); qdev_prop_set_int32(dev, "lines", lines); - qdev_prop_set_int32(dev, "ncpu", env->cpu_index); + qdev_prop_set_int32(dev, "ncpu", cs->cpu_index); qdev_init_nofail(dev); sysbus_mmio_map(sysbus_from_qdev(dev), 0, base); @@ -276,7 +277,7 @@ static int pxa2xx_gpio_initfn(SysBusDevice *dev) s = FROM_SYSBUS(PXA2xxGPIOInfo, dev); - s->cpu = arm_env_get_cpu(qemu_get_cpu(s->ncpu)); + s->cpu = ARM_CPU(qemu_get_cpu(s->ncpu)); qdev_init_gpio_in(&dev->qdev, pxa2xx_gpio_set, s->lines); qdev_init_gpio_out(&dev->qdev, s->handler, s->lines); diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index f8d7ef3..96db9a7 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -85,9 +85,7 @@ static void scsi_free_request(SCSIRequest *req) { SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req); - if (r->iov.iov_base) { - qemu_vfree(r->iov.iov_base); - } + qemu_vfree(r->iov.iov_base); } /* Helper function for command completion with sense. */ @@ -140,6 +140,7 @@ 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(); uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; @@ -147,19 +148,20 @@ 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)); uint32_t associativity[] = {cpu_to_be32(0x5), cpu_to_be32(0x0), cpu_to_be32(0x0), cpu_to_be32(0x0), - cpu_to_be32(env->numa_node), - cpu_to_be32(env->cpu_index)}; + cpu_to_be32(cpu->numa_node), + cpu_to_be32(cpu->cpu_index)}; - if ((env->cpu_index % smt) != 0) { + if ((cpu->cpu_index % smt) != 0) { continue; } snprintf(cpu_model, 32, "/cpus/%s@%x", spapr->cpu_model, - env->cpu_index); + cpu->cpu_index); offset = fdt_path_offset(fdt, cpu_model); if (offset < 0) { @@ -308,7 +310,8 @@ static void *spapr_create_fdt_skel(const char *cpu_model, spapr->cpu_model = g_strdup(modelname); for (env = first_cpu; env != NULL; env = env->next_cpu) { - int index = env->cpu_index; + CPUState *cpu = CPU(ppc_env_get_cpu(env)); + int index = cpu->cpu_index; uint32_t servers_prop[smp_threads]; uint32_t gservers_prop[smp_threads * 2]; char *nodename; diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c index afb1297..2889742 100644 --- a/hw/spapr_hcall.c +++ b/hw/spapr_hcall.c @@ -467,9 +467,11 @@ static target_ulong h_register_vpa(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong vpa = args[2]; target_ulong ret = H_PARAMETER; CPUPPCState *tenv; + CPUState *tcpu; for (tenv = first_cpu; tenv; tenv = tenv->next_cpu) { - if (tenv->cpu_index == procno) { + tcpu = CPU(ppc_env_get_cpu(tenv)); + if (tcpu->cpu_index == procno) { break; } } diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c index 81eecd0..5ec787f 100644 --- a/hw/spapr_rtas.c +++ b/hw/spapr_rtas.c @@ -131,6 +131,7 @@ static void rtas_query_cpu_stopped_state(sPAPREnvironment *spapr, { target_ulong id; CPUPPCState *env; + CPUState *cpu; if (nargs != 1 || nret != 2) { rtas_st(rets, 0, -3); @@ -139,7 +140,8 @@ static void rtas_query_cpu_stopped_state(sPAPREnvironment *spapr, id = rtas_ld(args, 0); for (env = first_cpu; env; env = env->next_cpu) { - if (env->cpu_index != id) { + cpu = CPU(ppc_env_get_cpu(env)); + if (cpu->cpu_index != id) { continue; } @@ -176,9 +178,9 @@ static void rtas_start_cpu(sPAPREnvironment *spapr, r3 = rtas_ld(args, 2); for (env = first_cpu; env; env = env->next_cpu) { - cpu = ENV_GET_CPU(env); + cpu = CPU(ppc_env_get_cpu(env)); - if (env->cpu_index != id) { + if (cpu->cpu_index != id) { continue; } diff --git a/hw/xen_disk.c b/hw/xen_disk.c index a6a64a2..7fea871 100644 --- a/hw/xen_disk.c +++ b/hw/xen_disk.c @@ -51,6 +51,13 @@ static int max_requests = 32; #define BLOCK_SIZE 512 #define IOCB_COUNT (BLKIF_MAX_SEGMENTS_PER_REQUEST + 2) +struct PersistentGrant { + void *page; + struct XenBlkDev *blkdev; +}; + +typedef struct PersistentGrant PersistentGrant; + struct ioreq { blkif_request_t req; int16_t status; @@ -68,6 +75,7 @@ struct ioreq { int prot; void *page[BLKIF_MAX_SEGMENTS_PER_REQUEST]; void *pages; + int num_unmap; /* aio status */ int aio_inflight; @@ -104,6 +112,12 @@ struct XenBlkDev { int requests_inflight; int requests_finished; + /* Persistent grants extension */ + gboolean feature_persistent; + GTree *persistent_gnts; + unsigned int persistent_gnt_count; + unsigned int max_grants; + /* qemu block driver */ DriveInfo *dinfo; BlockDriverState *bs; @@ -112,6 +126,54 @@ struct XenBlkDev { /* ------------------------------------------------------------- */ +static void ioreq_reset(struct ioreq *ioreq) +{ + memset(&ioreq->req, 0, sizeof(ioreq->req)); + ioreq->status = 0; + ioreq->start = 0; + ioreq->presync = 0; + ioreq->postsync = 0; + ioreq->mapped = 0; + + memset(ioreq->domids, 0, sizeof(ioreq->domids)); + memset(ioreq->refs, 0, sizeof(ioreq->refs)); + ioreq->prot = 0; + memset(ioreq->page, 0, sizeof(ioreq->page)); + ioreq->pages = NULL; + + ioreq->aio_inflight = 0; + ioreq->aio_errors = 0; + + ioreq->blkdev = NULL; + memset(&ioreq->list, 0, sizeof(ioreq->list)); + memset(&ioreq->acct, 0, sizeof(ioreq->acct)); + + qemu_iovec_reset(&ioreq->v); +} + +static gint int_cmp(gconstpointer a, gconstpointer b, gpointer user_data) +{ + uint ua = GPOINTER_TO_UINT(a); + uint ub = GPOINTER_TO_UINT(b); + return (ua > ub) - (ua < ub); +} + +static void destroy_grant(gpointer pgnt) +{ + PersistentGrant *grant = pgnt; + XenGnttab gnt = grant->blkdev->xendev.gnttabdev; + + if (xc_gnttab_munmap(gnt, grant->page, 1) != 0) { + xen_be_printf(&grant->blkdev->xendev, 0, + "xc_gnttab_munmap failed: %s\n", + strerror(errno)); + } + grant->blkdev->persistent_gnt_count--; + xen_be_printf(&grant->blkdev->xendev, 3, + "unmapped grant %p\n", grant->page); + g_free(grant); +} + static struct ioreq *ioreq_start(struct XenBlkDev *blkdev) { struct ioreq *ioreq = NULL; @@ -129,7 +191,6 @@ static struct ioreq *ioreq_start(struct XenBlkDev *blkdev) /* get one from freelist */ ioreq = QLIST_FIRST(&blkdev->freelist); QLIST_REMOVE(ioreq, list); - qemu_iovec_reset(&ioreq->v); } QLIST_INSERT_HEAD(&blkdev->inflight, ioreq, list); blkdev->requests_inflight++; @@ -153,7 +214,7 @@ static void ioreq_release(struct ioreq *ioreq, bool finish) struct XenBlkDev *blkdev = ioreq->blkdev; QLIST_REMOVE(ioreq, list); - memset(ioreq, 0, sizeof(*ioreq)); + ioreq_reset(ioreq); ioreq->blkdev = blkdev; QLIST_INSERT_HEAD(&blkdev->freelist, ioreq, list); if (finish) { @@ -182,12 +243,11 @@ static int ioreq_parse(struct ioreq *ioreq) case BLKIF_OP_READ: ioreq->prot = PROT_WRITE; /* to memory */ break; - case BLKIF_OP_WRITE_BARRIER: + case BLKIF_OP_FLUSH_DISKCACHE: + ioreq->presync = 1; if (!ioreq->req.nr_segments) { - ioreq->presync = 1; return 0; } - ioreq->presync = ioreq->postsync = 1; /* fall through */ case BLKIF_OP_WRITE: ioreq->prot = PROT_READ; /* from memory */ @@ -241,21 +301,21 @@ static void ioreq_unmap(struct ioreq *ioreq) XenGnttab gnt = ioreq->blkdev->xendev.gnttabdev; int i; - if (ioreq->v.niov == 0 || ioreq->mapped == 0) { + if (ioreq->num_unmap == 0 || ioreq->mapped == 0) { return; } if (batch_maps) { if (!ioreq->pages) { return; } - if (xc_gnttab_munmap(gnt, ioreq->pages, ioreq->v.niov) != 0) { + if (xc_gnttab_munmap(gnt, ioreq->pages, ioreq->num_unmap) != 0) { xen_be_printf(&ioreq->blkdev->xendev, 0, "xc_gnttab_munmap failed: %s\n", strerror(errno)); } - ioreq->blkdev->cnt_map -= ioreq->v.niov; + ioreq->blkdev->cnt_map -= ioreq->num_unmap; ioreq->pages = NULL; } else { - for (i = 0; i < ioreq->v.niov; i++) { + for (i = 0; i < ioreq->num_unmap; i++) { if (!ioreq->page[i]) { continue; } @@ -273,41 +333,120 @@ static void ioreq_unmap(struct ioreq *ioreq) static int ioreq_map(struct ioreq *ioreq) { XenGnttab gnt = ioreq->blkdev->xendev.gnttabdev; - int i; + uint32_t domids[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + uint32_t refs[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + void *page[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + int i, j, new_maps = 0; + PersistentGrant *grant; + /* domids and refs variables will contain the information necessary + * to map the grants that are needed to fulfill this request. + * + * After mapping the needed grants, the page array will contain the + * memory address of each granted page in the order specified in ioreq + * (disregarding if it's a persistent grant or not). + */ if (ioreq->v.niov == 0 || ioreq->mapped == 1) { return 0; } - if (batch_maps) { + if (ioreq->blkdev->feature_persistent) { + for (i = 0; i < ioreq->v.niov; i++) { + grant = g_tree_lookup(ioreq->blkdev->persistent_gnts, + GUINT_TO_POINTER(ioreq->refs[i])); + + if (grant != NULL) { + page[i] = grant->page; + xen_be_printf(&ioreq->blkdev->xendev, 3, + "using persistent-grant %" PRIu32 "\n", + ioreq->refs[i]); + } else { + /* Add the grant to the list of grants that + * should be mapped + */ + domids[new_maps] = ioreq->domids[i]; + refs[new_maps] = ioreq->refs[i]; + page[i] = NULL; + new_maps++; + } + } + /* Set the protection to RW, since grants may be reused later + * with a different protection than the one needed for this request + */ + ioreq->prot = PROT_WRITE | PROT_READ; + } else { + /* All grants in the request should be mapped */ + memcpy(refs, ioreq->refs, sizeof(refs)); + memcpy(domids, ioreq->domids, sizeof(domids)); + memset(page, 0, sizeof(page)); + new_maps = ioreq->v.niov; + } + + if (batch_maps && new_maps) { ioreq->pages = xc_gnttab_map_grant_refs - (gnt, ioreq->v.niov, ioreq->domids, ioreq->refs, ioreq->prot); + (gnt, new_maps, domids, refs, ioreq->prot); if (ioreq->pages == NULL) { xen_be_printf(&ioreq->blkdev->xendev, 0, "can't map %d grant refs (%s, %d maps)\n", - ioreq->v.niov, strerror(errno), ioreq->blkdev->cnt_map); + new_maps, strerror(errno), ioreq->blkdev->cnt_map); return -1; } - for (i = 0; i < ioreq->v.niov; i++) { - ioreq->v.iov[i].iov_base = ioreq->pages + i * XC_PAGE_SIZE + - (uintptr_t)ioreq->v.iov[i].iov_base; + for (i = 0, j = 0; i < ioreq->v.niov; i++) { + if (page[i] == NULL) { + page[i] = ioreq->pages + (j++) * XC_PAGE_SIZE; + } } - ioreq->blkdev->cnt_map += ioreq->v.niov; - } else { - for (i = 0; i < ioreq->v.niov; i++) { + ioreq->blkdev->cnt_map += new_maps; + } else if (new_maps) { + for (i = 0; i < new_maps; i++) { ioreq->page[i] = xc_gnttab_map_grant_ref - (gnt, ioreq->domids[i], ioreq->refs[i], ioreq->prot); + (gnt, domids[i], refs[i], ioreq->prot); if (ioreq->page[i] == NULL) { xen_be_printf(&ioreq->blkdev->xendev, 0, "can't map grant ref %d (%s, %d maps)\n", - ioreq->refs[i], strerror(errno), ioreq->blkdev->cnt_map); + refs[i], strerror(errno), ioreq->blkdev->cnt_map); ioreq_unmap(ioreq); return -1; } - ioreq->v.iov[i].iov_base = ioreq->page[i] + (uintptr_t)ioreq->v.iov[i].iov_base; ioreq->blkdev->cnt_map++; } + for (i = 0, j = 0; i < ioreq->v.niov; i++) { + if (page[i] == NULL) { + page[i] = ioreq->page[j++]; + } + } + } + if (ioreq->blkdev->feature_persistent) { + while ((ioreq->blkdev->persistent_gnt_count < ioreq->blkdev->max_grants) + && new_maps) { + /* Go through the list of newly mapped grants and add as many + * as possible to the list of persistently mapped grants. + * + * Since we start at the end of ioreq->page(s), we only need + * to decrease new_maps to prevent this granted pages from + * being unmapped in ioreq_unmap. + */ + grant = g_malloc0(sizeof(*grant)); + new_maps--; + if (batch_maps) { + grant->page = ioreq->pages + (new_maps) * XC_PAGE_SIZE; + } else { + grant->page = ioreq->page[new_maps]; + } + grant->blkdev = ioreq->blkdev; + xen_be_printf(&ioreq->blkdev->xendev, 3, + "adding grant %" PRIu32 " page: %p\n", + refs[new_maps], grant->page); + g_tree_insert(ioreq->blkdev->persistent_gnts, + GUINT_TO_POINTER(refs[new_maps]), + grant); + ioreq->blkdev->persistent_gnt_count++; + } + } + for (i = 0; i < ioreq->v.niov; i++) { + ioreq->v.iov[i].iov_base += (uintptr_t)page[i]; } ioreq->mapped = 1; + ioreq->num_unmap = new_maps; return 0; } @@ -369,7 +508,7 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq) qemu_aio_complete, ioreq); break; case BLKIF_OP_WRITE: - case BLKIF_OP_WRITE_BARRIER: + case BLKIF_OP_FLUSH_DISKCACHE: if (!ioreq->req.nr_segments) { break; } @@ -654,7 +793,8 @@ static int blk_init(struct XenDevice *xendev) blkdev->file_size, blkdev->file_size >> 20); /* fill info */ - xenstore_write_be_int(&blkdev->xendev, "feature-barrier", 1); + xenstore_write_be_int(&blkdev->xendev, "feature-flush-cache", 1); + xenstore_write_be_int(&blkdev->xendev, "feature-persistent", 1); xenstore_write_be_int(&blkdev->xendev, "info", info); xenstore_write_be_int(&blkdev->xendev, "sector-size", blkdev->file_blk); xenstore_write_be_int(&blkdev->xendev, "sectors", @@ -678,6 +818,7 @@ out_error: static int blk_connect(struct XenDevice *xendev) { struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); + int pers; if (xenstore_read_fe_int(&blkdev->xendev, "ring-ref", &blkdev->ring_ref) == -1) { return -1; @@ -686,6 +827,11 @@ static int blk_connect(struct XenDevice *xendev) &blkdev->xendev.remote_port) == -1) { return -1; } + if (xenstore_read_fe_int(&blkdev->xendev, "feature-persistent", &pers)) { + blkdev->feature_persistent = FALSE; + } else { + blkdev->feature_persistent = !!pers; + } blkdev->protocol = BLKIF_PROTOCOL_NATIVE; if (blkdev->xendev.protocol) { @@ -729,6 +875,15 @@ static int blk_connect(struct XenDevice *xendev) } } + if (blkdev->feature_persistent) { + /* Init persistent grants */ + blkdev->max_grants = max_requests * BLKIF_MAX_SEGMENTS_PER_REQUEST; + blkdev->persistent_gnts = g_tree_new_full((GCompareDataFunc)int_cmp, + NULL, NULL, + (GDestroyNotify)destroy_grant); + blkdev->persistent_gnt_count = 0; + } + xen_be_bind_evtchn(&blkdev->xendev); xen_be_printf(&blkdev->xendev, 1, "ok: proto %s, ring-ref %d, " @@ -769,6 +924,11 @@ static int blk_free(struct XenDevice *xendev) blk_disconnect(xendev); } + /* Free persistent grants */ + if (blkdev->feature_persistent) { + g_tree_destroy(blkdev->persistent_gnts); + } + while (!QLIST_EMPTY(&blkdev->freelist)) { ioreq = QLIST_FIRST(&blkdev->freelist); QLIST_REMOVE(ioreq, list); @@ -357,10 +357,10 @@ void xics_set_irq_type(struct icp_state *icp, int irq, bool lsi) static target_ulong h_cppr(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { - CPUPPCState *env = &cpu->env; + CPUState *cs = CPU(cpu); target_ulong cppr = args[0]; - icp_set_cppr(spapr->icp, env->cpu_index, cppr); + icp_set_cppr(spapr->icp, cs->cpu_index, cppr); return H_SUCCESS; } @@ -376,14 +376,13 @@ static target_ulong h_ipi(PowerPCCPU *cpu, sPAPREnvironment *spapr, 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) { - CPUPPCState *env = &cpu->env; - uint32_t xirr = icp_accept(spapr->icp->ss + env->cpu_index); + CPUState *cs = CPU(cpu); + uint32_t xirr = icp_accept(spapr->icp->ss + cs->cpu_index); args[0] = xirr; return H_SUCCESS; @@ -392,10 +391,10 @@ static target_ulong h_xirr(PowerPCCPU *cpu, sPAPREnvironment *spapr, static target_ulong h_eoi(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { - CPUPPCState *env = &cpu->env; + CPUState *cs = CPU(cpu); target_ulong xirr = args[0]; - icp_eoi(spapr->icp, env->cpu_index, xirr); + icp_eoi(spapr->icp, cs->cpu_index, xirr); return H_SUCCESS; } @@ -525,14 +524,16 @@ static void xics_reset(void *opaque) struct icp_state *xics_system_init(int nr_irqs) { CPUPPCState *env; + CPUState *cpu; int max_server_num; struct icp_state *icp; struct ics_state *ics; max_server_num = -1; for (env = first_cpu; env != NULL; env = env->next_cpu) { - if (env->cpu_index > max_server_num) { - max_server_num = env->cpu_index; + cpu = CPU(ppc_env_get_cpu(env)); + if (cpu->cpu_index > max_server_num) { + max_server_num = cpu->cpu_index; } } @@ -541,7 +542,8 @@ struct icp_state *xics_system_init(int nr_irqs) icp->ss = g_malloc0(icp->nr_servers*sizeof(struct icp_server_state)); for (env = first_cpu; env != NULL; env = env->next_cpu) { - struct icp_server_state *ss = &icp->ss[env->cpu_index]; + cpu = CPU(ppc_env_get_cpu(env)); + struct icp_server_state *ss = &icp->ss[cpu->cpu_index]; switch (PPC_INPUT(env)) { case PPC_FLAGS_INPUT_POWER7: |