mirror of https://github.com/xemu-project/xemu.git
hw/intc/loongarch_extioi: Add vmstate post_load support
There are elements sw_ipmap and sw_coremap, which is usd to speed up irq injection flow. They are saved and restored in vmstate during migration, indeed they can calculated from hw registers. Here post_load is added for get sw_ipmap and sw_coremap from extioi hw state. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Song Gao <gaosong@loongson.cn> Message-Id: <20231215100333.3933632-5-maobibo@loongson.cn> Signed-off-by: Song Gao <gaosong@loongson.cn>
This commit is contained in:
parent
10a8f7d25a
commit
428a6ef439
|
@ -130,12 +130,66 @@ static inline void extioi_enable_irq(LoongArchExtIOI *s, int index,\
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void extioi_update_sw_coremap(LoongArchExtIOI *s, int irq,
|
||||||
|
uint64_t val, bool notify)
|
||||||
|
{
|
||||||
|
int i, cpu;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* loongarch only support little endian,
|
||||||
|
* so we paresd the value with little endian.
|
||||||
|
*/
|
||||||
|
val = cpu_to_le64(val);
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
cpu = val & 0xff;
|
||||||
|
cpu = ctz32(cpu);
|
||||||
|
cpu = (cpu >= 4) ? 0 : cpu;
|
||||||
|
val = val >> 8;
|
||||||
|
|
||||||
|
if (s->sw_coremap[irq + i] == cpu) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notify && test_bit(irq, (unsigned long *)s->isr)) {
|
||||||
|
/*
|
||||||
|
* lower irq at old cpu and raise irq at new cpu
|
||||||
|
*/
|
||||||
|
extioi_update_irq(s, irq + i, 0);
|
||||||
|
s->sw_coremap[irq + i] = cpu;
|
||||||
|
extioi_update_irq(s, irq + i, 1);
|
||||||
|
} else {
|
||||||
|
s->sw_coremap[irq + i] = cpu;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void extioi_update_sw_ipmap(LoongArchExtIOI *s, int index,
|
||||||
|
uint64_t val)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint8_t ipnum;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* loongarch only support little endian,
|
||||||
|
* so we paresd the value with little endian.
|
||||||
|
*/
|
||||||
|
val = cpu_to_le64(val);
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
ipnum = val & 0xff;
|
||||||
|
ipnum = ctz32(ipnum);
|
||||||
|
ipnum = (ipnum >= 4) ? 0 : ipnum;
|
||||||
|
s->sw_ipmap[index * 4 + i] = ipnum;
|
||||||
|
val = val >> 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static MemTxResult extioi_writew(void *opaque, hwaddr addr,
|
static MemTxResult extioi_writew(void *opaque, hwaddr addr,
|
||||||
uint64_t val, unsigned size,
|
uint64_t val, unsigned size,
|
||||||
MemTxAttrs attrs)
|
MemTxAttrs attrs)
|
||||||
{
|
{
|
||||||
LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
|
LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
|
||||||
int i, cpu, index, old_data, irq;
|
int cpu, index, old_data, irq;
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
|
|
||||||
trace_loongarch_extioi_writew(addr, val);
|
trace_loongarch_extioi_writew(addr, val);
|
||||||
|
@ -153,20 +207,7 @@ static MemTxResult extioi_writew(void *opaque, hwaddr addr,
|
||||||
*/
|
*/
|
||||||
index = (offset - EXTIOI_IPMAP_START) >> 2;
|
index = (offset - EXTIOI_IPMAP_START) >> 2;
|
||||||
s->ipmap[index] = val;
|
s->ipmap[index] = val;
|
||||||
/*
|
extioi_update_sw_ipmap(s, index, val);
|
||||||
* loongarch only support little endian,
|
|
||||||
* so we paresd the value with little endian.
|
|
||||||
*/
|
|
||||||
val = cpu_to_le64(val);
|
|
||||||
for (i = 0; i < 4; i++) {
|
|
||||||
uint8_t ipnum;
|
|
||||||
ipnum = val & 0xff;
|
|
||||||
ipnum = ctz32(ipnum);
|
|
||||||
ipnum = (ipnum >= 4) ? 0 : ipnum;
|
|
||||||
s->sw_ipmap[index * 4 + i] = ipnum;
|
|
||||||
val = val >> 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case EXTIOI_ENABLE_START ... EXTIOI_ENABLE_END - 1:
|
case EXTIOI_ENABLE_START ... EXTIOI_ENABLE_END - 1:
|
||||||
index = (offset - EXTIOI_ENABLE_START) >> 2;
|
index = (offset - EXTIOI_ENABLE_START) >> 2;
|
||||||
|
@ -205,33 +246,8 @@ static MemTxResult extioi_writew(void *opaque, hwaddr addr,
|
||||||
irq = offset - EXTIOI_COREMAP_START;
|
irq = offset - EXTIOI_COREMAP_START;
|
||||||
index = irq / 4;
|
index = irq / 4;
|
||||||
s->coremap[index] = val;
|
s->coremap[index] = val;
|
||||||
/*
|
|
||||||
* loongarch only support little endian,
|
|
||||||
* so we paresd the value with little endian.
|
|
||||||
*/
|
|
||||||
val = cpu_to_le64(val);
|
|
||||||
|
|
||||||
for (i = 0; i < 4; i++) {
|
extioi_update_sw_coremap(s, irq, val, true);
|
||||||
cpu = val & 0xff;
|
|
||||||
cpu = ctz32(cpu);
|
|
||||||
cpu = (cpu >= 4) ? 0 : cpu;
|
|
||||||
val = val >> 8;
|
|
||||||
|
|
||||||
if (s->sw_coremap[irq + i] == cpu) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (test_bit(irq, (unsigned long *)s->isr)) {
|
|
||||||
/*
|
|
||||||
* lower irq at old cpu and raise irq at new cpu
|
|
||||||
*/
|
|
||||||
extioi_update_irq(s, irq + i, 0);
|
|
||||||
s->sw_coremap[irq + i] = cpu;
|
|
||||||
extioi_update_irq(s, irq + i, 1);
|
|
||||||
} else {
|
|
||||||
s->sw_coremap[irq + i] = cpu;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -288,6 +304,23 @@ static void loongarch_extioi_finalize(Object *obj)
|
||||||
g_free(s->cpu);
|
g_free(s->cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int vmstate_extioi_post_load(void *opaque, int version_id)
|
||||||
|
{
|
||||||
|
LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
|
||||||
|
int i, start_irq;
|
||||||
|
|
||||||
|
for (i = 0; i < (EXTIOI_IRQS / 4); i++) {
|
||||||
|
start_irq = i * 4;
|
||||||
|
extioi_update_sw_coremap(s, start_irq, s->coremap[i], false);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < (EXTIOI_IRQS_IPMAP_SIZE / 4); i++) {
|
||||||
|
extioi_update_sw_ipmap(s, i, s->ipmap[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const VMStateDescription vmstate_extioi_core = {
|
static const VMStateDescription vmstate_extioi_core = {
|
||||||
.name = "extioi-core",
|
.name = "extioi-core",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
|
@ -302,6 +335,7 @@ static const VMStateDescription vmstate_loongarch_extioi = {
|
||||||
.name = TYPE_LOONGARCH_EXTIOI,
|
.name = TYPE_LOONGARCH_EXTIOI,
|
||||||
.version_id = 2,
|
.version_id = 2,
|
||||||
.minimum_version_id = 2,
|
.minimum_version_id = 2,
|
||||||
|
.post_load = vmstate_extioi_post_load,
|
||||||
.fields = (const VMStateField[]) {
|
.fields = (const VMStateField[]) {
|
||||||
VMSTATE_UINT32_ARRAY(bounce, LoongArchExtIOI, EXTIOI_IRQS_GROUP_COUNT),
|
VMSTATE_UINT32_ARRAY(bounce, LoongArchExtIOI, EXTIOI_IRQS_GROUP_COUNT),
|
||||||
VMSTATE_UINT32_ARRAY(nodetype, LoongArchExtIOI,
|
VMSTATE_UINT32_ARRAY(nodetype, LoongArchExtIOI,
|
||||||
|
@ -310,8 +344,6 @@ static const VMStateDescription vmstate_loongarch_extioi = {
|
||||||
VMSTATE_UINT32_ARRAY(isr, LoongArchExtIOI, EXTIOI_IRQS / 32),
|
VMSTATE_UINT32_ARRAY(isr, LoongArchExtIOI, EXTIOI_IRQS / 32),
|
||||||
VMSTATE_UINT32_ARRAY(ipmap, LoongArchExtIOI, EXTIOI_IRQS_IPMAP_SIZE / 4),
|
VMSTATE_UINT32_ARRAY(ipmap, LoongArchExtIOI, EXTIOI_IRQS_IPMAP_SIZE / 4),
|
||||||
VMSTATE_UINT32_ARRAY(coremap, LoongArchExtIOI, EXTIOI_IRQS / 4),
|
VMSTATE_UINT32_ARRAY(coremap, LoongArchExtIOI, EXTIOI_IRQS / 4),
|
||||||
VMSTATE_UINT8_ARRAY(sw_ipmap, LoongArchExtIOI, EXTIOI_IRQS_IPMAP_SIZE),
|
|
||||||
VMSTATE_UINT8_ARRAY(sw_coremap, LoongArchExtIOI, EXTIOI_IRQS),
|
|
||||||
|
|
||||||
VMSTATE_STRUCT_VARRAY_POINTER_UINT32(cpu, LoongArchExtIOI, num_cpu,
|
VMSTATE_STRUCT_VARRAY_POINTER_UINT32(cpu, LoongArchExtIOI, num_cpu,
|
||||||
vmstate_extioi_core, ExtIOICore),
|
vmstate_extioi_core, ExtIOICore),
|
||||||
|
|
Loading…
Reference in New Issue