Misc HW patch queue

- Restrict probe_access*() functions to TCG (Phil)
 - Extract do_invalidate_device_tlb from vtd_process_device_iotlb_desc (Clément)
 - Fixes in Loongson IPI model (Bibo & Phil)
 - Make docs/interop/firmware.json compatible with qapi-gen.py script (Thomas)
 - Correct MPC I2C MMIO region size (Zoltan)
 - Remove useless cast in Loongson3 Virt machine (Yao)
 - Various uses of range overlap API (Yao)
 - Use ERRP_GUARD macro in nubus_virtio_mmio_realize (Zhao)
 - Use DMA memory API in Goldfish UART model (Phil)
 - Expose fifo8_pop_buf and introduce fifo8_drop (Phil)
 - MAINTAINERS updates (Zhao, Phil)
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmagFF8ACgkQ4+MsLN6t
 wN5bKg//f5TwUhsy2ff0FJpHheDOj/9Gc2nZ1U/Fp0E5N3sz3A7MGp91wye6Xwi3
 XG34YN9LK1AVzuCdrEEs5Uaxs1ZS1R2mV+fZaGHwYYxPDdnXxGyp/2Q0eyRxzbcN
 zxE2hWscYSZbPVEru4HvZJKfp4XnE1cqA78fJKMAdtq0IPq38tmQNRlJ+gWD9dC6
 ZUHXPFf3DnucvVuwqb0JYO/E+uJpcTtgR6pc09Xtv/HFgMiS0vKZ1I/6LChqAUw9
 eLMpD/5V2naemVadJe98/dL7gIUnhB8GTjsb4ioblG59AO/uojutwjBSQvFxBUUw
 U5lX9OSn20ouwcGiqimsz+5ziwhCG0R6r1zeQJFqUxrpZSscq7NQp9ygbvirm+wS
 edLc8yTPf4MtYOihzPP9jLPcXPZjEV64gSnJISDDFYWANCrysX3suaFEOuVYPl+s
 ZgQYRVSSYOYHgNqBSRkPKKVUxskSQiqLY3SfGJG4EA9Ktt5lD1cLCXQxhdsqphFm
 Ws3zkrVVL0EKl4v/4MtCgITIIctN1ZJE9u3oPJjASqSvK6EebFqAJkc2SidzKHz0
 F3iYX2AheWNHCQ3HFu023EvFryjlxYk95fs2f6Uj2a9yVbi813qsvd3gcZ8t0kTT
 +dmQwpu1MxjzZnA6838R6OCMnC+UpMPqQh3dPkU/5AF2fc3NnN8=
 =J/I2
 -----END PGP SIGNATURE-----

Merge tag 'hw-misc-20240723' of https://github.com/philmd/qemu into staging

Misc HW patch queue

- Restrict probe_access*() functions to TCG (Phil)
- Extract do_invalidate_device_tlb from vtd_process_device_iotlb_desc (Clément)
- Fixes in Loongson IPI model (Bibo & Phil)
- Make docs/interop/firmware.json compatible with qapi-gen.py script (Thomas)
- Correct MPC I2C MMIO region size (Zoltan)
- Remove useless cast in Loongson3 Virt machine (Yao)
- Various uses of range overlap API (Yao)
- Use ERRP_GUARD macro in nubus_virtio_mmio_realize (Zhao)
- Use DMA memory API in Goldfish UART model (Phil)
- Expose fifo8_pop_buf and introduce fifo8_drop (Phil)
- MAINTAINERS updates (Zhao, Phil)

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmagFF8ACgkQ4+MsLN6t
# wN5bKg//f5TwUhsy2ff0FJpHheDOj/9Gc2nZ1U/Fp0E5N3sz3A7MGp91wye6Xwi3
# XG34YN9LK1AVzuCdrEEs5Uaxs1ZS1R2mV+fZaGHwYYxPDdnXxGyp/2Q0eyRxzbcN
# zxE2hWscYSZbPVEru4HvZJKfp4XnE1cqA78fJKMAdtq0IPq38tmQNRlJ+gWD9dC6
# ZUHXPFf3DnucvVuwqb0JYO/E+uJpcTtgR6pc09Xtv/HFgMiS0vKZ1I/6LChqAUw9
# eLMpD/5V2naemVadJe98/dL7gIUnhB8GTjsb4ioblG59AO/uojutwjBSQvFxBUUw
# U5lX9OSn20ouwcGiqimsz+5ziwhCG0R6r1zeQJFqUxrpZSscq7NQp9ygbvirm+wS
# edLc8yTPf4MtYOihzPP9jLPcXPZjEV64gSnJISDDFYWANCrysX3suaFEOuVYPl+s
# ZgQYRVSSYOYHgNqBSRkPKKVUxskSQiqLY3SfGJG4EA9Ktt5lD1cLCXQxhdsqphFm
# Ws3zkrVVL0EKl4v/4MtCgITIIctN1ZJE9u3oPJjASqSvK6EebFqAJkc2SidzKHz0
# F3iYX2AheWNHCQ3HFu023EvFryjlxYk95fs2f6Uj2a9yVbi813qsvd3gcZ8t0kTT
# +dmQwpu1MxjzZnA6838R6OCMnC+UpMPqQh3dPkU/5AF2fc3NnN8=
# =J/I2
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 24 Jul 2024 06:36:47 AM AEST
# gpg:                using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE
# gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [full]

* tag 'hw-misc-20240723' of https://github.com/philmd/qemu: (28 commits)
  MAINTAINERS: Add myself as a reviewer of machine core
  MAINTAINERS: Cover guest-agent in QAPI schema
  util/fifo8: Introduce fifo8_drop()
  util/fifo8: Expose fifo8_pop_buf()
  util/fifo8: Rename fifo8_pop_buf() -> fifo8_pop_bufptr()
  util/fifo8: Rename fifo8_peek_buf() -> fifo8_peek_bufptr()
  util/fifo8: Use fifo8_reset() in fifo8_create()
  util/fifo8: Fix style
  chardev/char-fe: Document returned value on error
  hw/char/goldfish: Use DMA memory API
  hw/nubus/virtio-mmio: Fix missing ERRP_GUARD() in realize handler
  dump: make range overlap check more readable
  crypto/block-luks: make range overlap check more readable
  system/memory_mapping: make range overlap check more readable
  sparc/ldst_helper: make range overlap check more readable
  cxl/mailbox: make range overlap check more readable
  util/range: Make ranges_overlap() return bool
  hw/mips/loongson3_virt: remove useless type cast
  hw/i2c/mpc_i2c: Fix mmio region size
  docs/interop/firmware.json: convert "Example" section
  ...

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2024-07-24 15:39:43 +10:00
commit 6410f877f5
26 changed files with 226 additions and 161 deletions

View File

@ -1879,6 +1879,7 @@ M: Eduardo Habkost <eduardo@habkost.net>
M: Marcel Apfelbaum <marcel.apfelbaum@gmail.com> M: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
R: Philippe Mathieu-Daudé <philmd@linaro.org> R: Philippe Mathieu-Daudé <philmd@linaro.org>
R: Yanan Wang <wangyanan55@huawei.com> R: Yanan Wang <wangyanan55@huawei.com>
R: Zhao Liu <zhao1.liu@intel.com>
S: Supported S: Supported
F: hw/core/cpu-common.c F: hw/core/cpu-common.c
F: hw/core/cpu-sysemu.c F: hw/core/cpu-sysemu.c
@ -3221,6 +3222,7 @@ M: Eric Blake <eblake@redhat.com>
M: Markus Armbruster <armbru@redhat.com> M: Markus Armbruster <armbru@redhat.com>
S: Supported S: Supported
F: qapi/*.json F: qapi/*.json
F: qga/qapi-schema.json
T: git https://repo.or.cz/qemu/armbru.git qapi-next T: git https://repo.or.cz/qemu/armbru.git qapi-next
QObject QObject

View File

@ -18,20 +18,6 @@ void tb_flush(CPUState *cpu)
{ {
} }
int probe_access_flags(CPUArchState *env, vaddr addr, int size,
MMUAccessType access_type, int mmu_idx,
bool nonfault, void **phost, uintptr_t retaddr)
{
g_assert_not_reached();
}
void *probe_access(CPUArchState *env, vaddr addr, int size,
MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
{
/* Handled by hardware accelerator. */
g_assert_not_reached();
}
G_NORETURN void cpu_loop_exit(CPUState *cpu) G_NORETURN void cpu_loop_exit(CPUState *cpu)
{ {
g_assert_not_reached(); g_assert_not_reached();

View File

@ -81,7 +81,7 @@ static void msmouse_chr_accept_input(Chardev *chr)
const uint8_t *buf; const uint8_t *buf;
uint32_t size; uint32_t size;
buf = fifo8_pop_buf(&mouse->outbuf, MIN(len, avail), &size); buf = fifo8_pop_bufptr(&mouse->outbuf, MIN(len, avail), &size);
qemu_chr_be_write(chr, buf, size); qemu_chr_be_write(chr, buf, size);
len = qemu_chr_be_can_write(chr); len = qemu_chr_be_can_write(chr);
avail -= size; avail -= size;

View File

@ -33,6 +33,7 @@
#include "qemu/uuid.h" #include "qemu/uuid.h"
#include "qemu/bitmap.h" #include "qemu/bitmap.h"
#include "qemu/range.h"
/* /*
* Reference for the LUKS format implemented here is * Reference for the LUKS format implemented here is
@ -572,7 +573,7 @@ qcrypto_block_luks_check_header(const QCryptoBlockLUKS *luks,
header_sectors, header_sectors,
slot2->stripes); slot2->stripes);
if (start1 + len1 > start2 && start2 + len2 > start1) { if (ranges_overlap(start1, len1, start2, len2)) {
error_setg(errp, error_setg(errp,
"Keyslots %zu and %zu are overlapping in the header", "Keyslots %zu and %zu are overlapping in the header",
i, j); i, j);

View File

@ -42,7 +42,7 @@ depending on the guest architecture.
- :ref:`Yes<QEMU-PC-System-emulator>` - :ref:`Yes<QEMU-PC-System-emulator>`
- Yes - Yes
- The ubiquitous desktop PC CPU architecture, 32 and 64 bit. - The ubiquitous desktop PC CPU architecture, 32 and 64 bit.
* - Loongarch * - LoongArch
- Yes - Yes
- Yes - Yes
- A MIPS-like 64bit RISC architecture developed in China - A MIPS-like 64bit RISC architecture developed in China

View File

@ -14,8 +14,10 @@
# = Firmware # = Firmware
## ##
{ 'include' : 'machine.json' } { 'pragma': {
{ 'include' : 'block-core.json' } 'member-name-exceptions': [
'FirmwareArchitecture' # x86_64
] } }
## ##
# @FirmwareOSInterface: # @FirmwareOSInterface:
@ -60,6 +62,27 @@
{ 'enum' : 'FirmwareDevice', { 'enum' : 'FirmwareDevice',
'data' : [ 'flash', 'kernel', 'memory' ] } 'data' : [ 'flash', 'kernel', 'memory' ] }
##
# @FirmwareArchitecture:
#
# Enumeration of architectures for which Qemu uses additional
# firmware files.
#
# @aarch64: 64-bit Arm.
#
# @arm: 32-bit Arm.
#
# @i386: 32-bit x86.
#
# @loongarch64: 64-bit LoongArch. (since: 7.1)
#
# @x86_64: 64-bit x86.
#
# Since: 3.0
##
{ 'enum' : 'FirmwareArchitecture',
'data' : [ 'aarch64', 'arm', 'i386', 'loongarch64', 'x86_64' ] }
## ##
# @FirmwareTarget: # @FirmwareTarget:
# #
@ -81,7 +104,7 @@
# Since: 3.0 # Since: 3.0
## ##
{ 'struct' : 'FirmwareTarget', { 'struct' : 'FirmwareTarget',
'data' : { 'architecture' : 'SysEmuTarget', 'data' : { 'architecture' : 'FirmwareArchitecture',
'machines' : [ 'str' ] } } 'machines' : [ 'str' ] } }
## ##
@ -200,6 +223,20 @@
'enrolled-keys', 'requires-smm', 'secure-boot', 'enrolled-keys', 'requires-smm', 'secure-boot',
'verbose-dynamic', 'verbose-static' ] } 'verbose-dynamic', 'verbose-static' ] }
##
# @FirmwareFormat:
#
# Formats that are supported for firmware images.
#
# @raw: Raw disk image format.
#
# @qcow2: The QCOW2 image format.
#
# Since: 3.0
##
{ 'enum': 'FirmwareFormat',
'data': [ 'raw', 'qcow2' ] }
## ##
# @FirmwareFlashFile: # @FirmwareFlashFile:
# #
@ -219,7 +256,7 @@
## ##
{ 'struct' : 'FirmwareFlashFile', { 'struct' : 'FirmwareFlashFile',
'data' : { 'filename' : 'str', 'data' : { 'filename' : 'str',
'format' : 'BlockdevDriver' } } 'format' : 'FirmwareFormat' } }
## ##
@ -433,7 +470,7 @@
# #
# Since: 3.0 # Since: 3.0
# #
# Examples: # .. qmp-example::
# #
# { # {
# "description": "SeaBIOS", # "description": "SeaBIOS",

View File

@ -30,6 +30,7 @@
#include "migration/blocker.h" #include "migration/blocker.h"
#include "hw/core/cpu.h" #include "hw/core/cpu.h"
#include "win_dump.h" #include "win_dump.h"
#include "qemu/range.h"
#include <zlib.h> #include <zlib.h>
#ifdef CONFIG_LZO #ifdef CONFIG_LZO
@ -574,8 +575,10 @@ static void get_offset_range(hwaddr phys_addr,
QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) { QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) {
if (dump_has_filter(s)) { if (dump_has_filter(s)) {
if (block->target_start >= s->filter_area_begin + s->filter_area_length || if (!ranges_overlap(block->target_start,
block->target_end <= s->filter_area_begin) { block->target_end - block->target_start,
s->filter_area_begin,
s->filter_area_length)) {
/* This block is out of the range */ /* This block is out of the range */
continue; continue;
} }
@ -734,8 +737,9 @@ int64_t dump_filtered_memblock_start(GuestPhysBlock *block,
{ {
if (filter_area_length) { if (filter_area_length) {
/* return -1 if the block is not within filter area */ /* return -1 if the block is not within filter area */
if (block->target_start >= filter_area_start + filter_area_length || if (!ranges_overlap(block->target_start,
block->target_end <= filter_area_start) { block->target_end - block->target_start,
filter_area_start, filter_area_length)) {
return -1; return -1;
} }

View File

@ -16,6 +16,7 @@
#include "qemu/log.h" #include "qemu/log.h"
#include "trace.h" #include "trace.h"
#include "exec/address-spaces.h" #include "exec/address-spaces.h"
#include "sysemu/dma.h"
#include "hw/char/goldfish_tty.h" #include "hw/char/goldfish_tty.h"
#define GOLDFISH_TTY_VERSION 1 #define GOLDFISH_TTY_VERSION 1
@ -69,7 +70,6 @@ static uint64_t goldfish_tty_read(void *opaque, hwaddr addr,
static void goldfish_tty_cmd(GoldfishTTYState *s, uint32_t cmd) static void goldfish_tty_cmd(GoldfishTTYState *s, uint32_t cmd)
{ {
uint32_t to_copy; uint32_t to_copy;
uint8_t *buf;
uint8_t data_out[GOLFISH_TTY_BUFFER_SIZE]; uint8_t data_out[GOLFISH_TTY_BUFFER_SIZE];
int len; int len;
uint64_t ptr; uint64_t ptr;
@ -97,8 +97,8 @@ static void goldfish_tty_cmd(GoldfishTTYState *s, uint32_t cmd)
while (len) { while (len) {
to_copy = MIN(GOLFISH_TTY_BUFFER_SIZE, len); to_copy = MIN(GOLFISH_TTY_BUFFER_SIZE, len);
address_space_rw(&address_space_memory, ptr, dma_memory_read_relaxed(&address_space_memory, ptr,
MEMTXATTRS_UNSPECIFIED, data_out, to_copy, 0); data_out, to_copy);
qemu_chr_fe_write_all(&s->chr, data_out, to_copy); qemu_chr_fe_write_all(&s->chr, data_out, to_copy);
len -= to_copy; len -= to_copy;
@ -109,9 +109,9 @@ static void goldfish_tty_cmd(GoldfishTTYState *s, uint32_t cmd)
len = s->data_len; len = s->data_len;
ptr = s->data_ptr; ptr = s->data_ptr;
while (len && !fifo8_is_empty(&s->rx_fifo)) { while (len && !fifo8_is_empty(&s->rx_fifo)) {
buf = (uint8_t *)fifo8_pop_buf(&s->rx_fifo, len, &to_copy); const uint8_t *buf = fifo8_pop_bufptr(&s->rx_fifo, len, &to_copy);
address_space_rw(&address_space_memory, ptr,
MEMTXATTRS_UNSPECIFIED, buf, to_copy, 1); dma_memory_write_relaxed(&address_space_memory, ptr, buf, to_copy);
len -= to_copy; len -= to_copy;
ptr += to_copy; ptr += to_copy;

View File

@ -1653,8 +1653,8 @@ static CXLRetCode cmd_media_get_poison_list(const struct cxl_cmd *cmd,
QLIST_FOREACH(ent, poison_list, node) { QLIST_FOREACH(ent, poison_list, node) {
/* Check for no overlap */ /* Check for no overlap */
if (ent->start >= query_start + query_length || if (!ranges_overlap(ent->start, ent->length,
ent->start + ent->length <= query_start) { query_start, query_length)) {
continue; continue;
} }
record_count++; record_count++;
@ -1666,8 +1666,8 @@ static CXLRetCode cmd_media_get_poison_list(const struct cxl_cmd *cmd,
uint64_t start, stop; uint64_t start, stop;
/* Check for no overlap */ /* Check for no overlap */
if (ent->start >= query_start + query_length || if (!ranges_overlap(ent->start, ent->length,
ent->start + ent->length <= query_start) { query_start, query_length)) {
continue; continue;
} }

View File

@ -82,7 +82,7 @@ struct MPCI2CState {
uint8_t cr; uint8_t cr;
uint8_t sr; uint8_t sr;
uint8_t dr; uint8_t dr;
uint8_t dfssr; uint8_t dfsrr;
}; };
static bool mpc_i2c_is_enabled(MPCI2CState *s) static bool mpc_i2c_is_enabled(MPCI2CState *s)
@ -293,7 +293,7 @@ static void mpc_i2c_write(void *opaque, hwaddr addr,
} }
break; break;
case MPC_I2C_DFSRR: case MPC_I2C_DFSRR:
s->dfssr = value; s->dfsrr = value;
break; break;
default: default:
DPRINTF("ERROR: Bad write addr 0x%x\n", (unsigned int)addr); DPRINTF("ERROR: Bad write addr 0x%x\n", (unsigned int)addr);
@ -319,7 +319,7 @@ static const VMStateDescription mpc_i2c_vmstate = {
VMSTATE_UINT8(cr, MPCI2CState), VMSTATE_UINT8(cr, MPCI2CState),
VMSTATE_UINT8(sr, MPCI2CState), VMSTATE_UINT8(sr, MPCI2CState),
VMSTATE_UINT8(dr, MPCI2CState), VMSTATE_UINT8(dr, MPCI2CState),
VMSTATE_UINT8(dfssr, MPCI2CState), VMSTATE_UINT8(dfsrr, MPCI2CState),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
} }
}; };
@ -329,7 +329,7 @@ static void mpc_i2c_realize(DeviceState *dev, Error **errp)
MPCI2CState *i2c = MPC_I2C(dev); MPCI2CState *i2c = MPC_I2C(dev);
sysbus_init_irq(SYS_BUS_DEVICE(dev), &i2c->irq); sysbus_init_irq(SYS_BUS_DEVICE(dev), &i2c->irq);
memory_region_init_io(&i2c->iomem, OBJECT(i2c), &i2c_ops, i2c, memory_region_init_io(&i2c->iomem, OBJECT(i2c), &i2c_ops, i2c,
"mpc-i2c", 0x14); "mpc-i2c", 0x15);
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &i2c->iomem); sysbus_init_mmio(SYS_BUS_DEVICE(dev), &i2c->iomem);
i2c->bus = i2c_init_bus(dev, "i2c"); i2c->bus = i2c_init_bus(dev, "i2c");
} }

View File

@ -2666,13 +2666,43 @@ static bool vtd_process_inv_iec_desc(IntelIOMMUState *s,
return true; return true;
} }
static void do_invalidate_device_tlb(VTDAddressSpace *vtd_dev_as,
bool size, hwaddr addr)
{
/*
* According to ATS spec table 2.4:
* S = 0, bits 15:12 = xxxx range size: 4K
* S = 1, bits 15:12 = xxx0 range size: 8K
* S = 1, bits 15:12 = xx01 range size: 16K
* S = 1, bits 15:12 = x011 range size: 32K
* S = 1, bits 15:12 = 0111 range size: 64K
* ...
*/
IOMMUTLBEvent event;
uint64_t sz;
if (size) {
sz = (VTD_PAGE_SIZE * 2) << cto64(addr >> VTD_PAGE_SHIFT);
addr &= ~(sz - 1);
} else {
sz = VTD_PAGE_SIZE;
}
event.type = IOMMU_NOTIFIER_DEVIOTLB_UNMAP;
event.entry.target_as = &vtd_dev_as->as;
event.entry.addr_mask = sz - 1;
event.entry.iova = addr;
event.entry.perm = IOMMU_NONE;
event.entry.translated_addr = 0;
memory_region_notify_iommu(&vtd_dev_as->iommu, 0, event);
}
static bool vtd_process_device_iotlb_desc(IntelIOMMUState *s, static bool vtd_process_device_iotlb_desc(IntelIOMMUState *s,
VTDInvDesc *inv_desc) VTDInvDesc *inv_desc)
{ {
VTDAddressSpace *vtd_dev_as; VTDAddressSpace *vtd_dev_as;
IOMMUTLBEvent event;
hwaddr addr; hwaddr addr;
uint64_t sz;
uint16_t sid; uint16_t sid;
bool size; bool size;
@ -2697,28 +2727,7 @@ static bool vtd_process_device_iotlb_desc(IntelIOMMUState *s,
goto done; goto done;
} }
/* According to ATS spec table 2.4: do_invalidate_device_tlb(vtd_dev_as, size, addr);
* S = 0, bits 15:12 = xxxx range size: 4K
* S = 1, bits 15:12 = xxx0 range size: 8K
* S = 1, bits 15:12 = xx01 range size: 16K
* S = 1, bits 15:12 = x011 range size: 32K
* S = 1, bits 15:12 = 0111 range size: 64K
* ...
*/
if (size) {
sz = (VTD_PAGE_SIZE * 2) << cto64(addr >> VTD_PAGE_SHIFT);
addr &= ~(sz - 1);
} else {
sz = VTD_PAGE_SIZE;
}
event.type = IOMMU_NOTIFIER_DEVIOTLB_UNMAP;
event.entry.target_as = &vtd_dev_as->as;
event.entry.addr_mask = sz - 1;
event.entry.iova = addr;
event.entry.perm = IOMMU_NONE;
event.entry.translated_addr = 0;
memory_region_notify_iommu(&vtd_dev_as->iommu, 0, event);
done: done:
return true; return true;

View File

@ -14,6 +14,7 @@
#include "qapi/error.h" #include "qapi/error.h"
#include "qemu/log.h" #include "qemu/log.h"
#include "exec/address-spaces.h" #include "exec/address-spaces.h"
#include "exec/memory.h"
#include "migration/vmstate.h" #include "migration/vmstate.h"
#ifdef TARGET_LOONGARCH64 #ifdef TARGET_LOONGARCH64
#include "target/loongarch/cpu.h" #include "target/loongarch/cpu.h"
@ -102,7 +103,7 @@ static MemTxResult send_ipi_data(CPUState *cpu, uint64_t val, hwaddr addr,
* if the mask is 0, we need not to do anything. * if the mask is 0, we need not to do anything.
*/ */
if ((val >> 27) & 0xf) { if ((val >> 27) & 0xf) {
data = address_space_ldl(iocsr_as, addr, attrs, NULL); data = address_space_ldl_le(iocsr_as, addr, attrs, NULL);
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
/* get mask for byte writing */ /* get mask for byte writing */
if (val & (0x1 << (27 + i))) { if (val & (0x1 << (27 + i))) {
@ -113,7 +114,7 @@ static MemTxResult send_ipi_data(CPUState *cpu, uint64_t val, hwaddr addr,
data &= mask; data &= mask;
data |= (val >> 32) & ~mask; data |= (val >> 32) & ~mask;
address_space_stl(iocsr_as, addr, data, attrs, NULL); address_space_stl_le(iocsr_as, addr, data, attrs, NULL);
return MEMTX_OK; return MEMTX_OK;
} }
@ -317,6 +318,13 @@ static void loongson_ipi_realize(DeviceState *dev, Error **errp)
} }
} }
static void loongson_ipi_unrealize(DeviceState *dev)
{
LoongsonIPI *s = LOONGSON_IPI(dev);
g_free(s->cpu);
}
static const VMStateDescription vmstate_ipi_core = { static const VMStateDescription vmstate_ipi_core = {
.name = "ipi-single", .name = "ipi-single",
.version_id = 2, .version_id = 2,
@ -352,28 +360,18 @@ static void loongson_ipi_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = loongson_ipi_realize; dc->realize = loongson_ipi_realize;
dc->unrealize = loongson_ipi_unrealize;
device_class_set_props(dc, ipi_properties); device_class_set_props(dc, ipi_properties);
dc->vmsd = &vmstate_loongson_ipi; dc->vmsd = &vmstate_loongson_ipi;
} }
static void loongson_ipi_finalize(Object *obj) static const TypeInfo loongson_ipi_types[] = {
{ {
LoongsonIPI *s = LOONGSON_IPI(obj); .name = TYPE_LOONGSON_IPI,
.parent = TYPE_SYS_BUS_DEVICE,
g_free(s->cpu); .instance_size = sizeof(LoongsonIPI),
} .class_init = loongson_ipi_class_init,
}
static const TypeInfo loongson_ipi_info = {
.name = TYPE_LOONGSON_IPI,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(LoongsonIPI),
.class_init = loongson_ipi_class_init,
.instance_finalize = loongson_ipi_finalize,
}; };
static void loongson_ipi_register_types(void) DEFINE_TYPES(loongson_ipi_types)
{
type_register_static(&loongson_ipi_info);
}
type_init(loongson_ipi_register_types)

View File

@ -355,8 +355,8 @@ static uint64_t load_kernel(CPUMIPSState *env)
kernel_size = load_elf(loaderparams.kernel_filename, NULL, kernel_size = load_elf(loaderparams.kernel_filename, NULL,
cpu_mips_kseg0_to_phys, NULL, cpu_mips_kseg0_to_phys, NULL,
(uint64_t *)&kernel_entry, &kernel_entry,
(uint64_t *)&kernel_low, (uint64_t *)&kernel_high, &kernel_low, &kernel_high,
NULL, 0, EM_MIPS, 1, 0); NULL, 0, EM_MIPS, 1, 0);
if (kernel_size < 0) { if (kernel_size < 0) {
error_report("could not load kernel '%s': %s", error_report("could not load kernel '%s': %s",

View File

@ -349,7 +349,7 @@ static void aw_emac_write(void *opaque, hwaddr offset, uint64_t value,
"allwinner_emac: TX length > fifo data length\n"); "allwinner_emac: TX length > fifo data length\n");
} }
if (len > 0) { if (len > 0) {
data = fifo8_pop_buf(fifo, len, &ret); data = fifo8_pop_bufptr(fifo, len, &ret);
qemu_send_packet(nc, data, ret); qemu_send_packet(nc, data, ret);
aw_emac_tx_reset(s, chan); aw_emac_tx_reset(s, chan);
/* Raise TX interrupt */ /* Raise TX interrupt */

View File

@ -7,6 +7,7 @@
*/ */
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qapi/error.h"
#include "hw/nubus/nubus-virtio-mmio.h" #include "hw/nubus/nubus-virtio-mmio.h"
@ -23,6 +24,7 @@ static void nubus_virtio_mmio_set_input_irq(void *opaque, int n, int level)
static void nubus_virtio_mmio_realize(DeviceState *dev, Error **errp) static void nubus_virtio_mmio_realize(DeviceState *dev, Error **errp)
{ {
ERRP_GUARD();
NubusVirtioMMIODeviceClass *nvmdc = NUBUS_VIRTIO_MMIO_GET_CLASS(dev); NubusVirtioMMIODeviceClass *nvmdc = NUBUS_VIRTIO_MMIO_GET_CLASS(dev);
NubusVirtioMMIO *s = NUBUS_VIRTIO_MMIO(dev); NubusVirtioMMIO *s = NUBUS_VIRTIO_MMIO(dev);
NubusDevice *nd = NUBUS_DEVICE(dev); NubusDevice *nd = NUBUS_DEVICE(dev);

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */ /* SPDX-License-Identifier: GPL-2.0-or-later */
/* /*
* Loongarch LS7A Real Time Clock emulation * LoongArch LS7A Real Time Clock emulation
* *
* Copyright (C) 2021 Loongson Technology Corporation Limited * Copyright (C) 2021 Loongson Technology Corporation Limited
*/ */

View File

@ -197,39 +197,9 @@ static uint8_t esp_fifo_pop(ESPState *s)
return val; return val;
} }
static uint32_t esp_fifo8_pop_buf(Fifo8 *fifo, uint8_t *dest, int maxlen)
{
const uint8_t *buf;
uint32_t n, n2;
int len;
if (maxlen == 0) {
return 0;
}
len = maxlen;
buf = fifo8_pop_buf(fifo, len, &n);
if (dest) {
memcpy(dest, buf, n);
}
/* Add FIFO wraparound if needed */
len -= n;
len = MIN(len, fifo8_num_used(fifo));
if (len) {
buf = fifo8_pop_buf(fifo, len, &n2);
if (dest) {
memcpy(&dest[n], buf, n2);
}
n += n2;
}
return n;
}
static uint32_t esp_fifo_pop_buf(ESPState *s, uint8_t *dest, int maxlen) static uint32_t esp_fifo_pop_buf(ESPState *s, uint8_t *dest, int maxlen)
{ {
uint32_t len = esp_fifo8_pop_buf(&s->fifo, dest, maxlen); uint32_t len = fifo8_pop_buf(&s->fifo, dest, maxlen);
esp_update_drq(s); esp_update_drq(s);
return len; return len;
@ -335,7 +305,7 @@ static void do_command_phase(ESPState *s)
if (!cmdlen || !s->current_dev) { if (!cmdlen || !s->current_dev) {
return; return;
} }
esp_fifo8_pop_buf(&s->cmdfifo, buf, cmdlen); fifo8_pop_buf(&s->cmdfifo, buf, cmdlen);
current_lun = scsi_device_find(&s->bus, 0, s->current_dev->id, s->lun); current_lun = scsi_device_find(&s->bus, 0, s->current_dev->id, s->lun);
if (!current_lun) { if (!current_lun) {
@ -381,7 +351,7 @@ static void do_message_phase(ESPState *s)
/* Ignore extended messages for now */ /* Ignore extended messages for now */
if (s->cmdfifo_cdb_offset) { if (s->cmdfifo_cdb_offset) {
int len = MIN(s->cmdfifo_cdb_offset, fifo8_num_used(&s->cmdfifo)); int len = MIN(s->cmdfifo_cdb_offset, fifo8_num_used(&s->cmdfifo));
esp_fifo8_pop_buf(&s->cmdfifo, NULL, len); fifo8_drop(&s->cmdfifo, len);
s->cmdfifo_cdb_offset = 0; s->cmdfifo_cdb_offset = 0;
} }
} }
@ -486,7 +456,7 @@ static bool esp_cdb_ready(ESPState *s)
return false; return false;
} }
pbuf = fifo8_peek_buf(&s->cmdfifo, len, &n); pbuf = fifo8_peek_bufptr(&s->cmdfifo, len, &n);
if (n < len) { if (n < len) {
/* /*
* In normal use the cmdfifo should never wrap, but include this check * In normal use the cmdfifo should never wrap, but include this check

View File

@ -228,6 +228,7 @@ guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond,
* is thread-safe. * is thread-safe.
* *
* Returns: the number of bytes consumed (0 if no associated Chardev) * Returns: the number of bytes consumed (0 if no associated Chardev)
* or -1 on error.
*/ */
int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len); int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len);
@ -242,6 +243,7 @@ int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len);
* attempted to be written. This function is thread-safe. * attempted to be written. This function is thread-safe.
* *
* Returns: the number of bytes consumed (0 if no associated Chardev) * Returns: the number of bytes consumed (0 if no associated Chardev)
* or -1 on error.
*/ */
int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len); int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len);
@ -253,6 +255,7 @@ int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len);
* Read data to a buffer from the back end. * Read data to a buffer from the back end.
* *
* Returns: the number of bytes read (0 if no associated Chardev) * Returns: the number of bytes read (0 if no associated Chardev)
* or -1 on error.
*/ */
int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len); int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len);

View File

@ -301,6 +301,9 @@ static inline void tlb_flush_range_by_mmuidx_all_cpus_synced(CPUState *cpu,
{ {
} }
#endif #endif
#if defined(CONFIG_TCG)
/** /**
* probe_access: * probe_access:
* @env: CPUArchState * @env: CPUArchState
@ -357,6 +360,7 @@ int probe_access_flags(CPUArchState *env, vaddr addr, int size,
bool nonfault, void **phost, uintptr_t retaddr); bool nonfault, void **phost, uintptr_t retaddr);
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
/** /**
* probe_access_full: * probe_access_full:
* Like probe_access_flags, except also return into @pfull. * Like probe_access_flags, except also return into @pfull.
@ -392,7 +396,8 @@ int probe_access_full_mmu(CPUArchState *env, vaddr addr, int size,
MMUAccessType access_type, int mmu_idx, MMUAccessType access_type, int mmu_idx,
void **phost, CPUTLBEntryFull **pfull); void **phost, CPUTLBEntryFull **pfull);
#endif #endif /* !CONFIG_USER_ONLY */
#endif /* CONFIG_TCG */
static inline tb_page_addr_t tb_page_addr0(const TranslationBlock *tb) static inline tb_page_addr_t tb_page_addr0(const TranslationBlock *tb)
{ {

View File

@ -15,10 +15,9 @@ typedef struct {
* @fifo: struct Fifo8 to initialise with new FIFO * @fifo: struct Fifo8 to initialise with new FIFO
* @capacity: capacity of the newly created FIFO * @capacity: capacity of the newly created FIFO
* *
* Create a FIFO of the specified size. Clients should call fifo8_destroy() * Create a FIFO of the specified capacity. Clients should call fifo8_destroy()
* when finished using the fifo. The FIFO is initially empty. * when finished using the fifo. The FIFO is initially empty.
*/ */
void fifo8_create(Fifo8 *fifo, uint32_t capacity); void fifo8_create(Fifo8 *fifo, uint32_t capacity);
/** /**
@ -26,9 +25,8 @@ void fifo8_create(Fifo8 *fifo, uint32_t capacity);
* @fifo: FIFO to cleanup * @fifo: FIFO to cleanup
* *
* Cleanup a FIFO created with fifo8_create(). Frees memory created for FIFO * Cleanup a FIFO created with fifo8_create(). Frees memory created for FIFO
*storage. The FIFO is no longer usable after this has been called. * storage. The FIFO is no longer usable after this has been called.
*/ */
void fifo8_destroy(Fifo8 *fifo); void fifo8_destroy(Fifo8 *fifo);
/** /**
@ -39,7 +37,6 @@ void fifo8_destroy(Fifo8 *fifo);
* Push a data byte to the FIFO. Behaviour is undefined if the FIFO is full. * Push a data byte to the FIFO. Behaviour is undefined if the FIFO is full.
* Clients are responsible for checking for fullness using fifo8_is_full(). * Clients are responsible for checking for fullness using fifo8_is_full().
*/ */
void fifo8_push(Fifo8 *fifo, uint8_t data); void fifo8_push(Fifo8 *fifo, uint8_t data);
/** /**
@ -52,7 +49,6 @@ void fifo8_push(Fifo8 *fifo, uint8_t data);
* Clients are responsible for checking the space left in the FIFO using * Clients are responsible for checking the space left in the FIFO using
* fifo8_num_free(). * fifo8_num_free().
*/ */
void fifo8_push_all(Fifo8 *fifo, const uint8_t *data, uint32_t num); void fifo8_push_all(Fifo8 *fifo, const uint8_t *data, uint32_t num);
/** /**
@ -64,25 +60,40 @@ void fifo8_push_all(Fifo8 *fifo, const uint8_t *data, uint32_t num);
* *
* Returns: The popped data byte. * Returns: The popped data byte.
*/ */
uint8_t fifo8_pop(Fifo8 *fifo); uint8_t fifo8_pop(Fifo8 *fifo);
/** /**
* fifo8_pop_buf: * fifo8_pop_buf:
* @fifo: FIFO to pop from * @fifo: FIFO to pop from
* @dest: the buffer to write the data into (can be NULL)
* @destlen: size of @dest and maximum number of bytes to pop
*
* Pop a number of elements from the FIFO up to a maximum of @destlen.
* The popped data is copied into the @dest buffer.
* Care is taken when the data wraps around in the ring buffer.
*
* Returns: number of bytes popped.
*/
uint32_t fifo8_pop_buf(Fifo8 *fifo, uint8_t *dest, uint32_t destlen);
/**
* fifo8_pop_bufptr:
* @fifo: FIFO to pop from
* @max: maximum number of bytes to pop * @max: maximum number of bytes to pop
* @numptr: pointer filled with number of bytes returned (can be NULL) * @numptr: pointer filled with number of bytes returned (can be NULL)
* *
* Pop a number of elements from the FIFO up to a maximum of max. The buffer * New code should prefer to use fifo8_pop_buf() instead of fifo8_pop_bufptr().
*
* Pop a number of elements from the FIFO up to a maximum of @max. The buffer
* containing the popped data is returned. This buffer points directly into * containing the popped data is returned. This buffer points directly into
* the FIFO backing store and data is invalidated once any of the fifo8_* APIs * the internal FIFO backing store and data (without checking for overflow!)
* are called on the FIFO. * and is invalidated once any of the fifo8_* APIs are called on the FIFO.
* *
* The function may return fewer bytes than requested when the data wraps * The function may return fewer bytes than requested when the data wraps
* around in the ring buffer; in this case only a contiguous part of the data * around in the ring buffer; in this case only a contiguous part of the data
* is returned. * is returned.
* *
* The number of valid bytes returned is populated in *numptr; will always * The number of valid bytes returned is populated in *@numptr; will always
* return at least 1 byte. max must not be 0 or greater than the number of * return at least 1 byte. max must not be 0 or greater than the number of
* bytes in the FIFO. * bytes in the FIFO.
* *
@ -91,15 +102,15 @@ uint8_t fifo8_pop(Fifo8 *fifo);
* *
* Returns: A pointer to popped data. * Returns: A pointer to popped data.
*/ */
const uint8_t *fifo8_pop_buf(Fifo8 *fifo, uint32_t max, uint32_t *numptr); const uint8_t *fifo8_pop_bufptr(Fifo8 *fifo, uint32_t max, uint32_t *numptr);
/** /**
* fifo8_peek_buf: read upto max bytes from the fifo * fifo8_peek_bufptr: read upto max bytes from the fifo
* @fifo: FIFO to read from * @fifo: FIFO to read from
* @max: maximum number of bytes to peek * @max: maximum number of bytes to peek
* @numptr: pointer filled with number of bytes returned (can be NULL) * @numptr: pointer filled with number of bytes returned (can be NULL)
* *
* Peek into a number of elements from the FIFO up to a maximum of max. * Peek into a number of elements from the FIFO up to a maximum of @max.
* The buffer containing the data peeked into is returned. This buffer points * The buffer containing the data peeked into is returned. This buffer points
* directly into the FIFO backing store. Since data is invalidated once any * directly into the FIFO backing store. Since data is invalidated once any
* of the fifo8_* APIs are called on the FIFO, it is the caller responsibility * of the fifo8_* APIs are called on the FIFO, it is the caller responsibility
@ -109,7 +120,7 @@ const uint8_t *fifo8_pop_buf(Fifo8 *fifo, uint32_t max, uint32_t *numptr);
* around in the ring buffer; in this case only a contiguous part of the data * around in the ring buffer; in this case only a contiguous part of the data
* is returned. * is returned.
* *
* The number of valid bytes returned is populated in *numptr; will always * The number of valid bytes returned is populated in *@numptr; will always
* return at least 1 byte. max must not be 0 or greater than the number of * return at least 1 byte. max must not be 0 or greater than the number of
* bytes in the FIFO. * bytes in the FIFO.
* *
@ -118,7 +129,16 @@ const uint8_t *fifo8_pop_buf(Fifo8 *fifo, uint32_t max, uint32_t *numptr);
* *
* Returns: A pointer to peekable data. * Returns: A pointer to peekable data.
*/ */
const uint8_t *fifo8_peek_buf(Fifo8 *fifo, uint32_t max, uint32_t *numptr); const uint8_t *fifo8_peek_bufptr(Fifo8 *fifo, uint32_t max, uint32_t *numptr);
/**
* fifo8_drop:
* @fifo: FIFO to drop bytes
* @len: number of bytes to drop
*
* Drop (consume) bytes from a FIFO.
*/
void fifo8_drop(Fifo8 *fifo, uint32_t len);
/** /**
* fifo8_reset: * fifo8_reset:
@ -126,7 +146,6 @@ const uint8_t *fifo8_peek_buf(Fifo8 *fifo, uint32_t max, uint32_t *numptr);
* *
* Reset a FIFO. All data is discarded and the FIFO is emptied. * Reset a FIFO. All data is discarded and the FIFO is emptied.
*/ */
void fifo8_reset(Fifo8 *fifo); void fifo8_reset(Fifo8 *fifo);
/** /**
@ -137,7 +156,6 @@ void fifo8_reset(Fifo8 *fifo);
* *
* Returns: True if the fifo is empty, false otherwise. * Returns: True if the fifo is empty, false otherwise.
*/ */
bool fifo8_is_empty(Fifo8 *fifo); bool fifo8_is_empty(Fifo8 *fifo);
/** /**
@ -148,7 +166,6 @@ bool fifo8_is_empty(Fifo8 *fifo);
* *
* Returns: True if the fifo is full, false otherwise. * Returns: True if the fifo is full, false otherwise.
*/ */
bool fifo8_is_full(Fifo8 *fifo); bool fifo8_is_full(Fifo8 *fifo);
/** /**
@ -159,7 +176,6 @@ bool fifo8_is_full(Fifo8 *fifo);
* *
* Returns: Number of free bytes. * Returns: Number of free bytes.
*/ */
uint32_t fifo8_num_free(Fifo8 *fifo); uint32_t fifo8_num_free(Fifo8 *fifo);
/** /**
@ -170,7 +186,6 @@ uint32_t fifo8_num_free(Fifo8 *fifo);
* *
* Returns: Number of used bytes. * Returns: Number of used bytes.
*/ */
uint32_t fifo8_num_used(Fifo8 *fifo); uint32_t fifo8_num_used(Fifo8 *fifo);
extern const VMStateDescription vmstate_fifo8; extern const VMStateDescription vmstate_fifo8;

View File

@ -210,8 +210,8 @@ static inline int range_covers_byte(uint64_t offset, uint64_t len,
/* Check whether 2 given ranges overlap. /* Check whether 2 given ranges overlap.
* Undefined if ranges that wrap around 0. */ * Undefined if ranges that wrap around 0. */
static inline int ranges_overlap(uint64_t first1, uint64_t len1, static inline bool ranges_overlap(uint64_t first1, uint64_t len1,
uint64_t first2, uint64_t len2) uint64_t first2, uint64_t len2)
{ {
uint64_t last1 = range_get_last(first1, len1); uint64_t last1 = range_get_last(first1, len1);
uint64_t last2 = range_get_last(first2, len2); uint64_t last2 = range_get_last(first2, len2);

View File

@ -12,6 +12,7 @@
*/ */
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qemu/range.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "sysemu/memory_mapping.h" #include "sysemu/memory_mapping.h"
@ -353,8 +354,7 @@ void memory_mapping_filter(MemoryMappingList *list, int64_t begin,
MemoryMapping *cur, *next; MemoryMapping *cur, *next;
QTAILQ_FOREACH_SAFE(cur, &list->head, next, next) { QTAILQ_FOREACH_SAFE(cur, &list->head, next, next) {
if (cur->phys_addr >= begin + length || if (!ranges_overlap(cur->phys_addr, cur->length, begin, length)) {
cur->phys_addr + cur->length <= begin) {
QTAILQ_REMOVE(&list->head, cur, next); QTAILQ_REMOVE(&list->head, cur, next);
g_free(cur); g_free(cur);
list->num--; list->num--;

View File

@ -19,6 +19,7 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qemu/log.h" #include "qemu/log.h"
#include "qemu/range.h"
#include "cpu.h" #include "cpu.h"
#include "tcg/tcg.h" #include "tcg/tcg.h"
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
@ -240,9 +241,7 @@ static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
if (new_ctx == ctx) { if (new_ctx == ctx) {
uint64_t vaddr = tlb[i].tag & ~0x1fffULL; uint64_t vaddr = tlb[i].tag & ~0x1fffULL;
uint64_t size = 8192ULL << 3 * TTE_PGSIZE(tlb[i].tte); uint64_t size = 8192ULL << 3 * TTE_PGSIZE(tlb[i].tte);
if (new_vaddr == vaddr if (ranges_overlap(new_vaddr, new_size, vaddr, size)) {
|| (new_vaddr < vaddr + size
&& vaddr < new_vaddr + new_size)) {
DPRINTF_MMU("auto demap entry [%d] %lx->%lx\n", i, vaddr, DPRINTF_MMU("auto demap entry [%d] %lx->%lx\n", i, vaddr,
new_vaddr); new_vaddr);
replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1); replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);

View File

@ -287,7 +287,7 @@ static void kbd_send_chars(QemuTextConsole *s)
const uint8_t *buf; const uint8_t *buf;
uint32_t size; uint32_t size;
buf = fifo8_pop_buf(&s->out_fifo, MIN(len, avail), &size); buf = fifo8_pop_bufptr(&s->out_fifo, MIN(len, avail), &size);
qemu_chr_be_write(s->chr, buf, size); qemu_chr_be_write(s->chr, buf, size);
len = qemu_chr_be_can_write(s->chr); len = qemu_chr_be_can_write(s->chr);
avail -= size; avail -= size;

View File

@ -1820,7 +1820,7 @@ static void gd_vc_send_chars(VirtualConsole *vc)
const uint8_t *buf; const uint8_t *buf;
uint32_t size; uint32_t size;
buf = fifo8_pop_buf(&vc->vte.out_fifo, MIN(len, avail), &size); buf = fifo8_pop_bufptr(&vc->vte.out_fifo, MIN(len, avail), &size);
qemu_chr_be_write(vc->vte.chr, buf, size); qemu_chr_be_write(vc->vte.chr, buf, size);
len = qemu_chr_be_can_write(vc->vte.chr); len = qemu_chr_be_can_write(vc->vte.chr);
avail -= size; avail -= size;

View File

@ -16,12 +16,17 @@
#include "migration/vmstate.h" #include "migration/vmstate.h"
#include "qemu/fifo8.h" #include "qemu/fifo8.h"
void fifo8_reset(Fifo8 *fifo)
{
fifo->num = 0;
fifo->head = 0;
}
void fifo8_create(Fifo8 *fifo, uint32_t capacity) void fifo8_create(Fifo8 *fifo, uint32_t capacity)
{ {
fifo->data = g_new(uint8_t, capacity); fifo->data = g_new(uint8_t, capacity);
fifo->capacity = capacity; fifo->capacity = capacity;
fifo->head = 0; fifo8_reset(fifo);
fifo->num = 0;
} }
void fifo8_destroy(Fifo8 *fifo) void fifo8_destroy(Fifo8 *fifo)
@ -87,20 +92,49 @@ static const uint8_t *fifo8_peekpop_buf(Fifo8 *fifo, uint32_t max,
return ret; return ret;
} }
const uint8_t *fifo8_peek_buf(Fifo8 *fifo, uint32_t max, uint32_t *numptr) const uint8_t *fifo8_peek_bufptr(Fifo8 *fifo, uint32_t max, uint32_t *numptr)
{ {
return fifo8_peekpop_buf(fifo, max, numptr, false); return fifo8_peekpop_buf(fifo, max, numptr, false);
} }
const uint8_t *fifo8_pop_buf(Fifo8 *fifo, uint32_t max, uint32_t *numptr) const uint8_t *fifo8_pop_bufptr(Fifo8 *fifo, uint32_t max, uint32_t *numptr)
{ {
return fifo8_peekpop_buf(fifo, max, numptr, true); return fifo8_peekpop_buf(fifo, max, numptr, true);
} }
void fifo8_reset(Fifo8 *fifo) uint32_t fifo8_pop_buf(Fifo8 *fifo, uint8_t *dest, uint32_t destlen)
{ {
fifo->num = 0; const uint8_t *buf;
fifo->head = 0; uint32_t n1, n2 = 0;
uint32_t len;
if (destlen == 0) {
return 0;
}
len = destlen;
buf = fifo8_pop_bufptr(fifo, len, &n1);
if (dest) {
memcpy(dest, buf, n1);
}
/* Add FIFO wraparound if needed */
len -= n1;
len = MIN(len, fifo8_num_used(fifo));
if (len) {
buf = fifo8_pop_bufptr(fifo, len, &n2);
if (dest) {
memcpy(&dest[n1], buf, n2);
}
}
return n1 + n2;
}
void fifo8_drop(Fifo8 *fifo, uint32_t len)
{
len -= fifo8_pop_buf(fifo, NULL, len);
assert(len == 0);
} }
bool fifo8_is_empty(Fifo8 *fifo) bool fifo8_is_empty(Fifo8 *fifo)