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 (*kvm_mmio_callback_fn
)(u64 addr
, u8
*data
, u32 len
, u8 is_write
);
20 static struct rb_root mmio_tree
= RB_ROOT
;
22 static struct mmio_mapping
*mmio_search(struct rb_root
*root
, u64 addr
, u64 len
)
24 struct rb_int_node
*node
;
26 node
= rb_int_search_range(root
, addr
, addr
+ len
);
30 return mmio_node(node
);
33 /* Find lowest match, Check for overlap */
34 static struct mmio_mapping
*mmio_search_single(struct rb_root
*root
, u64 addr
)
36 struct rb_int_node
*node
;
38 node
= rb_int_search_single(root
, addr
);
42 return mmio_node(node
);
45 static int mmio_insert(struct rb_root
*root
, struct mmio_mapping
*data
)
47 return rb_int_insert(root
, &data
->node
);
50 static const char *to_direction(u8 is_write
)
58 bool kvm__register_mmio(struct kvm
*kvm
, u64 phys_addr
, u64 phys_addr_len
, void (*kvm_mmio_callback_fn
)(u64 addr
, u8
*data
, u32 len
, u8 is_write
))
60 struct mmio_mapping
*mmio
;
61 struct kvm_coalesced_mmio_zone zone
;
64 mmio
= malloc(sizeof(*mmio
));
68 *mmio
= (struct mmio_mapping
) {
69 .node
= RB_INT_INIT(phys_addr
, phys_addr
+ phys_addr_len
),
70 .kvm_mmio_callback_fn
= kvm_mmio_callback_fn
,
73 zone
= (struct kvm_coalesced_mmio_zone
) {
75 .size
= phys_addr_len
,
77 ret
= ioctl(kvm
->vm_fd
, KVM_REGISTER_COALESCED_MMIO
, &zone
);
84 ret
= mmio_insert(&mmio_tree
, mmio
);
90 bool kvm__deregister_mmio(struct kvm
*kvm
, u64 phys_addr
)
92 struct mmio_mapping
*mmio
;
93 struct kvm_coalesced_mmio_zone zone
;
96 mmio
= mmio_search_single(&mmio_tree
, phys_addr
);
102 zone
= (struct kvm_coalesced_mmio_zone
) {
106 ioctl(kvm
->vm_fd
, KVM_UNREGISTER_COALESCED_MMIO
, &zone
);
108 rb_int_erase(&mmio_tree
, &mmio
->node
);
115 bool kvm__emulate_mmio(struct kvm
*kvm
, u64 phys_addr
, u8
*data
, u32 len
, u8 is_write
)
117 struct mmio_mapping
*mmio
;
120 mmio
= mmio_search(&mmio_tree
, phys_addr
, len
);
123 mmio
->kvm_mmio_callback_fn(phys_addr
, data
, len
, is_write
);
125 fprintf(stderr
, "Warning: Ignoring MMIO %s at %016llx (length %u)\n",
126 to_direction(is_write
), phys_addr
, len
);