diff options
| -rw-r--r-- | accel/tcg/cpu-exec.c | 4 | ||||
| -rw-r--r-- | hw/core/loader.c | 45 | ||||
| -rw-r--r-- | hw/display/ati.c | 2 | ||||
| -rw-r--r-- | hw/display/qxl-render.c | 4 | ||||
| -rw-r--r-- | hw/display/virtio-gpu.c | 3 | ||||
| -rw-r--r-- | hw/display/vmware_vga.c | 8 | ||||
| -rw-r--r-- | hw/isa/vt82c686.c | 2 | ||||
| -rw-r--r-- | hw/mips/fuloong2e.c | 2 | ||||
| -rw-r--r-- | hw/ppc/amigaone.c | 5 | ||||
| -rw-r--r-- | hw/ppc/pegasos2.c | 4 | ||||
| -rw-r--r-- | hw/scsi/esp.c | 4 | ||||
| -rw-r--r-- | hw/sd/sd.c | 385 | ||||
| -rw-r--r-- | hw/sd/trace-events | 2 | ||||
| -rw-r--r-- | include/hw/core/cpu.h | 8 | ||||
| -rw-r--r-- | include/hw/loader.h | 4 | ||||
| -rw-r--r-- | include/hw/qdev-core.h | 17 | ||||
| -rw-r--r-- | include/hw/sd/sd.h | 3 | ||||
| -rw-r--r-- | include/ui/console.h | 5 | ||||
| -rw-r--r-- | meson.build | 3 | ||||
| -rw-r--r-- | system/cpus.c | 30 | ||||
| -rw-r--r-- | system/physmem.c | 7 | ||||
| -rw-r--r-- | system/vl.c | 13 | ||||
| -rw-r--r-- | target/tricore/cpu.c | 6 | ||||
| -rw-r--r-- | ui/cocoa.m | 104 | ||||
| -rw-r--r-- | ui/console.c | 18 | ||||
| -rw-r--r-- | ui/dbus-listener.c | 2 | ||||
| -rw-r--r-- | ui/gtk.c | 2 | ||||
| -rw-r--r-- | ui/sdl2.c | 4 | ||||
| -rw-r--r-- | ui/spice-display.c | 11 | ||||
| -rw-r--r-- | ui/vnc.c | 2 |
30 files changed, 584 insertions, 125 deletions
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 245fd6327d..9010dad073 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -857,8 +857,7 @@ static inline bool cpu_handle_interrupt(CPUState *cpu, else { const TCGCPUOps *tcg_ops = cpu->cc->tcg_ops; - if (tcg_ops->cpu_exec_interrupt && - tcg_ops->cpu_exec_interrupt(cpu, interrupt_request)) { + if (tcg_ops->cpu_exec_interrupt(cpu, interrupt_request)) { if (!tcg_ops->need_replay_interrupt || tcg_ops->need_replay_interrupt(interrupt_request)) { replay_interrupt(); @@ -1080,6 +1079,7 @@ bool tcg_exec_realizefn(CPUState *cpu, Error **errp) /* Check mandatory TCGCPUOps handlers */ #ifndef CONFIG_USER_ONLY assert(cpu->cc->tcg_ops->cpu_exec_halt); + assert(cpu->cc->tcg_ops->cpu_exec_interrupt); #endif /* !CONFIG_USER_ONLY */ cpu->cc->tcg_ops->initialize(); tcg_target_initialized = true; diff --git a/hw/core/loader.c b/hw/core/loader.c index a3bea1e718..31593a1171 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -845,19 +845,6 @@ ssize_t load_image_gzipped_buffer(const char *filename, uint64_t max_sz, return ret; } -/* Load a gzip-compressed kernel. */ -ssize_t load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz) -{ - ssize_t bytes; - uint8_t *data; - - bytes = load_image_gzipped_buffer(filename, max_sz, &data); - if (bytes != -1) { - rom_add_blob_fixed(filename, data, bytes, addr); - g_free(data); - } - return bytes; -} /* The PE/COFF MS-DOS stub magic number */ #define EFI_PE_MSDOS_MAGIC "MZ" @@ -1076,8 +1063,8 @@ ssize_t rom_add_file(const char *file, const char *fw_dir, { MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine()); Rom *rom; - ssize_t rc; - int fd = -1; + gsize size; + g_autoptr(GError) gerr = NULL; char devpath[100]; if (as && mr) { @@ -1095,10 +1082,10 @@ ssize_t rom_add_file(const char *file, const char *fw_dir, rom->path = g_strdup(file); } - fd = open(rom->path, O_RDONLY | O_BINARY); - if (fd == -1) { - fprintf(stderr, "Could not open option rom '%s': %s\n", - rom->path, strerror(errno)); + if (!g_file_get_contents(rom->path, (gchar **) &rom->data, + &size, &gerr)) { + fprintf(stderr, "rom: file %-20s: error %s\n", + rom->name, gerr->message); goto err; } @@ -1107,23 +1094,8 @@ ssize_t rom_add_file(const char *file, const char *fw_dir, rom->fw_file = g_strdup(file); } rom->addr = addr; - rom->romsize = lseek(fd, 0, SEEK_END); - if (rom->romsize == -1) { - fprintf(stderr, "rom: file %-20s: get size error: %s\n", - rom->name, strerror(errno)); - goto err; - } - + rom->romsize = size; rom->datasize = rom->romsize; - rom->data = g_malloc0(rom->datasize); - lseek(fd, 0, SEEK_SET); - rc = read(fd, rom->data, rom->datasize); - if (rc != rom->datasize) { - fprintf(stderr, "rom: file %-20s: read error: rc=%zd (expected %zd)\n", - rom->name, rc, rom->datasize); - goto err; - } - close(fd); rom_insert(rom); if (rom->fw_file && fw_cfg) { const char *basename; @@ -1160,9 +1132,6 @@ ssize_t rom_add_file(const char *file, const char *fw_dir, return 0; err: - if (fd != -1) - close(fd); - rom_free(rom); return -1; } diff --git a/hw/display/ati.c b/hw/display/ati.c index 8d2501bd82..b1f94f5b76 100644 --- a/hw/display/ati.c +++ b/hw/display/ati.c @@ -742,7 +742,7 @@ static void ati_mm_write(void *opaque, hwaddr addr, if (!s->cursor_guest_mode && (s->regs.crtc_gen_cntl & CRTC2_CUR_EN) && !(t & BIT(31))) { dpy_mouse_set(s->vga.con, s->regs.cur_hv_pos >> 16, - s->regs.cur_hv_pos & 0xffff, 1); + s->regs.cur_hv_pos & 0xffff, true); } break; } diff --git a/hw/display/qxl-render.c b/hw/display/qxl-render.c index 8daae72c8d..335d01edde 100644 --- a/hw/display/qxl-render.c +++ b/hw/display/qxl-render.c @@ -307,10 +307,6 @@ int qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext) return 1; } - if (!dpy_cursor_define_supported(qxl->vga.con)) { - return 0; - } - if (qxl->debug > 1 && cmd->type != QXL_CURSOR_MOVE) { fprintf(stderr, "%s", __func__); qxl_log_cmd_cursor(qxl, cmd, ext->group_id); diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index d60b1b2973..3281842bfe 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -109,8 +109,7 @@ static void update_cursor(VirtIOGPU *g, struct virtio_gpu_update_cursor *cursor) s->cursor.pos.x = cursor->pos.x; s->cursor.pos.y = cursor->pos.y; } - dpy_mouse_set(s->con, cursor->pos.x, cursor->pos.y, - cursor->resource_id ? 1 : 0); + dpy_mouse_set(s->con, cursor->pos.x, cursor->pos.y, cursor->resource_id); } struct virtio_gpu_simple_resource * diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c index 1c0f9d9a99..3db3ff98f7 100644 --- a/hw/display/vmware_vga.c +++ b/hw/display/vmware_vga.c @@ -904,10 +904,8 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address) caps |= SVGA_CAP_RECT_FILL; #endif #ifdef HW_MOUSE_ACCEL - if (dpy_cursor_define_supported(s->vga.con)) { - caps |= SVGA_CAP_CURSOR | SVGA_CAP_CURSOR_BYPASS_2 | - SVGA_CAP_CURSOR_BYPASS; - } + caps |= SVGA_CAP_CURSOR | SVGA_CAP_CURSOR_BYPASS_2 | + SVGA_CAP_CURSOR_BYPASS; #endif ret = caps; break; @@ -1167,7 +1165,7 @@ static void vmsvga_reset(DeviceState *dev) s->enable = 0; s->config = 0; s->svgaid = SVGA_ID; - s->cursor.on = 0; + s->cursor.on = false; s->redraw_fifo_last = 0; s->syncing = 0; diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 8582ac0322..505b44c4e6 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -719,7 +719,7 @@ static void via_isa_realize(PCIDevice *d, Error **errp) ISABus *isa_bus; int i; - qdev_init_gpio_out(dev, &s->cpu_intr, 1); + qdev_init_gpio_out_named(dev, &s->cpu_intr, "intr", 1); qdev_init_gpio_in_named(dev, via_isa_pirq, "pirq", PCI_NUM_PINS); isa_irq = qemu_allocate_irqs(via_isa_request_i8259_irq, s, 1); isa_bus = isa_bus_new(dev, pci_address_space(d), pci_address_space_io(d), diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c index a45aac368c..6e4303ba47 100644 --- a/hw/mips/fuloong2e.c +++ b/hw/mips/fuloong2e.c @@ -299,7 +299,7 @@ static void mips_fuloong2e_init(MachineState *machine) object_resolve_path_component(OBJECT(pci_dev), "rtc"), "date"); - qdev_connect_gpio_out(DEVICE(pci_dev), 0, env->irq[5]); + qdev_connect_gpio_out_named(DEVICE(pci_dev), "intr", 0, env->irq[5]); dev = DEVICE(object_resolve_path_component(OBJECT(pci_dev), "ide")); pci_ide_create_devs(PCI_DEVICE(dev)); diff --git a/hw/ppc/amigaone.c b/hw/ppc/amigaone.c index ddfa09457a..900f93c15e 100644 --- a/hw/ppc/amigaone.c +++ b/hw/ppc/amigaone.c @@ -153,8 +153,9 @@ static void amigaone_init(MachineState *machine) object_property_add_alias(OBJECT(machine), "rtc-time", object_resolve_path_component(via, "rtc"), "date"); - qdev_connect_gpio_out(DEVICE(via), 0, - qdev_get_gpio_in(DEVICE(cpu), PPC6xx_INPUT_INT)); + qdev_connect_gpio_out_named(DEVICE(via), "intr", 0, + qdev_get_gpio_in(DEVICE(cpu), + PPC6xx_INPUT_INT)); for (i = 0; i < PCI_NUM_PINS; i++) { qdev_connect_gpio_out(dev, i, qdev_get_gpio_in_named(DEVICE(via), "pirq", i)); diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c index c1bd8dfa21..9b0a6b70ab 100644 --- a/hw/ppc/pegasos2.c +++ b/hw/ppc/pegasos2.c @@ -195,8 +195,8 @@ static void pegasos2_init(MachineState *machine) object_property_add_alias(OBJECT(machine), "rtc-time", object_resolve_path_component(via, "rtc"), "date"); - qdev_connect_gpio_out(DEVICE(via), 0, - qdev_get_gpio_in_named(pm->mv, "gpp", 31)); + qdev_connect_gpio_out_named(DEVICE(via), "intr", 0, + qdev_get_gpio_in_named(pm->mv, "gpp", 31)); dev = PCI_DEVICE(object_resolve_path_component(via, "ide")); pci_ide_create_devs(dev); diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c index 5d9b52632e..8504dd30a0 100644 --- a/hw/scsi/esp.c +++ b/hw/scsi/esp.c @@ -594,7 +594,7 @@ static void esp_do_dma(ESPState *s) if (!s->current_req) { return; } - if (s->async_len == 0 && esp_get_tc(s) && s->ti_size) { + if (s->async_len == 0 && esp_get_tc(s)) { /* Defer until data is available. */ return; } @@ -647,7 +647,7 @@ static void esp_do_dma(ESPState *s) if (!s->current_req) { return; } - if (s->async_len == 0 && esp_get_tc(s) && s->ti_size) { + if (s->async_len == 0 && esp_get_tc(s)) { /* Defer until data is available. */ return; } diff --git a/hw/sd/sd.c b/hw/sd/sd.c index d6a07f0ade..07cb97d88c 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -2,6 +2,8 @@ * SD Memory Card emulation as defined in the "SD Memory Card Physical * layer specification, Version 2.00." * + * eMMC emulation defined in "JEDEC Standard No. 84-A43" + * * Copyright (c) 2006 Andrzej Zaborowski <balrog@zabor.org> * Copyright (c) 2007 CodeSourcery * Copyright (c) 2018 Philippe Mathieu-Daudé <f4bug@amsat.org> @@ -122,11 +124,20 @@ struct SDState { uint16_t rca; uint32_t card_status; uint8_t sd_status[64]; + union { + uint8_t ext_csd[512]; + struct { + uint8_t ext_csd_rw[192]; /* Modes segment */ + uint8_t ext_csd_ro[320]; /* Properties segment */ + }; + }; /* Static properties */ uint8_t spec_version; + uint64_t boot_part_size; BlockBackend *blk; + uint8_t boot_config; const SDProto *proto; @@ -169,12 +180,18 @@ struct SDState { static void sd_realize(DeviceState *dev, Error **errp); static const SDProto sd_proto_spi; +static const SDProto sd_proto_emmc; static bool sd_is_spi(SDState *sd) { return sd->proto == &sd_proto_spi; } +static bool sd_is_emmc(SDState *sd) +{ + return sd->proto == &sd_proto_emmc; +} + static const char *sd_version_str(enum SDPhySpecificationVersion version) { static const char *sdphy_version[] = { @@ -438,6 +455,23 @@ static void sd_set_cid(SDState *sd) sd->cid[15] = (sd_crc7(sd->cid, 15) << 1) | 1; } +static void emmc_set_cid(SDState *sd) +{ + sd->cid[0] = MID; /* Fake card manufacturer ID (MID) */ + sd->cid[1] = 0b01; /* CBX: soldered BGA */ + sd->cid[2] = OID[0]; /* OEM/Application ID (OID) */ + sd->cid[3] = PNM[0]; /* Fake product name (PNM) */ + sd->cid[4] = PNM[1]; + sd->cid[5] = PNM[2]; + sd->cid[6] = PNM[3]; + sd->cid[7] = PNM[4]; + sd->cid[8] = PNM[4]; + sd->cid[9] = PRV; /* Fake product revision (PRV) */ + stl_be_p(&sd->cid[10], 0xdeadbeef); /* Fake serial number (PSN) */ + sd->cid[14] = (MDT_MON << 4) | (MDT_YR - 1997); /* Manufacture date (MDT) */ + sd->cid[15] = (sd_crc7(sd->cid, 15) << 1) | 1; +} + /* Card-Specific Data register */ #define HWBLOCK_SHIFT 9 /* 512 bytes */ @@ -451,6 +485,79 @@ static const uint8_t sd_csd_rw_mask[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfe, }; +static void emmc_set_ext_csd(SDState *sd, uint64_t size) +{ + uint32_t sectcount = size >> HWBLOCK_SHIFT; + + memset(sd->ext_csd, 0, sizeof(sd->ext_csd)); /* FIXME only RW at reset */ + + /* Properties segment (RO) */ + sd->ext_csd[EXT_CSD_S_CMD_SET] = 0b1; /* supported command sets */ + sd->ext_csd[EXT_CSD_BOOT_INFO] = 0x0; /* Boot information */ + /* Boot partition size. 128KB unit */ + sd->ext_csd[EXT_CSD_BOOT_MULT] = sd->boot_part_size / (128 * KiB); + sd->ext_csd[EXT_CSD_ACC_SIZE] = 0x1; /* Access size */ + sd->ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] = 0x01; /* HC Erase unit size */ + sd->ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT] = 0x01; /* HC erase timeout */ + sd->ext_csd[EXT_CSD_REL_WR_SEC_C] = 0x1; /* Reliable write sector count */ + sd->ext_csd[EXT_CSD_HC_WP_GRP_SIZE] = 0x01; /* HC write protect group size */ + sd->ext_csd[EXT_CSD_S_C_VCC] = 0x01; /* Sleep current VCC */ + sd->ext_csd[EXT_CSD_S_C_VCCQ] = 0x01; /* Sleep current VCCQ */ + sd->ext_csd[EXT_CSD_S_A_TIMEOUT] = 0x01; /* Sleep/Awake timeout */ + stl_le_p(&sd->ext_csd[EXT_CSD_SEC_CNT], sectcount); /* Sector count */ + sd->ext_csd[210] = 0x46; /* Min write perf for 8bit@52Mhz */ + sd->ext_csd[209] = 0x46; /* Min read perf for 8bit@52Mhz */ + sd->ext_csd[208] = 0x46; /* Min write perf for 4bit@52Mhz */ + sd->ext_csd[207] = 0x46; /* Min read perf for 4bit@52Mhz */ + sd->ext_csd[206] = 0x46; /* Min write perf for 4bit@26Mhz */ + sd->ext_csd[205] = 0x46; /* Min read perf for 4bit@26Mhz */ + sd->ext_csd[EXT_CSD_CARD_TYPE] = 0b11; + sd->ext_csd[EXT_CSD_STRUCTURE] = 2; + sd->ext_csd[EXT_CSD_REV] = 3; + + /* Mode segment (RW) */ + sd->ext_csd[EXT_CSD_PART_CONFIG] = sd->boot_config; +} + +static void emmc_set_csd(SDState *sd, uint64_t size) +{ + int hwblock_shift = HWBLOCK_SHIFT; + uint32_t sectsize = (1 << (SECTOR_SHIFT + 1)) - 1; + uint32_t wpsize = (1 << (WPGROUP_SHIFT + 1)) - 1; + + sd->csd[0] = (3 << 6) | (4 << 2); /* Spec v4.3 with EXT_CSD */ + sd->csd[1] = (1 << 3) | 6; /* Asynchronous data access time: 1ms */ + sd->csd[2] = 0x00; + sd->csd[3] = (1 << 3) | 3;; /* Maximum bus clock frequency: 100MHz */ + sd->csd[4] = 0x0f; + if (size <= 2 * GiB) { + /* use 1k blocks */ + uint32_t csize1k = (size >> (CMULT_SHIFT + 10)) - 1; + sd->csd[5] = 0x5a; + sd->csd[6] = 0x80 | ((csize1k >> 10) & 0xf); + sd->csd[7] = (csize1k >> 2) & 0xff; + } else { /* >= 2GB : size stored in ext CSD, block addressing */ + sd->csd[5] = 0x59; + sd->csd[6] = 0x8f; + sd->csd[7] = 0xff; + sd->ocr = FIELD_DP32(sd->ocr, OCR, CARD_CAPACITY, 1); + } + sd->csd[8] = 0xff; + sd->csd[9] = 0xfc | /* Max. write current */ + ((CMULT_SHIFT - 2) >> 1); + sd->csd[10] = 0x40 | /* Erase sector size */ + (((CMULT_SHIFT - 2) << 7) & 0x80) | (sectsize >> 1); + sd->csd[11] = 0x00 | /* Write protect group size */ + ((sectsize << 7) & 0x80) | wpsize; + sd->csd[12] = 0x90 | /* Write speed factor */ + (hwblock_shift >> 2); + sd->csd[13] = 0x20 | /* Max. write data block length */ + ((hwblock_shift << 6) & 0xc0); + sd->csd[14] = 0x00; + sd->csd[15] = (sd_crc7(sd->csd, 15) << 1) | 1; + emmc_set_ext_csd(sd, size); +} + static void sd_set_csd(SDState *sd, uint64_t size) { int hwblock_shift = HWBLOCK_SHIFT; @@ -539,6 +646,7 @@ static bool sd_req_rca_same(SDState *s, SDRequest req) FIELD(CSR, AKE_SEQ_ERROR, 3, 1) FIELD(CSR, APP_CMD, 5, 1) FIELD(CSR, FX_EVENT, 6, 1) +FIELD(CSR, SWITCH_ERROR, 7, 1) FIELD(CSR, READY_FOR_DATA, 8, 1) FIELD(CSR, CURRENT_STATE, 9, 4) FIELD(CSR, ERASE_RESET, 13, 1) @@ -659,6 +767,40 @@ static uint32_t sd_blk_len(SDState *sd) return sd->blk_len; } +/* + * This requires a disk image that has two boot partitions inserted at the + * beginning of it. The size of the boot partitions is the "boot-size" + * property. + */ +static uint32_t sd_bootpart_offset(SDState *sd) +{ + bool partitions_enabled; + unsigned partition_access; + + if (!sd->boot_part_size || !sd_is_emmc(sd)) { + return 0; + } + + partitions_enabled = sd->ext_csd[EXT_CSD_PART_CONFIG] + & EXT_CSD_PART_CONFIG_EN_MASK; + if (!partitions_enabled) { + return 0; + } + + partition_access = sd->ext_csd[EXT_CSD_PART_CONFIG] + & EXT_CSD_PART_CONFIG_ACC_MASK; + switch (partition_access) { + case EXT_CSD_PART_CONFIG_ACC_DEFAULT: + return sd->boot_part_size * 2; + case EXT_CSD_PART_CONFIG_ACC_BOOT0: + return 0; + case EXT_CSD_PART_CONFIG_ACC_BOOT0 + 1: + return sd->boot_part_size * 1; + default: + g_assert_not_reached(); + } +} + static uint64_t sd_req_get_address(SDState *sd, SDRequest req) { uint64_t addr; @@ -691,13 +833,14 @@ static void sd_reset(DeviceState *dev) sect = 0; } size = sect << HWBLOCK_SHIFT; + size -= sd_bootpart_offset(sd); sect = sd_addr_to_wpnum(size) + 1; sd->state = sd_idle_state; /* card registers */ - sd->rca = 0x0000; + sd->rca = sd_is_emmc(sd) ? 0x0001 : 0x0000; sd->size = size; sd_set_ocr(sd); sd_set_scr(sd); @@ -784,6 +927,24 @@ static const VMStateDescription sd_ocr_vmstate = { }, }; +static bool vmstate_needed_for_emmc(void *opaque) +{ + SDState *sd = opaque; + + return sd_is_emmc(sd); +} + +static const VMStateDescription emmc_extcsd_vmstate = { + .name = "sd-card/ext_csd_modes-state", + .version_id = 1, + .minimum_version_id = 1, + .needed = vmstate_needed_for_emmc, + .fields = (const VMStateField[]) { + VMSTATE_UINT8_ARRAY(ext_csd_rw, SDState, 192), + VMSTATE_END_OF_LIST() + }, +}; + static int sd_vmstate_pre_load(void *opaque) { SDState *sd = opaque; @@ -831,6 +992,7 @@ static const VMStateDescription sd_vmstate = { }, .subsections = (const VMStateDescription * const []) { &sd_ocr_vmstate, + &emmc_extcsd_vmstate, NULL }, }; @@ -880,6 +1042,7 @@ void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert) static void sd_blk_read(SDState *sd, uint64_t addr, uint32_t len) { trace_sdcard_read_block(addr, len); + addr += sd_bootpart_offset(sd); if (!sd->blk || blk_pread(sd->blk, addr, len, sd->data, 0) < 0) { fprintf(stderr, "sd_blk_read: read error on host side\n"); } @@ -888,6 +1051,7 @@ static void sd_blk_read(SDState *sd, uint64_t addr, uint32_t len) static void sd_blk_write(SDState *sd, uint64_t addr, uint32_t len) { trace_sdcard_write_block(addr, len); + addr += sd_bootpart_offset(sd); if (!sd->blk || blk_pwrite(sd->blk, addr, len, sd->data, 0) < 0) { fprintf(stderr, "sd_blk_write: write error on host side\n"); } @@ -969,6 +1133,47 @@ static uint32_t sd_wpbits(SDState *sd, uint64_t addr) return ret; } +enum ExtCsdAccessMode { + EXT_CSD_ACCESS_MODE_COMMAND_SET = 0, + EXT_CSD_ACCESS_MODE_SET_BITS = 1, + EXT_CSD_ACCESS_MODE_CLEAR_BITS = 2, + EXT_CSD_ACCESS_MODE_WRITE_BYTE = 3 +}; + +static void emmc_function_switch(SDState *sd, uint32_t arg) +{ + uint8_t access = extract32(arg, 24, 2); + uint8_t index = extract32(arg, 16, 8); + uint8_t value = extract32(arg, 8, 8); + uint8_t b = sd->ext_csd[index]; + + trace_sdcard_switch(access, index, value, extract32(arg, 0, 2)); + + if (index >= 192) { + qemu_log_mask(LOG_GUEST_ERROR, "MMC switching illegal offset\n"); + sd->card_status |= R_CSR_SWITCH_ERROR_MASK; + return; + } + + switch (access) { + case EXT_CSD_ACCESS_MODE_COMMAND_SET: + qemu_log_mask(LOG_UNIMP, "MMC Command set switching not supported\n"); + return; + case EXT_CSD_ACCESS_MODE_SET_BITS: + b |= value; + break; + case EXT_CSD_ACCESS_MODE_CLEAR_BITS: + b &= ~value; + break; + case EXT_CSD_ACCESS_MODE_WRITE_BYTE: + b = value; + break; + } + + trace_sdcard_ext_csd_update(index, sd->ext_csd[index], b); + sd->ext_csd[index] = b; +} + static void sd_function_switch(SDState *sd, uint32_t arg) { int i, mode, new_func; @@ -1173,8 +1378,19 @@ static sd_rsp_type_t sd_cmd_to_sendingdata(SDState *sd, SDRequest req, /* CMD0 */ static sd_rsp_type_t sd_cmd_GO_IDLE_STATE(SDState *sd, SDRequest req) { - sd->state = sd_idle_state; - sd_reset(DEVICE(sd)); + if (sd->state == sd_sleep_state) { + switch (req.arg) { + case 0x00000000: + case 0xf0f0f0f0: + break; + default: + return sd_r0; + } + } + if (sd->state != sd_inactive_state) { + sd->state = sd_idle_state; + sd_reset(DEVICE(sd)); + } return sd_is_spi(sd) ? sd_r1 : sd_r0; } @@ -1217,6 +1433,44 @@ static sd_rsp_type_t sd_cmd_SEND_RELATIVE_ADDR(SDState *sd, SDRequest req) } } +static sd_rsp_type_t emmc_cmd_SET_RELATIVE_ADDR(SDState *sd, SDRequest req) +{ + switch (sd->state) { + case sd_identification_state: + case sd_standby_state: + sd->state = sd_standby_state; + sd_set_rca(sd, req.arg >> 16); + return sd_r1; + + default: + return sd_invalid_state_for_cmd(sd, req); + } +} + +/* CMD5 */ +static sd_rsp_type_t emmc_cmd_sleep_awake(SDState *sd, SDRequest req) +{ + bool do_sleep = extract32(req.arg, 15, 1); + + switch (sd->state) { + case sd_sleep_state: + if (!do_sleep) { + /* Awake */ + sd->state = sd_standby_state; + } + return sd_r1b; + + case sd_standby_state: + if (do_sleep) { + sd->state = sd_sleep_state; + } + return sd_r1b; + + default: + return sd_invalid_state_for_cmd(sd, req); + } +} + /* CMD6 */ static sd_rsp_type_t sd_cmd_SWITCH_FUNCTION(SDState *sd, SDRequest req) { @@ -1231,6 +1485,19 @@ static sd_rsp_type_t sd_cmd_SWITCH_FUNCTION(SDState *sd, SDRequest req) return sd_cmd_to_sendingdata(sd, req, 0, NULL, 64); } +static sd_rsp_type_t emmc_cmd_SWITCH(SDState *sd, SDRequest req) +{ + switch (sd->state) { + case sd_transfer_state: + sd->state = sd_programming_state; + emmc_function_switch(sd, req.arg); + sd->state = sd_transfer_state; + return sd_r1b; + default: + return sd_invalid_state_for_cmd(sd, req); + } +} + /* CMD7 */ static sd_rsp_type_t sd_cmd_DE_SELECT_CARD(SDState *sd, SDRequest req) { @@ -1293,6 +1560,17 @@ static sd_rsp_type_t sd_cmd_SEND_IF_COND(SDState *sd, SDRequest req) return sd_r7; } +/* CMD8 */ +static sd_rsp_type_t emmc_cmd_SEND_EXT_CSD(SDState *sd, SDRequest req) +{ + if (sd->state != sd_transfer_state) { + return sd_invalid_state_for_cmd(sd, req); + } + + return sd_cmd_to_sendingdata(sd, req, sd_req_get_address(sd, req), + sd->ext_csd, sizeof(sd->ext_csd)); +} + /* CMD9 */ static sd_rsp_type_t spi_cmd_SEND_CSD(SDState *sd, SDRequest req) { @@ -1456,6 +1734,9 @@ static sd_rsp_type_t sd_cmd_SET_BLOCK_COUNT(SDState *sd, SDRequest req) } sd->multi_blk_cnt = req.arg; + if (sd_is_emmc(sd)) { + sd->multi_blk_cnt &= 0xffff; + } trace_sdcard_set_block_count(sd->multi_blk_cnt); return sd_r1; @@ -1488,6 +1769,12 @@ static sd_rsp_type_t sd_cmd_WRITE_SINGLE_BLOCK(SDState *sd, SDRequest req) return sd_cmd_to_receivingdata(sd, req, addr, sd->blk_len); } +/* CMD26 */ +static sd_rsp_type_t emmc_cmd_PROGRAM_CID(SDState *sd, SDRequest req) +{ + return sd_cmd_to_receivingdata(sd, req, 0, sizeof(sd->cid)); +} + /* CMD27 */ static sd_rsp_type_t sd_cmd_PROGRAM_CSD(SDState *sd, SDRequest req) { @@ -1610,6 +1897,7 @@ static sd_rsp_type_t sd_cmd_APP_CMD(SDState *sd, SDRequest req) case sd_ready_state: case sd_identification_state: case sd_inactive_state: + case sd_sleep_state: return sd_invalid_state_for_cmd(sd, req); case sd_idle_state: if (!sd_is_spi(sd) && sd_req_get_rca(sd, req) != 0x0000) { @@ -1837,9 +2125,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) } break; - case 26: /* CMD26: PROGRAM_CID */ - return sd_cmd_to_receivingdata(sd, req, 0, sizeof(sd->cid)); - default: qemu_log_mask(LOG_GUEST_ERROR, "SD: Unknown CMD%i\n", req.cmd); return sd_illegal; @@ -1935,6 +2220,12 @@ int sd_do_command(SDState *sd, SDRequest *req, req->cmd &= 0x3f; } + if (sd->state == sd_sleep_state && req->cmd) { + qemu_log_mask(LOG_GUEST_ERROR, "SD: Card is sleeping\n"); + rtype = sd_r0; + goto send_response; + } + if (sd->card_status & CARD_IS_LOCKED) { if (!cmd_valid_while_locked(sd, req->cmd)) { sd->card_status |= ILLEGAL_COMMAND; @@ -2209,6 +2500,7 @@ uint8_t sd_read_byte(SDState *sd) sd->data_offset, sd->data_size, io_len); switch (sd->current_cmd) { case 6: /* CMD6: SWITCH_FUNCTION */ + case 8: /* CMD8: SEND_EXT_CSD */ case 9: /* CMD9: SEND_CSD */ case 10: /* CMD10: SEND_CID */ case 13: /* ACMD13: SD_STATUS */ @@ -2375,6 +2667,50 @@ static const SDProto sd_proto_sd = { }, }; +static const SDProto sd_proto_emmc = { + /* Only v4.3 is supported */ + .name = "eMMC", + .cmd = { + [0] = {0, sd_bc, "GO_IDLE_STATE", sd_cmd_GO_IDLE_STATE}, + [1] = {0, sd_bcr, "SEND_OP_COND", sd_cmd_SEND_OP_COND}, + [2] = {0, sd_bcr, "ALL_SEND_CID", sd_cmd_ALL_SEND_CID}, + [3] = {0, sd_ac, "SET_RELATIVE_ADDR", emmc_cmd_SET_RELATIVE_ADDR}, + [4] = {0, sd_bc, "SEND_DSR", sd_cmd_unimplemented}, + [5] = {0, sd_ac, "SLEEP/AWAKE", emmc_cmd_sleep_awake}, + [6] = {10, sd_adtc, "SWITCH", emmc_cmd_SWITCH}, + [7] = {0, sd_ac, "(DE)SELECT_CARD", sd_cmd_DE_SELECT_CARD}, + [8] = {0, sd_adtc, "SEND_EXT_CSD", emmc_cmd_SEND_EXT_CSD}, + [9] = {0, sd_ac, "SEND_CSD", sd_cmd_SEND_CSD}, + [10] = {0, sd_ac, "SEND_CID", sd_cmd_SEND_CID}, + [11] = {1, sd_adtc, "READ_DAT_UNTIL_STOP", sd_cmd_unimplemented}, + [12] = {0, sd_ac, "STOP_TRANSMISSION", sd_cmd_STOP_TRANSMISSION}, + [13] = {0, sd_ac, "SEND_STATUS", sd_cmd_SEND_STATUS}, + [14] = {0, sd_adtc, "BUSTEST_R", sd_cmd_unimplemented}, + [15] = {0, sd_ac, "GO_INACTIVE_STATE", sd_cmd_GO_INACTIVE_STATE}, + [16] = {2, sd_ac, "SET_BLOCKLEN", sd_cmd_SET_BLOCKLEN}, + [17] = {2, sd_adtc, "READ_SINGLE_BLOCK", sd_cmd_READ_SINGLE_BLOCK}, + [19] = {0, sd_adtc, "BUSTEST_W", sd_cmd_unimplemented}, + [20] = {3, sd_adtc, "WRITE_DAT_UNTIL_STOP", sd_cmd_unimplemented}, + [23] = {2, sd_ac, "SET_BLOCK_COUNT", sd_cmd_SET_BLOCK_COUNT}, + [24] = {4, sd_adtc, "WRITE_SINGLE_BLOCK", sd_cmd_WRITE_SINGLE_BLOCK}, + [26] = {4, sd_adtc, "PROGRAM_CID", emmc_cmd_PROGRAM_CID}, + [27] = {4, sd_adtc, "PROGRAM_CSD", sd_cmd_PROGRAM_CSD}, + [28] = {6, sd_ac, "SET_WRITE_PROT", sd_cmd_SET_WRITE_PROT}, + [29] = {6, sd_ac, "CLR_WRITE_PROT", sd_cmd_CLR_WRITE_PROT}, + [30] = {6, sd_adtc, "SEND_WRITE_PROT", sd_cmd_SEND_WRITE_PROT}, + [31] = {6, sd_adtc, "SEND_WRITE_PROT_TYPE", sd_cmd_unimplemented}, + [35] = {5, sd_ac, "ERASE_WR_BLK_START", sd_cmd_ERASE_WR_BLK_START}, + [36] = {5, sd_ac, "ERASE_WR_BLK_END", sd_cmd_ERASE_WR_BLK_END}, + [38] = {5, sd_ac, "ERASE", sd_cmd_ERASE}, + [39] = {9, sd_ac, "FAST_IO", sd_cmd_unimplemented}, + [40] = {9, sd_bcr, "GO_IRQ_STATE", sd_cmd_unimplemented}, + [42] = {7, sd_adtc, "LOCK_UNLOCK", sd_cmd_LOCK_UNLOCK}, + [49] = {0, sd_adtc, "SET_TIME", sd_cmd_unimplemented}, + [55] = {8, sd_ac, "APP_CMD", sd_cmd_APP_CMD}, + [56] = {8, sd_adtc, "GEN_CMD", sd_cmd_GEN_CMD}, + }, +}; + static void sd_instance_init(Object *obj) { SDState *sd = SDMMC_COMMON(obj); @@ -2446,6 +2782,15 @@ static void sd_realize(DeviceState *dev, Error **errp) } } +static void emmc_realize(DeviceState *dev, Error **errp) +{ + SDState *sd = SDMMC_COMMON(dev); + + sd->spec_version = SD_PHY_SPECv3_01_VERS; /* Actually v4.3 */ + + sd_realize(dev, errp); +} + static Property sdmmc_common_properties[] = { DEFINE_PROP_DRIVE("drive", SDState, blk), DEFINE_PROP_END_OF_LIST() @@ -2457,6 +2802,12 @@ static Property sd_properties[] = { DEFINE_PROP_END_OF_LIST() }; +static Property emmc_properties[] = { + DEFINE_PROP_UINT64("boot-partition-size", SDState, boot_part_size, 0), + DEFINE_PROP_UINT8("boot-config", SDState, boot_config, 0x0), + DEFINE_PROP_END_OF_LIST() +}; + static void sdmmc_common_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -2509,6 +2860,23 @@ static void sd_spi_class_init(ObjectClass *klass, void *data) sc->proto = &sd_proto_spi; } +static void emmc_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + SDCardClass *sc = SDMMC_COMMON_CLASS(klass); + + dc->desc = "eMMC"; + dc->realize = emmc_realize; + device_class_set_props(dc, emmc_properties); + /* Reason: Soldered on board */ + dc->user_creatable = false; + + sc->proto = &sd_proto_emmc; + + sc->set_cid = emmc_set_cid; + sc->set_csd = emmc_set_csd; +} + static const TypeInfo sd_types[] = { { .name = TYPE_SDMMC_COMMON, @@ -2530,6 +2898,11 @@ static const TypeInfo sd_types[] = { .parent = TYPE_SD_CARD, .class_init = sd_spi_class_init, }, + { + .name = TYPE_EMMC, + .parent = TYPE_SDMMC_COMMON, + .class_init = emmc_class_init, + }, }; DEFINE_TYPES(sd_types) diff --git a/hw/sd/trace-events b/hw/sd/trace-events index 5dfe6be7b7..43671dc791 100644 --- a/hw/sd/trace-events +++ b/hw/sd/trace-events @@ -57,6 +57,8 @@ sdcard_write_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x" sdcard_write_data(const char *proto, const char *cmd_desc, uint8_t cmd, uint32_t offset, uint8_t value) "%s %20s/ CMD%02d ofs %"PRIu32" value 0x%02x" sdcard_read_data(const char *proto, const char *cmd_desc, uint8_t cmd, uint32_t offset, uint64_t size, uint32_t blklen) "%s %20s/ CMD%02d ofs %"PRIu32" size %"PRIu64" blklen %" PRIu32 sdcard_set_voltage(uint16_t millivolts) "%u mV" +sdcard_ext_csd_update(unsigned index, uint8_t oval, uint8_t nval) "index %u: 0x%02x -> 0x%02x" +sdcard_switch(unsigned access, unsigned index, unsigned value, unsigned set) "SWITCH acc:%u idx:%u val:%u set:%u" # pxa2xx_mmci.c pxa2xx_mmci_read(uint8_t size, uint32_t addr, uint32_t value) "size %d addr 0x%02x value 0x%08x" diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index 8e6466c1dd..d946161717 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -985,6 +985,14 @@ void cpu_reset_interrupt(CPUState *cpu, int mask); void cpu_exit(CPUState *cpu); /** + * cpu_pause: + * @cpu: The CPU to pause. + * + * Pauses CPU, i.e. puts CPU into stopped state. + */ +void cpu_pause(CPUState *cpu); + +/** * cpu_resume: * @cpu: The CPU to resume. * diff --git a/include/hw/loader.h b/include/hw/loader.h index 9844c5e3cf..7f6d06b956 100644 --- a/include/hw/loader.h +++ b/include/hw/loader.h @@ -77,15 +77,13 @@ ssize_t load_image_targphys(const char *filename, hwaddr, ssize_t load_image_mr(const char *filename, MemoryRegion *mr); /* This is the limit on the maximum uncompressed image size that - * load_image_gzipped_buffer() and load_image_gzipped() will read. It prevents + * load_image_gzipped_buffer() will read. It prevents * g_malloc() in those functions from allocating a huge amount of memory. */ #define LOAD_IMAGE_MAX_GUNZIP_BYTES (256 << 20) ssize_t load_image_gzipped_buffer(const char *filename, uint64_t max_sz, uint8_t **buffer); -ssize_t load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz); - /** * unpack_efi_zboot_image: * @buffer: pointer to a variable holding the address of a buffer containing the diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 5336728a23..77bfcbdf73 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -624,8 +624,9 @@ qemu_irq qdev_get_gpio_in(DeviceState *dev, int n); * @name: Name of the input GPIO array * @n: Number of the GPIO line in that array (which must be in range) * - * Returns the qemu_irq corresponding to a named input GPIO line - * (which the device has set up with qdev_init_gpio_in_named()). + * Returns the qemu_irq corresponding to a single input GPIO line + * in a named array of input GPIO lines on a device (which the device + * has set up with qdev_init_gpio_in_named()). * The @name string must correspond to an input GPIO array which exists on * the device, and the index @n of the GPIO line must be valid (i.e. * be at least 0 and less than the total number of input GPIOs in that @@ -673,15 +674,15 @@ void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin); * GPIO lines * @dev: Device whose GPIO to connect * @name: Name of the output GPIO array - * @n: Number of the anonymous output GPIO line (which must be in range) + * @n: Number of the output GPIO line within that array (which must be in range) * @input_pin: qemu_irq to connect the output line to * - * This function connects an anonymous output GPIO line on a device - * up to an arbitrary qemu_irq, so that when the device asserts that - * output GPIO line, the qemu_irq's callback is invoked. + * This function connects a single GPIO output in a named array of output + * GPIO lines on a device up to an arbitrary qemu_irq, so that when the + * device asserts that output GPIO line, the qemu_irq's callback is invoked. * The @name string must correspond to an output GPIO array which exists on * the device, and the index @n of the GPIO line must be valid (i.e. - * be at least 0 and less than the total number of input GPIOs in that + * be at least 0 and less than the total number of output GPIOs in that * array); this function will assert() if passed an invalid name or index. * * Outbound GPIO lines can be connected to any qemu_irq, but the common @@ -796,7 +797,7 @@ void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n); * @dev: Device to create output GPIOs for * @pins: Pointer to qemu_irq or qemu_irq array for the GPIO lines * @name: Name to give this array of GPIO lines - * @n: Number of GPIO lines to create + * @n: Number of GPIO lines to create in this array * * Like qdev_init_gpio_out(), but creates an array of GPIO output lines * with a name. Code using the device can then connect these GPIO lines diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h index 0d6d9e452b..d35a839f5e 100644 --- a/include/hw/sd/sd.h +++ b/include/hw/sd/sd.h @@ -96,6 +96,9 @@ OBJECT_DECLARE_TYPE(SDState, SDCardClass, SD_CARD) #define TYPE_SD_CARD_SPI "sd-card-spi" DECLARE_INSTANCE_CHECKER(SDState, SD_CARD_SPI, TYPE_SD_CARD_SPI) +#define TYPE_EMMC "emmc" +DECLARE_INSTANCE_CHECKER(SDState, EMMC, TYPE_EMMC) + struct SDCardClass { /*< private >*/ DeviceClass parent_class; diff --git a/include/ui/console.h b/include/ui/console.h index a208a68b88..fa986ab97e 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -233,7 +233,7 @@ typedef struct DisplayChangeListenerOps { /* optional */ void (*dpy_mouse_set)(DisplayChangeListener *dcl, - int x, int y, int on); + int x, int y, bool on); /* optional */ void (*dpy_cursor_define)(DisplayChangeListener *dcl, QEMUCursor *cursor); @@ -322,9 +322,8 @@ void dpy_gfx_replace_surface(QemuConsole *con, void dpy_text_cursor(QemuConsole *con, int x, int y); void dpy_text_update(QemuConsole *con, int x, int y, int w, int h); void dpy_text_resize(QemuConsole *con, int w, int h); -void dpy_mouse_set(QemuConsole *con, int x, int y, int on); +void dpy_mouse_set(QemuConsole *con, int x, int y, bool on); void dpy_cursor_define(QemuConsole *con, QEMUCursor *cursor); -bool dpy_cursor_define_supported(QemuConsole *con); bool dpy_gfx_check_format(QemuConsole *con, pixman_format_code_t format); diff --git a/meson.build b/meson.build index 6a93da48e1..a1e51277b0 100644 --- a/meson.build +++ b/meson.build @@ -1070,7 +1070,8 @@ if get_option('attr').allowed() endif endif -cocoa = dependency('appleframeworks', modules: ['Cocoa', 'CoreVideo'], +cocoa = dependency('appleframeworks', + modules: ['Cocoa', 'CoreVideo', 'QuartzCore'], required: get_option('cocoa')) vmnet = dependency('appleframeworks', modules: 'vmnet', required: get_option('vmnet')) diff --git a/system/cpus.c b/system/cpus.c index d3640c9503..5e3a988a0a 100644 --- a/system/cpus.c +++ b/system/cpus.c @@ -568,6 +568,22 @@ void cpu_thread_signal_destroyed(CPUState *cpu) qemu_cond_signal(&qemu_cpu_cond); } +void cpu_pause(CPUState *cpu) +{ + if (qemu_cpu_is_self(cpu)) { + qemu_cpu_stop(cpu, true); + } else { + cpu->stop = true; + qemu_cpu_kick(cpu); + } +} + +void cpu_resume(CPUState *cpu) +{ + cpu->stop = false; + cpu->stopped = false; + qemu_cpu_kick(cpu); +} static bool all_vcpus_paused(void) { @@ -588,12 +604,7 @@ void pause_all_vcpus(void) qemu_clock_enable(QEMU_CLOCK_VIRTUAL, false); CPU_FOREACH(cpu) { - if (qemu_cpu_is_self(cpu)) { - qemu_cpu_stop(cpu, true); - } else { - cpu->stop = true; - qemu_cpu_kick(cpu); - } + cpu_pause(cpu); } /* We need to drop the replay_lock so any vCPU threads woken up @@ -613,13 +624,6 @@ void pause_all_vcpus(void) bql_lock(); } -void cpu_resume(CPUState *cpu) -{ - cpu->stop = false; - cpu->stopped = false; - qemu_cpu_kick(cpu); -} - void resume_all_vcpus(void) { CPUState *cpu; diff --git a/system/physmem.c b/system/physmem.c index 2154432cb6..9a3b3a7636 100644 --- a/system/physmem.c +++ b/system/physmem.c @@ -1845,11 +1845,14 @@ static void ram_block_add(RAMBlock *new_block, Error **errp) } if (new_block->flags & RAM_GUEST_MEMFD) { + int ret; + assert(kvm_enabled()); assert(new_block->guest_memfd < 0); - if (ram_block_discard_require(true) < 0) { - error_setg_errno(errp, errno, + ret = ram_block_discard_require(true); + if (ret < 0) { + error_setg_errno(errp, -ret, "cannot set up private guest memory: discard currently blocked"); error_append_hint(errp, "Are you using assigned devices?\n"); goto out_free; diff --git a/system/vl.c b/system/vl.c index bdd2f6ecf6..9e8f16f155 100644 --- a/system/vl.c +++ b/system/vl.c @@ -1000,9 +1000,16 @@ static bool vga_interface_available(VGAInterfaceType t) const VGAInterfaceInfo *ti = &vga_interfaces[t]; assert(t < VGA_TYPE_MAX); - return !ti->class_names[0] || - module_object_class_by_name(ti->class_names[0]) || - module_object_class_by_name(ti->class_names[1]); + + if (!ti->class_names[0] || module_object_class_by_name(ti->class_names[0])) { + return true; + } + + if (ti->class_names[1] && module_object_class_by_name(ti->class_names[1])) { + return true; + } + + return false; } static const char * diff --git a/target/tricore/cpu.c b/target/tricore/cpu.c index 4d9c0368f2..1a26171590 100644 --- a/target/tricore/cpu.c +++ b/target/tricore/cpu.c @@ -155,6 +155,11 @@ static void tc37x_initfn(Object *obj) set_feature(&cpu->env, TRICORE_FEATURE_162); } +static bool tricore_cpu_exec_interrupt(CPUState *cs, int interrupt_request) +{ + /* Interrupts are not implemented */ + return false; +} #include "hw/core/sysemu-cpu-ops.h" @@ -169,6 +174,7 @@ static const TCGCPUOps tricore_tcg_ops = { .synchronize_from_tb = tricore_cpu_synchronize_from_tb, .restore_state_to_opc = tricore_restore_state_to_opc, .tlb_fill = tricore_cpu_tlb_fill, + .cpu_exec_interrupt = tricore_cpu_exec_interrupt, .cpu_exec_halt = tricore_cpu_has_work, }; diff --git a/ui/cocoa.m b/ui/cocoa.m index 2935247cdd..4c2dd33532 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -25,6 +25,7 @@ #include "qemu/osdep.h" #import <Cocoa/Cocoa.h> +#import <QuartzCore/QuartzCore.h> #include <crt_externs.h> #include "qemu/help-texts.h" @@ -79,12 +80,16 @@ static void cocoa_switch(DisplayChangeListener *dcl, DisplaySurface *surface); static void cocoa_refresh(DisplayChangeListener *dcl); +static void cocoa_mouse_set(DisplayChangeListener *dcl, int x, int y, bool on); +static void cocoa_cursor_define(DisplayChangeListener *dcl, QEMUCursor *cursor); static const DisplayChangeListenerOps dcl_ops = { .dpy_name = "cocoa", .dpy_gfx_update = cocoa_update, .dpy_gfx_switch = cocoa_switch, .dpy_refresh = cocoa_refresh, + .dpy_mouse_set = cocoa_mouse_set, + .dpy_cursor_define = cocoa_cursor_define, }; static DisplayChangeListener dcl = { .ops = &dcl_ops, @@ -307,6 +312,12 @@ static void handleAnyDeviceErrors(Error * err) BOOL isMouseGrabbed; BOOL isAbsoluteEnabled; CFMachPortRef eventsTap; + CGColorSpaceRef colorspace; + CALayer *cursorLayer; + QEMUCursor *cursor; + int mouseX; + int mouseY; + bool mouseOn; } - (void) switchSurface:(pixman_image_t *)image; - (void) grabMouse; @@ -359,9 +370,16 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven [trackingArea release]; screen.width = frameRect.size.width; screen.height = frameRect.size.height; + colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_14_0 [self setClipsToBounds:YES]; #endif + [self setWantsLayer:YES]; + cursorLayer = [[CALayer alloc] init]; + [cursorLayer setAnchorPoint:CGPointMake(0, 1)]; + [cursorLayer setAutoresizingMask:kCALayerMaxXMargin | + kCALayerMinYMargin]; + [[self layer] addSublayer:cursorLayer]; } return self; @@ -379,6 +397,9 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven CFRelease(eventsTap); } + CGColorSpaceRelease(colorspace); + [cursorLayer release]; + cursor_unref(cursor); [super dealloc]; } @@ -423,6 +444,72 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven [NSCursor unhide]; } +- (void)setMouseX:(int)x y:(int)y on:(bool)on +{ + CGPoint position; + + mouseX = x; + mouseY = y; + mouseOn = on; + + position.x = mouseX; + position.y = screen.height - mouseY; + + [CATransaction begin]; + [CATransaction setDisableActions:YES]; + [cursorLayer setPosition:position]; + [cursorLayer setHidden:!mouseOn]; + [CATransaction commit]; +} + +- (void)setCursor:(QEMUCursor *)given_cursor +{ + CGDataProviderRef provider; + CGImageRef image; + CGRect bounds = CGRectZero; + + cursor_unref(cursor); + cursor = given_cursor; + + if (!cursor) { + return; + } + + cursor_ref(cursor); + + bounds.size.width = cursor->width; + bounds.size.height = cursor->height; + + provider = CGDataProviderCreateWithData( + NULL, + cursor->data, + cursor->width * cursor->height * 4, + NULL + ); + + image = CGImageCreate( + cursor->width, //width + cursor->height, //height + 8, //bitsPerComponent + 32, //bitsPerPixel + cursor->width * 4, //bytesPerRow + colorspace, //colorspace + kCGBitmapByteOrder32Little | kCGImageAlphaFirst, //bitmapInfo + provider, //provider + NULL, //decode + 0, //interpolate + kCGRenderingIntentDefault //intent + ); + + CGDataProviderRelease(provider); + [CATransaction begin]; + [CATransaction setDisableActions:YES]; + [cursorLayer setBounds:bounds]; + [cursorLayer setContents:(id)image]; + [CATransaction commit]; + CGImageRelease(image); +} + - (void) drawRect:(NSRect) rect { COCOA_DEBUG("QemuCocoaView: drawRect\n"); @@ -456,7 +543,7 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven DIV_ROUND_UP(bitsPerPixel, 8) * 2, //bitsPerComponent bitsPerPixel, //bitsPerPixel stride, //bytesPerRow - CGColorSpaceCreateWithName(kCGColorSpaceSRGB), //colorspace + colorspace, //colorspace kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst, //bitmapInfo dataProviderRef, //provider NULL, //decode @@ -2012,6 +2099,21 @@ static void cocoa_refresh(DisplayChangeListener *dcl) [pool release]; } +static void cocoa_mouse_set(DisplayChangeListener *dcl, int x, int y, bool on) +{ + dispatch_async(dispatch_get_main_queue(), ^{ + [cocoaView setMouseX:x y:y on:on]; + }); +} + +static void cocoa_cursor_define(DisplayChangeListener *dcl, QEMUCursor *cursor) +{ + dispatch_async(dispatch_get_main_queue(), ^{ + BQL_LOCK_GUARD(); + [cocoaView setCursor:qemu_console_get_cursor(dcl->con)]; + }); +} + static void cocoa_display_init(DisplayState *ds, DisplayOptions *opts) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; diff --git a/ui/console.c b/ui/console.c index e67c5dae2b..e8f0083af7 100644 --- a/ui/console.c +++ b/ui/console.c @@ -49,7 +49,8 @@ typedef struct QemuGraphicConsole { uint32_t head; QEMUCursor *cursor; - int cursor_x, cursor_y, cursor_on; + int cursor_x, cursor_y; + bool cursor_on; } QemuGraphicConsole; typedef QemuConsoleClass QemuGraphicConsoleClass; @@ -957,7 +958,7 @@ void dpy_text_resize(QemuConsole *con, int w, int h) } } -void dpy_mouse_set(QemuConsole *c, int x, int y, int on) +void dpy_mouse_set(QemuConsole *c, int x, int y, bool on) { QemuGraphicConsole *con = QEMU_GRAPHIC_CONSOLE(c); DisplayState *s = c->ds; @@ -1000,19 +1001,6 @@ void dpy_cursor_define(QemuConsole *c, QEMUCursor *cursor) } } -bool dpy_cursor_define_supported(QemuConsole *con) -{ - DisplayState *s = con->ds; - DisplayChangeListener *dcl; - - QLIST_FOREACH(dcl, &s->listeners, next) { - if (dcl->ops->dpy_cursor_define) { - return true; - } - } - return false; -} - QEMUGLContext dpy_gl_ctx_create(QemuConsole *con, struct QEMUGLParams *qparams) { diff --git a/ui/dbus-listener.c b/ui/dbus-listener.c index 5490088043..a54123acea 100644 --- a/ui/dbus-listener.c +++ b/ui/dbus-listener.c @@ -726,7 +726,7 @@ static void dbus_gfx_switch(DisplayChangeListener *dcl, } static void dbus_mouse_set(DisplayChangeListener *dcl, - int x, int y, int on) + int x, int y, bool on) { DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl); diff --git a/ui/gtk.c b/ui/gtk.c index 93b13b7a30..bc29f7a1b4 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -446,7 +446,7 @@ static GdkDevice *gd_get_pointer(GdkDisplay *dpy) } static void gd_mouse_set(DisplayChangeListener *dcl, - int x, int y, int visible) + int x, int y, bool visible) { VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); GdkDisplay *dpy; diff --git a/ui/sdl2.c b/ui/sdl2.c index 0a0eb5a42d..98ed974371 100644 --- a/ui/sdl2.c +++ b/ui/sdl2.c @@ -49,7 +49,7 @@ static int gui_grab_code = KMOD_LALT | KMOD_LCTRL; static SDL_Cursor *sdl_cursor_normal; static SDL_Cursor *sdl_cursor_hidden; static int absolute_enabled; -static int guest_cursor; +static bool guest_cursor; static int guest_x, guest_y; static SDL_Cursor *guest_sprite; static Notifier mouse_mode_notifier; @@ -729,7 +729,7 @@ void sdl2_poll_events(struct sdl2_console *scon) } static void sdl_mouse_warp(DisplayChangeListener *dcl, - int x, int y, int on) + int x, int y, bool on) { struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl); diff --git a/ui/spice-display.c b/ui/spice-display.c index 8a8472d029..c794ae0649 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -254,7 +254,7 @@ static void qemu_spice_create_update(SimpleSpiceDisplay *ssd) static SimpleSpiceCursor* qemu_spice_create_cursor_update(SimpleSpiceDisplay *ssd, QEMUCursor *c, - int on) + bool on) { size_t size = c ? c->width * c->height * 4 : 0; SimpleSpiceCursor *update; @@ -448,7 +448,8 @@ void qemu_spice_display_switch(SimpleSpiceDisplay *ssd, qemu_mutex_lock(&ssd->lock); if (ssd->cursor) { g_free(ssd->ptr_define); - ssd->ptr_define = qemu_spice_create_cursor_update(ssd, ssd->cursor, 0); + ssd->ptr_define = + qemu_spice_create_cursor_update(ssd, ssd->cursor, false); } qemu_mutex_unlock(&ssd->lock); } @@ -476,7 +477,7 @@ void qemu_spice_cursor_refresh_bh(void *opaque) ssd->mouse_x = -1; ssd->mouse_y = -1; qemu_mutex_unlock(&ssd->lock); - dpy_mouse_set(ssd->dcl.con, x, y, 1); + dpy_mouse_set(ssd->dcl.con, x, y, true); } else { qemu_mutex_unlock(&ssd->lock); } @@ -747,7 +748,7 @@ static void display_refresh(DisplayChangeListener *dcl) } static void display_mouse_set(DisplayChangeListener *dcl, - int x, int y, int on) + int x, int y, bool on) { SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl); @@ -774,7 +775,7 @@ static void display_mouse_define(DisplayChangeListener *dcl, g_free(ssd->ptr_move); ssd->ptr_move = NULL; g_free(ssd->ptr_define); - ssd->ptr_define = qemu_spice_create_cursor_update(ssd, c, 0); + ssd->ptr_define = qemu_spice_create_cursor_update(ssd, c, false); qemu_mutex_unlock(&ssd->lock); qemu_spice_wakeup(ssd); } diff --git a/ui/vnc.c b/ui/vnc.c index dd530f04e5..dae5d51210 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -981,7 +981,7 @@ int vnc_send_framebuffer_update(VncState *vs, int x, int y, int w, int h) } static void vnc_mouse_set(DisplayChangeListener *dcl, - int x, int y, int visible) + int x, int y, bool visible) { /* can we ask the client(s) to move the pointer ??? */ } |