提交 07e070aa 编写于 作者: P Peter Maydell

Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging

* docs/atomics fixes and atomic_rcu_* optimization (Emilio)
* NBD bugfix (Eric)
* Memory fixes and cleanups (Paolo, Paul)
* scsi-block support for SCSI status, including persistent
  reservations (Paolo)
* kvm_stat moves to the Linux repository
* SCSI bug fixes (Peter, Prasad)
* Killing qemu_char_get_next_serial, non-ARM parts (Xiaoqiang)

# gpg: Signature made Sun 29 May 2016 08:11:20 BST using RSA key ID 78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>"
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>"

* remotes/bonzini/tags/for-upstream: (30 commits)
  exec: hide mr->ram_addr from qemu_get_ram_ptr users
  memory: split memory_region_from_host from qemu_ram_addr_from_host
  exec: remove ram_addr argument from qemu_ram_block_from_host
  memory: remove qemu_get_ram_fd, qemu_set_ram_fd, qemu_ram_block_host_ptr
  scsi-generic: Merge block max xfer len in INQUIRY response
  scsi-block: always use SG_IO
  scsi-disk: introduce scsi_disk_req_check_error
  scsi-disk: add need_fua_emulation to SCSIDiskClass
  scsi-disk: introduce dma_readv and dma_writev
  scsi-disk: introduce a common base class
  xen-hvm: ignore background I/O sections
  docs/atomics: update comparison with Linux
  atomics: do not emit consume barrier for atomic_rcu_read
  atomics: emit an smp_read_barrier_depends() barrier only for Alpha and Thread Sanitizer
  docs/atomics: update atomic_read/set comparison with Linux
  bt: rewrite csrhci_write to avoid out-of-bounds writes
  block/iscsi: avoid potential overflow of acb->task->cdb
  scsi: megasas: check 'read_queue_head' index value
  scsi: megasas: initialise local configuration data buffer
  scsi: megasas: use appropriate property buffer size
  ...
Signed-off-by: NPeter Maydell <peter.maydell@linaro.org>
......@@ -92,9 +92,6 @@ HELPERS-$(CONFIG_LINUX) = qemu-bridge-helper$(EXESUF)
ifdef BUILD_DOCS
DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1 qemu-nbd.8 qemu-ga.8
DOCS+=qmp-commands.txt
ifdef CONFIG_LINUX
DOCS+=kvm_stat.1
endif
ifdef CONFIG_VIRTFS
DOCS+=fsdev/virtfs-proxy-helper.1
endif
......@@ -571,12 +568,6 @@ qemu-ga.8: qemu-ga.texi
$(POD2MAN) --section=8 --center=" " --release=" " qemu-ga.pod > $@, \
" GEN $@")
kvm_stat.1: scripts/kvm/kvm_stat.texi
$(call quiet-command, \
perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< kvm_stat.pod && \
$(POD2MAN) --section=1 --center=" " --release=" " kvm_stat.pod > $@, \
" GEN $@")
dvi: qemu-doc.dvi qemu-tech.dvi
html: qemu-doc.html qemu-tech.html
info: qemu-doc.info qemu-tech.info
......
......@@ -833,6 +833,13 @@ static BlockAIOCB *iscsi_aio_ioctl(BlockDriverState *bs,
return &acb->common;
}
if (acb->ioh->cmd_len > SCSI_CDB_MAX_SIZE) {
error_report("iSCSI: ioctl error CDB exceeds max size (%d > %d)",
acb->ioh->cmd_len, SCSI_CDB_MAX_SIZE);
qemu_aio_unref(acb);
return NULL;
}
acb->task = malloc(sizeof(struct scsi_task));
if (acb->task == NULL) {
error_report("iSCSI: Failed to allocate task for scsi command. %s",
......
......@@ -246,7 +246,8 @@ static inline ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
{
ram_addr_t ram_addr;
if (qemu_ram_addr_from_host(ptr, &ram_addr) == NULL) {
ram_addr = qemu_ram_addr_from_host(ptr);
if (ram_addr == RAM_ADDR_INVALID) {
fprintf(stderr, "Bad ram pointer %p\n", ptr);
abort();
}
......
......@@ -326,21 +326,41 @@ and memory barriers, and the equivalents in QEMU:
use a boxed atomic_t type; atomic operations in QEMU are polymorphic
and use normal C types.
- atomic_read and atomic_set in Linux give no guarantee at all;
atomic_read and atomic_set in QEMU include a compiler barrier
(similar to the READ_ONCE/WRITE_ONCE macros in Linux).
- most atomic read-modify-write operations in Linux return void;
in QEMU, all of them return the old value of the variable.
- Originally, atomic_read and atomic_set in Linux gave no guarantee
at all. Linux 4.1 updated them to implement volatile
semantics via ACCESS_ONCE (or the more recent READ/WRITE_ONCE).
QEMU's atomic_read/set implement, if the compiler supports it, C11
atomic relaxed semantics, and volatile semantics otherwise.
Both semantics prevent the compiler from doing certain transformations;
the difference is that atomic accesses are guaranteed to be atomic,
while volatile accesses aren't. Thus, in the volatile case we just cross
our fingers hoping that the compiler will generate atomic accesses,
since we assume the variables passed are machine-word sized and
properly aligned.
No barriers are implied by atomic_read/set in either Linux or QEMU.
- atomic read-modify-write operations in Linux are of three kinds:
atomic_OP returns void
atomic_OP_return returns new value of the variable
atomic_fetch_OP returns the old value of the variable
atomic_cmpxchg returns the old value of the variable
In QEMU, the second kind does not exist. Currently Linux has
atomic_fetch_or only. QEMU provides and, or, inc, dec, add, sub.
- different atomic read-modify-write operations in Linux imply
a different set of memory barriers; in QEMU, all of them enforce
sequential consistency, which means they imply full memory barriers
before and after the operation.
- Linux does not have an equivalent of atomic_mb_read() and
atomic_mb_set(). In particular, note that set_mb() is a little
weaker than atomic_mb_set().
- Linux does not have an equivalent of atomic_mb_set(). In particular,
note that smp_store_mb() is a little weaker than atomic_mb_set().
atomic_mb_read() compiles to the same instructions as Linux's
smp_load_acquire(), but this should be treated as an implementation
detail. If required, QEMU might later add atomic_load_acquire() and
atomic_store_release() macros.
SOURCES
......
......@@ -1815,40 +1815,6 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
}
#endif /* !_WIN32 */
int qemu_get_ram_fd(ram_addr_t addr)
{
RAMBlock *block;
int fd;
rcu_read_lock();
block = qemu_get_ram_block(addr);
fd = block->fd;
rcu_read_unlock();
return fd;
}
void qemu_set_ram_fd(ram_addr_t addr, int fd)
{
RAMBlock *block;
rcu_read_lock();
block = qemu_get_ram_block(addr);
block->fd = fd;
rcu_read_unlock();
}
void *qemu_get_ram_block_host_ptr(ram_addr_t addr)
{
RAMBlock *block;
void *ptr;
rcu_read_lock();
block = qemu_get_ram_block(addr);
ptr = ramblock_ptr(block, 0);
rcu_read_unlock();
return ptr;
}
/* Return a host pointer to ram allocated with qemu_ram_alloc.
* This should not be used for general purpose DMA. Use address_space_map
* or address_space_rw instead. For local memory (e.g. video ram) that the
......@@ -1856,12 +1822,13 @@ void *qemu_get_ram_block_host_ptr(ram_addr_t addr)
*
* Called within RCU critical section.
*/
void *qemu_get_ram_ptr(RAMBlock *ram_block, ram_addr_t addr)
void *qemu_map_ram_ptr(RAMBlock *ram_block, ram_addr_t addr)
{
RAMBlock *block = ram_block;
if (block == NULL) {
block = qemu_get_ram_block(addr);
addr -= block->offset;
}
if (xen_enabled() && block->host == NULL) {
......@@ -1875,10 +1842,10 @@ void *qemu_get_ram_ptr(RAMBlock *ram_block, ram_addr_t addr)
block->host = xen_map_cache(block->offset, block->max_length, 1);
}
return ramblock_ptr(block, addr - block->offset);
return ramblock_ptr(block, addr);
}
/* Return a host pointer to guest's ram. Similar to qemu_get_ram_ptr
/* Return a host pointer to guest's ram. Similar to qemu_map_ram_ptr
* but takes a size argument.
*
* Called within RCU critical section.
......@@ -1887,16 +1854,15 @@ static void *qemu_ram_ptr_length(RAMBlock *ram_block, ram_addr_t addr,
hwaddr *size)
{
RAMBlock *block = ram_block;
ram_addr_t offset_inside_block;
if (*size == 0) {
return NULL;
}
if (block == NULL) {
block = qemu_get_ram_block(addr);
addr -= block->offset;
}
offset_inside_block = addr - block->offset;
*size = MIN(*size, block->max_length - offset_inside_block);
*size = MIN(*size, block->max_length - addr);
if (xen_enabled() && block->host == NULL) {
/* We need to check if the requested address is in the RAM
......@@ -1910,7 +1876,7 @@ static void *qemu_ram_ptr_length(RAMBlock *ram_block, ram_addr_t addr,
block->host = xen_map_cache(block->offset, block->max_length, 1);
}
return ramblock_ptr(block, offset_inside_block);
return ramblock_ptr(block, addr);
}
/*
......@@ -1931,16 +1897,16 @@ static void *qemu_ram_ptr_length(RAMBlock *ram_block, ram_addr_t addr,
* ram_addr_t.
*/
RAMBlock *qemu_ram_block_from_host(void *ptr, bool round_offset,
ram_addr_t *ram_addr,
ram_addr_t *offset)
{
RAMBlock *block;
uint8_t *host = ptr;
if (xen_enabled()) {
ram_addr_t ram_addr;
rcu_read_lock();
*ram_addr = xen_ram_addr_from_mapcache(ptr);
block = qemu_get_ram_block(*ram_addr);
ram_addr = xen_ram_addr_from_mapcache(ptr);
block = qemu_get_ram_block(ram_addr);
if (block) {
*offset = (host - block->host);
}
......@@ -1972,7 +1938,6 @@ found:
if (round_offset) {
*offset &= TARGET_PAGE_MASK;
}
*ram_addr = block->offset + *offset;
rcu_read_unlock();
return block;
}
......@@ -1999,18 +1964,17 @@ RAMBlock *qemu_ram_block_by_name(const char *name)
/* Some of the softmmu routines need to translate from a host pointer
(typically a TLB entry) back to a ram offset. */
MemoryRegion *qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
ram_addr_t qemu_ram_addr_from_host(void *ptr)
{
RAMBlock *block;
ram_addr_t offset; /* Not used */
block = qemu_ram_block_from_host(ptr, false, ram_addr, &offset);
ram_addr_t offset;
block = qemu_ram_block_from_host(ptr, false, &offset);
if (!block) {
return NULL;
return RAM_ADDR_INVALID;
}
return block->mr;
return block->offset + offset;
}
/* Called within RCU critical section. */
......@@ -2022,13 +1986,13 @@ static void notdirty_mem_write(void *opaque, hwaddr ram_addr,
}
switch (size) {
case 1:
stb_p(qemu_get_ram_ptr(NULL, ram_addr), val);
stb_p(qemu_map_ram_ptr(NULL, ram_addr), val);
break;
case 2:
stw_p(qemu_get_ram_ptr(NULL, ram_addr), val);
stw_p(qemu_map_ram_ptr(NULL, ram_addr), val);
break;
case 4:
stl_p(qemu_get_ram_ptr(NULL, ram_addr), val);
stl_p(qemu_map_ram_ptr(NULL, ram_addr), val);
break;
default:
abort();
......@@ -2490,6 +2454,8 @@ static void invalidate_and_set_dirty(MemoryRegion *mr, hwaddr addr,
hwaddr length)
{
uint8_t dirty_log_mask = memory_region_get_dirty_log_mask(mr);
addr += memory_region_get_ram_addr(mr);
/* No early return if dirty_log_mask is or becomes 0, because
* cpu_physical_memory_set_dirty_range will still call
* xen_modified_memory.
......@@ -2602,9 +2568,8 @@ static MemTxResult address_space_write_continue(AddressSpace *as, hwaddr addr,
abort();
}
} else {
addr1 += memory_region_get_ram_addr(mr);
/* RAM case */
ptr = qemu_get_ram_ptr(mr->ram_block, addr1);
ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
memcpy(ptr, buf, l);
invalidate_and_set_dirty(mr, addr1, l);
}
......@@ -2695,8 +2660,7 @@ MemTxResult address_space_read_continue(AddressSpace *as, hwaddr addr,
}
} else {
/* RAM case */
ptr = qemu_get_ram_ptr(mr->ram_block,
memory_region_get_ram_addr(mr) + addr1);
ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
memcpy(buf, ptr, l);
}
......@@ -2779,9 +2743,8 @@ static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as,
memory_region_is_romd(mr))) {
l = memory_access_size(mr, l, addr1);
} else {
addr1 += memory_region_get_ram_addr(mr);
/* ROM/RAM case */
ptr = qemu_get_ram_ptr(mr->ram_block, addr1);
ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
switch (type) {
case WRITE_DATA:
memcpy(ptr, buf, l);
......@@ -2939,7 +2902,6 @@ void *address_space_map(AddressSpace *as,
hwaddr done = 0;
hwaddr l, xlat, base;
MemoryRegion *mr, *this_mr;
ram_addr_t raddr;
void *ptr;
if (len == 0) {
......@@ -2974,7 +2936,6 @@ void *address_space_map(AddressSpace *as,
}
base = xlat;
raddr = memory_region_get_ram_addr(mr);
for (;;) {
len -= l;
......@@ -2993,7 +2954,7 @@ void *address_space_map(AddressSpace *as,
memory_region_ref(mr);
*plen = done;
ptr = qemu_ram_ptr_length(mr->ram_block, raddr + base, plen);
ptr = qemu_ram_ptr_length(mr->ram_block, base, plen);
rcu_read_unlock();
return ptr;
......@@ -3010,7 +2971,7 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len,
MemoryRegion *mr;
ram_addr_t addr1;
mr = qemu_ram_addr_from_host(buffer, &addr1);
mr = memory_region_from_host(buffer, &addr1);
assert(mr != NULL);
if (is_write) {
invalidate_and_set_dirty(mr, addr1, access_len);
......@@ -3077,8 +3038,7 @@ static inline uint32_t address_space_ldl_internal(AddressSpace *as, hwaddr addr,
#endif
} else {
/* RAM case */
ptr = qemu_get_ram_ptr(mr->ram_block,
memory_region_get_ram_addr(mr) + addr1);
ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
switch (endian) {
case DEVICE_LITTLE_ENDIAN:
val = ldl_le_p(ptr);
......@@ -3171,8 +3131,7 @@ static inline uint64_t address_space_ldq_internal(AddressSpace *as, hwaddr addr,
#endif
} else {
/* RAM case */
ptr = qemu_get_ram_ptr(mr->ram_block,
memory_region_get_ram_addr(mr) + addr1);
ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
switch (endian) {
case DEVICE_LITTLE_ENDIAN:
val = ldq_le_p(ptr);
......@@ -3285,8 +3244,7 @@ static inline uint32_t address_space_lduw_internal(AddressSpace *as,
#endif
} else {
/* RAM case */
ptr = qemu_get_ram_ptr(mr->ram_block,
memory_region_get_ram_addr(mr) + addr1);
ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
switch (endian) {
case DEVICE_LITTLE_ENDIAN:
val = lduw_le_p(ptr);
......@@ -3368,13 +3326,13 @@ void address_space_stl_notdirty(AddressSpace *as, hwaddr addr, uint32_t val,
r = memory_region_dispatch_write(mr, addr1, val, 4, attrs);
} else {
addr1 += memory_region_get_ram_addr(mr);
ptr = qemu_get_ram_ptr(mr->ram_block, addr1);
ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
stl_p(ptr, val);
dirty_log_mask = memory_region_get_dirty_log_mask(mr);
dirty_log_mask &= ~(1 << DIRTY_MEMORY_CODE);
cpu_physical_memory_set_dirty_range(addr1, 4, dirty_log_mask);
cpu_physical_memory_set_dirty_range(memory_region_get_ram_addr(mr) + addr,
4, dirty_log_mask);
r = MEMTX_OK;
}
if (result) {
......@@ -3423,8 +3381,7 @@ static inline void address_space_stl_internal(AddressSpace *as,
r = memory_region_dispatch_write(mr, addr1, val, 4, attrs);
} else {
/* RAM case */
addr1 += memory_region_get_ram_addr(mr);
ptr = qemu_get_ram_ptr(mr->ram_block, addr1);
ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
switch (endian) {
case DEVICE_LITTLE_ENDIAN:
stl_le_p(ptr, val);
......@@ -3533,8 +3490,7 @@ static inline void address_space_stw_internal(AddressSpace *as,
r = memory_region_dispatch_write(mr, addr1, val, 2, attrs);
} else {
/* RAM case */
addr1 += memory_region_get_ram_addr(mr);
ptr = qemu_get_ram_ptr(mr->ram_block, addr1);
ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
switch (endian) {
case DEVICE_LITTLE_ENDIAN:
stw_le_p(ptr, val);
......
......@@ -39,9 +39,14 @@ struct csrhci_s {
int out_size;
uint8_t outfifo[FIFO_LEN * 2];
uint8_t inpkt[FIFO_LEN];
enum {
CSR_HDR_LEN,
CSR_DATA_LEN,
CSR_DATA
} in_state;
int in_len;
int in_hdr;
int in_data;
int in_needed;
QEMUTimer *out_tm;
int64_t baud_delay;
......@@ -296,38 +301,60 @@ static int csrhci_data_len(const uint8_t *pkt)
exit(-1);
}
static void csrhci_ready_for_next_inpkt(struct csrhci_s *s)
{
s->in_state = CSR_HDR_LEN;
s->in_len = 0;
s->in_needed = 2;
s->in_hdr = INT_MAX;
}
static int csrhci_write(struct CharDriverState *chr,
const uint8_t *buf, int len)
{
struct csrhci_s *s = (struct csrhci_s *) chr->opaque;
int plen = s->in_len;
int total = 0;
if (!s->enable)
return 0;
s->in_len += len;
memcpy(s->inpkt + plen, buf, len);
for (;;) {
int cnt = MIN(len, s->in_needed - s->in_len);
if (cnt) {
memcpy(s->inpkt + s->in_len, buf, cnt);
s->in_len += cnt;
buf += cnt;
len -= cnt;
total += cnt;
}
if (s->in_len < s->in_needed) {
break;
}
while (1) {
if (s->in_len >= 2 && plen < 2)
if (s->in_state == CSR_HDR_LEN) {
s->in_hdr = csrhci_header_len(s->inpkt) + 1;
assert(s->in_hdr >= s->in_needed);
s->in_needed = s->in_hdr;
s->in_state = CSR_DATA_LEN;
continue;
}
if (s->in_len >= s->in_hdr && plen < s->in_hdr)
s->in_data = csrhci_data_len(s->inpkt) + s->in_hdr;
if (s->in_state == CSR_DATA_LEN) {
s->in_needed += csrhci_data_len(s->inpkt);
/* hci_acl_hdr could specify more than 4096 bytes, so assert. */
assert(s->in_needed <= sizeof(s->inpkt));
s->in_state = CSR_DATA;
continue;
}
if (s->in_len >= s->in_data) {
if (s->in_state == CSR_DATA) {
csrhci_in_packet(s, s->inpkt);
memmove(s->inpkt, s->inpkt + s->in_len, s->in_len - s->in_data);
s->in_len -= s->in_data;
s->in_hdr = INT_MAX;
s->in_data = INT_MAX;
plen = 0;
} else
break;
csrhci_ready_for_next_inpkt(s);
}
}
return len;
return total;
}
static void csrhci_out_hci_packet_event(void *opaque,
......@@ -389,11 +416,9 @@ static void csrhci_reset(struct csrhci_s *s)
{
s->out_len = 0;
s->out_size = FIFO_LEN;
s->in_len = 0;
csrhci_ready_for_next_inpkt(s);
s->baud_delay = NANOSECONDS_PER_SECOND;
s->enable = 0;
s->in_hdr = INT_MAX;
s->in_data = INT_MAX;
s->modem_state = 0;
/* After a while... (but sooner than 10ms) */
......
......@@ -983,9 +983,10 @@ void slavio_serial_ms_kbd_init(hwaddr base, qemu_irq irq,
sysbus_mmio_map(s, 0, base);
}
static int escc_init1(SysBusDevice *dev)
static void escc_init1(Object *obj)
{
ESCCState *s = ESCC(dev);
ESCCState *s = ESCC(obj);
SysBusDevice *dev = SYS_BUS_DEVICE(obj);
unsigned int i;
s->chn[0].disabled = s->disabled;
......@@ -994,17 +995,26 @@ static int escc_init1(SysBusDevice *dev)
sysbus_init_irq(dev, &s->chn[i].irq);
s->chn[i].chn = 1 - i;
s->chn[i].clock = s->frequency / 2;
if (s->chn[i].chr) {
qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
serial_receive1, serial_event, &s->chn[i]);
}
}
s->chn[0].otherchn = &s->chn[1];
s->chn[1].otherchn = &s->chn[0];
memory_region_init_io(&s->mmio, OBJECT(s), &escc_mem_ops, s, "escc",
memory_region_init_io(&s->mmio, obj, &escc_mem_ops, s, "escc",
ESCC_SIZE << s->it_shift);
sysbus_init_mmio(dev, &s->mmio);
}
static void escc_realize(DeviceState *dev, Error **errp)
{
ESCCState *s = ESCC(dev);
unsigned int i;
for (i = 0; i < 2; i++) {
if (s->chn[i].chr) {
qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
serial_receive1, serial_event, &s->chn[i]);
}
}
if (s->chn[0].type == mouse) {
qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0,
......@@ -1014,8 +1024,6 @@ static int escc_init1(SysBusDevice *dev)
s->chn[1].hs = qemu_input_handler_register((DeviceState *)(&s->chn[1]),
&sunkbd_handler);
}
return 0;
}
static Property escc_properties[] = {
......@@ -1032,10 +1040,9 @@ static Property escc_properties[] = {
static void escc_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = escc_init1;
dc->reset = escc_reset;
dc->realize = escc_realize;
dc->vmsd = &vmstate_escc;
dc->props = escc_properties;
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
......@@ -1045,6 +1052,7 @@ static const TypeInfo escc_info = {
.name = TYPE_ESCC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(ESCCState),
.instance_init = escc_init1,
.class_init = escc_class_init,
};
......
......@@ -159,6 +159,11 @@ static const MemoryRegionOps ser_ops = {
}
};
static Property etraxfs_ser_properties[] = {
DEFINE_PROP_CHR("chardev", ETRAXSerial, chr),
DEFINE_PROP_END_OF_LIST(),
};
static void serial_receive(void *opaque, const uint8_t *buf, int size)
{
ETRAXSerial *s = opaque;
......@@ -209,40 +214,42 @@ static void etraxfs_ser_reset(DeviceState *d)
}
static int etraxfs_ser_init(SysBusDevice *dev)
static void etraxfs_ser_init(Object *obj)
{
ETRAXSerial *s = ETRAX_SERIAL(dev);
ETRAXSerial *s = ETRAX_SERIAL(obj);
SysBusDevice *dev = SYS_BUS_DEVICE(obj);
sysbus_init_irq(dev, &s->irq);
memory_region_init_io(&s->mmio, OBJECT(s), &ser_ops, s,
memory_region_init_io(&s->mmio, obj, &ser_ops, s,
"etraxfs-serial", R_MAX * 4);
sysbus_init_mmio(dev, &s->mmio);
}
static void etraxfs_ser_realize(DeviceState *dev, Error **errp)
{
ETRAXSerial *s = ETRAX_SERIAL(dev);
/* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */
s->chr = qemu_char_get_next_serial();
if (s->chr) {
qemu_chr_add_handlers(s->chr,
serial_can_receive, serial_receive,
serial_event, s);
}
return 0;
}
static void etraxfs_ser_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = etraxfs_ser_init;
dc->reset = etraxfs_ser_reset;
/* Reason: init() method uses qemu_char_get_next_serial() */
dc->cannot_instantiate_with_device_add_yet = true;
dc->props = etraxfs_ser_properties;
dc->realize = etraxfs_ser_realize;
}
static const TypeInfo etraxfs_ser_info = {
.name = TYPE_ETRAX_FS_SERIAL,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(ETRAXSerial),
.instance_init = etraxfs_ser_init,
.class_init = etraxfs_ser_class_init,
};
......
......@@ -114,17 +114,13 @@ static void juart_reset(DeviceState *d)
s->jrx = 0;
}
static int lm32_juart_init(SysBusDevice *dev)
static void lm32_juart_realize(DeviceState *dev, Error **errp)
{
LM32JuartState *s = LM32_JUART(dev);
/* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */
s->chr = qemu_char_get_next_serial();
if (s->chr) {
qemu_chr_add_handlers(s->chr, juart_can_rx, juart_rx, juart_event, s);
}
return 0;
}
static const VMStateDescription vmstate_lm32_juart = {
......@@ -138,16 +134,19 @@ static const VMStateDescription vmstate_lm32_juart = {
}
};
static Property lm32_juart_properties[] = {
DEFINE_PROP_CHR("chardev", LM32JuartState, chr),
DEFINE_PROP_END_OF_LIST(),
};
static void lm32_juart_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = lm32_juart_init;
dc->reset = juart_reset;
dc->vmsd = &vmstate_lm32_juart;
/* Reason: init() method uses qemu_char_get_next_serial() */
dc->cannot_instantiate_with_device_add_yet = true;
dc->props = lm32_juart_properties;
dc->realize = lm32_juart_realize;
}
static const TypeInfo lm32_juart_info = {
......
......@@ -249,23 +249,25 @@ static void uart_reset(DeviceState *d)
s->regs[R_LSR] = LSR_THRE | LSR_TEMT;
}
static int lm32_uart_init(SysBusDevice *dev)
static void lm32_uart_init(Object *obj)
{
LM32UartState *s = LM32_UART(dev);
LM32UartState *s = LM32_UART(obj);
SysBusDevice *dev = SYS_BUS_DEVICE(obj);
sysbus_init_irq(dev, &s->irq);
memory_region_init_io(&s->iomem, OBJECT(s), &uart_ops, s,
memory_region_init_io(&s->iomem, obj, &uart_ops, s,
"uart", R_MAX * 4);
sysbus_init_mmio(dev, &s->iomem);
}
static void lm32_uart_realize(DeviceState *dev, Error **errp)
{
LM32UartState *s = LM32_UART(dev);
/* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */
s->chr = qemu_char_get_next_serial();
if (s->chr) {
qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
}
return 0;
}
static const VMStateDescription vmstate_lm32_uart = {
......@@ -278,22 +280,26 @@ static const VMStateDescription vmstate_lm32_uart = {
}
};
static Property lm32_uart_properties[] = {
DEFINE_PROP_CHR("chardev", LM32UartState, chr),
DEFINE_PROP_END_OF_LIST(),
};
static void lm32_uart_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = lm32_uart_init;
dc->reset = uart_reset;
dc->vmsd = &vmstate_lm32_uart;
/* Reason: init() method uses qemu_char_get_next_serial() */
dc->cannot_instantiate_with_device_add_yet = true;
dc->props = lm32_uart_properties;
dc->realize = lm32_uart_realize;
}
static const TypeInfo lm32_uart_info = {
.name = TYPE_LM32_UART,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(LM32UartState),
.instance_init = lm32_uart_init,
.class_init = lm32_uart_class_init,
};
......
......@@ -200,8 +200,6 @@ static void milkymist_uart_realize(DeviceState *dev, Error **errp)
{
MilkymistUartState *s = MILKYMIST_UART(dev);
/* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */
s->chr = qemu_char_get_next_serial();
if (s->chr) {
qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
}
......@@ -229,6 +227,11 @@ static const VMStateDescription vmstate_milkymist_uart = {
}
};
static Property milkymist_uart_properties[] = {
DEFINE_PROP_CHR("chardev", MilkymistUartState, chr),
DEFINE_PROP_END_OF_LIST(),
};
static void milkymist_uart_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
......@@ -236,8 +239,7 @@ static void milkymist_uart_class_init(ObjectClass *klass, void *data)
dc->realize = milkymist_uart_realize;
dc->reset = milkymist_uart_reset;
dc->vmsd = &vmstate_milkymist_uart;
/* Reason: realize() method uses qemu_char_get_next_serial() */
dc->cannot_instantiate_with_device_add_yet = true;
dc->props = milkymist_uart_properties;
}
static const TypeInfo milkymist_uart_info = {
......
......@@ -37,6 +37,7 @@
#include "sysemu/block-backend.h"
#include "exec/address-spaces.h"
#include "sysemu/qtest.h"
#include "sysemu/sysemu.h"
#define D(x)
#define DNAND(x)
......@@ -341,8 +342,7 @@ void axisdev88_init(MachineState *machine)
sysbus_create_varargs("etraxfs,timer", 0x3005e000, irq[0x1b], nmi[1], NULL);
for (i = 0; i < 4; i++) {
sysbus_create_simple("etraxfs,serial", 0x30026000 + i * 0x2000,
irq[0x14 + i]);
etraxfs_ser_create(0x30026000 + i * 0x2000, irq[0x14 + i], serial_hds[i]);
}
if (kernel_filename) {
......
......@@ -16,14 +16,31 @@ static inline DeviceState *lm32_pic_init(qemu_irq cpu_irq)
return dev;
}
static inline DeviceState *lm32_juart_init(void)
static inline DeviceState *lm32_juart_init(CharDriverState *chr)
{
DeviceState *dev;
dev = qdev_create(NULL, TYPE_LM32_JUART);
qdev_prop_set_chr(dev, "chardev", chr);
qdev_init_nofail(dev);
return dev;
}
static inline DeviceState *lm32_uart_create(hwaddr addr,
qemu_irq irq,
CharDriverState *chr)
{
DeviceState *dev;
SysBusDevice *s;
dev = qdev_create(NULL, "lm32-uart");
s = SYS_BUS_DEVICE(dev);
qdev_prop_set_chr(dev, "chardev", chr);
qdev_init_nofail(dev);
sysbus_mmio_map(s, 0, addr);
sysbus_connect_irq(s, 0, irq);
return dev;
}
#endif
......@@ -31,6 +31,7 @@
#include "lm32_hwsetup.h"
#include "lm32.h"
#include "exec/address-spaces.h"
#include "sysemu/sysemu.h"
typedef struct {
LM32CPU *cpu;
......@@ -131,12 +132,12 @@ static void lm32_evr_init(MachineState *machine)
irq[i] = qdev_get_gpio_in(env->pic_state, i);
}
sysbus_create_simple("lm32-uart", uart0_base, irq[uart0_irq]);
lm32_uart_create(uart0_base, irq[uart0_irq], serial_hds[0]);
sysbus_create_simple("lm32-timer", timer0_base, irq[timer0_irq]);
sysbus_create_simple("lm32-timer", timer1_base, irq[timer1_irq]);
/* make sure juart isn't the first chardev */
env->juart_state = lm32_juart_init();
env->juart_state = lm32_juart_init(serial_hds[1]);
reset_info->bootstrap_pc = flash_base;
......@@ -232,13 +233,13 @@ static void lm32_uclinux_init(MachineState *machine)
irq[i] = qdev_get_gpio_in(env->pic_state, i);
}
sysbus_create_simple("lm32-uart", uart0_base, irq[uart0_irq]);
lm32_uart_create(uart0_base, irq[uart0_irq], serial_hds[0]);
sysbus_create_simple("lm32-timer", timer0_base, irq[timer0_irq]);
sysbus_create_simple("lm32-timer", timer1_base, irq[timer1_irq]);
sysbus_create_simple("lm32-timer", timer2_base, irq[timer2_irq]);
/* make sure juart isn't the first chardev */
env->juart_state = lm32_juart_init();
env->juart_state = lm32_juart_init(serial_hds[1]);
reset_info->bootstrap_pc = flash_base;
......
......@@ -5,11 +5,13 @@
#include "net/net.h"
static inline DeviceState *milkymist_uart_create(hwaddr base,
qemu_irq irq)
qemu_irq irq,
CharDriverState *chr)
{
DeviceState *dev;
dev = qdev_create(NULL, "milkymist-uart");
qdev_prop_set_chr(dev, "chardev", chr);
qdev_init_nofail(dev);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq);
......
......@@ -159,7 +159,7 @@ milkymist_init(MachineState *machine)
}
g_free(bios_filename);
milkymist_uart_create(0x60000000, irq[0]);
milkymist_uart_create(0x60000000, irq[0], serial_hds[0]);
milkymist_sysctl_create(0x60001000, irq[1], irq[2], irq[3],
80000000, 0x10014d31, 0x0000041f, 0x00000001);
milkymist_hpdmc_create(0x60002000);
......@@ -175,7 +175,7 @@ milkymist_init(MachineState *machine)
0x20000000, 0x1000, 0x20020000, 0x2000);
/* make sure juart isn't the first chardev */
env->juart_state = lm32_juart_init();
env->juart_state = lm32_juart_init(serial_hds[1]);
if (kernel_filename) {
uint64_t entry;
......
......@@ -33,7 +33,6 @@
#include "sysemu/hostmem.h"
#include "sysemu/qtest.h"
#include "qapi/visitor.h"
#include "exec/ram_addr.h"
#include "hw/misc/ivshmem.h"
......@@ -533,7 +532,7 @@ static void process_msg_shmem(IVShmemState *s, int fd, Error **errp)
}
memory_region_init_ram_ptr(&s->server_bar2, OBJECT(s),
"ivshmem.bar2", size, ptr);
qemu_set_ram_fd(memory_region_get_ram_addr(&s->server_bar2), fd);
memory_region_set_fd(&s->server_bar2, fd);
s->ivshmem_bar2 = &s->server_bar2;
}
......@@ -940,7 +939,7 @@ static void ivshmem_exit(PCIDevice *dev)
strerror(errno));
}
fd = qemu_get_ram_fd(memory_region_get_ram_addr(s->ivshmem_bar2));
fd = memory_region_get_fd(s->ivshmem_bar2);
close(fd);
}
......
......@@ -650,7 +650,9 @@ static int megasas_init_firmware(MegasasState *s, MegasasCmd *cmd)
pa_hi = le32_to_cpu(initq->pi_addr_hi);
s->producer_pa = ((uint64_t) pa_hi << 32) | pa_lo;
s->reply_queue_head = ldl_le_pci_dma(pcid, s->producer_pa);
s->reply_queue_head %= MEGASAS_MAX_FRAMES;
s->reply_queue_tail = ldl_le_pci_dma(pcid, s->consumer_pa);
s->reply_queue_tail %= MEGASAS_MAX_FRAMES;
flags = le32_to_cpu(initq->flags);
if (flags & MFI_QUEUE_FLAG_CONTEXT64) {
s->flags |= MEGASAS_MASK_USE_QUEUE64;
......@@ -1293,7 +1295,7 @@ static int megasas_dcmd_ld_get_info(MegasasState *s, MegasasCmd *cmd)
static int megasas_dcmd_cfg_read(MegasasState *s, MegasasCmd *cmd)
{
uint8_t data[4096];
uint8_t data[4096] = { 0 };
struct mfi_config_data *info;
int num_pd_disks = 0, array_offset, ld_offset;
BusChild *kid;
......@@ -1446,7 +1448,7 @@ static int megasas_dcmd_set_properties(MegasasState *s, MegasasCmd *cmd)
dcmd_size);
return MFI_STAT_INVALID_PARAMETER;
}
dma_buf_write((uint8_t *)&info, cmd->iov_size, &cmd->qsg);
dma_buf_write((uint8_t *)&info, dcmd_size, &cmd->qsg);
trace_megasas_dcmd_unsupported(cmd->index, cmd->iov_size);
return MFI_STAT_OK;
}
......
......@@ -754,11 +754,6 @@ static void mptsas_fetch_request(MPTSASState *s)
hwaddr addr;
int size;
if (s->state != MPI_IOC_STATE_OPERATIONAL) {
mptsas_set_fault(s, MPI_IOCSTATUS_INVALID_STATE);
return;
}
/* Read the message header from the guest first. */
addr = s->host_mfa_high_addr | MPTSAS_FIFO_GET(s, request_post);
pci_dma_read(pci, addr, req, sizeof(hdr));
......@@ -789,6 +784,10 @@ static void mptsas_fetch_requests(void *opaque)
{
MPTSASState *s = opaque;
if (s->state != MPI_IOC_STATE_OPERATIONAL) {
mptsas_set_fault(s, MPI_IOCSTATUS_INVALID_STATE);
return;
}
while (!MPTSAS_FIFO_EMPTY(s, request_post)) {
mptsas_fetch_request(s);
}
......
此差异已折叠。
......@@ -222,6 +222,18 @@ static void scsi_read_complete(void * opaque, int ret)
r->buf[3] |= 0x80;
}
}
if (s->type == TYPE_DISK &&
r->req.cmd.buf[0] == INQUIRY &&
r->req.cmd.buf[2] == 0xb0) {
uint32_t max_xfer_len = blk_get_max_transfer_length(s->conf.blk);
if (max_xfer_len) {
stl_be_p(&r->buf[8], max_xfer_len);
/* Also take care of the opt xfer len. */
if (ldl_be_p(&r->buf[12]) > max_xfer_len) {
stl_be_p(&r->buf[12], max_xfer_len);
}
}
}
scsi_req_data(&r->req, len);
scsi_req_unref(&r->req);
}
......
......@@ -153,7 +153,7 @@ pvscsi_log2(uint32_t input)
return log;
}
static void
static int
pvscsi_ring_init_data(PVSCSIRingInfo *m, PVSCSICmdDescSetupRings *ri)
{
int i;
......@@ -161,6 +161,10 @@ pvscsi_ring_init_data(PVSCSIRingInfo *m, PVSCSICmdDescSetupRings *ri)
uint32_t req_ring_size, cmp_ring_size;
m->rs_pa = ri->ringsStatePPN << VMW_PAGE_SHIFT;
if ((ri->reqRingNumPages > PVSCSI_SETUP_RINGS_MAX_NUM_PAGES)
|| (ri->cmpRingNumPages > PVSCSI_SETUP_RINGS_MAX_NUM_PAGES)) {
return -1;
}
req_ring_size = ri->reqRingNumPages * PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE;
cmp_ring_size = ri->cmpRingNumPages * PVSCSI_MAX_NUM_CMP_ENTRIES_PER_PAGE;
txr_len_log2 = pvscsi_log2(req_ring_size - 1);
......@@ -192,15 +196,20 @@ pvscsi_ring_init_data(PVSCSIRingInfo *m, PVSCSICmdDescSetupRings *ri)
/* Flush ring state page changes */
smp_wmb();
return 0;
}
static void
static int
pvscsi_ring_init_msg(PVSCSIRingInfo *m, PVSCSICmdDescSetupMsgRing *ri)
{
int i;
uint32_t len_log2;
uint32_t ring_size;
if (ri->numPages > PVSCSI_SETUP_MSG_RING_MAX_NUM_PAGES) {
return -1;
}
ring_size = ri->numPages * PVSCSI_MAX_NUM_MSG_ENTRIES_PER_PAGE;
len_log2 = pvscsi_log2(ring_size - 1);
......@@ -220,6 +229,8 @@ pvscsi_ring_init_msg(PVSCSIRingInfo *m, PVSCSICmdDescSetupMsgRing *ri)
/* Flush ring state page changes */
smp_wmb();
return 0;
}
static void
......@@ -770,7 +781,10 @@ pvscsi_on_cmd_setup_rings(PVSCSIState *s)
trace_pvscsi_on_cmd_arrived("PVSCSI_CMD_SETUP_RINGS");
pvscsi_dbg_dump_tx_rings_config(rc);
pvscsi_ring_init_data(&s->rings, rc);
if (pvscsi_ring_init_data(&s->rings, rc) < 0) {
return PVSCSI_COMMAND_PROCESSING_FAILED;
}
s->rings_info_valid = TRUE;
return PVSCSI_COMMAND_PROCESSING_SUCCEEDED;
}
......@@ -850,7 +864,9 @@ pvscsi_on_cmd_setup_msg_ring(PVSCSIState *s)
}
if (s->rings_info_valid) {
pvscsi_ring_init_msg(&s->rings, rc);
if (pvscsi_ring_init_msg(&s->rings, rc) < 0) {
return PVSCSI_COMMAND_PROCESSING_FAILED;
}
s->msg_ring_info_valid = TRUE;
}
return sizeof(PVSCSICmdDescSetupMsgRing) / sizeof(uint32_t);
......
......@@ -17,7 +17,6 @@
#include "sysemu/kvm.h"
#include "qemu/error-report.h"
#include "qemu/sockets.h"
#include "exec/ram_addr.h"
#include "migration/migration.h"
#include <sys/ioctl.h>
......@@ -247,18 +246,18 @@ static int vhost_user_set_mem_table(struct vhost_dev *dev,
for (i = 0; i < dev->mem->nregions; ++i) {
struct vhost_memory_region *reg = dev->mem->regions + i;
ram_addr_t ram_addr;
ram_addr_t offset;
MemoryRegion *mr;
assert((uintptr_t)reg->userspace_addr == reg->userspace_addr);
qemu_ram_addr_from_host((void *)(uintptr_t)reg->userspace_addr,
&ram_addr);
fd = qemu_get_ram_fd(ram_addr);
mr = memory_region_from_host((void *)(uintptr_t)reg->userspace_addr,
&offset);
fd = memory_region_get_fd(mr);
if (fd > 0) {
msg.payload.memory.regions[fd_num].userspace_addr = reg->userspace_addr;
msg.payload.memory.regions[fd_num].memory_size = reg->memory_size;
msg.payload.memory.regions[fd_num].guest_phys_addr = reg->guest_phys_addr;
msg.payload.memory.regions[fd_num].mmap_offset = reg->userspace_addr -
(uintptr_t) qemu_get_ram_block_host_ptr(ram_addr);
msg.payload.memory.regions[fd_num].mmap_offset = offset;
assert(fd_num < VHOST_MEMORY_MAX_NREGIONS);
fds[fd_num++] = fd;
}
......@@ -616,17 +615,15 @@ static bool vhost_user_can_merge(struct vhost_dev *dev,
uint64_t start1, uint64_t size1,
uint64_t start2, uint64_t size2)
{
ram_addr_t ram_addr;
ram_addr_t offset;
int mfd, rfd;
MemoryRegion *mr;
mr = qemu_ram_addr_from_host((void *)(uintptr_t)start1, &ram_addr);
assert(mr);
mfd = qemu_get_ram_fd(ram_addr);
mr = memory_region_from_host((void *)(uintptr_t)start1, &offset);
mfd = memory_region_get_fd(mr);
mr = qemu_ram_addr_from_host((void *)(uintptr_t)start2, &ram_addr);
assert(mr);
rfd = qemu_get_ram_fd(ram_addr);
mr = memory_region_from_host((void *)(uintptr_t)start2, &offset);
rfd = memory_region_get_fd(mr);
return mfd == rfd;
}
......
......@@ -57,10 +57,10 @@ typedef uint32_t CPUReadMemoryFunc(void *opaque, hwaddr addr);
void qemu_ram_remap(ram_addr_t addr, ram_addr_t length);
/* This should not be used by devices. */
MemoryRegion *qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr);
ram_addr_t qemu_ram_addr_from_host(void *ptr);
RAMBlock *qemu_ram_block_by_name(const char *name);
RAMBlock *qemu_ram_block_from_host(void *ptr, bool round_offset,
ram_addr_t *ram_addr, ram_addr_t *offset);
ram_addr_t *offset);
void qemu_ram_set_idstr(RAMBlock *block, const char *name, DeviceState *dev);
void qemu_ram_unset_idstr(RAMBlock *block);
const char *qemu_ram_get_idstr(RAMBlock *rb);
......
......@@ -32,6 +32,8 @@
#include "qom/object.h"
#include "qemu/rcu.h"
#define RAM_ADDR_INVALID (~(ram_addr_t)0)
#define MAX_PHYS_ADDR_SPACE_BITS 62
#define MAX_PHYS_ADDR (((hwaddr)1 << MAX_PHYS_ADDR_SPACE_BITS) - 1)
......@@ -666,6 +668,35 @@ static inline bool memory_region_is_rom(MemoryRegion *mr)
*/
int memory_region_get_fd(MemoryRegion *mr);
/**
* memory_region_set_fd: Mark a RAM memory region as backed by a
* file descriptor.
*
* This function is typically used after memory_region_init_ram_ptr().
*
* @mr: the memory region being queried.
* @fd: the file descriptor that backs @mr.
*/
void memory_region_set_fd(MemoryRegion *mr, int fd);
/**
* memory_region_from_host: Convert a pointer into a RAM memory region
* and an offset within it.
*
* Given a host pointer inside a RAM memory region (created with
* memory_region_init_ram() or memory_region_init_ram_ptr()), return
* the MemoryRegion and the offset within it.
*
* Use with care; by the time this function returns, the returned pointer is
* not protected by RCU anymore. If the caller is not within an RCU critical
* section and does not hold the iothread lock, it must have other means of
* protecting the pointer, such as a reference to the region that includes
* the incoming ram_addr_t.
*
* @mr: the memory region being queried.
*/
MemoryRegion *memory_region_from_host(void *ptr, ram_addr_t *offset);
/**
* memory_region_get_ram_ptr: Get a pointer into a RAM memory region.
*
......@@ -1362,7 +1393,7 @@ MemTxResult address_space_read_continue(AddressSpace *as, hwaddr addr,
MemoryRegion *mr);
MemTxResult address_space_read_full(AddressSpace *as, hwaddr addr,
MemTxAttrs attrs, uint8_t *buf, int len);
void *qemu_get_ram_ptr(RAMBlock *ram_block, ram_addr_t addr);
void *qemu_map_ram_ptr(RAMBlock *ram_block, ram_addr_t addr);
static inline bool memory_access_is_direct(MemoryRegion *mr, bool is_write)
{
......@@ -1400,8 +1431,7 @@ MemTxResult address_space_read(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
l = len;
mr = address_space_translate(as, addr, &addr1, &l, false);
if (len == l && memory_access_is_direct(mr, false)) {
addr1 += memory_region_get_ram_addr(mr);
ptr = qemu_get_ram_ptr(mr->ram_block, addr1);
ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
memcpy(buf, ptr, len);
} else {
result = address_space_read_continue(as, addr, attrs, buf, len,
......
......@@ -105,9 +105,6 @@ RAMBlock *qemu_ram_alloc_resizeable(ram_addr_t size, ram_addr_t max_size,
uint64_t length,
void *host),
MemoryRegion *mr, Error **errp);
int qemu_get_ram_fd(ram_addr_t addr);
void qemu_set_ram_fd(ram_addr_t addr, int fd);
void *qemu_get_ram_block_host_ptr(ram_addr_t addr);
void qemu_ram_free(RAMBlock *block);
int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, Error **errp);
......
......@@ -46,4 +46,20 @@ etraxfs_eth_init(NICInfo *nd, hwaddr base, int phyaddr,
return dev;
}
static inline DeviceState *etraxfs_ser_create(hwaddr addr,
qemu_irq irq,
CharDriverState *chr)
{
DeviceState *dev;
SysBusDevice *s;
dev = qdev_create(NULL, "etraxfs,serial");
s = SYS_BUS_DEVICE(dev);
qdev_prop_set_chr(dev, "chardev", chr);
qdev_init_nofail(dev);
sysbus_mmio_map(s, 0, addr);
sysbus_connect_irq(s, 0, irq);
return dev;
}
#endif
......@@ -36,7 +36,18 @@
#define smp_wmb() ({ barrier(); __atomic_thread_fence(__ATOMIC_RELEASE); barrier(); })
#define smp_rmb() ({ barrier(); __atomic_thread_fence(__ATOMIC_ACQUIRE); barrier(); })
/* Most compilers currently treat consume and acquire the same, but really
* no processors except Alpha need a barrier here. Leave it in if
* using Thread Sanitizer to avoid warnings, otherwise optimize it away.
*/
#if defined(__SANITIZE_THREAD__)
#define smp_read_barrier_depends() ({ barrier(); __atomic_thread_fence(__ATOMIC_CONSUME); barrier(); })
#elsif defined(__alpha__)
#define smp_read_barrier_depends() asm volatile("mb":::"memory")
#else
#define smp_read_barrier_depends() barrier()
#endif
/* Weak atomic operations prevent the compiler moving other
* loads/stores past the atomic operation load/store. However there is
......@@ -56,13 +67,23 @@
__atomic_store(ptr, &_val, __ATOMIC_RELAXED); \
} while(0)
/* Atomic RCU operations imply weak memory barriers */
/* See above: most compilers currently treat consume and acquire the
* same, but this slows down atomic_rcu_read unnecessarily.
*/
#ifdef __SANITIZE_THREAD__
#define atomic_rcu_read__nocheck(ptr, valptr) \
__atomic_load(ptr, valptr, __ATOMIC_CONSUME);
#else
#define atomic_rcu_read__nocheck(ptr, valptr) \
__atomic_load(ptr, valptr, __ATOMIC_RELAXED); \
smp_read_barrier_depends();
#endif
#define atomic_rcu_read(ptr) \
({ \
QEMU_BUILD_BUG_ON(sizeof(*ptr) > sizeof(void *)); \
typeof(*ptr) _val; \
__atomic_load(ptr, &_val, __ATOMIC_CONSUME); \
atomic_rcu_read__nocheck(ptr, &_val); \
_val; \
})
......
......@@ -33,8 +33,6 @@
//#define DEBUG_UNASSIGNED
#define RAM_ADDR_INVALID (~(ram_addr_t)0)
static unsigned memory_region_transaction_depth;
static bool memory_region_update_pending;
static bool ioeventfd_update_pending;
......@@ -227,6 +225,7 @@ struct FlatRange {
hwaddr offset_in_region;
AddrRange addr;
uint8_t dirty_log_mask;
bool romd_mode;
bool readonly;
};
......@@ -251,6 +250,7 @@ static bool flatrange_equal(FlatRange *a, FlatRange *b)
return a->mr == b->mr
&& addrrange_equal(a->addr, b->addr)
&& a->offset_in_region == b->offset_in_region
&& a->romd_mode == b->romd_mode
&& a->readonly == b->readonly;
}
......@@ -310,6 +310,7 @@ static bool can_merge(FlatRange *r1, FlatRange *r2)
r1->addr.size),
int128_make64(r2->offset_in_region))
&& r1->dirty_log_mask == r2->dirty_log_mask
&& r1->romd_mode == r2->romd_mode
&& r1->readonly == r2->readonly;
}
......@@ -663,6 +664,7 @@ static void render_memory_region(FlatView *view,
fr.mr = mr;
fr.dirty_log_mask = memory_region_get_dirty_log_mask(mr);
fr.romd_mode = mr->romd_mode;
fr.readonly = readonly;
/* Render the region itself into any gaps left by the current view. */
......@@ -1622,13 +1624,26 @@ void memory_region_reset_dirty(MemoryRegion *mr, hwaddr addr,
int memory_region_get_fd(MemoryRegion *mr)
{
if (mr->alias) {
return memory_region_get_fd(mr->alias);
int fd;
rcu_read_lock();
while (mr->alias) {
mr = mr->alias;
}
fd = mr->ram_block->fd;
rcu_read_unlock();
assert(mr->ram_block);
return fd;
}
return qemu_get_ram_fd(memory_region_get_ram_addr(mr));
void memory_region_set_fd(MemoryRegion *mr, int fd)
{
rcu_read_lock();
while (mr->alias) {
mr = mr->alias;
}
mr->ram_block->fd = fd;
rcu_read_unlock();
}
void *memory_region_get_ram_ptr(MemoryRegion *mr)
......@@ -1642,10 +1657,22 @@ void *memory_region_get_ram_ptr(MemoryRegion *mr)
mr = mr->alias;
}
assert(mr->ram_block);
ptr = qemu_get_ram_ptr(mr->ram_block, memory_region_get_ram_addr(mr));
ptr = qemu_map_ram_ptr(mr->ram_block, offset);
rcu_read_unlock();
return ptr + offset;
return ptr;
}
MemoryRegion *memory_region_from_host(void *ptr, ram_addr_t *offset)
{
RAMBlock *block;
block = qemu_ram_block_from_host(ptr, false, offset);
if (!block) {
return NULL;
}
return block->mr;
}
ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr)
......
......@@ -407,7 +407,6 @@ static void *postcopy_ram_fault_thread(void *opaque)
while (true) {
ram_addr_t rb_offset;
ram_addr_t in_raspace;
struct pollfd pfd[2];
/*
......@@ -459,7 +458,7 @@ static void *postcopy_ram_fault_thread(void *opaque)
rb = qemu_ram_block_from_host(
(void *)(uintptr_t)msg.arg.pagefault.address,
true, &in_raspace, &rb_offset);
true, &rb_offset);
if (!rb) {
error_report("postcopy_ram_fault_thread: Fault outside guest: %"
PRIx64, (uint64_t)msg.arg.pagefault.address);
......
......@@ -1153,12 +1153,20 @@ static void nbd_trip(void *opaque)
break;
case NBD_CMD_TRIM:
TRACE("Request type is TRIM");
ret = blk_co_discard(exp->blk, (request.from + exp->dev_offset)
/ BDRV_SECTOR_SIZE,
request.len / BDRV_SECTOR_SIZE);
if (ret < 0) {
LOG("discard failed");
reply.error = -ret;
/* Ignore unaligned head or tail, until block layer adds byte
* interface */
if (request.len >= BDRV_SECTOR_SIZE) {
request.len -= (request.from + request.len) % BDRV_SECTOR_SIZE;
ret = blk_co_discard(exp->blk,
DIV_ROUND_UP(request.from + exp->dev_offset,
BDRV_SECTOR_SIZE),
request.len / BDRV_SECTOR_SIZE);
if (ret < 0) {
LOG("discard failed");
reply.error = -ret;
}
} else {
TRACE("trim request too small, ignoring");
}
if (nbd_co_send_reply(req, &reply, 0) < 0) {
goto out;
......
......@@ -328,23 +328,10 @@ def qlist_foreach(head, field_str):
yield var
def qemu_get_ram_block(ram_addr):
"""Returns the RAMBlock struct to which the given address belongs."""
ram_blocks = gdb.parse_and_eval("ram_list.blocks")
for block in qlist_foreach(ram_blocks, "next"):
if (ram_addr - block["offset"]) < block["used_length"]:
return block
raise gdb.GdbError("Bad ram offset %x" % ram_addr)
def qemu_get_ram_ptr(ram_addr):
def qemu_map_ram_ptr(block, offset):
"""Returns qemu vaddr for given guest physical address."""
block = qemu_get_ram_block(ram_addr)
return block["host"] + (ram_addr - block["offset"])
return block["host"] + offset
def memory_region_get_ram_ptr(memory_region):
......@@ -352,7 +339,7 @@ def memory_region_get_ram_ptr(memory_region):
return (memory_region_get_ram_ptr(memory_region["alias"].dereference())
+ memory_region["alias_offset"])
return qemu_get_ram_ptr(memory_region["ram_block"]["offset"])
return qemu_map_ram_ptr(memory_region["ram_block"], 0)
def get_guest_phys_blocks():
......
此差异已折叠。
@example
@c man begin SYNOPSIS
usage: kvm_stat [OPTION]...
@c man end
@end example
@c man begin DESCRIPTION
kvm_stat prints counts of KVM kernel module trace events. These events signify
state transitions such as guest mode entry and exit.
This tool is useful for observing guest behavior from the host perspective.
Often conclusions about performance or buggy behavior can be drawn from the
output.
The set of KVM kernel module trace events may be specific to the kernel version
or architecture. It is best to check the KVM kernel module source code for the
meaning of events.
Note that trace events are counted globally across all running guests.
@c man end
@c man begin OPTIONS
@table @option
@item -1, --once, --batch
run in batch mode for one second
@item -l, --log
run in logging mode (like vmstat)
@item -t, --tracepoints
retrieve statistics from tracepoints
@item -d, --debugfs
retrieve statistics from debugfs
@item -f, --fields=@var{fields}
fields to display (regex)
@item -h, --help
show help message
@end table
@c man end
@ignore
@setfilename kvm_stat
@settitle Report KVM kernel module event counters.
@c man begin AUTHOR
Stefan Hajnoczi <stefanha@redhat.com>
@c man end
@c man begin SEEALSO
perf(1), trace-cmd(1)
@c man end
@end ignore
......@@ -411,7 +411,8 @@ int kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
if ((env->mcg_cap & MCG_SER_P) && addr
&& (code == BUS_MCEERR_AR || code == BUS_MCEERR_AO)) {
if (qemu_ram_addr_from_host(addr, &ram_addr) == NULL ||
ram_addr = qemu_ram_addr_from_host(addr);
if (ram_addr == RAM_ADDR_INVALID ||
!kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
fprintf(stderr, "Hardware memory error for memory used by "
"QEMU itself instead of guest system!\n");
......@@ -445,7 +446,8 @@ int kvm_arch_on_sigbus(int code, void *addr)
hwaddr paddr;
/* Hope we are lucky for AO MCE */
if (qemu_ram_addr_from_host(addr, &ram_addr) == NULL ||
ram_addr = qemu_ram_addr_from_host(addr);
if (ram_addr == RAM_ADDR_INVALID ||
!kvm_physical_memory_addr_from_host(first_cpu->kvm_state,
addr, &paddr)) {
fprintf(stderr, "Hardware memory error for memory used by "
......
......@@ -511,8 +511,13 @@ static void xen_io_add(MemoryListener *listener,
MemoryRegionSection *section)
{
XenIOState *state = container_of(listener, XenIOState, io_listener);
MemoryRegion *mr = section->mr;
memory_region_ref(section->mr);
if (mr->ops == &unassigned_io_ops) {
return;
}
memory_region_ref(mr);
xen_map_io_section(xen_xc, xen_domid, state->ioservid, section);
}
......@@ -521,10 +526,15 @@ static void xen_io_del(MemoryListener *listener,
MemoryRegionSection *section)
{
XenIOState *state = container_of(listener, XenIOState, io_listener);
MemoryRegion *mr = section->mr;
if (mr->ops == &unassigned_io_ops) {
return;
}
xen_unmap_io_section(xen_xc, xen_domid, state->ioservid, section);
memory_region_unref(section->mr);
memory_region_unref(mr);
}
static void xen_device_realize(DeviceListener *listener,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册