1 #include "kvm/ioport.h"
5 #include "kvm/brlock.h"
6 #include "kvm/rbtree-interval.h"
9 #include <linux/kvm.h> /* for KVM_EXIT_* */
10 #include <linux/types.h>
18 #define ioport_node(n) rb_entry(n, struct ioport, node)
20 DEFINE_MUTEX(ioport_mutex
);
22 static u16 free_io_port_idx
; /* protected by ioport_mutex */
24 static struct rb_root ioport_tree
= RB_ROOT
;
27 static u16
ioport__find_free_port(void)
31 mutex_lock(&ioport_mutex
);
32 free_port
= IOPORT_START
+ free_io_port_idx
* IOPORT_SIZE
;
34 mutex_unlock(&ioport_mutex
);
39 static struct ioport
*ioport_search(struct rb_root
*root
, u64 addr
)
41 struct rb_int_node
*node
;
43 node
= rb_int_search_single(root
, addr
);
47 return ioport_node(node
);
50 static int ioport_insert(struct rb_root
*root
, struct ioport
*data
)
52 return rb_int_insert(root
, &data
->node
);
55 static bool debug_io_out(struct ioport
*ioport
, struct kvm
*kvm
, u16 port
, void *data
, int size
)
60 static struct ioport_operations debug_ops
= {
61 .io_out
= debug_io_out
,
64 static bool dummy_io_in(struct ioport
*ioport
, struct kvm
*kvm
, u16 port
, void *data
, int size
)
69 static bool dummy_io_out(struct ioport
*ioport
, struct kvm
*kvm
, u16 port
, void *data
, int size
)
74 static struct ioport_operations dummy_read_write_ioport_ops
= {
76 .io_out
= dummy_io_out
,
79 static struct ioport_operations dummy_write_only_ioport_ops
= {
80 .io_out
= dummy_io_out
,
83 u16
ioport__register(u16 port
, struct ioport_operations
*ops
, int count
, void *param
)
88 if (port
== IOPORT_EMPTY
)
89 port
= ioport__find_free_port();
91 entry
= ioport_search(&ioport_tree
, port
);
93 pr_warning("ioport re-registered: %x", port
);
94 rb_int_erase(&ioport_tree
, &entry
->node
);
97 entry
= malloc(sizeof(*entry
));
99 die("Failed allocating new ioport entry");
101 *entry
= (struct ioport
) {
102 .node
= RB_INT_INIT(port
, port
+ count
),
107 ioport_insert(&ioport_tree
, entry
);
114 static const char *to_direction(int direction
)
116 if (direction
== KVM_EXIT_IO_IN
)
122 static void ioport_error(u16 port
, void *data
, int direction
, int size
, u32 count
)
124 fprintf(stderr
, "IO error: %s port=%x, size=%d, count=%u\n", to_direction(direction
), port
, size
, count
);
127 bool kvm__emulate_io(struct kvm
*kvm
, u16 port
, void *data
, int direction
, int size
, u32 count
)
129 struct ioport_operations
*ops
;
131 struct ioport
*entry
;
135 entry
= ioport_search(&ioport_tree
, port
);
142 if (direction
== KVM_EXIT_IO_IN
) {
144 ret
= ops
->io_in(entry
, kvm
, port
, ptr
, size
);
147 ret
= ops
->io_out(entry
, kvm
, port
, ptr
, size
);
163 ioport_error(port
, data
, direction
, size
, count
);
165 return !ioport_debug
;
168 void ioport__setup_legacy(void)
170 /* 0x0020 - 0x003F - 8259A PIC 1 */
171 ioport__register(0x0020, &dummy_read_write_ioport_ops
, 2, NULL
);
173 /* PORT 0040-005F - PIT - PROGRAMMABLE INTERVAL TIMER (8253, 8254) */
174 ioport__register(0x0040, &dummy_read_write_ioport_ops
, 4, NULL
);
176 /* 0x00A0 - 0x00AF - 8259A PIC 2 */
177 ioport__register(0x00A0, &dummy_read_write_ioport_ops
, 2, NULL
);
179 /* PORT 00E0-00EF are 'motherboard specific' so we use them for our
180 internal debugging purposes. */
181 ioport__register(IOPORT_DBG
, &debug_ops
, 1, NULL
);
183 /* PORT 00ED - DUMMY PORT FOR DELAY??? */
184 ioport__register(0x00ED, &dummy_write_only_ioport_ops
, 1, NULL
);
186 /* 0x00F0 - 0x00FF - Math co-processor */
187 ioport__register(0x00F0, &dummy_write_only_ioport_ops
, 2, NULL
);
189 /* PORT 03D4-03D5 - COLOR VIDEO - CRT CONTROL REGISTERS */
190 ioport__register(0x03D4, &dummy_read_write_ioport_ops
, 1, NULL
);
191 ioport__register(0x03D5, &dummy_write_only_ioport_ops
, 1, NULL
);