aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--HACKING20
-rwxr-xr-xconfigure17
-rw-r--r--exec-all.h4
-rw-r--r--exec.c2
-rw-r--r--fsdev/virtfs-proxy-helper.c93
-rw-r--r--hw/acpi.c113
-rw-r--r--hw/acpi.h18
-rw-r--r--hw/acpi_ich9.c199
-rw-r--r--hw/acpi_ich9.h3
-rw-r--r--hw/acpi_piix4.c185
-rw-r--r--hw/apm.c23
-rw-r--r--hw/apm.h5
-rw-r--r--hw/cirrus_vga.c48
-rw-r--r--hw/dma.c106
-rw-r--r--hw/ich9.h1
-rw-r--r--hw/isa-bus.c9
-rw-r--r--hw/isa.h1
-rw-r--r--hw/lpc_ich9.c31
-rw-r--r--hw/mips_mipssim.c3
-rw-r--r--hw/pc.c49
-rw-r--r--hw/pc_piix.c24
-rw-r--r--hw/pm_smbus.c17
-rw-r--r--hw/pm_smbus.h3
-rw-r--r--hw/serial.c4
-rw-r--r--hw/serial.h2
-rw-r--r--hw/smbus_ich9.c64
-rw-r--r--hw/usb.h2
-rw-r--r--hw/usb/bus.c3
-rw-r--r--hw/usb/core.c4
-rw-r--r--hw/usb/dev-hid.c85
-rw-r--r--hw/usb/dev-hub.c2
-rw-r--r--hw/usb/dev-network.c7
-rw-r--r--hw/usb/dev-wacom.c4
-rw-r--r--hw/usb/hcd-ehci.c39
-rw-r--r--hw/usb/hcd-ehci.h1
-rw-r--r--hw/usb/host-bsd.c1
-rw-r--r--hw/usb/host-linux.c1
-rw-r--r--hw/usb/redirect.c4
-rw-r--r--hw/vt82c686.c104
-rw-r--r--linux-user/arm/syscall_nr.h4
-rw-r--r--linux-user/i386/syscall_nr.h4
-rw-r--r--linux-user/sparc/syscall_nr.h4
-rw-r--r--linux-user/strace.list6
-rw-r--r--linux-user/syscall.c18
-rw-r--r--linux-user/unicore32/syscall_nr.h4
-rw-r--r--qemu-config.c49
-rw-r--r--target-alpha/translate.c12
-rw-r--r--target-arm/translate.c12
-rw-r--r--target-cris/translate.c14
-rw-r--r--target-i386/translate.c19
-rw-r--r--target-lm32/translate.c12
-rw-r--r--target-m68k/translate.c12
-rw-r--r--target-microblaze/translate.c12
-rw-r--r--target-mips/translate.c12
-rw-r--r--target-openrisc/translate.c12
-rw-r--r--target-ppc/translate.c12
-rw-r--r--target-s390x/translate.c12
-rw-r--r--target-sh4/translate.c12
-rw-r--r--target-sparc/translate.c12
-rw-r--r--target-unicore32/translate.c12
-rw-r--r--target-xtensa/cpu.c3
-rw-r--r--target-xtensa/cpu.h14
-rw-r--r--target-xtensa/helper.c75
-rw-r--r--target-xtensa/helper.h1
-rw-r--r--target-xtensa/op_helper.c57
-rw-r--r--target-xtensa/overlay_tool.h12
-rw-r--r--target-xtensa/translate.c377
-rw-r--r--tcg/tcg.h3
-rw-r--r--tests/tcg/xtensa/Makefile2
-rw-r--r--tests/tcg/xtensa/macros.inc2
-rw-r--r--tests/tcg/xtensa/test_s32c1i.S39
-rw-r--r--tests/tcg/xtensa/test_sr.S90
-rw-r--r--translate-all.c9
-rw-r--r--ui/curses.c4
74 files changed, 1354 insertions, 901 deletions
diff --git a/HACKING b/HACKING
index 89a6b3ad44..6654d33249 100644
--- a/HACKING
+++ b/HACKING
@@ -123,3 +123,23 @@ gcc's printf attribute directive in the prototype.
This makes it so gcc's -Wformat and -Wformat-security options can do
their jobs and cross-check format strings with the number and types
of arguments.
+
+6. C standard, implementation defined and undefined behaviors
+
+C code in QEMU should be written to the C99 language specification. A copy
+of the final version of the C99 standard with corrigenda TC1, TC2, and TC3
+included, formatted as a draft, can be downloaded from:
+ http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf
+
+The C language specification defines regions of undefined behavior and
+implementation defined behavior (to give compiler authors enough leeway to
+produce better code). In general, code in QEMU should follow the language
+specification and avoid both undefined and implementation defined
+constructs. ("It works fine on the gcc I tested it with" is not a valid
+argument...) However there are a few areas where we allow ourselves to
+assume certain behaviors because in practice all the platforms we care about
+behave in the same way and writing strictly conformant code would be
+painful. These are:
+ * you may assume that integers are 2s complement representation
+ * you may assume that right shift of a signed integer duplicates
+ the sign bit (ie it is an arithmetic shift, not a logical shift)
diff --git a/configure b/configure
index 79605d2b75..38b1cc6b35 100755
--- a/configure
+++ b/configure
@@ -116,7 +116,7 @@ audio_drv_list=""
audio_card_list="ac97 es1370 sb16 hda"
audio_possible_cards="ac97 es1370 sb16 cs4231a adlib gus hda"
block_drv_whitelist=""
-host_cc="gcc"
+host_cc="cc"
libs_softmmu=""
libs_tools=""
audio_pt_int=""
@@ -250,7 +250,16 @@ done
# Using uname is really, really broken. Once we have the right set of checks
# we can eliminate its usage altogether.
-cc="${CC-${cross_prefix}gcc}"
+# Preferred compiler:
+# ${CC} (if set)
+# ${cross_prefix}gcc (if cross-prefix specified)
+# system compiler
+if test -z "${CC}${cross_prefix}"; then
+ cc="$host_cc"
+else
+ cc="${CC-${cross_prefix}gcc}"
+fi
+
ar="${AR-${cross_prefix}ar}"
objcopy="${OBJCOPY-${cross_prefix}objcopy}"
ld="${LD-${cross_prefix}ld}"
@@ -2118,7 +2127,7 @@ fi
# pixman support probe
if test "$pixman" = ""; then
- if $pkg_config pixman-1 > /dev/null 2>&1; then
+ if $pkg_config --atleast-version=0.18.4 pixman-1 > /dev/null 2>&1; then
pixman="system"
else
pixman="internal"
@@ -2129,7 +2138,7 @@ if test "$pixman" = "system"; then
pixman_libs=`$pkg_config --libs pixman-1 2>/dev/null`
else
if test ! -d ${source_path}/pixman/pixman; then
- echo "ERROR: pixman not present. Your options:"
+ echo "ERROR: pixman not present (or older than 0.18.4). Your options:"
echo " (1) Preferred: Install the pixman devel package (any recent"
echo " distro should have packages as Xorg needs pixman too)."
echo " (2) Fetch the pixman submodule, using:"
diff --git a/exec-all.h b/exec-all.h
index 21aacdab50..b18d4ca534 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -70,10 +70,6 @@ typedef struct TranslationBlock TranslationBlock;
#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * MAX_OPC_PARAM)
-extern target_ulong gen_opc_pc[OPC_BUF_SIZE];
-extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
-extern uint16_t gen_opc_icount[OPC_BUF_SIZE];
-
#include "qemu-log.h"
void gen_intermediate_code(CPUArchState *env, struct TranslationBlock *tb);
diff --git a/exec.c b/exec.c
index 8435de0bd2..0594b07057 100644
--- a/exec.c
+++ b/exec.c
@@ -607,6 +607,8 @@ static inline void code_gen_alloc(size_t tb_size)
exit(1);
}
+ qemu_madvise(code_gen_buffer, code_gen_buffer_size, QEMU_MADV_HUGEPAGE);
+
/* Steal room for the prologue at the end of the buffer. This ensures
(via the MAX_CODE_GEN_BUFFER_SIZE limits above) that direct branches
from TB's to the prologue are going to be in range. It also means
diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index f9a8270ee9..df2a9392b1 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -272,31 +272,76 @@ static int send_status(int sockfd, struct iovec *iovec, int status)
/*
* from man 7 capabilities, section
* Effect of User ID Changes on Capabilities:
- * 4. If the file system user ID is changed from 0 to nonzero (see setfsuid(2))
- * then the following capabilities are cleared from the effective set:
- * CAP_CHOWN, CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH, CAP_FOWNER, CAP_FSETID,
- * CAP_LINUX_IMMUTABLE (since Linux 2.2.30), CAP_MAC_OVERRIDE, and CAP_MKNOD
- * (since Linux 2.2.30). If the file system UID is changed from nonzero to 0,
- * then any of these capabilities that are enabled in the permitted set
- * are enabled in the effective set.
+ * If the effective user ID is changed from nonzero to 0, then the permitted
+ * set is copied to the effective set. If the effective user ID is changed
+ * from 0 to nonzero, then all capabilities are are cleared from the effective
+ * set.
+ *
+ * The setfsuid/setfsgid man pages warn that changing the effective user ID may
+ * expose the program to unwanted signals, but this is not true anymore: for an
+ * unprivileged (without CAP_KILL) program to send a signal, the real or
+ * effective user ID of the sending process must equal the real or saved user
+ * ID of the target process. Even when dropping privileges, it is enough to
+ * keep the saved UID to a "privileged" value and virtfs-proxy-helper won't
+ * be exposed to signals. So just use setresuid/setresgid.
*/
-static int setfsugid(int uid, int gid)
+static int setugid(int uid, int gid, int *suid, int *sgid)
{
+ int retval;
+
/*
- * We still need DAC_OVERRIDE because we don't change
+ * We still need DAC_OVERRIDE because we don't change
* supplementary group ids, and hence may be subjected DAC rules
*/
cap_value_t cap_list[] = {
CAP_DAC_OVERRIDE,
};
- setfsgid(gid);
- setfsuid(uid);
+ *suid = geteuid();
+ *sgid = getegid();
+
+ if (setresgid(-1, gid, *sgid) == -1) {
+ retval = -errno;
+ goto err_out;
+ }
+
+ if (setresuid(-1, uid, *suid) == -1) {
+ retval = -errno;
+ goto err_sgid;
+ }
if (uid != 0 || gid != 0) {
- return do_cap_set(cap_list, ARRAY_SIZE(cap_list), 0);
+ if (do_cap_set(cap_list, ARRAY_SIZE(cap_list), 0) < 0) {
+ retval = -errno;
+ goto err_suid;
+ }
}
return 0;
+
+err_suid:
+ if (setresuid(-1, *suid, *suid) == -1) {
+ abort();
+ }
+err_sgid:
+ if (setresgid(-1, *sgid, *sgid) == -1) {
+ abort();
+ }
+err_out:
+ return retval;
+}
+
+/*
+ * This is used to reset the ugid back with the saved values
+ * There is nothing much we can do checking error values here.
+ */
+static void resetugid(int suid, int sgid)
+{
+ if (setresgid(-1, sgid, sgid) == -1) {
+ abort();
+ }
+ if (setresuid(-1, suid, suid) == -1) {
+ abort();
+ }
}
/*
@@ -578,18 +623,15 @@ static int do_create_others(int type, struct iovec *iovec)
v9fs_string_init(&path);
v9fs_string_init(&oldpath);
- cur_uid = geteuid();
- cur_gid = getegid();
retval = proxy_unmarshal(iovec, offset, "dd", &uid, &gid);
if (retval < 0) {
return retval;
}
offset += retval;
- retval = setfsugid(uid, gid);
+ retval = setugid(uid, gid, &cur_uid, &cur_gid);
if (retval < 0) {
- retval = -errno;
- goto err_out;
+ goto unmarshal_err_out;
}
switch (type) {
case T_MKNOD:
@@ -619,9 +661,10 @@ static int do_create_others(int type, struct iovec *iovec)
}
err_out:
+ resetugid(cur_uid, cur_gid);
+unmarshal_err_out:
v9fs_string_free(&path);
v9fs_string_free(&oldpath);
- setfsugid(cur_uid, cur_gid);
return retval;
}
@@ -641,24 +684,16 @@ static int do_create(struct iovec *iovec)
if (ret < 0) {
goto unmarshal_err_out;
}
- cur_uid = geteuid();
- cur_gid = getegid();
- ret = setfsugid(uid, gid);
+ ret = setugid(uid, gid, &cur_uid, &cur_gid);
if (ret < 0) {
- /*
- * On failure reset back to the
- * old uid/gid
- */
- ret = -errno;
- goto err_out;
+ goto unmarshal_err_out;
}
ret = open(path.data, flags, mode);
if (ret < 0) {
ret = -errno;
}
-err_out:
- setfsugid(cur_uid, cur_gid);
+ resetugid(cur_uid, cur_gid);
unmarshal_err_out:
v9fs_string_free(&path);
return ret;
diff --git a/hw/acpi.c b/hw/acpi.c
index f4aca493fc..ae29a59077 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -275,7 +275,7 @@ uint16_t acpi_pm1_evt_get_sts(ACPIREGS *ar)
return ar->pm1.evt.sts;
}
-void acpi_pm1_evt_write_sts(ACPIREGS *ar, uint16_t val)
+static void acpi_pm1_evt_write_sts(ACPIREGS *ar, uint16_t val)
{
uint16_t pm1_sts = acpi_pm1_evt_get_sts(ar);
if (pm1_sts & val & ACPI_BITMASK_TIMER_STATUS) {
@@ -285,7 +285,7 @@ void acpi_pm1_evt_write_sts(ACPIREGS *ar, uint16_t val)
ar->pm1.evt.sts &= ~val;
}
-void acpi_pm1_evt_write_en(ACPIREGS *ar, uint16_t val)
+static void acpi_pm1_evt_write_en(ACPIREGS *ar, uint16_t val)
{
ar->pm1.evt.en = val;
qemu_system_wakeup_enable(QEMU_WAKEUP_REASON_RTC,
@@ -310,6 +310,51 @@ void acpi_pm1_evt_reset(ACPIREGS *ar)
qemu_system_wakeup_enable(QEMU_WAKEUP_REASON_PMTIMER, 0);
}
+static uint64_t acpi_pm_evt_read(void *opaque, hwaddr addr, unsigned width)
+{
+ ACPIREGS *ar = opaque;
+ switch (addr) {
+ case 0:
+ return acpi_pm1_evt_get_sts(ar);
+ case 2:
+ return ar->pm1.evt.en;
+ default:
+ return 0;
+ }
+}
+
+static void acpi_pm_evt_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned width)
+{
+ ACPIREGS *ar = opaque;
+ switch (addr) {
+ case 0:
+ acpi_pm1_evt_write_sts(ar, val);
+ ar->pm1.evt.update_sci(ar);
+ break;
+ case 2:
+ acpi_pm1_evt_write_en(ar, val);
+ ar->pm1.evt.update_sci(ar);
+ break;
+ }
+}
+
+static const MemoryRegionOps acpi_pm_evt_ops = {
+ .read = acpi_pm_evt_read,
+ .write = acpi_pm_evt_write,
+ .valid.min_access_size = 2,
+ .valid.max_access_size = 2,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+void acpi_pm1_evt_init(ACPIREGS *ar, acpi_update_sci_fn update_sci,
+ MemoryRegion *parent)
+{
+ ar->pm1.evt.update_sci = update_sci;
+ memory_region_init_io(&ar->pm1.evt.io, &acpi_pm_evt_ops, ar, "acpi-evt", 4);
+ memory_region_add_subregion(parent, 0, &ar->pm1.evt.io);
+}
+
/* ACPI PM_TMR */
void acpi_pm_tmr_update(ACPIREGS *ar, bool enable)
{
@@ -331,7 +376,7 @@ void acpi_pm_tmr_calc_overflow_time(ACPIREGS *ar)
ar->tmr.overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
}
-uint32_t acpi_pm_tmr_get(ACPIREGS *ar)
+static uint32_t acpi_pm_tmr_get(ACPIREGS *ar)
{
uint32_t d = acpi_pm_tmr_get_clock();
return d & 0xffffff;
@@ -344,10 +389,25 @@ static void acpi_pm_tmr_timer(void *opaque)
ar->tmr.update_sci(ar);
}
-void acpi_pm_tmr_init(ACPIREGS *ar, acpi_update_sci_fn update_sci)
+static uint64_t acpi_pm_tmr_read(void *opaque, hwaddr addr, unsigned width)
+{
+ return acpi_pm_tmr_get(opaque);
+}
+
+static const MemoryRegionOps acpi_pm_tmr_ops = {
+ .read = acpi_pm_tmr_read,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 4,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+void acpi_pm_tmr_init(ACPIREGS *ar, acpi_update_sci_fn update_sci,
+ MemoryRegion *parent)
{
ar->tmr.update_sci = update_sci;
ar->tmr.timer = qemu_new_timer_ns(vm_clock, acpi_pm_tmr_timer, ar);
+ memory_region_init_io(&ar->tmr.io, &acpi_pm_tmr_ops, ar, "acpi-tmr", 4);
+ memory_region_add_subregion(parent, 8, &ar->tmr.io);
}
void acpi_pm_tmr_reset(ACPIREGS *ar)
@@ -357,13 +417,7 @@ void acpi_pm_tmr_reset(ACPIREGS *ar)
}
/* ACPI PM1aCNT */
-void acpi_pm1_cnt_init(ACPIREGS *ar)
-{
- ar->wakeup.notify = acpi_notify_wakeup;
- qemu_register_wakeup_notifier(&ar->wakeup);
-}
-
-void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val, char s4)
+static void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val)
{
ar->pm1.cnt.cnt = val & ~(ACPI_BITMASK_SLEEP_ENABLE);
@@ -378,7 +432,7 @@ void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val, char s4)
qemu_system_suspend_request();
break;
default:
- if (sus_typ == s4) { /* S4 request */
+ if (sus_typ == ar->pm1.cnt.s4_val) { /* S4 request */
monitor_protocol_event(QEVENT_SUSPEND_DISK, NULL);
qemu_system_shutdown_request();
}
@@ -398,6 +452,34 @@ void acpi_pm1_cnt_update(ACPIREGS *ar,
}
}
+static uint64_t acpi_pm_cnt_read(void *opaque, hwaddr addr, unsigned width)
+{
+ ACPIREGS *ar = opaque;
+ return ar->pm1.cnt.cnt;
+}
+
+static void acpi_pm_cnt_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned width)
+{
+ acpi_pm1_cnt_write(opaque, val);
+}
+
+static const MemoryRegionOps acpi_pm_cnt_ops = {
+ .read = acpi_pm_cnt_read,
+ .write = acpi_pm_cnt_write,
+ .valid.min_access_size = 2,
+ .valid.max_access_size = 2,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent)
+{
+ ar->wakeup.notify = acpi_notify_wakeup;
+ qemu_register_wakeup_notifier(&ar->wakeup);
+ memory_region_init_io(&ar->pm1.cnt.io, &acpi_pm_cnt_ops, ar, "acpi-cnt", 2);
+ memory_region_add_subregion(parent, 4, &ar->pm1.cnt.io);
+}
+
void acpi_pm1_cnt_reset(ACPIREGS *ar)
{
ar->pm1.cnt.cnt = 0;
@@ -411,11 +493,6 @@ void acpi_gpe_init(ACPIREGS *ar, uint8_t len)
ar->gpe.en = g_malloc0(len / 2);
}
-void acpi_gpe_blk(ACPIREGS *ar, uint32_t blk)
-{
- ar->gpe.blk = blk;
-}
-
void acpi_gpe_reset(ACPIREGS *ar)
{
memset(ar->gpe.sts, 0, ar->gpe.len / 2);
@@ -441,7 +518,6 @@ void acpi_gpe_ioport_writeb(ACPIREGS *ar, uint32_t addr, uint32_t val)
{
uint8_t *cur;
- addr -= ar->gpe.blk;
cur = acpi_gpe_ioport_get_ptr(ar, addr);
if (addr < ar->gpe.len / 2) {
/* GPE_STS */
@@ -459,7 +535,6 @@ uint32_t acpi_gpe_ioport_readb(ACPIREGS *ar, uint32_t addr)
uint8_t *cur;
uint32_t val;
- addr -= ar->gpe.blk;
cur = acpi_gpe_ioport_get_ptr(ar, addr);
val = 0;
if (cur != NULL) {
diff --git a/hw/acpi.h b/hw/acpi.h
index 7337f41857..afda153d09 100644
--- a/hw/acpi.h
+++ b/hw/acpi.h
@@ -84,22 +84,26 @@ typedef void (*acpi_update_sci_fn)(ACPIREGS *ar);
struct ACPIPMTimer {
QEMUTimer *timer;
+ MemoryRegion io;
int64_t overflow_time;
acpi_update_sci_fn update_sci;
};
struct ACPIPM1EVT {
+ MemoryRegion io;
uint16_t sts;
uint16_t en;
+ acpi_update_sci_fn update_sci;
};
struct ACPIPM1CNT {
+ MemoryRegion io;
uint16_t cnt;
+ uint8_t s4_val;
};
struct ACPIGPE {
- uint32_t blk;
uint8_t len;
uint8_t *sts;
@@ -119,8 +123,8 @@ struct ACPIREGS {
/* PM_TMR */
void acpi_pm_tmr_update(ACPIREGS *ar, bool enable);
void acpi_pm_tmr_calc_overflow_time(ACPIREGS *ar);
-uint32_t acpi_pm_tmr_get(ACPIREGS *ar);
-void acpi_pm_tmr_init(ACPIREGS *ar, acpi_update_sci_fn update_sci);
+void acpi_pm_tmr_init(ACPIREGS *ar, acpi_update_sci_fn update_sci,
+ MemoryRegion *parent);
void acpi_pm_tmr_reset(ACPIREGS *ar);
#include "qemu-timer.h"
@@ -132,21 +136,19 @@ static inline int64_t acpi_pm_tmr_get_clock(void)
/* PM1a_EVT: piix and ich9 don't implement PM1b. */
uint16_t acpi_pm1_evt_get_sts(ACPIREGS *ar);
-void acpi_pm1_evt_write_sts(ACPIREGS *ar, uint16_t val);
-void acpi_pm1_evt_write_en(ACPIREGS *ar, uint16_t val);
void acpi_pm1_evt_power_down(ACPIREGS *ar);
void acpi_pm1_evt_reset(ACPIREGS *ar);
+void acpi_pm1_evt_init(ACPIREGS *ar, acpi_update_sci_fn update_sci,
+ MemoryRegion *parent);
/* PM1a_CNT: piix and ich9 don't implement PM1b CNT. */
-void acpi_pm1_cnt_init(ACPIREGS *ar);
-void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val, char s4);
+void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent);
void acpi_pm1_cnt_update(ACPIREGS *ar,
bool sci_enable, bool sci_disable);
void acpi_pm1_cnt_reset(ACPIREGS *ar);
/* GPE0 */
void acpi_gpe_init(ACPIREGS *ar, uint8_t len);
-void acpi_gpe_blk(ACPIREGS *ar, uint32_t blk);
void acpi_gpe_reset(ACPIREGS *ar);
void acpi_gpe_ioport_writeb(ACPIREGS *ar, uint32_t addr, uint32_t val);
diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c
index 61034d3bd7..c5978d33cc 100644
--- a/hw/acpi_ich9.c
+++ b/hw/acpi_ich9.c
@@ -29,6 +29,7 @@
#include "sysemu.h"
#include "acpi.h"
#include "kvm.h"
+#include "exec-memory.h"
#include "ich9.h"
@@ -41,10 +42,6 @@ do { printf("%s "fmt, __func__, ## __VA_ARGS__); } while (0)
#define ICH9_DEBUG(fmt, ...) do { } while (0)
#endif
-static void pm_ioport_write_fallback(void *opaque, uint32_t addr, int len,
- uint32_t val);
-static uint32_t pm_ioport_read_fallback(void *opaque, uint32_t addr, int len);
-
static void pm_update_sci(ICH9LPCPMRegs *pm)
{
int sci_level, pm1a_sts;
@@ -70,152 +67,60 @@ static void ich9_pm_update_sci_fn(ACPIREGS *regs)
pm_update_sci(pm);
}
-static void pm_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+static uint64_t ich9_gpe_readb(void *opaque, hwaddr addr, unsigned width)
{
ICH9LPCPMRegs *pm = opaque;
-
- switch (addr & ICH9_PMIO_MASK) {
- case ICH9_PMIO_GPE0_STS ... (ICH9_PMIO_GPE0_STS + ICH9_PMIO_GPE0_LEN - 1):
- acpi_gpe_ioport_writeb(&pm->acpi_regs, addr, val);
- break;
- default:
- break;
- }
-
- ICH9_DEBUG("port=0x%04x val=0x%04x\n", addr, val);
+ return acpi_gpe_ioport_readb(&pm->acpi_regs, addr);
}
-static uint32_t pm_ioport_readb(void *opaque, uint32_t addr)
+static void ich9_gpe_writeb(void *opaque, hwaddr addr, uint64_t val,
+ unsigned width)
{
ICH9LPCPMRegs *pm = opaque;
- uint32_t val = 0;
-
- switch (addr & ICH9_PMIO_MASK) {
- case ICH9_PMIO_GPE0_STS ... (ICH9_PMIO_GPE0_STS + ICH9_PMIO_GPE0_LEN - 1):
- val = acpi_gpe_ioport_readb(&pm->acpi_regs, addr);
- break;
- default:
- val = 0;
- break;
- }
- ICH9_DEBUG("port=0x%04x val=0x%04x\n", addr, val);
- return val;
+ acpi_gpe_ioport_writeb(&pm->acpi_regs, addr, val);
}
-static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
-{
- ICH9LPCPMRegs *pm = opaque;
-
- switch (addr & ICH9_PMIO_MASK) {
- case ICH9_PMIO_PM1_STS:
- acpi_pm1_evt_write_sts(&pm->acpi_regs, val);
- pm_update_sci(pm);
- break;
- case ICH9_PMIO_PM1_EN:
- pm->acpi_regs.pm1.evt.en = val;
- pm_update_sci(pm);
- break;
- case ICH9_PMIO_PM1_CNT:
- acpi_pm1_cnt_write(&pm->acpi_regs, val, 0);
- break;
- default:
- pm_ioport_write_fallback(opaque, addr, 2, val);
- break;
- }
- ICH9_DEBUG("port=0x%04x val=0x%04x\n", addr, val);
-}
+static const MemoryRegionOps ich9_gpe_ops = {
+ .read = ich9_gpe_readb,
+ .write = ich9_gpe_writeb,
+ .valid.min_access_size = 1,
+ .valid.max_access_size = 4,
+ .impl.min_access_size = 1,
+ .impl.max_access_size = 1,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
-static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
+static uint64_t ich9_smi_readl(void *opaque, hwaddr addr, unsigned width)
{
ICH9LPCPMRegs *pm = opaque;
- uint32_t val;
-
- switch (addr & ICH9_PMIO_MASK) {
- case ICH9_PMIO_PM1_STS:
- val = acpi_pm1_evt_get_sts(&pm->acpi_regs);
- break;
- case ICH9_PMIO_PM1_EN:
- val = pm->acpi_regs.pm1.evt.en;
- break;
- case ICH9_PMIO_PM1_CNT:
- val = pm->acpi_regs.pm1.cnt.cnt;
- break;
+ switch (addr) {
+ case 0:
+ return pm->smi_en;
+ case 4:
+ return pm->smi_sts;
default:
- val = pm_ioport_read_fallback(opaque, addr, 2);
- break;
+ return 0;
}
- ICH9_DEBUG("port=0x%04x val=0x%04x\n", addr, val);
- return val;
}
-static void pm_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
+static void ich9_smi_writel(void *opaque, hwaddr addr, uint64_t val,
+ unsigned width)
{
ICH9LPCPMRegs *pm = opaque;
-
- switch (addr & ICH9_PMIO_MASK) {
- case ICH9_PMIO_SMI_EN:
+ switch (addr) {
+ case 0:
pm->smi_en = val;
break;
- default:
- pm_ioport_write_fallback(opaque, addr, 4, val);
- break;
}
- ICH9_DEBUG("port=0x%04x val=0x%08x\n", addr, val);
}
-static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
-{
- ICH9LPCPMRegs *pm = opaque;
- uint32_t val;
-
- switch (addr & ICH9_PMIO_MASK) {
- case ICH9_PMIO_PM1_TMR:
- val = acpi_pm_tmr_get(&pm->acpi_regs);
- break;
- case ICH9_PMIO_SMI_EN:
- val = pm->smi_en;
- break;
-
- default:
- val = pm_ioport_read_fallback(opaque, addr, 4);
- break;
- }
- ICH9_DEBUG("port=0x%04x val=0x%08x\n", addr, val);
- return val;
-}
-
-static void pm_ioport_write_fallback(void *opaque, uint32_t addr, int len,
- uint32_t val)
- {
- int subsize = (len == 4) ? 2 : 1;
- IOPortWriteFunc *ioport_write =
- (subsize == 2) ? pm_ioport_writew : pm_ioport_writeb;
-
- int i;
-
- for (i = 0; i < len; i += subsize) {
- ioport_write(opaque, addr, val);
- val >>= 8 * subsize;
- }
-}
-
-static uint32_t pm_ioport_read_fallback(void *opaque, uint32_t addr, int len)
-{
- int subsize = (len == 4) ? 2 : 1;
- IOPortReadFunc *ioport_read =
- (subsize == 2) ? pm_ioport_readw : pm_ioport_readb;
-
- uint32_t val;
- int i;
-
- val = 0;
- for (i = 0; i < len; i += subsize) {
- val <<= 8 * subsize;
- val |= ioport_read(opaque, addr);
- }
-
- return val;
-}
+static const MemoryRegionOps ich9_smi_ops = {
+ .read = ich9_smi_readl,
+ .write = ich9_smi_writel,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 4,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
void ich9_pm_iospace_update(ICH9LPCPMRegs *pm, uint32_t pm_io_base)
{
@@ -223,24 +128,11 @@ void ich9_pm_iospace_update(ICH9LPCPMRegs *pm, uint32_t pm_io_base)
assert((pm_io_base & ICH9_PMIO_MASK) == 0);
- if (pm->pm_io_base != 0) {
- isa_unassign_ioport(pm->pm_io_base, ICH9_PMIO_SIZE);
- }
-
- /* don't map at 0 */
- if (pm_io_base == 0) {
- return;
- }
-
- register_ioport_write(pm_io_base, ICH9_PMIO_SIZE, 1, pm_ioport_writeb, pm);
- register_ioport_read(pm_io_base, ICH9_PMIO_SIZE, 1, pm_ioport_readb, pm);
- register_ioport_write(pm_io_base, ICH9_PMIO_SIZE, 2, pm_ioport_writew, pm);
- register_ioport_read(pm_io_base, ICH9_PMIO_SIZE, 2, pm_ioport_readw, pm);
- register_ioport_write(pm_io_base, ICH9_PMIO_SIZE, 4, pm_ioport_writel, pm);
- register_ioport_read(pm_io_base, ICH9_PMIO_SIZE, 4, pm_ioport_readl, pm);
-
pm->pm_io_base = pm_io_base;
- acpi_gpe_blk(&pm->acpi_regs, pm_io_base + ICH9_PMIO_GPE0_STS);
+ memory_region_transaction_begin();
+ memory_region_set_enabled(&pm->io, pm->pm_io_base != 0);
+ memory_region_set_address(&pm->io, pm->pm_io_base);
+ memory_region_transaction_commit();
}
static int ich9_pm_post_load(void *opaque, int version_id)
@@ -311,9 +203,22 @@ static void pm_powerdown_req(Notifier *n, void *opaque)
void ich9_pm_init(ICH9LPCPMRegs *pm, qemu_irq sci_irq, qemu_irq cmos_s3)
{
- acpi_pm_tmr_init(&pm->acpi_regs, ich9_pm_update_sci_fn);
- acpi_pm1_cnt_init(&pm->acpi_regs);
+ memory_region_init(&pm->io, "ich9-pm", ICH9_PMIO_SIZE);
+ memory_region_set_enabled(&pm->io, false);
+ memory_region_add_subregion(get_system_io(), 0, &pm->io);
+
+ acpi_pm_tmr_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io);
+ acpi_pm1_evt_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io);
+ acpi_pm1_cnt_init(&pm->acpi_regs, &pm->io);
+
acpi_gpe_init(&pm->acpi_regs, ICH9_PMIO_GPE0_LEN);
+ memory_region_init_io(&pm->io_gpe, &ich9_gpe_ops, pm, "apci-gpe0",
+ ICH9_PMIO_GPE0_LEN);
+ memory_region_add_subregion(&pm->io, ICH9_PMIO_GPE0_STS, &pm->io_gpe);
+
+ memory_region_init_io(&pm->io_smi, &ich9_smi_ops, pm, "apci-smi",
+ 8);
+ memory_region_add_subregion(&pm->io, ICH9_PMIO_SMI_EN, &pm->io_smi);
pm->irq = sci_irq;
qemu_register_reset(pm_reset, pm);
diff --git a/hw/acpi_ich9.h b/hw/acpi_ich9.h
index 180c40673b..bc221d3cbc 100644
--- a/hw/acpi_ich9.h
+++ b/hw/acpi_ich9.h
@@ -30,6 +30,9 @@ typedef struct ICH9LPCPMRegs {
* PM1a_CNT_BLK = 2 in FADT so it is defined as uint16_t.
*/
ACPIREGS acpi_regs;
+ MemoryRegion io;
+ MemoryRegion io_gpe;
+ MemoryRegion io_smi;
uint32_t smi_en;
uint32_t smi_sts;
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 519269a013..0b5b0d3d3e 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -28,6 +28,7 @@
#include "range.h"
#include "ioport.h"
#include "fw_cfg.h"
+#include "exec-memory.h"
//#define DEBUG
@@ -37,10 +38,11 @@
# define PIIX4_DPRINTF(format, ...) do { } while (0)
#endif
-#define ACPI_DBG_IO_ADDR 0xb044
-
#define GPE_BASE 0xafe0
#define GPE_LEN 4
+
+#define PCI_HOTPLUG_ADDR 0xae00
+#define PCI_HOTPLUG_SIZE 0x000f
#define PCI_UP_BASE 0xae00
#define PCI_DOWN_BASE 0xae04
#define PCI_EJ_BASE 0xae08
@@ -55,7 +57,9 @@ struct pci_status {
typedef struct PIIX4PMState {
PCIDevice dev;
- IORange ioport;
+ MemoryRegion io;
+ MemoryRegion io_gpe;
+ MemoryRegion io_pci;
ACPIREGS ar;
APMState apm;
@@ -109,67 +113,6 @@ static void pm_tmr_timer(ACPIREGS *ar)
pm_update_sci(s);
}
-static void pm_ioport_write(IORange *ioport, uint64_t addr, unsigned width,
- uint64_t val)
-{
- PIIX4PMState *s = container_of(ioport, PIIX4PMState, ioport);
-
- if (width != 2) {
- PIIX4_DPRINTF("PM write port=0x%04x width=%d val=0x%08x\n",
- (unsigned)addr, width, (unsigned)val);
- }
-
- switch(addr) {
- case 0x00:
- acpi_pm1_evt_write_sts(&s->ar, val);
- pm_update_sci(s);
- break;
- case 0x02:
- acpi_pm1_evt_write_en(&s->ar, val);
- pm_update_sci(s);
- break;
- case 0x04:
- acpi_pm1_cnt_write(&s->ar, val, s->s4_val);
- break;
- default:
- break;
- }
- PIIX4_DPRINTF("PM writew port=0x%04x val=0x%04x\n", (unsigned int)addr,
- (unsigned int)val);
-}
-
-static void pm_ioport_read(IORange *ioport, uint64_t addr, unsigned width,
- uint64_t *data)
-{
- PIIX4PMState *s = container_of(ioport, PIIX4PMState, ioport);
- uint32_t val;
-
- switch(addr) {
- case 0x00:
- val = acpi_pm1_evt_get_sts(&s->ar);
- break;
- case 0x02:
- val = s->ar.pm1.evt.en;
- break;
- case 0x04:
- val = s->ar.pm1.cnt.cnt;
- break;
- case 0x08:
- val = acpi_pm_tmr_get(&s->ar);
- break;
- default:
- val = 0;
- break;
- }
- PIIX4_DPRINTF("PM readw port=0x%04x val=0x%04x\n", (unsigned int)addr, val);
- *data = val;
-}
-
-static const IORangeOps pm_iorange_ops = {
- .read = pm_ioport_read,
- .write = pm_ioport_write,
-};
-
static void apm_ctrl_changed(uint32_t val, void *arg)
{
PIIX4PMState *s = arg;
@@ -184,32 +127,42 @@ static void apm_ctrl_changed(uint32_t val, void *arg)
}
}
-static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val)
-{
- PIIX4_DPRINTF("ACPI: DBG: 0x%08x\n", val);
-}
-
static void pm_io_space_update(PIIX4PMState *s)
{
uint32_t pm_io_base;
- if (s->dev.config[0x80] & 1) {
- pm_io_base = le32_to_cpu(*(uint32_t *)(s->dev.config + 0x40));
- pm_io_base &= 0xffc0;
+ pm_io_base = le32_to_cpu(*(uint32_t *)(s->dev.config + 0x40));
+ pm_io_base &= 0xffc0;
- /* XXX: need to improve memory and ioport allocation */
- PIIX4_DPRINTF("PM: mapping to 0x%x\n", pm_io_base);
- iorange_init(&s->ioport, &pm_iorange_ops, pm_io_base, 64);
- ioport_register(&s->ioport);
- }
+ memory_region_transaction_begin();
+ memory_region_set_enabled(&s->io, s->dev.config[0x80] & 1);
+ memory_region_set_address(&s->io, pm_io_base);
+ memory_region_transaction_commit();
+}
+
+static void smbus_io_space_update(PIIX4PMState *s)
+{
+ s->smb_io_base = le32_to_cpu(*(uint32_t *)(s->dev.config + 0x90));
+ s->smb_io_base &= 0xffc0;
+
+ memory_region_transaction_begin();
+ memory_region_set_enabled(&s->smb.io, s->dev.config[0xd2] & 1);
+ memory_region_set_address(&s->smb.io, s->smb_io_base);
+ memory_region_transaction_commit();
}
static void pm_write_config(PCIDevice *d,
uint32_t address, uint32_t val, int len)
{
pci_default_write_config(d, address, val, len);
- if (range_covers_byte(address, len, 0x80))
+ if (range_covers_byte(address, len, 0x80) ||
+ ranges_overlap(address, len, 0x40, 4)) {
pm_io_space_update((PIIX4PMState *)d);
+ }
+ if (range_covers_byte(address, len, 0xd2) ||
+ ranges_overlap(address, len, 0x90, 4)) {
+ smbus_io_space_update((PIIX4PMState *)d);
+ }
}
static void vmstate_pci_status_pre_save(void *opaque)
@@ -438,9 +391,7 @@ static int piix4_pm_initfn(PCIDevice *dev)
pci_conf[0x3d] = 0x01; // interrupt pin 1
/* APM */
- apm_init(&s->apm, apm_ctrl_changed, s);
-
- register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, acpi_dbg_writel, s);
+ apm_init(dev, &s->apm, apm_ctrl_changed, s);
if (s->kvm_enabled) {
/* Mark SMM as already inited to prevent SMM from running. KVM does not
@@ -453,16 +404,22 @@ static int piix4_pm_initfn(PCIDevice *dev)
pci_conf[0x90] = s->smb_io_base | 1;
pci_conf[0x91] = s->smb_io_base >> 8;
pci_conf[0xd2] = 0x09;
- register_ioport_write(s->smb_io_base, 64, 1, smb_ioport_writeb, &s->smb);
- register_ioport_read(s->smb_io_base, 64, 1, smb_ioport_readb, &s->smb);
+ pm_smbus_init(&s->dev.qdev, &s->smb);
+ memory_region_set_enabled(&s->smb.io, pci_conf[0xd2] & 1);
+ memory_region_add_subregion(get_system_io(), s->smb_io_base, &s->smb.io);
+
+ memory_region_init(&s->io, "piix4-pm", 64);
+ memory_region_set_enabled(&s->io, false);
+ memory_region_add_subregion(get_system_io(), 0, &s->io);
- acpi_pm_tmr_init(&s->ar, pm_tmr_timer);
+ acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io);
+ acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io);
+ acpi_pm1_cnt_init(&s->ar, &s->io);
acpi_gpe_init(&s->ar, GPE_LEN);
s->powerdown_notifier.notify = piix4_pm_powerdown_req;
qemu_register_powerdown_notifier(&s->powerdown_notifier);
- pm_smbus_init(&s->dev.qdev, &s->smb);
s->machine_ready.notify = piix4_pm_machine_ready;
qemu_add_machine_init_done_notifier(&s->machine_ready);
qemu_register_reset(piix4_reset, s);
@@ -483,7 +440,6 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
s = DO_UPCAST(PIIX4PMState, dev, dev);
s->irq = sci_irq;
- acpi_pm1_cnt_init(&s->ar);
s->smi_irq = smi_irq;
s->kvm_enabled = kvm_enabled;
@@ -540,7 +496,7 @@ static void piix4_pm_register_types(void)
type_init(piix4_pm_register_types)
-static uint32_t gpe_readb(void *opaque, uint32_t addr)
+static uint64_t gpe_readb(void *opaque, hwaddr addr, unsigned width)
{
PIIX4PMState *s = opaque;
uint32_t val = acpi_gpe_ioport_readb(&s->ar, addr);
@@ -549,7 +505,8 @@ static uint32_t gpe_readb(void *opaque, uint32_t addr)
return val;
}
-static void gpe_writeb(void *opaque, uint32_t addr, uint32_t val)
+static void gpe_writeb(void *opaque, hwaddr addr, uint64_t val,
+ unsigned width)
{
PIIX4PMState *s = opaque;
@@ -559,6 +516,16 @@ static void gpe_writeb(void *opaque, uint32_t addr, uint32_t val)
PIIX4_DPRINTF("gpe write %x <== %d\n", addr, val);
}
+static const MemoryRegionOps piix4_gpe_ops = {
+ .read = gpe_readb,
+ .write = gpe_writeb,
+ .valid.min_access_size = 1,
+ .valid.max_access_size = 4,
+ .impl.min_access_size = 1,
+ .impl.max_access_size = 1,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
static uint32_t pci_up_read(void *opaque, uint32_t addr)
{
PIIX4PMState *s = opaque;
@@ -602,24 +569,40 @@ static uint32_t pcirmv_read(void *opaque, uint32_t addr)
return s->pci0_hotplug_enable;
}
+static const MemoryRegionOps piix4_pci_ops = {
+ .old_portio = (MemoryRegionPortio[]) {
+ {
+ .offset = PCI_UP_BASE - PCI_HOTPLUG_ADDR, .len = 4, .size = 4,
+ .read = pci_up_read,
+ },{
+ .offset = PCI_DOWN_BASE - PCI_HOTPLUG_ADDR, .len = 4, .size = 4,
+ .read = pci_down_read,
+ },{
+ .offset = PCI_EJ_BASE - PCI_HOTPLUG_ADDR, .len = 4, .size = 4,
+ .read = pci_features_read,
+ .write = pciej_write,
+ },{
+ .offset = PCI_RMV_BASE - PCI_HOTPLUG_ADDR, .len = 4, .size = 4,
+ .read = pcirmv_read,
+ },
+ PORTIO_END_OF_LIST()
+ },
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
PCIHotplugState state);
static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
{
-
- register_ioport_write(GPE_BASE, GPE_LEN, 1, gpe_writeb, s);
- register_ioport_read(GPE_BASE, GPE_LEN, 1, gpe_readb, s);
- acpi_gpe_blk(&s->ar, GPE_BASE);
-
- register_ioport_read(PCI_UP_BASE, 4, 4, pci_up_read, s);
- register_ioport_read(PCI_DOWN_BASE, 4, 4, pci_down_read, s);
-
- register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, s);
- register_ioport_read(PCI_EJ_BASE, 4, 4, pci_features_read, s);
-
- register_ioport_read(PCI_RMV_BASE, 4, 4, pcirmv_read, s);
-
+ memory_region_init_io(&s->io_gpe, &piix4_gpe_ops, s, "apci-gpe0",
+ GPE_LEN);
+ memory_region_add_subregion(get_system_io(), GPE_BASE, &s->io_gpe);
+
+ memory_region_init_io(&s->io_pci, &piix4_pci_ops, s, "apci-pci-hotplug",
+ PCI_HOTPLUG_SIZE);
+ memory_region_add_subregion(get_system_io(), PCI_HOTPLUG_ADDR,
+ &s->io_pci);
pci_bus_hotplug(bus, piix4_device_hotplug, &s->dev.qdev);
}
diff --git a/hw/apm.c b/hw/apm.c
index 2aead52a74..e988ad9939 100644
--- a/hw/apm.c
+++ b/hw/apm.c
@@ -22,6 +22,7 @@
#include "apm.h"
#include "hw.h"
+#include "pci.h"
//#define DEBUG
@@ -35,7 +36,8 @@
#define APM_CNT_IOPORT 0xb2
#define APM_STS_IOPORT 0xb3
-static void apm_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+static void apm_ioport_writeb(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
{
APMState *apm = opaque;
addr &= 1;
@@ -51,7 +53,7 @@ static void apm_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
}
}
-static uint32_t apm_ioport_readb(void *opaque, uint32_t addr)
+static uint64_t apm_ioport_readb(void *opaque, hwaddr addr, unsigned size)
{
APMState *apm = opaque;
uint32_t val;
@@ -78,12 +80,23 @@ const VMStateDescription vmstate_apm = {
}
};
-void apm_init(APMState *apm, apm_ctrl_changed_t callback, void *arg)
+static const MemoryRegionOps apm_ops = {
+ .read = apm_ioport_readb,
+ .write = apm_ioport_writeb,
+ .impl = {
+ .min_access_size = 1,
+ .max_access_size = 1,
+ },
+};
+
+void apm_init(PCIDevice *dev, APMState *apm, apm_ctrl_changed_t callback,
+ void *arg)
{
apm->callback = callback;
apm->arg = arg;
/* ioport 0xb2, 0xb3 */
- register_ioport_write(APM_CNT_IOPORT, 2, 1, apm_ioport_writeb, apm);
- register_ioport_read(APM_CNT_IOPORT, 2, 1, apm_ioport_readb, apm);
+ memory_region_init_io(&apm->io, &apm_ops, apm, "apm-io", 2);
+ memory_region_add_subregion(pci_address_space_io(dev), APM_CNT_IOPORT,
+ &apm->io);
}
diff --git a/hw/apm.h b/hw/apm.h
index f7c741e327..5431b6d7c8 100644
--- a/hw/apm.h
+++ b/hw/apm.h
@@ -4,6 +4,7 @@
#include <stdint.h>
#include "qemu-common.h"
#include "hw.h"
+#include "memory.h"
typedef void (*apm_ctrl_changed_t)(uint32_t val, void *arg);
@@ -13,9 +14,11 @@ typedef struct APMState {
apm_ctrl_changed_t callback;
void *arg;
+ MemoryRegion io;
} APMState;
-void apm_init(APMState *s, apm_ctrl_changed_t callback, void *arg);
+void apm_init(PCIDevice *dev, APMState *s, apm_ctrl_changed_t callback,
+ void *arg);
extern const VMStateDescription vmstate_apm;
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 9bef96e6d7..40efa8a523 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -197,6 +197,7 @@ typedef void (*cirrus_fill_t)(struct CirrusVGAState *s,
typedef struct CirrusVGAState {
VGACommonState vga;
+ MemoryRegion cirrus_vga_io;
MemoryRegion cirrus_linear_io;
MemoryRegion cirrus_linear_bitblt_io;
MemoryRegion cirrus_mmio_io;
@@ -2432,13 +2433,15 @@ static void cirrus_update_memory_access(CirrusVGAState *s)
/* I/O ports */
-static uint32_t cirrus_vga_ioport_read(void *opaque, uint32_t addr)
+static uint64_t cirrus_vga_ioport_read(void *opaque, hwaddr addr,
+ unsigned size)
{
CirrusVGAState *c = opaque;
VGACommonState *s = &c->vga;
int val, index;
qemu_flush_coalesced_mmio_buffer();
+ addr += 0x3b0;
if (vga_ioport_invalid(s, addr)) {
val = 0xff;
@@ -2527,13 +2530,15 @@ static uint32_t cirrus_vga_ioport_read(void *opaque, uint32_t addr)
return val;
}
-static void cirrus_vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+static void cirrus_vga_ioport_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
{
CirrusVGAState *c = opaque;
VGACommonState *s = &c->vga;
int index;
qemu_flush_coalesced_mmio_buffer();
+ addr += 0x3b0;
/* check port range access depending on color/monochrome mode */
if (vga_ioport_invalid(s, addr)) {
@@ -2646,7 +2651,7 @@ static uint64_t cirrus_mmio_read(void *opaque, hwaddr addr,
if (addr >= 0x100) {
return cirrus_mmio_blt_read(s, addr - 0x100);
} else {
- return cirrus_vga_ioport_read(s, addr + 0x3c0);
+ return cirrus_vga_ioport_read(s, addr + 0x10, size);
}
}
@@ -2658,7 +2663,7 @@ static void cirrus_mmio_write(void *opaque, hwaddr addr,
if (addr >= 0x100) {
cirrus_mmio_blt_write(s, addr - 0x100, val);
} else {
- cirrus_vga_ioport_write(s, addr + 0x3c0, val);
+ cirrus_vga_ioport_write(s, addr + 0x10, val, size);
}
}
@@ -2784,8 +2789,19 @@ static const MemoryRegionOps cirrus_linear_io_ops = {
},
};
+static const MemoryRegionOps cirrus_vga_io_ops = {
+ .read = cirrus_vga_ioport_read,
+ .write = cirrus_vga_ioport_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .impl = {
+ .min_access_size = 1,
+ .max_access_size = 1,
+ },
+};
+
static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci,
- MemoryRegion *system_memory)
+ MemoryRegion *system_memory,
+ MemoryRegion *system_io)
{
int i;
static int inited;
@@ -2817,19 +2833,10 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci,
s->bustype = CIRRUS_BUSTYPE_ISA;
}
- register_ioport_write(0x3c0, 16, 1, cirrus_vga_ioport_write, s);
-
- register_ioport_write(0x3b4, 2, 1, cirrus_vga_ioport_write, s);
- register_ioport_write(0x3d4, 2, 1, cirrus_vga_ioport_write, s);
- register_ioport_write(0x3ba, 1, 1, cirrus_vga_ioport_write, s);
- register_ioport_write(0x3da, 1, 1, cirrus_vga_ioport_write, s);
-
- register_ioport_read(0x3c0, 16, 1, cirrus_vga_ioport_read, s);
-
- register_ioport_read(0x3b4, 2, 1, cirrus_vga_ioport_read, s);
- register_ioport_read(0x3d4, 2, 1, cirrus_vga_ioport_read, s);
- register_ioport_read(0x3ba, 1, 1, cirrus_vga_ioport_read, s);
- register_ioport_read(0x3da, 1, 1, cirrus_vga_ioport_read, s);
+ /* Register ioport 0x3b0 - 0x3df */
+ memory_region_init_io(&s->cirrus_vga_io, &cirrus_vga_io_ops, s,
+ "cirrus-io", 0x30);
+ memory_region_add_subregion(system_io, 0x3b0, &s->cirrus_vga_io);
memory_region_init(&s->low_mem_container,
"cirrus-lowmem-container",
@@ -2900,7 +2907,7 @@ static int vga_initfn(ISADevice *dev)
vga_common_init(s);
cirrus_init_common(&d->cirrus_vga, CIRRUS_ID_CLGD5430, 0,
- isa_address_space(dev));
+ isa_address_space(dev), isa_address_space_io(dev));
s->ds = graphic_console_init(s->update, s->invalidate,
s->screen_dump, s->text_update,
s);
@@ -2948,7 +2955,8 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
/* setup VGA */
vga_common_init(&s->vga);
- cirrus_init_common(s, device_id, 1, pci_address_space(dev));
+ cirrus_init_common(s, device_id, 1, pci_address_space(dev),
+ pci_address_space_io(dev));
s->vga.ds = graphic_console_init(s->vga.update, s->vga.invalidate,
s->vga.screen_dump, s->vga.text_update,
&s->vga);
diff --git a/hw/dma.c b/hw/dma.c
index d6aeac2834..c2d7b21562 100644
--- a/hw/dma.c
+++ b/hw/dma.c
@@ -58,6 +58,8 @@ static struct dma_cont {
int dshift;
struct dma_regs regs[4];
qemu_irq *cpu_request_exit;
+ MemoryRegion channel_io;
+ MemoryRegion cont_io;
} dma_controllers[2];
enum {
@@ -149,7 +151,7 @@ static inline int getff (struct dma_cont *d)
return ff;
}
-static uint32_t read_chan (void *opaque, uint32_t nport)
+static uint64_t read_chan(void *opaque, hwaddr nport, unsigned size)
{
struct dma_cont *d = opaque;
int ichan, nreg, iport, ff, val, dir;
@@ -171,7 +173,8 @@ static uint32_t read_chan (void *opaque, uint32_t nport)
return (val >> (d->dshift + (ff << 3))) & 0xff;
}
-static void write_chan (void *opaque, uint32_t nport, uint32_t data)
+static void write_chan(void *opaque, hwaddr nport, uint64_t data,
+ unsigned size)
{
struct dma_cont *d = opaque;
int iport, ichan, nreg;
@@ -189,22 +192,23 @@ static void write_chan (void *opaque, uint32_t nport, uint32_t data)
}
}
-static void write_cont (void *opaque, uint32_t nport, uint32_t data)
+static void write_cont(void *opaque, hwaddr nport, uint64_t data,
+ unsigned size)
{
struct dma_cont *d = opaque;
int iport, ichan = 0;
iport = (nport >> d->dshift) & 0x0f;
switch (iport) {
- case 0x08: /* command */
+ case 0x01: /* command */
if ((data != 0) && (data & CMD_NOT_SUPPORTED)) {
- dolog ("command %#x not supported\n", data);
+ dolog("command %"PRIx64" not supported\n", data);
return;
}
d->command = data;
break;
- case 0x09:
+ case 0x02:
ichan = data & 3;
if (data & 4) {
d->status |= 1 << (ichan + 4);
@@ -216,7 +220,7 @@ static void write_cont (void *opaque, uint32_t nport, uint32_t data)
DMA_run();
break;
- case 0x0a: /* single mask */
+ case 0x03: /* single mask */
if (data & 4)
d->mask |= 1 << (data & 3);
else
@@ -224,7 +228,7 @@ static void write_cont (void *opaque, uint32_t nport, uint32_t data)
DMA_run();
break;
- case 0x0b: /* mode */
+ case 0x04: /* mode */
{
ichan = data & 3;
#ifdef DEBUG_DMA
@@ -243,23 +247,23 @@ static void write_cont (void *opaque, uint32_t nport, uint32_t data)
break;
}
- case 0x0c: /* clear flip flop */
+ case 0x05: /* clear flip flop */
d->flip_flop = 0;
break;
- case 0x0d: /* reset */
+ case 0x06: /* reset */
d->flip_flop = 0;
d->mask = ~0;
d->status = 0;
d->command = 0;
break;
- case 0x0e: /* clear mask for all channels */
+ case 0x07: /* clear mask for all channels */
d->mask = 0;
DMA_run();
break;
- case 0x0f: /* write mask for all channels */
+ case 0x08: /* write mask for all channels */
d->mask = data;
DMA_run();
break;
@@ -277,7 +281,7 @@ static void write_cont (void *opaque, uint32_t nport, uint32_t data)
#endif
}
-static uint32_t read_cont (void *opaque, uint32_t nport)
+static uint64_t read_cont(void *opaque, hwaddr nport, unsigned size)
{
struct dma_cont *d = opaque;
int iport, val;
@@ -463,7 +467,7 @@ void DMA_schedule(int nchan)
static void dma_reset(void *opaque)
{
struct dma_cont *d = opaque;
- write_cont (d, (0x0d << d->dshift), 0);
+ write_cont(d, (0x06 << d->dshift), 0, 1);
}
static int dma_phony_handler (void *opaque, int nchan, int dma_pos, int dma_len)
@@ -473,38 +477,68 @@ static int dma_phony_handler (void *opaque, int nchan, int dma_pos, int dma_len)
return dma_pos;
}
+
+static const MemoryRegionOps channel_io_ops = {
+ .read = read_chan,
+ .write = write_chan,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .impl = {
+ .min_access_size = 1,
+ .max_access_size = 1,
+ },
+};
+
+/* IOport from page_base */
+static const MemoryRegionPortio page_portio_list[] = {
+ { 0x01, 3, 1, .write = write_page, .read = read_page, },
+ { 0x07, 1, 1, .write = write_page, .read = read_page, },
+ PORTIO_END_OF_LIST(),
+};
+
+/* IOport from pageh_base */
+static const MemoryRegionPortio pageh_portio_list[] = {
+ { 0x01, 3, 1, .write = write_pageh, .read = read_pageh, },
+ { 0x07, 3, 1, .write = write_pageh, .read = read_pageh, },
+ PORTIO_END_OF_LIST(),
+};
+
+static const MemoryRegionOps cont_io_ops = {
+ .read = read_cont,
+ .write = write_cont,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .impl = {
+ .min_access_size = 1,
+ .max_access_size = 1,
+ },
+};
+
/* dshift = 0: 8 bit DMA, 1 = 16 bit DMA */
static void dma_init2(struct dma_cont *d, int base, int dshift,
int page_base, int pageh_base,
qemu_irq *cpu_request_exit)
{
- static const int page_port_list[] = { 0x1, 0x2, 0x3, 0x7 };
int i;
d->dshift = dshift;
d->cpu_request_exit = cpu_request_exit;
- for (i = 0; i < 8; i++) {
- register_ioport_write (base + (i << dshift), 1, 1, write_chan, d);
- register_ioport_read (base + (i << dshift), 1, 1, read_chan, d);
- }
- for (i = 0; i < ARRAY_SIZE (page_port_list); i++) {
- register_ioport_write (page_base + page_port_list[i], 1, 1,
- write_page, d);
- register_ioport_read (page_base + page_port_list[i], 1, 1,
- read_page, d);
- if (pageh_base >= 0) {
- register_ioport_write (pageh_base + page_port_list[i], 1, 1,
- write_pageh, d);
- register_ioport_read (pageh_base + page_port_list[i], 1, 1,
- read_pageh, d);
- }
- }
- for (i = 0; i < 8; i++) {
- register_ioport_write (base + ((i + 8) << dshift), 1, 1,
- write_cont, d);
- register_ioport_read (base + ((i + 8) << dshift), 1, 1,
- read_cont, d);
+
+ memory_region_init_io(&d->channel_io, &channel_io_ops, d,
+ "dma-chan", 8 << d->dshift);
+ memory_region_add_subregion(isa_address_space_io(NULL),
+ base, &d->channel_io);
+
+ isa_register_portio_list(NULL, page_base, page_portio_list, d,
+ "dma-page");
+ if (pageh_base >= 0) {
+ isa_register_portio_list(NULL, pageh_base, pageh_portio_list, d,
+ "dma-pageh");
}
+
+ memory_region_init_io(&d->cont_io, &cont_io_ops, d, "dma-cont",
+ 8 << d->dshift);
+ memory_region_add_subregion(isa_address_space_io(NULL),
+ base + (8 << d->dshift), &d->cont_io);
+
qemu_register_reset(dma_reset, d);
dma_reset(d);
for (i = 0; i < ARRAY_SIZE (d->regs); ++i) {
diff --git a/hw/ich9.h b/hw/ich9.h
index de491350c3..34e216f142 100644
--- a/hw/ich9.h
+++ b/hw/ich9.h
@@ -51,6 +51,7 @@ typedef struct ICH9LPCState {
/* isa bus */
ISABus *isa_bus;
MemoryRegion rbca_mem;
+ Notifier machine_ready;
qemu_irq *pic;
qemu_irq *ioapic;
diff --git a/hw/isa-bus.c b/hw/isa-bus.c
index 685fdc0f82..144a88e272 100644
--- a/hw/isa-bus.c
+++ b/hw/isa-bus.c
@@ -264,4 +264,13 @@ MemoryRegion *isa_address_space(ISADevice *dev)
return get_system_memory();
}
+MemoryRegion *isa_address_space_io(ISADevice *dev)
+{
+ if (dev) {
+ return isa_bus_from_device(dev)->address_space_io;
+ }
+
+ return isabus->address_space_io;
+}
+
type_init(isabus_register_types)
diff --git a/hw/isa.h b/hw/isa.h
index f9382e8367..9d719fa3c8 100644
--- a/hw/isa.h
+++ b/hw/isa.h
@@ -43,6 +43,7 @@ void isa_bus_irqs(ISABus *bus, qemu_irq *irqs);
qemu_irq isa_get_irq(ISADevice *dev, int isairq);
void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq);
MemoryRegion *isa_address_space(ISADevice *dev);
+MemoryRegion *isa_address_space_io(ISADevice *dev);
ISADevice *isa_create(ISABus *bus, const char *name);
ISADevice *isa_try_create(ISABus *bus, const char *name);
ISADevice *isa_create_simple(ISABus *bus, const char *name);
diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c
index 2fc83a496f..878a43e92c 100644
--- a/hw/lpc_ich9.c
+++ b/hw/lpc_ich9.c
@@ -60,6 +60,7 @@
#include "pam.h"
#include "pci_internals.h"
#include "exec-memory.h"
+#include "sysemu.h"
static int ich9_lpc_sci_irq(ICH9LPCState *lpc);
@@ -456,6 +457,30 @@ static const MemoryRegionOps rbca_mmio_ops = {
.endianness = DEVICE_LITTLE_ENDIAN,
};
+static void ich9_lpc_machine_ready(Notifier *n, void *opaque)
+{
+ ICH9LPCState *s = container_of(n, ICH9LPCState, machine_ready);
+ uint8_t *pci_conf;
+
+ pci_conf = s->d.config;
+ if (isa_is_ioport_assigned(0x3f8)) {
+ /* com1 */
+ pci_conf[0x82] |= 0x01;
+ }
+ if (isa_is_ioport_assigned(0x2f8)) {
+ /* com2 */
+ pci_conf[0x82] |= 0x02;
+ }
+ if (isa_is_ioport_assigned(0x378)) {
+ /* lpt */
+ pci_conf[0x82] |= 0x04;
+ }
+ if (isa_is_ioport_assigned(0x3f0)) {
+ /* floppy */
+ pci_conf[0x82] |= 0x08;
+ }
+}
+
static int ich9_lpc_initfn(PCIDevice *d)
{
ICH9LPCState *lpc = ICH9_LPC_DEVICE(d);
@@ -472,7 +497,11 @@ static int ich9_lpc_initfn(PCIDevice *d)
lpc->isa_bus = isa_bus;
ich9_cc_init(lpc);
- apm_init(&lpc->apm, ich9_apm_ctrl_changed, lpc);
+ apm_init(d, &lpc->apm, ich9_apm_ctrl_changed, lpc);
+
+ lpc->machine_ready.notify = ich9_lpc_machine_ready;
+ qemu_add_machine_init_done_notifier(&lpc->machine_ready);
+
return 0;
}
diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c
index a95a3c1f11..20b5f1a58c 100644
--- a/hw/mips_mipssim.c
+++ b/hw/mips_mipssim.c
@@ -217,7 +217,8 @@ mips_mipssim_init(QEMUMachineInitArgs *args)
/* A single 16450 sits at offset 0x3f8. It is attached to
MIPS CPU INT2, which is interrupt 4. */
if (serial_hds[0])
- serial_init(0x3f8, env->irq[4], 115200, serial_hds[0]);
+ serial_init(0x3f8, env->irq[4], 115200, serial_hds[0],
+ get_system_io());
if (nd_table[0].used)
/* MIPSnet uses the MIPS CPU INT0, which is interrupt 2. */
diff --git a/hw/pc.c b/hw/pc.c
index 2b5bbbfb30..b11e7c4adc 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -98,7 +98,8 @@ void gsi_handler(void *opaque, int n, int level)
qemu_set_irq(s->ioapic_irq[n], level);
}
-static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
+static void ioport80_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned size)
{
}
@@ -116,7 +117,8 @@ void cpu_set_ferr(CPUX86State *s)
qemu_irq_raise(ferr_irq);
}
-static void ioportF0_write(void *opaque, uint32_t addr, uint32_t data)
+static void ioportF0_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned size)
{
qemu_irq_lower(ferr_irq);
}
@@ -567,6 +569,14 @@ int e820_add_entry(uint64_t address, uint64_t length, uint32_t type)
return index;
}
+static const MemoryRegionPortio bochs_bios_portio_list[] = {
+ { 0x500, 1, 1, .write = bochs_bios_write, }, /* 0x500 */
+ { 0x501, 1, 1, .write = bochs_bios_write, }, /* 0x501 */
+ { 0x501, 2, 2, .write = bochs_bios_write, }, /* 0x501 */
+ { 0x8900, 1, 1, .write = bochs_bios_write, }, /* 0x8900 */
+ PORTIO_END_OF_LIST(),
+};
+
static void *bochs_bios_init(void)
{
void *fw_cfg;
@@ -574,12 +584,11 @@ static void *bochs_bios_init(void)
size_t smbios_len;
uint64_t *numa_fw_cfg;
int i, j;
+ PortioList *bochs_bios_port_list = g_new(PortioList, 1);
- register_ioport_write(0x8900, 1, 1, bochs_bios_write, NULL);
-
- register_ioport_write(0x501, 1, 1, bochs_bios_write, NULL);
- register_ioport_write(0x501, 1, 2, bochs_bios_write, NULL);
- register_ioport_write(0x502, 1, 2, bochs_bios_write, NULL);
+ portio_list_init(bochs_bios_port_list, bochs_bios_portio_list,
+ NULL, "bochs-bios");
+ portio_list_add(bochs_bios_port_list, get_system_io(), 0x0);
fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0);
@@ -967,6 +976,24 @@ static void cpu_request_exit(void *opaque, int irq, int level)
}
}
+static const MemoryRegionOps ioport80_io_ops = {
+ .write = ioport80_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .impl = {
+ .min_access_size = 1,
+ .max_access_size = 1,
+ },
+};
+
+static const MemoryRegionOps ioportF0_io_ops = {
+ .write = ioportF0_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .impl = {
+ .min_access_size = 1,
+ .max_access_size = 1,
+ },
+};
+
void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
ISADevice **rtc_state,
ISADevice **floppy,
@@ -981,10 +1008,14 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
qemu_irq *a20_line;
ISADevice *i8042, *port92, *vmmouse, *pit = NULL;
qemu_irq *cpu_exit_irq;
+ MemoryRegion *ioport80_io = g_new(MemoryRegion, 1);
+ MemoryRegion *ioportF0_io = g_new(MemoryRegion, 1);
- register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
+ memory_region_init_io(ioport80_io, &ioport80_io_ops, NULL, "ioport80", 1);
+ memory_region_add_subregion(isa_bus->address_space_io, 0x80, ioport80_io);
- register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
+ memory_region_init_io(ioportF0_io, &ioportF0_io_ops, NULL, "ioportF0", 1);
+ memory_region_add_subregion(isa_bus->address_space_io, 0xf0, ioportF0_io);
/*
* Check if an HPET shall be created.
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index aa3e7f40dc..19e342aeb4 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -281,8 +281,8 @@ static void pc_xen_hvm_init(QEMUMachineInitArgs *args)
}
#endif
-static QEMUMachine pc_machine_v1_3 = {
- .name = "pc-1.3",
+static QEMUMachine pc_machine_v1_4 = {
+ .name = "pc-1.4",
.alias = "pc",
.desc = "Standard PC",
.init = pc_init_pci_1_3,
@@ -290,7 +290,26 @@ static QEMUMachine pc_machine_v1_3 = {
.is_default = 1,
};
+#define PC_COMPAT_1_3 \
+ {\
+ .driver = "usb-tablet",\
+ .property = "usb_version",\
+ .value = stringify(1),\
+ }
+
+static QEMUMachine pc_machine_v1_3 = {
+ .name = "pc-1.3",
+ .desc = "Standard PC",
+ .init = pc_init_pci_1_3,
+ .max_cpus = 255,
+ .compat_props = (GlobalProperty[]) {
+ PC_COMPAT_1_3,
+ { /* end of list */ }
+ },
+};
+
#define PC_COMPAT_1_2 \
+ PC_COMPAT_1_3,\
{\
.driver = "nec-usb-xhci",\
.property = "msi",\
@@ -626,6 +645,7 @@ static QEMUMachine xenfv_machine = {
static void pc_machine_init(void)
{
+ qemu_register_machine(&pc_machine_v1_4);
qemu_register_machine(&pc_machine_v1_3);
qemu_register_machine(&pc_machine_v1_2);
qemu_register_machine(&pc_machine_v1_1);
diff --git a/hw/pm_smbus.c b/hw/pm_smbus.c
index 5d6046de5a..ea1380ca68 100644
--- a/hw/pm_smbus.c
+++ b/hw/pm_smbus.c
@@ -94,10 +94,11 @@ static void smb_transaction(PMSMBus *s)
s->smb_stat |= 0x04;
}
-void smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+static void smb_ioport_writeb(void *opaque, hwaddr addr, uint64_t val,
+ unsigned width)
{
PMSMBus *s = opaque;
- addr &= 0x3f;
+
SMBUS_DPRINTF("SMB writeb port=0x%04x val=0x%02x\n", addr, val);
switch(addr) {
case SMBHSTSTS:
@@ -131,12 +132,11 @@ void smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
}
}
-uint32_t smb_ioport_readb(void *opaque, uint32_t addr)
+static uint64_t smb_ioport_readb(void *opaque, hwaddr addr, unsigned width)
{
PMSMBus *s = opaque;
uint32_t val;
- addr &= 0x3f;
switch(addr) {
case SMBHSTSTS:
val = s->smb_stat;
@@ -170,7 +170,16 @@ uint32_t smb_ioport_readb(void *opaque, uint32_t addr)
return val;
}
+static const MemoryRegionOps pm_smbus_ops = {
+ .read = smb_ioport_readb,
+ .write = smb_ioport_writeb,
+ .valid.min_access_size = 1,
+ .valid.max_access_size = 1,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
void pm_smbus_init(DeviceState *parent, PMSMBus *smb)
{
smb->smbus = i2c_init_bus(parent, "i2c");
+ memory_region_init_io(&smb->io, &pm_smbus_ops, smb, "pm-smbus", 64);
}
diff --git a/hw/pm_smbus.h b/hw/pm_smbus.h
index 4750a409f9..e3069bf7d4 100644
--- a/hw/pm_smbus.h
+++ b/hw/pm_smbus.h
@@ -3,6 +3,7 @@
typedef struct PMSMBus {
i2c_bus *smbus;
+ MemoryRegion io;
uint8_t smb_stat;
uint8_t smb_ctl;
@@ -15,7 +16,5 @@ typedef struct PMSMBus {
} PMSMBus;
void pm_smbus_init(DeviceState *parent, PMSMBus *smb);
-void smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val);
-uint32_t smb_ioport_readb(void *opaque, uint32_t addr);
#endif /* !PM_SMBUS_H */
diff --git a/hw/serial.c b/hw/serial.c
index 60283eab91..07a2a11931 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -718,7 +718,7 @@ const MemoryRegionOps serial_io_ops = {
};
SerialState *serial_init(int base, qemu_irq irq, int baudbase,
- CharDriverState *chr)
+ CharDriverState *chr, MemoryRegion *system_io)
{
SerialState *s;
@@ -732,7 +732,7 @@ SerialState *serial_init(int base, qemu_irq irq, int baudbase,
vmstate_register(NULL, base, &vmstate_serial, s);
memory_region_init_io(&s->io, &serial_io_ops, s, "serial", 8);
- memory_region_add_subregion(get_system_io(), base, &s->io);
+ memory_region_add_subregion(system_io, base, &s->io);
return s;
}
diff --git a/hw/serial.h b/hw/serial.h
index f1e3c4aaa7..ed1a5cd43e 100644
--- a/hw/serial.h
+++ b/hw/serial.h
@@ -89,7 +89,7 @@ void serial_set_frequency(SerialState *s, uint32_t frequency);
/* legacy pre qom */
SerialState *serial_init(int base, qemu_irq irq, int baudbase,
- CharDriverState *chr);
+ CharDriverState *chr, MemoryRegion *system_io);
SerialState *serial_mm_init(MemoryRegion *address_space,
hwaddr base, int it_shift,
qemu_irq irq, int baudbase,
diff --git a/hw/smbus_ich9.c b/hw/smbus_ich9.c
index 6940583bb6..4194785d71 100644
--- a/hw/smbus_ich9.c
+++ b/hw/smbus_ich9.c
@@ -40,7 +40,6 @@ typedef struct ICH9SMBState {
PCIDevice dev;
PMSMBus smb;
- MemoryRegion mem_bar;
} ICH9SMBState;
static const VMStateDescription vmstate_ich9_smbus = {
@@ -54,42 +53,23 @@ static const VMStateDescription vmstate_ich9_smbus = {
}
};
-static void ich9_smb_ioport_writeb(void *opaque, hwaddr addr,
- uint64_t val, unsigned size)
+static void ich9_smbus_write_config(PCIDevice *d, uint32_t address,
+ uint32_t val, int len)
{
- ICH9SMBState *s = opaque;
- uint8_t hostc = s->dev.config[ICH9_SMB_HOSTC];
-
- if ((hostc & ICH9_SMB_HOSTC_HST_EN) && !(hostc & ICH9_SMB_HOSTC_I2C_EN)) {
- uint64_t offset = addr - s->dev.io_regions[ICH9_SMB_SMB_BASE_BAR].addr;
- smb_ioport_writeb(&s->smb, offset, val);
- }
-}
-
-static uint64_t ich9_smb_ioport_readb(void *opaque, hwaddr addr,
- unsigned size)
-{
- ICH9SMBState *s = opaque;
- uint8_t hostc = s->dev.config[ICH9_SMB_HOSTC];
+ ICH9SMBState *s = ICH9_SMB_DEVICE(d);
- if ((hostc & ICH9_SMB_HOSTC_HST_EN) && !(hostc & ICH9_SMB_HOSTC_I2C_EN)) {
- uint64_t offset = addr - s->dev.io_regions[ICH9_SMB_SMB_BASE_BAR].addr;
- return smb_ioport_readb(&s->smb, offset);
+ pci_default_write_config(d, address, val, len);
+ if (range_covers_byte(address, len, ICH9_SMB_HOSTC)) {
+ uint8_t hostc = s->dev.config[ICH9_SMB_HOSTC];
+ if ((hostc & ICH9_SMB_HOSTC_HST_EN) &&
+ !(hostc & ICH9_SMB_HOSTC_I2C_EN)) {
+ memory_region_set_enabled(&s->smb.io, true);
+ } else {
+ memory_region_set_enabled(&s->smb.io, false);
+ }
}
-
- return 0xff;
}
-static const MemoryRegionOps lpc_smb_mmio_ops = {
- .read = ich9_smb_ioport_readb,
- .write = ich9_smb_ioport_writeb,
- .endianness = DEVICE_LITTLE_ENDIAN,
- .impl = {
- .min_access_size = 1,
- .max_access_size = 1,
- },
-};
-
static int ich9_smbus_initfn(PCIDevice *d)
{
ICH9SMBState *s = ICH9_SMB_DEVICE(d);
@@ -98,26 +78,11 @@ static int ich9_smbus_initfn(PCIDevice *d)
pci_config_set_interrupt_pin(d->config, 0x01); /* interrupt pin 1 */
pci_set_byte(d->config + ICH9_SMB_HOSTC, 0);
-
- /*
- * update parameters based on
- * paralell_hds[0]
- * serial_hds[0]
- * serial_hds[0]
- * fdc
- *
- * Is there any OS that depends on them?
- */
-
- /* TODO smb_io_base */
- pci_set_byte(d->config + ICH9_SMB_HOSTC, 0);
/* TODO bar0, bar1: 64bit BAR support*/
- memory_region_init_io(&s->mem_bar, &lpc_smb_mmio_ops, s, "ich9-smbus-bar",
- ICH9_SMB_SMB_BASE_SIZE);
- pci_register_bar(d, ICH9_SMB_SMB_BASE_BAR, PCI_BASE_ADDRESS_SPACE_IO,
- &s->mem_bar);
pm_smbus_init(&d->qdev, &s->smb);
+ pci_register_bar(d, ICH9_SMB_SMB_BASE_BAR, PCI_BASE_ADDRESS_SPACE_IO,
+ &s->smb.io);
return 0;
}
@@ -134,6 +99,7 @@ static void ich9_smb_class_init(ObjectClass *klass, void *data)
dc->vmsd = &vmstate_ich9_smbus;
dc->desc = "ICH9 SMBUS Bridge";
k->init = ich9_smbus_initfn;
+ k->config_write = ich9_smbus_write_config;
}
i2c_bus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base)
diff --git a/hw/usb.h b/hw/usb.h
index f05eb1797f..efae65dcad 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -197,6 +197,7 @@ struct USBEndpoint {
enum USBDeviceFlags {
USB_DEV_FLAG_FULL_PATH,
+ USB_DEV_FLAG_IS_HOST,
};
/* definition of a USB device */
@@ -229,6 +230,7 @@ struct USBDevice {
USBEndpoint ep_out[USB_MAX_ENDPOINTS];
QLIST_HEAD(, USBDescString) strings;
+ const USBDesc *usb_desc; /* Overrides class usb_desc if not NULL */
const USBDescDevice *device;
int configuration;
diff --git a/hw/usb/bus.c b/hw/usb/bus.c
index 55d0edd5c3..8264c240ee 100644
--- a/hw/usb/bus.c
+++ b/hw/usb/bus.c
@@ -166,6 +166,9 @@ const char *usb_device_get_product_desc(USBDevice *dev)
const USBDesc *usb_device_get_usb_desc(USBDevice *dev)
{
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+ if (dev->usb_desc) {
+ return dev->usb_desc;
+ }
return klass->usb_desc;
}
diff --git a/hw/usb/core.c b/hw/usb/core.c
index 52b53108cd..8e360d3ec0 100644
--- a/hw/usb/core.c
+++ b/hw/usb/core.c
@@ -406,7 +406,11 @@ void usb_handle_packet(USBDevice *dev, USBPacket *p)
if (QTAILQ_EMPTY(&p->ep->queue) || p->ep->pipeline) {
usb_process_one(p);
if (p->status == USB_RET_ASYNC) {
+ /* hcd drivers cannot handle async for isoc */
assert(p->ep->type != USB_ENDPOINT_XFER_ISOC);
+ /* using async for interrupt packets breaks migration */
+ assert(p->ep->type != USB_ENDPOINT_XFER_INT ||
+ (dev->flags & USB_DEV_FLAG_IS_HOST));
usb_packet_set_state(p, USB_PACKET_ASYNC);
QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
} else if (p->status == USB_RET_ADD_TO_QUEUE) {
diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c
index 55266b18ef..87491284a8 100644
--- a/hw/usb/dev-hid.c
+++ b/hw/usb/dev-hid.c
@@ -46,6 +46,7 @@ typedef struct USBHIDState {
USBDevice dev;
USBEndpoint *intr;
HIDState hid;
+ uint32_t usb_version;
} USBHIDState;
enum {
@@ -131,6 +132,36 @@ static const USBDescIface desc_iface_tablet = {
},
};
+static const USBDescIface desc_iface_tablet2 = {
+ .bInterfaceNumber = 0,
+ .bNumEndpoints = 1,
+ .bInterfaceClass = USB_CLASS_HID,
+ .bInterfaceProtocol = 0x02,
+ .ndesc = 1,
+ .descs = (USBDescOther[]) {
+ {
+ /* HID descriptor */
+ .data = (uint8_t[]) {
+ 0x09, /* u8 bLength */
+ USB_DT_HID, /* u8 bDescriptorType */
+ 0x01, 0x00, /* u16 HID_class */
+ 0x00, /* u8 country_code */
+ 0x01, /* u8 num_descriptors */
+ USB_DT_REPORT, /* u8 type: Report */
+ 74, 0, /* u16 len */
+ },
+ },
+ },
+ .eps = (USBDescEndpoint[]) {
+ {
+ .bEndpointAddress = USB_DIR_IN | 0x01,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = 8,
+ .bInterval = 4, /* 2 ^ (4-1) * 125 usecs = 1 ms */
+ },
+ },
+};
+
static const USBDescIface desc_iface_keyboard = {
.bInterfaceNumber = 0,
.bNumEndpoints = 1,
@@ -196,6 +227,23 @@ static const USBDescDevice desc_device_tablet = {
},
};
+static const USBDescDevice desc_device_tablet2 = {
+ .bcdUSB = 0x0200,
+ .bMaxPacketSize0 = 64,
+ .bNumConfigurations = 1,
+ .confs = (USBDescConfig[]) {
+ {
+ .bNumInterfaces = 1,
+ .bConfigurationValue = 1,
+ .iConfiguration = STR_CONFIG_TABLET,
+ .bmAttributes = 0xa0,
+ .bMaxPower = 50,
+ .nif = 1,
+ .ifs = &desc_iface_tablet2,
+ },
+ },
+};
+
static const USBDescDevice desc_device_keyboard = {
.bcdUSB = 0x0100,
.bMaxPacketSize0 = 8,
@@ -239,6 +287,20 @@ static const USBDesc desc_tablet = {
.str = desc_strings,
};
+static const USBDesc desc_tablet2 = {
+ .id = {
+ .idVendor = 0x0627,
+ .idProduct = 0x0001,
+ .bcdDevice = 0,
+ .iManufacturer = STR_MANUFACTURER,
+ .iProduct = STR_PRODUCT_TABLET,
+ .iSerialNumber = STR_SERIALNUMBER,
+ },
+ .full = &desc_device_tablet,
+ .high = &desc_device_tablet2,
+ .str = desc_strings,
+};
+
static const USBDesc desc_keyboard = {
.id = {
.idVendor = 0x0627,
@@ -508,6 +570,21 @@ static int usb_hid_initfn(USBDevice *dev, int kind)
static int usb_tablet_initfn(USBDevice *dev)
{
+ USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
+
+ switch (us->usb_version) {
+ case 1:
+ dev->usb_desc = &desc_tablet;
+ break;
+ case 2:
+ dev->usb_desc = &desc_tablet2;
+ break;
+ default:
+ error_report("Invalid usb version %d for usb-tabler (must be 1 or 2)",
+ us->usb_version);
+ return -1;
+ }
+
return usb_hid_initfn(dev, HID_TABLET);
}
@@ -562,8 +639,14 @@ static void usb_hid_class_initfn(ObjectClass *klass, void *data)
uc->handle_control = usb_hid_handle_control;
uc->handle_data = usb_hid_handle_data;
uc->handle_destroy = usb_hid_handle_destroy;
+ uc->handle_attach = usb_desc_attach;
}
+static Property usb_tablet_properties[] = {
+ DEFINE_PROP_UINT32("usb_version", USBHIDState, usb_version, 2),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
static void usb_tablet_class_initfn(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -572,8 +655,8 @@ static void usb_tablet_class_initfn(ObjectClass *klass, void *data)
usb_hid_class_initfn(klass, data);
uc->init = usb_tablet_initfn;
uc->product_desc = "QEMU USB Tablet";
- uc->usb_desc = &desc_tablet;
dc->vmsd = &vmstate_usb_ptr;
+ dc->props = usb_tablet_properties;
}
static TypeInfo usb_tablet_info = {
diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c
index 9ee60dd412..470fbbb86c 100644
--- a/hw/usb/dev-hub.c
+++ b/hw/usb/dev-hub.c
@@ -184,6 +184,7 @@ static void usb_hub_detach(USBPort *port1)
port->wPortStatus &= ~PORT_STAT_ENABLE;
port->wPortChange |= PORT_STAT_C_ENABLE;
}
+ usb_wakeup(s->intr);
}
static void usb_hub_child_detach(USBPort *port1, USBDevice *child)
@@ -363,6 +364,7 @@ static void usb_hub_handle_control(USBDevice *dev, USBPacket *p,
port->wPortChange |= PORT_STAT_C_RESET;
/* set enable bit */
port->wPortStatus |= PORT_STAT_ENABLE;
+ usb_wakeup(s->intr);
}
break;
case PORT_POWER:
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
index 14d9e5aa5b..30cb03373e 100644
--- a/hw/usb/dev-network.c
+++ b/hw/usb/dev-network.c
@@ -639,6 +639,8 @@ typedef struct USBNetState {
unsigned int in_ptr, in_len;
uint8_t in_buf[2048];
+ USBEndpoint *intr;
+
char usbstring_mac[13];
NICState *nic;
NICConf conf;
@@ -851,6 +853,10 @@ static void *rndis_queue_response(USBNetState *s, unsigned int length)
struct rndis_response *r =
g_malloc0(sizeof(struct rndis_response) + length);
+ if (QTAILQ_EMPTY(&s->rndis_resp)) {
+ usb_wakeup(s->intr);
+ }
+
QTAILQ_INSERT_TAIL(&s->rndis_resp, r, entries);
r->length = length;
@@ -1349,6 +1355,7 @@ static int usb_net_initfn(USBDevice *dev)
s->media_state = 0; /* NDIS_MEDIA_STATE_CONNECTED */;
s->filter = 0;
s->vendorid = 0x1234;
+ s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_usbnet_info, &s->conf,
diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c
index 08b416daa6..f7342b08c3 100644
--- a/hw/usb/dev-wacom.c
+++ b/hw/usb/dev-wacom.c
@@ -43,6 +43,7 @@
typedef struct USBWacomState {
USBDevice dev;
+ USBEndpoint *intr;
QEMUPutMouseEntry *eh_entry;
int dx, dy, dz, buttons_state;
int x, y;
@@ -137,6 +138,7 @@ static void usb_mouse_event(void *opaque,
s->dz += dz1;
s->buttons_state = buttons_state;
s->changed = 1;
+ usb_wakeup(s->intr);
}
static void usb_wacom_event(void *opaque,
@@ -150,6 +152,7 @@ static void usb_wacom_event(void *opaque,
s->dz += dz;
s->buttons_state = buttons_state;
s->changed = 1;
+ usb_wakeup(s->intr);
}
static inline int int_clamp(int val, int vmin, int vmax)
@@ -337,6 +340,7 @@ static int usb_wacom_initfn(USBDevice *dev)
USBWacomState *s = DO_UPCAST(USBWacomState, dev, dev);
usb_desc_create_serial(dev);
usb_desc_init(dev);
+ s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
s->changed = 1;
return 0;
}
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 7df8e21ecb..7536837fb2 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -114,6 +114,7 @@
#define BUFF_SIZE 5*4096 // Max bytes to transfer per transaction
#define MAX_QH 100 // Max allowable queue heads in a chain
#define MIN_FR_PER_TICK 3 // Min frames to process when catching up
+#define PERIODIC_ACTIVE 64
/* Internal periodic / asynchronous schedule state machine states
*/
@@ -738,6 +739,19 @@ static int ehci_register_companion(USBBus *bus, USBPort *ports[],
return 0;
}
+static void ehci_wakeup_endpoint(USBBus *bus, USBEndpoint *ep)
+{
+ EHCIState *s = container_of(bus, EHCIState, bus);
+ uint32_t portsc = s->portsc[ep->dev->port->index];
+
+ if (portsc & PORTSC_POWNER) {
+ return;
+ }
+
+ s->periodic_sched_active = PERIODIC_ACTIVE;
+ qemu_bh_schedule(s->async_bh);
+}
+
static USBDevice *ehci_find_device(EHCIState *ehci, uint8_t addr)
{
USBDevice *dev;
@@ -1188,9 +1202,10 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
trace_usb_ehci_packet_action(p->queue, p, "wakeup");
p->async = EHCI_ASYNC_FINISHED;
- if (p->queue->async) {
- qemu_bh_schedule(p->queue->ehci->async_bh);
+ if (!p->queue->async) {
+ s->periodic_sched_active = PERIODIC_ACTIVE;
}
+ qemu_bh_schedule(s->async_bh);
}
static void ehci_execute_complete(EHCIQueue *q)
@@ -1344,6 +1359,8 @@ static int ehci_process_itd(EHCIState *ehci,
uint32_t i, len, pid, dir, devaddr, endp;
uint32_t pg, off, ptr1, ptr2, max, mult;
+ ehci->periodic_sched_active = PERIODIC_ACTIVE;
+
dir =(itd->bufptr[1] & ITD_BUFPTR_DIRECTION);
devaddr = get_field(itd->bufptr[0], ITD_BUFPTR_DEVADDR);
endp = get_field(itd->bufptr[0], ITD_BUFPTR_EP);
@@ -2033,6 +2050,9 @@ static void ehci_advance_state(EHCIState *ehci, int async)
case EST_WRITEBACK:
assert(q != NULL);
again = ehci_state_writeback(q);
+ if (!async) {
+ ehci->periodic_sched_active = PERIODIC_ACTIVE;
+ }
break;
default:
@@ -2198,7 +2218,6 @@ static void ehci_frame_timer(void *opaque)
if (ehci_periodic_enabled(ehci) || ehci->pstate != EST_INACTIVE) {
need_timer++;
- ehci->async_stepdown = 0;
if (frames > ehci->maxframes) {
skipped_frames = frames - ehci->maxframes;
@@ -2222,18 +2241,25 @@ static void ehci_frame_timer(void *opaque)
break;
}
}
+ if (ehci->periodic_sched_active) {
+ ehci->periodic_sched_active--;
+ }
ehci_update_frindex(ehci, 1);
ehci_advance_periodic_state(ehci);
ehci->last_run_ns += FRAME_TIMER_NS;
}
} else {
- if (ehci->async_stepdown < ehci->maxframes / 2) {
- ehci->async_stepdown++;
- }
+ ehci->periodic_sched_active = 0;
ehci_update_frindex(ehci, frames);
ehci->last_run_ns += FRAME_TIMER_NS * frames;
}
+ if (ehci->periodic_sched_active) {
+ ehci->async_stepdown = 0;
+ } else if (ehci->async_stepdown < ehci->maxframes / 2) {
+ ehci->async_stepdown++;
+ }
+
/* Async is not inside loop since it executes everything it can once
* called
*/
@@ -2301,6 +2327,7 @@ static USBPortOps ehci_port_ops = {
static USBBusOps ehci_bus_ops = {
.register_companion = ehci_register_companion,
+ .wakeup_endpoint = ehci_wakeup_endpoint,
};
static int usb_ehci_post_load(void *opaque, int version_id)
diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h
index d8078f4555..772870b727 100644
--- a/hw/usb/hcd-ehci.h
+++ b/hw/usb/hcd-ehci.h
@@ -311,6 +311,7 @@ struct EHCIState {
uint64_t last_run_ns;
uint32_t async_stepdown;
+ uint32_t periodic_sched_active;
bool int_req_by_async;
};
diff --git a/hw/usb/host-bsd.c b/hw/usb/host-bsd.c
index 6473e8b747..dae0009378 100644
--- a/hw/usb/host-bsd.c
+++ b/hw/usb/host-bsd.c
@@ -292,6 +292,7 @@ static void usb_host_handle_destroy(USBDevice *opaque)
static int usb_host_initfn(USBDevice *dev)
{
+ dev->flags |= (1 << USB_DEV_FLAG_IS_HOST);
return 0;
}
diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c
index aa77b7704d..bdafb6bc87 100644
--- a/hw/usb/host-linux.c
+++ b/hw/usb/host-linux.c
@@ -1476,6 +1476,7 @@ static int usb_host_initfn(USBDevice *dev)
{
USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
+ dev->flags |= (1 << USB_DEV_FLAG_IS_HOST);
dev->auto_attach = 0;
s->fd = -1;
s->hub_fd = -1;
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 490c90fae1..9e7f6453f7 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -1644,6 +1644,10 @@ static void usbredir_interrupt_packet(void *priv, uint64_t id,
return;
}
+ if (QTAILQ_EMPTY(&dev->endpoint[EP2I(ep)].bufpq)) {
+ usb_wakeup(usb_ep_get(&dev->dev, USB_TOKEN_IN, ep & 0x0f));
+ }
+
/* bufp_alloc also adds the packet to the ep queue */
bufp_alloc(dev, data, data_len, interrupt_packet->status, ep);
} else {
diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index 5d7c00cf4b..57d16c0134 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -24,6 +24,7 @@
#include "pm_smbus.h"
#include "sysemu.h"
#include "qemu-timer.h"
+#include "exec-memory.h"
typedef uint32_t pci_addr_t;
#include "pci_host.h"
@@ -159,6 +160,7 @@ static void vt82c686b_write_config(PCIDevice * d, uint32_t address,
typedef struct VT686PMState {
PCIDevice dev;
+ MemoryRegion io;
ACPIREGS ar;
APMState apm;
PMSMBus smb;
@@ -195,92 +197,17 @@ static void pm_tmr_timer(ACPIREGS *ar)
pm_update_sci(s);
}
-static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
-{
- VT686PMState *s = opaque;
-
- addr &= 0x0f;
- switch (addr) {
- case 0x00:
- acpi_pm1_evt_write_sts(&s->ar, val);
- pm_update_sci(s);
- break;
- case 0x02:
- acpi_pm1_evt_write_en(&s->ar, val);
- pm_update_sci(s);
- break;
- case 0x04:
- acpi_pm1_cnt_write(&s->ar, val, 0);
- break;
- default:
- break;
- }
- DPRINTF("PM writew port=0x%04x val=0x%02x\n", addr, val);
-}
-
-static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
-{
- VT686PMState *s = opaque;
- uint32_t val;
-
- addr &= 0x0f;
- switch (addr) {
- case 0x00:
- val = acpi_pm1_evt_get_sts(&s->ar);
- break;
- case 0x02:
- val = s->ar.pm1.evt.en;
- break;
- case 0x04:
- val = s->ar.pm1.cnt.cnt;
- break;
- default:
- val = 0;
- break;
- }
- DPRINTF("PM readw port=0x%04x val=0x%02x\n", addr, val);
- return val;
-}
-
-static void pm_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
-{
- addr &= 0x0f;
- DPRINTF("PM writel port=0x%04x val=0x%08x\n", addr, val);
-}
-
-static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
-{
- VT686PMState *s = opaque;
- uint32_t val;
-
- addr &= 0x0f;
- switch (addr) {
- case 0x08:
- val = acpi_pm_tmr_get(&s->ar);
- break;
- default:
- val = 0;
- break;
- }
- DPRINTF("PM readl port=0x%04x val=0x%08x\n", addr, val);
- return val;
-}
-
static void pm_io_space_update(VT686PMState *s)
{
uint32_t pm_io_base;
- if (s->dev.config[0x80] & 1) {
- pm_io_base = pci_get_long(s->dev.config + 0x40);
- pm_io_base &= 0xffc0;
+ pm_io_base = pci_get_long(s->dev.config + 0x40);
+ pm_io_base &= 0xffc0;
- /* XXX: need to improve memory and ioport allocation */
- DPRINTF("PM: mapping to 0x%x\n", pm_io_base);
- register_ioport_write(pm_io_base, 64, 2, pm_ioport_writew, s);
- register_ioport_read(pm_io_base, 64, 2, pm_ioport_readw, s);
- register_ioport_write(pm_io_base, 64, 4, pm_ioport_writel, s);
- register_ioport_read(pm_io_base, 64, 4, pm_ioport_readl, s);
- }
+ memory_region_transaction_begin();
+ memory_region_set_enabled(&s->io, s->dev.config[0x80] & 1);
+ memory_region_set_address(&s->io, pm_io_base);
+ memory_region_transaction_commit();
}
static void pm_write_config(PCIDevice *d,
@@ -424,15 +351,18 @@ static int vt82c686b_pm_initfn(PCIDevice *dev)
pci_conf[0x90] = s->smb_io_base | 1;
pci_conf[0x91] = s->smb_io_base >> 8;
pci_conf[0xd2] = 0x90;
- register_ioport_write(s->smb_io_base, 0xf, 1, smb_ioport_writeb, &s->smb);
- register_ioport_read(s->smb_io_base, 0xf, 1, smb_ioport_readb, &s->smb);
+ pm_smbus_init(&s->dev.qdev, &s->smb);
+ memory_region_add_subregion(get_system_io(), s->smb_io_base, &s->smb.io);
- apm_init(&s->apm, NULL, s);
+ apm_init(dev, &s->apm, NULL, s);
- acpi_pm_tmr_init(&s->ar, pm_tmr_timer);
- acpi_pm1_cnt_init(&s->ar);
+ memory_region_init(&s->io, "vt82c686-pm", 64);
+ memory_region_set_enabled(&s->io, false);
+ memory_region_add_subregion(get_system_io(), 0, &s->io);
- pm_smbus_init(&s->dev.qdev, &s->smb);
+ acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io);
+ acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io);
+ acpi_pm1_cnt_init(&s->ar, &s->io);
return 0;
}
diff --git a/linux-user/arm/syscall_nr.h b/linux-user/arm/syscall_nr.h
index 5356395659..42d68550dc 100644
--- a/linux-user/arm/syscall_nr.h
+++ b/linux-user/arm/syscall_nr.h
@@ -182,8 +182,8 @@
#define TARGET_NR_rt_sigtimedwait (177)
#define TARGET_NR_rt_sigqueueinfo (178)
#define TARGET_NR_rt_sigsuspend (179)
-#define TARGET_NR_pread (180)
-#define TARGET_NR_pwrite (181)
+#define TARGET_NR_pread64 (180)
+#define TARGET_NR_pwrite64 (181)
#define TARGET_NR_chown (182)
#define TARGET_NR_getcwd (183)
#define TARGET_NR_capget (184)
diff --git a/linux-user/i386/syscall_nr.h b/linux-user/i386/syscall_nr.h
index 74abfcacb4..f0803050d8 100644
--- a/linux-user/i386/syscall_nr.h
+++ b/linux-user/i386/syscall_nr.h
@@ -182,8 +182,8 @@
#define TARGET_NR_rt_sigtimedwait 177
#define TARGET_NR_rt_sigqueueinfo 178
#define TARGET_NR_rt_sigsuspend 179
-#define TARGET_NR_pread 180
-#define TARGET_NR_pwrite 181
+#define TARGET_NR_pread64 180
+#define TARGET_NR_pwrite64 181
#define TARGET_NR_chown 182
#define TARGET_NR_getcwd 183
#define TARGET_NR_capget 184
diff --git a/linux-user/sparc/syscall_nr.h b/linux-user/sparc/syscall_nr.h
index f201f9f788..061711cc03 100644
--- a/linux-user/sparc/syscall_nr.h
+++ b/linux-user/sparc/syscall_nr.h
@@ -62,8 +62,8 @@
#define TARGET_NR_getpagesize 64 /* Common */
#define TARGET_NR_msync 65 /* Common in newer 1.3.x revs... */
#define TARGET_NR_vfork 66 /* Common */
-#define TARGET_NR_pread 67 /* Linux Specific */
-#define TARGET_NR_pwrite 68 /* Linux Specific */
+#define TARGET_NR_pread64 67 /* Linux Specific */
+#define TARGET_NR_pwrite64 68 /* Linux Specific */
#define TARGET_NR_geteuid32 69 /* Linux sparc32, sbrk under SunOS */
#define TARGET_NR_getegid32 70 /* Linux sparc32, sstk under SunOS */
#define TARGET_NR_mmap 71 /* Common */
diff --git a/linux-user/strace.list b/linux-user/strace.list
index af3c6a0cce..08f115d843 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -972,9 +972,6 @@
#ifdef TARGET_NR_prctl
{ TARGET_NR_prctl, "prctl" , NULL, NULL, NULL },
#endif
-#ifdef TARGET_NR_pread
-{ TARGET_NR_pread, "pread" , NULL, NULL, NULL },
-#endif
#ifdef TARGET_NR_pread64
{ TARGET_NR_pread64, "pread64" , NULL, NULL, NULL },
#endif
@@ -993,9 +990,6 @@
#ifdef TARGET_NR_putpmsg
{ TARGET_NR_putpmsg, "putpmsg" , NULL, NULL, NULL },
#endif
-#ifdef TARGET_NR_pwrite
-{ TARGET_NR_pwrite, "pwrite" , NULL, NULL, NULL },
-#endif
#ifdef TARGET_NR_pwrite64
{ TARGET_NR_pwrite64, "pwrite64" , NULL, NULL, NULL },
#endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index e4291ed776..31d5276465 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -7449,24 +7449,6 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
goto unimplemented;
#endif
#endif
-#ifdef TARGET_NR_pread
- case TARGET_NR_pread:
- if (regpairs_aligned(cpu_env))
- arg4 = arg5;
- if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
- goto efault;
- ret = get_errno(pread(arg1, p, arg3, arg4));
- unlock_user(p, arg2, ret);
- break;
- case TARGET_NR_pwrite:
- if (regpairs_aligned(cpu_env))
- arg4 = arg5;
- if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
- goto efault;
- ret = get_errno(pwrite(arg1, p, arg3, arg4));
- unlock_user(p, arg2, 0);
- break;
-#endif
#ifdef TARGET_NR_pread64
case TARGET_NR_pread64:
if (regpairs_aligned(cpu_env)) {
diff --git a/linux-user/unicore32/syscall_nr.h b/linux-user/unicore32/syscall_nr.h
index 9c72d84d80..486b8c45a0 100644
--- a/linux-user/unicore32/syscall_nr.h
+++ b/linux-user/unicore32/syscall_nr.h
@@ -187,8 +187,8 @@
#define TARGET_NR_rt_sigtimedwait 177
#define TARGET_NR_rt_sigqueueinfo 178
#define TARGET_NR_rt_sigsuspend 179
-#define TARGET_NR_pread 180
-#define TARGET_NR_pwrite 181
+#define TARGET_NR_pread64 180
+#define TARGET_NR_pwrite64 181
#define TARGET_NR_chown 182
#define TARGET_NR_getcwd 183
#define TARGET_NR_capget 184
diff --git a/qemu-config.c b/qemu-config.c
index 10d1ba4176..aa78fb9ea7 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -417,54 +417,6 @@ static QemuOptsList qemu_trace_opts = {
},
};
-static QemuOptsList qemu_cpudef_opts = {
- .name = "cpudef",
- .head = QTAILQ_HEAD_INITIALIZER(qemu_cpudef_opts.head),
- .desc = {
- {
- .name = "name",
- .type = QEMU_OPT_STRING,
- },{
- .name = "level",
- .type = QEMU_OPT_NUMBER,
- },{
- .name = "vendor",
- .type = QEMU_OPT_STRING,
- },{
- .name = "family",
- .type = QEMU_OPT_NUMBER,
- },{
- .name = "model",
- .type = QEMU_OPT_NUMBER,
- },{
- .name = "stepping",
- .type = QEMU_OPT_NUMBER,
- },{
- .name = "feature_edx", /* cpuid 0000_0001.edx */
- .type = QEMU_OPT_STRING,
- },{
- .name = "feature_ecx", /* cpuid 0000_0001.ecx */
- .type = QEMU_OPT_STRING,
- },{
- .name = "extfeature_edx", /* cpuid 8000_0001.edx */
- .type = QEMU_OPT_STRING,
- },{
- .name = "extfeature_ecx", /* cpuid 8000_0001.ecx */
- .type = QEMU_OPT_STRING,
- },{
- .name = "xlevel",
- .type = QEMU_OPT_NUMBER,
- },{
- .name = "model_id",
- .type = QEMU_OPT_STRING,
- },{
- .name = "vendor_override",
- .type = QEMU_OPT_NUMBER,
- },
- { /* end of list */ }
- },
-};
-
QemuOptsList qemu_spice_opts = {
.name = "spice",
.head = QTAILQ_HEAD_INITIALIZER(qemu_spice_opts.head),
@@ -700,7 +652,6 @@ static QemuOptsList *vm_config_groups[32] = {
&qemu_rtc_opts,
&qemu_global_opts,
&qemu_mon_opts,
- &qemu_cpudef_opts,
&qemu_trace_opts,
&qemu_option_rom_opts,
&qemu_machine_opts,
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 4045f788ea..71fe1a1ab0 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -3410,11 +3410,11 @@ static inline void gen_intermediate_code_internal(CPUAlphaState *env,
if (lj < j) {
lj++;
while (lj < j)
- gen_opc_instr_start[lj++] = 0;
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
}
- gen_opc_pc[lj] = ctx.pc;
- gen_opc_instr_start[lj] = 1;
- gen_opc_icount[lj] = num_insns;
+ tcg_ctx.gen_opc_pc[lj] = ctx.pc;
+ tcg_ctx.gen_opc_instr_start[lj] = 1;
+ tcg_ctx.gen_opc_icount[lj] = num_insns;
}
if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
gen_io_start();
@@ -3468,7 +3468,7 @@ static inline void gen_intermediate_code_internal(CPUAlphaState *env,
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
lj++;
while (lj <= j)
- gen_opc_instr_start[lj++] = 0;
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
} else {
tb->size = ctx.pc - pc_start;
tb->icount = num_insns;
@@ -3551,5 +3551,5 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model)
void restore_state_to_opc(CPUAlphaState *env, TranslationBlock *tb, int pc_pos)
{
- env->pc = gen_opc_pc[pc_pos];
+ env->pc = tcg_ctx.gen_opc_pc[pc_pos];
}
diff --git a/target-arm/translate.c b/target-arm/translate.c
index c42110ab0d..3cf3604517 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -9838,12 +9838,12 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
if (lj < j) {
lj++;
while (lj < j)
- gen_opc_instr_start[lj++] = 0;
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
}
- gen_opc_pc[lj] = dc->pc;
+ tcg_ctx.gen_opc_pc[lj] = dc->pc;
gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
- gen_opc_instr_start[lj] = 1;
- gen_opc_icount[lj] = num_insns;
+ tcg_ctx.gen_opc_instr_start[lj] = 1;
+ tcg_ctx.gen_opc_icount[lj] = num_insns;
}
if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
@@ -9977,7 +9977,7 @@ done_generating:
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
lj++;
while (lj <= j)
- gen_opc_instr_start[lj++] = 0;
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
} else {
tb->size = dc->pc - pc_start;
tb->icount = num_insns;
@@ -10043,6 +10043,6 @@ void cpu_dump_state(CPUARMState *env, FILE *f, fprintf_function cpu_fprintf,
void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos)
{
- env->regs[15] = gen_opc_pc[pc_pos];
+ env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
env->condexec_bits = gen_opc_condexec_bits[pc_pos];
}
diff --git a/target-cris/translate.c b/target-cris/translate.c
index 0b0e86dbd1..60bdc241ef 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3301,16 +3301,16 @@ gen_intermediate_code_internal(CPUCRISState *env, TranslationBlock *tb,
if (lj < j) {
lj++;
while (lj < j) {
- gen_opc_instr_start[lj++] = 0;
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
}
}
if (dc->delayed_branch == 1) {
- gen_opc_pc[lj] = dc->ppc | 1;
+ tcg_ctx.gen_opc_pc[lj] = dc->ppc | 1;
} else {
- gen_opc_pc[lj] = dc->pc;
+ tcg_ctx.gen_opc_pc[lj] = dc->pc;
}
- gen_opc_instr_start[lj] = 1;
- gen_opc_icount[lj] = num_insns;
+ tcg_ctx.gen_opc_instr_start[lj] = 1;
+ tcg_ctx.gen_opc_icount[lj] = num_insns;
}
/* Pretty disas. */
@@ -3439,7 +3439,7 @@ gen_intermediate_code_internal(CPUCRISState *env, TranslationBlock *tb,
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
lj++;
while (lj <= j) {
- gen_opc_instr_start[lj++] = 0;
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
}
} else {
tb->size = dc->pc - pc_start;
@@ -3621,5 +3621,5 @@ CRISCPU *cpu_cris_init(const char *cpu_model)
void restore_state_to_opc(CPUCRISState *env, TranslationBlock *tb, int pc_pos)
{
- env->pc = gen_opc_pc[pc_pos];
+ env->pc = tcg_ctx.gen_opc_pc[pc_pos];
}
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 8e676ba1a8..f394ea69a5 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -7988,12 +7988,12 @@ static inline void gen_intermediate_code_internal(CPUX86State *env,
if (lj < j) {
lj++;
while (lj < j)
- gen_opc_instr_start[lj++] = 0;
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
}
- gen_opc_pc[lj] = pc_ptr;
+ tcg_ctx.gen_opc_pc[lj] = pc_ptr;
gen_opc_cc_op[lj] = dc->cc_op;
- gen_opc_instr_start[lj] = 1;
- gen_opc_icount[lj] = num_insns;
+ tcg_ctx.gen_opc_instr_start[lj] = 1;
+ tcg_ctx.gen_opc_icount[lj] = num_insns;
}
if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
gen_io_start();
@@ -8037,7 +8037,7 @@ static inline void gen_intermediate_code_internal(CPUX86State *env,
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
lj++;
while (lj <= j)
- gen_opc_instr_start[lj++] = 0;
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
}
#ifdef DEBUG_DISAS
@@ -8080,16 +8080,17 @@ void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb, int pc_pos)
int i;
qemu_log("RESTORE:\n");
for(i = 0;i <= pc_pos; i++) {
- if (gen_opc_instr_start[i]) {
- qemu_log("0x%04x: " TARGET_FMT_lx "\n", i, gen_opc_pc[i]);
+ if (tcg_ctx.gen_opc_instr_start[i]) {
+ qemu_log("0x%04x: " TARGET_FMT_lx "\n", i,
+ tcg_ctx.gen_opc_pc[i]);
}
}
qemu_log("pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",
- pc_pos, gen_opc_pc[pc_pos] - tb->cs_base,
+ pc_pos, tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base,
(uint32_t)tb->cs_base);
}
#endif
- env->eip = gen_opc_pc[pc_pos] - tb->cs_base;
+ env->eip = tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base;
cc_op = gen_opc_cc_op[pc_pos];
if (cc_op != CC_OP_DYNAMIC)
env->cc_op = cc_op;
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index af986499f2..e131ad1b5f 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -1051,12 +1051,12 @@ static void gen_intermediate_code_internal(CPULM32State *env,
if (lj < j) {
lj++;
while (lj < j) {
- gen_opc_instr_start[lj++] = 0;
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
}
}
- gen_opc_pc[lj] = dc->pc;
- gen_opc_instr_start[lj] = 1;
- gen_opc_icount[lj] = num_insns;
+ tcg_ctx.gen_opc_pc[lj] = dc->pc;
+ tcg_ctx.gen_opc_instr_start[lj] = 1;
+ tcg_ctx.gen_opc_icount[lj] = num_insns;
}
/* Pretty disas. */
@@ -1110,7 +1110,7 @@ static void gen_intermediate_code_internal(CPULM32State *env,
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
lj++;
while (lj <= j) {
- gen_opc_instr_start[lj++] = 0;
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
}
} else {
tb->size = dc->pc - pc_start;
@@ -1172,7 +1172,7 @@ void cpu_dump_state(CPULM32State *env, FILE *f, fprintf_function cpu_fprintf,
void restore_state_to_opc(CPULM32State *env, TranslationBlock *tb, int pc_pos)
{
- env->pc = gen_opc_pc[pc_pos];
+ env->pc = tcg_ctx.gen_opc_pc[pc_pos];
}
void lm32_translate_init(void)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index b13be4899e..11defc6e04 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -3019,11 +3019,11 @@ gen_intermediate_code_internal(CPUM68KState *env, TranslationBlock *tb,
if (lj < j) {
lj++;
while (lj < j)
- gen_opc_instr_start[lj++] = 0;
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
}
- gen_opc_pc[lj] = dc->pc;
- gen_opc_instr_start[lj] = 1;
- gen_opc_icount[lj] = num_insns;
+ tcg_ctx.gen_opc_pc[lj] = dc->pc;
+ tcg_ctx.gen_opc_instr_start[lj] = 1;
+ tcg_ctx.gen_opc_icount[lj] = num_insns;
}
if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
gen_io_start();
@@ -3078,7 +3078,7 @@ gen_intermediate_code_internal(CPUM68KState *env, TranslationBlock *tb,
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
lj++;
while (lj <= j)
- gen_opc_instr_start[lj++] = 0;
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
} else {
tb->size = dc->pc - pc_start;
tb->icount = num_insns;
@@ -3121,5 +3121,5 @@ void cpu_dump_state(CPUM68KState *env, FILE *f, fprintf_function cpu_fprintf,
void restore_state_to_opc(CPUM68KState *env, TranslationBlock *tb, int pc_pos)
{
- env->pc = gen_opc_pc[pc_pos];
+ env->pc = tcg_ctx.gen_opc_pc[pc_pos];
}
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index cce4494954..6ceff02a12 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1788,11 +1788,11 @@ gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb,
if (lj < j) {
lj++;
while (lj < j)
- gen_opc_instr_start[lj++] = 0;
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
}
- gen_opc_pc[lj] = dc->pc;
- gen_opc_instr_start[lj] = 1;
- gen_opc_icount[lj] = num_insns;
+ tcg_ctx.gen_opc_pc[lj] = dc->pc;
+ tcg_ctx.gen_opc_instr_start[lj] = 1;
+ tcg_ctx.gen_opc_icount[lj] = num_insns;
}
/* Pretty disas. */
@@ -1902,7 +1902,7 @@ gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb,
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
lj++;
while (lj <= j)
- gen_opc_instr_start[lj++] = 0;
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
} else {
tb->size = dc->pc - pc_start;
tb->icount = num_insns;
@@ -2014,5 +2014,5 @@ MicroBlazeCPU *cpu_mb_init(const char *cpu_model)
void restore_state_to_opc(CPUMBState *env, TranslationBlock *tb, int pc_pos)
{
- env->sregs[SR_PC] = gen_opc_pc[pc_pos];
+ env->sregs[SR_PC] = tcg_ctx.gen_opc_pc[pc_pos];
}
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 71c55bcadb..65e6725cc9 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -15579,13 +15579,13 @@ gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
if (lj < j) {
lj++;
while (lj < j)
- gen_opc_instr_start[lj++] = 0;
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
}
- gen_opc_pc[lj] = ctx.pc;
+ tcg_ctx.gen_opc_pc[lj] = ctx.pc;
gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
gen_opc_btarget[lj] = ctx.btarget;
- gen_opc_instr_start[lj] = 1;
- gen_opc_icount[lj] = num_insns;
+ tcg_ctx.gen_opc_instr_start[lj] = 1;
+ tcg_ctx.gen_opc_icount[lj] = num_insns;
}
if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
gen_io_start();
@@ -15662,7 +15662,7 @@ done_generating:
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
lj++;
while (lj <= j)
- gen_opc_instr_start[lj++] = 0;
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
} else {
tb->size = ctx.pc - pc_start;
tb->icount = num_insns;
@@ -16002,7 +16002,7 @@ void cpu_state_reset(CPUMIPSState *env)
void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
{
- env->active_tc.PC = gen_opc_pc[pc_pos];
+ env->active_tc.PC = tcg_ctx.gen_opc_pc[pc_pos];
env->hflags &= ~MIPS_HFLAG_BMASK;
env->hflags |= gen_opc_hflags[pc_pos];
switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index f14da7bd1a..9ac999a9c8 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -1707,12 +1707,12 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
if (k < j) {
k++;
while (k < j) {
- gen_opc_instr_start[k++] = 0;
+ tcg_ctx.gen_opc_instr_start[k++] = 0;
}
}
- gen_opc_pc[k] = dc->pc;
- gen_opc_instr_start[k] = 1;
- gen_opc_icount[k] = num_insns;
+ tcg_ctx.gen_opc_pc[k] = dc->pc;
+ tcg_ctx.gen_opc_instr_start[k] = 1;
+ tcg_ctx.gen_opc_icount[k] = num_insns;
}
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
@@ -1787,7 +1787,7 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
k++;
while (k <= j) {
- gen_opc_instr_start[k++] = 0;
+ tcg_ctx.gen_opc_instr_start[k++] = 0;
}
} else {
tb->size = dc->pc - pc_start;
@@ -1832,5 +1832,5 @@ void cpu_dump_state(CPUOpenRISCState *env, FILE *f,
void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb,
int pc_pos)
{
- env->pc = gen_opc_pc[pc_pos];
+ env->pc = tcg_ctx.gen_opc_pc[pc_pos];
}
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 987b04eda5..653c2fdb1f 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -9680,11 +9680,11 @@ static inline void gen_intermediate_code_internal(CPUPPCState *env,
if (lj < j) {
lj++;
while (lj < j)
- gen_opc_instr_start[lj++] = 0;
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
}
- gen_opc_pc[lj] = ctx.nip;
- gen_opc_instr_start[lj] = 1;
- gen_opc_icount[lj] = num_insns;
+ tcg_ctx.gen_opc_pc[lj] = ctx.nip;
+ tcg_ctx.gen_opc_instr_start[lj] = 1;
+ tcg_ctx.gen_opc_icount[lj] = num_insns;
}
LOG_DISAS("----------------\n");
LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n",
@@ -9781,7 +9781,7 @@ static inline void gen_intermediate_code_internal(CPUPPCState *env,
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
lj++;
while (lj <= j)
- gen_opc_instr_start[lj++] = 0;
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
} else {
tb->size = ctx.nip - pc_start;
tb->icount = num_insns;
@@ -9810,5 +9810,5 @@ void gen_intermediate_code_pc (CPUPPCState *env, struct TranslationBlock *tb)
void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb, int pc_pos)
{
- env->nip = gen_opc_pc[pc_pos];
+ env->nip = tcg_ctx.gen_opc_pc[pc_pos];
}
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 993f20752c..787e3c6963 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -5160,13 +5160,13 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
if (lj < j) {
lj++;
while (lj < j) {
- gen_opc_instr_start[lj++] = 0;
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
}
}
- gen_opc_pc[lj] = dc.pc;
+ tcg_ctx.gen_opc_pc[lj] = dc.pc;
gen_opc_cc_op[lj] = dc.cc_op;
- gen_opc_instr_start[lj] = 1;
- gen_opc_icount[lj] = num_insns;
+ tcg_ctx.gen_opc_instr_start[lj] = 1;
+ tcg_ctx.gen_opc_icount[lj] = num_insns;
}
if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
@@ -5212,7 +5212,7 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
lj++;
while (lj <= j) {
- gen_opc_instr_start[lj++] = 0;
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
}
} else {
tb->size = dc.pc - pc_start;
@@ -5240,7 +5240,7 @@ void gen_intermediate_code_pc (CPUS390XState *env, struct TranslationBlock *tb)
void restore_state_to_opc(CPUS390XState *env, TranslationBlock *tb, int pc_pos)
{
int cc_op;
- env->psw.addr = gen_opc_pc[pc_pos];
+ env->psw.addr = tcg_ctx.gen_opc_pc[pc_pos];
cc_op = gen_opc_cc_op[pc_pos];
if ((cc_op != CC_OP_DYNAMIC) && (cc_op != CC_OP_STATIC)) {
env->cc_op = cc_op;
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 5497dede05..86493e1b03 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -2003,12 +2003,12 @@ gen_intermediate_code_internal(CPUSH4State * env, TranslationBlock * tb,
if (ii < i) {
ii++;
while (ii < i)
- gen_opc_instr_start[ii++] = 0;
+ tcg_ctx.gen_opc_instr_start[ii++] = 0;
}
- gen_opc_pc[ii] = ctx.pc;
+ tcg_ctx.gen_opc_pc[ii] = ctx.pc;
gen_opc_hflags[ii] = ctx.flags;
- gen_opc_instr_start[ii] = 1;
- gen_opc_icount[ii] = num_insns;
+ tcg_ctx.gen_opc_instr_start[ii] = 1;
+ tcg_ctx.gen_opc_icount[ii] = num_insns;
}
if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
gen_io_start();
@@ -2061,7 +2061,7 @@ gen_intermediate_code_internal(CPUSH4State * env, TranslationBlock * tb,
i = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
ii++;
while (ii <= i)
- gen_opc_instr_start[ii++] = 0;
+ tcg_ctx.gen_opc_instr_start[ii++] = 0;
} else {
tb->size = ctx.pc - pc_start;
tb->icount = num_insns;
@@ -2088,6 +2088,6 @@ void gen_intermediate_code_pc(CPUSH4State * env, struct TranslationBlock *tb)
void restore_state_to_opc(CPUSH4State *env, TranslationBlock *tb, int pc_pos)
{
- env->pc = gen_opc_pc[pc_pos];
+ env->pc = tcg_ctx.gen_opc_pc[pc_pos];
env->flags = gen_opc_hflags[pc_pos];
}
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 2ae803695b..5859f2e801 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -5283,11 +5283,11 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
if (lj < j) {
lj++;
while (lj < j)
- gen_opc_instr_start[lj++] = 0;
- gen_opc_pc[lj] = dc->pc;
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
+ tcg_ctx.gen_opc_pc[lj] = dc->pc;
gen_opc_npc[lj] = dc->npc;
- gen_opc_instr_start[lj] = 1;
- gen_opc_icount[lj] = num_insns;
+ tcg_ctx.gen_opc_instr_start[lj] = 1;
+ tcg_ctx.gen_opc_icount[lj] = num_insns;
}
}
if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
@@ -5339,7 +5339,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
lj++;
while (lj <= j)
- gen_opc_instr_start[lj++] = 0;
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
#if 0
log_page_dump();
#endif
@@ -5478,7 +5478,7 @@ void gen_intermediate_code_init(CPUSPARCState *env)
void restore_state_to_opc(CPUSPARCState *env, TranslationBlock *tb, int pc_pos)
{
target_ulong npc;
- env->pc = gen_opc_pc[pc_pos];
+ env->pc = tcg_ctx.gen_opc_pc[pc_pos];
npc = gen_opc_npc[pc_pos];
if (npc == 1) {
/* dynamic NPC: already stored */
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
index 052bb45d70..3951758fc8 100644
--- a/target-unicore32/translate.c
+++ b/target-unicore32/translate.c
@@ -2003,12 +2003,12 @@ static inline void gen_intermediate_code_internal(CPUUniCore32State *env,
if (lj < j) {
lj++;
while (lj < j) {
- gen_opc_instr_start[lj++] = 0;
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
}
}
- gen_opc_pc[lj] = dc->pc;
- gen_opc_instr_start[lj] = 1;
- gen_opc_icount[lj] = num_insns;
+ tcg_ctx.gen_opc_pc[lj] = dc->pc;
+ tcg_ctx.gen_opc_instr_start[lj] = 1;
+ tcg_ctx.gen_opc_icount[lj] = num_insns;
}
if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
@@ -2117,7 +2117,7 @@ done_generating:
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
lj++;
while (lj <= j) {
- gen_opc_instr_start[lj++] = 0;
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
}
} else {
tb->size = dc->pc - pc_start;
@@ -2203,5 +2203,5 @@ void cpu_dump_state(CPUUniCore32State *env, FILE *f,
void restore_state_to_opc(CPUUniCore32State *env, TranslationBlock *tb, int pc_pos)
{
- env->regs[31] = gen_opc_pc[pc_pos];
+ env->regs[31] = tcg_ctx.gen_opc_pc[pc_pos];
}
diff --git a/target-xtensa/cpu.c b/target-xtensa/cpu.c
index 9d01983d44..035b07c1c5 100644
--- a/target-xtensa/cpu.c
+++ b/target-xtensa/cpu.c
@@ -48,6 +48,9 @@ static void xtensa_cpu_reset(CPUState *s)
XTENSA_OPTION_INTERRUPT) ? 0x1f : 0x10;
env->sregs[VECBASE] = env->config->vecbase;
env->sregs[IBREAKENABLE] = 0;
+ env->sregs[CACHEATTR] = 0x22222222;
+ env->sregs[ATOMCTL] = xtensa_option_enabled(env->config,
+ XTENSA_OPTION_ATOMCTL) ? 0x28 : 0x15;
env->pending_irq_level = 0;
reset_mmu(env);
diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 74e98883bf..08fd5bc395 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -65,6 +65,7 @@ enum {
XTENSA_OPTION_FP_COPROCESSOR,
XTENSA_OPTION_MP_SYNCHRO,
XTENSA_OPTION_CONDITIONAL_STORE,
+ XTENSA_OPTION_ATOMCTL,
/* Interrupts and exceptions */
XTENSA_OPTION_EXCEPTION,
@@ -93,6 +94,7 @@ enum {
XTENSA_OPTION_REGION_PROTECTION,
XTENSA_OPTION_REGION_TRANSLATION,
XTENSA_OPTION_MMU,
+ XTENSA_OPTION_CACHEATTR,
/* Other */
XTENSA_OPTION_WINDOWED_REGISTER,
@@ -128,6 +130,8 @@ enum {
ITLBCFG = 91,
DTLBCFG = 92,
IBREAKENABLE = 96,
+ CACHEATTR = 98,
+ ATOMCTL = 99,
IBREAKA = 128,
DBREAKA = 144,
DBREAKC = 160,
@@ -149,6 +153,7 @@ enum {
ICOUNTLEVEL = 237,
EXCVADDR = 238,
CCOMPARE = 240,
+ MISC = 244,
};
#define PS_INTLEVEL 0xf
@@ -193,6 +198,14 @@ enum {
#define REGION_PAGE_MASK 0xe0000000
+#define PAGE_CACHE_MASK 0x700
+#define PAGE_CACHE_SHIFT 8
+#define PAGE_CACHE_INVALID 0x000
+#define PAGE_CACHE_BYPASS 0x100
+#define PAGE_CACHE_WT 0x200
+#define PAGE_CACHE_WB 0x400
+#define PAGE_CACHE_ISOLATE 0x600
+
enum {
/* Static vectors */
EXC_RESET,
@@ -404,6 +417,7 @@ void debug_exception_env(CPUXtensaState *new_env, uint32_t cause);
#define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt))
+#define XTENSA_OPTION_ALL (~(uint64_t)0)
static inline bool xtensa_option_bits_enabled(const XtensaConfig *config,
uint64_t opt)
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index d94bae210d..200fb43c28 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -390,6 +390,7 @@ int xtensa_tlb_lookup(const CPUXtensaState *env, uint32_t addr, bool dtlb,
static unsigned mmu_attr_to_access(uint32_t attr)
{
unsigned access = 0;
+
if (attr < 12) {
access |= PAGE_READ;
if (attr & 0x1) {
@@ -398,8 +399,22 @@ static unsigned mmu_attr_to_access(uint32_t attr)
if (attr & 0x2) {
access |= PAGE_WRITE;
}
+
+ switch (attr & 0xc) {
+ case 0:
+ access |= PAGE_CACHE_BYPASS;
+ break;
+
+ case 4:
+ access |= PAGE_CACHE_WB;
+ break;
+
+ case 8:
+ access |= PAGE_CACHE_WT;
+ break;
+ }
} else if (attr == 13) {
- access |= PAGE_READ | PAGE_WRITE;
+ access |= PAGE_READ | PAGE_WRITE | PAGE_CACHE_ISOLATE;
}
return access;
}
@@ -410,14 +425,35 @@ static unsigned mmu_attr_to_access(uint32_t attr)
*/
static unsigned region_attr_to_access(uint32_t attr)
{
- unsigned access = 0;
- if ((attr < 6 && attr != 3) || attr == 14) {
- access |= PAGE_READ | PAGE_WRITE;
- }
- if (attr > 0 && attr < 6) {
- access |= PAGE_EXEC;
- }
- return access;
+ static const unsigned access[16] = {
+ [0] = PAGE_READ | PAGE_WRITE | PAGE_CACHE_WT,
+ [1] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_WT,
+ [2] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_BYPASS,
+ [3] = PAGE_EXEC | PAGE_CACHE_WB,
+ [4] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_WB,
+ [5] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_WB,
+ [14] = PAGE_READ | PAGE_WRITE | PAGE_CACHE_ISOLATE,
+ };
+
+ return access[attr & 0xf];
+}
+
+/*!
+ * Convert cacheattr to PAGE_{READ,WRITE,EXEC} mask.
+ * See ISA, A.2.14 The Cache Attribute Register
+ */
+static unsigned cacheattr_attr_to_access(uint32_t attr)
+{
+ static const unsigned access[16] = {
+ [0] = PAGE_READ | PAGE_WRITE | PAGE_CACHE_WT,
+ [1] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_WT,
+ [2] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_BYPASS,
+ [3] = PAGE_EXEC | PAGE_CACHE_WB,
+ [4] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_WB,
+ [14] = PAGE_READ | PAGE_WRITE | PAGE_CACHE_ISOLATE,
+ };
+
+ return access[attr & 0xf];
}
static bool is_access_granted(unsigned access, int is_write)
@@ -566,7 +602,8 @@ int xtensa_get_physical_addr(CPUXtensaState *env, bool update_tlb,
} else {
*paddr = vaddr;
*page_size = TARGET_PAGE_SIZE;
- *access = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+ *access = cacheattr_attr_to_access(
+ env->sregs[CACHEATTR] >> ((vaddr & 0xe0000000) >> 27));
return 0;
}
}
@@ -599,24 +636,34 @@ static void dump_tlb(FILE *f, fprintf_function cpu_fprintf,
xtensa_tlb_get_entry(env, dtlb, wi, ei);
if (entry->asid) {
+ static const char * const cache_text[8] = {
+ [PAGE_CACHE_BYPASS >> PAGE_CACHE_SHIFT] = "Bypass",
+ [PAGE_CACHE_WT >> PAGE_CACHE_SHIFT] = "WT",
+ [PAGE_CACHE_WB >> PAGE_CACHE_SHIFT] = "WB",
+ [PAGE_CACHE_ISOLATE >> PAGE_CACHE_SHIFT] = "Isolate",
+ };
unsigned access = attr_to_access(entry->attr);
+ unsigned cache_idx = (access & PAGE_CACHE_MASK) >>
+ PAGE_CACHE_SHIFT;
if (print_header) {
print_header = false;
cpu_fprintf(f, "Way %u (%d %s)\n", wi, sz, sz_text);
cpu_fprintf(f,
- "\tVaddr Paddr ASID Attr RWX\n"
- "\t---------- ---------- ---- ---- ---\n");
+ "\tVaddr Paddr ASID Attr RWX Cache\n"
+ "\t---------- ---------- ---- ---- --- -------\n");
}
cpu_fprintf(f,
- "\t0x%08x 0x%08x 0x%02x 0x%02x %c%c%c\n",
+ "\t0x%08x 0x%08x 0x%02x 0x%02x %c%c%c %-7s\n",
entry->vaddr,
entry->paddr,
entry->asid,
entry->attr,
(access & PAGE_READ) ? 'R' : '-',
(access & PAGE_WRITE) ? 'W' : '-',
- (access & PAGE_EXEC) ? 'X' : '-');
+ (access & PAGE_EXEC) ? 'X' : '-',
+ cache_text[cache_idx] ? cache_text[cache_idx] :
+ "Invalid");
}
}
}
diff --git a/target-xtensa/helper.h b/target-xtensa/helper.h
index 1163c09836..5b4cd2700f 100644
--- a/target-xtensa/helper.h
+++ b/target-xtensa/helper.h
@@ -23,6 +23,7 @@ DEF_HELPER_3(waiti, void, env, i32, i32)
DEF_HELPER_3(timer_irq, void, env, i32, i32)
DEF_HELPER_2(advance_ccount, void, env, i32)
DEF_HELPER_1(check_interrupts, void, env)
+DEF_HELPER_3(check_atomctl, void, env, i32, i32)
DEF_HELPER_2(wsr_rasid, void, env, i32)
DEF_HELPER_FLAGS_3(rtlb0, TCG_CALL_NO_RWG_SE, i32, env, i32, i32)
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index ae0c09977b..0e0f21d1a2 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -415,6 +415,63 @@ void HELPER(check_interrupts)(CPUXtensaState *env)
check_interrupts(env);
}
+/*!
+ * Check vaddr accessibility/cache attributes and raise an exception if
+ * specified by the ATOMCTL SR.
+ *
+ * Note: local memory exclusion is not implemented
+ */
+void HELPER(check_atomctl)(CPUXtensaState *env, uint32_t pc, uint32_t vaddr)
+{
+ uint32_t paddr, page_size, access;
+ uint32_t atomctl = env->sregs[ATOMCTL];
+ int rc = xtensa_get_physical_addr(env, true, vaddr, 1,
+ xtensa_get_cring(env), &paddr, &page_size, &access);
+
+ /*
+ * s32c1i never causes LOAD_PROHIBITED_CAUSE exceptions,
+ * see opcode description in the ISA
+ */
+ if (rc == 0 &&
+ (access & (PAGE_READ | PAGE_WRITE)) != (PAGE_READ | PAGE_WRITE)) {
+ rc = STORE_PROHIBITED_CAUSE;
+ }
+
+ if (rc) {
+ HELPER(exception_cause_vaddr)(env, pc, rc, vaddr);
+ }
+
+ /*
+ * When data cache is not configured use ATOMCTL bypass field.
+ * See ISA, 4.3.12.4 The Atomic Operation Control Register (ATOMCTL)
+ * under the Conditional Store Option.
+ */
+ if (!xtensa_option_enabled(env->config, XTENSA_OPTION_DCACHE)) {
+ access = PAGE_CACHE_BYPASS;
+ }
+
+ switch (access & PAGE_CACHE_MASK) {
+ case PAGE_CACHE_WB:
+ atomctl >>= 2;
+ case PAGE_CACHE_WT:
+ atomctl >>= 2;
+ case PAGE_CACHE_BYPASS:
+ if ((atomctl & 0x3) == 0) {
+ HELPER(exception_cause_vaddr)(env, pc,
+ LOAD_STORE_ERROR_CAUSE, vaddr);
+ }
+ break;
+
+ case PAGE_CACHE_ISOLATE:
+ HELPER(exception_cause_vaddr)(env, pc,
+ LOAD_STORE_ERROR_CAUSE, vaddr);
+ break;
+
+ default:
+ break;
+ }
+}
+
void HELPER(wsr_rasid)(CPUXtensaState *env, uint32_t v)
{
v = (v & 0xffffff00) | 0x1;
diff --git a/target-xtensa/overlay_tool.h b/target-xtensa/overlay_tool.h
index e39505316b..dd4f51a7b7 100644
--- a/target-xtensa/overlay_tool.h
+++ b/target-xtensa/overlay_tool.h
@@ -42,6 +42,10 @@
#define XCHAL_VECBASE_RESET_VADDR 0
#endif
+#ifndef XCHAL_HW_MIN_VERSION
+#define XCHAL_HW_MIN_VERSION 0
+#endif
+
#define XCHAL_OPTION(xchal, qemu) ((xchal) ? XTENSA_OPTION_BIT(qemu) : 0)
#define XTENSA_OPTIONS ( \
@@ -62,6 +66,8 @@
XCHAL_OPTION(XCHAL_HAVE_FP, XTENSA_OPTION_FP_COPROCESSOR) | \
XCHAL_OPTION(XCHAL_HAVE_RELEASE_SYNC, XTENSA_OPTION_MP_SYNCHRO) | \
XCHAL_OPTION(XCHAL_HAVE_S32C1I, XTENSA_OPTION_CONDITIONAL_STORE) | \
+ XCHAL_OPTION(XCHAL_HAVE_S32C1I && XCHAL_HW_MIN_VERSION >= 230000, \
+ XTENSA_OPTION_ATOMCTL) | \
/* Interrupts and exceptions */ \
XCHAL_OPTION(XCHAL_HAVE_EXCEPTIONS, XTENSA_OPTION_EXCEPTION) | \
XCHAL_OPTION(XCHAL_HAVE_VECBASE, XTENSA_OPTION_RELOCATABLE_VECTOR) | \
@@ -85,9 +91,13 @@
XCHAL_OPTION(XCHAL_HAVE_XLT_CACHEATTR, \
XTENSA_OPTION_REGION_TRANSLATION) | \
XCHAL_OPTION(XCHAL_HAVE_PTP_MMU, XTENSA_OPTION_MMU) | \
+ XCHAL_OPTION(XCHAL_HAVE_CACHEATTR, XTENSA_OPTION_CACHEATTR) | \
/* Other, TODO */ \
XCHAL_OPTION(XCHAL_HAVE_WINDOWED, XTENSA_OPTION_WINDOWED_REGISTER) | \
- XCHAL_OPTION(XCHAL_HAVE_DEBUG, XTENSA_OPTION_DEBUG))
+ XCHAL_OPTION(XCHAL_HAVE_DEBUG, XTENSA_OPTION_DEBUG) |\
+ XCHAL_OPTION(XCHAL_NUM_MISC_REGS > 0, XTENSA_OPTION_MISC_SR) | \
+ XCHAL_OPTION(XCHAL_HAVE_THREADPTR, XTENSA_OPTION_THREAD_POINTER) | \
+ XCHAL_OPTION(XCHAL_HAVE_PRID, XTENSA_OPTION_PROCESSOR_ID))
#ifndef XCHAL_WINDOW_OF4_VECOFS
#define XCHAL_WINDOW_OF4_VECOFS 0x00000000
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index e5a3f49a75..5d8762c0ca 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -78,76 +78,117 @@ static TCGv_i32 cpu_UR[256];
#include "gen-icount.h"
-static const char * const sregnames[256] = {
- [LBEG] = "LBEG",
- [LEND] = "LEND",
- [LCOUNT] = "LCOUNT",
- [SAR] = "SAR",
- [BR] = "BR",
- [LITBASE] = "LITBASE",
- [SCOMPARE1] = "SCOMPARE1",
- [ACCLO] = "ACCLO",
- [ACCHI] = "ACCHI",
- [MR] = "MR0",
- [MR + 1] = "MR1",
- [MR + 2] = "MR2",
- [MR + 3] = "MR3",
- [WINDOW_BASE] = "WINDOW_BASE",
- [WINDOW_START] = "WINDOW_START",
- [PTEVADDR] = "PTEVADDR",
- [RASID] = "RASID",
- [ITLBCFG] = "ITLBCFG",
- [DTLBCFG] = "DTLBCFG",
- [IBREAKENABLE] = "IBREAKENABLE",
- [IBREAKA] = "IBREAKA0",
- [IBREAKA + 1] = "IBREAKA1",
- [DBREAKA] = "DBREAKA0",
- [DBREAKA + 1] = "DBREAKA1",
- [DBREAKC] = "DBREAKC0",
- [DBREAKC + 1] = "DBREAKC1",
- [EPC1] = "EPC1",
- [EPC1 + 1] = "EPC2",
- [EPC1 + 2] = "EPC3",
- [EPC1 + 3] = "EPC4",
- [EPC1 + 4] = "EPC5",
- [EPC1 + 5] = "EPC6",
- [EPC1 + 6] = "EPC7",
- [DEPC] = "DEPC",
- [EPS2] = "EPS2",
- [EPS2 + 1] = "EPS3",
- [EPS2 + 2] = "EPS4",
- [EPS2 + 3] = "EPS5",
- [EPS2 + 4] = "EPS6",
- [EPS2 + 5] = "EPS7",
- [EXCSAVE1] = "EXCSAVE1",
- [EXCSAVE1 + 1] = "EXCSAVE2",
- [EXCSAVE1 + 2] = "EXCSAVE3",
- [EXCSAVE1 + 3] = "EXCSAVE4",
- [EXCSAVE1 + 4] = "EXCSAVE5",
- [EXCSAVE1 + 5] = "EXCSAVE6",
- [EXCSAVE1 + 6] = "EXCSAVE7",
- [CPENABLE] = "CPENABLE",
- [INTSET] = "INTSET",
- [INTCLEAR] = "INTCLEAR",
- [INTENABLE] = "INTENABLE",
- [PS] = "PS",
- [VECBASE] = "VECBASE",
- [EXCCAUSE] = "EXCCAUSE",
- [DEBUGCAUSE] = "DEBUGCAUSE",
- [CCOUNT] = "CCOUNT",
- [PRID] = "PRID",
- [ICOUNT] = "ICOUNT",
- [ICOUNTLEVEL] = "ICOUNTLEVEL",
- [EXCVADDR] = "EXCVADDR",
- [CCOMPARE] = "CCOMPARE0",
- [CCOMPARE + 1] = "CCOMPARE1",
- [CCOMPARE + 2] = "CCOMPARE2",
+typedef struct XtensaReg {
+ const char *name;
+ uint64_t opt_bits;
+ enum {
+ SR_R = 1,
+ SR_W = 2,
+ SR_X = 4,
+ SR_RW = 3,
+ SR_RWX = 7,
+ } access;
+} XtensaReg;
+
+#define XTENSA_REG_ACCESS(regname, opt, acc) { \
+ .name = (regname), \
+ .opt_bits = XTENSA_OPTION_BIT(opt), \
+ .access = (acc), \
+ }
+
+#define XTENSA_REG(regname, opt) XTENSA_REG_ACCESS(regname, opt, SR_RWX)
+
+#define XTENSA_REG_BITS(regname, opt) { \
+ .name = (regname), \
+ .opt_bits = (opt), \
+ .access = SR_RWX, \
+ }
+
+static const XtensaReg sregnames[256] = {
+ [LBEG] = XTENSA_REG("LBEG", XTENSA_OPTION_LOOP),
+ [LEND] = XTENSA_REG("LEND", XTENSA_OPTION_LOOP),
+ [LCOUNT] = XTENSA_REG("LCOUNT", XTENSA_OPTION_LOOP),
+ [SAR] = XTENSA_REG_BITS("SAR", XTENSA_OPTION_ALL),
+ [BR] = XTENSA_REG("BR", XTENSA_OPTION_BOOLEAN),
+ [LITBASE] = XTENSA_REG("LITBASE", XTENSA_OPTION_EXTENDED_L32R),
+ [SCOMPARE1] = XTENSA_REG("SCOMPARE1", XTENSA_OPTION_CONDITIONAL_STORE),
+ [ACCLO] = XTENSA_REG("ACCLO", XTENSA_OPTION_MAC16),
+ [ACCHI] = XTENSA_REG("ACCHI", XTENSA_OPTION_MAC16),
+ [MR] = XTENSA_REG("MR0", XTENSA_OPTION_MAC16),
+ [MR + 1] = XTENSA_REG("MR1", XTENSA_OPTION_MAC16),
+ [MR + 2] = XTENSA_REG("MR2", XTENSA_OPTION_MAC16),
+ [MR + 3] = XTENSA_REG("MR3", XTENSA_OPTION_MAC16),
+ [WINDOW_BASE] = XTENSA_REG("WINDOW_BASE", XTENSA_OPTION_WINDOWED_REGISTER),
+ [WINDOW_START] = XTENSA_REG("WINDOW_START",
+ XTENSA_OPTION_WINDOWED_REGISTER),
+ [PTEVADDR] = XTENSA_REG("PTEVADDR", XTENSA_OPTION_MMU),
+ [RASID] = XTENSA_REG("RASID", XTENSA_OPTION_MMU),
+ [ITLBCFG] = XTENSA_REG("ITLBCFG", XTENSA_OPTION_MMU),
+ [DTLBCFG] = XTENSA_REG("DTLBCFG", XTENSA_OPTION_MMU),
+ [IBREAKENABLE] = XTENSA_REG("IBREAKENABLE", XTENSA_OPTION_DEBUG),
+ [CACHEATTR] = XTENSA_REG("CACHEATTR", XTENSA_OPTION_CACHEATTR),
+ [ATOMCTL] = XTENSA_REG("ATOMCTL", XTENSA_OPTION_ATOMCTL),
+ [IBREAKA] = XTENSA_REG("IBREAKA0", XTENSA_OPTION_DEBUG),
+ [IBREAKA + 1] = XTENSA_REG("IBREAKA1", XTENSA_OPTION_DEBUG),
+ [DBREAKA] = XTENSA_REG("DBREAKA0", XTENSA_OPTION_DEBUG),
+ [DBREAKA + 1] = XTENSA_REG("DBREAKA1", XTENSA_OPTION_DEBUG),
+ [DBREAKC] = XTENSA_REG("DBREAKC0", XTENSA_OPTION_DEBUG),
+ [DBREAKC + 1] = XTENSA_REG("DBREAKC1", XTENSA_OPTION_DEBUG),
+ [EPC1] = XTENSA_REG("EPC1", XTENSA_OPTION_EXCEPTION),
+ [EPC1 + 1] = XTENSA_REG("EPC2", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+ [EPC1 + 2] = XTENSA_REG("EPC3", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+ [EPC1 + 3] = XTENSA_REG("EPC4", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+ [EPC1 + 4] = XTENSA_REG("EPC5", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+ [EPC1 + 5] = XTENSA_REG("EPC6", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+ [EPC1 + 6] = XTENSA_REG("EPC7", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+ [DEPC] = XTENSA_REG("DEPC", XTENSA_OPTION_EXCEPTION),
+ [EPS2] = XTENSA_REG("EPS2", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+ [EPS2 + 1] = XTENSA_REG("EPS3", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+ [EPS2 + 2] = XTENSA_REG("EPS4", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+ [EPS2 + 3] = XTENSA_REG("EPS5", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+ [EPS2 + 4] = XTENSA_REG("EPS6", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+ [EPS2 + 5] = XTENSA_REG("EPS7", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+ [EXCSAVE1] = XTENSA_REG("EXCSAVE1", XTENSA_OPTION_EXCEPTION),
+ [EXCSAVE1 + 1] = XTENSA_REG("EXCSAVE2",
+ XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+ [EXCSAVE1 + 2] = XTENSA_REG("EXCSAVE3",
+ XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+ [EXCSAVE1 + 3] = XTENSA_REG("EXCSAVE4",
+ XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+ [EXCSAVE1 + 4] = XTENSA_REG("EXCSAVE5",
+ XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+ [EXCSAVE1 + 5] = XTENSA_REG("EXCSAVE6",
+ XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+ [EXCSAVE1 + 6] = XTENSA_REG("EXCSAVE7",
+ XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+ [CPENABLE] = XTENSA_REG("CPENABLE", XTENSA_OPTION_COPROCESSOR),
+ [INTSET] = XTENSA_REG_ACCESS("INTSET", XTENSA_OPTION_INTERRUPT, SR_RW),
+ [INTCLEAR] = XTENSA_REG_ACCESS("INTCLEAR", XTENSA_OPTION_INTERRUPT, SR_W),
+ [INTENABLE] = XTENSA_REG("INTENABLE", XTENSA_OPTION_INTERRUPT),
+ [PS] = XTENSA_REG_BITS("PS", XTENSA_OPTION_ALL),
+ [VECBASE] = XTENSA_REG("VECBASE", XTENSA_OPTION_RELOCATABLE_VECTOR),
+ [EXCCAUSE] = XTENSA_REG("EXCCAUSE", XTENSA_OPTION_EXCEPTION),
+ [DEBUGCAUSE] = XTENSA_REG_ACCESS("DEBUGCAUSE", XTENSA_OPTION_DEBUG, SR_R),
+ [CCOUNT] = XTENSA_REG("CCOUNT", XTENSA_OPTION_TIMER_INTERRUPT),
+ [PRID] = XTENSA_REG_ACCESS("PRID", XTENSA_OPTION_PROCESSOR_ID, SR_R),
+ [ICOUNT] = XTENSA_REG("ICOUNT", XTENSA_OPTION_DEBUG),
+ [ICOUNTLEVEL] = XTENSA_REG("ICOUNTLEVEL", XTENSA_OPTION_DEBUG),
+ [EXCVADDR] = XTENSA_REG("EXCVADDR", XTENSA_OPTION_EXCEPTION),
+ [CCOMPARE] = XTENSA_REG("CCOMPARE0", XTENSA_OPTION_TIMER_INTERRUPT),
+ [CCOMPARE + 1] = XTENSA_REG("CCOMPARE1",
+ XTENSA_OPTION_TIMER_INTERRUPT),
+ [CCOMPARE + 2] = XTENSA_REG("CCOMPARE2",
+ XTENSA_OPTION_TIMER_INTERRUPT),
+ [MISC] = XTENSA_REG("MISC0", XTENSA_OPTION_MISC_SR),
+ [MISC + 1] = XTENSA_REG("MISC1", XTENSA_OPTION_MISC_SR),
+ [MISC + 2] = XTENSA_REG("MISC2", XTENSA_OPTION_MISC_SR),
+ [MISC + 3] = XTENSA_REG("MISC3", XTENSA_OPTION_MISC_SR),
};
-static const char * const uregnames[256] = {
- [THREADPTR] = "THREADPTR",
- [FCR] = "FCR",
- [FSR] = "FSR",
+static const XtensaReg uregnames[256] = {
+ [THREADPTR] = XTENSA_REG("THREADPTR", XTENSA_OPTION_THREAD_POINTER),
+ [FCR] = XTENSA_REG("FCR", XTENSA_OPTION_FP_COPROCESSOR),
+ [FSR] = XTENSA_REG("FSR", XTENSA_OPTION_FP_COPROCESSOR),
};
void xtensa_translate_init(void)
@@ -183,18 +224,18 @@ void xtensa_translate_init(void)
}
for (i = 0; i < 256; ++i) {
- if (sregnames[i]) {
+ if (sregnames[i].name) {
cpu_SR[i] = tcg_global_mem_new_i32(TCG_AREG0,
offsetof(CPUXtensaState, sregs[i]),
- sregnames[i]);
+ sregnames[i].name);
}
}
for (i = 0; i < 256; ++i) {
- if (uregnames[i]) {
+ if (uregnames[i].name) {
cpu_UR[i] = tcg_global_mem_new_i32(TCG_AREG0,
offsetof(CPUXtensaState, uregs[i]),
- uregnames[i]);
+ uregnames[i].name);
}
}
#define GEN_HELPER 2
@@ -450,6 +491,28 @@ static void gen_brcondi(DisasContext *dc, TCGCond cond,
tcg_temp_free(tmp);
}
+static void gen_check_sr(DisasContext *dc, uint32_t sr, unsigned access)
+{
+ if (!xtensa_option_bits_enabled(dc->config, sregnames[sr].opt_bits)) {
+ if (sregnames[sr].name) {
+ qemu_log("SR %s is not configured\n", sregnames[sr].name);
+ } else {
+ qemu_log("SR %d is not implemented\n", sr);
+ }
+ gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
+ } else if (!(sregnames[sr].access & access)) {
+ static const char * const access_text[] = {
+ [SR_R] = "rsr",
+ [SR_W] = "wsr",
+ [SR_X] = "xsr",
+ };
+ assert(access < ARRAY_SIZE(access_text) && access_text[access]);
+ qemu_log("SR %s is not available for %s\n", sregnames[sr].name,
+ access_text[access]);
+ gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
+ }
+}
+
static void gen_rsr_ccount(DisasContext *dc, TCGv_i32 d, uint32_t sr)
{
gen_advance_ccount(dc);
@@ -471,14 +534,10 @@ static void gen_rsr(DisasContext *dc, TCGv_i32 d, uint32_t sr)
[PTEVADDR] = gen_rsr_ptevaddr,
};
- if (sregnames[sr]) {
- if (rsr_handler[sr]) {
- rsr_handler[sr](dc, d, sr);
- } else {
- tcg_gen_mov_i32(d, cpu_SR[sr]);
- }
+ if (rsr_handler[sr]) {
+ rsr_handler[sr](dc, d, sr);
} else {
- qemu_log("RSR %d not implemented, ", sr);
+ tcg_gen_mov_i32(d, cpu_SR[sr]);
}
}
@@ -556,6 +615,11 @@ static void gen_wsr_ibreakenable(DisasContext *dc, uint32_t sr, TCGv_i32 v)
gen_jumpi_check_loop_end(dc, 0);
}
+static void gen_wsr_atomctl(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+ tcg_gen_andi_i32(cpu_SR[sr], v, 0x3f);
+}
+
static void gen_wsr_ibreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v)
{
unsigned id = sr - IBREAKA;
@@ -640,14 +704,6 @@ static void gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v)
gen_jumpi_check_loop_end(dc, -1);
}
-static void gen_wsr_debugcause(DisasContext *dc, uint32_t sr, TCGv_i32 v)
-{
-}
-
-static void gen_wsr_prid(DisasContext *dc, uint32_t sr, TCGv_i32 v)
-{
-}
-
static void gen_wsr_icount(DisasContext *dc, uint32_t sr, TCGv_i32 v)
{
if (dc->icount) {
@@ -693,6 +749,7 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
[ITLBCFG] = gen_wsr_tlbcfg,
[DTLBCFG] = gen_wsr_tlbcfg,
[IBREAKENABLE] = gen_wsr_ibreakenable,
+ [ATOMCTL] = gen_wsr_atomctl,
[IBREAKA] = gen_wsr_ibreaka,
[IBREAKA + 1] = gen_wsr_ibreaka,
[DBREAKA] = gen_wsr_dbreaka,
@@ -704,8 +761,6 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
[INTCLEAR] = gen_wsr_intclear,
[INTENABLE] = gen_wsr_intenable,
[PS] = gen_wsr_ps,
- [DEBUGCAUSE] = gen_wsr_debugcause,
- [PRID] = gen_wsr_prid,
[ICOUNT] = gen_wsr_icount,
[ICOUNTLEVEL] = gen_wsr_icountlevel,
[CCOMPARE] = gen_wsr_ccompare,
@@ -713,14 +768,10 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
[CCOMPARE + 2] = gen_wsr_ccompare,
};
- if (sregnames[sr]) {
- if (wsr_handler[sr]) {
- wsr_handler[sr](dc, sr, s);
- } else {
- tcg_gen_mov_i32(cpu_SR[sr], s);
- }
+ if (wsr_handler[sr]) {
+ wsr_handler[sr](dc, sr, s);
} else {
- qemu_log("WSR %d not implemented, ", sr);
+ tcg_gen_mov_i32(cpu_SR[sr], s);
}
}
@@ -1352,12 +1403,14 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
case 1: /*ABS*/
{
- int label = gen_new_label();
- tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
- tcg_gen_brcondi_i32(
- TCG_COND_GE, cpu_R[RRR_R], 0, label);
- tcg_gen_neg_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
- gen_set_label(label);
+ TCGv_i32 zero = tcg_const_i32(0);
+ TCGv_i32 neg = tcg_temp_new_i32();
+
+ tcg_gen_neg_i32(neg, cpu_R[RRR_T]);
+ tcg_gen_movcond_i32(TCG_COND_GE, cpu_R[RRR_R],
+ cpu_R[RRR_T], zero, cpu_R[RRR_T], neg);
+ tcg_temp_free(neg);
+ tcg_temp_free(zero);
}
break;
@@ -1431,6 +1484,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
case 6: /*XSR*/
{
TCGv_i32 tmp = tcg_temp_new_i32();
+ gen_check_sr(dc, RSR_SR, SR_X);
if (RSR_SR >= 64) {
gen_check_privilege(dc);
}
@@ -1439,9 +1493,6 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
gen_rsr(dc, cpu_R[RRR_T], RSR_SR);
gen_wsr(dc, RSR_SR, tmp);
tcg_temp_free(tmp);
- if (!sregnames[RSR_SR]) {
- TBD();
- }
}
break;
@@ -1664,25 +1715,21 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
case 3: /*RST3*/
switch (OP2) {
case 0: /*RSR*/
+ gen_check_sr(dc, RSR_SR, SR_R);
if (RSR_SR >= 64) {
gen_check_privilege(dc);
}
gen_window_check1(dc, RRR_T);
gen_rsr(dc, cpu_R[RRR_T], RSR_SR);
- if (!sregnames[RSR_SR]) {
- TBD();
- }
break;
case 1: /*WSR*/
+ gen_check_sr(dc, RSR_SR, SR_W);
if (RSR_SR >= 64) {
gen_check_privilege(dc);
}
gen_window_check1(dc, RRR_T);
gen_wsr(dc, RSR_SR, cpu_R[RRR_T]);
- if (!sregnames[RSR_SR]) {
- TBD();
- }
break;
case 2: /*SEXTu*/
@@ -1710,22 +1757,20 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
{
TCGv_i32 tmp1 = tcg_temp_new_i32();
TCGv_i32 tmp2 = tcg_temp_new_i32();
- int label = gen_new_label();
+ TCGv_i32 zero = tcg_const_i32(0);
tcg_gen_sari_i32(tmp1, cpu_R[RRR_S], 24 - RRR_T);
tcg_gen_xor_i32(tmp2, tmp1, cpu_R[RRR_S]);
tcg_gen_andi_i32(tmp2, tmp2, 0xffffffff << (RRR_T + 7));
- tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
- tcg_gen_brcondi_i32(TCG_COND_EQ, tmp2, 0, label);
tcg_gen_sari_i32(tmp1, cpu_R[RRR_S], 31);
- tcg_gen_xori_i32(cpu_R[RRR_R], tmp1,
- 0xffffffff >> (25 - RRR_T));
-
- gen_set_label(label);
+ tcg_gen_xori_i32(tmp1, tmp1, 0xffffffff >> (25 - RRR_T));
+ tcg_gen_movcond_i32(TCG_COND_EQ, cpu_R[RRR_R], tmp2, zero,
+ cpu_R[RRR_S], tmp1);
tcg_temp_free(tmp1);
tcg_temp_free(tmp2);
+ tcg_temp_free(zero);
}
break;
@@ -1742,19 +1787,9 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
TCG_COND_LEU,
TCG_COND_GEU
};
- int label = gen_new_label();
-
- if (RRR_R != RRR_T) {
- tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
- tcg_gen_brcond_i32(cond[OP2 - 4],
- cpu_R[RRR_S], cpu_R[RRR_T], label);
- tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
- } else {
- tcg_gen_brcond_i32(cond[OP2 - 4],
- cpu_R[RRR_T], cpu_R[RRR_S], label);
- tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
- }
- gen_set_label(label);
+ tcg_gen_movcond_i32(cond[OP2 - 4], cpu_R[RRR_R],
+ cpu_R[RRR_S], cpu_R[RRR_T],
+ cpu_R[RRR_S], cpu_R[RRR_T]);
}
break;
@@ -1765,15 +1800,16 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
{
static const TCGCond cond[] = {
- TCG_COND_NE,
TCG_COND_EQ,
+ TCG_COND_NE,
+ TCG_COND_LT,
TCG_COND_GE,
- TCG_COND_LT
};
- int label = gen_new_label();
- tcg_gen_brcondi_i32(cond[OP2 - 8], cpu_R[RRR_T], 0, label);
- tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
- gen_set_label(label);
+ TCGv_i32 zero = tcg_const_i32(0);
+
+ tcg_gen_movcond_i32(cond[OP2 - 8], cpu_R[RRR_R],
+ cpu_R[RRR_T], zero, cpu_R[RRR_S], cpu_R[RRR_R]);
+ tcg_temp_free(zero);
}
break;
@@ -1782,16 +1818,16 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
HAS_OPTION(XTENSA_OPTION_BOOLEAN);
gen_window_check2(dc, RRR_R, RRR_S);
{
- int label = gen_new_label();
+ TCGv_i32 zero = tcg_const_i32(0);
TCGv_i32 tmp = tcg_temp_new_i32();
tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << RRR_T);
- tcg_gen_brcondi_i32(
- OP2 & 1 ? TCG_COND_EQ : TCG_COND_NE,
- tmp, 0, label);
- tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
- gen_set_label(label);
+ tcg_gen_movcond_i32(OP2 & 1 ? TCG_COND_NE : TCG_COND_EQ,
+ cpu_R[RRR_R], tmp, zero,
+ cpu_R[RRR_S], cpu_R[RRR_R]);
+
tcg_temp_free(tmp);
+ tcg_temp_free(zero);
}
break;
@@ -1799,7 +1835,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
gen_window_check1(dc, RRR_R);
{
int st = (RRR_S << 4) + RRR_T;
- if (uregnames[st]) {
+ if (uregnames[st].name) {
tcg_gen_mov_i32(cpu_R[RRR_R], cpu_UR[st]);
} else {
qemu_log("RUR %d not implemented, ", st);
@@ -1810,7 +1846,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
case 15: /*WUR*/
gen_window_check1(dc, RRR_T);
- if (uregnames[RSR_SR]) {
+ if (uregnames[RSR_SR].name) {
gen_wur(RSR_SR, cpu_R[RRR_T]);
} else {
qemu_log("WUR %d not implemented, ", RSR_SR);
@@ -2082,15 +2118,16 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
gen_check_cpenable(dc, 0);
{
static const TCGCond cond[] = {
- TCG_COND_NE,
TCG_COND_EQ,
+ TCG_COND_NE,
+ TCG_COND_LT,
TCG_COND_GE,
- TCG_COND_LT
};
- int label = gen_new_label();
- tcg_gen_brcondi_i32(cond[OP2 - 8], cpu_R[RRR_T], 0, label);
- tcg_gen_mov_i32(cpu_FR[RRR_R], cpu_FR[RRR_S]);
- gen_set_label(label);
+ TCGv_i32 zero = tcg_const_i32(0);
+
+ tcg_gen_movcond_i32(cond[OP2 - 8], cpu_FR[RRR_R],
+ cpu_R[RRR_T], zero, cpu_FR[RRR_S], cpu_FR[RRR_R]);
+ tcg_temp_free(zero);
}
break;
@@ -2099,16 +2136,16 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
HAS_OPTION(XTENSA_OPTION_BOOLEAN);
gen_check_cpenable(dc, 0);
{
- int label = gen_new_label();
+ TCGv_i32 zero = tcg_const_i32(0);
TCGv_i32 tmp = tcg_temp_new_i32();
tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << RRR_T);
- tcg_gen_brcondi_i32(
- OP2 & 1 ? TCG_COND_EQ : TCG_COND_NE,
- tmp, 0, label);
- tcg_gen_mov_i32(cpu_FR[RRR_R], cpu_FR[RRR_S]);
- gen_set_label(label);
+ tcg_gen_movcond_i32(OP2 & 1 ? TCG_COND_NE : TCG_COND_EQ,
+ cpu_FR[RRR_R], tmp, zero,
+ cpu_FR[RRR_S], cpu_FR[RRR_R]);
+
tcg_temp_free(tmp);
+ tcg_temp_free(zero);
}
break;
@@ -2317,10 +2354,15 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
int label = gen_new_label();
TCGv_i32 tmp = tcg_temp_local_new_i32();
TCGv_i32 addr = tcg_temp_local_new_i32();
+ TCGv_i32 tpc;
tcg_gen_mov_i32(tmp, cpu_R[RRI8_T]);
tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2);
gen_load_store_alignment(dc, 2, addr, true);
+
+ gen_advance_ccount(dc);
+ tpc = tcg_const_i32(dc->pc);
+ gen_helper_check_atomctl(cpu_env, tpc, addr);
tcg_gen_qemu_ld32u(cpu_R[RRI8_T], addr, dc->cring);
tcg_gen_brcond_i32(TCG_COND_NE, cpu_R[RRI8_T],
cpu_SR[SCOMPARE1], label);
@@ -2328,6 +2370,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
tcg_gen_qemu_st32(tmp, addr, dc->cring);
gen_set_label(label);
+ tcg_temp_free(tpc);
tcg_temp_free(addr);
tcg_temp_free(tmp);
}
@@ -2897,12 +2940,12 @@ static void gen_intermediate_code_internal(
if (lj < j) {
lj++;
while (lj < j) {
- gen_opc_instr_start[lj++] = 0;
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
}
}
- gen_opc_pc[lj] = dc.pc;
- gen_opc_instr_start[lj] = 1;
- gen_opc_icount[lj] = insn_count;
+ tcg_ctx.gen_opc_pc[lj] = dc.pc;
+ tcg_ctx.gen_opc_instr_start[lj] = 1;
+ tcg_ctx.gen_opc_icount[lj] = insn_count;
}
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
@@ -2986,8 +3029,8 @@ void cpu_dump_state(CPUXtensaState *env, FILE *f, fprintf_function cpu_fprintf,
cpu_fprintf(f, "PC=%08x\n\n", env->pc);
for (i = j = 0; i < 256; ++i) {
- if (sregnames[i]) {
- cpu_fprintf(f, "%s=%08x%c", sregnames[i], env->sregs[i],
+ if (xtensa_option_bits_enabled(env->config, sregnames[i].opt_bits)) {
+ cpu_fprintf(f, "%12s=%08x%c", sregnames[i].name, env->sregs[i],
(j++ % 4) == 3 ? '\n' : ' ');
}
}
@@ -2995,8 +3038,8 @@ void cpu_dump_state(CPUXtensaState *env, FILE *f, fprintf_function cpu_fprintf,
cpu_fprintf(f, (j % 4) == 0 ? "\n" : "\n\n");
for (i = j = 0; i < 256; ++i) {
- if (uregnames[i]) {
- cpu_fprintf(f, "%s=%08x%c", uregnames[i], env->uregs[i],
+ if (xtensa_option_bits_enabled(env->config, uregnames[i].opt_bits)) {
+ cpu_fprintf(f, "%s=%08x%c", uregnames[i].name, env->uregs[i],
(j++ % 4) == 3 ? '\n' : ' ');
}
}
@@ -3004,7 +3047,7 @@ void cpu_dump_state(CPUXtensaState *env, FILE *f, fprintf_function cpu_fprintf,
cpu_fprintf(f, (j % 4) == 0 ? "\n" : "\n\n");
for (i = 0; i < 16; ++i) {
- cpu_fprintf(f, "A%02d=%08x%c", i, env->regs[i],
+ cpu_fprintf(f, " A%02d=%08x%c", i, env->regs[i],
(i % 4) == 3 ? '\n' : ' ');
}
@@ -3028,5 +3071,5 @@ void cpu_dump_state(CPUXtensaState *env, FILE *f, fprintf_function cpu_fprintf,
void restore_state_to_opc(CPUXtensaState *env, TranslationBlock *tb, int pc_pos)
{
- env->pc = gen_opc_pc[pc_pos];
+ env->pc = tcg_ctx.gen_opc_pc[pc_pos];
}
diff --git a/tcg/tcg.h b/tcg/tcg.h
index e7de8c00a3..b2e2a25653 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -455,6 +455,9 @@ struct TCGContext {
uint16_t *gen_opc_ptr;
TCGArg *gen_opparam_ptr;
+ target_ulong gen_opc_pc[OPC_BUF_SIZE];
+ uint16_t gen_opc_icount[OPC_BUF_SIZE];
+ uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
#if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU)
/* labels info for qemu_ld/st IRs
diff --git a/tests/tcg/xtensa/Makefile b/tests/tcg/xtensa/Makefile
index 0ff0ccfb8c..002fd871d9 100644
--- a/tests/tcg/xtensa/Makefile
+++ b/tests/tcg/xtensa/Makefile
@@ -42,9 +42,11 @@ endif
TESTCASES += test_quo.tst
TESTCASES += test_rem.tst
TESTCASES += test_rst0.tst
+TESTCASES += test_s32c1i.tst
TESTCASES += test_sar.tst
TESTCASES += test_sext.tst
TESTCASES += test_shift.tst
+TESTCASES += test_sr.tst
TESTCASES += test_timer.tst
TESTCASES += test_windowed.tst
diff --git a/tests/tcg/xtensa/macros.inc b/tests/tcg/xtensa/macros.inc
index 23bf3e96c8..c9be1ce516 100644
--- a/tests/tcg/xtensa/macros.inc
+++ b/tests/tcg/xtensa/macros.inc
@@ -1,7 +1,7 @@
.macro test_suite name
.data
status: .word result
-result: .space 20
+result: .space 256
.text
.global main
.align 4
diff --git a/tests/tcg/xtensa/test_s32c1i.S b/tests/tcg/xtensa/test_s32c1i.S
new file mode 100644
index 0000000000..4536015a84
--- /dev/null
+++ b/tests/tcg/xtensa/test_s32c1i.S
@@ -0,0 +1,39 @@
+.include "macros.inc"
+
+test_suite s32c1i
+
+test s32c1i_nowrite
+ movi a2, 1f
+ movi a3, 1
+ wsr a3, scompare1
+ movi a1, 2
+ s32c1i a1, a2, 0
+ assert ne, a1, a3
+ l32i a1, a2, 0
+ assert eqi, a1, 3
+
+.data
+.align 4
+1:
+ .word 3
+.text
+test_end
+
+test s32c1i_write
+ movi a2, 1f
+ movi a3, 3
+ wsr a3, scompare1
+ movi a1, 2
+ s32c1i a1, a2, 0
+ assert eq, a1, a3
+ l32i a1, a2, 0
+ assert eqi, a1, 2
+
+.data
+.align 4
+1:
+ .word 3
+.text
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_sr.S b/tests/tcg/xtensa/test_sr.S
new file mode 100644
index 0000000000..470c03dae2
--- /dev/null
+++ b/tests/tcg/xtensa/test_sr.S
@@ -0,0 +1,90 @@
+.include "macros.inc"
+
+test_suite sr
+
+.macro sr_op sym, op_sym, op_byte, sr
+ .if \sym
+ \op_sym a4, \sr
+ .else
+ .byte 0x40, \sr, \op_byte
+ .endif
+.endm
+
+.macro test_sr_op sym, mask, op, op_byte, sr
+ movi a4, 0
+ .if (\mask)
+ set_vector kernel, 0
+ sr_op \sym, \op, \op_byte, \sr
+ .else
+ set_vector kernel, 2f
+1:
+ sr_op \sym, \op, \op_byte, \sr
+ test_fail
+2:
+ reset_ps
+ rsr a2, exccause
+ assert eqi, a2, 0
+ rsr a2, epc1
+ movi a3, 1b
+ assert eq, a2, a3
+ .endif
+.endm
+
+.macro test_sr_mask sr, sym, mask
+test \sr
+ test_sr_op \sym, \mask & 1, rsr, 0x03, \sr
+ test_sr_op \sym, \mask & 2, wsr, 0x13, \sr
+ test_sr_op \sym, \mask & 4, xsr, 0x61, \sr
+test_end
+.endm
+
+.macro test_sr sr, conf
+ test_sr_mask \sr, \conf, 7
+.endm
+
+test_sr acchi, 1
+test_sr acclo, 1
+test_sr_mask /*atomctl*/99, 0, 0
+test_sr_mask /*br*/4, 0, 0
+test_sr_mask /*cacheattr*/98, 0, 0
+test_sr ccompare0, 1
+test_sr ccount, 1
+test_sr cpenable, 1
+test_sr dbreaka0, 1
+test_sr dbreakc0, 1
+test_sr_mask debugcause, 1, 1
+test_sr depc, 1
+test_sr dtlbcfg, 1
+test_sr epc1, 1
+test_sr epc2, 1
+test_sr eps2, 1
+test_sr exccause, 1
+test_sr excsave1, 1
+test_sr excsave2, 1
+test_sr excvaddr, 1
+test_sr ibreaka0, 1
+test_sr ibreakenable, 1
+test_sr icount, 1
+test_sr icountlevel, 1
+test_sr_mask /*intclear*/227, 0, 2
+test_sr_mask /*interrupt*/226, 0, 3
+test_sr intenable, 1
+test_sr itlbcfg, 1
+test_sr lbeg, 1
+test_sr lcount, 1
+test_sr lend, 1
+test_sr litbase, 1
+test_sr m0, 1
+test_sr misc0, 1
+test_sr_mask /*prefctl*/40, 0, 0
+test_sr_mask /*prid*/235, 0, 1
+test_sr ps, 1
+test_sr ptevaddr, 1
+test_sr rasid, 1
+test_sr sar, 1
+test_sr scompare1, 1
+test_sr vecbase, 1
+test_sr windowbase, 1
+test_sr windowstart, 1
+
+test_suite_end
diff --git a/translate-all.c b/translate-all.c
index d9c2e57861..f22e3eedd2 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -33,10 +33,6 @@
/* code generation context */
TCGContext tcg_ctx;
-target_ulong gen_opc_pc[OPC_BUF_SIZE];
-uint16_t gen_opc_icount[OPC_BUF_SIZE];
-uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
-
void cpu_gen_init(void)
{
tcg_context_init(&tcg_ctx);
@@ -146,9 +142,10 @@ int cpu_restore_state(TranslationBlock *tb,
if (j < 0)
return -1;
/* now find start of instruction before */
- while (gen_opc_instr_start[j] == 0)
+ while (s->gen_opc_instr_start[j] == 0) {
j--;
- env->icount_decr.u16.low -= gen_opc_icount[j];
+ }
+ env->icount_decr.u16.low -= s->gen_opc_icount[j];
restore_state_to_opc(env, tb, j);
diff --git a/ui/curses.c b/ui/curses.c
index b40b22307d..5dc0b2c95f 100644
--- a/ui/curses.c
+++ b/ui/curses.c
@@ -28,10 +28,6 @@
#include <termios.h>
#endif
-#ifdef __OpenBSD__
-#define resize_term resizeterm
-#endif
-
#include "qemu-common.h"
#include "console.h"
#include "sysemu.h"