mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
x86/HVM: allocate emulation cache entries dynamically
Both caches may need higher capacity, and the upper bound will need to be determined dynamically based on CPUID policy (for AMX'es TILELOAD / TILESTORE at least). Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Roger Pau Monné <roger.pau@citrix.com> Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
This commit is contained in:
1 parent
e5339bb689
commit
23d60dbb04
3 files changed
+46
-25
No files matched your search
+39
-12
@@ -26,6 +26,18 @@
|
||||
#include <asm/iocap.h>
|
||||
#include <asm/vm_event.h>
|
||||
|
||||
/*
|
||||
* We may read or write up to m512 or up to a tile row as a number of
|
||||
* device-model transactions.
|
||||
*/
|
||||
struct hvm_mmio_cache {
|
||||
unsigned long gla;
|
||||
unsigned int size; /* Amount of buffer[] actually used. */
|
||||
unsigned int space:31; /* Allocated size of buffer[]. */
|
||||
unsigned int dir:1;
|
||||
uint8_t buffer[] __aligned(sizeof(long));
|
||||
};
|
||||
|
||||
struct hvmemul_cache
|
||||
{
|
||||
/* The cache is disabled as long as num_ents > max_ents. */
|
||||
@@ -935,7 +947,7 @@ static int hvmemul_phys_mmio_access(
|
||||
}
|
||||
|
||||
/* Accesses must not overflow the cache's buffer. */
|
||||
if ( offset + size > sizeof(cache->buffer) )
|
||||
if ( offset + size > cache->space )
|
||||
{
|
||||
ASSERT_UNREACHABLE();
|
||||
return X86EMUL_UNHANDLEABLE;
|
||||
@@ -1011,7 +1023,7 @@ static struct hvm_mmio_cache *hvmemul_find_mmio_cache(
|
||||
|
||||
for ( i = 0; i < hvio->mmio_cache_count; i ++ )
|
||||
{
|
||||
cache = &hvio->mmio_cache[i];
|
||||
cache = hvio->mmio_cache[i];
|
||||
|
||||
if ( gla == cache->gla &&
|
||||
dir == cache->dir )
|
||||
@@ -1027,10 +1039,11 @@ static struct hvm_mmio_cache *hvmemul_find_mmio_cache(
|
||||
|
||||
++hvio->mmio_cache_count;
|
||||
|
||||
cache = &hvio->mmio_cache[i];
|
||||
memset(cache, 0, sizeof (*cache));
|
||||
cache = hvio->mmio_cache[i];
|
||||
memset(cache->buffer, 0, cache->space);
|
||||
|
||||
cache->gla = gla;
|
||||
cache->size = 0;
|
||||
cache->dir = dir;
|
||||
|
||||
return cache;
|
||||
@@ -2980,16 +2993,21 @@ void hvm_dump_emulation_state(const char *loglvl, const char *prefix,
|
||||
int hvmemul_cache_init(struct vcpu *v)
|
||||
{
|
||||
/*
|
||||
* No insn can access more than 16 independent linear addresses (AVX512F
|
||||
* scatters/gathers being the worst). Each such linear range can span a
|
||||
* page boundary, i.e. may require two page walks. Account for each insn
|
||||
* byte individually, for simplicity.
|
||||
* AVX512F scatter/gather insns can access up to 16 independent linear
|
||||
* addresses, up to 8 bytes size. Each such linear range can span a page
|
||||
* boundary, i.e. may require two page walks.
|
||||
*/
|
||||
const unsigned int nents = (CONFIG_PAGING_LEVELS + 1) *
|
||||
(MAX_INST_LEN + 16 * 2);
|
||||
struct hvmemul_cache *cache = xmalloc_flex_struct(struct hvmemul_cache,
|
||||
ents, nents);
|
||||
unsigned int nents = 16 * 2 * (CONFIG_PAGING_LEVELS + 1);
|
||||
unsigned int i, max_bytes = 64;
|
||||
struct hvmemul_cache *cache;
|
||||
|
||||
/*
|
||||
* Account for each insn byte individually, both for simplicity and to
|
||||
* leave some slack space.
|
||||
*/
|
||||
nents += MAX_INST_LEN * (CONFIG_PAGING_LEVELS + 1);
|
||||
|
||||
cache = xvmalloc_flex_struct(struct hvmemul_cache, ents, nents);
|
||||
if ( !cache )
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -2999,6 +3017,15 @@ int hvmemul_cache_init(struct vcpu *v)
|
||||
|
||||
v->arch.hvm.hvm_io.cache = cache;
|
||||
|
||||
for ( i = 0; i < ARRAY_SIZE(v->arch.hvm.hvm_io.mmio_cache); ++i )
|
||||
{
|
||||
v->arch.hvm.hvm_io.mmio_cache[i] =
|
||||
xvmalloc_flex_struct(struct hvm_mmio_cache, buffer, max_bytes);
|
||||
if ( !v->arch.hvm.hvm_io.mmio_cache[i] )
|
||||
return -ENOMEM;
|
||||
v->arch.hvm.hvm_io.mmio_cache[i]->space = max_bytes;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <xen/err.h>
|
||||
#include <xen/mm.h>
|
||||
#include <xen/sched.h>
|
||||
#include <xen/xvmalloc.h>
|
||||
#include <asm/hvm/hvm.h>
|
||||
#include <asm/x86_emulate.h>
|
||||
|
||||
@@ -119,7 +120,11 @@ int hvmemul_do_pio_buffer(uint16_t port,
|
||||
int __must_check hvmemul_cache_init(struct vcpu *v);
|
||||
static inline void hvmemul_cache_destroy(struct vcpu *v)
|
||||
{
|
||||
XFREE(v->arch.hvm.hvm_io.cache);
|
||||
unsigned int i;
|
||||
|
||||
for ( i = 0; i < ARRAY_SIZE(v->arch.hvm.hvm_io.mmio_cache); ++i )
|
||||
XFREE(v->arch.hvm.hvm_io.mmio_cache[i]);
|
||||
XVFREE(v->arch.hvm.hvm_io.cache);
|
||||
}
|
||||
bool hvmemul_read_cache(const struct vcpu *v, paddr_t gpa,
|
||||
void *buffer, unsigned int size);
|
||||
|
||||
@@ -22,17 +22,6 @@ struct hvm_vcpu_asid {
|
||||
uint32_t asid;
|
||||
};
|
||||
|
||||
/*
|
||||
* We may read or write up to m512 as a number of device-model
|
||||
* transactions.
|
||||
*/
|
||||
struct hvm_mmio_cache {
|
||||
unsigned long gla;
|
||||
unsigned int size;
|
||||
uint8_t dir;
|
||||
uint8_t buffer[64] __aligned(sizeof(long));
|
||||
};
|
||||
|
||||
struct hvm_vcpu_io {
|
||||
/*
|
||||
* HVM emulation:
|
||||
@@ -48,7 +37,7 @@ struct hvm_vcpu_io {
|
||||
* We may need to handle up to 3 distinct memory accesses per
|
||||
* instruction.
|
||||
*/
|
||||
struct hvm_mmio_cache mmio_cache[3];
|
||||
struct hvm_mmio_cache *mmio_cache[3];
|
||||
unsigned int mmio_cache_count;
|
||||
|
||||
/* For retries we shouldn't re-fetch the instruction. */
|
||||
|
||||