aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xconfigure37
-rw-r--r--console.c26
-rw-r--r--default-configs/i386-softmmu.mak1
-rw-r--r--disas.c19
-rw-r--r--exec.c18
-rw-r--r--hw/esp.c574
-rw-r--r--hw/imx_avic.c2
-rw-r--r--hw/omap.h8
-rw-r--r--hw/pci-stub.c15
-rw-r--r--hw/pci_ids.h1
-rw-r--r--hw/sh_serial.c6
-rw-r--r--hw/vga.c14
-rw-r--r--hw/vga_int.h2
-rw-r--r--kvm-all.c13
-rw-r--r--kvm.h2
-rw-r--r--monitor.c29
-rw-r--r--oslib-posix.c3
-rw-r--r--target-arm/cpu.c6
-rw-r--r--target-arm/cpu.h15
-rw-r--r--target-arm/helper.c441
-rw-r--r--target-arm/machine.c10
-rw-r--r--target-arm/translate.c4
-rw-r--r--target-s390x/kvm.c35
-rw-r--r--targphys.h16
-rw-r--r--trace-events17
25 files changed, 1110 insertions, 204 deletions
diff --git a/configure b/configure
index 500fe24cba..0a3896e757 100755
--- a/configure
+++ b/configure
@@ -1139,10 +1139,26 @@ else
exit 1
fi
+# Consult white-list to determine whether to enable werror
+# by default. Only enable by default for git builds
+z_version=`cut -f3 -d. $source_path/VERSION`
+
+if test -z "$werror" ; then
+ if test "$z_version" = "50" -a \
+ "$linux" = "yes" ; then
+ werror="yes"
+ else
+ werror="no"
+ fi
+fi
+
gcc_flags="-Wold-style-declaration -Wold-style-definition -Wtype-limits"
gcc_flags="-Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers $gcc_flags"
gcc_flags="-Wmissing-include-dirs -Wempty-body -Wnested-externs $gcc_flags"
gcc_flags="-fstack-protector-all -Wendif-labels $gcc_flags"
+if test "$werror" = "yes" ; then
+ gcc_flags="-Werror $gcc_flags"
+fi
cat > $TMPC << EOF
int main(void) { return 0; }
EOF
@@ -2573,7 +2589,7 @@ if test "$libiscsi" != "no" ; then
#include <iscsi/iscsi.h>
int main(void) { iscsi_unmap_sync(NULL,0,0,0,NULL,0); return 0; }
EOF
- if compile_prog "-Werror" "-liscsi" ; then
+ if compile_prog "" "-liscsi" ; then
libiscsi="yes"
LIBS="$LIBS -liscsi"
else
@@ -2877,19 +2893,6 @@ if test "$debug" = "no" ; then
CFLAGS="-O2 -D_FORTIFY_SOURCE=2 $CFLAGS"
fi
-# Consult white-list to determine whether to enable werror
-# by default. Only enable by default for git builds
-z_version=`cut -f3 -d. $source_path/VERSION`
-
-if test -z "$werror" ; then
- if test "$z_version" = "50" -a \
- "$linux" = "yes" ; then
- werror="yes"
- else
- werror="no"
- fi
-fi
-
# Disable zero malloc errors for official releases unless explicitly told to
# enable/disable
if test -z "$zero_malloc" ; then
@@ -2900,10 +2903,6 @@ if test -z "$zero_malloc" ; then
fi
fi
-if test "$werror" = "yes" ; then
- QEMU_CFLAGS="-Werror $QEMU_CFLAGS"
-fi
-
if test "$solaris" = "no" ; then
if $ld --version 2>/dev/null | grep "GNU ld" >/dev/null 2>/dev/null ; then
LDFLAGS="-Wl,--warn-common $LDFLAGS"
@@ -3571,7 +3570,7 @@ case "$target_arch2" in
bflt="yes"
target_nptl="yes"
gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml"
- target_phys_bits=32
+ target_phys_bits=64
target_llong_alignment=4
target_libs_softmmu="$fdt_libs"
;;
diff --git a/console.c b/console.c
index 6a463f5918..4525cc70b8 100644
--- a/console.c
+++ b/console.c
@@ -28,6 +28,7 @@
//#define DEBUG_CONSOLE
#define DEFAULT_BACKSCROLL 512
#define MAX_CONSOLES 12
+#define CONSOLE_CURSOR_PERIOD 500
#define QEMU_RGBA(r, g, b, a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
#define QEMU_RGB(r, g, b) QEMU_RGBA(r, g, b, 0xff)
@@ -139,6 +140,8 @@ struct TextConsole {
TextCell *cells;
int text_x[2], text_y[2], cursor_invalidate;
int echo;
+ bool cursor_visible_phase;
+ QEMUTimer *cursor_timer;
int update_x0;
int update_y0;
@@ -615,7 +618,7 @@ static void console_show_cursor(TextConsole *s, int show)
y += s->total_height;
if (y < s->height) {
c = &s->cells[y1 * s->width + x];
- if (show) {
+ if (show && s->cursor_visible_phase) {
TextAttributes t_attrib = s->t_attrib_default;
t_attrib.invers = !(t_attrib.invers); /* invert fg and bg */
vga_putcharxy(s->ds, x, y, c->ch, &t_attrib);
@@ -1083,6 +1086,10 @@ void console_select(unsigned int index)
s = consoles[index];
if (s) {
DisplayState *ds = s->ds;
+
+ if (active_console->cursor_timer) {
+ qemu_del_timer(active_console->cursor_timer);
+ }
active_console = s;
if (ds_get_bits_per_pixel(s->ds)) {
ds->surface = qemu_resize_displaysurface(ds, s->g_width, s->g_height);
@@ -1090,6 +1097,10 @@ void console_select(unsigned int index)
s->ds->surface->width = s->width;
s->ds->surface->height = s->height;
}
+ if (s->cursor_timer) {
+ qemu_mod_timer(s->cursor_timer,
+ qemu_get_clock_ms(rt_clock) + CONSOLE_CURSOR_PERIOD / 2);
+ }
dpy_resize(s->ds);
vga_hw_invalidate();
}
@@ -1454,6 +1465,16 @@ static void text_console_set_echo(CharDriverState *chr, bool echo)
s->echo = echo;
}
+static void text_console_update_cursor(void *opaque)
+{
+ TextConsole *s = opaque;
+
+ s->cursor_visible_phase = !s->cursor_visible_phase;
+ vga_hw_invalidate();
+ qemu_mod_timer(s->cursor_timer,
+ qemu_get_clock_ms(rt_clock) + CONSOLE_CURSOR_PERIOD / 2);
+}
+
static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
{
TextConsole *s;
@@ -1482,6 +1503,9 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
s->g_height = ds_get_height(s->ds);
}
+ s->cursor_timer =
+ qemu_new_timer_ms(rt_clock, text_console_update_cursor, s);
+
s->hw_invalidate = text_console_invalidate;
s->hw_text_update = text_console_update;
s->hw = s;
diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 2c78175ae7..fee8cde88b 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -25,3 +25,4 @@ CONFIG_HPET=y
CONFIG_APPLESMC=y
CONFIG_I8259=y
CONFIG_PFLASH_CFI01=y
+CONFIG_ESP=y
diff --git a/disas.c b/disas.c
index 93d8d30d1b..7b2acc9943 100644
--- a/disas.c
+++ b/disas.c
@@ -64,6 +64,22 @@ generic_print_address (bfd_vma addr, struct disassemble_info *info)
(*info->fprintf_func) (info->stream, "0x%" PRIx64, addr);
}
+/* Print address in hex, truncated to the width of a target virtual address. */
+static void
+generic_print_target_address(bfd_vma addr, struct disassemble_info *info)
+{
+ uint64_t mask = ~0ULL >> (64 - TARGET_VIRT_ADDR_SPACE_BITS);
+ generic_print_address(addr & mask, info);
+}
+
+/* Print address in hex, truncated to the width of a host virtual address. */
+static void
+generic_print_host_address(bfd_vma addr, struct disassemble_info *info)
+{
+ uint64_t mask = ~0ULL >> (64 - (sizeof(void *) * 8));
+ generic_print_address(addr & mask, info);
+}
+
/* Just return the given address. */
int
@@ -154,6 +170,7 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
disasm_info.read_memory_func = target_read_memory;
disasm_info.buffer_vma = code;
disasm_info.buffer_length = size;
+ disasm_info.print_address_func = generic_print_target_address;
#ifdef TARGET_WORDS_BIGENDIAN
disasm_info.endian = BFD_ENDIAN_BIG;
@@ -274,6 +291,7 @@ void disas(FILE *out, void *code, unsigned long size)
int (*print_insn)(bfd_vma pc, disassemble_info *info);
INIT_DISASSEMBLE_INFO(disasm_info, out, fprintf);
+ disasm_info.print_address_func = generic_print_host_address;
disasm_info.buffer = code;
disasm_info.buffer_vma = (uintptr_t)code;
@@ -386,6 +404,7 @@ void monitor_disas(Monitor *mon, CPUArchState *env,
monitor_disas_env = env;
monitor_disas_is_physical = is_physical;
disasm_info.read_memory_func = monitor_read_memory;
+ disasm_info.print_address_func = generic_print_target_address;
disasm_info.buffer_vma = pc;
diff --git a/exec.c b/exec.c
index dd4833d316..c9fa17de6f 100644
--- a/exec.c
+++ b/exec.c
@@ -2536,26 +2536,14 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
exit(1);
#endif
} else {
-#if defined(TARGET_S390X) && defined(CONFIG_KVM)
- /* S390 KVM requires the topmost vma of the RAM to be smaller than
- an system defined value, which is at least 256GB. Larger systems
- have larger values. We put the guest between the end of data
- segment (system break) and this value. We use 32GB as a base to
- have enough room for the system break to grow. */
- new_block->host = mmap((void*)0x800000000, size,
- PROT_EXEC|PROT_READ|PROT_WRITE,
- MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
- if (new_block->host == MAP_FAILED) {
- fprintf(stderr, "Allocating RAM failed\n");
- abort();
- }
-#else
if (xen_enabled()) {
xen_ram_alloc(new_block->offset, size, mr);
+ } else if (kvm_enabled()) {
+ /* some s390/kvm configurations have special constraints */
+ new_block->host = kvm_vmalloc(size);
} else {
new_block->host = qemu_vmalloc(size);
}
-#endif
qemu_madvise(new_block->host, size, QEMU_MADV_MERGEABLE);
}
}
diff --git a/hw/esp.c b/hw/esp.c
index 8d73e56886..c6422ad340 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -2,6 +2,7 @@
* QEMU ESP/NCR53C9x emulation
*
* Copyright (c) 2005-2006 Fabrice Bellard
+ * Copyright (c) 2012 Herve Poussineau
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,9 +24,11 @@
*/
#include "sysbus.h"
+#include "pci.h"
#include "scsi.h"
#include "esp.h"
#include "trace.h"
+#include "qemu-log.h"
/*
* On Sparc32, this is the ESP (NCR53C90) part of chip STP2000 (Master I/O),
@@ -35,21 +38,16 @@
* http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9X.txt
*/
-#define ESP_ERROR(fmt, ...) \
- do { printf("ESP ERROR: %s: " fmt, __func__ , ## __VA_ARGS__); } while (0)
-
#define ESP_REGS 16
#define TI_BUFSZ 16
typedef struct ESPState ESPState;
struct ESPState {
- SysBusDevice busdev;
- MemoryRegion iomem;
uint8_t rregs[ESP_REGS];
uint8_t wregs[ESP_REGS];
qemu_irq irq;
- uint32_t it_shift;
+ uint8_t chip_id;
int32_t ti_size;
uint32_t ti_rptr, ti_wptr;
uint32_t status;
@@ -113,10 +111,12 @@ struct ESPState {
#define CMD_MSGACC 0x12
#define CMD_PAD 0x18
#define CMD_SATN 0x1a
+#define CMD_RSTATN 0x1b
#define CMD_SEL 0x41
#define CMD_SELATN 0x42
#define CMD_SELATNS 0x43
#define CMD_ENSEL 0x44
+#define CMD_DISSEL 0x45
#define STAT_DO 0x00
#define STAT_DI 0x01
@@ -144,6 +144,7 @@ struct ESPState {
#define CFG1_RESREPT 0x40
#define TCHI_FAS100A 0x4
+#define TCHI_AM53C974 0x12
static void esp_raise_irq(ESPState *s)
{
@@ -163,11 +164,8 @@ static void esp_lower_irq(ESPState *s)
}
}
-static void esp_dma_enable(void *opaque, int irq, int level)
+static void esp_dma_enable(ESPState *s, int irq, int level)
{
- DeviceState *d = opaque;
- ESPState *s = container_of(d, ESPState, busdev.qdev);
-
if (level) {
s->dma_enabled = 1;
trace_esp_dma_enable();
@@ -183,7 +181,7 @@ static void esp_dma_enable(void *opaque, int irq, int level)
static void esp_request_cancelled(SCSIRequest *req)
{
- ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);
+ ESPState *s = req->hba_private;
if (req == s->current_req) {
scsi_req_unref(s->current_req);
@@ -239,7 +237,7 @@ static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid)
trace_esp_do_busid_cmd(busid);
lun = busid & 7;
current_lun = scsi_device_find(&s->bus, 0, s->current_dev->id, lun);
- s->current_req = scsi_req_new(current_lun, 0, lun, buf, NULL);
+ s->current_req = scsi_req_new(current_lun, 0, lun, buf, s);
datalen = scsi_req_enqueue(s->current_req);
s->ti_size = datalen;
if (datalen != 0) {
@@ -270,7 +268,7 @@ static void handle_satn(ESPState *s)
uint8_t buf[32];
int len;
- if (!s->dma_enabled) {
+ if (s->dma && !s->dma_enabled) {
s->dma_cb = handle_satn;
return;
}
@@ -284,7 +282,7 @@ static void handle_s_without_atn(ESPState *s)
uint8_t buf[32];
int len;
- if (!s->dma_enabled) {
+ if (s->dma && !s->dma_enabled) {
s->dma_cb = handle_s_without_atn;
return;
}
@@ -296,7 +294,7 @@ static void handle_s_without_atn(ESPState *s)
static void handle_satn_stop(ESPState *s)
{
- if (!s->dma_enabled) {
+ if (s->dma && !s->dma_enabled) {
s->dma_cb = handle_satn_stop;
return;
}
@@ -393,7 +391,7 @@ static void esp_do_dma(ESPState *s)
static void esp_command_complete(SCSIRequest *req, uint32_t status,
size_t resid)
{
- ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);
+ ESPState *s = req->hba_private;
trace_esp_command_complete();
if (s->ti_size != 0) {
@@ -417,7 +415,7 @@ static void esp_command_complete(SCSIRequest *req, uint32_t status,
static void esp_transfer_data(SCSIRequest *req, uint32_t len)
{
- ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);
+ ESPState *s = req->hba_private;
trace_esp_transfer_data(s->dma_left, s->ti_size);
s->async_len = len;
@@ -435,6 +433,11 @@ static void handle_ti(ESPState *s)
{
uint32_t dmalen, minlen;
+ if (s->dma && !s->dma_enabled) {
+ s->dma_cb = handle_ti;
+ return;
+ }
+
dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
if (dmalen==0) {
dmalen=0x10000;
@@ -462,13 +465,11 @@ static void handle_ti(ESPState *s)
}
}
-static void esp_hard_reset(DeviceState *d)
+static void esp_hard_reset(ESPState *s)
{
- ESPState *s = container_of(d, ESPState, busdev.qdev);
-
memset(s->rregs, 0, ESP_REGS);
memset(s->wregs, 0, ESP_REGS);
- s->rregs[ESP_TCHI] = TCHI_FAS100A; // Indicate fas100a
+ s->rregs[ESP_TCHI] = s->chip_id;
s->ti_size = 0;
s->ti_rptr = 0;
s->ti_wptr = 0;
@@ -479,40 +480,23 @@ static void esp_hard_reset(DeviceState *d)
s->rregs[ESP_CFG1] = 7;
}
-static void esp_soft_reset(DeviceState *d)
+static void esp_soft_reset(ESPState *s)
{
- ESPState *s = container_of(d, ESPState, busdev.qdev);
-
qemu_irq_lower(s->irq);
- esp_hard_reset(d);
+ esp_hard_reset(s);
}
-static void parent_esp_reset(void *opaque, int irq, int level)
+static void parent_esp_reset(ESPState *s, int irq, int level)
{
if (level) {
- esp_soft_reset(opaque);
+ esp_soft_reset(s);
}
}
-static void esp_gpio_demux(void *opaque, int irq, int level)
+static uint64_t esp_reg_read(ESPState *s, uint32_t saddr)
{
- switch (irq) {
- case 0:
- parent_esp_reset(opaque, irq, level);
- break;
- case 1:
- esp_dma_enable(opaque, irq, level);
- break;
- }
-}
-
-static uint64_t esp_mem_read(void *opaque, target_phys_addr_t addr,
- unsigned size)
-{
- ESPState *s = opaque;
- uint32_t saddr, old_val;
+ uint32_t old_val;
- saddr = addr >> s->it_shift;
trace_esp_mem_readb(saddr, s->rregs[saddr]);
switch (saddr) {
case ESP_FIFO:
@@ -520,7 +504,8 @@ static uint64_t esp_mem_read(void *opaque, target_phys_addr_t addr,
s->ti_size--;
if ((s->rregs[ESP_RSTAT] & STAT_PIO_MASK) == 0) {
/* Data out. */
- ESP_ERROR("PIO data read not implemented\n");
+ qemu_log_mask(LOG_UNIMP,
+ "esp: PIO data read not implemented\n");
s->rregs[ESP_FIFO] = 0;
} else {
s->rregs[ESP_FIFO] = s->ti_buf[s->ti_rptr++];
@@ -548,13 +533,8 @@ static uint64_t esp_mem_read(void *opaque, target_phys_addr_t addr,
return s->rregs[saddr];
}
-static void esp_mem_write(void *opaque, target_phys_addr_t addr,
- uint64_t val, unsigned size)
+static void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val)
{
- ESPState *s = opaque;
- uint32_t saddr;
-
- saddr = addr >> s->it_shift;
trace_esp_mem_writeb(saddr, s->wregs[saddr], val);
switch (saddr) {
case ESP_TCLO:
@@ -565,7 +545,7 @@ static void esp_mem_write(void *opaque, target_phys_addr_t addr,
if (s->do_cmd) {
s->cmdbuf[s->cmdlen++] = val & 0xff;
} else if (s->ti_size == TI_BUFSZ - 1) {
- ESP_ERROR("fifo overrun\n");
+ trace_esp_error_fifo_overrun();
} else {
s->ti_size++;
s->ti_buf[s->ti_wptr++] = val & 0xff;
@@ -594,7 +574,7 @@ static void esp_mem_write(void *opaque, target_phys_addr_t addr,
break;
case CMD_RESET:
trace_esp_mem_writeb_cmd_reset(val);
- esp_soft_reset(&s->busdev.qdev);
+ esp_soft_reset(s);
break;
case CMD_BUSRESET:
trace_esp_mem_writeb_cmd_bus_reset(val);
@@ -628,6 +608,9 @@ static void esp_mem_write(void *opaque, target_phys_addr_t addr,
case CMD_SATN:
trace_esp_mem_writeb_cmd_satn(val);
break;
+ case CMD_RSTATN:
+ trace_esp_mem_writeb_cmd_rstatn(val);
+ break;
case CMD_SEL:
trace_esp_mem_writeb_cmd_sel(val);
handle_s_without_atn(s);
@@ -644,8 +627,13 @@ static void esp_mem_write(void *opaque, target_phys_addr_t addr,
trace_esp_mem_writeb_cmd_ensel(val);
s->rregs[ESP_RINTR] = 0;
break;
+ case CMD_DISSEL:
+ trace_esp_mem_writeb_cmd_dissel(val);
+ s->rregs[ESP_RINTR] = 0;
+ esp_raise_irq(s);
+ break;
default:
- ESP_ERROR("Unhandled ESP command (%2.2x)\n", (unsigned)val);
+ trace_esp_error_unhandled_command(val);
break;
}
break;
@@ -660,7 +648,7 @@ static void esp_mem_write(void *opaque, target_phys_addr_t addr,
s->rregs[saddr] = val;
break;
default:
- ESP_ERROR("invalid write of 0x%02x at [0x%x]\n", (unsigned)val, saddr);
+ trace_esp_error_invalid_write(val, saddr);
return;
}
s->wregs[saddr] = val;
@@ -672,13 +660,6 @@ static bool esp_mem_accepts(void *opaque, target_phys_addr_t addr,
return (size == 1) || (is_write && size == 4);
}
-static const MemoryRegionOps esp_mem_ops = {
- .read = esp_mem_read,
- .write = esp_mem_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
- .valid.accepts = esp_mem_accepts,
-};
-
static const VMStateDescription vmstate_esp = {
.name ="esp",
.version_id = 3,
@@ -701,6 +682,40 @@ static const VMStateDescription vmstate_esp = {
}
};
+typedef struct {
+ SysBusDevice busdev;
+ MemoryRegion iomem;
+ uint32_t it_shift;
+ ESPState esp;
+} SysBusESPState;
+
+static void sysbus_esp_mem_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val, unsigned int size)
+{
+ SysBusESPState *sysbus = opaque;
+ uint32_t saddr;
+
+ saddr = addr >> sysbus->it_shift;
+ esp_reg_write(&sysbus->esp, saddr, val);
+}
+
+static uint64_t sysbus_esp_mem_read(void *opaque, target_phys_addr_t addr,
+ unsigned int size)
+{
+ SysBusESPState *sysbus = opaque;
+ uint32_t saddr;
+
+ saddr = addr >> sysbus->it_shift;
+ return esp_reg_read(&sysbus->esp, saddr);
+}
+
+static const MemoryRegionOps sysbus_esp_mem_ops = {
+ .read = sysbus_esp_mem_read,
+ .write = sysbus_esp_mem_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid.accepts = esp_mem_accepts,
+};
+
void esp_init(target_phys_addr_t espaddr, int it_shift,
ESPDMAMemoryReadWriteFunc dma_memory_read,
ESPDMAMemoryReadWriteFunc dma_memory_write,
@@ -709,14 +724,16 @@ void esp_init(target_phys_addr_t espaddr, int it_shift,
{
DeviceState *dev;
SysBusDevice *s;
+ SysBusESPState *sysbus;
ESPState *esp;
dev = qdev_create(NULL, "esp");
- esp = DO_UPCAST(ESPState, busdev.qdev, dev);
+ sysbus = DO_UPCAST(SysBusESPState, busdev.qdev, dev);
+ esp = &sysbus->esp;
esp->dma_memory_read = dma_memory_read;
esp->dma_memory_write = dma_memory_write;
esp->dma_opaque = dma_opaque;
- esp->it_shift = it_shift;
+ sysbus->it_shift = it_shift;
/* XXX for now until rc4030 has been changed to use DMA enable signal */
esp->dma_enabled = 1;
qdev_init_nofail(dev);
@@ -737,48 +754,441 @@ static const struct SCSIBusInfo esp_scsi_info = {
.cancel = esp_request_cancelled
};
-static int esp_init1(SysBusDevice *dev)
+static void sysbus_esp_gpio_demux(void *opaque, int irq, int level)
{
- ESPState *s = FROM_SYSBUS(ESPState, dev);
+ DeviceState *d = opaque;
+ SysBusESPState *sysbus = container_of(d, SysBusESPState, busdev.qdev);
+ ESPState *s = &sysbus->esp;
+
+ switch (irq) {
+ case 0:
+ parent_esp_reset(s, irq, level);
+ break;
+ case 1:
+ esp_dma_enable(opaque, irq, level);
+ break;
+ }
+}
+
+static int sysbus_esp_init(SysBusDevice *dev)
+{
+ SysBusESPState *sysbus = FROM_SYSBUS(SysBusESPState, dev);
+ ESPState *s = &sysbus->esp;
sysbus_init_irq(dev, &s->irq);
- assert(s->it_shift != -1);
+ assert(sysbus->it_shift != -1);
- memory_region_init_io(&s->iomem, &esp_mem_ops, s,
- "esp", ESP_REGS << s->it_shift);
- sysbus_init_mmio(dev, &s->iomem);
+ s->chip_id = TCHI_FAS100A;
+ memory_region_init_io(&sysbus->iomem, &sysbus_esp_mem_ops, sysbus,
+ "esp", ESP_REGS << sysbus->it_shift);
+ sysbus_init_mmio(dev, &sysbus->iomem);
- qdev_init_gpio_in(&dev->qdev, esp_gpio_demux, 2);
+ qdev_init_gpio_in(&dev->qdev, sysbus_esp_gpio_demux, 2);
scsi_bus_new(&s->bus, &dev->qdev, &esp_scsi_info);
return scsi_bus_legacy_handle_cmdline(&s->bus);
}
-static Property esp_properties[] = {
- {.name = NULL},
+static void sysbus_esp_hard_reset(DeviceState *dev)
+{
+ SysBusESPState *sysbus = DO_UPCAST(SysBusESPState, busdev.qdev, dev);
+ esp_hard_reset(&sysbus->esp);
+}
+
+static const VMStateDescription vmstate_sysbus_esp_scsi = {
+ .name = "sysbusespscsi",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_STRUCT(esp, SysBusESPState, 0, vmstate_esp, ESPState),
+ VMSTATE_END_OF_LIST()
+ }
};
-static void esp_class_init(ObjectClass *klass, void *data)
+static void sysbus_esp_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = esp_init1;
- dc->reset = esp_hard_reset;
- dc->vmsd = &vmstate_esp;
- dc->props = esp_properties;
+ k->init = sysbus_esp_init;
+ dc->reset = sysbus_esp_hard_reset;
+ dc->vmsd = &vmstate_sysbus_esp_scsi;
}
-static TypeInfo esp_info = {
+static TypeInfo sysbus_esp_info = {
.name = "esp",
.parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(ESPState),
- .class_init = esp_class_init,
+ .instance_size = sizeof(SysBusESPState),
+ .class_init = sysbus_esp_class_init,
+};
+
+#define DMA_CMD 0x0
+#define DMA_STC 0x1
+#define DMA_SPA 0x2
+#define DMA_WBC 0x3
+#define DMA_WAC 0x4
+#define DMA_STAT 0x5
+#define DMA_SMDLA 0x6
+#define DMA_WMAC 0x7
+
+#define DMA_CMD_MASK 0x03
+#define DMA_CMD_DIAG 0x04
+#define DMA_CMD_MDL 0x10
+#define DMA_CMD_INTE_P 0x20
+#define DMA_CMD_INTE_D 0x40
+#define DMA_CMD_DIR 0x80
+
+#define DMA_STAT_PWDN 0x01
+#define DMA_STAT_ERROR 0x02
+#define DMA_STAT_ABORT 0x04
+#define DMA_STAT_DONE 0x08
+#define DMA_STAT_SCSIINT 0x10
+#define DMA_STAT_BCMBLT 0x20
+
+#define SBAC_STATUS 0x1000
+
+typedef struct PCIESPState {
+ PCIDevice dev;
+ MemoryRegion io;
+ uint32_t dma_regs[8];
+ uint32_t sbac;
+ ESPState esp;
+} PCIESPState;
+
+static void esp_pci_handle_idle(PCIESPState *pci, uint32_t val)
+{
+ trace_esp_pci_dma_idle(val);
+ esp_dma_enable(&pci->esp, 0, 0);
+}
+
+static void esp_pci_handle_blast(PCIESPState *pci, uint32_t val)
+{
+ trace_esp_pci_dma_blast(val);
+ qemu_log_mask(LOG_UNIMP, "am53c974: cmd BLAST not implemented\n");
+}
+
+static void esp_pci_handle_abort(PCIESPState *pci, uint32_t val)
+{
+ trace_esp_pci_dma_abort(val);
+ if (pci->esp.current_req) {
+ scsi_req_cancel(pci->esp.current_req);
+ }
+}
+
+static void esp_pci_handle_start(PCIESPState *pci, uint32_t val)
+{
+ trace_esp_pci_dma_start(val);
+
+ pci->dma_regs[DMA_WBC] = pci->dma_regs[DMA_STC];
+ pci->dma_regs[DMA_WAC] = pci->dma_regs[DMA_SPA];
+ pci->dma_regs[DMA_WMAC] = pci->dma_regs[DMA_SMDLA];
+
+ pci->dma_regs[DMA_STAT] &= ~(DMA_STAT_BCMBLT | DMA_STAT_SCSIINT
+ | DMA_STAT_DONE | DMA_STAT_ABORT
+ | DMA_STAT_ERROR | DMA_STAT_PWDN);
+
+ esp_dma_enable(&pci->esp, 0, 1);
+}
+
+static void esp_pci_dma_write(PCIESPState *pci, uint32_t saddr, uint32_t val)
+{
+ trace_esp_pci_dma_write(saddr, pci->dma_regs[saddr], val);
+ switch (saddr) {
+ case DMA_CMD:
+ pci->dma_regs[saddr] = val;
+ switch (val & DMA_CMD_MASK) {
+ case 0x0: /* IDLE */
+ esp_pci_handle_idle(pci, val);
+ break;
+ case 0x1: /* BLAST */
+ esp_pci_handle_blast(pci, val);
+ break;
+ case 0x2: /* ABORT */
+ esp_pci_handle_abort(pci, val);
+ break;
+ case 0x3: /* START */
+ esp_pci_handle_start(pci, val);
+ break;
+ default: /* can't happen */
+ abort();
+ }
+ break;
+ case DMA_STC:
+ case DMA_SPA:
+ case DMA_SMDLA:
+ pci->dma_regs[saddr] = val;
+ break;
+ case DMA_STAT:
+ if (!(pci->sbac & SBAC_STATUS)) {
+ /* clear some bits on write */
+ uint32_t mask = DMA_STAT_ERROR | DMA_STAT_ABORT | DMA_STAT_DONE;
+ pci->dma_regs[DMA_STAT] &= ~(val & mask);
+ }
+ break;
+ default:
+ trace_esp_pci_error_invalid_write_dma(val, saddr);
+ return;
+ }
+}
+
+static uint32_t esp_pci_dma_read(PCIESPState *pci, uint32_t saddr)
+{
+ uint32_t val;
+
+ val = pci->dma_regs[saddr];
+ if (saddr == DMA_STAT) {
+ if (pci->esp.rregs[ESP_RSTAT] & STAT_INT) {
+ val |= DMA_STAT_SCSIINT;
+ }
+ if (pci->sbac & SBAC_STATUS) {
+ pci->dma_regs[DMA_STAT] &= ~(DMA_STAT_ERROR | DMA_STAT_ABORT |
+ DMA_STAT_DONE);
+ }
+ }
+
+ trace_esp_pci_dma_read(saddr, val);
+ return val;
+}
+
+static void esp_pci_io_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val, unsigned int size)
+{
+ PCIESPState *pci = opaque;
+
+ if (size < 4 || addr & 3) {
+ /* need to upgrade request: we only support 4-bytes accesses */
+ uint32_t current = 0, mask;
+ int shift;
+
+ if (addr < 0x40) {
+ current = pci->esp.wregs[addr >> 2];
+ } else if (addr < 0x60) {
+ current = pci->dma_regs[(addr - 0x40) >> 2];
+ } else if (addr < 0x74) {
+ current = pci->sbac;
+ }
+
+ shift = (4 - size) * 8;
+ mask = (~(uint32_t)0 << shift) >> shift;
+
+ shift = ((4 - (addr & 3)) & 3) * 8;
+ val <<= shift;
+ val |= current & ~(mask << shift);
+ addr &= ~3;
+ size = 4;
+ }
+
+ if (addr < 0x40) {
+ /* SCSI core reg */
+ esp_reg_write(&pci->esp, addr >> 2, val);
+ } else if (addr < 0x60) {
+ /* PCI DMA CCB */
+ esp_pci_dma_write(pci, (addr - 0x40) >> 2, val);
+ } else if (addr == 0x70) {
+ /* DMA SCSI Bus and control */
+ trace_esp_pci_sbac_write(pci->sbac, val);
+ pci->sbac = val;
+ } else {
+ trace_esp_pci_error_invalid_write((int)addr);
+ }
+}
+
+static uint64_t esp_pci_io_read(void *opaque, target_phys_addr_t addr,
+ unsigned int size)
+{
+ PCIESPState *pci = opaque;
+ uint32_t ret;
+
+ if (addr < 0x40) {
+ /* SCSI core reg */
+ ret = esp_reg_read(&pci->esp, addr >> 2);
+ } else if (addr < 0x60) {
+ /* PCI DMA CCB */
+ ret = esp_pci_dma_read(pci, (addr - 0x40) >> 2);
+ } else if (addr == 0x70) {
+ /* DMA SCSI Bus and control */
+ trace_esp_pci_sbac_read(pci->sbac);
+ ret = pci->sbac;
+ } else {
+ /* Invalid region */
+ trace_esp_pci_error_invalid_read((int)addr);
+ ret = 0;
+ }
+
+ /* give only requested data */
+ ret >>= (addr & 3) * 8;
+ ret &= ~(~(uint64_t)0 << (8 * size));
+
+ return ret;
+}
+
+static void esp_pci_dma_memory_rw(PCIESPState *pci, uint8_t *buf, int len,
+ DMADirection dir)
+{
+ dma_addr_t addr;
+ DMADirection expected_dir;
+
+ if (pci->dma_regs[DMA_CMD] & DMA_CMD_DIR) {
+ expected_dir = DMA_DIRECTION_FROM_DEVICE;
+ } else {
+ expected_dir = DMA_DIRECTION_TO_DEVICE;
+ }
+
+ if (dir != expected_dir) {
+ trace_esp_pci_error_invalid_dma_direction();
+ return;
+ }
+
+ if (pci->dma_regs[DMA_STAT] & DMA_CMD_MDL) {
+ qemu_log_mask(LOG_UNIMP, "am53c974: MDL transfer not implemented\n");
+ }
+
+ addr = pci->dma_regs[DMA_SPA];
+ if (pci->dma_regs[DMA_WBC] < len) {
+ len = pci->dma_regs[DMA_WBC];
+ }
+
+ pci_dma_rw(&pci->dev, addr, buf, len, dir);
+
+ /* update status registers */
+ pci->dma_regs[DMA_WBC] -= len;
+ pci->dma_regs[DMA_WAC] += len;
+}
+
+static void esp_pci_dma_memory_read(void *opaque, uint8_t *buf, int len)
+{
+ PCIESPState *pci = opaque;
+ esp_pci_dma_memory_rw(pci, buf, len, DMA_DIRECTION_TO_DEVICE);
+}
+
+static void esp_pci_dma_memory_write(void *opaque, uint8_t *buf, int len)
+{
+ PCIESPState *pci = opaque;
+ esp_pci_dma_memory_rw(pci, buf, len, DMA_DIRECTION_FROM_DEVICE);
+}
+
+static const MemoryRegionOps esp_pci_io_ops = {
+ .read = esp_pci_io_read,
+ .write = esp_pci_io_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .impl = {
+ .min_access_size = 1,
+ .max_access_size = 4,
+ },
+};
+
+static void esp_pci_hard_reset(DeviceState *dev)
+{
+ PCIESPState *pci = DO_UPCAST(PCIESPState, dev.qdev, dev);
+ esp_hard_reset(&pci->esp);
+ pci->dma_regs[DMA_CMD] &= ~(DMA_CMD_DIR | DMA_CMD_INTE_D | DMA_CMD_INTE_P
+ | DMA_CMD_MDL | DMA_CMD_DIAG | DMA_CMD_MASK);
+ pci->dma_regs[DMA_WBC] &= ~0xffff;
+ pci->dma_regs[DMA_WAC] = 0xffffffff;
+ pci->dma_regs[DMA_STAT] &= ~(DMA_STAT_BCMBLT | DMA_STAT_SCSIINT
+ | DMA_STAT_DONE | DMA_STAT_ABORT
+ | DMA_STAT_ERROR);
+ pci->dma_regs[DMA_WMAC] = 0xfffffffd;
+}
+
+static const VMStateDescription vmstate_esp_pci_scsi = {
+ .name = "pciespscsi",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_PCI_DEVICE(dev, PCIESPState),
+ VMSTATE_BUFFER_UNSAFE(dma_regs, PCIESPState, 0, 8 * sizeof(uint32_t)),
+ VMSTATE_STRUCT(esp, PCIESPState, 0, vmstate_esp, ESPState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void esp_pci_command_complete(SCSIRequest *req, uint32_t status,
+ size_t resid)
+{
+ ESPState *s = req->hba_private;
+ PCIESPState *pci = container_of(s, PCIESPState, esp);
+
+ esp_command_complete(req, status, resid);
+ pci->dma_regs[DMA_WBC] = 0;
+ pci->dma_regs[DMA_STAT] |= DMA_STAT_DONE;
+}
+
+static const struct SCSIBusInfo esp_pci_scsi_info = {
+ .tcq = false,
+ .max_target = ESP_MAX_DEVS,
+ .max_lun = 7,
+
+ .transfer_data = esp_transfer_data,
+ .complete = esp_pci_command_complete,
+ .cancel = esp_request_cancelled,
+};
+
+static int esp_pci_scsi_init(PCIDevice *dev)
+{
+ PCIESPState *pci = DO_UPCAST(PCIESPState, dev, dev);
+ ESPState *s = &pci->esp;
+ uint8_t *pci_conf;
+
+ pci_conf = pci->dev.config;
+
+ /* Interrupt pin A */
+ pci_conf[PCI_INTERRUPT_PIN] = 0x01;
+
+ s->dma_memory_read = esp_pci_dma_memory_read;
+ s->dma_memory_write = esp_pci_dma_memory_write;
+ s->dma_opaque = pci;
+ s->chip_id = TCHI_AM53C974;
+ memory_region_init_io(&pci->io, &esp_pci_io_ops, pci, "esp-io", 0x80);
+
+ pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->io);
+ s->irq = pci->dev.irq[0];
+
+ scsi_bus_new(&s->bus, &dev->qdev, &esp_pci_scsi_info);
+ if (!dev->qdev.hotplugged) {
+ return scsi_bus_legacy_handle_cmdline(&s->bus);
+ }
+ return 0;
+}
+
+static int esp_pci_scsi_uninit(PCIDevice *d)
+{
+ PCIESPState *pci = DO_UPCAST(PCIESPState, dev, d);
+
+ memory_region_destroy(&pci->io);
+
+ return 0;
+}
+
+static void esp_pci_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = esp_pci_scsi_init;
+ k->exit = esp_pci_scsi_uninit;
+ k->vendor_id = PCI_VENDOR_ID_AMD;
+ k->device_id = PCI_DEVICE_ID_AMD_SCSI;
+ k->revision = 0x10;
+ k->class_id = PCI_CLASS_STORAGE_SCSI;
+ dc->desc = "AMD Am53c974 PCscsi-PCI SCSI adapter";
+ dc->reset = esp_pci_hard_reset;
+ dc->vmsd = &vmstate_esp_pci_scsi;
+}
+
+static TypeInfo esp_pci_info = {
+ .name = "am53c974",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIESPState),
+ .class_init = esp_pci_class_init,
};
static void esp_register_types(void)
{
- type_register_static(&esp_info);
+ type_register_static(&sysbus_esp_info);
+ type_register_static(&esp_pci_info);
}
type_init(esp_register_types)
diff --git a/hw/imx_avic.c b/hw/imx_avic.c
index 25f47f331b..4f010e8ee2 100644
--- a/hw/imx_avic.c
+++ b/hw/imx_avic.c
@@ -267,7 +267,7 @@ static void imx_avic_write(void *opaque, target_phys_addr_t offset,
/* Vector Registers not yet supported */
if (offset >= 0x100 && offset <= 0x2fc) {
IPRINTF("imx_avic_write to vector register %d ignored\n",
- (offset - 0x100) >> 2);
+ (unsigned int)((offset - 0x100) >> 2));
return;
}
diff --git a/hw/omap.h b/hw/omap.h
index 3d98941b72..413851bc34 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -942,13 +942,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
unsigned long sdram_size,
const char *core);
-# if TARGET_PHYS_ADDR_BITS == 32
-# define OMAP_FMT_plx "%#08x"
-# elif TARGET_PHYS_ADDR_BITS == 64
-# define OMAP_FMT_plx "%#08" PRIx64
-# else
-# error TARGET_PHYS_ADDR_BITS undefined
-# endif
+#define OMAP_FMT_plx "%#08" TARGET_PRIxPHYS
uint32_t omap_badwidth_read8(void *opaque, target_phys_addr_t addr);
void omap_badwidth_write8(void *opaque, target_phys_addr_t addr,
diff --git a/hw/pci-stub.c b/hw/pci-stub.c
index 134c4484b6..e083191529 100644
--- a/hw/pci-stub.c
+++ b/hw/pci-stub.c
@@ -34,6 +34,21 @@ static void pci_error_message(Monitor *mon)
monitor_printf(mon, "PCI devices not supported\n");
}
+void pci_register_bar(PCIDevice *pci_dev, int region_num,
+ uint8_t type, MemoryRegion *memory)
+{
+}
+
+const VMStateDescription vmstate_pci_device = {
+ .name = "PCIDeviceStub",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_END_OF_LIST()
+ }
+};
+
int do_pcie_aer_inject_error(Monitor *mon,
const QDict *qdict, QObject **ret_data)
{
diff --git a/hw/pci_ids.h b/hw/pci_ids.h
index b4801d2168..301bf1cd86 100644
--- a/hw/pci_ids.h
+++ b/hw/pci_ids.h
@@ -59,6 +59,7 @@
#define PCI_VENDOR_ID_AMD 0x1022
#define PCI_DEVICE_ID_AMD_LANCE 0x2000
+#define PCI_DEVICE_ID_AMD_SCSI 0x2020
#define PCI_VENDOR_ID_TI 0x104c
diff --git a/hw/sh_serial.c b/hw/sh_serial.c
index 43b0eb1c1d..1d1883dd20 100644
--- a/hw/sh_serial.c
+++ b/hw/sh_serial.c
@@ -186,7 +186,8 @@ static void sh_serial_write(void *opaque, target_phys_addr_t offs,
}
}
- fprintf(stderr, "sh_serial: unsupported write to 0x%02x\n", offs);
+ fprintf(stderr, "sh_serial: unsupported write to 0x%02"
+ TARGET_PRIxPHYS "\n", offs);
abort();
}
@@ -287,7 +288,8 @@ static uint64_t sh_serial_read(void *opaque, target_phys_addr_t offs,
#endif
if (ret & ~((1 << 16) - 1)) {
- fprintf(stderr, "sh_serial: unsupported read from 0x%02x\n", offs);
+ fprintf(stderr, "sh_serial: unsupported read from 0x%02"
+ TARGET_PRIxPHYS "\n", offs);
abort();
}
diff --git a/hw/vga.c b/hw/vga.c
index acb3f7d924..f82ced8e66 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -38,6 +38,9 @@
//#define DEBUG_BOCHS_VBE
+/* 16 state changes per vertical frame @60 Hz */
+#define VGA_TEXT_CURSOR_PERIOD_MS (1000 * 2 * 16 / 60)
+
/*
* Video Graphics Array (VGA)
*
@@ -1300,6 +1303,7 @@ static void vga_draw_text(VGACommonState *s, int full_update)
uint32_t *ch_attr_ptr;
vga_draw_glyph8_func *vga_draw_glyph8;
vga_draw_glyph9_func *vga_draw_glyph9;
+ int64_t now = qemu_get_clock_ms(vm_clock);
/* compute font data address (in plane 2) */
v = s->sr[VGA_SEQ_CHARACTER_MAP];
@@ -1370,6 +1374,10 @@ static void vga_draw_text(VGACommonState *s, int full_update)
s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
}
cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
+ if (now >= s->cursor_blink_time) {
+ s->cursor_blink_time = now + VGA_TEXT_CURSOR_PERIOD_MS / 2;
+ s->cursor_visible_phase = !s->cursor_visible_phase;
+ }
depth_index = get_depth_index(s->ds);
if (cw == 16)
@@ -1390,7 +1398,7 @@ static void vga_draw_text(VGACommonState *s, int full_update)
cx_max = -1;
for(cx = 0; cx < width; cx++) {
ch_attr = *(uint16_t *)src;
- if (full_update || ch_attr != *ch_attr_ptr) {
+ if (full_update || ch_attr != *ch_attr_ptr || src == cursor_ptr) {
if (cx < cx_min)
cx_min = cx;
if (cx > cx_max)
@@ -1420,7 +1428,8 @@ static void vga_draw_text(VGACommonState *s, int full_update)
font_ptr, cheight, fgcol, bgcol, dup9);
}
if (src == cursor_ptr &&
- !(s->cr[VGA_CRTC_CURSOR_START] & 0x20)) {
+ !(s->cr[VGA_CRTC_CURSOR_START] & 0x20) &&
+ s->cursor_visible_phase) {
int line_start, line_last, h;
/* draw the cursor */
line_start = s->cr[VGA_CRTC_CURSOR_START] & 0x1f;
@@ -1884,6 +1893,7 @@ static void vga_update_display(void *opaque)
}
if (graphic_mode != s->graphic_mode) {
s->graphic_mode = graphic_mode;
+ s->cursor_blink_time = qemu_get_clock_ms(vm_clock);
full_update = 1;
}
switch(graphic_mode) {
diff --git a/hw/vga_int.h b/hw/vga_int.h
index 3b38764a38..8938093682 100644
--- a/hw/vga_int.h
+++ b/hw/vga_int.h
@@ -156,6 +156,8 @@ typedef struct VGACommonState {
uint32_t last_scr_width, last_scr_height; /* in pixels */
uint32_t last_depth; /* in bits */
uint8_t cursor_start, cursor_end;
+ bool cursor_visible_phase;
+ int64_t cursor_blink_time;
uint32_t cursor_offset;
unsigned int (*rgb_to_pixel)(unsigned int r,
unsigned int g, unsigned b);
diff --git a/kvm-all.c b/kvm-all.c
index f8e432841f..1016ca49b1 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1655,6 +1655,19 @@ int kvm_allows_irq0_override(void)
return !kvm_irqchip_in_kernel() || kvm_has_gsi_routing();
}
+void *kvm_vmalloc(ram_addr_t size)
+{
+#ifdef TARGET_S390X
+ void *mem;
+
+ mem = kvm_arch_vmalloc(size);
+ if (mem) {
+ return mem;
+ }
+#endif
+ return qemu_vmalloc(size);
+}
+
void kvm_setup_guest_memory(void *start, size_t size)
{
if (!kvm_has_sync_mmu()) {
diff --git a/kvm.h b/kvm.h
index 9c7b0ea6ae..ddc7c53cb0 100644
--- a/kvm.h
+++ b/kvm.h
@@ -70,6 +70,8 @@ int kvm_init_vcpu(CPUArchState *env);
int kvm_cpu_exec(CPUArchState *env);
#if !defined(CONFIG_USER_ONLY)
+void *kvm_vmalloc(ram_addr_t size);
+void *kvm_arch_vmalloc(ram_addr_t size);
void kvm_setup_guest_memory(void *start, size_t size);
int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size);
diff --git a/monitor.c b/monitor.c
index f6107badb6..188c03d5b1 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1262,45 +1262,24 @@ static void do_print(Monitor *mon, const QDict *qdict)
int format = qdict_get_int(qdict, "format");
target_phys_addr_t val = qdict_get_int(qdict, "val");
-#if TARGET_PHYS_ADDR_BITS == 32
switch(format) {
case 'o':
- monitor_printf(mon, "%#o", val);
+ monitor_printf(mon, "%#" TARGET_PRIoPHYS, val);
break;
case 'x':
- monitor_printf(mon, "%#x", val);
+ monitor_printf(mon, "%#" TARGET_PRIxPHYS, val);
break;
case 'u':
- monitor_printf(mon, "%u", val);
+ monitor_printf(mon, "%" TARGET_PRIuPHYS, val);
break;
default:
case 'd':
- monitor_printf(mon, "%d", val);
+ monitor_printf(mon, "%" TARGET_PRIdPHYS, val);
break;
case 'c':
monitor_printc(mon, val);
break;
}
-#else
- switch(format) {
- case 'o':
- monitor_printf(mon, "%#" PRIo64, val);
- break;
- case 'x':
- monitor_printf(mon, "%#" PRIx64, val);
- break;
- case 'u':
- monitor_printf(mon, "%" PRIu64, val);
- break;
- default:
- case 'd':
- monitor_printf(mon, "%" PRId64, val);
- break;
- case 'c':
- monitor_printc(mon, val);
- break;
- }
-#endif
monitor_printf(mon, "\n");
}
diff --git a/oslib-posix.c b/oslib-posix.c
index 6b7ba646c7..dbeb6272b8 100644
--- a/oslib-posix.c
+++ b/oslib-posix.c
@@ -41,6 +41,9 @@ extern int daemon(int, int);
therefore we need special code which handles running on Valgrind. */
# define QEMU_VMALLOC_ALIGN (512 * 4096)
# define CONFIG_VALGRIND
+#elif defined(__linux__) && defined(__s390x__)
+ /* Use 1 MiB (segment size) alignment so gmap can be used by KVM. */
+# define QEMU_VMALLOC_ALIGN (256 * 4096)
#else
# define QEMU_VMALLOC_ALIGN getpagesize()
#endif
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index ae5795337f..b00f5fa547 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -129,7 +129,7 @@ static void arm_cpu_reset(CPUState *s)
static inline void set_feature(CPUARMState *env, int feature)
{
- env->features |= 1u << feature;
+ env->features |= 1ULL << feature;
}
static void arm_cpu_initfn(Object *obj)
@@ -192,6 +192,9 @@ void arm_cpu_realize(ARMCPU *cpu)
if (arm_feature(env, ARM_FEATURE_VFP3)) {
set_feature(env, ARM_FEATURE_VFP);
}
+ if (arm_feature(env, ARM_FEATURE_LPAE)) {
+ set_feature(env, ARM_FEATURE_PXN);
+ }
register_cp_regs_for_features(cpu);
}
@@ -532,6 +535,7 @@ static void cortex_a15_initfn(Object *obj)
set_feature(&cpu->env, ARM_FEATURE_V7MP);
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
+ set_feature(&cpu->env, ARM_FEATURE_LPAE);
cpu->midr = 0x412fc0f1;
cpu->reset_fpsid = 0x410430f0;
cpu->mvfr0 = 0x10110222;
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 33afa185e9..191895cca8 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -113,7 +113,9 @@ typedef struct CPUARMState {
uint32_t c1_xscaleauxcr; /* XScale auxiliary control register. */
uint32_t c1_scr; /* secure config register. */
uint32_t c2_base0; /* MMU translation table base 0. */
- uint32_t c2_base1; /* MMU translation table base 1. */
+ uint32_t c2_base0_hi; /* MMU translation table base 0, high 32 bits */
+ uint32_t c2_base1; /* MMU translation table base 0. */
+ uint32_t c2_base1_hi; /* MMU translation table base 1, high 32 bits */
uint32_t c2_control; /* MMU translation table base control. */
uint32_t c2_mask; /* MMU translation table base selection mask. */
uint32_t c2_base_mask; /* MMU translation table base 0 mask. */
@@ -127,6 +129,7 @@ typedef struct CPUARMState {
uint32_t c6_insn; /* Fault address registers. */
uint32_t c6_data;
uint32_t c7_par; /* Translation result. */
+ uint32_t c7_par_hi; /* Translation result, high 32 bits */
uint32_t c9_insn; /* Cache lockdown registers. */
uint32_t c9_data;
uint32_t c9_pmcr; /* performance monitor control register */
@@ -221,7 +224,7 @@ typedef struct CPUARMState {
/* These fields after the common ones so they are preserved on reset. */
/* Internal CPU feature flags. */
- uint32_t features;
+ uint64_t features;
void *nvic;
const struct arm_boot_info *boot_info;
@@ -386,11 +389,13 @@ enum arm_features {
ARM_FEATURE_CACHE_DIRTY_REG, /* 1136/1176 cache dirty status register */
ARM_FEATURE_CACHE_BLOCK_OPS, /* v6 optional cache block operations */
ARM_FEATURE_MPIDR, /* has cp15 MPIDR */
+ ARM_FEATURE_PXN, /* has Privileged Execute Never bit */
+ ARM_FEATURE_LPAE, /* has Large Physical Address Extension */
};
static inline int arm_feature(CPUARMState *env, int feature)
{
- return (env->features & (1u << feature)) != 0;
+ return (env->features & (1ULL << feature)) != 0;
}
void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf);
@@ -619,7 +624,7 @@ static inline bool cp_access_ok(CPUARMState *env,
#define TARGET_PAGE_BITS 10
#endif
-#define TARGET_PHYS_ADDR_SPACE_BITS 32
+#define TARGET_PHYS_ADDR_SPACE_BITS 40
#define TARGET_VIRT_ADDR_SPACE_BITS 32
static inline CPUARMState *cpu_init(const char *cpu_model)
@@ -636,7 +641,7 @@ static inline CPUARMState *cpu_init(const char *cpu_model)
#define cpu_signal_handler cpu_arm_signal_handler
#define cpu_list arm_cpu_list
-#define CPU_SAVE_VERSION 7
+#define CPU_SAVE_VERSION 9
/* MMU modes definitions */
#define MMU_MODE0_SUFFIX _kernel
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 23099236ad..5727da296c 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3,11 +3,12 @@
#include "helper.h"
#include "host-utils.h"
#include "sysemu.h"
+#include "bitops.h"
#ifndef CONFIG_USER_ONLY
static inline int get_phys_addr(CPUARMState *env, uint32_t address,
int access_type, int is_user,
- uint32_t *phys_ptr, int *prot,
+ target_phys_addr_t *phys_ptr, int *prot,
target_ulong *page_size);
#endif
@@ -216,9 +217,9 @@ static const ARMCPRegInfo v6_cp_reginfo[] = {
.access = PL1_W, .type = ARM_CP_NOP },
{ .name = "ISB", .cp = 15, .crn = 7, .crm = 5, .opc1 = 0, .opc2 = 4,
.access = PL0_W, .type = ARM_CP_NOP },
- { .name = "ISB", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 4,
+ { .name = "DSB", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 4,
.access = PL0_W, .type = ARM_CP_NOP },
- { .name = "ISB", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 5,
+ { .name = "DMB", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 5,
.access = PL0_W, .type = ARM_CP_NOP },
{ .name = "IFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 2,
.access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c6_insn),
@@ -346,7 +347,7 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
*/
{ .name = "DBGDRAR", .cp = 14, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 0,
.access = PL0_R, .type = ARM_CP_CONST, .resetvalue = 0 },
- { .name = "DBGDRAR", .cp = 14, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0,
+ { .name = "DBGDSAR", .cp = 14, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0,
.access = PL0_R, .type = ARM_CP_CONST, .resetvalue = 0 },
/* the old v6 WFI, UNPREDICTABLE in v7 but we choose to NOP */
{ .name = "NOP", .cp = 15, .crn = 7, .crm = 0, .opc1 = 0, .opc2 = 4,
@@ -491,7 +492,9 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
static int par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
{
- if (arm_feature(env, ARM_FEATURE_V7)) {
+ if (arm_feature(env, ARM_FEATURE_LPAE)) {
+ env->cp15.c7_par = value;
+ } else if (arm_feature(env, ARM_FEATURE_V7)) {
env->cp15.c7_par = value & 0xfffff6ff;
} else {
env->cp15.c7_par = value & 0xfffff1ff;
@@ -501,9 +504,20 @@ static int par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
#ifndef CONFIG_USER_ONLY
/* get_phys_addr() isn't present for user-mode-only targets */
+
+/* Return true if extended addresses are enabled, ie this is an
+ * LPAE implementation and we are using the long-descriptor translation
+ * table format because the TTBCR EAE bit is set.
+ */
+static inline bool extended_addresses_enabled(CPUARMState *env)
+{
+ return arm_feature(env, ARM_FEATURE_LPAE)
+ && (env->cp15.c2_control & (1 << 31));
+}
+
static int ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
{
- uint32_t phys_addr;
+ target_phys_addr_t phys_addr;
target_ulong page_size;
int prot;
int ret, is_user = ri->opc2 & 2;
@@ -515,18 +529,44 @@ static int ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
}
ret = get_phys_addr(env, value, access_type, is_user,
&phys_addr, &prot, &page_size);
- if (ret == 0) {
- /* We do not set any attribute bits in the PAR */
- if (page_size == (1 << 24)
- && arm_feature(env, ARM_FEATURE_V7)) {
- env->cp15.c7_par = (phys_addr & 0xff000000) | 1 << 1;
+ if (extended_addresses_enabled(env)) {
+ /* ret is a DFSR/IFSR value for the long descriptor
+ * translation table format, but with WnR always clear.
+ * Convert it to a 64-bit PAR.
+ */
+ uint64_t par64 = (1 << 11); /* LPAE bit always set */
+ if (ret == 0) {
+ par64 |= phys_addr & ~0xfffULL;
+ /* We don't set the ATTR or SH fields in the PAR. */
} else {
- env->cp15.c7_par = phys_addr & 0xfffff000;
+ par64 |= 1; /* F */
+ par64 |= (ret & 0x3f) << 1; /* FS */
+ /* Note that S2WLK and FSTAGE are always zero, because we don't
+ * implement virtualization and therefore there can't be a stage 2
+ * fault.
+ */
}
+ env->cp15.c7_par = par64;
+ env->cp15.c7_par_hi = par64 >> 32;
} else {
- env->cp15.c7_par = ((ret & (10 << 1)) >> 5) |
- ((ret & (12 << 1)) >> 6) |
- ((ret & 0xf) << 1) | 1;
+ /* ret is a DFSR/IFSR value for the short descriptor
+ * translation table format (with WnR always clear).
+ * Convert it to a 32-bit PAR.
+ */
+ if (ret == 0) {
+ /* We do not set any attribute bits in the PAR */
+ if (page_size == (1 << 24)
+ && arm_feature(env, ARM_FEATURE_V7)) {
+ env->cp15.c7_par = (phys_addr & 0xff000000) | 1 << 1;
+ } else {
+ env->cp15.c7_par = phys_addr & 0xfffff000;
+ }
+ } else {
+ env->cp15.c7_par = ((ret & (10 << 1)) >> 5) |
+ ((ret & (12 << 1)) >> 6) |
+ ((ret & 0xf) << 1) | 1;
+ }
+ env->cp15.c7_par_hi = 0;
}
return 0;
}
@@ -653,7 +693,20 @@ static const ARMCPRegInfo pmsav5_cp_reginfo[] = {
static int vmsa_ttbcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t value)
{
- value &= 7;
+ if (arm_feature(env, ARM_FEATURE_LPAE)) {
+ value &= ~((7 << 19) | (3 << 14) | (0xf << 3));
+ /* With LPAE the TTBCR could result in a change of ASID
+ * via the TTBCR.A1 bit, so do a TLB flush.
+ */
+ tlb_flush(env, 1);
+ } else {
+ value &= 7;
+ }
+ /* Note that we always calculate c2_mask and c2_base_mask, but
+ * they are only used for short-descriptor tables (ie if EAE is 0);
+ * for long-descriptor tables the TTBCR fields are used differently
+ * and the c2_mask and c2_base_mask values are meaningless.
+ */
env->cp15.c2_control = value;
env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> value);
env->cp15.c2_base_mask = ~((uint32_t)0x3fffu >> value);
@@ -679,7 +732,7 @@ static const ARMCPRegInfo vmsa_cp_reginfo[] = {
.fieldoffset = offsetof(CPUARMState, cp15.c2_base0), .resetvalue = 0, },
{ .name = "TTBR1", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 1,
.access = PL1_RW,
- .fieldoffset = offsetof(CPUARMState, cp15.c2_base0), .resetvalue = 0, },
+ .fieldoffset = offsetof(CPUARMState, cp15.c2_base1), .resetvalue = 0, },
{ .name = "TTBCR", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 2,
.access = PL1_RW, .writefn = vmsa_ttbcr_write,
.resetfn = vmsa_ttbcr_reset,
@@ -871,6 +924,96 @@ static const ARMCPRegInfo mpidr_cp_reginfo[] = {
REGINFO_SENTINEL
};
+static int par64_read(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t *value)
+{
+ *value = ((uint64_t)env->cp15.c7_par_hi << 32) | env->cp15.c7_par;
+ return 0;
+}
+
+static int par64_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
+{
+ env->cp15.c7_par_hi = value >> 32;
+ env->cp15.c7_par = value;
+ return 0;
+}
+
+static void par64_reset(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ env->cp15.c7_par_hi = 0;
+ env->cp15.c7_par = 0;
+}
+
+static int ttbr064_read(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t *value)
+{
+ *value = ((uint64_t)env->cp15.c2_base0_hi << 32) | env->cp15.c2_base0;
+ return 0;
+}
+
+static int ttbr064_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ env->cp15.c2_base0_hi = value >> 32;
+ env->cp15.c2_base0 = value;
+ /* Writes to the 64 bit format TTBRs may change the ASID */
+ tlb_flush(env, 1);
+ return 0;
+}
+
+static void ttbr064_reset(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ env->cp15.c2_base0_hi = 0;
+ env->cp15.c2_base0 = 0;
+}
+
+static int ttbr164_read(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t *value)
+{
+ *value = ((uint64_t)env->cp15.c2_base1_hi << 32) | env->cp15.c2_base1;
+ return 0;
+}
+
+static int ttbr164_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ env->cp15.c2_base1_hi = value >> 32;
+ env->cp15.c2_base1 = value;
+ return 0;
+}
+
+static void ttbr164_reset(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ env->cp15.c2_base1_hi = 0;
+ env->cp15.c2_base1 = 0;
+}
+
+static const ARMCPRegInfo lpae_cp_reginfo[] = {
+ /* NOP AMAIR0/1: the override is because these clash with tha rather
+ * broadly specified TLB_LOCKDOWN entry in the generic cp_reginfo.
+ */
+ { .name = "AMAIR0", .cp = 15, .crn = 10, .crm = 3, .opc1 = 0, .opc2 = 0,
+ .access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_OVERRIDE,
+ .resetvalue = 0 },
+ { .name = "AMAIR1", .cp = 15, .crn = 10, .crm = 3, .opc1 = 0, .opc2 = 1,
+ .access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_OVERRIDE,
+ .resetvalue = 0 },
+ /* 64 bit access versions of the (dummy) debug registers */
+ { .name = "DBGDRAR", .cp = 14, .crm = 1, .opc1 = 0,
+ .access = PL0_R, .type = ARM_CP_CONST|ARM_CP_64BIT, .resetvalue = 0 },
+ { .name = "DBGDSAR", .cp = 14, .crm = 2, .opc1 = 0,
+ .access = PL0_R, .type = ARM_CP_CONST|ARM_CP_64BIT, .resetvalue = 0 },
+ { .name = "PAR", .cp = 15, .crm = 7, .opc1 = 0,
+ .access = PL1_RW, .type = ARM_CP_64BIT,
+ .readfn = par64_read, .writefn = par64_write, .resetfn = par64_reset },
+ { .name = "TTBR0", .cp = 15, .crm = 2, .opc1 = 0,
+ .access = PL1_RW, .type = ARM_CP_64BIT, .readfn = ttbr064_read,
+ .writefn = ttbr064_write, .resetfn = ttbr064_reset },
+ { .name = "TTBR1", .cp = 15, .crm = 2, .opc1 = 1,
+ .access = PL1_RW, .type = ARM_CP_64BIT, .readfn = ttbr164_read,
+ .writefn = ttbr164_write, .resetfn = ttbr164_reset },
+ REGINFO_SENTINEL
+};
+
static int sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
{
env->cp15.c1_sys = value;
@@ -1016,6 +1159,9 @@ void register_cp_regs_for_features(ARMCPU *cpu)
if (arm_feature(env, ARM_FEATURE_MPIDR)) {
define_arm_cp_regs(cpu, mpidr_cp_reginfo);
}
+ if (arm_feature(env, ARM_FEATURE_LPAE)) {
+ define_arm_cp_regs(cpu, lpae_cp_reginfo);
+ }
/* Slightly awkwardly, the OMAP and StrongARM cores need all of
* cp15 crn=0 to be writes-ignored, whereas for other cores they should
* be read-only (ie write causes UNDEF exception).
@@ -1833,8 +1979,8 @@ static uint32_t get_level1_table_address(CPUARMState *env, uint32_t address)
}
static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type,
- int is_user, uint32_t *phys_ptr, int *prot,
- target_ulong *page_size)
+ int is_user, target_phys_addr_t *phys_ptr,
+ int *prot, target_ulong *page_size)
{
int code;
uint32_t table;
@@ -1843,7 +1989,7 @@ static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type,
int ap;
int domain;
int domain_prot;
- uint32_t phys_addr;
+ target_phys_addr_t phys_addr;
/* Pagetable walk. */
/* Lookup l1 descriptor. */
@@ -1928,45 +2074,46 @@ do_fault:
}
static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
- int is_user, uint32_t *phys_ptr, int *prot,
- target_ulong *page_size)
+ int is_user, target_phys_addr_t *phys_ptr,
+ int *prot, target_ulong *page_size)
{
int code;
uint32_t table;
uint32_t desc;
uint32_t xn;
+ uint32_t pxn = 0;
int type;
int ap;
- int domain;
+ int domain = 0;
int domain_prot;
- uint32_t phys_addr;
+ target_phys_addr_t phys_addr;
/* Pagetable walk. */
/* Lookup l1 descriptor. */
table = get_level1_table_address(env, address);
desc = ldl_phys(table);
type = (desc & 3);
- if (type == 0) {
- /* Section translation fault. */
+ if (type == 0 || (type == 3 && !arm_feature(env, ARM_FEATURE_PXN))) {
+ /* Section translation fault, or attempt to use the encoding
+ * which is Reserved on implementations without PXN.
+ */
code = 5;
- domain = 0;
goto do_fault;
- } else if (type == 2 && (desc & (1 << 18))) {
- /* Supersection. */
- domain = 0;
- } else {
- /* Section or page. */
+ }
+ if ((type == 1) || !(desc & (1 << 18))) {
+ /* Page or Section. */
domain = (desc >> 5) & 0x0f;
}
domain_prot = (env->cp15.c3 >> (domain * 2)) & 3;
if (domain_prot == 0 || domain_prot == 2) {
- if (type == 2)
+ if (type != 1) {
code = 9; /* Section domain fault. */
- else
+ } else {
code = 11; /* Page domain fault. */
+ }
goto do_fault;
}
- if (type == 2) {
+ if (type != 1) {
if (desc & (1 << 18)) {
/* Supersection. */
phys_addr = (desc & 0xff000000) | (address & 0x00ffffff);
@@ -1978,8 +2125,12 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
}
ap = ((desc >> 10) & 3) | ((desc >> 13) & 4);
xn = desc & (1 << 4);
+ pxn = desc & 1;
code = 13;
} else {
+ if (arm_feature(env, ARM_FEATURE_PXN)) {
+ pxn = (desc >> 2) & 1;
+ }
/* Lookup l2 entry. */
table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
desc = ldl_phys(table);
@@ -2007,6 +2158,9 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
if (domain_prot == 3) {
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
} else {
+ if (pxn && !is_user) {
+ xn = 1;
+ }
if (xn && access_type == 2)
goto do_fault;
@@ -2031,8 +2185,187 @@ do_fault:
return code | (domain << 4);
}
-static int get_phys_addr_mpu(CPUARMState *env, uint32_t address, int access_type,
- int is_user, uint32_t *phys_ptr, int *prot)
+/* Fault type for long-descriptor MMU fault reporting; this corresponds
+ * to bits [5..2] in the STATUS field in long-format DFSR/IFSR.
+ */
+typedef enum {
+ translation_fault = 1,
+ access_fault = 2,
+ permission_fault = 3,
+} MMUFaultType;
+
+static int get_phys_addr_lpae(CPUARMState *env, uint32_t address,
+ int access_type, int is_user,
+ target_phys_addr_t *phys_ptr, int *prot,
+ target_ulong *page_size_ptr)
+{
+ /* Read an LPAE long-descriptor translation table. */
+ MMUFaultType fault_type = translation_fault;
+ uint32_t level = 1;
+ uint32_t epd;
+ uint32_t tsz;
+ uint64_t ttbr;
+ int ttbr_select;
+ int n;
+ target_phys_addr_t descaddr;
+ uint32_t tableattrs;
+ target_ulong page_size;
+ uint32_t attrs;
+
+ /* Determine whether this address is in the region controlled by
+ * TTBR0 or TTBR1 (or if it is in neither region and should fault).
+ * This is a Non-secure PL0/1 stage 1 translation, so controlled by
+ * TTBCR/TTBR0/TTBR1 in accordance with ARM ARM DDI0406C table B-32:
+ */
+ uint32_t t0sz = extract32(env->cp15.c2_control, 0, 3);
+ uint32_t t1sz = extract32(env->cp15.c2_control, 16, 3);
+ if (t0sz && !extract32(address, 32 - t0sz, t0sz)) {
+ /* there is a ttbr0 region and we are in it (high bits all zero) */
+ ttbr_select = 0;
+ } else if (t1sz && !extract32(~address, 32 - t1sz, t1sz)) {
+ /* there is a ttbr1 region and we are in it (high bits all one) */
+ ttbr_select = 1;
+ } else if (!t0sz) {
+ /* ttbr0 region is "everything not in the ttbr1 region" */
+ ttbr_select = 0;
+ } else if (!t1sz) {
+ /* ttbr1 region is "everything not in the ttbr0 region" */
+ ttbr_select = 1;
+ } else {
+ /* in the gap between the two regions, this is a Translation fault */
+ fault_type = translation_fault;
+ goto do_fault;
+ }
+
+ /* Note that QEMU ignores shareability and cacheability attributes,
+ * so we don't need to do anything with the SH, ORGN, IRGN fields
+ * in the TTBCR. Similarly, TTBCR:A1 selects whether we get the
+ * ASID from TTBR0 or TTBR1, but QEMU's TLB doesn't currently
+ * implement any ASID-like capability so we can ignore it (instead
+ * we will always flush the TLB any time the ASID is changed).
+ */
+ if (ttbr_select == 0) {
+ ttbr = ((uint64_t)env->cp15.c2_base0_hi << 32) | env->cp15.c2_base0;
+ epd = extract32(env->cp15.c2_control, 7, 1);
+ tsz = t0sz;
+ } else {
+ ttbr = ((uint64_t)env->cp15.c2_base1_hi << 32) | env->cp15.c2_base1;
+ epd = extract32(env->cp15.c2_control, 23, 1);
+ tsz = t1sz;
+ }
+
+ if (epd) {
+ /* Translation table walk disabled => Translation fault on TLB miss */
+ goto do_fault;
+ }
+
+ /* If the region is small enough we will skip straight to a 2nd level
+ * lookup. This affects the number of bits of the address used in
+ * combination with the TTBR to find the first descriptor. ('n' here
+ * matches the usage in the ARM ARM sB3.6.6, where bits [39..n] are
+ * from the TTBR, [n-1..3] from the vaddr, and [2..0] always zero).
+ */
+ if (tsz > 1) {
+ level = 2;
+ n = 14 - tsz;
+ } else {
+ n = 5 - tsz;
+ }
+
+ /* Clear the vaddr bits which aren't part of the within-region address,
+ * so that we don't have to special case things when calculating the
+ * first descriptor address.
+ */
+ address &= (0xffffffffU >> tsz);
+
+ /* Now we can extract the actual base address from the TTBR */
+ descaddr = extract64(ttbr, 0, 40);
+ descaddr &= ~((1ULL << n) - 1);
+
+ tableattrs = 0;
+ for (;;) {
+ uint64_t descriptor;
+
+ descaddr |= ((address >> (9 * (4 - level))) & 0xff8);
+ descriptor = ldq_phys(descaddr);
+ if (!(descriptor & 1) ||
+ (!(descriptor & 2) && (level == 3))) {
+ /* Invalid, or the Reserved level 3 encoding */
+ goto do_fault;
+ }
+ descaddr = descriptor & 0xfffffff000ULL;
+
+ if ((descriptor & 2) && (level < 3)) {
+ /* Table entry. The top five bits are attributes which may
+ * propagate down through lower levels of the table (and
+ * which are all arranged so that 0 means "no effect", so
+ * we can gather them up by ORing in the bits at each level).
+ */
+ tableattrs |= extract64(descriptor, 59, 5);
+ level++;
+ continue;
+ }
+ /* Block entry at level 1 or 2, or page entry at level 3.
+ * These are basically the same thing, although the number
+ * of bits we pull in from the vaddr varies.
+ */
+ page_size = (1 << (39 - (9 * level)));
+ descaddr |= (address & (page_size - 1));
+ /* Extract attributes from the descriptor and merge with table attrs */
+ attrs = extract64(descriptor, 2, 10)
+ | (extract64(descriptor, 52, 12) << 10);
+ attrs |= extract32(tableattrs, 0, 2) << 11; /* XN, PXN */
+ attrs |= extract32(tableattrs, 3, 1) << 5; /* APTable[1] => AP[2] */
+ /* The sense of AP[1] vs APTable[0] is reversed, as APTable[0] == 1
+ * means "force PL1 access only", which means forcing AP[1] to 0.
+ */
+ if (extract32(tableattrs, 2, 1)) {
+ attrs &= ~(1 << 4);
+ }
+ /* Since we're always in the Non-secure state, NSTable is ignored. */
+ break;
+ }
+ /* Here descaddr is the final physical address, and attributes
+ * are all in attrs.
+ */
+ fault_type = access_fault;
+ if ((attrs & (1 << 8)) == 0) {
+ /* Access flag */
+ goto do_fault;
+ }
+ fault_type = permission_fault;
+ if (is_user && !(attrs & (1 << 4))) {
+ /* Unprivileged access not enabled */
+ goto do_fault;
+ }
+ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+ if (attrs & (1 << 12) || (!is_user && (attrs & (1 << 11)))) {
+ /* XN or PXN */
+ if (access_type == 2) {
+ goto do_fault;
+ }
+ *prot &= ~PAGE_EXEC;
+ }
+ if (attrs & (1 << 5)) {
+ /* Write access forbidden */
+ if (access_type == 1) {
+ goto do_fault;
+ }
+ *prot &= ~PAGE_WRITE;
+ }
+
+ *phys_ptr = descaddr;
+ *page_size_ptr = page_size;
+ return 0;
+
+do_fault:
+ /* Long-descriptor format IFSR/DFSR value */
+ return (1 << 9) | (fault_type << 2) | level;
+}
+
+static int get_phys_addr_mpu(CPUARMState *env, uint32_t address,
+ int access_type, int is_user,
+ target_phys_addr_t *phys_ptr, int *prot)
{
int n;
uint32_t mask;
@@ -2091,9 +2424,32 @@ static int get_phys_addr_mpu(CPUARMState *env, uint32_t address, int access_type
return 0;
}
+/* get_phys_addr - get the physical address for this virtual address
+ *
+ * Find the physical address corresponding to the given virtual address,
+ * by doing a translation table walk on MMU based systems or using the
+ * MPU state on MPU based systems.
+ *
+ * Returns 0 if the translation was successful. Otherwise, phys_ptr,
+ * prot and page_size are not filled in, and the return value provides
+ * information on why the translation aborted, in the format of a
+ * DFSR/IFSR fault register, with the following caveats:
+ * * we honour the short vs long DFSR format differences.
+ * * the WnR bit is never set (the caller must do this).
+ * * for MPU based systems we don't bother to return a full FSR format
+ * value.
+ *
+ * @env: CPUARMState
+ * @address: virtual address to get physical address for
+ * @access_type: 0 for read, 1 for write, 2 for execute
+ * @is_user: 0 for privileged access, 1 for user
+ * @phys_ptr: set to the physical address corresponding to the virtual address
+ * @prot: set to the permissions for the page containing phys_ptr
+ * @page_size: set to the size of the page containing phys_ptr
+ */
static inline int get_phys_addr(CPUARMState *env, uint32_t address,
int access_type, int is_user,
- uint32_t *phys_ptr, int *prot,
+ target_phys_addr_t *phys_ptr, int *prot,
target_ulong *page_size)
{
/* Fast Context Switch Extension. */
@@ -2110,6 +2466,9 @@ static inline int get_phys_addr(CPUARMState *env, uint32_t address,
*page_size = TARGET_PAGE_SIZE;
return get_phys_addr_mpu(env, address, access_type, is_user, phys_ptr,
prot);
+ } else if (extended_addresses_enabled(env)) {
+ return get_phys_addr_lpae(env, address, access_type, is_user, phys_ptr,
+ prot, page_size);
} else if (env->cp15.c1_sys & (1 << 23)) {
return get_phys_addr_v6(env, address, access_type, is_user, phys_ptr,
prot, page_size);
@@ -2122,7 +2481,7 @@ static inline int get_phys_addr(CPUARMState *env, uint32_t address,
int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address,
int access_type, int mmu_idx)
{
- uint32_t phys_addr;
+ target_phys_addr_t phys_addr;
target_ulong page_size;
int prot;
int ret, is_user;
@@ -2132,7 +2491,7 @@ int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address,
&page_size);
if (ret == 0) {
/* Map a single [sub]page. */
- phys_addr &= ~(uint32_t)0x3ff;
+ phys_addr &= ~(target_phys_addr_t)0x3ff;
address &= ~(uint32_t)0x3ff;
tlb_set_page (env, address, phys_addr, prot, mmu_idx, page_size);
return 0;
@@ -2154,7 +2513,7 @@ int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address,
target_phys_addr_t cpu_get_phys_page_debug(CPUARMState *env, target_ulong addr)
{
- uint32_t phys_addr;
+ target_phys_addr_t phys_addr;
target_ulong page_size;
int prot;
int ret;
diff --git a/target-arm/machine.c b/target-arm/machine.c
index a2a75fbd19..68dca7ffb2 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -27,7 +27,9 @@ void cpu_save(QEMUFile *f, void *opaque)
qemu_put_be32(f, env->cp15.c1_xscaleauxcr);
qemu_put_be32(f, env->cp15.c1_scr);
qemu_put_be32(f, env->cp15.c2_base0);
+ qemu_put_be32(f, env->cp15.c2_base0_hi);
qemu_put_be32(f, env->cp15.c2_base1);
+ qemu_put_be32(f, env->cp15.c2_base1_hi);
qemu_put_be32(f, env->cp15.c2_control);
qemu_put_be32(f, env->cp15.c2_mask);
qemu_put_be32(f, env->cp15.c2_base_mask);
@@ -42,6 +44,7 @@ void cpu_save(QEMUFile *f, void *opaque)
qemu_put_be32(f, env->cp15.c6_insn);
qemu_put_be32(f, env->cp15.c6_data);
qemu_put_be32(f, env->cp15.c7_par);
+ qemu_put_be32(f, env->cp15.c7_par_hi);
qemu_put_be32(f, env->cp15.c9_insn);
qemu_put_be32(f, env->cp15.c9_data);
qemu_put_be32(f, env->cp15.c9_pmcr);
@@ -60,7 +63,7 @@ void cpu_save(QEMUFile *f, void *opaque)
qemu_put_be32(f, env->cp15.c15_diagnostic);
qemu_put_be32(f, env->cp15.c15_power_diagnostic);
- qemu_put_be32(f, env->features);
+ qemu_put_be64(f, env->features);
if (arm_feature(env, ARM_FEATURE_VFP)) {
for (i = 0; i < 16; i++) {
@@ -144,7 +147,9 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
env->cp15.c1_xscaleauxcr = qemu_get_be32(f);
env->cp15.c1_scr = qemu_get_be32(f);
env->cp15.c2_base0 = qemu_get_be32(f);
+ env->cp15.c2_base0_hi = qemu_get_be32(f);
env->cp15.c2_base1 = qemu_get_be32(f);
+ env->cp15.c2_base1_hi = qemu_get_be32(f);
env->cp15.c2_control = qemu_get_be32(f);
env->cp15.c2_mask = qemu_get_be32(f);
env->cp15.c2_base_mask = qemu_get_be32(f);
@@ -159,6 +164,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
env->cp15.c6_insn = qemu_get_be32(f);
env->cp15.c6_data = qemu_get_be32(f);
env->cp15.c7_par = qemu_get_be32(f);
+ env->cp15.c7_par_hi = qemu_get_be32(f);
env->cp15.c9_insn = qemu_get_be32(f);
env->cp15.c9_data = qemu_get_be32(f);
env->cp15.c9_pmcr = qemu_get_be32(f);
@@ -177,7 +183,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
env->cp15.c15_diagnostic = qemu_get_be32(f);
env->cp15.c15_power_diagnostic = qemu_get_be32(f);
- env->features = qemu_get_be32(f);
+ env->features = qemu_get_be64(f);
if (arm_feature(env, ARM_FEATURE_VFP)) {
for (i = 0; i < 16; i++) {
diff --git a/target-arm/translate.c b/target-arm/translate.c
index a2a0ecddad..29008a4b34 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -6236,7 +6236,7 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
}
gen_set_pc_im(s->pc);
s->is_jmp = DISAS_WFI;
- break;
+ return 0;
default:
break;
}
@@ -6263,7 +6263,9 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
tcg_gen_trunc_i64_i32(tmp, tmp64);
store_reg(s, rt, tmp);
tcg_gen_shri_i64(tmp64, tmp64, 32);
+ tmp = tcg_temp_new_i32();
tcg_gen_trunc_i64_i32(tmp, tmp64);
+ tcg_temp_free_i64(tmp64);
store_reg(s, rt2, tmp);
} else {
TCGv tmp;
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index ec08dd0474..47008c24f2 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -135,6 +135,41 @@ int kvm_arch_get_registers(CPUS390XState *env)
return 0;
}
+/*
+ * Legacy layout for s390:
+ * Older S390 KVM requires the topmost vma of the RAM to be
+ * smaller than an system defined value, which is at least 256GB.
+ * Larger systems have larger values. We put the guest between
+ * the end of data segment (system break) and this value. We
+ * use 32GB as a base to have enough room for the system break
+ * to grow. We also have to use MAP parameters that avoid
+ * read-only mapping of guest pages.
+ */
+static void *legacy_s390_alloc(ram_addr_t size)
+{
+ void *mem;
+
+ mem = mmap((void *) 0x800000000ULL, size,
+ PROT_EXEC|PROT_READ|PROT_WRITE,
+ MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+ if (mem == MAP_FAILED) {
+ fprintf(stderr, "Allocating RAM failed\n");
+ abort();
+ }
+ return mem;
+}
+
+void *kvm_arch_vmalloc(ram_addr_t size)
+{
+ /* Can we use the standard allocation ? */
+ if (kvm_check_extension(kvm_state, KVM_CAP_S390_GMAP) &&
+ kvm_check_extension(kvm_state, KVM_CAP_S390_COW)) {
+ return NULL;
+ } else {
+ return legacy_s390_alloc(size);
+ }
+}
+
int kvm_arch_insert_sw_breakpoint(CPUS390XState *env, struct kvm_sw_breakpoint *bp)
{
static const uint8_t diag_501[] = {0x83, 0x24, 0x05, 0x01};
diff --git a/targphys.h b/targphys.h
index 95648d6882..bd4938fc02 100644
--- a/targphys.h
+++ b/targphys.h
@@ -11,10 +11,26 @@
typedef uint32_t target_phys_addr_t;
#define TARGET_PHYS_ADDR_MAX UINT32_MAX
#define TARGET_FMT_plx "%08x"
+/* Format strings for printing target_phys_addr_t types.
+ * These are recommended over the less flexible TARGET_FMT_plx,
+ * which is retained for the benefit of existing code.
+ */
+#define TARGET_PRIdPHYS PRId32
+#define TARGET_PRIiPHYS PRIi32
+#define TARGET_PRIoPHYS PRIo32
+#define TARGET_PRIuPHYS PRIu32
+#define TARGET_PRIxPHYS PRIx32
+#define TARGET_PRIXPHYS PRIX32
#elif TARGET_PHYS_ADDR_BITS == 64
typedef uint64_t target_phys_addr_t;
#define TARGET_PHYS_ADDR_MAX UINT64_MAX
#define TARGET_FMT_plx "%016" PRIx64
+#define TARGET_PRIdPHYS PRId64
+#define TARGET_PRIiPHYS PRIi64
+#define TARGET_PRIoPHYS PRIo64
+#define TARGET_PRIuPHYS PRIu64
+#define TARGET_PRIxPHYS PRIx64
+#define TARGET_PRIXPHYS PRIX64
#endif
#endif
diff --git a/trace-events b/trace-events
index 1f9fc98c89..fc32bc69cb 100644
--- a/trace-events
+++ b/trace-events
@@ -726,6 +726,9 @@ iscsi_aio_read16_cb(void *iscsi, int status, void *acb, int canceled) "iscsi %p
iscsi_aio_readv(void *iscsi, int64_t sector_num, int nb_sectors, void *opaque, void *acb) "iscsi %p sector_num %"PRId64" nb_sectors %d opaque %p acb %p"
# hw/esp.c
+esp_error_fifo_overrun(void) "FIFO overrun"
+esp_error_unhandled_command(uint32_t val) "unhandled command (%2.2x)"
+esp_error_invalid_write(uint32_t val, uint32_t addr) "invalid write of 0x%02x at [0x%x]"
esp_raise_irq(void) "Raise IRQ"
esp_lower_irq(void) "Lower IRQ"
esp_dma_enable(void) "Raise enable"
@@ -751,10 +754,24 @@ esp_mem_writeb_cmd_iccs(uint32_t val) "Initiator Command Complete Sequence (%2.2
esp_mem_writeb_cmd_msgacc(uint32_t val) "Message Accepted (%2.2x)"
esp_mem_writeb_cmd_pad(uint32_t val) "Transfer padding (%2.2x)"
esp_mem_writeb_cmd_satn(uint32_t val) "Set ATN (%2.2x)"
+esp_mem_writeb_cmd_rstatn(uint32_t val) "Reset ATN (%2.2x)"
esp_mem_writeb_cmd_sel(uint32_t val) "Select without ATN (%2.2x)"
esp_mem_writeb_cmd_selatn(uint32_t val) "Select with ATN (%2.2x)"
esp_mem_writeb_cmd_selatns(uint32_t val) "Select with ATN & stop (%2.2x)"
esp_mem_writeb_cmd_ensel(uint32_t val) "Enable selection (%2.2x)"
+esp_mem_writeb_cmd_dissel(uint32_t val) "Disable selection (%2.2x)"
+esp_pci_error_invalid_dma_direction(void) "invalid DMA transfer direction"
+esp_pci_error_invalid_read(uint32_t reg) "read access outside bounds (reg 0x%x)"
+esp_pci_error_invalid_write(uint32_t reg) "write access outside bounds (reg 0x%x)"
+esp_pci_error_invalid_write_dma(uint32_t val, uint32_t addr) "invalid write of 0x%02x at [0x%x]"
+esp_pci_dma_read(uint32_t saddr, uint32_t reg) "reg[%d]: 0x%8.8x"
+esp_pci_dma_write(uint32_t saddr, uint32_t reg, uint32_t val) "reg[%d]: 0x%8.8x -> 0x%8.8x"
+esp_pci_dma_idle(uint32_t val) "IDLE (%.8x)"
+esp_pci_dma_blast(uint32_t val) "BLAST (%.8x)"
+esp_pci_dma_abort(uint32_t val) "ABORT (%.8x)"
+esp_pci_dma_start(uint32_t val) "START (%.8x)"
+esp_pci_sbac_read(uint32_t reg) "sbac: 0x%8.8x"
+esp_pci_sbac_write(uint32_t reg, uint32_t val) "sbac: 0x%8.8x -> 0x%8.8x"
# monitor.c
handle_qmp_command(void *mon, const char *cmd_name) "mon %p cmd_name \"%s\""