Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging

* KVM error improvement from Laurent
* CONFIG_PARALLEL fix from Mirek
* Atomic/optimized dirty bitmap access from myself and Stefan
* BUILD_DIR convenience/bugfix from Peter C
* Memory leak fix from Shannon
* SMM improvements (though still TCG only) from myself and Gerd, acked by mst

# gpg: Signature made Fri Jun  5 18:45:20 2015 BST using RSA key ID 78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>"
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg:          It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4  E2F7 7E15 100C CD36 69B1
#      Subkey fingerprint: F133 3857 4B66 2389 866C  7682 BFFB D25F 78C7 AE83

* remotes/bonzini/tags/for-upstream: (62 commits)
  update Linux headers from kvm/next
  atomics: add explicit compiler fence in __atomic memory barriers
  ich9: implement SMI_LOCK
  q35: implement TSEG
  q35: add test for SMRAM.D_LCK
  q35: implement SMRAM.D_LCK
  q35: add config space wmask for SMRAM and ESMRAMC
  q35: fix ESMRAMC default
  q35: implement high SMRAM
  hw/i386: remove smram_update
  target-i386: use memory API to implement SMRAM
  hw/i386: add a separate region that tracks the SMRAME bit
  target-i386: create a separate AddressSpace for each CPU
  vl: run "late" notifiers immediately
  qom: add object_property_add_const_link
  vl: allow full-blown QemuOpts syntax for -global
  pflash_cfi01: add secure property
  pflash_cfi01: change to new-style MMIO accessors
  pflash_cfi01: change big-endian property to BIT type
  target-i386: wake up processors that receive an SMI
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell
2015-06-08 15:57:41 +01:00
75 changed files with 1548 additions and 1043 deletions
+2
View File
@@ -1,5 +1,7 @@
# -*- Mode: makefile -*-
BUILD_DIR?=$(CURDIR)/..
include ../config-host.mak
include config-target.mak
include config-devices.mak
+2 -44
View File
@@ -609,52 +609,10 @@ ram_addr_t migration_bitmap_find_and_reset_dirty(MemoryRegion *mr,
return (next - base) << TARGET_PAGE_BITS;
}
static inline bool migration_bitmap_set_dirty(ram_addr_t addr)
{
bool ret;
int nr = addr >> TARGET_PAGE_BITS;
ret = test_and_set_bit(nr, migration_bitmap);
if (!ret) {
migration_dirty_pages++;
}
return ret;
}
static void migration_bitmap_sync_range(ram_addr_t start, ram_addr_t length)
{
ram_addr_t addr;
unsigned long page = BIT_WORD(start >> TARGET_PAGE_BITS);
/* start address is aligned at the start of a word? */
if (((page * BITS_PER_LONG) << TARGET_PAGE_BITS) == start) {
int k;
int nr = BITS_TO_LONGS(length >> TARGET_PAGE_BITS);
unsigned long *src = ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION];
for (k = page; k < page + nr; k++) {
if (src[k]) {
unsigned long new_dirty;
new_dirty = ~migration_bitmap[k];
migration_bitmap[k] |= src[k];
new_dirty &= src[k];
migration_dirty_pages += ctpopl(new_dirty);
src[k] = 0;
}
}
} else {
for (addr = 0; addr < length; addr += TARGET_PAGE_SIZE) {
if (cpu_physical_memory_get_dirty(start + addr,
TARGET_PAGE_SIZE,
DIRTY_MEMORY_MIGRATION)) {
cpu_physical_memory_reset_dirty(start + addr,
TARGET_PAGE_SIZE,
DIRTY_MEMORY_MIGRATION);
migration_bitmap_set_dirty(start + addr);
}
}
}
migration_dirty_pages +=
cpu_physical_memory_sync_dirty_bitmap(migration_bitmap, start, length);
}
-4
View File
@@ -108,10 +108,6 @@ void cpu_list_unlock(void)
/***********************************************************/
/* CPUX86 core interface */
void cpu_smm_update(CPUX86State *env)
{
}
uint64_t cpu_get_tsc(CPUX86State *env)
{
return cpu_get_real_ticks();
+58 -26
View File
@@ -105,6 +105,7 @@ static bool all_cpu_threads_idle(void)
/* Protected by TimersState seqlock */
static bool icount_sleep = true;
static int64_t vm_clock_warp_start = -1;
/* Conversion factor from emulated instructions to virtual clock ticks. */
static int icount_time_shift;
@@ -393,15 +394,18 @@ void qemu_clock_warp(QEMUClockType type)
return;
}
/*
* If the CPUs have been sleeping, advance QEMU_CLOCK_VIRTUAL timer now.
* This ensures that the deadline for the timer is computed correctly below.
* This also makes sure that the insn counter is synchronized before the
* CPU starts running, in case the CPU is woken by an event other than
* the earliest QEMU_CLOCK_VIRTUAL timer.
*/
icount_warp_rt(NULL);
timer_del(icount_warp_timer);
if (icount_sleep) {
/*
* If the CPUs have been sleeping, advance QEMU_CLOCK_VIRTUAL timer now.
* This ensures that the deadline for the timer is computed correctly
* below.
* This also makes sure that the insn counter is synchronized before
* the CPU starts running, in case the CPU is woken by an event other
* than the earliest QEMU_CLOCK_VIRTUAL timer.
*/
icount_warp_rt(NULL);
timer_del(icount_warp_timer);
}
if (!all_cpu_threads_idle()) {
return;
}
@@ -415,6 +419,11 @@ void qemu_clock_warp(QEMUClockType type)
clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT);
deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
if (deadline < 0) {
static bool notified;
if (!icount_sleep && !notified) {
error_report("WARNING: icount sleep disabled and no active timers");
notified = true;
}
return;
}
@@ -425,23 +434,35 @@ void qemu_clock_warp(QEMUClockType type)
* interrupt to wake it up, but the interrupt never comes because
* the vCPU isn't running any insns and thus doesn't advance the
* QEMU_CLOCK_VIRTUAL.
*
* An extreme solution for this problem would be to never let VCPUs
* sleep in icount mode if there is a pending QEMU_CLOCK_VIRTUAL
* timer; rather time could just advance to the next QEMU_CLOCK_VIRTUAL
* event. Instead, we do stop VCPUs and only advance QEMU_CLOCK_VIRTUAL
* after some "real" time, (related to the time left until the next
* event) has passed. The QEMU_CLOCK_VIRTUAL_RT clock will do this.
* This avoids that the warps are visible externally; for example,
* you will not be sending network packets continuously instead of
* every 100ms.
*/
seqlock_write_lock(&timers_state.vm_clock_seqlock);
if (vm_clock_warp_start == -1 || vm_clock_warp_start > clock) {
vm_clock_warp_start = clock;
if (!icount_sleep) {
/*
* We never let VCPUs sleep in no sleep icount mode.
* If there is a pending QEMU_CLOCK_VIRTUAL timer we just advance
* to the next QEMU_CLOCK_VIRTUAL event and notify it.
* It is useful when we want a deterministic execution time,
* isolated from host latencies.
*/
seqlock_write_lock(&timers_state.vm_clock_seqlock);
timers_state.qemu_icount_bias += deadline;
seqlock_write_unlock(&timers_state.vm_clock_seqlock);
qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
} else {
/*
* We do stop VCPUs and only advance QEMU_CLOCK_VIRTUAL after some
* "real" time, (related to the time left until the next event) has
* passed. The QEMU_CLOCK_VIRTUAL_RT clock will do this.
* This avoids that the warps are visible externally; for example,
* you will not be sending network packets continuously instead of
* every 100ms.
*/
seqlock_write_lock(&timers_state.vm_clock_seqlock);
if (vm_clock_warp_start == -1 || vm_clock_warp_start > clock) {
vm_clock_warp_start = clock;
}
seqlock_write_unlock(&timers_state.vm_clock_seqlock);
timer_mod_anticipate(icount_warp_timer, clock + deadline);
}
seqlock_write_unlock(&timers_state.vm_clock_seqlock);
timer_mod_anticipate(icount_warp_timer, clock + deadline);
} else if (deadline == 0) {
qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
}
@@ -504,9 +525,18 @@ void configure_icount(QemuOpts *opts, Error **errp)
}
return;
}
icount_sleep = qemu_opt_get_bool(opts, "sleep", true);
if (icount_sleep) {
icount_warp_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT,
icount_warp_rt, NULL);
}
icount_align_option = qemu_opt_get_bool(opts, "align", false);
icount_warp_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT,
icount_warp_rt, NULL);
if (icount_align_option && !icount_sleep) {
error_setg(errp, "align=on and sleep=no are incompatible");
}
if (strcmp(option, "auto") != 0) {
errno = 0;
icount_time_shift = strtol(option, &rem_str, 0);
@@ -517,6 +547,8 @@ void configure_icount(QemuOpts *opts, Error **errp)
return;
} else if (icount_align_option) {
error_setg(errp, "shift=auto and align=on are incompatible");
} else if (!icount_sleep) {
error_setg(errp, "shift=auto and sleep=no are incompatible");
}
use_icount = 2;
+3 -4
View File
@@ -125,14 +125,13 @@ void tlb_flush_page(CPUState *cpu, target_ulong addr)
can be detected */
void tlb_protect_code(ram_addr_t ram_addr)
{
cpu_physical_memory_reset_dirty(ram_addr, TARGET_PAGE_SIZE,
DIRTY_MEMORY_CODE);
cpu_physical_memory_test_and_clear_dirty(ram_addr, TARGET_PAGE_SIZE,
DIRTY_MEMORY_CODE);
}
/* update the TLB so that writes in physical page 'phys_addr' are no longer
tested for self modifying code */
void tlb_unprotect_code_phys(CPUState *cpu, ram_addr_t ram_addr,
target_ulong vaddr)
void tlb_unprotect_code(ram_addr_t ram_addr)
{
cpu_physical_memory_set_dirty_flag(ram_addr, DIRTY_MEMORY_CODE);
}
+58 -65
View File
@@ -59,8 +59,6 @@
//#define DEBUG_SUBPAGE
#if !defined(CONFIG_USER_ONLY)
static bool in_migration;
/* ram_list is read under rcu_read_lock()/rcu_read_unlock(). Writes
* are protected by the ramlist lock.
*/
@@ -173,17 +171,22 @@ static void phys_map_node_reserve(PhysPageMap *map, unsigned nodes)
}
}
static uint32_t phys_map_node_alloc(PhysPageMap *map)
static uint32_t phys_map_node_alloc(PhysPageMap *map, bool leaf)
{
unsigned i;
uint32_t ret;
PhysPageEntry e;
PhysPageEntry *p;
ret = map->nodes_nb++;
p = map->nodes[ret];
assert(ret != PHYS_MAP_NODE_NIL);
assert(ret != map->nodes_nb_alloc);
e.skip = leaf ? 0 : 1;
e.ptr = leaf ? PHYS_SECTION_UNASSIGNED : PHYS_MAP_NODE_NIL;
for (i = 0; i < P_L2_SIZE; ++i) {
map->nodes[ret][i].skip = 1;
map->nodes[ret][i].ptr = PHYS_MAP_NODE_NIL;
memcpy(&p[i], &e, sizeof(e));
}
return ret;
}
@@ -193,21 +196,12 @@ static void phys_page_set_level(PhysPageMap *map, PhysPageEntry *lp,
int level)
{
PhysPageEntry *p;
int i;
hwaddr step = (hwaddr)1 << (level * P_L2_BITS);
if (lp->skip && lp->ptr == PHYS_MAP_NODE_NIL) {
lp->ptr = phys_map_node_alloc(map);
p = map->nodes[lp->ptr];
if (level == 0) {
for (i = 0; i < P_L2_SIZE; i++) {
p[i].skip = 0;
p[i].ptr = PHYS_SECTION_UNASSIGNED;
}
}
} else {
p = map->nodes[lp->ptr];
lp->ptr = phys_map_node_alloc(map, level == 0);
}
p = map->nodes[lp->ptr];
lp = &p[(*index >> (level * P_L2_BITS)) & (P_L2_SIZE - 1)];
while (*nb && lp < &p[P_L2_SIZE]) {
@@ -858,21 +852,27 @@ static void tlb_reset_dirty_range_all(ram_addr_t start, ram_addr_t length)
}
/* Note: start and end must be within the same ram block. */
void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t length,
unsigned client)
bool cpu_physical_memory_test_and_clear_dirty(ram_addr_t start,
ram_addr_t length,
unsigned client)
{
if (length == 0)
return;
cpu_physical_memory_clear_dirty_range_type(start, length, client);
unsigned long end, page;
bool dirty;
if (tcg_enabled()) {
if (length == 0) {
return false;
}
end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS;
page = start >> TARGET_PAGE_BITS;
dirty = bitmap_test_and_clear_atomic(ram_list.dirty_memory[client],
page, end - page);
if (dirty && tcg_enabled()) {
tlb_reset_dirty_range_all(start, length);
}
}
static void cpu_physical_memory_set_dirty_tracking(bool enable)
{
in_migration = enable;
return dirty;
}
/* Called from RCU critical section */
@@ -1362,7 +1362,8 @@ int qemu_ram_resize(ram_addr_t base, ram_addr_t newsize, Error **errp)
cpu_physical_memory_clear_dirty_range(block->offset, block->used_length);
block->used_length = newsize;
cpu_physical_memory_set_dirty_range(block->offset, block->used_length);
cpu_physical_memory_set_dirty_range(block->offset, block->used_length,
DIRTY_CLIENTS_ALL);
memory_region_set_size(block->mr, newsize);
if (block->resized) {
block->resized(block->idstr, newsize, block->host);
@@ -1436,7 +1437,8 @@ static ram_addr_t ram_block_add(RAMBlock *new_block, Error **errp)
}
}
cpu_physical_memory_set_dirty_range(new_block->offset,
new_block->used_length);
new_block->used_length,
DIRTY_CLIENTS_ALL);
if (new_block->host) {
qemu_ram_setup_dump(new_block->host, new_block->max_length);
@@ -1824,7 +1826,11 @@ static void notdirty_mem_write(void *opaque, hwaddr ram_addr,
default:
abort();
}
cpu_physical_memory_set_dirty_range_nocode(ram_addr, size);
/* Set both VGA and migration bits for simplicity and to remove
* the notdirty callback faster.
*/
cpu_physical_memory_set_dirty_range(ram_addr, size,
DIRTY_CLIENTS_NOCODE);
/* we remove the notdirty callback only if the code has been
flushed */
if (!cpu_physical_memory_is_clean(ram_addr)) {
@@ -2165,22 +2171,6 @@ static void tcg_commit(MemoryListener *listener)
}
}
static void core_log_global_start(MemoryListener *listener)
{
cpu_physical_memory_set_dirty_tracking(true);
}
static void core_log_global_stop(MemoryListener *listener)
{
cpu_physical_memory_set_dirty_tracking(false);
}
static MemoryListener core_memory_listener = {
.log_global_start = core_log_global_start,
.log_global_stop = core_log_global_stop,
.priority = 1,
};
void address_space_init_dispatch(AddressSpace *as)
{
as->dispatch = NULL;
@@ -2220,8 +2210,6 @@ static void memory_map_init(void)
memory_region_init_io(system_io, NULL, &unassigned_io_ops, NULL, "io",
65536);
address_space_init(&address_space_io, system_io, "I/O");
memory_listener_register(&core_memory_listener, &address_space_memory);
}
MemoryRegion *get_system_memory(void)
@@ -2279,14 +2267,23 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
#else
static void invalidate_and_set_dirty(hwaddr addr,
static void invalidate_and_set_dirty(MemoryRegion *mr, hwaddr addr,
hwaddr length)
{
if (cpu_physical_memory_range_includes_clean(addr, length)) {
tb_invalidate_phys_range(addr, addr + length, 0);
cpu_physical_memory_set_dirty_range_nocode(addr, length);
uint8_t dirty_log_mask = memory_region_get_dirty_log_mask(mr);
/* No early return if dirty_log_mask is or becomes 0, because
* cpu_physical_memory_set_dirty_range will still call
* xen_modified_memory.
*/
if (dirty_log_mask) {
dirty_log_mask =
cpu_physical_memory_range_includes_clean(addr, length, dirty_log_mask);
}
xen_modified_memory(addr, length);
if (dirty_log_mask & (1 << DIRTY_MEMORY_CODE)) {
tb_invalidate_phys_range(addr, addr + length);
dirty_log_mask &= ~(1 << DIRTY_MEMORY_CODE);
}
cpu_physical_memory_set_dirty_range(addr, length, dirty_log_mask);
}
static int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr)
@@ -2371,7 +2368,7 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
/* RAM case */
ptr = qemu_get_ram_ptr(addr1);
memcpy(ptr, buf, l);
invalidate_and_set_dirty(addr1, l);
invalidate_and_set_dirty(mr, addr1, l);
}
} else {
if (!memory_access_is_direct(mr, is_write)) {
@@ -2468,7 +2465,7 @@ static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as,
switch (type) {
case WRITE_DATA:
memcpy(ptr, buf, l);
invalidate_and_set_dirty(addr1, l);
invalidate_and_set_dirty(mr, addr1, l);
break;
case FLUSH_CACHE:
flush_icache_range((uintptr_t)ptr, (uintptr_t)ptr + l);
@@ -2693,7 +2690,7 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len,
mr = qemu_ram_addr_from_host(buffer, &addr1);
assert(mr != NULL);
if (is_write) {
invalidate_and_set_dirty(addr1, access_len);
invalidate_and_set_dirty(mr, addr1, access_len);
}
if (xen_enabled()) {
xen_invalidate_map_cache_entry(buffer);
@@ -3022,6 +3019,7 @@ void address_space_stl_notdirty(AddressSpace *as, hwaddr addr, uint32_t val,
hwaddr l = 4;
hwaddr addr1;
MemTxResult r;
uint8_t dirty_log_mask;
rcu_read_lock();
mr = address_space_translate(as, addr, &addr1, &l,
@@ -3033,14 +3031,9 @@ void address_space_stl_notdirty(AddressSpace *as, hwaddr addr, uint32_t val,
ptr = qemu_get_ram_ptr(addr1);
stl_p(ptr, val);
if (unlikely(in_migration)) {
if (cpu_physical_memory_is_clean(addr1)) {
/* invalidate code */
tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
/* set dirty bit */
cpu_physical_memory_set_dirty_range_nocode(addr1, 4);
}
}
dirty_log_mask = memory_region_get_dirty_log_mask(mr);
dirty_log_mask &= ~(1 << DIRTY_MEMORY_CODE);
cpu_physical_memory_set_dirty_range(addr1, 4, dirty_log_mask);
r = MEMTX_OK;
}
if (result) {
@@ -3096,7 +3089,7 @@ static inline void address_space_stl_internal(AddressSpace *as,
stl_p(ptr, val);
break;
}
invalidate_and_set_dirty(addr1, 4);
invalidate_and_set_dirty(mr, addr1, 4);
r = MEMTX_OK;
}
if (result) {
@@ -3200,7 +3193,7 @@ static inline void address_space_stw_internal(AddressSpace *as,
stw_p(ptr, val);
break;
}
invalidate_and_set_dirty(addr1, 2);
invalidate_and_set_dirty(mr, addr1, 2);
r = MEMTX_OK;
}
if (result) {
+3 -1
View File
@@ -94,7 +94,8 @@ static void ich9_smi_writel(void *opaque, hwaddr addr, uint64_t val,
ICH9LPCPMRegs *pm = opaque;
switch (addr) {
case 0:
pm->smi_en = val;
pm->smi_en &= ~pm->smi_en_wmask;
pm->smi_en |= (val & pm->smi_en_wmask);
break;
}
}
@@ -198,6 +199,7 @@ static void pm_reset(void *opaque)
* support SMM mode. */
pm->smi_en |= ICH9_PMIO_SMI_EN_APMC_EN;
}
pm->smi_en_wmask = ~0;
acpi_update_sci(&pm->acpi_regs, pm->irq);
}
+1 -1
View File
@@ -525,7 +525,7 @@ static pflash_t *ve_pflash_cfi01_register(hwaddr base, const char *name,
qdev_prop_set_uint64(dev, "sector-length", VEXPRESS_FLASH_SECT_SIZE);
qdev_prop_set_uint8(dev, "width", 4);
qdev_prop_set_uint8(dev, "device-width", 2);
qdev_prop_set_uint8(dev, "big-endian", 0);
qdev_prop_set_bit(dev, "big-endian", false);
qdev_prop_set_uint16(dev, "id0", 0x89);
qdev_prop_set_uint16(dev, "id1", 0x18);
qdev_prop_set_uint16(dev, "id2", 0x00);
+1 -1
View File
@@ -555,7 +555,7 @@ static void create_one_flash(const char *name, hwaddr flashbase,
qdev_prop_set_uint64(dev, "sector-length", sectorlength);
qdev_prop_set_uint8(dev, "width", 4);
qdev_prop_set_uint8(dev, "device-width", 2);
qdev_prop_set_uint8(dev, "big-endian", 0);
qdev_prop_set_bit(dev, "big-endian", false);
qdev_prop_set_uint16(dev, "id0", 0x89);
qdev_prop_set_uint16(dev, "id1", 0x18);
qdev_prop_set_uint16(dev, "id2", 0x00);
+77 -127
View File
@@ -64,6 +64,9 @@ do { \
#define TYPE_CFI_PFLASH01 "cfi.pflash01"
#define CFI_PFLASH01(obj) OBJECT_CHECK(pflash_t, (obj), TYPE_CFI_PFLASH01)
#define PFLASH_BE 0
#define PFLASH_SECURE 1
struct pflash_t {
/*< private >*/
SysBusDevice parent_obj;
@@ -75,7 +78,7 @@ struct pflash_t {
uint8_t bank_width;
uint8_t device_width; /* If 0, device width not specified. */
uint8_t max_device_width; /* max device width in bytes */
uint8_t be;
uint32_t features;
uint8_t wcycle; /* if 0, the flash is read normally */
int ro;
uint8_t cmd;
@@ -235,12 +238,57 @@ static uint32_t pflash_devid_query(pflash_t *pfl, hwaddr offset)
return resp;
}
static uint32_t pflash_data_read(pflash_t *pfl, hwaddr offset,
int width, int be)
{
uint8_t *p;
uint32_t ret;
p = pfl->storage;
switch (width) {
case 1:
ret = p[offset];
DPRINTF("%s: data offset " TARGET_FMT_plx " %02x\n",
__func__, offset, ret);
break;
case 2:
if (be) {
ret = p[offset] << 8;
ret |= p[offset + 1];
} else {
ret = p[offset];
ret |= p[offset + 1] << 8;
}
DPRINTF("%s: data offset " TARGET_FMT_plx " %04x\n",
__func__, offset, ret);
break;
case 4:
if (be) {
ret = p[offset] << 24;
ret |= p[offset + 1] << 16;
ret |= p[offset + 2] << 8;
ret |= p[offset + 3];
} else {
ret = p[offset];
ret |= p[offset + 1] << 8;
ret |= p[offset + 2] << 16;
ret |= p[offset + 3] << 24;
}
DPRINTF("%s: data offset " TARGET_FMT_plx " %08x\n",
__func__, offset, ret);
break;
default:
DPRINTF("BUG in %s\n", __func__);
abort();
}
return ret;
}
static uint32_t pflash_read (pflash_t *pfl, hwaddr offset,
int width, int be)
{
hwaddr boff;
uint32_t ret;
uint8_t *p;
ret = -1;
@@ -257,43 +305,7 @@ static uint32_t pflash_read (pflash_t *pfl, hwaddr offset,
/* fall through to read code */
case 0x00:
/* Flash area read */
p = pfl->storage;
switch (width) {
case 1:
ret = p[offset];
DPRINTF("%s: data offset " TARGET_FMT_plx " %02x\n",
__func__, offset, ret);
break;
case 2:
if (be) {
ret = p[offset] << 8;
ret |= p[offset + 1];
} else {
ret = p[offset];
ret |= p[offset + 1] << 8;
}
DPRINTF("%s: data offset " TARGET_FMT_plx " %04x\n",
__func__, offset, ret);
break;
case 4:
if (be) {
ret = p[offset] << 24;
ret |= p[offset + 1] << 16;
ret |= p[offset + 2] << 8;
ret |= p[offset + 3];
} else {
ret = p[offset];
ret |= p[offset + 1] << 8;
ret |= p[offset + 2] << 16;
ret |= p[offset + 3] << 24;
}
DPRINTF("%s: data offset " TARGET_FMT_plx " %08x\n",
__func__, offset, ret);
break;
default:
DPRINTF("BUG in %s\n", __func__);
}
ret = pflash_data_read(pfl, offset, width, be);
break;
case 0x10: /* Single byte program */
case 0x20: /* Block erase */
@@ -648,101 +660,37 @@ static void pflash_write(pflash_t *pfl, hwaddr offset,
}
static uint32_t pflash_readb_be(void *opaque, hwaddr addr)
{
return pflash_read(opaque, addr, 1, 1);
}
static uint32_t pflash_readb_le(void *opaque, hwaddr addr)
{
return pflash_read(opaque, addr, 1, 0);
}
static uint32_t pflash_readw_be(void *opaque, hwaddr addr)
static MemTxResult pflash_mem_read_with_attrs(void *opaque, hwaddr addr, uint64_t *value,
unsigned len, MemTxAttrs attrs)
{
pflash_t *pfl = opaque;
bool be = !!(pfl->features & (1 << PFLASH_BE));
return pflash_read(pfl, addr, 2, 1);
if ((pfl->features & (1 << PFLASH_SECURE)) && !attrs.secure) {
*value = pflash_data_read(opaque, addr, len, be);
} else {
*value = pflash_read(opaque, addr, len, be);
}
return MEMTX_OK;
}
static uint32_t pflash_readw_le(void *opaque, hwaddr addr)
static MemTxResult pflash_mem_write_with_attrs(void *opaque, hwaddr addr, uint64_t value,
unsigned len, MemTxAttrs attrs)
{
pflash_t *pfl = opaque;
bool be = !!(pfl->features & (1 << PFLASH_BE));
return pflash_read(pfl, addr, 2, 0);
if ((pfl->features & (1 << PFLASH_SECURE)) && !attrs.secure) {
return MEMTX_ERROR;
} else {
pflash_write(opaque, addr, value, len, be);
return MEMTX_OK;
}
}
static uint32_t pflash_readl_be(void *opaque, hwaddr addr)
{
pflash_t *pfl = opaque;
return pflash_read(pfl, addr, 4, 1);
}
static uint32_t pflash_readl_le(void *opaque, hwaddr addr)
{
pflash_t *pfl = opaque;
return pflash_read(pfl, addr, 4, 0);
}
static void pflash_writeb_be(void *opaque, hwaddr addr,
uint32_t value)
{
pflash_write(opaque, addr, value, 1, 1);
}
static void pflash_writeb_le(void *opaque, hwaddr addr,
uint32_t value)
{
pflash_write(opaque, addr, value, 1, 0);
}
static void pflash_writew_be(void *opaque, hwaddr addr,
uint32_t value)
{
pflash_t *pfl = opaque;
pflash_write(pfl, addr, value, 2, 1);
}
static void pflash_writew_le(void *opaque, hwaddr addr,
uint32_t value)
{
pflash_t *pfl = opaque;
pflash_write(pfl, addr, value, 2, 0);
}
static void pflash_writel_be(void *opaque, hwaddr addr,
uint32_t value)
{
pflash_t *pfl = opaque;
pflash_write(pfl, addr, value, 4, 1);
}
static void pflash_writel_le(void *opaque, hwaddr addr,
uint32_t value)
{
pflash_t *pfl = opaque;
pflash_write(pfl, addr, value, 4, 0);
}
static const MemoryRegionOps pflash_cfi01_ops_be = {
.old_mmio = {
.read = { pflash_readb_be, pflash_readw_be, pflash_readl_be, },
.write = { pflash_writeb_be, pflash_writew_be, pflash_writel_be, },
},
.endianness = DEVICE_NATIVE_ENDIAN,
};
static const MemoryRegionOps pflash_cfi01_ops_le = {
.old_mmio = {
.read = { pflash_readb_le, pflash_readw_le, pflash_readl_le, },
.write = { pflash_writeb_le, pflash_writew_le, pflash_writel_le, },
},
static const MemoryRegionOps pflash_cfi01_ops = {
.read_with_attrs = pflash_mem_read_with_attrs,
.write_with_attrs = pflash_mem_write_with_attrs,
.endianness = DEVICE_NATIVE_ENDIAN,
};
@@ -773,7 +721,8 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
memory_region_init_rom_device(
&pfl->mem, OBJECT(dev),
pfl->be ? &pflash_cfi01_ops_be : &pflash_cfi01_ops_le, pfl,
&pflash_cfi01_ops,
pfl,
pfl->name, total_len, &local_err);
if (local_err) {
error_propagate(errp, local_err);
@@ -925,7 +874,8 @@ static Property pflash_cfi01_properties[] = {
DEFINE_PROP_UINT8("width", struct pflash_t, bank_width, 0),
DEFINE_PROP_UINT8("device-width", struct pflash_t, device_width, 0),
DEFINE_PROP_UINT8("max-device-width", struct pflash_t, max_device_width, 0),
DEFINE_PROP_UINT8("big-endian", struct pflash_t, be, 0),
DEFINE_PROP_BIT("big-endian", struct pflash_t, features, PFLASH_BE, 0),
DEFINE_PROP_BIT("secure", struct pflash_t, features, PFLASH_SECURE, 0),
DEFINE_PROP_UINT16("id0", struct pflash_t, ident0, 0),
DEFINE_PROP_UINT16("id1", struct pflash_t, ident1, 0),
DEFINE_PROP_UINT16("id2", struct pflash_t, ident2, 0),
@@ -975,7 +925,7 @@ pflash_t *pflash_cfi01_register(hwaddr base,
qdev_prop_set_uint32(dev, "num-blocks", nb_blocs);
qdev_prop_set_uint64(dev, "sector-length", sector_len);
qdev_prop_set_uint8(dev, "width", bank_width);
qdev_prop_set_uint8(dev, "big-endian", !!be);
qdev_prop_set_bit(dev, "big-endian", !!be);
qdev_prop_set_uint16(dev, "id0", id0);
qdev_prop_set_uint16(dev, "id1", id1);
qdev_prop_set_uint16(dev, "id2", id2);
-25
View File
@@ -641,28 +641,3 @@ static void parallel_register_types(void)
}
type_init(parallel_register_types)
static void parallel_init(ISABus *bus, int index, CharDriverState *chr)
{
DeviceState *dev;
ISADevice *isadev;
isadev = isa_create(bus, "isa-parallel");
dev = DEVICE(isadev);
qdev_prop_set_uint32(dev, "index", index);
qdev_prop_set_chr(dev, "chardev", chr);
qdev_init_nofail(dev);
}
void parallel_hds_isa_init(ISABus *bus, int n)
{
int i;
assert(n <= MAX_PARALLEL_PORTS);
for (i = 0; i < n; i++) {
if (parallel_hds[i]) {
parallel_init(bus, i, parallel_hds[i]);
}
}
}
+2
View File
@@ -106,6 +106,7 @@ static void cg3_update_display(void *opaque)
pix = memory_region_get_ram_ptr(&s->vram_mem);
data = (uint32_t *)surface_data(surface);
memory_region_sync_dirty_bitmap(&s->vram_mem);
for (y = 0; y < height; y++) {
int update = s->full_update;
@@ -309,6 +310,7 @@ static void cg3_realizefn(DeviceState *dev, Error **errp)
memory_region_init_ram(&s->vram_mem, NULL, "cg3.vram", s->vram_size,
&error_abort);
memory_region_set_log(&s->vram_mem, true, DIRTY_MEMORY_VGA);
vmstate_register_ram_global(&s->vram_mem);
sysbus_init_mmio(sbd, &s->vram_mem);
+13 -7
View File
@@ -1109,6 +1109,12 @@ static inline int fimd_get_buffer_id(Exynos4210fimdWindow *w)
}
}
static void exynos4210_fimd_invalidate(void *opaque)
{
Exynos4210fimdState *s = (Exynos4210fimdState *)opaque;
s->invalidate = true;
}
/* Updates specified window's MemorySection based on values of WINCON,
* VIDOSDA, VIDOSDB, VIDWADDx and SHADOWCON registers */
static void fimd_update_memory_section(Exynos4210fimdState *s, unsigned win)
@@ -1136,7 +1142,11 @@ static void fimd_update_memory_section(Exynos4210fimdState *s, unsigned win)
/* TODO: add .exit and unref the region there. Not needed yet since sysbus
* does not support hot-unplug.
*/
memory_region_unref(w->mem_section.mr);
if (w->mem_section.mr) {
memory_region_set_log(w->mem_section.mr, false, DIRTY_MEMORY_VGA);
memory_region_unref(w->mem_section.mr);
}
w->mem_section = memory_region_find(sysbus_address_space(sbd),
fb_start_addr, w->fb_len);
assert(w->mem_section.mr);
@@ -1162,6 +1172,8 @@ static void fimd_update_memory_section(Exynos4210fimdState *s, unsigned win)
cpu_physical_memory_unmap(w->host_fb_addr, fb_mapped_len, 0, 0);
goto error_return;
}
memory_region_set_log(w->mem_section.mr, true, DIRTY_MEMORY_VGA);
exynos4210_fimd_invalidate(s);
return;
error_return:
@@ -1224,12 +1236,6 @@ static void exynos4210_fimd_update_irq(Exynos4210fimdState *s)
}
}
static void exynos4210_fimd_invalidate(void *opaque)
{
Exynos4210fimdState *s = (Exynos4210fimdState *)opaque;
s->invalidate = true;
}
static void exynos4210_update_resolution(Exynos4210fimdState *s)
{
DisplaySurface *surface = qemu_console_surface(s->console);
+4
View File
@@ -63,6 +63,10 @@ void framebuffer_update_display(
assert(mem_section.offset_within_address_space == base);
memory_region_sync_dirty_bitmap(mem);
if (!memory_region_is_logging(mem, DIRTY_MEMORY_VGA)) {
invalidate = true;
}
src_base = cpu_physical_memory_map(base, &src_len, 0);
/* If we can't map the framebuffer then bail. We could try harder,
but it's not really worth it as dirty flag tracking will probably
+2 -1
View File
@@ -260,6 +260,7 @@ static void g364fb_update_display(void *opaque)
qemu_console_resize(s->con, s->width, s->height);
}
memory_region_sync_dirty_bitmap(&s->mem_vram);
if (s->ctla & CTLA_FORCE_BLANK) {
g364fb_draw_blank(s);
} else if (s->depth == 8) {
@@ -489,7 +490,7 @@ static void g364fb_init(DeviceState *dev, G364State *s)
memory_region_init_ram_ptr(&s->mem_vram, NULL, "vram",
s->vram_size, s->vram);
vmstate_register_ram(&s->mem_vram, dev);
memory_region_set_coalescing(&s->mem_vram);
memory_region_set_log(&s->mem_vram, true, DIRTY_MEMORY_VGA);
}
#define TYPE_G364 "sysbus-g364"
+2
View File
@@ -1322,6 +1322,7 @@ static void sm501_draw_crt(SM501State * s)
}
/* draw each line according to conditions */
memory_region_sync_dirty_bitmap(&s->local_mem_region);
for (y = 0; y < height; y++) {
int update_hwc = draw_hwc_line ? within_hwc_y_range(s, y, 1) : 0;
int update = full_update || update_hwc;
@@ -1412,6 +1413,7 @@ void sm501_init(MemoryRegion *address_space_mem, uint32_t base,
memory_region_init_ram(&s->local_mem_region, NULL, "sm501.local",
local_mem_bytes, &error_abort);
vmstate_register_ram_global(&s->local_mem_region);
memory_region_set_log(&s->local_mem_region, true, DIRTY_MEMORY_VGA);
s->local_mem = memory_region_get_ram_ptr(&s->local_mem_region);
memory_region_add_subregion(address_space_mem, base, &s->local_mem_region);
+3
View File
@@ -353,6 +353,7 @@ static void tcx_update_display(void *opaque)
return;
}
memory_region_sync_dirty_bitmap(&ts->vram_mem);
for (y = 0; y < ts->height; page += TARGET_PAGE_SIZE) {
if (memory_region_get_dirty(&ts->vram_mem, page, TARGET_PAGE_SIZE,
DIRTY_MEMORY_VGA)) {
@@ -446,6 +447,7 @@ static void tcx24_update_display(void *opaque)
dd = surface_stride(surface);
ds = 1024;
memory_region_sync_dirty_bitmap(&ts->vram_mem);
for (y = 0; y < ts->height; page += TARGET_PAGE_SIZE,
page24 += TARGET_PAGE_SIZE, cpage += TARGET_PAGE_SIZE) {
if (tcx24_check_dirty(ts, page, page24, cpage)) {
@@ -1006,6 +1008,7 @@ static void tcx_realizefn(DeviceState *dev, Error **errp)
memory_region_init_ram(&s->vram_mem, OBJECT(s), "tcx.vram",
s->vram_size * (1 + 4 + 4), &error_abort);
vmstate_register_ram_global(&s->vram_mem);
memory_region_set_log(&s->vram_mem, true, DIRTY_MEMORY_VGA);
vram_base = memory_region_get_ram_ptr(&s->vram_mem);
/* 10/ROM : FCode ROM */
+1 -1
View File
@@ -1124,7 +1124,7 @@ static void vmsvga_update_display(void *opaque)
* Is it more efficient to look at vram VGA-dirty bits or wait
* for the driver to issue SVGA_CMD_UPDATE?
*/
if (memory_region_is_logging(&s->vga.vram)) {
if (memory_region_is_logging(&s->vga.vram, DIRTY_MEMORY_VGA)) {
vga_sync_dirty_bitmap(&s->vga);
dirty = memory_region_get_dirty(&s->vga.vram, 0,
surface_stride(surface) * surface_height(surface),
-21
View File
@@ -164,27 +164,6 @@ uint64_t cpu_get_tsc(CPUX86State *env)
return cpu_get_ticks();
}
/* SMM support */
static cpu_set_smm_t smm_set;
static void *smm_arg;
void cpu_smm_register(cpu_set_smm_t callback, void *arg)
{
assert(smm_set == NULL);
assert(smm_arg == NULL);
smm_set = callback;
smm_arg = arg;
}
void cpu_smm_update(CPUX86State *env)
{
if (smm_set && smm_arg && CPU(x86_env_get_cpu(env)) == first_cpu) {
smm_set(!!(env->hflags & HF_SMM_MASK), smm_arg);
}
}
/* IRQ handling */
int cpu_get_pic_interrupt(CPUX86State *env)
{
+26
View File
@@ -21,6 +21,7 @@
#include "hw/sysbus.h"
#include "sysemu/sysemu.h"
#include "hw/isa/isa.h"
#include "hw/i386/pc.h"
static ISABus *isabus;
@@ -267,3 +268,28 @@ MemoryRegion *isa_address_space_io(ISADevice *dev)
}
type_init(isabus_register_types)
static void parallel_init(ISABus *bus, int index, CharDriverState *chr)
{
DeviceState *dev;
ISADevice *isadev;
isadev = isa_create(bus, "isa-parallel");
dev = DEVICE(isadev);
qdev_prop_set_uint32(dev, "index", index);
qdev_prop_set_chr(dev, "chardev", chr);
qdev_init_nofail(dev);
}
void parallel_hds_isa_init(ISABus *bus, int n)
{
int i;
assert(n <= MAX_PARALLEL_PORTS);
for (i = 0; i < n; i++) {
if (parallel_hds[i]) {
parallel_init(bus, i, parallel_hds[i]);
}
}
}

Some files were not shown because too many files have changed in this diff Show More