diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/block/block_int.h | 61 | ||||
| -rw-r--r-- | include/chardev/char.h | 34 | ||||
| -rw-r--r-- | include/exec/translate-all.h | 1 | ||||
| -rw-r--r-- | include/exec/translator.h | 44 | ||||
| -rw-r--r-- | include/hw/arm/virt.h | 2 | ||||
| -rw-r--r-- | include/hw/core/tcg-cpu-ops.h | 26 | ||||
| -rw-r--r-- | include/hw/intc/arm_gicv3_common.h | 13 | ||||
| -rw-r--r-- | include/hw/intc/arm_gicv3_its_common.h | 32 | ||||
| -rw-r--r-- | include/hw/qdev-core.h | 28 | ||||
| -rw-r--r-- | include/tcg/tcg-op.h | 2 | ||||
| -rw-r--r-- | include/ui/console.h | 3 | ||||
| -rw-r--r-- | include/ui/egl-helpers.h | 3 | ||||
| -rw-r--r-- | include/ui/gtk.h | 5 |
13 files changed, 216 insertions, 38 deletions
diff --git a/include/block/block_int.h b/include/block/block_int.h index f1a54db0f8..5451f89b8d 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -34,6 +34,7 @@ #include "qemu/hbitmap.h" #include "block/snapshot.h" #include "qemu/throttle.h" +#include "qemu/rcu.h" #define BLOCK_FLAG_LAZY_REFCOUNTS 8 @@ -347,6 +348,15 @@ struct BlockDriver { * clamped to bdrv_getlength() and aligned to request_alignment, * as well as non-NULL pnum, map, and file; in turn, the driver * must return an error or set pnum to an aligned non-zero value. + * + * Note that @bytes is just a hint on how big of a region the + * caller wants to inspect. It is not a limit on *pnum. + * Implementations are free to return larger values of *pnum if + * doing so does not incur a performance penalty. + * + * block/io.c's bdrv_co_block_status() will utilize an unclamped + * *pnum value for the block-status cache on protocol nodes, prior + * to clamping *pnum for return to its caller. */ int coroutine_fn (*bdrv_co_block_status)(BlockDriverState *bs, bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum, @@ -840,11 +850,23 @@ struct BdrvChild { }; /* - * Note: the function bdrv_append() copies and swaps contents of - * BlockDriverStates, so if you add new fields to this struct, please - * inspect bdrv_append() to determine if the new fields need to be - * copied as well. + * Allows bdrv_co_block_status() to cache one data region for a + * protocol node. + * + * @valid: Whether the cache is valid (should be accessed with atomic + * functions so this can be reset by RCU readers) + * @data_start: Offset where we know (or strongly assume) is data + * @data_end: Offset where the data region ends (which is not necessarily + * the start of a zeroed region) */ +typedef struct BdrvBlockStatusCache { + struct rcu_head rcu; + + bool valid; + int64_t data_start; + int64_t data_end; +} BdrvBlockStatusCache; + struct BlockDriverState { /* Protected by big QEMU lock or read-only after opening. No special * locking needed during I/O... @@ -1010,6 +1032,11 @@ struct BlockDriverState { /* BdrvChild links to this node may never be frozen */ bool never_freeze; + + /* Lock for block-status cache RCU writers */ + CoMutex bsc_modify_lock; + /* Always non-NULL, but must only be dereferenced under an RCU read guard */ + BdrvBlockStatusCache *block_status_cache; }; struct BlockBackendRootState { @@ -1435,4 +1462,30 @@ static inline BlockDriverState *bdrv_primary_bs(BlockDriverState *bs) */ void bdrv_drain_all_end_quiesce(BlockDriverState *bs); +/** + * Check whether the given offset is in the cached block-status data + * region. + * + * If it is, and @pnum is not NULL, *pnum is set to + * `bsc.data_end - offset`, i.e. how many bytes, starting from + * @offset, are data (according to the cache). + * Otherwise, *pnum is not touched. + */ +bool bdrv_bsc_is_data(BlockDriverState *bs, int64_t offset, int64_t *pnum); + +/** + * If [offset, offset + bytes) overlaps with the currently cached + * block-status region, invalidate the cache. + * + * (To be used by I/O paths that cause data regions to be zero or + * holes.) + */ +void bdrv_bsc_invalidate_range(BlockDriverState *bs, + int64_t offset, int64_t bytes); + +/** + * Mark the range [offset, offset + bytes) as a data region. + */ +void bdrv_bsc_fill(BlockDriverState *bs, int64_t offset, int64_t bytes); + #endif /* BLOCK_INT_H */ diff --git a/include/chardev/char.h b/include/chardev/char.h index 7c0444f90d..a319b5fdff 100644 --- a/include/chardev/char.h +++ b/include/chardev/char.h @@ -254,26 +254,58 @@ struct ChardevClass { bool internal; /* TODO: eventually use TYPE_USER_CREATABLE */ bool supports_yank; + + /* parse command line options and populate QAPI @backend */ void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp); + /* called after construction, open/starts the backend */ void (*open)(Chardev *chr, ChardevBackend *backend, bool *be_opened, Error **errp); + /* write buf to the backend */ int (*chr_write)(Chardev *s, const uint8_t *buf, int len); + + /* + * Read from the backend (blocking). A typical front-end will instead rely + * on chr_can_read/chr_read being called when polling/looping. + */ int (*chr_sync_read)(Chardev *s, const uint8_t *buf, int len); + + /* create a watch on the backend */ GSource *(*chr_add_watch)(Chardev *s, GIOCondition cond); + + /* update the backend internal sources */ void (*chr_update_read_handler)(Chardev *s); + + /* send an ioctl to the backend */ int (*chr_ioctl)(Chardev *s, int cmd, void *arg); + + /* get ancillary-received fds during last read */ int (*get_msgfds)(Chardev *s, int* fds, int num); + + /* set ancillary fds to be sent with next write */ int (*set_msgfds)(Chardev *s, int *fds, int num); + + /* accept the given fd */ int (*chr_add_client)(Chardev *chr, int fd); + + /* wait for a connection */ int (*chr_wait_connected)(Chardev *chr, Error **errp); + + /* disconnect a connection */ void (*chr_disconnect)(Chardev *chr); + + /* called by frontend when it can read */ void (*chr_accept_input)(Chardev *chr); + + /* set terminal echo */ void (*chr_set_echo)(Chardev *chr, bool echo); + + /* notify the backend of frontend open state */ void (*chr_set_fe_open)(Chardev *chr, int fe_open); + + /* handle various events */ void (*chr_be_event)(Chardev *s, QEMUChrEvent event); - void (*chr_options_parsed)(Chardev *chr); }; Chardev *qemu_chardev_new(const char *id, const char *typename, diff --git a/include/exec/translate-all.h b/include/exec/translate-all.h index a557b4e2bb..9f646389af 100644 --- a/include/exec/translate-all.h +++ b/include/exec/translate-all.h @@ -33,6 +33,7 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end); void tb_check_watchpoint(CPUState *cpu, uintptr_t retaddr); #ifdef CONFIG_USER_ONLY +void page_protect(tb_page_addr_t page_addr); int page_unprotect(target_ulong address, uintptr_t pc); #endif diff --git a/include/exec/translator.h b/include/exec/translator.h index d318803267..9bc46eda59 100644 --- a/include/exec/translator.h +++ b/include/exec/translator.h @@ -23,6 +23,7 @@ #include "exec/exec-all.h" #include "exec/cpu_ldst.h" #include "exec/plugin-gen.h" +#include "exec/translate-all.h" #include "tcg/tcg.h" @@ -74,6 +75,17 @@ typedef struct DisasContextBase { int num_insns; int max_insns; bool singlestep_enabled; +#ifdef CONFIG_USER_ONLY + /* + * Guest address of the last byte of the last protected page. + * + * Pages containing the translated instructions are made non-writable in + * order to achieve consistency in case another thread is modifying the + * code while translate_insn() fetches the instruction bytes piecemeal. + * Such writer threads are blocked on mmap_lock() in page_unprotect(). + */ + target_ulong page_protect_end; +#endif } DisasContextBase; /** @@ -156,27 +168,23 @@ bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest); */ #define GEN_TRANSLATOR_LD(fullname, type, load_fn, swap_fn) \ - static inline type \ - fullname ## _swap(CPUArchState *env, abi_ptr pc, bool do_swap) \ + type fullname ## _swap(CPUArchState *env, DisasContextBase *dcbase, \ + abi_ptr pc, bool do_swap); \ + static inline type fullname(CPUArchState *env, \ + DisasContextBase *dcbase, abi_ptr pc) \ { \ - type ret = load_fn(env, pc); \ - if (do_swap) { \ - ret = swap_fn(ret); \ - } \ - plugin_insn_append(&ret, sizeof(ret)); \ - return ret; \ - } \ - \ - static inline type fullname(CPUArchState *env, abi_ptr pc) \ - { \ - return fullname ## _swap(env, pc, false); \ + return fullname ## _swap(env, dcbase, pc, false); \ } -GEN_TRANSLATOR_LD(translator_ldub, uint8_t, cpu_ldub_code, /* no swap */) -GEN_TRANSLATOR_LD(translator_ldsw, int16_t, cpu_ldsw_code, bswap16) -GEN_TRANSLATOR_LD(translator_lduw, uint16_t, cpu_lduw_code, bswap16) -GEN_TRANSLATOR_LD(translator_ldl, uint32_t, cpu_ldl_code, bswap32) -GEN_TRANSLATOR_LD(translator_ldq, uint64_t, cpu_ldq_code, bswap64) +#define FOR_EACH_TRANSLATOR_LD(F) \ + F(translator_ldub, uint8_t, cpu_ldub_code, /* no swap */) \ + F(translator_ldsw, int16_t, cpu_ldsw_code, bswap16) \ + F(translator_lduw, uint16_t, cpu_lduw_code, bswap16) \ + F(translator_ldl, uint32_t, cpu_ldl_code, bswap32) \ + F(translator_ldq, uint64_t, cpu_ldq_code, bswap64) + +FOR_EACH_TRANSLATOR_LD(GEN_TRANSLATOR_LD) + #undef GEN_TRANSLATOR_LD #endif /* EXEC__TRANSLATOR_H */ diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index 9661c46699..b461b8d261 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -120,6 +120,7 @@ struct VirtMachineClass { MachineClass parent; bool disallow_affinity_adjustment; bool no_its; + bool no_tcg_its; bool no_pmu; bool claim_edge_triggered_timers; bool smbios_old_sys_ver; @@ -141,6 +142,7 @@ struct VirtMachineState { bool highmem; bool highmem_ecam; bool its; + bool tcg_its; bool virt; bool ras; bool mte; diff --git a/include/hw/core/tcg-cpu-ops.h b/include/hw/core/tcg-cpu-ops.h index eab27d0c03..55123cb4d2 100644 --- a/include/hw/core/tcg-cpu-ops.h +++ b/include/hw/core/tcg-cpu-ops.h @@ -35,16 +35,6 @@ struct TCGCPUOps { void (*cpu_exec_enter)(CPUState *cpu); /** @cpu_exec_exit: Callback for cpu_exec cleanup */ void (*cpu_exec_exit)(CPUState *cpu); - /** @cpu_exec_interrupt: Callback for processing interrupts in cpu_exec */ - bool (*cpu_exec_interrupt)(CPUState *cpu, int interrupt_request); - /** - * @do_interrupt: Callback for interrupt handling. - * - * note that this is in general SOFTMMU only, but it actually isn't - * because of an x86 hack (accel/tcg/cpu-exec.c), so we cannot put it - * in the SOFTMMU section in general. - */ - void (*do_interrupt)(CPUState *cpu); /** * @tlb_fill: Handle a softmmu tlb miss or user-only address fault * @@ -61,7 +51,23 @@ struct TCGCPUOps { void (*debug_excp_handler)(CPUState *cpu); #ifdef NEED_CPU_H +#if defined(CONFIG_USER_ONLY) && defined(TARGET_I386) + /** + * @fake_user_interrupt: Callback for 'fake exception' handling. + * + * Simulate 'fake exception' which will be handled outside the + * cpu execution loop (hack for x86 user mode). + */ + void (*fake_user_interrupt)(CPUState *cpu); +#else + /** + * @do_interrupt: Callback for interrupt handling. + */ + void (*do_interrupt)(CPUState *cpu); +#endif /* !CONFIG_USER_ONLY || !TARGET_I386 */ #ifdef CONFIG_SOFTMMU + /** @cpu_exec_interrupt: Callback for processing interrupts in cpu_exec */ + bool (*cpu_exec_interrupt)(CPUState *cpu, int interrupt_request); /** * @do_transaction_failed: Callback for handling failed memory transactions * (ie bus faults or external aborts; not MMU faults) diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h index 91491a2f66..aa4f0d6770 100644 --- a/include/hw/intc/arm_gicv3_common.h +++ b/include/hw/intc/arm_gicv3_common.h @@ -36,6 +36,8 @@ #define GICV3_MAXIRQ 1020 #define GICV3_MAXSPI (GICV3_MAXIRQ - GIC_INTERNAL) +#define GICV3_LPI_INTID_START 8192 + #define GICV3_REDIST_SIZE 0x20000 /* Number of SGI target-list bits */ @@ -202,6 +204,13 @@ struct GICv3CPUState { * real state above; it doesn't need to be migrated. */ PendingIrq hppi; + + /* + * Cached information recalculated from LPI tables + * in guest memory + */ + PendingIrq hpplpi; + /* This is temporary working state, to avoid a malloc in gicv3_update() */ bool seenbetter; }; @@ -219,6 +228,7 @@ struct GICv3State { uint32_t num_cpu; uint32_t num_irq; uint32_t revision; + bool lpi_enable; bool security_extn; bool irq_reset_nonsecure; bool gicd_no_migration_shift_bug; @@ -226,6 +236,9 @@ struct GICv3State { int dev_fd; /* kvm device fd if backed by kvm vgic support */ Error *migration_blocker; + MemoryRegion *dma; + AddressSpace dma_as; + /* Distributor */ /* for a GIC with the security extensions the NS banked version of this diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h index 5a0952b404..4e79145dde 100644 --- a/include/hw/intc/arm_gicv3_its_common.h +++ b/include/hw/intc/arm_gicv3_its_common.h @@ -25,17 +25,41 @@ #include "hw/intc/arm_gicv3_common.h" #include "qom/object.h" +#define TYPE_ARM_GICV3_ITS "arm-gicv3-its" + #define ITS_CONTROL_SIZE 0x10000 #define ITS_TRANS_SIZE 0x10000 #define ITS_SIZE (ITS_CONTROL_SIZE + ITS_TRANS_SIZE) #define GITS_CTLR 0x0 #define GITS_IIDR 0x4 +#define GITS_TYPER 0x8 #define GITS_CBASER 0x80 #define GITS_CWRITER 0x88 #define GITS_CREADR 0x90 #define GITS_BASER 0x100 +#define GITS_TRANSLATER 0x0040 + +typedef struct { + bool valid; + bool indirect; + uint16_t entry_sz; + uint32_t page_sz; + uint32_t max_entries; + union { + uint32_t max_devids; + uint32_t max_collids; + } maxids; + uint64_t base_addr; +} TableDesc; + +typedef struct { + bool valid; + uint32_t max_entries; + uint64_t base_addr; +} CmdQDesc; + struct GICv3ITSState { SysBusDevice parent_obj; @@ -52,17 +76,23 @@ struct GICv3ITSState { /* Registers */ uint32_t ctlr; uint32_t iidr; + uint64_t typer; uint64_t cbaser; uint64_t cwriter; uint64_t creadr; uint64_t baser[8]; + TableDesc dt; + TableDesc ct; + CmdQDesc cq; + Error *migration_blocker; }; typedef struct GICv3ITSState GICv3ITSState; -void gicv3_its_init_mmio(GICv3ITSState *s, const MemoryRegionOps *ops); +void gicv3_its_init_mmio(GICv3ITSState *s, const MemoryRegionOps *ops, + const MemoryRegionOps *tops); #define TYPE_ARM_GICV3_ITS_COMMON "arm-gicv3-its-common" typedef struct GICv3ITSCommonClass GICv3ITSCommonClass; diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index bafc311bfa..34c8a7506a 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -264,6 +264,7 @@ struct BusState { HotplugHandler *hotplug_handler; int max_index; bool realized; + bool full; int num_children; /* @@ -597,6 +598,10 @@ void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n); * * See qdev_connect_gpio_out() for how code that uses such a device * can connect to one of its output GPIO lines. + * + * There is no need to release the @pins allocated array because it + * will be automatically released when @dev calls its instance_finalize() + * handler. */ void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n); /** @@ -798,6 +803,29 @@ static inline bool qbus_is_hotpluggable(BusState *bus) return bus->hotplug_handler; } +/** + * qbus_mark_full: Mark this bus as full, so no more devices can be attached + * @bus: Bus to mark as full + * + * By default, QEMU will allow devices to be plugged into a bus up + * to the bus class's device count limit. Calling this function + * marks a particular bus as full, so that no more devices can be + * plugged into it. In particular this means that the bus will not + * be considered as a candidate for plugging in devices created by + * the user on the commandline or via the monitor. + * If a machine has multiple buses of a given type, such as I2C, + * where some of those buses in the real hardware are used only for + * internal devices and some are exposed via expansion ports, you + * can use this function to mark the internal-only buses as full + * after you have created all their internal devices. Then user + * created devices will appear on the expansion-port bus where + * guest software expects them. + */ +static inline void qbus_mark_full(BusState *bus) +{ + bus->full = true; +} + void device_listener_register(DeviceListener *listener); void device_listener_unregister(DeviceListener *listener); diff --git a/include/tcg/tcg-op.h b/include/tcg/tcg-op.h index 2a654f350c..0545a6224c 100644 --- a/include/tcg/tcg-op.h +++ b/include/tcg/tcg-op.h @@ -843,7 +843,6 @@ static inline void tcg_gen_plugin_cb_end(void) #if TARGET_LONG_BITS == 32 #define tcg_temp_new() tcg_temp_new_i32() -#define tcg_global_reg_new tcg_global_reg_new_i32 #define tcg_global_mem_new tcg_global_mem_new_i32 #define tcg_temp_local_new() tcg_temp_local_new_i32() #define tcg_temp_free tcg_temp_free_i32 @@ -851,7 +850,6 @@ static inline void tcg_gen_plugin_cb_end(void) #define tcg_gen_qemu_st_tl tcg_gen_qemu_st_i32 #else #define tcg_temp_new() tcg_temp_new_i64() -#define tcg_global_reg_new tcg_global_reg_new_i64 #define tcg_global_mem_new tcg_global_mem_new_i64 #define tcg_temp_local_new() tcg_temp_local_new_i64() #define tcg_temp_free tcg_temp_free_i64 diff --git a/include/ui/console.h b/include/ui/console.h index 3be21497a2..244664d727 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -168,6 +168,9 @@ typedef struct QemuDmaBuf { uint64_t modifier; uint32_t texture; bool y0_top; + void *sync; + int fence_fd; + bool allow_fences; } QemuDmaBuf; typedef struct DisplayState DisplayState; diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h index f1bf8f97fc..2fb6e0dd6b 100644 --- a/include/ui/egl-helpers.h +++ b/include/ui/egl-helpers.h @@ -19,6 +19,7 @@ typedef struct egl_fb { GLuint texture; GLuint framebuffer; bool delete_texture; + QemuDmaBuf *dmabuf; } egl_fb; void egl_fb_destroy(egl_fb *fb); @@ -45,6 +46,8 @@ int egl_get_fd_for_texture(uint32_t tex_id, EGLint *stride, EGLint *fourcc, void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf); void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf); +void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf); +void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf); #endif diff --git a/include/ui/gtk.h b/include/ui/gtk.h index 7835ef1a71..7d22affd38 100644 --- a/include/ui/gtk.h +++ b/include/ui/gtk.h @@ -155,6 +155,7 @@ extern bool gtk_use_gl_area; /* ui/gtk.c */ void gd_update_windowsize(VirtualConsole *vc); int gd_monitor_update_interval(GtkWidget *widget); +void gd_hw_gl_flushed(void *vc); /* ui/gtk-egl.c */ void gd_egl_init(VirtualConsole *vc); @@ -181,8 +182,8 @@ void gd_egl_cursor_dmabuf(DisplayChangeListener *dcl, uint32_t hot_x, uint32_t hot_y); void gd_egl_cursor_position(DisplayChangeListener *dcl, uint32_t pos_x, uint32_t pos_y); -void gd_egl_release_dmabuf(DisplayChangeListener *dcl, - QemuDmaBuf *dmabuf); +void gd_egl_flush(DisplayChangeListener *dcl, + uint32_t x, uint32_t y, uint32_t w, uint32_t h); void gd_egl_scanout_flush(DisplayChangeListener *dcl, uint32_t x, uint32_t y, uint32_t w, uint32_t h); void gtk_egl_init(DisplayGLMode mode); |