xref: /kvmtool/x86/ioport.c (revision 3adbcb235020cf4de636973f2b59e559856beae1)
1 #include "kvm/ioport.h"
2 
3 #include <stdlib.h>
4 #include <stdio.h>
5 
dummy_io(struct kvm_cpu * vcpu,u64 addr,u8 * data,u32 len,u8 is_write,void * ptr)6 static void dummy_io(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
7 		     u8 is_write, void *ptr)
8 {
9 }
10 
debug_io(struct kvm_cpu * vcpu,u64 addr,u8 * data,u32 len,u8 is_write,void * ptr)11 static void debug_io(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
12 		     u8 is_write, void *ptr)
13 {
14 	if (!vcpu->kvm->cfg.ioport_debug)
15 		return;
16 
17 	fprintf(stderr, "debug port %s from VCPU%lu: port=0x%lx, size=%u",
18 		is_write ? "write" : "read", vcpu->cpu_id,
19 		(unsigned long)addr, len);
20 	if (is_write) {
21 		u32 value;
22 
23 		switch (len) {
24 		case 1: value = ioport__read8(data); break;
25 		case 2: value = ioport__read16((u16*)data); break;
26 		case 4: value = ioport__read32((u32*)data); break;
27 		default: value = 0; break;
28 		}
29 		fprintf(stderr, ", data: 0x%x\n", value);
30 	} else {
31 		fprintf(stderr, "\n");
32 	}
33 }
34 
seabios_debug_io(struct kvm_cpu * vcpu,u64 addr,u8 * data,u32 len,u8 is_write,void * ptr)35 static void seabios_debug_io(struct kvm_cpu *vcpu, u64 addr, u8 *data,
36 			     u32 len, u8 is_write, void *ptr)
37 {
38 	char ch;
39 
40 	if (!is_write)
41 		return;
42 
43 	ch = ioport__read8(data);
44 
45 	putchar(ch);
46 }
47 
48 /*
49  * The "fast A20 gate"
50  */
51 
ps2_control_io(struct kvm_cpu * vcpu,u64 addr,u8 * data,u32 len,u8 is_write,void * ptr)52 static void ps2_control_io(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
53 			   u8 is_write, void *ptr)
54 {
55 	/*
56 	 * A20 is always enabled.
57 	 */
58 	if (!is_write)
59 		ioport__write8(data, 0x02);
60 }
61 
ioport__map_irq(u8 * irq)62 void ioport__map_irq(u8 *irq)
63 {
64 }
65 
ioport__setup_arch(struct kvm * kvm)66 static int ioport__setup_arch(struct kvm *kvm)
67 {
68 	int r;
69 
70 	/* Legacy ioport setup */
71 
72 	/* 0000 - 001F - DMA1 controller */
73 	r = kvm__register_pio(kvm, 0x0000, 32, dummy_io, NULL);
74 	if (r < 0)
75 		return r;
76 
77 	/* 0x0020 - 0x003F - 8259A PIC 1 */
78 	r = kvm__register_pio(kvm, 0x0020, 2, dummy_io, NULL);
79 	if (r < 0)
80 		return r;
81 
82 	/* PORT 0040-005F - PIT - PROGRAMMABLE INTERVAL TIMER (8253, 8254) */
83 	r = kvm__register_pio(kvm, 0x0040, 4, dummy_io, NULL);
84 	if (r < 0)
85 		return r;
86 
87 	/* 0092 - PS/2 system control port A */
88 	r = kvm__register_pio(kvm, 0x0092, 1, ps2_control_io, NULL);
89 	if (r < 0)
90 		return r;
91 
92 	/* 0x00A0 - 0x00AF - 8259A PIC 2 */
93 	r = kvm__register_pio(kvm, 0x00A0, 2, dummy_io, NULL);
94 	if (r < 0)
95 		return r;
96 
97 	/* 00C0 - 001F - DMA2 controller */
98 	r = kvm__register_pio(kvm, 0x00c0, 32, dummy_io, NULL);
99 	if (r < 0)
100 		return r;
101 
102 	/* PORT 00E0-00EF are 'motherboard specific' so we use them for our
103 	   internal debugging purposes.  */
104 	r = kvm__register_pio(kvm, IOPORT_DBG, 1, debug_io, NULL);
105 	if (r < 0)
106 		return r;
107 
108 	/* PORT 00ED - DUMMY PORT FOR DELAY??? */
109 	r = kvm__register_pio(kvm, 0x00ed, 1, dummy_io, NULL);
110 	if (r < 0)
111 		return r;
112 
113 	/* 0x00F0 - 0x00FF - Math co-processor */
114 	r = kvm__register_pio(kvm, 0x00f0, 2, dummy_io, NULL);
115 
116 	if (r < 0)
117 		return r;
118 
119 	/* PORT 0278-027A - PARALLEL PRINTER PORT (usually LPT1, sometimes LPT2) */
120 	r = kvm__register_pio(kvm, 0x0278, 3, dummy_io, NULL);
121 	if (r < 0)
122 		return r;
123 
124 	/* PORT 0378-037A - PARALLEL PRINTER PORT (usually LPT2, sometimes LPT3) */
125 	r = kvm__register_pio(kvm, 0x0378, 3, dummy_io, NULL);
126 	if (r < 0)
127 		return r;
128 
129 	/* PORT 03D4-03D5 - COLOR VIDEO - CRT CONTROL REGISTERS */
130 	r = kvm__register_pio(kvm, 0x03d4, 1, dummy_io, NULL);
131 	if (r < 0)
132 		return r;
133 	r = kvm__register_pio(kvm, 0x03d5, 1, dummy_io, NULL);
134 	if (r < 0)
135 		return r;
136 
137 	r = kvm__register_pio(kvm, 0x0402, 1, seabios_debug_io, NULL);
138 	if (r < 0)
139 		return r;
140 
141 	/* 0510 - QEMU BIOS configuration register */
142 	r = kvm__register_pio(kvm, 0x0510, 2, dummy_io, NULL);
143 	if (r < 0)
144 		return r;
145 
146 	return 0;
147 }
148 dev_base_init(ioport__setup_arch);
149