Merge remote-tracking branch 'mst/for_anthony' into staging

This commit is contained in:
Anthony Liguori 2011-05-05 13:05:32 -05:00
commit 3964f535c3
19 changed files with 545 additions and 298 deletions

View File

@ -34,10 +34,21 @@ typedef unsigned long ram_addr_t;
typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t value);
typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr);
void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
ram_addr_t size,
ram_addr_t phys_offset,
ram_addr_t region_offset);
void cpu_register_physical_memory_log(target_phys_addr_t start_addr,
ram_addr_t size,
ram_addr_t phys_offset,
ram_addr_t region_offset,
bool log_dirty);
static inline void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
ram_addr_t size,
ram_addr_t phys_offset,
ram_addr_t region_offset)
{
cpu_register_physical_memory_log(start_addr, size, phys_offset,
region_offset, false);
}
static inline void cpu_register_physical_memory(target_phys_addr_t start_addr,
ram_addr_t size,
ram_addr_t phys_offset)
@ -91,7 +102,8 @@ struct CPUPhysMemoryClient {
void (*set_memory)(struct CPUPhysMemoryClient *client,
target_phys_addr_t start_addr,
ram_addr_t size,
ram_addr_t phys_offset);
ram_addr_t phys_offset,
bool log_dirty);
int (*sync_dirty_bitmap)(struct CPUPhysMemoryClient *client,
target_phys_addr_t start_addr,
target_phys_addr_t end_addr);

30
exec.c
View File

@ -1718,11 +1718,12 @@ static QLIST_HEAD(memory_client_list, CPUPhysMemoryClient) memory_client_list
static void cpu_notify_set_memory(target_phys_addr_t start_addr,
ram_addr_t size,
ram_addr_t phys_offset)
ram_addr_t phys_offset,
bool log_dirty)
{
CPUPhysMemoryClient *client;
QLIST_FOREACH(client, &memory_client_list, list) {
client->set_memory(client, start_addr, size, phys_offset);
client->set_memory(client, start_addr, size, phys_offset, log_dirty);
}
}
@ -1749,8 +1750,14 @@ static int cpu_notify_migration_log(int enable)
return 0;
}
/* The l1_phys_map provides the upper P_L1_BITs of the guest physical
* address. Each intermediate table provides the next L2_BITs of guest
* physical address space. The number of levels vary based on host and
* guest configuration, making it efficient to build the final guest
* physical address by seeding the L1 offset and shifting and adding in
* each L2 offset as we recurse through them. */
static void phys_page_for_each_1(CPUPhysMemoryClient *client,
int level, void **lp)
int level, void **lp, target_phys_addr_t addr)
{
int i;
@ -1759,16 +1766,18 @@ static void phys_page_for_each_1(CPUPhysMemoryClient *client,
}
if (level == 0) {
PhysPageDesc *pd = *lp;
addr <<= L2_BITS + TARGET_PAGE_BITS;
for (i = 0; i < L2_SIZE; ++i) {
if (pd[i].phys_offset != IO_MEM_UNASSIGNED) {
client->set_memory(client, pd[i].region_offset,
TARGET_PAGE_SIZE, pd[i].phys_offset);
client->set_memory(client, addr | i << TARGET_PAGE_BITS,
TARGET_PAGE_SIZE, pd[i].phys_offset, false);
}
}
} else {
void **pp = *lp;
for (i = 0; i < L2_SIZE; ++i) {
phys_page_for_each_1(client, level - 1, pp + i);
phys_page_for_each_1(client, level - 1, pp + i,
(addr << L2_BITS) | i);
}
}
}
@ -1778,7 +1787,7 @@ static void phys_page_for_each(CPUPhysMemoryClient *client)
int i;
for (i = 0; i < P_L1_SIZE; ++i) {
phys_page_for_each_1(client, P_L1_SHIFT / L2_BITS - 1,
l1_phys_map + 1);
l1_phys_map + i, i);
}
}
@ -2607,10 +2616,11 @@ static subpage_t *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
start_addr and region_offset are rounded down to a page boundary
before calculating this offset. This should not be a problem unless
the low bits of start_addr and region_offset differ. */
void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
void cpu_register_physical_memory_log(target_phys_addr_t start_addr,
ram_addr_t size,
ram_addr_t phys_offset,
ram_addr_t region_offset)
ram_addr_t region_offset,
bool log_dirty)
{
target_phys_addr_t addr, end_addr;
PhysPageDesc *p;
@ -2619,7 +2629,7 @@ void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
subpage_t *subpage;
assert(size);
cpu_notify_set_memory(start_addr, size, phys_offset);
cpu_notify_set_memory(start_addr, size, phys_offset, log_dirty);
if (phys_offset == IO_MEM_UNASSIGNED) {
region_offset = start_addr;

View File

@ -2489,7 +2489,9 @@ static void map_linear_vram(CirrusVGAState *s)
if (!s->vga.map_addr && s->vga.lfb_addr && s->vga.lfb_end) {
s->vga.map_addr = s->vga.lfb_addr;
s->vga.map_end = s->vga.lfb_end;
cpu_register_physical_memory(s->vga.map_addr, s->vga.map_end - s->vga.map_addr, s->vga.vram_offset);
cpu_register_physical_memory_log(s->vga.map_addr,
s->vga.map_end - s->vga.map_addr,
s->vga.vram_offset, 0, true);
}
if (!s->vga.map_addr)
@ -2502,10 +2504,14 @@ static void map_linear_vram(CirrusVGAState *s)
&& !((s->vga.gr[0x0B] & 0x14) == 0x14)
&& !(s->vga.gr[0x0B] & 0x02)) {
cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x8000,
(s->vga.vram_offset + s->cirrus_bank_base[0]) | IO_MEM_RAM);
cpu_register_physical_memory(isa_mem_base + 0xa8000, 0x8000,
(s->vga.vram_offset + s->cirrus_bank_base[1]) | IO_MEM_RAM);
cpu_register_physical_memory_log(isa_mem_base + 0xa0000, 0x8000,
(s->vga.vram_offset +
s->cirrus_bank_base[0]) |
IO_MEM_RAM, 0, true);
cpu_register_physical_memory_log(isa_mem_base + 0xa8000, 0x8000,
(s->vga.vram_offset +
s->cirrus_bank_base[1]) |
IO_MEM_RAM, 0, true);
s->vga.lfb_vram_mapped = 1;
}
@ -3024,7 +3030,6 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
s->vga.cursor_draw_line = cirrus_cursor_draw_line;
qemu_register_reset(cirrus_reset, s);
cirrus_reset(s);
}
/***************************************
@ -3076,15 +3081,6 @@ static void cirrus_pci_lfb_map(PCIDevice *d, int region_num,
vga_dirty_log_start(&s->vga);
}
static void cirrus_pci_mmio_map(PCIDevice *d, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
CirrusVGAState *s = &DO_UPCAST(PCICirrusVGAState, dev, d)->cirrus_vga;
cpu_register_physical_memory(addr, CIRRUS_PNPMMIO_SIZE,
s->cirrus_mmio_io_addr);
}
static void pci_cirrus_write_config(PCIDevice *d,
uint32_t address, uint32_t val, int len)
{
@ -3123,8 +3119,8 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
pci_register_bar(&d->dev, 0, 0x2000000,
PCI_BASE_ADDRESS_MEM_PREFETCH, cirrus_pci_lfb_map);
if (device_id == CIRRUS_ID_CLGD5446) {
pci_register_bar(&d->dev, 1, CIRRUS_PNPMMIO_SIZE,
PCI_BASE_ADDRESS_SPACE_MEMORY, cirrus_pci_mmio_map);
pci_register_bar_simple(&d->dev, 1, CIRRUS_PNPMMIO_SIZE, 0,
s->cirrus_mmio_io_addr);
}
return 0;
}

View File

@ -1,7 +1,7 @@
/*
* QEMU i8255x (PRO100) emulation
*
* Copyright (C) 2006-2010 Stefan Weil
* Copyright (C) 2006-2011 Stefan Weil
*
* Portions of the code are copies from grub / etherboot eepro100.c
* and linux e100.c.
@ -20,11 +20,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Tested features (i82559):
* PXE boot (i386) ok
* PXE boot (i386 guest, i386 / mips / mipsel / ppc host) ok
* Linux networking (i386) ok
*
* Untested:
* non-i386 platforms
* Windows networking
*
* References:
@ -48,6 +47,15 @@
#include "eeprom93xx.h"
#include "sysemu.h"
/* QEMU sends frames smaller than 60 bytes to ethernet nics.
* Such frames are rejected by real nics and their emulations.
* To avoid this behaviour, other nic emulations pad received
* frames. The following definition enables this padding for
* eepro100, too. We keep the define around in case it might
* become useful the future if the core networking is ever
* changed to pad short packets itself. */
#define CONFIG_PAD_RECEIVED_FRAMES
#define KiB 1024
/* Debug EEPRO100 card. */
@ -130,7 +138,7 @@ typedef struct {
/* Offsets to the various registers.
All accesses need not be longword aligned. */
enum speedo_offsets {
typedef enum {
SCBStatus = 0, /* Status Word. */
SCBAck = 1,
SCBCmd = 2, /* Rx/Command Unit command and status. */
@ -145,7 +153,7 @@ enum speedo_offsets {
SCBpmdr = 27, /* Power Management Driver. */
SCBgctrl = 28, /* General Control. */
SCBgstat = 29, /* General Status. */
};
} E100RegisterOffset;
/* A speedo3 transmit buffer descriptor with two buffers... */
typedef struct {
@ -173,7 +181,7 @@ typedef struct {
uint32_t rx_buf_addr; /* void * */
uint16_t count;
uint16_t size;
char packet[MAX_ETH_FRAME_SIZE + 4];
/* Ethernet frame data follows. */
} eepro100_rx_t;
typedef enum {
@ -228,11 +236,10 @@ typedef struct {
uint8_t scb_stat; /* SCB stat/ack byte */
uint8_t int_stat; /* PCI interrupt status */
/* region must not be saved by nic_save. */
uint32_t region[3]; /* PCI region addresses */
uint32_t region1; /* PCI region 1 address */
uint16_t mdimem[32];
eeprom_t *eeprom;
uint32_t device; /* device variant */
uint32_t pointer;
/* (cu_base + cu_offset) address the next command block in the command block list. */
uint32_t cu_base; /* CU base address */
uint32_t cu_offset; /* CU address offset */
@ -249,11 +256,13 @@ typedef struct {
/* Statistical counters. Also used for wake-up packet (i82559). */
eepro100_stats_t statistics;
/* Data in mem is always in the byte order of the controller (le).
* It must be dword aligned to allow direct access to 32 bit values. */
uint8_t mem[PCI_MEM_SIZE] __attribute__((aligned(8)));;
/* Configuration bytes. */
uint8_t configuration[22];
/* Data in mem is always in the byte order of the controller (le). */
uint8_t mem[PCI_MEM_SIZE];
/* vmstate for each particular nic */
VMStateDescription *vmstate;
@ -307,11 +316,36 @@ static const uint16_t eepro100_mdi_mask[] = {
0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
};
/* XXX: optimize */
static void stl_le_phys(target_phys_addr_t addr, uint32_t val)
/* Read a 16 bit little endian value from physical memory. */
static uint16_t e100_ldw_le_phys(target_phys_addr_t addr)
{
/* Load 16 bit (little endian) word from emulated hardware. */
uint16_t val;
cpu_physical_memory_read(addr, &val, sizeof(val));
return le16_to_cpu(val);
}
/* Read a 32 bit little endian value from physical memory. */
static uint32_t e100_ldl_le_phys(target_phys_addr_t addr)
{
/* Load 32 bit (little endian) word from emulated hardware. */
uint32_t val;
cpu_physical_memory_read(addr, &val, sizeof(val));
return le32_to_cpu(val);
}
/* Write a 16 bit little endian value to physical memory. */
static void e100_stw_le_phys(target_phys_addr_t addr, uint16_t val)
{
val = cpu_to_le16(val);
cpu_physical_memory_write(addr, &val, sizeof(val));
}
/* Write a 32 bit little endian value to physical memory. */
static void e100_stl_le_phys(target_phys_addr_t addr, uint32_t val)
{
val = cpu_to_le32(val);
cpu_physical_memory_write(addr, (const uint8_t *)&val, sizeof(val));
cpu_physical_memory_write(addr, &val, sizeof(val));
}
#define POLYNOMIAL 0x04c11db6
@ -339,6 +373,36 @@ static unsigned compute_mcast_idx(const uint8_t * ep)
return (crc & BITS(7, 2)) >> 2;
}
/* Read a 16 bit control/status (CSR) register. */
static uint16_t e100_read_reg2(EEPRO100State *s, E100RegisterOffset addr)
{
assert(!((uintptr_t)&s->mem[addr] & 1));
return le16_to_cpup((uint16_t *)&s->mem[addr]);
}
/* Read a 32 bit control/status (CSR) register. */
static uint32_t e100_read_reg4(EEPRO100State *s, E100RegisterOffset addr)
{
assert(!((uintptr_t)&s->mem[addr] & 3));
return le32_to_cpup((uint32_t *)&s->mem[addr]);
}
/* Write a 16 bit control/status (CSR) register. */
static void e100_write_reg2(EEPRO100State *s, E100RegisterOffset addr,
uint16_t val)
{
assert(!((uintptr_t)&s->mem[addr] & 1));
cpu_to_le16w((uint16_t *)&s->mem[addr], val);
}
/* Read a 32 bit control/status (CSR) register. */
static void e100_write_reg4(EEPRO100State *s, E100RegisterOffset addr,
uint32_t val)
{
assert(!((uintptr_t)&s->mem[addr] & 3));
cpu_to_le32w((uint32_t *)&s->mem[addr], val);
}
#if defined(DEBUG_EEPRO100)
static const char *nic_dump(const uint8_t * buf, unsigned size)
{
@ -590,8 +654,7 @@ static void nic_selective_reset(EEPRO100State * s)
TRACE(EEPROM, logout("checksum=0x%04x\n", eeprom_contents[EEPROM_SIZE - 1]));
memset(s->mem, 0, sizeof(s->mem));
uint32_t val = BIT(21);
memcpy(&s->mem[SCBCtrlMDI], &val, sizeof(val));
e100_write_reg4(s, SCBCtrlMDI, BIT(21));
assert(sizeof(s->mdimem) == sizeof(eepro100_mdi_default));
memcpy(&s->mdimem[0], &eepro100_mdi_default[0], sizeof(s->mdimem));
@ -694,22 +757,21 @@ static void dump_statistics(EEPRO100State * s)
* values which really matter.
* Number of data should check configuration!!!
*/
cpu_physical_memory_write(s->statsaddr,
(uint8_t *) & s->statistics, s->stats_size);
stl_le_phys(s->statsaddr + 0, s->statistics.tx_good_frames);
stl_le_phys(s->statsaddr + 36, s->statistics.rx_good_frames);
stl_le_phys(s->statsaddr + 48, s->statistics.rx_resource_errors);
stl_le_phys(s->statsaddr + 60, s->statistics.rx_short_frame_errors);
cpu_physical_memory_write(s->statsaddr, &s->statistics, s->stats_size);
e100_stl_le_phys(s->statsaddr + 0, s->statistics.tx_good_frames);
e100_stl_le_phys(s->statsaddr + 36, s->statistics.rx_good_frames);
e100_stl_le_phys(s->statsaddr + 48, s->statistics.rx_resource_errors);
e100_stl_le_phys(s->statsaddr + 60, s->statistics.rx_short_frame_errors);
#if 0
stw_le_phys(s->statsaddr + 76, s->statistics.xmt_tco_frames);
stw_le_phys(s->statsaddr + 78, s->statistics.rcv_tco_frames);
e100_stw_le_phys(s->statsaddr + 76, s->statistics.xmt_tco_frames);
e100_stw_le_phys(s->statsaddr + 78, s->statistics.rcv_tco_frames);
missing("CU dump statistical counters");
#endif
}
static void read_cb(EEPRO100State *s)
{
cpu_physical_memory_read(s->cb_address, (uint8_t *) &s->tx, sizeof(s->tx));
cpu_physical_memory_read(s->cb_address, &s->tx, sizeof(s->tx));
s->tx.status = le16_to_cpu(s->tx.status);
s->tx.command = le16_to_cpu(s->tx.command);
s->tx.link = le32_to_cpu(s->tx.link);
@ -739,10 +801,10 @@ static void tx_command(EEPRO100State *s)
}
assert(tcb_bytes <= sizeof(buf));
while (size < tcb_bytes) {
uint32_t tx_buffer_address = ldl_phys(tbd_address);
uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
uint32_t tx_buffer_address = e100_ldl_le_phys(tbd_address);
uint16_t tx_buffer_size = e100_ldw_le_phys(tbd_address + 4);
#if 0
uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
uint16_t tx_buffer_el = e100_ldw_le_phys(tbd_address + 6);
#endif
tbd_address += 8;
TRACE(RXTX, logout
@ -761,9 +823,9 @@ static void tx_command(EEPRO100State *s)
if (s->has_extended_tcb_support && !(s->configuration[6] & BIT(4))) {
/* Extended Flexible TCB. */
for (; tbd_count < 2; tbd_count++) {
uint32_t tx_buffer_address = ldl_phys(tbd_address);
uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
uint32_t tx_buffer_address = e100_ldl_le_phys(tbd_address);
uint16_t tx_buffer_size = e100_ldw_le_phys(tbd_address + 4);
uint16_t tx_buffer_el = e100_ldw_le_phys(tbd_address + 6);
tbd_address += 8;
TRACE(RXTX, logout
("TBD (extended flexible mode): buffer address 0x%08x, size 0x%04x\n",
@ -779,9 +841,9 @@ static void tx_command(EEPRO100State *s)
}
tbd_address = tbd_array;
for (; tbd_count < s->tx.tbd_count; tbd_count++) {
uint32_t tx_buffer_address = ldl_phys(tbd_address);
uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
uint32_t tx_buffer_address = e100_ldl_le_phys(tbd_address);
uint16_t tx_buffer_size = e100_ldw_le_phys(tbd_address + 4);
uint16_t tx_buffer_el = e100_ldw_le_phys(tbd_address + 6);
tbd_address += 8;
TRACE(RXTX, logout
("TBD (flexible mode): buffer address 0x%08x, size 0x%04x\n",
@ -889,7 +951,7 @@ static void action_command(EEPRO100State *s)
break;
}
/* Write new status. */
stw_phys(s->cb_address, s->tx.status | ok_status | STATUS_C);
e100_stw_le_phys(s->cb_address, s->tx.status | ok_status | STATUS_C);
if (bit_i) {
/* CU completed action. */
eepro100_cx_interrupt(s);
@ -928,7 +990,7 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
logout("unexpected CU state is %u\n", cu_state);
}
set_cu_state(s, cu_active);
s->cu_offset = s->pointer;
s->cu_offset = e100_read_reg4(s, SCBPointer);
action_command(s);
break;
case CU_RESUME:
@ -949,25 +1011,25 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
break;
case CU_STATSADDR:
/* Load dump counters address. */
s->statsaddr = s->pointer;
s->statsaddr = e100_read_reg4(s, SCBPointer);
TRACE(OTHER, logout("val=0x%02x (status address)\n", val));
break;
case CU_SHOWSTATS:
/* Dump statistical counters. */
TRACE(OTHER, logout("val=0x%02x (dump stats)\n", val));
dump_statistics(s);
stl_le_phys(s->statsaddr + s->stats_size, 0xa005);
e100_stl_le_phys(s->statsaddr + s->stats_size, 0xa005);
break;
case CU_CMD_BASE:
/* Load CU base. */
TRACE(OTHER, logout("val=0x%02x (CU base address)\n", val));
s->cu_base = s->pointer;
s->cu_base = e100_read_reg4(s, SCBPointer);
break;
case CU_DUMPSTATS:
/* Dump and reset statistical counters. */
TRACE(OTHER, logout("val=0x%02x (dump stats and reset)\n", val));
dump_statistics(s);
stl_le_phys(s->statsaddr + s->stats_size, 0xa007);
e100_stl_le_phys(s->statsaddr + s->stats_size, 0xa007);
memset(&s->statistics, 0, sizeof(s->statistics));
break;
case CU_SRESUME:
@ -994,7 +1056,7 @@ static void eepro100_ru_command(EEPRO100State * s, uint8_t val)
#endif
}
set_ru_state(s, ru_ready);
s->ru_offset = s->pointer;
s->ru_offset = e100_read_reg4(s, SCBPointer);
TRACE(OTHER, logout("val=0x%02x (rx start)\n", val));
break;
case RX_RESUME:
@ -1018,7 +1080,7 @@ static void eepro100_ru_command(EEPRO100State * s, uint8_t val)
case RX_ADDR_LOAD:
/* Load RU base. */
TRACE(OTHER, logout("val=0x%02x (RU base address)\n", val));
s->ru_base = s->pointer;
s->ru_base = e100_read_reg4(s, SCBPointer);
break;
default:
logout("val=0x%02x (undefined RU command)\n", val);
@ -1050,8 +1112,7 @@ static void eepro100_write_command(EEPRO100State * s, uint8_t val)
static uint16_t eepro100_read_eeprom(EEPRO100State * s)
{
uint16_t val;
memcpy(&val, &s->mem[SCBeeprom], sizeof(val));
uint16_t val = e100_read_reg2(s, SCBeeprom);
if (eeprom93xx_read(s->eeprom)) {
val |= EEPROM_DO;
} else {
@ -1076,12 +1137,6 @@ static void eepro100_write_eeprom(eeprom_t * eeprom, uint8_t val)
eeprom93xx_write(eeprom, eecs, eesk, eedi);
}
static void eepro100_write_pointer(EEPRO100State * s, uint32_t val)
{
s->pointer = le32_to_cpu(val);
TRACE(OTHER, logout("val=0x%08x\n", val));
}
/*****************************************************************************
*
* MDI emulation.
@ -1121,8 +1176,7 @@ static const char *reg2name(uint8_t reg)
static uint32_t eepro100_read_mdi(EEPRO100State * s)
{
uint32_t val;
memcpy(&val, &s->mem[0x10], sizeof(val));
uint32_t val = e100_read_reg4(s, SCBCtrlMDI);
#ifdef DEBUG_EEPRO100
uint8_t raiseint = (val & BIT(29)) >> 29;
@ -1139,8 +1193,9 @@ static uint32_t eepro100_read_mdi(EEPRO100State * s)
return val;
}
static void eepro100_write_mdi(EEPRO100State * s, uint32_t val)
static void eepro100_write_mdi(EEPRO100State *s)
{
uint32_t val = e100_read_reg4(s, SCBCtrlMDI);
uint8_t raiseint = (val & BIT(29)) >> 29;
uint8_t opcode = (val & BITS(27, 26)) >> 26;
uint8_t phy = (val & BITS(25, 21)) >> 21;
@ -1231,7 +1286,7 @@ static void eepro100_write_mdi(EEPRO100State * s, uint32_t val)
}
}
val = (val & 0xffff0000) + data;
memcpy(&s->mem[0x10], &val, sizeof(val));
e100_write_reg4(s, SCBCtrlMDI, val);
}
/*****************************************************************************
@ -1256,9 +1311,9 @@ static uint32_t eepro100_read_port(EEPRO100State * s)
return 0;
}
static void eepro100_write_port(EEPRO100State * s, uint32_t val)
static void eepro100_write_port(EEPRO100State *s)
{
val = le32_to_cpu(val);
uint32_t val = e100_read_reg4(s, SCBPort);
uint32_t address = (val & ~PORT_SELECTION_MASK);
uint8_t selection = (val & PORT_SELECTION_MASK);
switch (selection) {
@ -1268,10 +1323,10 @@ static void eepro100_write_port(EEPRO100State * s, uint32_t val)
case PORT_SELFTEST:
TRACE(OTHER, logout("selftest address=0x%08x\n", address));
eepro100_selftest_t data;
cpu_physical_memory_read(address, (uint8_t *) & data, sizeof(data));
cpu_physical_memory_read(address, &data, sizeof(data));
data.st_sign = 0xffffffff;
data.st_result = 0;
cpu_physical_memory_write(address, (uint8_t *) & data, sizeof(data));
cpu_physical_memory_write(address, &data, sizeof(data));
break;
case PORT_SELECTIVE_RESET:
TRACE(OTHER, logout("selective reset, selftest address=0x%08x\n", address));
@ -1293,7 +1348,7 @@ static uint8_t eepro100_read1(EEPRO100State * s, uint32_t addr)
{
uint8_t val = 0;
if (addr <= sizeof(s->mem) - sizeof(val)) {
memcpy(&val, &s->mem[addr], sizeof(val));
val = s->mem[addr];
}
switch (addr) {
@ -1316,10 +1371,20 @@ static uint8_t eepro100_read1(EEPRO100State * s, uint32_t addr)
case SCBeeprom:
val = eepro100_read_eeprom(s);
break;
case SCBCtrlMDI:
case SCBCtrlMDI + 1:
case SCBCtrlMDI + 2:
case SCBCtrlMDI + 3:
val = (uint8_t)(eepro100_read_mdi(s) >> (8 * (addr & 3)));
TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
break;
case SCBpmdr: /* Power Management Driver Register */
val = 0;
TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
break;
case SCBgctrl: /* General Control Register */
TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
break;
case SCBgstat: /* General Status Register */
/* 100 Mbps full duplex, valid link */
val = 0x07;
@ -1336,7 +1401,7 @@ static uint16_t eepro100_read2(EEPRO100State * s, uint32_t addr)
{
uint16_t val = 0;
if (addr <= sizeof(s->mem) - sizeof(val)) {
memcpy(&val, &s->mem[addr], sizeof(val));
val = e100_read_reg2(s, addr);
}
switch (addr) {
@ -1348,6 +1413,11 @@ static uint16_t eepro100_read2(EEPRO100State * s, uint32_t addr)
val = eepro100_read_eeprom(s);
TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
break;
case SCBCtrlMDI:
case SCBCtrlMDI + 2:
val = (uint16_t)(eepro100_read_mdi(s) >> (8 * (addr & 3)));
TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
break;
default:
logout("addr=%s val=0x%04x\n", regname(addr), val);
missing("unknown word read");
@ -1359,7 +1429,7 @@ static uint32_t eepro100_read4(EEPRO100State * s, uint32_t addr)
{
uint32_t val = 0;
if (addr <= sizeof(s->mem) - sizeof(val)) {
memcpy(&val, &s->mem[addr], sizeof(val));
val = e100_read_reg4(s, addr);
}
switch (addr) {
@ -1367,15 +1437,16 @@ static uint32_t eepro100_read4(EEPRO100State * s, uint32_t addr)
TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
break;
case SCBPointer:
#if 0
val = eepro100_read_pointer(s);
#endif
TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
break;
case SCBPort:
val = eepro100_read_port(s);
TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
break;
case SCBflash:
val = eepro100_read_eeprom(s);
TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
break;
case SCBCtrlMDI:
val = eepro100_read_mdi(s);
break;
@ -1390,27 +1461,43 @@ static void eepro100_write1(EEPRO100State * s, uint32_t addr, uint8_t val)
{
/* SCBStatus is readonly. */
if (addr > SCBStatus && addr <= sizeof(s->mem) - sizeof(val)) {
memcpy(&s->mem[addr], &val, sizeof(val));
s->mem[addr] = val;
}
TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
switch (addr) {
case SCBStatus:
TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
break;
case SCBAck:
TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
eepro100_acknowledge(s);
break;
case SCBCmd:
TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
eepro100_write_command(s, val);
break;
case SCBIntmask:
TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
if (val & BIT(1)) {
eepro100_swi_interrupt(s);
}
eepro100_interrupt(s, 0);
break;
case SCBPointer:
case SCBPointer + 1:
case SCBPointer + 2:
case SCBPointer + 3:
TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
break;
case SCBPort:
case SCBPort + 1:
case SCBPort + 2:
TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
break;
case SCBPort + 3:
TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
eepro100_write_port(s);
break;
case SCBFlow: /* does not exist on 82557 */
case SCBFlow + 1:
case SCBFlow + 2:
@ -1418,8 +1505,18 @@ static void eepro100_write1(EEPRO100State * s, uint32_t addr, uint8_t val)
TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
break;
case SCBeeprom:
TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
eepro100_write_eeprom(s->eeprom, val);
break;
case SCBCtrlMDI:
case SCBCtrlMDI + 1:
case SCBCtrlMDI + 2:
TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
break;
case SCBCtrlMDI + 3:
TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
eepro100_write_mdi(s);
break;
default:
logout("addr=%s val=0x%02x\n", regname(addr), val);
missing("unknown byte write");
@ -1430,23 +1527,42 @@ static void eepro100_write2(EEPRO100State * s, uint32_t addr, uint16_t val)
{
/* SCBStatus is readonly. */
if (addr > SCBStatus && addr <= sizeof(s->mem) - sizeof(val)) {
memcpy(&s->mem[addr], &val, sizeof(val));
e100_write_reg2(s, addr, val);
}
TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
switch (addr) {
case SCBStatus:
TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
s->mem[SCBAck] = (val >> 8);
eepro100_acknowledge(s);
break;
case SCBCmd:
TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
eepro100_write_command(s, val);
eepro100_write1(s, SCBIntmask, val >> 8);
break;
case SCBPointer:
case SCBPointer + 2:
TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
break;
case SCBPort:
TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
break;
case SCBPort + 2:
TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
eepro100_write_port(s);
break;
case SCBeeprom:
TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
eepro100_write_eeprom(s->eeprom, val);
break;
case SCBCtrlMDI:
TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
break;
case SCBCtrlMDI + 2:
TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
eepro100_write_mdi(s);
break;
default:
logout("addr=%s val=0x%04x\n", regname(addr), val);
missing("unknown word write");
@ -1456,19 +1572,25 @@ static void eepro100_write2(EEPRO100State * s, uint32_t addr, uint16_t val)
static void eepro100_write4(EEPRO100State * s, uint32_t addr, uint32_t val)
{
if (addr <= sizeof(s->mem) - sizeof(val)) {
memcpy(&s->mem[addr], &val, sizeof(val));
e100_write_reg4(s, addr, val);
}
switch (addr) {
case SCBPointer:
eepro100_write_pointer(s, val);
TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
break;
case SCBPort:
TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
eepro100_write_port(s, val);
eepro100_write_port(s);
break;
case SCBflash:
TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
val = val >> 16;
eepro100_write_eeprom(s->eeprom, val);
break;
case SCBCtrlMDI:
eepro100_write_mdi(s, val);
TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
eepro100_write_mdi(s);
break;
default:
logout("addr=%s val=0x%08x\n", regname(addr), val);
@ -1488,19 +1610,19 @@ static uint32_t ioport_read1(void *opaque, uint32_t addr)
#if 0
logout("addr=%s\n", regname(addr));
#endif
return eepro100_read1(s, addr - s->region[1]);
return eepro100_read1(s, addr - s->region1);
}
static uint32_t ioport_read2(void *opaque, uint32_t addr)
{
EEPRO100State *s = opaque;
return eepro100_read2(s, addr - s->region[1]);
return eepro100_read2(s, addr - s->region1);
}
static uint32_t ioport_read4(void *opaque, uint32_t addr)
{
EEPRO100State *s = opaque;
return eepro100_read4(s, addr - s->region[1]);
return eepro100_read4(s, addr - s->region1);
}
static void ioport_write1(void *opaque, uint32_t addr, uint32_t val)
@ -1509,19 +1631,19 @@ static void ioport_write1(void *opaque, uint32_t addr, uint32_t val)
#if 0
logout("addr=%s val=0x%02x\n", regname(addr), val);
#endif
eepro100_write1(s, addr - s->region[1], val);
eepro100_write1(s, addr - s->region1, val);
}
static void ioport_write2(void *opaque, uint32_t addr, uint32_t val)
{
EEPRO100State *s = opaque;
eepro100_write2(s, addr - s->region[1], val);
eepro100_write2(s, addr - s->region1, val);
}
static void ioport_write4(void *opaque, uint32_t addr, uint32_t val)
{
EEPRO100State *s = opaque;
eepro100_write4(s, addr - s->region[1], val);
eepro100_write4(s, addr - s->region1, val);
}
/***********************************************************/
@ -1544,7 +1666,7 @@ static void pci_map(PCIDevice * pci_dev, int region_num,
register_ioport_write(addr, size, 4, ioport_write4, s);
register_ioport_read(addr, size, 4, ioport_read4, s);
s->region[region_num] = addr;
s->region1 = addr;
}
/*****************************************************************************
@ -1619,22 +1741,6 @@ static CPUReadMemoryFunc * const pci_mmio_read[] = {
pci_mmio_readl
};
static void pci_mmio_map(PCIDevice * pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
TRACE(OTHER, logout("region %d, addr=0x%08"FMT_PCIBUS", "
"size=0x%08"FMT_PCIBUS", type=%d\n",
region_num, addr, size, type));
assert(region_num == 0 || region_num == 2);
/* Map control / status registers and flash. */
cpu_register_physical_memory(addr, size, s->mmio_index);
s->region[region_num] = addr;
}
static int nic_can_receive(VLANClientState *nc)
{
EEPRO100State *s = DO_UPCAST(NICState, nc, nc)->opaque;
@ -1653,19 +1759,32 @@ static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size
*/
EEPRO100State *s = DO_UPCAST(NICState, nc, nc)->opaque;
uint16_t rfd_status = 0xa000;
#if defined(CONFIG_PAD_RECEIVED_FRAMES)
uint8_t min_buf[60];
#endif
static const uint8_t broadcast_macaddr[6] =
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
#if defined(CONFIG_PAD_RECEIVED_FRAMES)
/* Pad to minimum Ethernet frame length */
if (size < sizeof(min_buf)) {
memcpy(min_buf, buf, size);
memset(&min_buf[size], 0, sizeof(min_buf) - size);
buf = min_buf;
size = sizeof(min_buf);
}
#endif
if (s->configuration[8] & 0x80) {
/* CSMA is disabled. */
logout("%p received while CSMA is disabled\n", s);
return -1;
#if !defined(CONFIG_PAD_RECEIVED_FRAMES)
} else if (size < 64 && (s->configuration[7] & BIT(0))) {
/* Short frame and configuration byte 7/0 (discard short receive) set:
* Short frame is discarded */
logout("%p received short frame (%zu byte)\n", s, size);
s->statistics.rx_short_frame_errors++;
#if 0
return -1;
#endif
} else if ((size > MAX_ETH_FRAME_SIZE + 4) && !(s->configuration[18] & BIT(3))) {
@ -1734,8 +1853,8 @@ static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size
}
/* !!! */
eepro100_rx_t rx;
cpu_physical_memory_read(s->ru_base + s->ru_offset, (uint8_t *) & rx,
offsetof(eepro100_rx_t, packet));
cpu_physical_memory_read(s->ru_base + s->ru_offset, &rx,
sizeof(eepro100_rx_t));
uint16_t rfd_command = le16_to_cpu(rx.command);
uint16_t rfd_size = le16_to_cpu(rx.size);
@ -1744,14 +1863,17 @@ static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size
"(%zu bytes); data truncated\n", rfd_size, size);
size = rfd_size;
}
#if !defined(CONFIG_PAD_RECEIVED_FRAMES)
if (size < 64) {
rfd_status |= 0x0080;
}
#endif
TRACE(OTHER, logout("command 0x%04x, link 0x%08x, addr 0x%08x, size %u\n",
rfd_command, rx.link, rx.rx_buf_addr, rfd_size));
stw_phys(s->ru_base + s->ru_offset + offsetof(eepro100_rx_t, status),
rfd_status);
stw_phys(s->ru_base + s->ru_offset + offsetof(eepro100_rx_t, count), size);
e100_stw_le_phys(s->ru_base + s->ru_offset +
offsetof(eepro100_rx_t, status), rfd_status);
e100_stw_le_phys(s->ru_base + s->ru_offset +
offsetof(eepro100_rx_t, count), size);
/* Early receive interrupt not supported. */
#if 0
eepro100_er_interrupt(s);
@ -1766,7 +1888,7 @@ static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size
assert(!(s->configuration[17] & BIT(0)));
#endif
cpu_physical_memory_write(s->ru_base + s->ru_offset +
offsetof(eepro100_rx_t, packet), buf, size);
sizeof(eepro100_rx_t), buf, size);
s->statistics.rx_good_frames++;
eepro100_fr_interrupt(s);
s->ru_offset = le32_to_cpu(rx.link);
@ -1801,7 +1923,6 @@ static const VMStateDescription vmstate_eepro100 = {
/* The eeprom should be saved and restored by its own routines. */
VMSTATE_UINT32(device, EEPRO100State),
/* TODO check device. */
VMSTATE_UINT32(pointer, EEPRO100State),
VMSTATE_UINT32(cu_base, EEPRO100State),
VMSTATE_UINT32(cu_offset, EEPRO100State),
VMSTATE_UINT32(ru_base, EEPRO100State),
@ -1880,19 +2001,18 @@ static int e100_nic_init(PCIDevice *pci_dev)
/* Handler for memory-mapped I/O */
s->mmio_index =
cpu_register_io_memory(pci_mmio_read, pci_mmio_write, s,
DEVICE_NATIVE_ENDIAN);
DEVICE_LITTLE_ENDIAN);
pci_register_bar_simple(&s->dev, 0, PCI_MEM_SIZE,
PCI_BASE_ADDRESS_MEM_PREFETCH, s->mmio_index);
pci_register_bar(&s->dev, 0, PCI_MEM_SIZE,
PCI_BASE_ADDRESS_SPACE_MEMORY |
PCI_BASE_ADDRESS_MEM_PREFETCH, pci_mmio_map);
pci_register_bar(&s->dev, 1, PCI_IO_SIZE, PCI_BASE_ADDRESS_SPACE_IO,
pci_map);
pci_register_bar(&s->dev, 2, PCI_FLASH_SIZE, PCI_BASE_ADDRESS_SPACE_MEMORY,
pci_mmio_map);
pci_register_bar_simple(&s->dev, 2, PCI_FLASH_SIZE, 0, s->mmio_index);
qemu_macaddr_default_if_unset(&s->conf.macaddr);
logout("macaddr: %s\n", nic_dump(&s->conf.macaddr.a[0], 6));
assert(s->region[1] == 0);
assert(s->region1 == 0);
nic_reset(s);

View File

@ -1129,15 +1129,6 @@ void ahci_uninit(AHCIState *s)
qemu_free(s->dev);
}
void ahci_pci_map(PCIDevice *pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
struct AHCIPCIState *d = (struct AHCIPCIState *)pci_dev;
AHCIState *s = &d->ahci;
cpu_register_physical_memory(addr, size, s->mem);
}
void ahci_reset(void *opaque)
{
struct AHCIPCIState *d = opaque;

View File

@ -325,9 +325,6 @@ typedef struct NCQFrame {
void ahci_init(AHCIState *s, DeviceState *qdev, int ports);
void ahci_uninit(AHCIState *s);
void ahci_pci_map(PCIDevice *pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type);
void ahci_reset(void *opaque);
#endif /* HW_IDE_AHCI_H */

View File

@ -94,8 +94,7 @@ static int pci_ich9_ahci_init(PCIDevice *dev)
qemu_register_reset(ahci_reset, d);
/* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */
pci_register_bar(&d->card, 5, 0x1000, PCI_BASE_ADDRESS_SPACE_MEMORY,
ahci_pci_map);
pci_register_bar_simple(&d->card, 5, 0x1000, 0, d->ahci.mem);
msi_init(dev, 0x50, 1, true, false);
@ -110,10 +109,7 @@ static int pci_ich9_uninit(PCIDevice *dev)
struct AHCIPCIState *d;
d = DO_UPCAST(struct AHCIPCIState, card, dev);
if (msi_enabled(dev)) {
msi_uninit(dev);
}
msi_uninit(dev);
qemu_unregister_reset(ahci_reset, d);
ahci_uninit(&d->ahci);

View File

@ -1109,14 +1109,6 @@ static CPUWriteMemoryFunc * const intel_hda_mmio_write[3] = {
intel_hda_mmio_writel,
};
static void intel_hda_map(PCIDevice *pci, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
IntelHDAState *d = DO_UPCAST(IntelHDAState, pci, pci);
cpu_register_physical_memory(addr, 0x4000, d->mmio_addr);
}
/* --------------------------------------------------------------------- */
static void intel_hda_reset(DeviceState *dev)
@ -1158,8 +1150,7 @@ static int intel_hda_init(PCIDevice *pci)
d->mmio_addr = cpu_register_io_memory(intel_hda_mmio_read,
intel_hda_mmio_write, d,
DEVICE_NATIVE_ENDIAN);
pci_register_bar(&d->pci, 0, 0x4000, PCI_BASE_ADDRESS_SPACE_MEMORY,
intel_hda_map);
pci_register_bar_simple(&d->pci, 0, 0x4000, 0, d->mmio_addr);
if (d->msi) {
msi_init(&d->pci, 0x50, 1, true, false);
}
@ -1174,9 +1165,7 @@ static int intel_hda_exit(PCIDevice *pci)
{
IntelHDAState *d = DO_UPCAST(IntelHDAState, pci, pci);
if (d->msi) {
msi_uninit(&d->pci);
}
msi_uninit(&d->pci);
cpu_unregister_io_memory(d->mmio_addr);
return 0;
}

View File

@ -2094,15 +2094,6 @@ static void lsi_ram_mapfunc(PCIDevice *pci_dev, int region_num,
cpu_register_physical_memory(addr + 0, 0x2000, s->ram_io_addr);
}
static void lsi_mmio_mapfunc(PCIDevice *pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
LSIState *s = DO_UPCAST(LSIState, dev, pci_dev);
DPRINTF("Mapping registers at %08"FMT_PCIBUS"\n", addr);
cpu_register_physical_memory(addr + 0, 0x400, s->mmio_io_addr);
}
static void lsi_scsi_reset(DeviceState *dev)
{
LSIState *s = DO_UPCAST(LSIState, dev.qdev, dev);
@ -2245,8 +2236,7 @@ static int lsi_scsi_init(PCIDevice *dev)
pci_register_bar(&s->dev, 0, 256,
PCI_BASE_ADDRESS_SPACE_IO, lsi_io_mapfunc);
pci_register_bar(&s->dev, 1, 0x400,
PCI_BASE_ADDRESS_SPACE_MEMORY, lsi_mmio_mapfunc);
pci_register_bar_simple(&s->dev, 1, 0x400, 0, s->mmio_io_addr);
pci_register_bar(&s->dev, 2, 0x2000,
PCI_BASE_ADDRESS_SPACE_MEMORY, lsi_ram_mapfunc);
QTAILQ_INIT(&s->queue);

View File

@ -164,9 +164,17 @@ int msi_init(struct PCIDevice *dev, uint8_t offset,
void msi_uninit(struct PCIDevice *dev)
{
uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
uint8_t cap_size = msi_cap_sizeof(flags);
uint16_t flags;
uint8_t cap_size;
if (!(dev->cap_present & QEMU_PCI_CAP_MSI)) {
return;
}
flags = pci_get_word(dev->config + msi_flags_off(dev));
cap_size = msi_cap_sizeof(flags);
pci_del_capability(dev, PCI_CAP_ID_MSIX, cap_size);
dev->cap_present &= ~QEMU_PCI_CAP_MSI;
MSI_DEV_PRINTF(dev, "uninit\n");
}

View File

@ -126,6 +126,13 @@ static void pci_change_irq_level(PCIDevice *pci_dev, int irq_num, int change)
bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
}
int pci_bus_get_irq_level(PCIBus *bus, int irq_num)
{
assert(irq_num >= 0);
assert(irq_num < bus->nirq);
return !!bus->irq_count[irq_num];
}
/* Update interrupt status bit in config space on interrupt
* state change. */
static void pci_update_irq_status(PCIDevice *dev)
@ -859,6 +866,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
r->filtered_size = size;
r->type = type;
r->map_func = map_func;
r->ram_addr = IO_MEM_UNASSIGNED;
wmask = ~(size - 1);
addr = pci_bar(pci_dev, region_num);
@ -877,6 +885,22 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
}
}
static void pci_simple_bar_mapfunc(PCIDevice *pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
cpu_register_physical_memory(addr, size,
pci_dev->io_regions[region_num].ram_addr);
}
void pci_register_bar_simple(PCIDevice *pci_dev, int region_num,
pcibus_t size, uint8_t attr, ram_addr_t ram_addr)
{
pci_register_bar(pci_dev, region_num, size,
PCI_BASE_ADDRESS_SPACE_MEMORY | attr,
pci_simple_bar_mapfunc);
pci_dev->io_regions[region_num].ram_addr = ram_addr;
}
static void pci_bridge_filter(PCIDevice *d, pcibus_t *addr, pcibus_t *size,
uint8_t type)
{
@ -1145,6 +1169,7 @@ static const pci_class_desc pci_class_descriptions[] =
{ 0x0400, "Video controller", "video"},
{ 0x0401, "Audio controller", "sound"},
{ 0x0402, "Phone"},
{ 0x0403, "Audio controller", "sound"},
{ 0x0480, "Multimedia controller"},
{ 0x0500, "RAM controller", "memory"},
{ 0x0501, "Flash controller", "flash"},

View File

@ -92,6 +92,7 @@ typedef struct PCIIORegion {
pcibus_t filtered_size;
uint8_t type;
PCIMapIORegionFunc *map_func;
ram_addr_t ram_addr;
} PCIIORegion;
#define PCI_ROM_SLOT 6
@ -200,6 +201,8 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name,
void pci_register_bar(PCIDevice *pci_dev, int region_num,
pcibus_t size, uint8_t type,
PCIMapIORegionFunc *map_func);
void pci_register_bar_simple(PCIDevice *pci_dev, int region_num,
pcibus_t size, uint8_t attr, ram_addr_t ram_addr);
int pci_add_capability(PCIDevice *pdev, uint8_t cap_id,
uint8_t offset, uint8_t size);
@ -234,6 +237,7 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
PCIBus *pci_bus_new(DeviceState *parent, const char *name, uint8_t devfn_min);
void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
void *irq_opaque, int nirq);
int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev);
PCIBus *pci_register_bus(DeviceState *parent, const char *name,
pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,

View File

@ -214,19 +214,6 @@ static CPUReadMemoryFunc * const pcnet_mmio_read[] = {
&pcnet_mmio_readl
};
static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, pci_dev);
#ifdef PCNET_DEBUG_IO
printf("pcnet_mmio_map addr=0x%08"FMT_PCIBUS" 0x%08"FMT_PCIBUS"\n",
addr, size);
#endif
cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->state.mmio_index);
}
static void pci_physical_memory_write(void *dma_opaque, target_phys_addr_t addr,
uint8_t *buf, int len, int do_bswap)
{
@ -300,8 +287,7 @@ static int pci_pcnet_init(PCIDevice *pci_dev)
pci_register_bar(pci_dev, 0, PCNET_IOPORT_SIZE,
PCI_BASE_ADDRESS_SPACE_IO, pcnet_ioport_map);
pci_register_bar(pci_dev, 1, PCNET_PNPMMIO_SIZE,
PCI_BASE_ADDRESS_SPACE_MEMORY, pcnet_mmio_map);
pci_register_bar_simple(pci_dev, 1, PCNET_PNPMMIO_SIZE, 0, s->mmio_index);
s->irq = pci_dev->irq[0];
s->phys_mem_read = pci_physical_memory_read;

View File

@ -37,10 +37,31 @@
typedef PCIHostState I440FXState;
#define PIIX_NUM_PIC_IRQS 16 /* i8259 * 2 */
#define PIIX_NUM_PIRQS 4ULL /* PIRQ[A-D] */
#define PIIX_PIRQC 0x60
typedef struct PIIX3State {
PCIDevice dev;
int pci_irq_levels[4];
/*
* bitmap to track pic levels.
* The pic level is the logical OR of all the PCI irqs mapped to it
* So one PIC level is tracked by PIIX_NUM_PIRQS bits.
*
* PIRQ is mapped to PIC pins, we track it by
* PIIX_NUM_PIRQS * PIIX_NUM_PIC_IRQS = 64 bits with
* pic_irq * PIIX_NUM_PIRQS + pirq
*/
#if PIIX_NUM_PIC_IRQS * PIIX_NUM_PIRQS > 64
#error "unable to encode pic state in 64bit in pic_levels."
#endif
uint64_t pic_levels;
qemu_irq *pic;
/* This member isn't used. Just for save/load compatibility */
int32_t pci_irq_levels_vmstate[PIIX_NUM_PIRQS];
} PIIX3State;
struct PCII440FXState {
@ -55,16 +76,16 @@ struct PCII440FXState {
#define I440FX_PAM_SIZE 7
#define I440FX_SMRAM 0x72
static void piix3_set_irq(void *opaque, int irq_num, int level);
static void piix3_set_irq(void *opaque, int pirq, int level);
/* return the global irq number corresponding to a given device irq
pin. We could also use the bus number to have a more precise
mapping. */
static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
static int pci_slot_get_pirq(PCIDevice *pci_dev, int pci_intx)
{
int slot_addend;
slot_addend = (pci_dev->devfn >> 3) - 1;
return (irq_num + slot_addend) & 3;
return (pci_intx + slot_addend) & 3;
}
static void update_pam(PCII440FXState *d, uint32_t start, uint32_t end, int r)
@ -162,9 +183,11 @@ static int i440fx_load_old(QEMUFile* f, void *opaque, int version_id)
i440fx_update_memory_mappings(d);
qemu_get_8s(f, &d->smm_enabled);
if (version_id == 2)
for (i = 0; i < 4; i++)
d->piix3->pci_irq_levels[i] = qemu_get_be32(f);
if (version_id == 2) {
for (i = 0; i < PIIX_NUM_PIRQS; i++) {
qemu_get_be32(f); /* dummy load for compatibility */
}
}
return 0;
}
@ -236,7 +259,7 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn, qemu_irq *
piix3 = DO_UPCAST(PIIX3State, dev,
pci_create_simple_multifunction(b, -1, true, "PIIX3"));
piix3->pic = pic;
pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3, 4);
pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3, PIIX_NUM_PIRQS);
(*pi440fx_state)->piix3 = piix3;
*piix3_devfn = piix3->dev.devfn;
@ -250,26 +273,60 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn, qemu_irq *
}
/* PIIX3 PCI to ISA bridge */
static void piix3_set_irq(void *opaque, int irq_num, int level)
static void piix3_set_irq_pic(PIIX3State *piix3, int pic_irq)
{
qemu_set_irq(piix3->pic[pic_irq],
!!(piix3->pic_levels &
(((1UL << PIIX_NUM_PIRQS) - 1) <<
(pic_irq * PIIX_NUM_PIRQS))));
}
static void piix3_set_irq_level(PIIX3State *piix3, int pirq, int level)
{
int pic_irq;
uint64_t mask;
pic_irq = piix3->dev.config[PIIX_PIRQC + pirq];
if (pic_irq >= PIIX_NUM_PIC_IRQS) {
return;
}
mask = 1ULL << ((pic_irq * PIIX_NUM_PIRQS) + pirq);
piix3->pic_levels &= ~mask;
piix3->pic_levels |= mask * !!level;
piix3_set_irq_pic(piix3, pic_irq);
}
static void piix3_set_irq(void *opaque, int pirq, int level)
{
int i, pic_irq, pic_level;
PIIX3State *piix3 = opaque;
piix3_set_irq_level(piix3, pirq, level);
}
piix3->pci_irq_levels[irq_num] = level;
/* irq routing is changed. so rebuild bitmap */
static void piix3_update_irq_levels(PIIX3State *piix3)
{
int pirq;
/* now we change the pic irq level according to the piix irq mappings */
/* XXX: optimize */
pic_irq = piix3->dev.config[0x60 + irq_num];
if (pic_irq < 16) {
/* The pic level is the logical OR of all the PCI irqs mapped
to it */
pic_level = 0;
for (i = 0; i < 4; i++) {
if (pic_irq == piix3->dev.config[0x60 + i])
pic_level |= piix3->pci_irq_levels[i];
piix3->pic_levels = 0;
for (pirq = 0; pirq < PIIX_NUM_PIRQS; pirq++) {
piix3_set_irq_level(piix3, pirq,
pci_bus_get_irq_level(piix3->dev.bus, pirq));
}
}
static void piix3_write_config(PCIDevice *dev,
uint32_t address, uint32_t val, int len)
{
pci_default_write_config(dev, address, val, len);
if (ranges_overlap(address, len, PIIX_PIRQC, 4)) {
PIIX3State *piix3 = DO_UPCAST(PIIX3State, dev, dev);
int pic_irq;
piix3_update_irq_levels(piix3);
for (pic_irq = 0; pic_irq < PIIX_NUM_PIC_IRQS; pic_irq++) {
piix3_set_irq_pic(piix3, pic_irq);
}
qemu_set_irq(piix3->pic[pic_irq], pic_level);
}
}
@ -310,7 +367,25 @@ static void piix3_reset(void *opaque)
pci_conf[0xac] = 0x00;
pci_conf[0xae] = 0x00;
memset(d->pci_irq_levels, 0, sizeof(d->pci_irq_levels));
d->pic_levels = 0;
}
static int piix3_post_load(void *opaque, int version_id)
{
PIIX3State *piix3 = opaque;
piix3_update_irq_levels(piix3);
return 0;
}
static void piix3_pre_save(void *opaque)
{
int i;
PIIX3State *piix3 = opaque;
for (i = 0; i < ARRAY_SIZE(piix3->pci_irq_levels_vmstate); i++) {
piix3->pci_irq_levels_vmstate[i] =
pci_bus_get_irq_level(piix3->dev.bus, i);
}
}
static const VMStateDescription vmstate_piix3 = {
@ -318,9 +393,12 @@ static const VMStateDescription vmstate_piix3 = {
.version_id = 3,
.minimum_version_id = 2,
.minimum_version_id_old = 2,
.post_load = piix3_post_load,
.pre_save = piix3_pre_save,
.fields = (VMStateField []) {
VMSTATE_PCI_DEVICE(dev, PIIX3State),
VMSTATE_INT32_ARRAY_V(pci_irq_levels, PIIX3State, 4, 3),
VMSTATE_INT32_ARRAY_V(pci_irq_levels_vmstate, PIIX3State,
PIIX_NUM_PIRQS, 3),
VMSTATE_END_OF_LIST()
}
};
@ -359,6 +437,7 @@ static PCIDeviceInfo i440fx_info[] = {
.qdev.no_user = 1,
.no_hotplug = 1,
.init = piix3_initfn,
.config_write = piix3_write_config,
},{
/* end of list */
}

View File

@ -3375,14 +3375,6 @@ static const VMStateDescription vmstate_rtl8139 = {
/***********************************************************/
/* PCI RTL8139 definitions */
static void rtl8139_mmio_map(PCIDevice *pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
RTL8139State *s = DO_UPCAST(RTL8139State, dev, pci_dev);
cpu_register_physical_memory(addr + 0, 0x100, s->rtl8139_mmio_io_addr);
}
static void rtl8139_ioport_map(PCIDevice *pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
@ -3478,8 +3470,7 @@ static int pci_rtl8139_init(PCIDevice *dev)
pci_register_bar(&s->dev, 0, 0x100,
PCI_BASE_ADDRESS_SPACE_IO, rtl8139_ioport_map);
pci_register_bar(&s->dev, 1, 0x100,
PCI_BASE_ADDRESS_SPACE_MEMORY, rtl8139_mmio_map);
pci_register_bar_simple(&s->dev, 1, 0x100, 0, s->rtl8139_mmio_io_addr);
qemu_macaddr_default_if_unset(&s->conf.macaddr);

View File

@ -1708,13 +1708,6 @@ typedef struct {
OHCIState state;
} OHCIPCIState;
static void ohci_mapfunc(PCIDevice *pci_dev, int i,
pcibus_t addr, pcibus_t size, int type)
{
OHCIPCIState *ohci = DO_UPCAST(OHCIPCIState, pci_dev, pci_dev);
cpu_register_physical_memory(addr, size, ohci->state.mem);
}
static int usb_ohci_initfn_pci(struct PCIDevice *dev)
{
OHCIPCIState *ohci = DO_UPCAST(OHCIPCIState, pci_dev, dev);
@ -1732,8 +1725,7 @@ static int usb_ohci_initfn_pci(struct PCIDevice *dev)
ohci->state.irq = ohci->pci_dev.irq[0];
/* TODO: avoid cast below by using dev */
pci_register_bar(&ohci->pci_dev, 0, 256,
PCI_BASE_ADDRESS_SPACE_MEMORY, ohci_mapfunc);
pci_register_bar_simple(&ohci->pci_dev, 0, 256, 0, ohci->state.mem);
return 0;
}

View File

@ -297,10 +297,50 @@ static int vhost_verify_ring_mappings(struct vhost_dev *dev,
return 0;
}
static struct vhost_memory_region *vhost_dev_find_reg(struct vhost_dev *dev,
uint64_t start_addr,
uint64_t size)
{
int i, n = dev->mem->nregions;
for (i = 0; i < n; ++i) {
struct vhost_memory_region *reg = dev->mem->regions + i;
if (ranges_overlap(reg->guest_phys_addr, reg->memory_size,
start_addr, size)) {
return reg;
}
}
return NULL;
}
static bool vhost_dev_cmp_memory(struct vhost_dev *dev,
uint64_t start_addr,
uint64_t size,
uint64_t uaddr)
{
struct vhost_memory_region *reg = vhost_dev_find_reg(dev, start_addr, size);
uint64_t reglast;
uint64_t memlast;
if (!reg) {
return true;
}
reglast = range_get_last(reg->guest_phys_addr, reg->memory_size);
memlast = range_get_last(start_addr, size);
/* Need to extend region? */
if (start_addr < reg->guest_phys_addr || memlast > reglast) {
return true;
}
/* userspace_addr changed? */
return uaddr != reg->userspace_addr + start_addr - reg->guest_phys_addr;
}
static void vhost_client_set_memory(CPUPhysMemoryClient *client,
target_phys_addr_t start_addr,
ram_addr_t size,
ram_addr_t phys_offset)
ram_addr_t phys_offset,
bool log_dirty)
{
struct vhost_dev *dev = container_of(client, struct vhost_dev, client);
ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
@ -308,10 +348,29 @@ static void vhost_client_set_memory(CPUPhysMemoryClient *client,
(dev->mem->nregions + 1) * sizeof dev->mem->regions[0];
uint64_t log_size;
int r;
dev->mem = qemu_realloc(dev->mem, s);
if (log_dirty) {
flags = IO_MEM_UNASSIGNED;
}
assert(size);
/* Optimize no-change case. At least cirrus_vga does this a lot at this time. */
if (flags == IO_MEM_RAM) {
if (!vhost_dev_cmp_memory(dev, start_addr, size,
(uintptr_t)qemu_get_ram_ptr(phys_offset))) {
/* Region exists with same address. Nothing to do. */
return;
}
} else {
if (!vhost_dev_find_reg(dev, start_addr, size)) {
/* Removing region that we don't access. Nothing to do. */
return;
}
}
vhost_dev_unassign_memory(dev, start_addr, size);
if (flags == IO_MEM_RAM) {
/* Add given mapping, merging adjacent regions if any */

View File

@ -355,31 +355,6 @@ static void i6300esb_mem_writel(void *vp, target_phys_addr_t addr, uint32_t val)
}
}
static void i6300esb_map(PCIDevice *dev, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
static CPUReadMemoryFunc * const mem_read[3] = {
i6300esb_mem_readb,
i6300esb_mem_readw,
i6300esb_mem_readl,
};
static CPUWriteMemoryFunc * const mem_write[3] = {
i6300esb_mem_writeb,
i6300esb_mem_writew,
i6300esb_mem_writel,
};
I6300State *d = DO_UPCAST(I6300State, dev, dev);
int io_mem;
i6300esb_debug("addr = %"FMT_PCIBUS", size = %"FMT_PCIBUS", type = %d\n",
addr, size, type);
io_mem = cpu_register_io_memory(mem_read, mem_write, d,
DEVICE_NATIVE_ENDIAN);
cpu_register_physical_memory (addr, 0x10, io_mem);
/* qemu_register_coalesced_mmio (addr, 0x10); ? */
}
static const VMStateDescription vmstate_i6300esb = {
.name = "i6300esb_wdt",
.version_id = sizeof(I6300State),
@ -407,6 +382,17 @@ static int i6300esb_init(PCIDevice *dev)
{
I6300State *d = DO_UPCAST(I6300State, dev, dev);
uint8_t *pci_conf;
int io_mem;
static CPUReadMemoryFunc * const mem_read[3] = {
i6300esb_mem_readb,
i6300esb_mem_readw,
i6300esb_mem_readl,
};
static CPUWriteMemoryFunc * const mem_write[3] = {
i6300esb_mem_writeb,
i6300esb_mem_writew,
i6300esb_mem_writel,
};
i6300esb_debug("I6300State = %p\n", d);
@ -418,8 +404,10 @@ static int i6300esb_init(PCIDevice *dev)
pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_ESB_9);
pci_config_set_class(pci_conf, PCI_CLASS_SYSTEM_OTHER);
pci_register_bar(&d->dev, 0, 0x10,
PCI_BASE_ADDRESS_SPACE_MEMORY, i6300esb_map);
io_mem = cpu_register_io_memory(mem_read, mem_write, d,
DEVICE_NATIVE_ENDIAN);
pci_register_bar_simple(&d->dev, 0, 0x10, 0, io_mem);
/* qemu_register_coalesced_mmio (addr, 0x10); ? */
return 0;
}

View File

@ -245,48 +245,60 @@ err:
/*
* dirty pages logging control
*/
static int kvm_dirty_pages_log_change(target_phys_addr_t phys_addr,
ram_addr_t size, int flags, int mask)
static int kvm_mem_flags(KVMState *s, bool log_dirty)
{
return log_dirty ? KVM_MEM_LOG_DIRTY_PAGES : 0;
}
static int kvm_slot_dirty_pages_log_change(KVMSlot *mem, bool log_dirty)
{
KVMState *s = kvm_state;
KVMSlot *mem = kvm_lookup_matching_slot(s, phys_addr, phys_addr + size);
int flags, mask = KVM_MEM_LOG_DIRTY_PAGES;
int old_flags;
if (mem == NULL) {
fprintf(stderr, "BUG: %s: invalid parameters " TARGET_FMT_plx "-"
TARGET_FMT_plx "\n", __func__, phys_addr,
(target_phys_addr_t)(phys_addr + size - 1));
return -EINVAL;
}
old_flags = mem->flags;
flags = (mem->flags & ~mask) | flags;
flags = (mem->flags & ~mask) | kvm_mem_flags(s, log_dirty);
mem->flags = flags;
/* If nothing changed effectively, no need to issue ioctl */
if (s->migration_log) {
flags |= KVM_MEM_LOG_DIRTY_PAGES;
}
if (flags == old_flags) {
return 0;
return 0;
}
return kvm_set_user_memory_region(s, mem);
}
static int kvm_dirty_pages_log_change(target_phys_addr_t phys_addr,
ram_addr_t size, bool log_dirty)
{
KVMState *s = kvm_state;
KVMSlot *mem = kvm_lookup_matching_slot(s, phys_addr, phys_addr + size);
if (mem == NULL) {
fprintf(stderr, "BUG: %s: invalid parameters " TARGET_FMT_plx "-"
TARGET_FMT_plx "\n", __func__, phys_addr,
(target_phys_addr_t)(phys_addr + size - 1));
return -EINVAL;
}
return kvm_slot_dirty_pages_log_change(mem, log_dirty);
}
static int kvm_log_start(CPUPhysMemoryClient *client,
target_phys_addr_t phys_addr, ram_addr_t size)
{
return kvm_dirty_pages_log_change(phys_addr, size, KVM_MEM_LOG_DIRTY_PAGES,
KVM_MEM_LOG_DIRTY_PAGES);
return kvm_dirty_pages_log_change(phys_addr, size, true);
}
static int kvm_log_stop(CPUPhysMemoryClient *client,
target_phys_addr_t phys_addr, ram_addr_t size)
{
return kvm_dirty_pages_log_change(phys_addr, size, 0,
KVM_MEM_LOG_DIRTY_PAGES);
return kvm_dirty_pages_log_change(phys_addr, size, false);
}
static int kvm_set_migration_log(int enable)
@ -508,7 +520,7 @@ kvm_check_extension_list(KVMState *s, const KVMCapabilityInfo *list)
}
static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
ram_addr_t phys_offset)
ram_addr_t phys_offset, bool log_dirty)
{
KVMState *s = kvm_state;
ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
@ -533,7 +545,8 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
(start_addr + size <= mem->start_addr + mem->memory_size) &&
(phys_offset - start_addr == mem->phys_offset - mem->start_addr)) {
/* The new slot fits into the existing one and comes with
* identical parameters - nothing to be done. */
* identical parameters - update flags and done. */
kvm_slot_dirty_pages_log_change(mem, log_dirty);
return;
}
@ -563,7 +576,7 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
mem->memory_size = old.memory_size;
mem->start_addr = old.start_addr;
mem->phys_offset = old.phys_offset;
mem->flags = 0;
mem->flags = kvm_mem_flags(s, log_dirty);
err = kvm_set_user_memory_region(s, mem);
if (err) {
@ -584,7 +597,7 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
mem->memory_size = start_addr - old.start_addr;
mem->start_addr = old.start_addr;
mem->phys_offset = old.phys_offset;
mem->flags = 0;
mem->flags = kvm_mem_flags(s, log_dirty);
err = kvm_set_user_memory_region(s, mem);
if (err) {
@ -603,7 +616,7 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
size_delta = mem->start_addr - old.start_addr;
mem->memory_size = old.memory_size - size_delta;
mem->phys_offset = old.phys_offset + size_delta;
mem->flags = 0;
mem->flags = kvm_mem_flags(s, log_dirty);
err = kvm_set_user_memory_region(s, mem);
if (err) {
@ -626,7 +639,7 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
mem->memory_size = size;
mem->start_addr = start_addr;
mem->phys_offset = phys_offset;
mem->flags = 0;
mem->flags = kvm_mem_flags(s, log_dirty);
err = kvm_set_user_memory_region(s, mem);
if (err) {
@ -638,9 +651,10 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
static void kvm_client_set_memory(struct CPUPhysMemoryClient *client,
target_phys_addr_t start_addr,
ram_addr_t size, ram_addr_t phys_offset)
ram_addr_t size, ram_addr_t phys_offset,
bool log_dirty)
{
kvm_set_phys_mem(start_addr, size, phys_offset);
kvm_set_phys_mem(start_addr, size, phys_offset, log_dirty);
}
static int kvm_client_sync_dirty_bitmap(struct CPUPhysMemoryClient *client,