2 #include "kvm/rbtree-interval.h"
3 #include "kvm/brlock.h"
10 #include <linux/types.h>
11 #include <linux/rbtree.h>
13 #define mmio_node(n) rb_entry(n, struct mmio_mapping, node)
16 struct rb_int_node node
;
17 void (*mmio_fn
)(u64 addr
, u8
*data
, u32 len
, u8 is_write
, void *ptr
);
21 static struct rb_root mmio_tree
= RB_ROOT
;
23 static struct mmio_mapping
*mmio_search(struct rb_root
*root
, u64 addr
, u64 len
)
25 struct rb_int_node
*node
;
27 node
= rb_int_search_range(root
, addr
, addr
+ len
);
31 return mmio_node(node
);
34 /* Find lowest match, Check for overlap */
35 static struct mmio_mapping
*mmio_search_single(struct rb_root
*root
, u64 addr
)
37 struct rb_int_node
*node
;
39 node
= rb_int_search_single(root
, addr
);
43 return mmio_node(node
);
46 static int mmio_insert(struct rb_root
*root
, struct mmio_mapping
*data
)
48 return rb_int_insert(root
, &data
->node
);
51 static const char *to_direction(u8 is_write
)
59 bool kvm__register_mmio(struct kvm
*kvm
, u64 phys_addr
, u64 phys_addr_len
, void (*mmio_fn
)(u64 addr
, u8
*data
, u32 len
, u8 is_write
, void *ptr
), void *ptr
)
61 struct mmio_mapping
*mmio
;
62 struct kvm_coalesced_mmio_zone zone
;
65 mmio
= malloc(sizeof(*mmio
));
69 *mmio
= (struct mmio_mapping
) {
70 .node
= RB_INT_INIT(phys_addr
, phys_addr
+ phys_addr_len
),
75 zone
= (struct kvm_coalesced_mmio_zone
) {
77 .size
= phys_addr_len
,
79 ret
= ioctl(kvm
->vm_fd
, KVM_REGISTER_COALESCED_MMIO
, &zone
);
86 ret
= mmio_insert(&mmio_tree
, mmio
);
92 bool kvm__deregister_mmio(struct kvm
*kvm
, u64 phys_addr
)
94 struct mmio_mapping
*mmio
;
95 struct kvm_coalesced_mmio_zone zone
;
98 mmio
= mmio_search_single(&mmio_tree
, phys_addr
);
104 zone
= (struct kvm_coalesced_mmio_zone
) {
108 ioctl(kvm
->vm_fd
, KVM_UNREGISTER_COALESCED_MMIO
, &zone
);
110 rb_int_erase(&mmio_tree
, &mmio
->node
);
117 bool kvm__emulate_mmio(struct kvm
*kvm
, u64 phys_addr
, u8
*data
, u32 len
, u8 is_write
)
119 struct mmio_mapping
*mmio
;
122 mmio
= mmio_search(&mmio_tree
, phys_addr
, len
);
125 mmio
->mmio_fn(phys_addr
, data
, len
, is_write
, mmio
->ptr
);
127 fprintf(stderr
, "Warning: Ignoring MMIO %s at %016llx (length %u)\n",
128 to_direction(is_write
), phys_addr
, len
);