2323
2424#include "qemu/osdep.h"
2525#include "qemu/log.h"
26+ #include "qemu/notify.h"
2627#include "qemu/units.h"
2728#include "qapi/error.h"
2829#include "hw/sysbus.h"
2930#include "hw/qdev-properties.h"
3031#include "hw/qdev-properties-system.h"
3132#include "hw/block/block.h"
3233#include "system/block-backend.h"
34+ #include "system/runstate.h"
3335
3436#define TYPE_PEBBLE_EXTFLASH "pebble-extflash"
3537OBJECT_DECLARE_SIMPLE_TYPE (PblExtFlash , PEBBLE_EXTFLASH )
@@ -51,8 +53,11 @@ struct PblExtFlash {
5153 BlockBackend * blk ;
5254 uint8_t * storage ;
5355 uint32_t size ;
56+ uint32_t backed_size ;
5457
5558 uint32_t ctrl ;
59+
60+ Notifier shutdown_notifier ;
5661};
5762
5863static uint64_t pbl_extflash_regs_read (void * opaque , hwaddr offset ,
@@ -100,6 +105,19 @@ static const MemoryRegionOps pbl_extflash_regs_ops = {
100105 .valid .max_access_size = 4 ,
101106};
102107
108+ static void pbl_extflash_shutdown_notify (Notifier * n , void * data )
109+ {
110+ PblExtFlash * s = container_of (n , PblExtFlash , shutdown_notifier );
111+
112+ if (!s -> blk || !blk_is_writable (s -> blk ) || s -> backed_size == 0 ) {
113+ return ;
114+ }
115+ if (blk_pwrite (s -> blk , 0 , s -> backed_size , s -> storage , 0 ) < 0 ) {
116+ qemu_log_mask (LOG_GUEST_ERROR ,
117+ "pebble-extflash: failed to flush storage on shutdown\n" );
118+ }
119+ }
120+
103121static void pbl_extflash_realize (DeviceState * dev , Error * * errp )
104122{
105123 PblExtFlash * s = PEBBLE_EXTFLASH (dev );
@@ -127,7 +145,14 @@ static void pbl_extflash_realize(DeviceState *dev, Error **errp)
127145 error_setg (errp , "pebble-extflash: failed to read drive" );
128146 return ;
129147 }
148+ s -> backed_size = blk_size ;
130149 }
150+
151+ /* Persist guest writes back to the file before bdrv_close_all()
152+ * tears the block layer down. Fires for graceful shutdown,
153+ * `(qemu) quit`, and SIGINT (Ctrl+C). */
154+ s -> shutdown_notifier .notify = pbl_extflash_shutdown_notify ;
155+ qemu_register_shutdown_notifier (& s -> shutdown_notifier );
131156 }
132157
133158 s -> ctrl = 1 ; /* XIP enabled by default */
0 commit comments