Add map client retry notification (Avi Kivity)
The target memory mapping API may fail if the bounce buffer resources are exhausted. Add a notification mechanism to allow clients to retry the mapping operation when resources become available again. Signed-off-by: Avi Kivity <avi@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6395 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
6d16c2f88f
commit
ba223c29da
|
@ -928,6 +928,8 @@ void *cpu_physical_memory_map(target_phys_addr_t addr,
|
||||||
int is_write);
|
int is_write);
|
||||||
void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
|
void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
|
||||||
int is_write, target_phys_addr_t access_len);
|
int is_write, target_phys_addr_t access_len);
|
||||||
|
void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque));
|
||||||
|
void cpu_unregister_map_client(void *cookie);
|
||||||
|
|
||||||
uint32_t ldub_phys(target_phys_addr_t addr);
|
uint32_t ldub_phys(target_phys_addr_t addr);
|
||||||
uint32_t lduw_phys(target_phys_addr_t addr);
|
uint32_t lduw_phys(target_phys_addr_t addr);
|
||||||
|
|
40
exec.c
40
exec.c
|
@ -3053,10 +3053,49 @@ typedef struct {
|
||||||
|
|
||||||
static BounceBuffer bounce;
|
static BounceBuffer bounce;
|
||||||
|
|
||||||
|
typedef struct MapClient {
|
||||||
|
void *opaque;
|
||||||
|
void (*callback)(void *opaque);
|
||||||
|
LIST_ENTRY(MapClient) link;
|
||||||
|
} MapClient;
|
||||||
|
|
||||||
|
static LIST_HEAD(map_client_list, MapClient) map_client_list
|
||||||
|
= LIST_HEAD_INITIALIZER(map_client_list);
|
||||||
|
|
||||||
|
void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque))
|
||||||
|
{
|
||||||
|
MapClient *client = qemu_malloc(sizeof(*client));
|
||||||
|
|
||||||
|
client->opaque = opaque;
|
||||||
|
client->callback = callback;
|
||||||
|
LIST_INSERT_HEAD(&map_client_list, client, link);
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cpu_unregister_map_client(void *_client)
|
||||||
|
{
|
||||||
|
MapClient *client = (MapClient *)_client;
|
||||||
|
|
||||||
|
LIST_REMOVE(client, link);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cpu_notify_map_clients(void)
|
||||||
|
{
|
||||||
|
MapClient *client;
|
||||||
|
|
||||||
|
while (!LIST_EMPTY(&map_client_list)) {
|
||||||
|
client = LIST_FIRST(&map_client_list);
|
||||||
|
client->callback(client->opaque);
|
||||||
|
LIST_REMOVE(client, link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Map a physical memory region into a host virtual address.
|
/* Map a physical memory region into a host virtual address.
|
||||||
* May map a subset of the requested range, given by and returned in *plen.
|
* May map a subset of the requested range, given by and returned in *plen.
|
||||||
* May return NULL if resources needed to perform the mapping are exhausted.
|
* May return NULL if resources needed to perform the mapping are exhausted.
|
||||||
* Use only for reads OR writes - not for read-modify-write operations.
|
* Use only for reads OR writes - not for read-modify-write operations.
|
||||||
|
* Use cpu_register_map_client() to know when retrying the map operation is
|
||||||
|
* likely to succeed.
|
||||||
*/
|
*/
|
||||||
void *cpu_physical_memory_map(target_phys_addr_t addr,
|
void *cpu_physical_memory_map(target_phys_addr_t addr,
|
||||||
target_phys_addr_t *plen,
|
target_phys_addr_t *plen,
|
||||||
|
@ -3146,6 +3185,7 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
|
||||||
}
|
}
|
||||||
qemu_free(bounce.buffer);
|
qemu_free(bounce.buffer);
|
||||||
bounce.buffer = NULL;
|
bounce.buffer = NULL;
|
||||||
|
cpu_notify_map_clients();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* warning: addr must be aligned */
|
/* warning: addr must be aligned */
|
||||||
|
|
Reference in New Issue