Changeset View
Changeset View
Standalone View
Standalone View
head/usr.sbin/bhyve/mem.c
Show First 20 Lines • Show All 130 Lines • ▼ Show 20 Lines | printf(" %lx:%lx, %s\n", np->mr_base, np->mr_end, | ||||
np->mr_param.name); | np->mr_param.name); | ||||
} | } | ||||
pthread_rwlock_unlock(&mmio_rwlock); | pthread_rwlock_unlock(&mmio_rwlock); | ||||
} | } | ||||
#endif | #endif | ||||
RB_GENERATE(mmio_rb_tree, mmio_rb_range, mr_link, mmio_rb_range_compare); | RB_GENERATE(mmio_rb_tree, mmio_rb_range, mr_link, mmio_rb_range_compare); | ||||
typedef int (mem_cb_t)(struct vmctx *ctx, int vcpu, uint64_t gpa, | |||||
struct mem_range *mr, void *arg); | |||||
static int | static int | ||||
mem_read(void *ctx, int vcpu, uint64_t gpa, uint64_t *rval, int size, void *arg) | mem_read(void *ctx, int vcpu, uint64_t gpa, uint64_t *rval, int size, void *arg) | ||||
{ | { | ||||
int error; | int error; | ||||
struct mem_range *mr = arg; | struct mem_range *mr = arg; | ||||
error = (*mr->handler)(ctx, vcpu, MEM_F_READ, gpa, size, | error = (*mr->handler)(ctx, vcpu, MEM_F_READ, gpa, size, | ||||
rval, mr->arg1, mr->arg2); | rval, mr->arg1, mr->arg2); | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | static int | ||||
mem_write(void *ctx, int vcpu, uint64_t gpa, uint64_t wval, int size, void *arg) | mem_write(void *ctx, int vcpu, uint64_t gpa, uint64_t wval, int size, void *arg) | ||||
{ | { | ||||
int error; | int error; | ||||
struct mem_range *mr = arg; | struct mem_range *mr = arg; | ||||
error = (*mr->handler)(ctx, vcpu, MEM_F_WRITE, gpa, size, | error = (*mr->handler)(ctx, vcpu, MEM_F_WRITE, gpa, size, | ||||
&wval, mr->arg1, mr->arg2); | &wval, mr->arg1, mr->arg2); | ||||
return (error); | return (error); | ||||
} | } | ||||
int | static int | ||||
emulate_mem(struct vmctx *ctx, int vcpu, uint64_t paddr, struct vie *vie, | access_memory(struct vmctx *ctx, int vcpu, uint64_t paddr, mem_cb_t *cb, | ||||
struct vm_guest_paging *paging) | void *arg) | ||||
{ | { | ||||
struct mmio_rb_range *entry; | struct mmio_rb_range *entry; | ||||
int err, immutable; | int err, immutable; | ||||
pthread_rwlock_rdlock(&mmio_rwlock); | pthread_rwlock_rdlock(&mmio_rwlock); | ||||
/* | /* | ||||
* First check the per-vCPU cache | * First check the per-vCPU cache | ||||
*/ | */ | ||||
Show All 26 Lines | access_memory(struct vmctx *ctx, int vcpu, uint64_t paddr, mem_cb_t *cb, | ||||
* to modify the PCIR_COMMAND register then register_mem() can | * to modify the PCIR_COMMAND register then register_mem() can | ||||
* deadlock on 'mmio_rwlock'. However by registering the extended | * deadlock on 'mmio_rwlock'. However by registering the extended | ||||
* config space window as 'immutable' the deadlock can be avoided. | * config space window as 'immutable' the deadlock can be avoided. | ||||
*/ | */ | ||||
immutable = (entry->mr_param.flags & MEM_F_IMMUTABLE); | immutable = (entry->mr_param.flags & MEM_F_IMMUTABLE); | ||||
if (immutable) | if (immutable) | ||||
pthread_rwlock_unlock(&mmio_rwlock); | pthread_rwlock_unlock(&mmio_rwlock); | ||||
err = vmm_emulate_instruction(ctx, vcpu, paddr, vie, paging, | err = cb(ctx, vcpu, paddr, &entry->mr_param, arg); | ||||
mem_read, mem_write, &entry->mr_param); | |||||
if (!immutable) | if (!immutable) | ||||
pthread_rwlock_unlock(&mmio_rwlock); | pthread_rwlock_unlock(&mmio_rwlock); | ||||
return (err); | return (err); | ||||
} | |||||
struct emulate_mem_args { | |||||
struct vie *vie; | |||||
struct vm_guest_paging *paging; | |||||
}; | |||||
static int | |||||
emulate_mem_cb(struct vmctx *ctx, int vcpu, uint64_t paddr, struct mem_range *mr, | |||||
void *arg) | |||||
{ | |||||
struct emulate_mem_args *ema; | |||||
ema = arg; | |||||
return (vmm_emulate_instruction(ctx, vcpu, paddr, ema->vie, ema->paging, | |||||
mem_read, mem_write, mr)); | |||||
} | |||||
int | |||||
emulate_mem(struct vmctx *ctx, int vcpu, uint64_t paddr, struct vie *vie, | |||||
struct vm_guest_paging *paging) | |||||
{ | |||||
struct emulate_mem_args ema; | |||||
ema.vie = vie; | |||||
ema.paging = paging; | |||||
return (access_memory(ctx, vcpu, paddr, emulate_mem_cb, &ema)); | |||||
} | |||||
struct read_mem_args { | |||||
uint64_t *rval; | |||||
int size; | |||||
}; | |||||
static int | |||||
read_mem_cb(struct vmctx *ctx, int vcpu, uint64_t paddr, struct mem_range *mr, | |||||
void *arg) | |||||
{ | |||||
struct read_mem_args *rma; | |||||
rma = arg; | |||||
return (mr->handler(ctx, vcpu, MEM_F_READ, paddr, rma->size, | |||||
rma->rval, mr->arg1, mr->arg2)); | |||||
} | |||||
int | |||||
read_mem(struct vmctx *ctx, int vcpu, uint64_t gpa, uint64_t *rval, int size) | |||||
{ | |||||
struct read_mem_args rma; | |||||
rma.rval = rval; | |||||
rma.size = size; | |||||
return (access_memory(ctx, vcpu, gpa, read_mem_cb, &rma)); | |||||
} | } | ||||
static int | static int | ||||
register_mem_int(struct mmio_rb_tree *rbt, struct mem_range *memp) | register_mem_int(struct mmio_rb_tree *rbt, struct mem_range *memp) | ||||
{ | { | ||||
struct mmio_rb_range *entry, *mrp; | struct mmio_rb_range *entry, *mrp; | ||||
int err; | int err; | ||||
▲ Show 20 Lines • Show All 72 Lines • Show Last 20 Lines |