@@ -423,6 +423,7 @@ typedef struct BlockConf {
uint32_t opt_io_size;
int32_t bootindex;
uint32_t discard_granularity;
+ uint32_t discard_zeroes_data;
} BlockConf;
static inline unsigned int get_physical_block_exp(BlockConf *conf)
@@ -444,10 +445,12 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
_conf.logical_block_size, 512), \
DEFINE_PROP_UINT16("physical_block_size", _state, \
_conf.physical_block_size, 512), \
- DEFINE_PROP_UINT16("min_io_size", _state, _conf.min_io_size, 0), \
+ DEFINE_PROP_UINT16("min_io_size", _state, _conf.min_io_size, 0), \
DEFINE_PROP_UINT32("opt_io_size", _state, _conf.opt_io_size, 0), \
DEFINE_PROP_INT32("bootindex", _state, _conf.bootindex, -1), \
- DEFINE_PROP_UINT32("discard_granularity", _state, \
+ DEFINE_PROP_BIT("discard_zeroes_data", _state, \
+ _conf.discard_zeroes_data, 0, false), \
+ DEFINE_PROP_UINT32("discard_granularity", _state, \
_conf.discard_granularity, 0)
#endif
@@ -128,7 +128,11 @@ static void ide_identify(IDEState *s)
put_le16(p + 67, 120);
put_le16(p + 68, 120);
if (dev && dev->conf.discard_granularity) {
- put_le16(p + 69, (1 << 14)); /* determinate TRIM behavior */
+ int val;
+
+ val = 0x4000;
+ val |= dev->conf.discard_zeroes_data ? 0x20 : 0;
+ put_le16(p + 69, val); /* determinate TRIM behavior */
}
if (s->ncq_queues) {
@@ -1295,8 +1295,11 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
outbuf[13] = get_physical_block_exp(&s->qdev.conf);
/* set TPE bit if the format supports discard */
- if (s->qdev.conf.discard_granularity) {
+ if (s->qdev.type == TYPE_DISK && s->qdev.conf.discard_granularity) {
outbuf[14] = 0x80;
+ if (s->qdev.conf.discard_zeroes_data) {
+ outbuf[14] |= 0x40;
+ }
}
/* Protection, exponent and lowest lba field left blank. */
Now that the block layer guarantees stable semantics for discard, we can expose them to guests. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- block.h | 7 +++++-- hw/ide/core.c | 6 +++++- hw/scsi-disk.c | 5 ++++- 3 files changed, 14 insertions(+), 4 deletions(-)