From aa941b944500bf77f0bdbfa0a7112b4e89670ff1 Mon Sep 17 00:00:00 2001 From: balrog Date: Thu, 24 May 2007 18:50:09 +0000 Subject: [PATCH] Savevm/loadvm bits for ARM core, the PXA2xx peripherals and Spitz hardware. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2857 c046a42c-6fe2-441c-8c8c-71466251a162 --- ecc.h | 17 +++ hw/ads7846.c | 37 +++++- hw/i2c.c | 31 +++++ hw/i2c.h | 4 + hw/ide.c | 157 ++++++++++++++++------- hw/max111x.c | 37 ++++++ hw/max7310.c | 38 ++++++ hw/nand.c | 47 +++++++ hw/pxa2xx.c | 315 ++++++++++++++++++++++++++++++++++++++++++++-- hw/pxa2xx_dma.c | 57 +++++++++ hw/pxa2xx_gpio.c | 48 +++++++ hw/pxa2xx_lcd.c | 79 ++++++++++++ hw/pxa2xx_mmci.c | 81 ++++++++++++ hw/pxa2xx_pic.c | 37 ++++++ hw/pxa2xx_timer.c | 71 +++++++++++ hw/spitz.c | 115 +++++++++++++++++ hw/wm8750.c | 89 +++++++++++++ vl.c | 133 +++++++++++++++++++- 18 files changed, 1330 insertions(+), 63 deletions(-) diff --git a/ecc.h b/ecc.h index 11e6d0113b..e8e39426f5 100644 --- a/ecc.h +++ b/ecc.h @@ -75,3 +75,20 @@ static inline void ecc_reset(struct ecc_state_s *s) s->cp = 0x00; s->count = 0; } + +/* Save/restore */ +static inline void ecc_put(QEMUFile *f, struct ecc_state_s *s) +{ + qemu_put_8s(f, &s->cp); + qemu_put_be16s(f, &s->lp[0]); + qemu_put_be16s(f, &s->lp[1]); + qemu_put_be16s(f, &s->count); +} + +static inline void ecc_get(QEMUFile *f, struct ecc_state_s *s) +{ + qemu_get_8s(f, &s->cp); + qemu_get_be16s(f, &s->lp[0]); + qemu_get_be16s(f, &s->lp[1]); + qemu_get_be16s(f, &s->count); +} diff --git a/hw/ads7846.c b/hw/ads7846.c index d63a915419..8eeb143b11 100644 --- a/hw/ads7846.c +++ b/hw/ads7846.c @@ -104,10 +104,41 @@ static void ads7846_ts_event(void *opaque, if (s->pressure == !buttons_state) { s->pressure = !!buttons_state; - ads7846_int_update(s); + ads7846_int_update(s); } } +static void ads7846_save(QEMUFile *f, void *opaque) +{ + struct ads7846_state_s *s = (struct ads7846_state_s *) opaque; + int i; + + for (i = 0; i < 8; i ++) + qemu_put_be32(f, s->input[i]); + qemu_put_be32(f, s->noise); + qemu_put_be32(f, s->cycle); + qemu_put_be32(f, s->output); +} + +static int ads7846_load(QEMUFile *f, void *opaque, int version_id) +{ + struct ads7846_state_s *s = (struct ads7846_state_s *) opaque; + int i; + + for (i = 0; i < 8; i ++) + s->input[i] = qemu_get_be32(f); + s->noise = qemu_get_be32(f); + s->cycle = qemu_get_be32(f); + s->output = qemu_get_be32(f); + + s->pressure = 0; + ads7846_int_update(s); + + return 0; +} + +static int ads7846_iid = 0; + struct ads7846_state_s *ads7846_init(qemu_irq penirq) { struct ads7846_state_s *s; @@ -127,5 +158,9 @@ struct ads7846_state_s *ads7846_init(qemu_irq penirq) "QEMU ADS7846-driven Touchscreen"); ads7846_int_update(s); + + register_savevm("ads7846", ads7846_iid ++, 0, + ads7846_save, ads7846_load, s); + return s; } diff --git a/hw/i2c.c b/hw/i2c.c index 5d9319da4c..3fc0733321 100644 --- a/hw/i2c.c +++ b/hw/i2c.c @@ -115,3 +115,34 @@ void i2c_nack(i2c_bus *bus) dev->event(dev, I2C_NACK); } +void i2c_bus_save(QEMUFile *f, i2c_bus *bus) +{ + qemu_put_byte(f, bus->current_dev ? bus->current_dev->address : 0x00); +} + +void i2c_bus_load(QEMUFile *f, i2c_bus *bus) +{ + i2c_slave *dev; + uint8_t address = qemu_get_byte(f); + + if (address) { + for (dev = bus->dev; dev; dev = dev->next) + if (dev->address == address) { + bus->current_dev = dev; + return; + } + + fprintf(stderr, "%s: I2C slave with address %02x disappeared\n", + __FUNCTION__, address); + } +} + +void i2c_slave_save(QEMUFile *f, i2c_slave *dev) +{ + qemu_put_byte(f, dev->address); +} + +void i2c_slave_load(QEMUFile *f, i2c_slave *dev) +{ + dev->address = qemu_get_byte(f); +} diff --git a/hw/i2c.h b/hw/i2c.h index dec45e5520..17e52e7e80 100644 --- a/hw/i2c.h +++ b/hw/i2c.h @@ -45,6 +45,10 @@ void i2c_end_transfer(i2c_bus *bus); void i2c_nack(i2c_bus *bus); int i2c_send(i2c_bus *bus, uint8_t data); int i2c_recv(i2c_bus *bus); +void i2c_bus_save(QEMUFile *f, i2c_bus *bus); +void i2c_bus_load(QEMUFile *f, i2c_bus *bus); +void i2c_slave_save(QEMUFile *f, i2c_slave *dev); +void i2c_slave_load(QEMUFile *f, i2c_slave *dev); /* max7310.c */ i2c_slave *max7310_init(i2c_bus *bus); diff --git a/hw/ide.c b/hw/ide.c index a1aebc9942..03875ce9ae 100644 --- a/hw/ide.c +++ b/hw/ide.c @@ -2416,6 +2416,62 @@ static void ide_init_ioport(IDEState *ide_state, int iobase, int iobase2) register_ioport_read(iobase, 4, 4, ide_data_readl, ide_state); } +/* save per IDE drive data */ +static void ide_save(QEMUFile* f, IDEState *s) +{ + qemu_put_be32s(f, &s->mult_sectors); + qemu_put_be32s(f, &s->identify_set); + if (s->identify_set) { + qemu_put_buffer(f, (const uint8_t *)s->identify_data, 512); + } + qemu_put_8s(f, &s->feature); + qemu_put_8s(f, &s->error); + qemu_put_be32s(f, &s->nsector); + qemu_put_8s(f, &s->sector); + qemu_put_8s(f, &s->lcyl); + qemu_put_8s(f, &s->hcyl); + qemu_put_8s(f, &s->hob_feature); + qemu_put_8s(f, &s->hob_nsector); + qemu_put_8s(f, &s->hob_sector); + qemu_put_8s(f, &s->hob_lcyl); + qemu_put_8s(f, &s->hob_hcyl); + qemu_put_8s(f, &s->select); + qemu_put_8s(f, &s->status); + qemu_put_8s(f, &s->lba48); + + qemu_put_8s(f, &s->sense_key); + qemu_put_8s(f, &s->asc); + /* XXX: if a transfer is pending, we do not save it yet */ +} + +/* load per IDE drive data */ +static void ide_load(QEMUFile* f, IDEState *s) +{ + qemu_get_be32s(f, &s->mult_sectors); + qemu_get_be32s(f, &s->identify_set); + if (s->identify_set) { + qemu_get_buffer(f, (uint8_t *)s->identify_data, 512); + } + qemu_get_8s(f, &s->feature); + qemu_get_8s(f, &s->error); + qemu_get_be32s(f, &s->nsector); + qemu_get_8s(f, &s->sector); + qemu_get_8s(f, &s->lcyl); + qemu_get_8s(f, &s->hcyl); + qemu_get_8s(f, &s->hob_feature); + qemu_get_8s(f, &s->hob_nsector); + qemu_get_8s(f, &s->hob_sector); + qemu_get_8s(f, &s->hob_lcyl); + qemu_get_8s(f, &s->hob_hcyl); + qemu_get_8s(f, &s->select); + qemu_get_8s(f, &s->status); + qemu_get_8s(f, &s->lba48); + + qemu_get_8s(f, &s->sense_key); + qemu_get_8s(f, &s->asc); + /* XXX: if a transfer is pending, we do not save it yet */ +} + /***********************************************************/ /* ISA IDE definitions */ @@ -2731,30 +2787,7 @@ static void pci_ide_save(QEMUFile* f, void *opaque) /* per IDE drive data */ for(i = 0; i < 4; i++) { - IDEState *s = &d->ide_if[i]; - qemu_put_be32s(f, &s->mult_sectors); - qemu_put_be32s(f, &s->identify_set); - if (s->identify_set) { - qemu_put_buffer(f, (const uint8_t *)s->identify_data, 512); - } - qemu_put_8s(f, &s->feature); - qemu_put_8s(f, &s->error); - qemu_put_be32s(f, &s->nsector); - qemu_put_8s(f, &s->sector); - qemu_put_8s(f, &s->lcyl); - qemu_put_8s(f, &s->hcyl); - qemu_put_8s(f, &s->hob_feature); - qemu_put_8s(f, &s->hob_nsector); - qemu_put_8s(f, &s->hob_sector); - qemu_put_8s(f, &s->hob_lcyl); - qemu_put_8s(f, &s->hob_hcyl); - qemu_put_8s(f, &s->select); - qemu_put_8s(f, &s->status); - qemu_put_8s(f, &s->lba48); - - qemu_put_8s(f, &s->sense_key); - qemu_put_8s(f, &s->asc); - /* XXX: if a transfer is pending, we do not save it yet */ + ide_save(f, &d->ide_if[i]); } } @@ -2788,30 +2821,7 @@ static int pci_ide_load(QEMUFile* f, void *opaque, int version_id) /* per IDE drive data */ for(i = 0; i < 4; i++) { - IDEState *s = &d->ide_if[i]; - qemu_get_be32s(f, &s->mult_sectors); - qemu_get_be32s(f, &s->identify_set); - if (s->identify_set) { - qemu_get_buffer(f, (uint8_t *)s->identify_data, 512); - } - qemu_get_8s(f, &s->feature); - qemu_get_8s(f, &s->error); - qemu_get_be32s(f, &s->nsector); - qemu_get_8s(f, &s->sector); - qemu_get_8s(f, &s->lcyl); - qemu_get_8s(f, &s->hcyl); - qemu_get_8s(f, &s->hob_feature); - qemu_get_8s(f, &s->hob_nsector); - qemu_get_8s(f, &s->hob_sector); - qemu_get_8s(f, &s->hob_lcyl); - qemu_get_8s(f, &s->hob_hcyl); - qemu_get_8s(f, &s->select); - qemu_get_8s(f, &s->status); - qemu_get_8s(f, &s->lba48); - - qemu_get_8s(f, &s->sense_key); - qemu_get_8s(f, &s->asc); - /* XXX: if a transfer is pending, we do not save it yet */ + ide_load(f, &d->ide_if[i]); } return 0; } @@ -3255,6 +3265,54 @@ static void md_common_write(void *opaque, uint32_t at, uint16_t value) } } +static void md_save(QEMUFile *f, void *opaque) +{ + struct md_s *s = (struct md_s *) opaque; + int i; + uint8_t drive1_selected; + + qemu_put_8s(f, &s->opt); + qemu_put_8s(f, &s->stat); + qemu_put_8s(f, &s->pins); + + qemu_put_8s(f, &s->ctrl); + qemu_put_be16s(f, &s->io); + qemu_put_byte(f, s->cycle); + + drive1_selected = (s->ide->cur_drive != s->ide); + qemu_put_8s(f, &s->ide->cmd); + qemu_put_8s(f, &drive1_selected); + + for (i = 0; i < 2; i ++) + ide_save(f, &s->ide[i]); +} + +static int md_load(QEMUFile *f, void *opaque, int version_id) +{ + struct md_s *s = (struct md_s *) opaque; + int i; + uint8_t drive1_selected; + + qemu_get_8s(f, &s->opt); + qemu_get_8s(f, &s->stat); + qemu_get_8s(f, &s->pins); + + qemu_get_8s(f, &s->ctrl); + qemu_get_be16s(f, &s->io); + s->cycle = qemu_get_byte(f); + + qemu_get_8s(f, &s->ide->cmd); + qemu_get_8s(f, &drive1_selected); + s->ide->cur_drive = &s->ide[(drive1_selected != 0)]; + + for (i = 0; i < 2; i ++) + ide_load(f, &s->ide[i]); + + return 0; +} + +static int md_iid = 0; + static const uint8_t dscm1xxxx_cis[0x14a] = { [0x000] = CISTPL_DEVICE, /* 5V Device Information */ [0x002] = 0x03, /* Tuple length = 4 bytes */ @@ -3480,5 +3538,8 @@ struct pcmcia_card_s *dscm1xxxx_init(BlockDriverState *bdrv) md->ide->is_cf = 1; md->ide->mdata_size = METADATA_SIZE; md->ide->mdata_storage = (uint8_t *) qemu_mallocz(METADATA_SIZE); + + register_savevm("microdrive", md_iid ++, 0, md_save, md_load, md); + return &md->card; } diff --git a/hw/max111x.c b/hw/max111x.c index 69019de7a2..8425bee576 100644 --- a/hw/max111x.c +++ b/hw/max111x.c @@ -89,6 +89,39 @@ void max111x_write(void *opaque, uint32_t value) qemu_irq_raise(s->interrupt); } +static void max111x_save(QEMUFile *f, void *opaque) +{ + struct max111x_s *s = (struct max111x_s *) opaque; + int i; + + qemu_put_8s(f, &s->tb1); + qemu_put_8s(f, &s->rb2); + qemu_put_8s(f, &s->rb3); + qemu_put_be32(f, s->inputs); + qemu_put_be32(f, s->com); + for (i = 0; i < s->inputs; i ++) + qemu_put_byte(f, s->input[i]); +} + +static int max111x_load(QEMUFile *f, void *opaque, int version_id) +{ + struct max111x_s *s = (struct max111x_s *) opaque; + int i; + + qemu_get_8s(f, &s->tb1); + qemu_get_8s(f, &s->rb2); + qemu_get_8s(f, &s->rb3); + if (s->inputs != qemu_get_be32(f)) + return -EINVAL; + s->com = qemu_get_be32(f); + for (i = 0; i < s->inputs; i ++) + s->input[i] = qemu_get_byte(f); + + return 0; +} + +static int max111x_iid = 0; + static struct max111x_s *max111x_init(qemu_irq cb) { struct max111x_s *s; @@ -108,6 +141,10 @@ static struct max111x_s *max111x_init(qemu_irq cb) s->input[6] = 0x90; s->input[7] = 0x80; s->com = 0; + + register_savevm("max111x", max111x_iid ++, 0, + max111x_save, max111x_load, s); + return s; } diff --git a/hw/max7310.c b/hw/max7310.c index a4aaf17d29..6b180d9b6d 100644 --- a/hw/max7310.c +++ b/hw/max7310.c @@ -143,6 +143,41 @@ static void max7310_event(i2c_slave *i2c, enum i2c_event event) } } +static void max7310_save(QEMUFile *f, void *opaque) +{ + struct max7310_s *s = (struct max7310_s *) opaque; + + qemu_put_be32(f, s->i2c_command_byte); + qemu_put_be32(f, s->len); + + qemu_put_8s(f, &s->level); + qemu_put_8s(f, &s->direction); + qemu_put_8s(f, &s->polarity); + qemu_put_8s(f, &s->status); + qemu_put_8s(f, &s->command); + + i2c_slave_save(f, &s->i2c); +} + +static int max7310_load(QEMUFile *f, void *opaque, int version_id) +{ + struct max7310_s *s = (struct max7310_s *) opaque; + + s->i2c_command_byte = qemu_get_be32(f); + s->len = qemu_get_be32(f); + + qemu_get_8s(f, &s->level); + qemu_get_8s(f, &s->direction); + qemu_get_8s(f, &s->polarity); + qemu_get_8s(f, &s->status); + qemu_get_8s(f, &s->command); + + i2c_slave_load(f, &s->i2c); + return 0; +} + +static int max7310_iid = 0; + static void max7310_gpio_set(void *opaque, int line, int level) { struct max7310_s *s = (struct max7310_s *) opaque; @@ -169,6 +204,9 @@ struct i2c_slave *max7310_init(i2c_bus *bus) max7310_reset(&s->i2c); + register_savevm("max7310", max7310_iid ++, 0, + max7310_save, max7310_load, s); + return &s->i2c; } diff --git a/hw/nand.c b/hw/nand.c index 5bce250526..8e39acd6e6 100644 --- a/hw/nand.c +++ b/hw/nand.c @@ -273,6 +273,50 @@ static void nand_command(struct nand_flash_s *s) } } +static void nand_save(QEMUFile *f, void *opaque) +{ + struct nand_flash_s *s = (struct nand_flash_s *) opaque; + qemu_put_byte(f, s->cle); + qemu_put_byte(f, s->ale); + qemu_put_byte(f, s->ce); + qemu_put_byte(f, s->wp); + qemu_put_byte(f, s->gnd); + qemu_put_buffer(f, s->io, sizeof(s->io)); + qemu_put_be32(f, s->ioaddr - s->io); + qemu_put_be32(f, s->iolen); + + qemu_put_be32s(f, &s->cmd); + qemu_put_be32s(f, &s->addr); + qemu_put_be32(f, s->addrlen); + qemu_put_be32(f, s->status); + qemu_put_be32(f, s->offset); + /* XXX: do we want to save s->storage too? */ +} + +static int nand_load(QEMUFile *f, void *opaque, int version_id) +{ + struct nand_flash_s *s = (struct nand_flash_s *) opaque; + s->cle = qemu_get_byte(f); + s->ale = qemu_get_byte(f); + s->ce = qemu_get_byte(f); + s->wp = qemu_get_byte(f); + s->gnd = qemu_get_byte(f); + qemu_get_buffer(f, s->io, sizeof(s->io)); + s->ioaddr = s->io + qemu_get_be32(f); + s->iolen = qemu_get_be32(f); + if (s->ioaddr >= s->io + sizeof(s->io) || s->ioaddr < s->io) + return -EINVAL; + + qemu_get_be32s(f, &s->cmd); + qemu_get_be32s(f, &s->addr); + s->addrlen = qemu_get_be32(f); + s->status = qemu_get_be32(f); + s->offset = qemu_get_be32(f); + return 0; +} + +static int nand_iid = 0; + /* * Chip inputs are CLE, ALE, CE, WP, GND and eight I/O pins. Chip * outputs are R/B and eight I/O pins. @@ -443,6 +487,9 @@ struct nand_flash_s *nand_init(int manf_id, int chip_id) if (pagesize) s->storage = (uint8_t *) memset(qemu_malloc(s->pages * pagesize), 0xff, s->pages * pagesize); + + register_savevm("nand", nand_iid ++, 0, nand_save, nand_load, s); + return s; } diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c index 03f4b47316..087acd0afd 100644 --- a/hw/pxa2xx.c +++ b/hw/pxa2xx.c @@ -141,6 +141,26 @@ static CPUWriteMemoryFunc *pxa2xx_pm_writefn[] = { pxa2xx_pm_write, }; +static void pxa2xx_pm_save(QEMUFile *f, void *opaque) +{ + struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque; + int i; + + for (i = 0; i < 0x40; i ++) + qemu_put_be32s(f, &s->pm_regs[i]); +} + +static int pxa2xx_pm_load(QEMUFile *f, void *opaque, int version_id) +{ + struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque; + int i; + + for (i = 0; i < 0x40; i ++) + qemu_get_be32s(f, &s->pm_regs[i]); + + return 0; +} + #define CCCR 0x00 /* Core Clock Configuration register */ #define CKEN 0x04 /* Clock Enable register */ #define OSCC 0x08 /* Oscillator Configuration register */ @@ -204,6 +224,30 @@ static CPUWriteMemoryFunc *pxa2xx_cm_writefn[] = { pxa2xx_cm_write, }; +static void pxa2xx_cm_save(QEMUFile *f, void *opaque) +{ + struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque; + int i; + + for (i = 0; i < 4; i ++) + qemu_put_be32s(f, &s->cm_regs[i]); + qemu_put_be32s(f, &s->clkcfg); + qemu_put_be32s(f, &s->pmnc); +} + +static int pxa2xx_cm_load(QEMUFile *f, void *opaque, int version_id) +{ + struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque; + int i; + + for (i = 0; i < 4; i ++) + qemu_get_be32s(f, &s->cm_regs[i]); + qemu_get_be32s(f, &s->clkcfg); + qemu_get_be32s(f, &s->pmnc); + + return 0; +} + static uint32_t pxa2xx_clkpwr_read(void *opaque, int op2, int reg, int crm) { struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque; @@ -482,6 +526,26 @@ static CPUWriteMemoryFunc *pxa2xx_mm_writefn[] = { pxa2xx_mm_write, }; +static void pxa2xx_mm_save(QEMUFile *f, void *opaque) +{ + struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque; + int i; + + for (i = 0; i < 0x1a; i ++) + qemu_put_be32s(f, &s->mm_regs[i]); +} + +static int pxa2xx_mm_load(QEMUFile *f, void *opaque, int version_id) +{ + struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque; + int i; + + for (i = 0; i < 0x1a; i ++) + qemu_get_be32s(f, &s->mm_regs[i]); + + return 0; +} + /* Synchronous Serial Ports */ struct pxa2xx_ssp_s { target_phys_addr_t base; @@ -761,6 +825,53 @@ static CPUWriteMemoryFunc *pxa2xx_ssp_writefn[] = { pxa2xx_ssp_write, }; +static void pxa2xx_ssp_save(QEMUFile *f, void *opaque) +{ + struct pxa2xx_ssp_s *s = (struct pxa2xx_ssp_s *) opaque; + int i; + + qemu_put_be32(f, s->enable); + + qemu_put_be32s(f, &s->sscr[0]); + qemu_put_be32s(f, &s->sscr[1]); + qemu_put_be32s(f, &s->sspsp); + qemu_put_be32s(f, &s->ssto); + qemu_put_be32s(f, &s->ssitr); + qemu_put_be32s(f, &s->sssr); + qemu_put_8s(f, &s->sstsa); + qemu_put_8s(f, &s->ssrsa); + qemu_put_8s(f, &s->ssacd); + + qemu_put_byte(f, s->rx_level); + for (i = 0; i < s->rx_level; i ++) + qemu_put_byte(f, s->rx_fifo[(s->rx_start + i) & 0xf]); +} + +static int pxa2xx_ssp_load(QEMUFile *f, void *opaque, int version_id) +{ + struct pxa2xx_ssp_s *s = (struct pxa2xx_ssp_s *) opaque; + int i; + + s->enable = qemu_get_be32(f); + + qemu_get_be32s(f, &s->sscr[0]); + qemu_get_be32s(f, &s->sscr[1]); + qemu_get_be32s(f, &s->sspsp); + qemu_get_be32s(f, &s->ssto); + qemu_get_be32s(f, &s->ssitr); + qemu_get_be32s(f, &s->sssr); + qemu_get_8s(f, &s->sstsa); + qemu_get_8s(f, &s->ssrsa); + qemu_get_8s(f, &s->ssacd); + + s->rx_level = qemu_get_byte(f); + s->rx_start = 0; + for (i = 0; i < s->rx_level; i ++) + s->rx_fifo[i] = qemu_get_byte(f); + + return 0; +} + /* Real-Time Clock */ #define RCNR 0x00 /* RTC Counter register */ #define RTAR 0x04 /* RTC Alarm register */ @@ -1052,7 +1163,19 @@ static void pxa2xx_rtc_write(void *opaque, target_phys_addr_t addr, } } -static void pxa2xx_rtc_reset(struct pxa2xx_state_s *s) +static CPUReadMemoryFunc *pxa2xx_rtc_readfn[] = { + pxa2xx_rtc_read, + pxa2xx_rtc_read, + pxa2xx_rtc_read, +}; + +static CPUWriteMemoryFunc *pxa2xx_rtc_writefn[] = { + pxa2xx_rtc_write, + pxa2xx_rtc_write, + pxa2xx_rtc_write, +}; + +static void pxa2xx_rtc_init(struct pxa2xx_state_s *s) { struct tm *tm; time_t ti; @@ -1086,17 +1209,61 @@ static void pxa2xx_rtc_reset(struct pxa2xx_state_s *s) s->rtc_pi = qemu_new_timer(rt_clock, pxa2xx_rtc_pi_tick, s); } -static CPUReadMemoryFunc *pxa2xx_rtc_readfn[] = { - pxa2xx_rtc_read, - pxa2xx_rtc_read, - pxa2xx_rtc_read, -}; +static void pxa2xx_rtc_save(QEMUFile *f, void *opaque) +{ + struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque; -static CPUWriteMemoryFunc *pxa2xx_rtc_writefn[] = { - pxa2xx_rtc_write, - pxa2xx_rtc_write, - pxa2xx_rtc_write, -}; + pxa2xx_rtc_hzupdate(s); + pxa2xx_rtc_piupdate(s); + pxa2xx_rtc_swupdate(s); + + qemu_put_be32s(f, &s->rttr); + qemu_put_be32s(f, &s->rtsr); + qemu_put_be32s(f, &s->rtar); + qemu_put_be32s(f, &s->rdar1); + qemu_put_be32s(f, &s->rdar2); + qemu_put_be32s(f, &s->ryar1); + qemu_put_be32s(f, &s->ryar2); + qemu_put_be32s(f, &s->swar1); + qemu_put_be32s(f, &s->swar2); + qemu_put_be32s(f, &s->piar); + qemu_put_be32s(f, &s->last_rcnr); + qemu_put_be32s(f, &s->last_rdcr); + qemu_put_be32s(f, &s->last_rycr); + qemu_put_be32s(f, &s->last_swcr); + qemu_put_be32s(f, &s->last_rtcpicr); + qemu_put_be64s(f, &s->last_hz); + qemu_put_be64s(f, &s->last_sw); + qemu_put_be64s(f, &s->last_pi); +} + +static int pxa2xx_rtc_load(QEMUFile *f, void *opaque, int version_id) +{ + struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque; + + qemu_get_be32s(f, &s->rttr); + qemu_get_be32s(f, &s->rtsr); + qemu_get_be32s(f, &s->rtar); + qemu_get_be32s(f, &s->rdar1); + qemu_get_be32s(f, &s->rdar2); + qemu_get_be32s(f, &s->ryar1); + qemu_get_be32s(f, &s->ryar2); + qemu_get_be32s(f, &s->swar1); + qemu_get_be32s(f, &s->swar2); + qemu_get_be32s(f, &s->piar); + qemu_get_be32s(f, &s->last_rcnr); + qemu_get_be32s(f, &s->last_rdcr); + qemu_get_be32s(f, &s->last_rycr); + qemu_get_be32s(f, &s->last_swcr); + qemu_get_be32s(f, &s->last_rtcpicr); + qemu_get_be64s(f, &s->last_hz); + qemu_get_be64s(f, &s->last_sw); + qemu_get_be64s(f, &s->last_pi); + + pxa2xx_rtc_alarm_update(s, s->rtsr); + + return 0; +} /* I2C Interface */ struct pxa2xx_i2c_s { @@ -1289,6 +1456,33 @@ static CPUWriteMemoryFunc *pxa2xx_i2c_writefn[] = { pxa2xx_i2c_write, }; +static void pxa2xx_i2c_save(QEMUFile *f, void *opaque) +{ + struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) opaque; + + qemu_put_be16s(f, &s->control); + qemu_put_be16s(f, &s->status); + qemu_put_8s(f, &s->ibmr); + qemu_put_8s(f, &s->data); + + i2c_bus_save(f, s->bus); + i2c_slave_save(f, &s->slave); +} + +static int pxa2xx_i2c_load(QEMUFile *f, void *opaque, int version_id) +{ + struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) opaque; + + qemu_get_be16s(f, &s->control); + qemu_get_be16s(f, &s->status); + qemu_get_8s(f, &s->ibmr); + qemu_get_8s(f, &s->data); + + i2c_bus_load(f, s->bus); + i2c_slave_load(f, &s->slave); + return 0; +} + struct pxa2xx_i2c_s *pxa2xx_i2c_init(target_phys_addr_t base, qemu_irq irq, int ioregister) { @@ -1309,6 +1503,9 @@ struct pxa2xx_i2c_s *pxa2xx_i2c_init(target_phys_addr_t base, cpu_register_physical_memory(s->base & 0xfffff000, 0xfff, iomemtype); } + register_savevm("pxa2xx_i2c", base, 0, + pxa2xx_i2c_save, pxa2xx_i2c_load, s); + return s; } @@ -1470,6 +1667,40 @@ static CPUWriteMemoryFunc *pxa2xx_i2s_writefn[] = { pxa2xx_i2s_write, }; +static void pxa2xx_i2s_save(QEMUFile *f, void *opaque) +{ + struct pxa2xx_i2s_s *s = (struct pxa2xx_i2s_s *) opaque; + + qemu_put_be32s(f, &s->control[0]); + qemu_put_be32s(f, &s->control[1]); + qemu_put_be32s(f, &s->status); + qemu_put_be32s(f, &s->mask); + qemu_put_be32s(f, &s->clk); + + qemu_put_be32(f, s->enable); + qemu_put_be32(f, s->rx_len); + qemu_put_be32(f, s->tx_len); + qemu_put_be32(f, s->fifo_len); +} + +static int pxa2xx_i2s_load(QEMUFile *f, void *opaque, int version_id) +{ + struct pxa2xx_i2s_s *s = (struct pxa2xx_i2s_s *) opaque; + + qemu_get_be32s(f, &s->control[0]); + qemu_get_be32s(f, &s->control[1]); + qemu_get_be32s(f, &s->status); + qemu_get_be32s(f, &s->mask); + qemu_get_be32s(f, &s->clk); + + s->enable = qemu_get_be32(f); + s->rx_len = qemu_get_be32(f); + s->tx_len = qemu_get_be32(f); + s->fifo_len = qemu_get_be32(f); + + return 0; +} + static void pxa2xx_i2s_data_req(void *opaque, int tx, int rx) { struct pxa2xx_i2s_s *s = (struct pxa2xx_i2s_s *) opaque; @@ -1510,6 +1741,9 @@ static struct pxa2xx_i2s_s *pxa2xx_i2s_init(target_phys_addr_t base, pxa2xx_i2s_writefn, s); cpu_register_physical_memory(s->base & 0xfff00000, 0xfffff, iomemtype); + register_savevm("pxa2xx_i2s", base, 0, + pxa2xx_i2s_save, pxa2xx_i2s_load, s); + return s; } @@ -1712,6 +1946,45 @@ static void pxa2xx_fir_event(void *opaque, int event) { } +static void pxa2xx_fir_save(QEMUFile *f, void *opaque) +{ + struct pxa2xx_fir_s *s = (struct pxa2xx_fir_s *) opaque; + int i; + + qemu_put_be32(f, s->enable); + + qemu_put_8s(f, &s->control[0]); + qemu_put_8s(f, &s->control[1]); + qemu_put_8s(f, &s->control[2]); + qemu_put_8s(f, &s->status[0]); + qemu_put_8s(f, &s->status[1]); + + qemu_put_byte(f, s->rx_len); + for (i = 0; i < s->rx_len; i ++) + qemu_put_byte(f, s->rx_fifo[(s->rx_start + i) & 63]); +} + +static int pxa2xx_fir_load(QEMUFile *f, void *opaque, int version_id) +{ + struct pxa2xx_fir_s *s = (struct pxa2xx_fir_s *) opaque; + int i; + + s->enable = qemu_get_be32(f); + + qemu_get_8s(f, &s->control[0]); + qemu_get_8s(f, &s->control[1]); + qemu_get_8s(f, &s->control[2]); + qemu_get_8s(f, &s->status[0]); + qemu_get_8s(f, &s->status[1]); + + s->rx_len = qemu_get_byte(f); + s->rx_start = 0; + for (i = 0; i < s->rx_len; i ++) + s->rx_fifo[i] = qemu_get_byte(f); + + return 0; +} + static struct pxa2xx_fir_s *pxa2xx_fir_init(target_phys_addr_t base, qemu_irq irq, struct pxa2xx_dma_state_s *dma, CharDriverState *chr) @@ -1735,6 +2008,8 @@ static struct pxa2xx_fir_s *pxa2xx_fir_init(target_phys_addr_t base, qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty, pxa2xx_fir_rx, pxa2xx_fir_event, s); + register_savevm("pxa2xx_fir", 0, 0, pxa2xx_fir_save, pxa2xx_fir_load, s); + return s; } @@ -1763,6 +2038,7 @@ struct pxa2xx_state_s *pxa270_init(unsigned int sdram_size, s->env = cpu_init(); cpu_arm_set_model(s->env, revision ?: "pxa270"); + register_savevm("cpu", 0, 0, cpu_save, cpu_load, s->env); /* SDRAM & Internal Memory Storage */ cpu_register_physical_memory(PXA2XX_SDRAM_BASE, @@ -1800,6 +2076,7 @@ struct pxa2xx_state_s *pxa270_init(unsigned int sdram_size, iomemtype = cpu_register_io_memory(0, pxa2xx_cm_readfn, pxa2xx_cm_writefn, s); cpu_register_physical_memory(s->cm_base, 0xfff, iomemtype); + register_savevm("pxa2xx_cm", 0, 0, pxa2xx_cm_save, pxa2xx_cm_load, s); cpu_arm_set_cp_io(s->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s); @@ -1810,6 +2087,7 @@ struct pxa2xx_state_s *pxa270_init(unsigned int sdram_size, iomemtype = cpu_register_io_memory(0, pxa2xx_mm_readfn, pxa2xx_mm_writefn, s); cpu_register_physical_memory(s->mm_base, 0xfff, iomemtype); + register_savevm("pxa2xx_mm", 0, 0, pxa2xx_mm_save, pxa2xx_mm_load, s); for (i = 0; pxa27x_ssp[i].io_base; i ++); s->ssp = (struct pxa2xx_ssp_s **) @@ -1824,6 +2102,8 @@ struct pxa2xx_state_s *pxa270_init(unsigned int sdram_size, iomemtype = cpu_register_io_memory(0, pxa2xx_ssp_readfn, pxa2xx_ssp_writefn, &ssp[i]); cpu_register_physical_memory(ssp[i].base, 0xfff, iomemtype); + register_savevm("pxa2xx_ssp", i, 0, + pxa2xx_ssp_save, pxa2xx_ssp_load, s); } if (usb_enabled) { @@ -1837,7 +2117,8 @@ struct pxa2xx_state_s *pxa270_init(unsigned int sdram_size, iomemtype = cpu_register_io_memory(0, pxa2xx_rtc_readfn, pxa2xx_rtc_writefn, s); cpu_register_physical_memory(s->rtc_base, 0xfff, iomemtype); - pxa2xx_rtc_reset(s); + pxa2xx_rtc_init(s); + register_savevm("pxa2xx_rtc", 0, 0, pxa2xx_rtc_save, pxa2xx_rtc_load, s); /* Note that PM registers are in the same page with PWRI2C registers. * As a workaround we don't map PWRI2C into memory and we expect @@ -1849,6 +2130,7 @@ struct pxa2xx_state_s *pxa270_init(unsigned int sdram_size, iomemtype = cpu_register_io_memory(0, pxa2xx_pm_readfn, pxa2xx_pm_writefn, s); cpu_register_physical_memory(s->pm_base, 0xfff, iomemtype); + register_savevm("pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s); s->i2s = pxa2xx_i2s_init(0x40400000, s->pic[PXA2XX_PIC_I2S], s->dma); @@ -1869,6 +2151,7 @@ struct pxa2xx_state_s *pxa255_init(unsigned int sdram_size, s->env = cpu_init(); cpu_arm_set_model(s->env, "pxa255"); + register_savevm("cpu", 0, 0, cpu_save, cpu_load, s->env); /* SDRAM & Internal Memory Storage */ cpu_register_physical_memory(PXA2XX_SDRAM_BASE, sdram_size, @@ -1905,6 +2188,7 @@ struct pxa2xx_state_s *pxa255_init(unsigned int sdram_size, iomemtype = cpu_register_io_memory(0, pxa2xx_cm_readfn, pxa2xx_cm_writefn, s); cpu_register_physical_memory(s->cm_base, 0xfff, iomemtype); + register_savevm("pxa2xx_cm", 0, 0, pxa2xx_cm_save, pxa2xx_cm_load, s); cpu_arm_set_cp_io(s->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s); @@ -1915,6 +2199,7 @@ struct pxa2xx_state_s *pxa255_init(unsigned int sdram_size, iomemtype = cpu_register_io_memory(0, pxa2xx_mm_readfn, pxa2xx_mm_writefn, s); cpu_register_physical_memory(s->mm_base, 0xfff, iomemtype); + register_savevm("pxa2xx_mm", 0, 0, pxa2xx_mm_save, pxa2xx_mm_load, s); for (i = 0; pxa255_ssp[i].io_base; i ++); s->ssp = (struct pxa2xx_ssp_s **) @@ -1929,6 +2214,8 @@ struct pxa2xx_state_s *pxa255_init(unsigned int sdram_size, iomemtype = cpu_register_io_memory(0, pxa2xx_ssp_readfn, pxa2xx_ssp_writefn, &ssp[i]); cpu_register_physical_memory(ssp[i].base, 0xfff, iomemtype); + register_savevm("pxa2xx_ssp", i, 0, + pxa2xx_ssp_save, pxa2xx_ssp_load, s); } if (usb_enabled) { @@ -1942,7 +2229,8 @@ struct pxa2xx_state_s *pxa255_init(unsigned int sdram_size, iomemtype = cpu_register_io_memory(0, pxa2xx_rtc_readfn, pxa2xx_rtc_writefn, s); cpu_register_physical_memory(s->rtc_base, 0xfff, iomemtype); - pxa2xx_rtc_reset(s); + pxa2xx_rtc_init(s); + register_savevm("pxa2xx_rtc", 0, 0, pxa2xx_rtc_save, pxa2xx_rtc_load, s); /* Note that PM registers are in the same page with PWRI2C registers. * As a workaround we don't map PWRI2C into memory and we expect @@ -1954,6 +2242,7 @@ struct pxa2xx_state_s *pxa255_init(unsigned int sdram_size, iomemtype = cpu_register_io_memory(0, pxa2xx_pm_readfn, pxa2xx_pm_writefn, s); cpu_register_physical_memory(s->pm_base, 0xfff, iomemtype); + register_savevm("pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s); s->i2s = pxa2xx_i2s_init(0x40400000, s->pic[PXA2XX_PIC_I2S], s->dma); diff --git a/hw/pxa2xx_dma.c b/hw/pxa2xx_dma.c index d2ed623573..1a79c8d9a1 100644 --- a/hw/pxa2xx_dma.c +++ b/hw/pxa2xx_dma.c @@ -430,6 +430,61 @@ static CPUWriteMemoryFunc *pxa2xx_dma_writefn[] = { pxa2xx_dma_write }; +static void pxa2xx_dma_save(QEMUFile *f, void *opaque) +{ + struct pxa2xx_dma_state_s *s = (struct pxa2xx_dma_state_s *) opaque; + int i; + + qemu_put_be32(f, s->channels); + + qemu_put_be32s(f, &s->stopintr); + qemu_put_be32s(f, &s->eorintr); + qemu_put_be32s(f, &s->rasintr); + qemu_put_be32s(f, &s->startintr); + qemu_put_be32s(f, &s->endintr); + qemu_put_be32s(f, &s->align); + qemu_put_be32s(f, &s->pio); + + qemu_put_buffer(f, s->req, PXA2XX_DMA_NUM_REQUESTS); + for (i = 0; i < s->channels; i ++) { + qemu_put_betl(f, s->chan[i].descr); + qemu_put_betl(f, s->chan[i].src); + qemu_put_betl(f, s->chan[i].dest); + qemu_put_be32s(f, &s->chan[i].cmd); + qemu_put_be32s(f, &s->chan[i].state); + qemu_put_be32(f, s->chan[i].request); + }; +} + +static int pxa2xx_dma_load(QEMUFile *f, void *opaque, int version_id) +{ + struct pxa2xx_dma_state_s *s = (struct pxa2xx_dma_state_s *) opaque; + int i; + + if (qemu_get_be32(f) != s->channels) + return -EINVAL; + + qemu_get_be32s(f, &s->stopintr); + qemu_get_be32s(f, &s->eorintr); + qemu_get_be32s(f, &s->rasintr); + qemu_get_be32s(f, &s->startintr); + qemu_get_be32s(f, &s->endintr); + qemu_get_be32s(f, &s->align); + qemu_get_be32s(f, &s->pio); + + qemu_get_buffer(f, s->req, PXA2XX_DMA_NUM_REQUESTS); + for (i = 0; i < s->channels; i ++) { + s->chan[i].descr = qemu_get_betl(f); + s->chan[i].src = qemu_get_betl(f); + s->chan[i].dest = qemu_get_betl(f); + qemu_get_be32s(f, &s->chan[i].cmd); + qemu_get_be32s(f, &s->chan[i].state); + s->chan[i].request = qemu_get_be32(f); + }; + + return 0; +} + static struct pxa2xx_dma_state_s *pxa2xx_dma_init(target_phys_addr_t base, qemu_irq irq, int channels) { @@ -455,6 +510,8 @@ static struct pxa2xx_dma_state_s *pxa2xx_dma_init(target_phys_addr_t base, pxa2xx_dma_writefn, s); cpu_register_physical_memory(base, 0x0000ffff, iomemtype); + register_savevm("pxa2xx_dma", 0, 0, pxa2xx_dma_save, pxa2xx_dma_load, s); + return s; } diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c index eab2e7225a..0e32329ed7 100644 --- a/hw/pxa2xx_gpio.c +++ b/hw/pxa2xx_gpio.c @@ -247,6 +247,51 @@ static CPUWriteMemoryFunc *pxa2xx_gpio_writefn[] = { pxa2xx_gpio_write }; +static void pxa2xx_gpio_save(QEMUFile *f, void *opaque) +{ + struct pxa2xx_gpio_info_s *s = (struct pxa2xx_gpio_info_s *) opaque; + int i; + + qemu_put_be32(f, s->lines); + + for (i = 0; i < PXA2XX_GPIO_BANKS; i ++) { + qemu_put_be32s(f, &s->ilevel[i]); + qemu_put_be32s(f, &s->olevel[i]); + qemu_put_be32s(f, &s->dir[i]); + qemu_put_be32s(f, &s->rising[i]); + qemu_put_be32s(f, &s->falling[i]); + qemu_put_be32s(f, &s->status[i]); + qemu_put_be32s(f, &s->gafr[i * 2 + 0]); + qemu_put_be32s(f, &s->gafr[i * 2 + 1]); + + qemu_put_be32s(f, &s->prev_level[i]); + } +} + +static int pxa2xx_gpio_load(QEMUFile *f, void *opaque, int version_id) +{ + struct pxa2xx_gpio_info_s *s = (struct pxa2xx_gpio_info_s *) opaque; + int i; + + if (qemu_get_be32(f) != s->lines) + return -EINVAL; + + for (i = 0; i < PXA2XX_GPIO_BANKS; i ++) { + qemu_get_be32s(f, &s->ilevel[i]); + qemu_get_be32s(f, &s->olevel[i]); + qemu_get_be32s(f, &s->dir[i]); + qemu_get_be32s(f, &s->rising[i]); + qemu_get_be32s(f, &s->falling[i]); + qemu_get_be32s(f, &s->status[i]); + qemu_get_be32s(f, &s->gafr[i * 2 + 0]); + qemu_get_be32s(f, &s->gafr[i * 2 + 1]); + + qemu_get_be32s(f, &s->prev_level[i]); + } + + return 0; +} + struct pxa2xx_gpio_info_s *pxa2xx_gpio_init(target_phys_addr_t base, CPUState *env, qemu_irq *pic, int lines) { @@ -265,6 +310,9 @@ struct pxa2xx_gpio_info_s *pxa2xx_gpio_init(target_phys_addr_t base, pxa2xx_gpio_writefn, s); cpu_register_physical_memory(base, 0x00000fff, iomemtype); + register_savevm("pxa2xx_gpio", 0, 0, + pxa2xx_gpio_save, pxa2xx_gpio_load, s); + return s; } diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c index f8ddbb4a41..232effdb13 100644 --- a/hw/pxa2xx_lcd.c +++ b/hw/pxa2xx_lcd.c @@ -924,6 +924,81 @@ void pxa2xx_lcdc_orientation(void *opaque, int angle) pxa2xx_lcdc_resize(s); } +static void pxa2xx_lcdc_save(QEMUFile *f, void *opaque) +{ + struct pxa2xx_lcdc_s *s = (struct pxa2xx_lcdc_s *) opaque; + int i; + + qemu_put_be32(f, s->irqlevel); + qemu_put_be32(f, s->transp); + + for (i = 0; i < 6; i ++) + qemu_put_be32s(f, &s->control[i]); + for (i = 0; i < 2; i ++) + qemu_put_be32s(f, &s->status[i]); + for (i = 0; i < 2; i ++) + qemu_put_be32s(f, &s->ovl1c[i]); + for (i = 0; i < 2; i ++) + qemu_put_be32s(f, &s->ovl2c[i]); + qemu_put_be32s(f, &s->ccr); + qemu_put_be32s(f, &s->cmdcr); + qemu_put_be32s(f, &s->trgbr); + qemu_put_be32s(f, &s->tcr); + qemu_put_be32s(f, &s->liidr); + qemu_put_8s(f, &s->bscntr); + + for (i = 0; i < 7; i ++) { + qemu_put_betl(f, s->dma_ch[i].branch); + qemu_put_byte(f, s->dma_ch[i].up); + qemu_put_buffer(f, s->dma_ch[i].pbuffer, sizeof(s->dma_ch[i].pbuffer)); + + qemu_put_betl(f, s->dma_ch[i].descriptor); + qemu_put_betl(f, s->dma_ch[i].source); + qemu_put_be32s(f, &s->dma_ch[i].id); + qemu_put_be32s(f, &s->dma_ch[i].command); + } +} + +static int pxa2xx_lcdc_load(QEMUFile *f, void *opaque, int version_id) +{ + struct pxa2xx_lcdc_s *s = (struct pxa2xx_lcdc_s *) opaque; + int i; + + s->irqlevel = qemu_get_be32(f); + s->transp = qemu_get_be32(f); + + for (i = 0; i < 6; i ++) + qemu_get_be32s(f, &s->control[i]); + for (i = 0; i < 2; i ++) + qemu_get_be32s(f, &s->status[i]); + for (i = 0; i < 2; i ++) + qemu_get_be32s(f, &s->ovl1c[i]); + for (i = 0; i < 2; i ++) + qemu_get_be32s(f, &s->ovl2c[i]); + qemu_get_be32s(f, &s->ccr); + qemu_get_be32s(f, &s->cmdcr); + qemu_get_be32s(f, &s->trgbr); + qemu_get_be32s(f, &s->tcr); + qemu_get_be32s(f, &s->liidr); + qemu_get_8s(f, &s->bscntr); + + for (i = 0; i < 7; i ++) { + s->dma_ch[i].branch = qemu_get_betl(f); + s->dma_ch[i].up = qemu_get_byte(f); + qemu_get_buffer(f, s->dma_ch[i].pbuffer, sizeof(s->dma_ch[i].pbuffer)); + + s->dma_ch[i].descriptor = qemu_get_betl(f); + s->dma_ch[i].source = qemu_get_betl(f); + qemu_get_be32s(f, &s->dma_ch[i].id); + qemu_get_be32s(f, &s->dma_ch[i].command); + } + + s->bpp = LCCR3_BPP(s->control[3]); + s->xres = s->yres = s->pal_for = -1; + + return 0; +} + #define BITS 8 #include "pxa2xx_template.h" #define BITS 15 @@ -989,6 +1064,10 @@ struct pxa2xx_lcdc_s *pxa2xx_lcdc_init(target_phys_addr_t base, qemu_irq irq, fprintf(stderr, "%s: Bad color depth\n", __FUNCTION__); exit(1); } + + register_savevm("pxa2xx_lcdc", 0, 0, + pxa2xx_lcdc_save, pxa2xx_lcdc_load, s); + return s; } diff --git a/hw/pxa2xx_mmci.c b/hw/pxa2xx_mmci.c index 7515ab8875..2081b54db8 100644 --- a/hw/pxa2xx_mmci.c +++ b/hw/pxa2xx_mmci.c @@ -443,6 +443,84 @@ static CPUWriteMemoryFunc *pxa2xx_mmci_writefn[] = { pxa2xx_mmci_writew }; +static void pxa2xx_mmci_save(QEMUFile *f, void *opaque) +{ + struct pxa2xx_mmci_s *s = (struct pxa2xx_mmci_s *) opaque; + int i; + + qemu_put_be32s(f, &s->status); + qemu_put_be32s(f, &s->clkrt); + qemu_put_be32s(f, &s->spi); + qemu_put_be32s(f, &s->cmdat); + qemu_put_be32s(f, &s->resp_tout); + qemu_put_be32s(f, &s->read_tout); + qemu_put_be32(f, s->blklen); + qemu_put_be32(f, s->numblk); + qemu_put_be32s(f, &s->intmask); + qemu_put_be32s(f, &s->intreq); + qemu_put_be32(f, s->cmd); + qemu_put_be32s(f, &s->arg); + qemu_put_be32(f, s->cmdreq); + qemu_put_be32(f, s->active); + qemu_put_be32(f, s->bytesleft); + + qemu_put_byte(f, s->tx_len); + for (i = 0; i < s->tx_len; i ++) + qemu_put_byte(f, s->tx_fifo[(s->tx_start + i) & 63]); + + qemu_put_byte(f, s->rx_len); + for (i = 0; i < s->rx_len; i ++) + qemu_put_byte(f, s->rx_fifo[(s->rx_start + i) & 31]); + + qemu_put_byte(f, s->resp_len); + for (i = s->resp_len; i < 9; i ++) + qemu_put_be16s(f, &s->resp_fifo[i]); +} + +static int pxa2xx_mmci_load(QEMUFile *f, void *opaque, int version_id) +{ + struct pxa2xx_mmci_s *s = (struct pxa2xx_mmci_s *) opaque; + int i; + + qemu_get_be32s(f, &s->status); + qemu_get_be32s(f, &s->clkrt); + qemu_get_be32s(f, &s->spi); + qemu_get_be32s(f, &s->cmdat); + qemu_get_be32s(f, &s->resp_tout); + qemu_get_be32s(f, &s->read_tout); + s->blklen = qemu_get_be32(f); + s->numblk = qemu_get_be32(f); + qemu_get_be32s(f, &s->intmask); + qemu_get_be32s(f, &s->intreq); + s->cmd = qemu_get_be32(f); + qemu_get_be32s(f, &s->arg); + s->cmdreq = qemu_get_be32(f); + s->active = qemu_get_be32(f); + s->bytesleft = qemu_get_be32(f); + + s->tx_len = qemu_get_byte(f); + s->tx_start = 0; + if (s->tx_len >= sizeof(s->tx_fifo) || s->tx_len < 0) + return -EINVAL; + for (i = 0; i < s->tx_len; i ++) + s->tx_fifo[i] = qemu_get_byte(f); + + s->rx_len = qemu_get_byte(f); + s->rx_start = 0; + if (s->rx_len >= sizeof(s->rx_fifo) || s->rx_len < 0) + return -EINVAL; + for (i = 0; i < s->rx_len; i ++) + s->rx_fifo[i] = qemu_get_byte(f); + + s->resp_len = qemu_get_byte(f); + if (s->resp_len > 9 || s->resp_len < 0) + return -EINVAL; + for (i = s->resp_len; i < 9; i ++) + qemu_get_be16s(f, &s->resp_fifo[i]); + + return 0; +} + struct pxa2xx_mmci_s *pxa2xx_mmci_init(target_phys_addr_t base, qemu_irq irq, void *dma) { @@ -461,6 +539,9 @@ struct pxa2xx_mmci_s *pxa2xx_mmci_init(target_phys_addr_t base, /* Instantiate the actual storage */ s->card = sd_init(sd_bdrv); + register_savevm("pxa2xx_mmci", 0, 0, + pxa2xx_mmci_save, pxa2xx_mmci_load, s); + return s; } diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c index e3cf241789..77e0b6cefe 100644 --- a/hw/pxa2xx_pic.c +++ b/hw/pxa2xx_pic.c @@ -245,6 +245,41 @@ static CPUWriteMemoryFunc *pxa2xx_pic_writefn[] = { pxa2xx_pic_mem_write, }; +static void pxa2xx_pic_save(QEMUFile *f, void *opaque) +{ + struct pxa2xx_pic_state_s *s = (struct pxa2xx_pic_state_s *) opaque; + int i; + + for (i = 0; i < 2; i ++) + qemu_put_be32s(f, &s->int_enabled[i]); + for (i = 0; i < 2; i ++) + qemu_put_be32s(f, &s->int_pending[i]); + for (i = 0; i < 2; i ++) + qemu_put_be32s(f, &s->is_fiq[i]); + qemu_put_be32s(f, &s->int_idle); + for (i = 0; i < PXA2XX_PIC_SRCS; i ++) + qemu_put_be32s(f, &s->priority[i]); +} + +static int pxa2xx_pic_load(QEMUFile *f, void *opaque, int version_id) +{ + struct pxa2xx_pic_state_s *s = (struct pxa2xx_pic_state_s *) opaque; + int i; + + for (i = 0; i < 2; i ++) + qemu_get_be32s(f, &s->int_enabled[i]); + for (i = 0; i < 2; i ++) + qemu_get_be32s(f, &s->int_pending[i]); + for (i = 0; i < 2; i ++) + qemu_get_be32s(f, &s->is_fiq[i]); + qemu_get_be32s(f, &s->int_idle); + for (i = 0; i < PXA2XX_PIC_SRCS; i ++) + qemu_get_be32s(f, &s->priority[i]); + + pxa2xx_pic_update(opaque); + return 0; +} + qemu_irq *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env) { struct pxa2xx_pic_state_s *s; @@ -276,5 +311,7 @@ qemu_irq *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env) /* Enable IC coprocessor access. */ cpu_arm_set_cp_io(env, 6, pxa2xx_pic_cp_read, pxa2xx_pic_cp_write, s); + register_savevm("pxa2xx_pic", 0, 0, pxa2xx_pic_save, pxa2xx_pic_load, s); + return qi; } diff --git a/hw/pxa2xx_timer.c b/hw/pxa2xx_timer.c index 073806a645..284f530407 100644 --- a/hw/pxa2xx_timer.c +++ b/hw/pxa2xx_timer.c @@ -364,6 +364,73 @@ static void pxa2xx_timer_tick4(void *opaque) pxa2xx_timer_update4(i, qemu_get_clock(vm_clock), t->tm.num - 4); } +static void pxa2xx_timer_save(QEMUFile *f, void *opaque) +{ + pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque; + int i; + + qemu_put_be32s(f, &s->clock); + qemu_put_be32s(f, &s->oldclock); + qemu_put_be64s(f, &s->lastload); + + for (i = 0; i < 4; i ++) { + qemu_put_be32s(f, &s->timer[i].value); + qemu_put_be32(f, s->timer[i].level); + } + if (s->tm4) + for (i = 0; i < 8; i ++) { + qemu_put_be32s(f, &s->tm4[i].tm.value); + qemu_put_be32(f, s->tm4[i].tm.level); + qemu_put_be32s(f, &s->tm4[i].oldclock); + qemu_put_be32s(f, &s->tm4[i].clock); + qemu_put_be64s(f, &s->tm4[i].lastload); + qemu_put_be32s(f, &s->tm4[i].freq); + qemu_put_be32s(f, &s->tm4[i].control); + } + + qemu_put_be32s(f, &s->events); + qemu_put_be32s(f, &s->irq_enabled); + qemu_put_be32s(f, &s->reset3); + qemu_put_be32s(f, &s->snapshot); +} + +static int pxa2xx_timer_load(QEMUFile *f, void *opaque, int version_id) +{ + pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque; + int64_t now; + int i; + + qemu_get_be32s(f, &s->clock); + qemu_get_be32s(f, &s->oldclock); + qemu_get_be64s(f, &s->lastload); + + now = qemu_get_clock(vm_clock); + for (i = 0; i < 4; i ++) { + qemu_get_be32s(f, &s->timer[i].value); + s->timer[i].level = qemu_get_be32(f); + } + pxa2xx_timer_update(s, now); + + if (s->tm4) + for (i = 0; i < 8; i ++) { + qemu_get_be32s(f, &s->tm4[i].tm.value); + s->tm4[i].tm.level = qemu_get_be32(f); + qemu_get_be32s(f, &s->tm4[i].oldclock); + qemu_get_be32s(f, &s->tm4[i].clock); + qemu_get_be64s(f, &s->tm4[i].lastload); + qemu_get_be32s(f, &s->tm4[i].freq); + qemu_get_be32s(f, &s->tm4[i].control); + pxa2xx_timer_update4(s, now, i); + } + + qemu_get_be32s(f, &s->events); + qemu_get_be32s(f, &s->irq_enabled); + qemu_get_be32s(f, &s->reset3); + qemu_get_be32s(f, &s->snapshot); + + return 0; +} + static pxa2xx_timer_info *pxa2xx_timer_init(target_phys_addr_t base, qemu_irq *irqs) { @@ -392,6 +459,10 @@ static pxa2xx_timer_info *pxa2xx_timer_init(target_phys_addr_t base, iomemtype = cpu_register_io_memory(0, pxa2xx_timer_readfn, pxa2xx_timer_writefn, s); cpu_register_physical_memory(base, 0x00000fff, iomemtype); + + register_savevm("pxa2xx_timer", 0, 0, + pxa2xx_timer_save, pxa2xx_timer_load, s); + return s; } diff --git a/hw/spitz.c b/hw/spitz.c index 4dd59bb6e2..171dba2e94 100644 --- a/hw/spitz.c +++ b/hw/spitz.c @@ -109,6 +109,24 @@ static void sl_writeb(void *opaque, target_phys_addr_t addr, } } +static void sl_save(QEMUFile *f, void *opaque) +{ + struct sl_nand_s *s = (struct sl_nand_s *) opaque; + + qemu_put_8s(f, &s->ctl); + ecc_put(f, &s->ecc); +} + +static int sl_load(QEMUFile *f, void *opaque, int version_id) +{ + struct sl_nand_s *s = (struct sl_nand_s *) opaque; + + qemu_get_8s(f, &s->ctl); + ecc_get(f, &s->ecc); + + return 0; +} + enum { FLASH_128M, FLASH_1024M, @@ -140,6 +158,8 @@ static void sl_flash_register(struct pxa2xx_state_s *cpu, int size) iomemtype = cpu_register_io_memory(0, sl_readfn, sl_writefn, s); cpu_register_physical_memory(s->target_base, 0x40, iomemtype); + + register_savevm("sl_flash", 0, 0, sl_save, sl_load, s); } /* Spitz Keyboard */ @@ -406,6 +426,38 @@ static void spitz_keyboard_pre_map(struct spitz_keyboard_s *s) #undef CTRL #undef FN +static void spitz_keyboard_save(QEMUFile *f, void *opaque) +{ + struct spitz_keyboard_s *s = (struct spitz_keyboard_s *) opaque; + int i; + + qemu_put_be16s(f, &s->sense_state); + qemu_put_be16s(f, &s->strobe_state); + for (i = 0; i < 5; i ++) + qemu_put_byte(f, spitz_gpio_invert[i]); +} + +static int spitz_keyboard_load(QEMUFile *f, void *opaque, int version_id) +{ + struct spitz_keyboard_s *s = (struct spitz_keyboard_s *) opaque; + int i; + + qemu_get_be16s(f, &s->sense_state); + qemu_get_be16s(f, &s->strobe_state); + for (i = 0; i < 5; i ++) + spitz_gpio_invert[i] = qemu_get_byte(f); + + /* Release all pressed keys */ + memset(s->keyrow, 0, sizeof(s->keyrow)); + spitz_keyboard_sense_update(s); + s->modifiers = 0; + s->imodifiers = 0; + s->fifopos = 0; + s->fifolen = 0; + + return 0; +} + static void spitz_keyboard_register(struct pxa2xx_state_s *cpu) { int i, j; @@ -429,6 +481,9 @@ static void spitz_keyboard_register(struct pxa2xx_state_s *cpu) spitz_keyboard_pre_map(s); qemu_add_kbd_event_handler((QEMUPutKBDEvent *) spitz_keyboard_handler, s); + + register_savevm("spitz_keyboard", 0, 0, + spitz_keyboard_save, spitz_keyboard_load, s); } /* SCOOP devices */ @@ -597,6 +652,42 @@ static inline void scoop_gpio_handler_set(struct scoop_info_s *s, int line, s->handler[line].opaque = opaque; } +static void scoop_save(QEMUFile *f, void *opaque) +{ + struct scoop_info_s *s = (struct scoop_info_s *) opaque; + qemu_put_be16s(f, &s->status); + qemu_put_be16s(f, &s->power); + qemu_put_be32s(f, &s->gpio_level); + qemu_put_be32s(f, &s->gpio_dir); + qemu_put_be32s(f, &s->prev_level); + qemu_put_be16s(f, &s->mcr); + qemu_put_be16s(f, &s->cdr); + qemu_put_be16s(f, &s->ccr); + qemu_put_be16s(f, &s->irr); + qemu_put_be16s(f, &s->imr); + qemu_put_be16s(f, &s->isr); + qemu_put_be16s(f, &s->gprr); +} + +static int scoop_load(QEMUFile *f, void *opaque, int version_id) +{ + struct scoop_info_s *s = (struct scoop_info_s *) opaque; + qemu_get_be16s(f, &s->status); + qemu_get_be16s(f, &s->power); + qemu_get_be32s(f, &s->gpio_level); + qemu_get_be32s(f, &s->gpio_dir); + qemu_get_be32s(f, &s->prev_level); + qemu_get_be16s(f, &s->mcr); + qemu_get_be16s(f, &s->cdr); + qemu_get_be16s(f, &s->ccr); + qemu_get_be16s(f, &s->irr); + qemu_get_be16s(f, &s->imr); + qemu_get_be16s(f, &s->isr); + qemu_get_be16s(f, &s->gprr); + + return 0; +} + static struct scoop_info_s *spitz_scoop_init(struct pxa2xx_state_s *cpu, int count) { int iomemtype; @@ -615,6 +706,7 @@ static struct scoop_info_s *spitz_scoop_init(struct pxa2xx_state_s *cpu, iomemtype = cpu_register_io_memory(0, scoop_readfn, scoop_writefn, &s[0]); cpu_register_physical_memory(s[0].target_base, 0xfff, iomemtype); + register_savevm("scoop", 0, 0, scoop_save, scoop_load, &s[0]); if (count < 2) return s; @@ -622,6 +714,7 @@ static struct scoop_info_s *spitz_scoop_init(struct pxa2xx_state_s *cpu, iomemtype = cpu_register_io_memory(0, scoop_readfn, scoop_writefn, &s[1]); cpu_register_physical_memory(s[1].target_base, 0xfff, iomemtype); + register_savevm("scoop", 1, 0, scoop_save, scoop_load, &s[1]); return s; } @@ -763,6 +856,26 @@ static void spitz_pendown_set(void *opaque, int line, int level) pxa2xx_gpio_set(cpu->gpio, SPITZ_GPIO_TP_INT, level); } +static void spitz_ssp_save(QEMUFile *f, void *opaque) +{ + qemu_put_be32(f, lcd_en); + qemu_put_be32(f, ads_en); + qemu_put_be32(f, max_en); + qemu_put_be32(f, bl_intensity); + qemu_put_be32(f, bl_power); +} + +static int spitz_ssp_load(QEMUFile *f, void *opaque, int version_id) +{ + lcd_en = qemu_get_be32(f); + ads_en = qemu_get_be32(f); + max_en = qemu_get_be32(f); + bl_intensity = qemu_get_be32(f); + bl_power = qemu_get_be32(f); + + return 0; +} + static void spitz_ssp_attach(struct pxa2xx_state_s *cpu) { lcd_en = ads_en = max_en = 0; @@ -786,6 +899,8 @@ static void spitz_ssp_attach(struct pxa2xx_state_s *cpu) bl_intensity = 0x20; bl_power = 0; + + register_savevm("spitz_ssp", 0, 0, spitz_ssp_save, spitz_ssp_load, cpu); } /* CF Microdrive */ diff --git a/hw/wm8750.c b/hw/wm8750.c index c08eb73001..b999890efb 100644 --- a/hw/wm8750.c +++ b/hw/wm8750.c @@ -491,6 +491,93 @@ static int wm8750_rx(i2c_slave *i2c) return 0x00; } +static void wm8750_save(QEMUFile *f, void *opaque) +{ + struct wm8750_s *s = (struct wm8750_s *) opaque; + int i; + qemu_put_8s(f, &s->i2c_data[0]); + qemu_put_8s(f, &s->i2c_data[1]); + qemu_put_be32(f, s->i2c_len); + qemu_put_be32(f, s->enable); + qemu_put_be32(f, s->idx_in); + qemu_put_be32(f, s->req_in); + qemu_put_be32(f, s->idx_out); + qemu_put_be32(f, s->req_out); + + for (i = 0; i < 7; i ++) + qemu_put_8s(f, &s->outvol[i]); + for (i = 0; i < 2; i ++) + qemu_put_8s(f, &s->outmute[i]); + for (i = 0; i < 4; i ++) + qemu_put_8s(f, &s->invol[i]); + for (i = 0; i < 2; i ++) + qemu_put_8s(f, &s->inmute[i]); + + for (i = 0; i < 2; i ++) + qemu_put_8s(f, &s->diff[i]); + qemu_put_8s(f, &s->pol); + qemu_put_8s(f, &s->ds); + for (i = 0; i < 2; i ++) + qemu_put_8s(f, &s->monomix[i]); + qemu_put_8s(f, &s->alc); + qemu_put_8s(f, &s->mute); + for (i = 0; i < 4; i ++) + qemu_put_8s(f, &s->path[i]); + for (i = 0; i < 2; i ++) + qemu_put_8s(f, &s->mpath[i]); + qemu_put_8s(f, &s->format); + qemu_put_8s(f, &s->power); + qemu_put_be32s(f, &s->inmask); + qemu_put_be32s(f, &s->outmask); + qemu_put_byte(f, (s->rate - wm_rate_table) / sizeof(*s->rate)); + i2c_slave_save(f, &s->i2c); +} + +static int wm8750_load(QEMUFile *f, void *opaque, int version_id) +{ + struct wm8750_s *s = (struct wm8750_s *) opaque; + int i; + qemu_get_8s(f, &s->i2c_data[0]); + qemu_get_8s(f, &s->i2c_data[1]); + s->i2c_len = qemu_get_be32(f); + s->enable = qemu_get_be32(f); + s->idx_in = qemu_get_be32(f); + s->req_in = qemu_get_be32(f); + s->idx_out = qemu_get_be32(f); + s->req_out = qemu_get_be32(f); + + for (i = 0; i < 7; i ++) + qemu_get_8s(f, &s->outvol[i]); + for (i = 0; i < 2; i ++) + qemu_get_8s(f, &s->outmute[i]); + for (i = 0; i < 4; i ++) + qemu_get_8s(f, &s->invol[i]); + for (i = 0; i < 2; i ++) + qemu_get_8s(f, &s->inmute[i]); + + for (i = 0; i < 2; i ++) + qemu_get_8s(f, &s->diff[i]); + qemu_get_8s(f, &s->pol); + qemu_get_8s(f, &s->ds); + for (i = 0; i < 2; i ++) + qemu_get_8s(f, &s->monomix[i]); + qemu_get_8s(f, &s->alc); + qemu_get_8s(f, &s->mute); + for (i = 0; i < 4; i ++) + qemu_get_8s(f, &s->path[i]); + for (i = 0; i < 2; i ++) + qemu_get_8s(f, &s->mpath[i]); + qemu_get_8s(f, &s->format); + qemu_get_8s(f, &s->power); + qemu_get_be32s(f, &s->inmask); + qemu_get_be32s(f, &s->outmask); + s->rate = &wm_rate_table[(uint8_t) qemu_get_byte(f) & 0x1f]; + i2c_slave_load(f, &s->i2c); + return 0; +} + +static int wm8750_iid = 0; + i2c_slave *wm8750_init(i2c_bus *bus, AudioState *audio) { struct wm8750_s *s = (struct wm8750_s *) @@ -502,6 +589,8 @@ i2c_slave *wm8750_init(i2c_bus *bus, AudioState *audio) AUD_register_card(audio, CODEC, &s->card); wm8750_reset(&s->i2c); + register_savevm(CODEC, wm8750_iid ++, 0, wm8750_save, wm8750_load, s); + return &s->i2c; } diff --git a/vl.c b/vl.c index 373435b4ac..7277165c71 100644 --- a/vl.c +++ b/vl.c @@ -5679,13 +5679,144 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) #elif defined(TARGET_ARM) -/* ??? Need to implement these. */ void cpu_save(QEMUFile *f, void *opaque) { + int i; + CPUARMState *env = (CPUARMState *)opaque; + + for (i = 0; i < 16; i++) { + qemu_put_be32(f, env->regs[i]); + } + qemu_put_be32(f, cpsr_read(env)); + qemu_put_be32(f, env->spsr); + for (i = 0; i < 6; i++) { + qemu_put_be32(f, env->banked_spsr[i]); + qemu_put_be32(f, env->banked_r13[i]); + qemu_put_be32(f, env->banked_r14[i]); + } + for (i = 0; i < 5; i++) { + qemu_put_be32(f, env->usr_regs[i]); + qemu_put_be32(f, env->fiq_regs[i]); + } + qemu_put_be32(f, env->cp15.c0_cpuid); + qemu_put_be32(f, env->cp15.c0_cachetype); + qemu_put_be32(f, env->cp15.c1_sys); + qemu_put_be32(f, env->cp15.c1_coproc); + qemu_put_be32(f, env->cp15.c2_base); + qemu_put_be32(f, env->cp15.c2_data); + qemu_put_be32(f, env->cp15.c2_insn); + qemu_put_be32(f, env->cp15.c3); + qemu_put_be32(f, env->cp15.c5_insn); + qemu_put_be32(f, env->cp15.c5_data); + for (i = 0; i < 8; i++) { + qemu_put_be32(f, env->cp15.c6_region[i]); + } + qemu_put_be32(f, env->cp15.c6_insn); + qemu_put_be32(f, env->cp15.c6_data); + qemu_put_be32(f, env->cp15.c9_insn); + qemu_put_be32(f, env->cp15.c9_data); + qemu_put_be32(f, env->cp15.c13_fcse); + qemu_put_be32(f, env->cp15.c13_context); + qemu_put_be32(f, env->cp15.c15_cpar); + + qemu_put_be32(f, env->features); + + if (arm_feature(env, ARM_FEATURE_VFP)) { + for (i = 0; i < 16; i++) { + CPU_DoubleU u; + u.d = env->vfp.regs[i]; + qemu_put_be32(f, u.l.upper); + qemu_put_be32(f, u.l.lower); + } + for (i = 0; i < 16; i++) { + qemu_put_be32(f, env->vfp.xregs[i]); + } + + /* TODO: Should use proper FPSCR access functions. */ + qemu_put_be32(f, env->vfp.vec_len); + qemu_put_be32(f, env->vfp.vec_stride); + } + + if (arm_feature(env, ARM_FEATURE_IWMMXT)) { + for (i = 0; i < 16; i++) { + qemu_put_be64(f, env->iwmmxt.regs[i]); + } + for (i = 0; i < 16; i++) { + qemu_put_be32(f, env->iwmmxt.cregs[i]); + } + } } int cpu_load(QEMUFile *f, void *opaque, int version_id) { + CPUARMState *env = (CPUARMState *)opaque; + int i; + + if (version_id != 0) + return -EINVAL; + + for (i = 0; i < 16; i++) { + env->regs[i] = qemu_get_be32(f); + } + cpsr_write(env, qemu_get_be32(f), 0xffffffff); + env->spsr = qemu_get_be32(f); + for (i = 0; i < 6; i++) { + env->banked_spsr[i] = qemu_get_be32(f); + env->banked_r13[i] = qemu_get_be32(f); + env->banked_r14[i] = qemu_get_be32(f); + } + for (i = 0; i < 5; i++) { + env->usr_regs[i] = qemu_get_be32(f); + env->fiq_regs[i] = qemu_get_be32(f); + } + env->cp15.c0_cpuid = qemu_get_be32(f); + env->cp15.c0_cachetype = qemu_get_be32(f); + env->cp15.c1_sys = qemu_get_be32(f); + env->cp15.c1_coproc = qemu_get_be32(f); + env->cp15.c2_base = qemu_get_be32(f); + env->cp15.c2_data = qemu_get_be32(f); + env->cp15.c2_insn = qemu_get_be32(f); + env->cp15.c3 = qemu_get_be32(f); + env->cp15.c5_insn = qemu_get_be32(f); + env->cp15.c5_data = qemu_get_be32(f); + for (i = 0; i < 8; i++) { + env->cp15.c6_region[i] = qemu_get_be32(f); + } + env->cp15.c6_insn = qemu_get_be32(f); + env->cp15.c6_data = qemu_get_be32(f); + env->cp15.c9_insn = qemu_get_be32(f); + env->cp15.c9_data = qemu_get_be32(f); + env->cp15.c13_fcse = qemu_get_be32(f); + env->cp15.c13_context = qemu_get_be32(f); + env->cp15.c15_cpar = qemu_get_be32(f); + + env->features = qemu_get_be32(f); + + if (arm_feature(env, ARM_FEATURE_VFP)) { + for (i = 0; i < 16; i++) { + CPU_DoubleU u; + u.l.upper = qemu_get_be32(f); + u.l.lower = qemu_get_be32(f); + env->vfp.regs[i] = u.d; + } + for (i = 0; i < 16; i++) { + env->vfp.xregs[i] = qemu_get_be32(f); + } + + /* TODO: Should use proper FPSCR access functions. */ + env->vfp.vec_len = qemu_get_be32(f); + env->vfp.vec_stride = qemu_get_be32(f); + } + + if (arm_feature(env, ARM_FEATURE_IWMMXT)) { + for (i = 0; i < 16; i++) { + env->iwmmxt.regs[i] = qemu_get_be64(f); + } + for (i = 0; i < 16; i++) { + env->iwmmxt.cregs[i] = qemu_get_be32(f); + } + } + return 0; }