mirror of https://github.com/proxmox/mirror_qemu
Xen 2017/07/18
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJZbokoAAoJEIlPj0hw4a6QgloP/jc9tVFrPjTDezDyPmXR4ls8 U/kvz5RCn2bu4y8h6U+FHK4BZ7DR1Ccd3Uq1qqDbnlyfcvJeISqqkN2RrnwUQEgV XMCEr+okQyiQV4H/MLvmUWtPHpHt3gSEBdoRdGHnkzA2dC/YsJ1F/khKgCh8wqWS GTeACabyDTb9L/QFdh//o7GtcI6qv/APGJ/rVVFrrVktp+lZuIZCGZ3hbJ8lopoI FSXuM7caVgIlNzP/6RmCoP91ibREPfbfL/yqgv0cW7kiOWVXWwriz6Mi/J2AzmCo jqgDqRzkLZPAl1WdZM7MosQIiY7ZlAGhpS9ArK5P4Kv7H6TYV7mkbiSap8SmjnZH NvSRLxgT3JjTE5evSodfaaQpjiX0KGaZX0JmpqXYPqOBSYal2lDUNFSokbeucp7w y3dBZGY0/9om+G34QzZNvPisYJ2F4Yr5DvCtue8hmkvLSw+z3251555wKQvc6TNx wob2h8b8h+YsfhvnSrN1R8w3OL69kGFlMz9PWEgB4opVacZqph/XsMKLARXCg+FD 83kCuJnV/WAannHpvQA8k4HO6GiKGtrulh6vv1QOlCJQokcK1mZt7Atot+cPcGU2 UTyhSaOv4sy07lPYzvv0B4MUHNObN/v/OoDygrf7WjCDKigH+RpsVruwAqFakoCB 09+PtQ26X2Vup+YtW5bG =qPq6 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/sstabellini/tags/xen-20170718-tag' into staging Xen 2017/07/18 # gpg: Signature made Tue 18 Jul 2017 23:18:16 BST # gpg: using RSA key 0x894F8F4870E1AE90 # gpg: Good signature from "Stefano Stabellini <stefano.stabellini@eu.citrix.com>" # gpg: aka "Stefano Stabellini <sstabellini@kernel.org>" # Primary key fingerprint: D04E 33AB A51F 67BA 07D3 0AEA 894F 8F48 70E1 AE90 * remotes/sstabellini/tags/xen-20170718-tag: xen: don't use xenstore to save/restore physmap anymore xen/mapcache: introduce xen_replace_cache_entry() xen/mapcache: add an ability to create dummy mappings xen: move physmap saving into a separate function xen-platform: separate unplugging of NVMe disks xen_pt_msi.c: Check for xen_host_pci_get_* failures in xen_pt_msix_init() hw/xen: Set emu_mask for igd_opregion register Signed-off-by: Peter Maydell <peter.maydell@linaro.org>master
commit
b3e46a8914
|
@ -2107,6 +2107,24 @@ EOF
|
||||||
# Xen unstable
|
# Xen unstable
|
||||||
elif
|
elif
|
||||||
cat > $TMPC <<EOF &&
|
cat > $TMPC <<EOF &&
|
||||||
|
#undef XC_WANT_COMPAT_MAP_FOREIGN_API
|
||||||
|
#include <xenforeignmemory.h>
|
||||||
|
int main(void) {
|
||||||
|
xenforeignmemory_handle *xfmem;
|
||||||
|
|
||||||
|
xfmem = xenforeignmemory_open(0, 0);
|
||||||
|
xenforeignmemory_map2(xfmem, 0, 0, 0, 0, 0, 0, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
compile_prog "" "$xen_libs -lxendevicemodel $xen_stable_libs"
|
||||||
|
then
|
||||||
|
xen_stable_libs="-lxendevicemodel $xen_stable_libs"
|
||||||
|
xen_ctrl_version=41000
|
||||||
|
xen=yes
|
||||||
|
elif
|
||||||
|
cat > $TMPC <<EOF &&
|
||||||
#undef XC_WANT_COMPAT_DEVICEMODEL_API
|
#undef XC_WANT_COMPAT_DEVICEMODEL_API
|
||||||
#define __XEN_TOOLS__
|
#define __XEN_TOOLS__
|
||||||
#include <xendevicemodel.h>
|
#include <xendevicemodel.h>
|
||||||
|
|
|
@ -288,6 +288,7 @@ static XenPhysmap *get_physmapping(XenIOState *state,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef XEN_COMPAT_PHYSMAP
|
||||||
static hwaddr xen_phys_offset_to_gaddr(hwaddr start_addr,
|
static hwaddr xen_phys_offset_to_gaddr(hwaddr start_addr,
|
||||||
ram_addr_t size, void *opaque)
|
ram_addr_t size, void *opaque)
|
||||||
{
|
{
|
||||||
|
@ -304,6 +305,42 @@ static hwaddr xen_phys_offset_to_gaddr(hwaddr start_addr,
|
||||||
return start_addr;
|
return start_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int xen_save_physmap(XenIOState *state, XenPhysmap *physmap)
|
||||||
|
{
|
||||||
|
char path[80], value[17];
|
||||||
|
|
||||||
|
snprintf(path, sizeof(path),
|
||||||
|
"/local/domain/0/device-model/%d/physmap/%"PRIx64"/start_addr",
|
||||||
|
xen_domid, (uint64_t)physmap->phys_offset);
|
||||||
|
snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)physmap->start_addr);
|
||||||
|
if (!xs_write(state->xenstore, 0, path, value, strlen(value))) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
snprintf(path, sizeof(path),
|
||||||
|
"/local/domain/0/device-model/%d/physmap/%"PRIx64"/size",
|
||||||
|
xen_domid, (uint64_t)physmap->phys_offset);
|
||||||
|
snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)physmap->size);
|
||||||
|
if (!xs_write(state->xenstore, 0, path, value, strlen(value))) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (physmap->name) {
|
||||||
|
snprintf(path, sizeof(path),
|
||||||
|
"/local/domain/0/device-model/%d/physmap/%"PRIx64"/name",
|
||||||
|
xen_domid, (uint64_t)physmap->phys_offset);
|
||||||
|
if (!xs_write(state->xenstore, 0, path,
|
||||||
|
physmap->name, strlen(physmap->name))) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static int xen_save_physmap(XenIOState *state, XenPhysmap *physmap)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int xen_add_to_physmap(XenIOState *state,
|
static int xen_add_to_physmap(XenIOState *state,
|
||||||
hwaddr start_addr,
|
hwaddr start_addr,
|
||||||
ram_addr_t size,
|
ram_addr_t size,
|
||||||
|
@ -315,7 +352,6 @@ static int xen_add_to_physmap(XenIOState *state,
|
||||||
XenPhysmap *physmap = NULL;
|
XenPhysmap *physmap = NULL;
|
||||||
hwaddr pfn, start_gpfn;
|
hwaddr pfn, start_gpfn;
|
||||||
hwaddr phys_offset = memory_region_get_ram_addr(mr);
|
hwaddr phys_offset = memory_region_get_ram_addr(mr);
|
||||||
char path[80], value[17];
|
|
||||||
const char *mr_name;
|
const char *mr_name;
|
||||||
|
|
||||||
if (get_physmapping(state, start_addr, size)) {
|
if (get_physmapping(state, start_addr, size)) {
|
||||||
|
@ -338,6 +374,26 @@ go_physmap:
|
||||||
DPRINTF("mapping vram to %"HWADDR_PRIx" - %"HWADDR_PRIx"\n",
|
DPRINTF("mapping vram to %"HWADDR_PRIx" - %"HWADDR_PRIx"\n",
|
||||||
start_addr, start_addr + size);
|
start_addr, start_addr + size);
|
||||||
|
|
||||||
|
mr_name = memory_region_name(mr);
|
||||||
|
|
||||||
|
physmap = g_malloc(sizeof(XenPhysmap));
|
||||||
|
|
||||||
|
physmap->start_addr = start_addr;
|
||||||
|
physmap->size = size;
|
||||||
|
physmap->name = mr_name;
|
||||||
|
physmap->phys_offset = phys_offset;
|
||||||
|
|
||||||
|
QLIST_INSERT_HEAD(&state->physmap, physmap, list);
|
||||||
|
|
||||||
|
if (runstate_check(RUN_STATE_INMIGRATE)) {
|
||||||
|
/* Now when we have a physmap entry we can replace a dummy mapping with
|
||||||
|
* a real one of guest foreign memory. */
|
||||||
|
uint8_t *p = xen_replace_cache_entry(phys_offset, start_addr, size);
|
||||||
|
assert(p && p == memory_region_get_ram_ptr(mr));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
pfn = phys_offset >> TARGET_PAGE_BITS;
|
pfn = phys_offset >> TARGET_PAGE_BITS;
|
||||||
start_gpfn = start_addr >> TARGET_PAGE_BITS;
|
start_gpfn = start_addr >> TARGET_PAGE_BITS;
|
||||||
for (i = 0; i < size >> TARGET_PAGE_BITS; i++) {
|
for (i = 0; i < size >> TARGET_PAGE_BITS; i++) {
|
||||||
|
@ -352,46 +408,11 @@ go_physmap:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mr_name = memory_region_name(mr);
|
|
||||||
|
|
||||||
physmap = g_malloc(sizeof (XenPhysmap));
|
|
||||||
|
|
||||||
physmap->start_addr = start_addr;
|
|
||||||
physmap->size = size;
|
|
||||||
physmap->name = mr_name;
|
|
||||||
physmap->phys_offset = phys_offset;
|
|
||||||
|
|
||||||
QLIST_INSERT_HEAD(&state->physmap, physmap, list);
|
|
||||||
|
|
||||||
xc_domain_pin_memory_cacheattr(xen_xc, xen_domid,
|
xc_domain_pin_memory_cacheattr(xen_xc, xen_domid,
|
||||||
start_addr >> TARGET_PAGE_BITS,
|
start_addr >> TARGET_PAGE_BITS,
|
||||||
(start_addr + size - 1) >> TARGET_PAGE_BITS,
|
(start_addr + size - 1) >> TARGET_PAGE_BITS,
|
||||||
XEN_DOMCTL_MEM_CACHEATTR_WB);
|
XEN_DOMCTL_MEM_CACHEATTR_WB);
|
||||||
|
return xen_save_physmap(state, physmap);
|
||||||
snprintf(path, sizeof(path),
|
|
||||||
"/local/domain/0/device-model/%d/physmap/%"PRIx64"/start_addr",
|
|
||||||
xen_domid, (uint64_t)phys_offset);
|
|
||||||
snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)start_addr);
|
|
||||||
if (!xs_write(state->xenstore, 0, path, value, strlen(value))) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
snprintf(path, sizeof(path),
|
|
||||||
"/local/domain/0/device-model/%d/physmap/%"PRIx64"/size",
|
|
||||||
xen_domid, (uint64_t)phys_offset);
|
|
||||||
snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)size);
|
|
||||||
if (!xs_write(state->xenstore, 0, path, value, strlen(value))) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (mr_name) {
|
|
||||||
snprintf(path, sizeof(path),
|
|
||||||
"/local/domain/0/device-model/%d/physmap/%"PRIx64"/name",
|
|
||||||
xen_domid, (uint64_t)phys_offset);
|
|
||||||
if (!xs_write(state->xenstore, 0, path, mr_name, strlen(mr_name))) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int xen_remove_from_physmap(XenIOState *state,
|
static int xen_remove_from_physmap(XenIOState *state,
|
||||||
|
@ -1152,6 +1173,7 @@ static void xen_exit_notifier(Notifier *n, void *data)
|
||||||
xs_daemon_close(state->xenstore);
|
xs_daemon_close(state->xenstore);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef XEN_COMPAT_PHYSMAP
|
||||||
static void xen_read_physmap(XenIOState *state)
|
static void xen_read_physmap(XenIOState *state)
|
||||||
{
|
{
|
||||||
XenPhysmap *physmap = NULL;
|
XenPhysmap *physmap = NULL;
|
||||||
|
@ -1199,6 +1221,11 @@ static void xen_read_physmap(XenIOState *state)
|
||||||
}
|
}
|
||||||
free(entries);
|
free(entries);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
static void xen_read_physmap(XenIOState *state)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void xen_wakeup_notifier(Notifier *notifier, void *data)
|
static void xen_wakeup_notifier(Notifier *notifier, void *data)
|
||||||
{
|
{
|
||||||
|
@ -1325,7 +1352,11 @@ void xen_hvm_init(PCMachineState *pcms, MemoryRegion **ram_memory)
|
||||||
state->bufioreq_local_port = rc;
|
state->bufioreq_local_port = rc;
|
||||||
|
|
||||||
/* Init RAM management */
|
/* Init RAM management */
|
||||||
|
#ifdef XEN_COMPAT_PHYSMAP
|
||||||
xen_map_cache_init(xen_phys_offset_to_gaddr, state);
|
xen_map_cache_init(xen_phys_offset_to_gaddr, state);
|
||||||
|
#else
|
||||||
|
xen_map_cache_init(NULL, state);
|
||||||
|
#endif
|
||||||
xen_ram_init(pcms, ram_size, ram_memory);
|
xen_ram_init(pcms, ram_size, ram_memory);
|
||||||
|
|
||||||
qemu_add_vm_change_state_handler(xen_hvm_change_state_handler, state);
|
qemu_add_vm_change_state_handler(xen_hvm_change_state_handler, state);
|
||||||
|
|
|
@ -53,6 +53,8 @@ typedef struct MapCacheEntry {
|
||||||
uint8_t *vaddr_base;
|
uint8_t *vaddr_base;
|
||||||
unsigned long *valid_mapping;
|
unsigned long *valid_mapping;
|
||||||
uint8_t lock;
|
uint8_t lock;
|
||||||
|
#define XEN_MAPCACHE_ENTRY_DUMMY (1 << 0)
|
||||||
|
uint8_t flags;
|
||||||
hwaddr size;
|
hwaddr size;
|
||||||
struct MapCacheEntry *next;
|
struct MapCacheEntry *next;
|
||||||
} MapCacheEntry;
|
} MapCacheEntry;
|
||||||
|
@ -149,8 +151,10 @@ void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xen_remap_bucket(MapCacheEntry *entry,
|
static void xen_remap_bucket(MapCacheEntry *entry,
|
||||||
|
void *vaddr,
|
||||||
hwaddr size,
|
hwaddr size,
|
||||||
hwaddr address_index)
|
hwaddr address_index,
|
||||||
|
bool dummy)
|
||||||
{
|
{
|
||||||
uint8_t *vaddr_base;
|
uint8_t *vaddr_base;
|
||||||
xen_pfn_t *pfns;
|
xen_pfn_t *pfns;
|
||||||
|
@ -164,7 +168,9 @@ static void xen_remap_bucket(MapCacheEntry *entry,
|
||||||
err = g_malloc0(nb_pfn * sizeof (int));
|
err = g_malloc0(nb_pfn * sizeof (int));
|
||||||
|
|
||||||
if (entry->vaddr_base != NULL) {
|
if (entry->vaddr_base != NULL) {
|
||||||
ram_block_notify_remove(entry->vaddr_base, entry->size);
|
if (!(entry->flags & XEN_MAPCACHE_ENTRY_DUMMY)) {
|
||||||
|
ram_block_notify_remove(entry->vaddr_base, entry->size);
|
||||||
|
}
|
||||||
if (munmap(entry->vaddr_base, entry->size) != 0) {
|
if (munmap(entry->vaddr_base, entry->size) != 0) {
|
||||||
perror("unmap fails");
|
perror("unmap fails");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
|
@ -177,11 +183,29 @@ static void xen_remap_bucket(MapCacheEntry *entry,
|
||||||
pfns[i] = (address_index << (MCACHE_BUCKET_SHIFT-XC_PAGE_SHIFT)) + i;
|
pfns[i] = (address_index << (MCACHE_BUCKET_SHIFT-XC_PAGE_SHIFT)) + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
vaddr_base = xenforeignmemory_map(xen_fmem, xen_domid, PROT_READ|PROT_WRITE,
|
if (!dummy) {
|
||||||
nb_pfn, pfns, err);
|
vaddr_base = xenforeignmemory_map2(xen_fmem, xen_domid, vaddr,
|
||||||
if (vaddr_base == NULL) {
|
PROT_READ | PROT_WRITE, 0,
|
||||||
perror("xenforeignmemory_map");
|
nb_pfn, pfns, err);
|
||||||
exit(-1);
|
if (vaddr_base == NULL) {
|
||||||
|
perror("xenforeignmemory_map2");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* We create dummy mappings where we are unable to create a foreign
|
||||||
|
* mapping immediately due to certain circumstances (i.e. on resume now)
|
||||||
|
*/
|
||||||
|
vaddr_base = mmap(vaddr, size, PROT_READ | PROT_WRITE,
|
||||||
|
MAP_ANON | MAP_SHARED, -1, 0);
|
||||||
|
if (vaddr_base == NULL) {
|
||||||
|
perror("mmap");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(entry->flags & XEN_MAPCACHE_ENTRY_DUMMY)) {
|
||||||
|
ram_block_notify_add(vaddr_base, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
entry->vaddr_base = vaddr_base;
|
entry->vaddr_base = vaddr_base;
|
||||||
|
@ -190,7 +214,12 @@ static void xen_remap_bucket(MapCacheEntry *entry,
|
||||||
entry->valid_mapping = (unsigned long *) g_malloc0(sizeof(unsigned long) *
|
entry->valid_mapping = (unsigned long *) g_malloc0(sizeof(unsigned long) *
|
||||||
BITS_TO_LONGS(size >> XC_PAGE_SHIFT));
|
BITS_TO_LONGS(size >> XC_PAGE_SHIFT));
|
||||||
|
|
||||||
ram_block_notify_add(entry->vaddr_base, entry->size);
|
if (dummy) {
|
||||||
|
entry->flags |= XEN_MAPCACHE_ENTRY_DUMMY;
|
||||||
|
} else {
|
||||||
|
entry->flags &= ~(XEN_MAPCACHE_ENTRY_DUMMY);
|
||||||
|
}
|
||||||
|
|
||||||
bitmap_zero(entry->valid_mapping, nb_pfn);
|
bitmap_zero(entry->valid_mapping, nb_pfn);
|
||||||
for (i = 0; i < nb_pfn; i++) {
|
for (i = 0; i < nb_pfn; i++) {
|
||||||
if (!err[i]) {
|
if (!err[i]) {
|
||||||
|
@ -210,7 +239,8 @@ static uint8_t *xen_map_cache_unlocked(hwaddr phys_addr, hwaddr size,
|
||||||
hwaddr address_offset;
|
hwaddr address_offset;
|
||||||
hwaddr cache_size = size;
|
hwaddr cache_size = size;
|
||||||
hwaddr test_bit_size;
|
hwaddr test_bit_size;
|
||||||
bool translated = false;
|
bool translated G_GNUC_UNUSED = false;
|
||||||
|
bool dummy = false;
|
||||||
|
|
||||||
tryagain:
|
tryagain:
|
||||||
address_index = phys_addr >> MCACHE_BUCKET_SHIFT;
|
address_index = phys_addr >> MCACHE_BUCKET_SHIFT;
|
||||||
|
@ -262,14 +292,14 @@ tryagain:
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
entry = g_malloc0(sizeof (MapCacheEntry));
|
entry = g_malloc0(sizeof (MapCacheEntry));
|
||||||
pentry->next = entry;
|
pentry->next = entry;
|
||||||
xen_remap_bucket(entry, cache_size, address_index);
|
xen_remap_bucket(entry, NULL, cache_size, address_index, dummy);
|
||||||
} else if (!entry->lock) {
|
} else if (!entry->lock) {
|
||||||
if (!entry->vaddr_base || entry->paddr_index != address_index ||
|
if (!entry->vaddr_base || entry->paddr_index != address_index ||
|
||||||
entry->size != cache_size ||
|
entry->size != cache_size ||
|
||||||
!test_bits(address_offset >> XC_PAGE_SHIFT,
|
!test_bits(address_offset >> XC_PAGE_SHIFT,
|
||||||
test_bit_size >> XC_PAGE_SHIFT,
|
test_bit_size >> XC_PAGE_SHIFT,
|
||||||
entry->valid_mapping)) {
|
entry->valid_mapping)) {
|
||||||
xen_remap_bucket(entry, cache_size, address_index);
|
xen_remap_bucket(entry, NULL, cache_size, address_index, dummy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,11 +307,17 @@ tryagain:
|
||||||
test_bit_size >> XC_PAGE_SHIFT,
|
test_bit_size >> XC_PAGE_SHIFT,
|
||||||
entry->valid_mapping)) {
|
entry->valid_mapping)) {
|
||||||
mapcache->last_entry = NULL;
|
mapcache->last_entry = NULL;
|
||||||
|
#ifdef XEN_COMPAT_PHYSMAP
|
||||||
if (!translated && mapcache->phys_offset_to_gaddr) {
|
if (!translated && mapcache->phys_offset_to_gaddr) {
|
||||||
phys_addr = mapcache->phys_offset_to_gaddr(phys_addr, size, mapcache->opaque);
|
phys_addr = mapcache->phys_offset_to_gaddr(phys_addr, size, mapcache->opaque);
|
||||||
translated = true;
|
translated = true;
|
||||||
goto tryagain;
|
goto tryagain;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
if (!dummy && runstate_check(RUN_STATE_INMIGRATE)) {
|
||||||
|
dummy = true;
|
||||||
|
goto tryagain;
|
||||||
|
}
|
||||||
trace_xen_map_cache_return(NULL);
|
trace_xen_map_cache_return(NULL);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -462,3 +498,66 @@ void xen_invalidate_map_cache(void)
|
||||||
|
|
||||||
mapcache_unlock();
|
mapcache_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint8_t *xen_replace_cache_entry_unlocked(hwaddr old_phys_addr,
|
||||||
|
hwaddr new_phys_addr,
|
||||||
|
hwaddr size)
|
||||||
|
{
|
||||||
|
MapCacheEntry *entry;
|
||||||
|
hwaddr address_index, address_offset;
|
||||||
|
hwaddr test_bit_size, cache_size = size;
|
||||||
|
|
||||||
|
address_index = old_phys_addr >> MCACHE_BUCKET_SHIFT;
|
||||||
|
address_offset = old_phys_addr & (MCACHE_BUCKET_SIZE - 1);
|
||||||
|
|
||||||
|
assert(size);
|
||||||
|
/* test_bit_size is always a multiple of XC_PAGE_SIZE */
|
||||||
|
test_bit_size = size + (old_phys_addr & (XC_PAGE_SIZE - 1));
|
||||||
|
if (test_bit_size % XC_PAGE_SIZE) {
|
||||||
|
test_bit_size += XC_PAGE_SIZE - (test_bit_size % XC_PAGE_SIZE);
|
||||||
|
}
|
||||||
|
cache_size = size + address_offset;
|
||||||
|
if (cache_size % MCACHE_BUCKET_SIZE) {
|
||||||
|
cache_size += MCACHE_BUCKET_SIZE - (cache_size % MCACHE_BUCKET_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = &mapcache->entry[address_index % mapcache->nr_buckets];
|
||||||
|
while (entry && !(entry->paddr_index == address_index &&
|
||||||
|
entry->size == cache_size)) {
|
||||||
|
entry = entry->next;
|
||||||
|
}
|
||||||
|
if (!entry) {
|
||||||
|
DPRINTF("Trying to update an entry for %lx " \
|
||||||
|
"that is not in the mapcache!\n", old_phys_addr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
address_index = new_phys_addr >> MCACHE_BUCKET_SHIFT;
|
||||||
|
address_offset = new_phys_addr & (MCACHE_BUCKET_SIZE - 1);
|
||||||
|
|
||||||
|
fprintf(stderr, "Replacing a dummy mapcache entry for %lx with %lx\n",
|
||||||
|
old_phys_addr, new_phys_addr);
|
||||||
|
|
||||||
|
xen_remap_bucket(entry, entry->vaddr_base,
|
||||||
|
cache_size, address_index, false);
|
||||||
|
if (!test_bits(address_offset >> XC_PAGE_SHIFT,
|
||||||
|
test_bit_size >> XC_PAGE_SHIFT,
|
||||||
|
entry->valid_mapping)) {
|
||||||
|
DPRINTF("Unable to update a mapcache entry for %lx!\n", old_phys_addr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return entry->vaddr_base + address_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *xen_replace_cache_entry(hwaddr old_phys_addr,
|
||||||
|
hwaddr new_phys_addr,
|
||||||
|
hwaddr size)
|
||||||
|
{
|
||||||
|
uint8_t *p;
|
||||||
|
|
||||||
|
mapcache_lock();
|
||||||
|
p = xen_replace_cache_entry_unlocked(old_phys_addr, new_phys_addr, size);
|
||||||
|
mapcache_unlock();
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
|
@ -87,10 +87,30 @@ static void log_writeb(PCIXenPlatformState *s, char val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Xen Platform, Fixed IOPort */
|
/*
|
||||||
#define UNPLUG_ALL_DISKS 1
|
* Unplug device flags.
|
||||||
#define UNPLUG_ALL_NICS 2
|
*
|
||||||
#define UNPLUG_AUX_IDE_DISKS 4
|
* The logic got a little confused at some point in the past but this is
|
||||||
|
* what they do now.
|
||||||
|
*
|
||||||
|
* bit 0: Unplug all IDE and SCSI disks.
|
||||||
|
* bit 1: Unplug all NICs.
|
||||||
|
* bit 2: Unplug IDE disks except primary master. This is overridden if
|
||||||
|
* bit 0 is also present in the mask.
|
||||||
|
* bit 3: Unplug all NVMe disks.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define _UNPLUG_IDE_SCSI_DISKS 0
|
||||||
|
#define UNPLUG_IDE_SCSI_DISKS (1u << _UNPLUG_IDE_SCSI_DISKS)
|
||||||
|
|
||||||
|
#define _UNPLUG_ALL_NICS 1
|
||||||
|
#define UNPLUG_ALL_NICS (1u << _UNPLUG_ALL_NICS)
|
||||||
|
|
||||||
|
#define _UNPLUG_AUX_IDE_DISKS 2
|
||||||
|
#define UNPLUG_AUX_IDE_DISKS (1u << _UNPLUG_AUX_IDE_DISKS)
|
||||||
|
|
||||||
|
#define _UNPLUG_NVME_DISKS 3
|
||||||
|
#define UNPLUG_NVME_DISKS (1u << _UNPLUG_NVME_DISKS)
|
||||||
|
|
||||||
static void unplug_nic(PCIBus *b, PCIDevice *d, void *o)
|
static void unplug_nic(PCIBus *b, PCIDevice *d, void *o)
|
||||||
{
|
{
|
||||||
|
@ -122,7 +142,7 @@ static void unplug_disks(PCIBus *b, PCIDevice *d, void *opaque)
|
||||||
{
|
{
|
||||||
uint32_t flags = *(uint32_t *)opaque;
|
uint32_t flags = *(uint32_t *)opaque;
|
||||||
bool aux = (flags & UNPLUG_AUX_IDE_DISKS) &&
|
bool aux = (flags & UNPLUG_AUX_IDE_DISKS) &&
|
||||||
!(flags & UNPLUG_ALL_DISKS);
|
!(flags & UNPLUG_IDE_SCSI_DISKS);
|
||||||
|
|
||||||
/* We have to ignore passthrough devices */
|
/* We have to ignore passthrough devices */
|
||||||
if (!strcmp(d->name, "xen-pci-passthrough")) {
|
if (!strcmp(d->name, "xen-pci-passthrough")) {
|
||||||
|
@ -135,12 +155,16 @@ static void unplug_disks(PCIBus *b, PCIDevice *d, void *opaque)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PCI_CLASS_STORAGE_SCSI:
|
case PCI_CLASS_STORAGE_SCSI:
|
||||||
case PCI_CLASS_STORAGE_EXPRESS:
|
|
||||||
if (!aux) {
|
if (!aux) {
|
||||||
object_unparent(OBJECT(d));
|
object_unparent(OBJECT(d));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PCI_CLASS_STORAGE_EXPRESS:
|
||||||
|
if (flags & UNPLUG_NVME_DISKS) {
|
||||||
|
object_unparent(OBJECT(d));
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -158,10 +182,9 @@ static void platform_fixed_ioport_writew(void *opaque, uint32_t addr, uint32_t v
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case 0: {
|
case 0: {
|
||||||
PCIDevice *pci_dev = PCI_DEVICE(s);
|
PCIDevice *pci_dev = PCI_DEVICE(s);
|
||||||
/* Unplug devices. Value is a bitmask of which devices to
|
/* Unplug devices. See comment above flag definitions */
|
||||||
unplug, with bit 0 the disk devices, bit 1 the network
|
if (val & (UNPLUG_IDE_SCSI_DISKS | UNPLUG_AUX_IDE_DISKS |
|
||||||
devices, and bit 2 the non-primary-master IDE devices. */
|
UNPLUG_NVME_DISKS)) {
|
||||||
if (val & (UNPLUG_ALL_DISKS | UNPLUG_AUX_IDE_DISKS)) {
|
|
||||||
DPRINTF("unplug disks\n");
|
DPRINTF("unplug disks\n");
|
||||||
pci_unplug_disks(pci_dev->bus, val);
|
pci_unplug_disks(pci_dev->bus, val);
|
||||||
}
|
}
|
||||||
|
@ -349,14 +372,14 @@ static void xen_platform_ioport_writeb(void *opaque, hwaddr addr,
|
||||||
* If VMDP was to control both disk and LAN it would use 4.
|
* If VMDP was to control both disk and LAN it would use 4.
|
||||||
* If it controlled just disk or just LAN, it would use 8 below.
|
* If it controlled just disk or just LAN, it would use 8 below.
|
||||||
*/
|
*/
|
||||||
pci_unplug_disks(pci_dev->bus, UNPLUG_ALL_DISKS);
|
pci_unplug_disks(pci_dev->bus, UNPLUG_IDE_SCSI_DISKS);
|
||||||
pci_unplug_nics(pci_dev->bus);
|
pci_unplug_nics(pci_dev->bus);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
switch (val) {
|
switch (val) {
|
||||||
case 1:
|
case 1:
|
||||||
pci_unplug_disks(pci_dev->bus, UNPLUG_ALL_DISKS);
|
pci_unplug_disks(pci_dev->bus, UNPLUG_IDE_SCSI_DISKS);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
pci_unplug_nics(pci_dev->bus);
|
pci_unplug_nics(pci_dev->bus);
|
||||||
|
|
|
@ -1535,6 +1535,7 @@ static XenPTRegInfo xen_pt_emu_reg_igd_opregion[] = {
|
||||||
.offset = 0x0,
|
.offset = 0x0,
|
||||||
.size = 4,
|
.size = 4,
|
||||||
.init_val = 0,
|
.init_val = 0,
|
||||||
|
.emu_mask = 0xFFFFFFFF,
|
||||||
.u.dw.read = xen_pt_intel_opregion_read,
|
.u.dw.read = xen_pt_intel_opregion_read,
|
||||||
.u.dw.write = xen_pt_intel_opregion_write,
|
.u.dw.write = xen_pt_intel_opregion_write,
|
||||||
},
|
},
|
||||||
|
|
|
@ -535,7 +535,11 @@ int xen_pt_msix_init(XenPCIPassthroughState *s, uint32_t base)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
xen_host_pci_get_word(hd, base + PCI_MSIX_FLAGS, &control);
|
rc = xen_host_pci_get_word(hd, base + PCI_MSIX_FLAGS, &control);
|
||||||
|
if (rc) {
|
||||||
|
XEN_PT_ERR(d, "Failed to read PCI_MSIX_FLAGS field\n");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
total_entries = control & PCI_MSIX_FLAGS_QSIZE;
|
total_entries = control & PCI_MSIX_FLAGS_QSIZE;
|
||||||
total_entries += 1;
|
total_entries += 1;
|
||||||
|
|
||||||
|
@ -554,7 +558,11 @@ int xen_pt_msix_init(XenPCIPassthroughState *s, uint32_t base)
|
||||||
+ XC_PAGE_SIZE - 1)
|
+ XC_PAGE_SIZE - 1)
|
||||||
& XC_PAGE_MASK);
|
& XC_PAGE_MASK);
|
||||||
|
|
||||||
xen_host_pci_get_long(hd, base + PCI_MSIX_TABLE, &table_off);
|
rc = xen_host_pci_get_long(hd, base + PCI_MSIX_TABLE, &table_off);
|
||||||
|
if (rc) {
|
||||||
|
XEN_PT_ERR(d, "Failed to read PCI_MSIX_TABLE field\n");
|
||||||
|
goto error_out;
|
||||||
|
}
|
||||||
bar_index = msix->bar_index = table_off & PCI_MSIX_FLAGS_BIRMASK;
|
bar_index = msix->bar_index = table_off & PCI_MSIX_FLAGS_BIRMASK;
|
||||||
table_off = table_off & ~PCI_MSIX_FLAGS_BIRMASK;
|
table_off = table_off & ~PCI_MSIX_FLAGS_BIRMASK;
|
||||||
msix->table_base = s->real_device.io_regions[bar_index].base_addr;
|
msix->table_base = s->real_device.io_regions[bar_index].base_addr;
|
||||||
|
|
|
@ -78,6 +78,21 @@ static inline void *xenforeignmemory_map(xc_interface *h, uint32_t dom,
|
||||||
|
|
||||||
extern xenforeignmemory_handle *xen_fmem;
|
extern xenforeignmemory_handle *xen_fmem;
|
||||||
|
|
||||||
|
#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 41000
|
||||||
|
|
||||||
|
#define XEN_COMPAT_PHYSMAP
|
||||||
|
static inline void *xenforeignmemory_map2(xenforeignmemory_handle *h,
|
||||||
|
uint32_t dom, void *addr,
|
||||||
|
int prot, int flags, size_t pages,
|
||||||
|
const xen_pfn_t arr[/*pages*/],
|
||||||
|
int err[/*pages*/])
|
||||||
|
{
|
||||||
|
assert(addr == NULL && flags == 0);
|
||||||
|
return xenforeignmemory_map(h, dom, prot, pages, arr, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 40900
|
#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 40900
|
||||||
|
|
||||||
typedef xc_interface xendevicemodel_handle;
|
typedef xc_interface xendevicemodel_handle;
|
||||||
|
|
|
@ -21,7 +21,9 @@ uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size,
|
||||||
ram_addr_t xen_ram_addr_from_mapcache(void *ptr);
|
ram_addr_t xen_ram_addr_from_mapcache(void *ptr);
|
||||||
void xen_invalidate_map_cache_entry(uint8_t *buffer);
|
void xen_invalidate_map_cache_entry(uint8_t *buffer);
|
||||||
void xen_invalidate_map_cache(void);
|
void xen_invalidate_map_cache(void);
|
||||||
|
uint8_t *xen_replace_cache_entry(hwaddr old_phys_addr,
|
||||||
|
hwaddr new_phys_addr,
|
||||||
|
hwaddr size);
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static inline void xen_map_cache_init(phys_offset_to_gaddr_t f,
|
static inline void xen_map_cache_init(phys_offset_to_gaddr_t f,
|
||||||
|
@ -50,6 +52,13 @@ static inline void xen_invalidate_map_cache(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline uint8_t *xen_replace_cache_entry(hwaddr old_phys_addr,
|
||||||
|
hwaddr new_phys_addr,
|
||||||
|
hwaddr size)
|
||||||
|
{
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* XEN_MAPCACHE_H */
|
#endif /* XEN_MAPCACHE_H */
|
||||||
|
|
Loading…
Reference in New Issue