aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/alpha_typhoon.c4
-rw-r--r--hw/arm_gic.c3
-rw-r--r--hw/arm_mptimer.c8
-rw-r--r--hw/ide/core.c79
-rw-r--r--hw/mips_malta.c9
-rw-r--r--hw/openpic.c5
-rw-r--r--hw/pc87312.c64
-rw-r--r--hw/pc87312.h2
-rw-r--r--hw/ppc/e500.c17
-rw-r--r--hw/ppce500_spin.c8
-rw-r--r--hw/pxa.h2
-rw-r--r--hw/pxa2xx.c4
-rw-r--r--hw/pxa2xx_gpio.c7
-rw-r--r--hw/scsi-disk.c4
-rw-r--r--hw/spapr.c13
-rw-r--r--hw/spapr_hcall.c4
-rw-r--r--hw/spapr_rtas.c8
-rw-r--r--hw/xen_disk.c208
-rw-r--r--hw/xics.c22
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;
}
diff --git a/hw/pxa.h b/hw/pxa.h
index c2577d1..668232c 100644
--- a/hw/pxa.h
+++ b/hw/pxa.h
@@ -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. */
diff --git a/hw/spapr.c b/hw/spapr.c
index b5e15b8..76aa09b 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -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);
diff --git a/hw/xics.c b/hw/xics.c
index 55899ce..9ef0d61 100644
--- a/hw/xics.c
+++ b/hw/xics.c
@@ -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: