ia64/xen-unstable

view tools/ioemu/hw/xen_platform.c @ 18394:dade7f0bdc8d

hvm: Use main memory for video memory.

When creating an HVM domain, if e.g. another domain is created before
qemu allocates video memory, the extra 8MB memory ballooning is not
available any more, because it got consumed by the other domain.

This fixes it by taking video memory from the main memory:

- make hvmloader use e820_malloc to reserve some of the main memory
and notify ioemu of its address through the Xen platform PCI card.
- add XENMAPSPACE_mfn to the xen_add_to_physmap memory op, to allow
ioemu to move the MFNs between the original position and the PCI
mapping, when LFB acceleration is disabled/enabled
- add a remove_from_physmap memory op, to allow ioemu to unmap it
completely for the case of old guests with acceleration disabled.
- add xc_domain_memory_translate_gpfn_list to libxc to allow ioemu to
get the MFNs of the video memory.
- have xend save the PCI memory space instead of ioemu: if a memory
page is there, the guest can access it like usual memory, so xend
can safely be responsible to save it. The extra benefit is that
live migration will apply the logdirty optimization there too.
- handle old saved images, populating the video memory from ioemu if
really needed.

Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Aug 27 14:53:39 2008 +0100 (2008-08-27)
parents d5efa03793a2
children
line source
1 /*
2 * XEN platform fake pci device, formerly known as the event channel device
3 *
4 * Copyright (c) 2003-2004 Intel Corp.
5 * Copyright (c) 2006 XenSource
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25 #include "vl.h"
27 #include <xenguest.h>
29 extern FILE *logfile;
31 #define PFFLAG_ROM_LOCK 1 /* Sets whether ROM memory area is RW or RO */
33 typedef struct PCIXenPlatformState
34 {
35 PCIDevice pci_dev;
36 uint8_t platform_flags;
37 uint64_t vga_stolen_ram;
38 } PCIXenPlatformState;
40 static uint32_t xen_platform_ioport_readb(void *opaque, uint32_t addr)
41 {
42 PCIXenPlatformState *s = opaque;
44 addr &= 0xff;
46 return (addr == 0) ? s->platform_flags : ~0u;
47 }
49 static void xen_platform_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
50 {
51 PCIXenPlatformState *d = opaque;
53 addr &= 0xff;
54 val &= 0xff;
56 switch (addr) {
57 case 0: /* Platform flags */ {
58 hvmmem_type_t mem_type = (val & PFFLAG_ROM_LOCK) ?
59 HVMMEM_ram_ro : HVMMEM_ram_rw;
60 if (xc_hvm_set_mem_type(xc_handle, domid, mem_type, 0xc0, 0x40))
61 fprintf(logfile,"xen_platform: unable to change ro/rw "
62 "state of ROM memory area!\n");
63 else
64 d->platform_flags = val & PFFLAG_ROM_LOCK;
65 break;
66 }
67 default:
68 break;
69 }
70 }
73 static uint32_t xen_platform_ioport_readl(void *opaque, uint32_t addr)
74 {
75 PCIXenPlatformState *d = opaque;
77 addr &= 0xff;
79 switch (addr) {
80 case 4: /* VGA stolen memory address */
81 return d->vga_stolen_ram;
82 default:
83 return ~0u;
84 }
85 }
87 static void xen_platform_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
88 {
89 PCIXenPlatformState *d = opaque;
91 addr &= 0xff;
92 val &= 0xffffffff;
94 switch (addr) {
95 case 4: /* VGA stolen memory address */
96 d->vga_stolen_ram = val;
97 xen_vga_stolen_vram_addr(val);
98 break;
99 default:
100 break;
101 }
102 }
106 static void platform_ioport_map(PCIDevice *pci_dev, int region_num, uint32_t addr, uint32_t size, int type)
107 {
108 PCIXenPlatformState *d = (PCIXenPlatformState *)pci_dev;
109 register_ioport_write(addr, size, 1, xen_platform_ioport_writeb, d);
110 register_ioport_write(addr, size, 4, xen_platform_ioport_writel, d);
111 register_ioport_read(addr, size, 1, xen_platform_ioport_readb, d);
112 register_ioport_read(addr, size, 4, xen_platform_ioport_readl, d);
113 }
115 static uint32_t platform_mmio_read(void *opaque, target_phys_addr_t addr)
116 {
117 static int warnings = 0;
118 if (warnings < 5) {
119 fprintf(logfile, "Warning: attempted read from physical address "
120 "0x%"PRIx64" in xen platform mmio space\n", (uint64_t)addr);
121 warnings++;
122 }
123 return 0;
124 }
126 static void platform_mmio_write(void *opaque, target_phys_addr_t addr,
127 uint32_t val)
128 {
129 static int warnings = 0;
130 if (warnings < 5) {
131 fprintf(logfile, "Warning: attempted write of 0x%x to physical "
132 "address 0x%"PRIx64" in xen platform mmio space\n",
133 val, (uint64_t)addr);
134 warnings++;
135 }
136 return;
137 }
139 static CPUReadMemoryFunc *platform_mmio_read_funcs[3] = {
140 platform_mmio_read,
141 platform_mmio_read,
142 platform_mmio_read,
143 };
145 static CPUWriteMemoryFunc *platform_mmio_write_funcs[3] = {
146 platform_mmio_write,
147 platform_mmio_write,
148 platform_mmio_write,
149 };
151 static void platform_mmio_map(PCIDevice *d, int region_num,
152 uint32_t addr, uint32_t size, int type)
153 {
154 int mmio_io_addr;
156 mmio_io_addr = cpu_register_io_memory(0, platform_mmio_read_funcs,
157 platform_mmio_write_funcs, NULL);
159 cpu_register_physical_memory(addr, 0x1000000, mmio_io_addr);
160 }
162 struct pci_config_header {
163 uint16_t vendor_id;
164 uint16_t device_id;
165 uint16_t command;
166 uint16_t status;
167 uint8_t revision;
168 uint8_t api;
169 uint8_t subclass;
170 uint8_t class;
171 uint8_t cache_line_size; /* Units of 32 bit words */
172 uint8_t latency_timer; /* In units of bus cycles */
173 uint8_t header_type; /* Should be 0 */
174 uint8_t bist; /* Built in self test */
175 uint32_t base_address_regs[6];
176 uint32_t reserved1;
177 uint16_t subsystem_vendor_id;
178 uint16_t subsystem_id;
179 uint32_t rom_addr;
180 uint32_t reserved3;
181 uint32_t reserved4;
182 uint8_t interrupt_line;
183 uint8_t interrupt_pin;
184 uint8_t min_gnt;
185 uint8_t max_lat;
186 };
188 void xen_pci_save(QEMUFile *f, void *opaque)
189 {
190 PCIXenPlatformState *d = opaque;
192 pci_device_save(&d->pci_dev, f);
193 qemu_put_8s(f, &d->platform_flags);
194 qemu_put_be64s(f, &d->vga_stolen_ram);
195 }
197 int xen_pci_load(QEMUFile *f, void *opaque, int version_id)
198 {
199 PCIXenPlatformState *d = opaque;
200 int ret;
202 if (version_id > 2)
203 return -EINVAL;
205 ret = pci_device_load(&d->pci_dev, f);
206 if (ret < 0)
207 return ret;
209 if (version_id >= 2) {
210 uint8_t flags;
211 qemu_get_8s(f, &flags);
212 xen_platform_ioport_writeb(d, 0, flags);
213 qemu_get_be64s(f, &d->vga_stolen_ram);
214 }
216 return 0;
217 }
219 void pci_xen_platform_init(PCIBus *bus)
220 {
221 PCIXenPlatformState *d;
222 struct pci_config_header *pch;
224 printf("Register xen platform.\n");
225 d = (PCIXenPlatformState *)pci_register_device(
226 bus, "xen-platform", sizeof(PCIXenPlatformState), -1, NULL, NULL);
227 pch = (struct pci_config_header *)d->pci_dev.config;
228 pch->vendor_id = 0x5853;
229 pch->device_id = 0x0001;
230 pch->command = 3; /* IO and memory access */
231 pch->revision = 1;
232 pch->api = 0;
233 pch->subclass = 0x80; /* Other */
234 pch->class = 0xff; /* Unclassified device class */
235 pch->header_type = 0;
236 pch->interrupt_pin = 1;
238 /* Microsoft WHQL requires non-zero subsystem IDs. */
239 /* http://www.pcisig.com/reflector/msg02205.html. */
240 pch->subsystem_vendor_id = pch->vendor_id; /* Duplicate vendor id. */
241 pch->subsystem_id = 0x0001; /* Hardcode sub-id as 1. */
243 pci_register_io_region(&d->pci_dev, 0, 0x100,
244 PCI_ADDRESS_SPACE_IO, platform_ioport_map);
246 /* reserve 16MB mmio address for share memory*/
247 pci_register_io_region(&d->pci_dev, 1, 0x1000000,
248 PCI_ADDRESS_SPACE_MEM_PREFETCH, platform_mmio_map);
250 xen_platform_ioport_writeb(d, 0, 0);
252 register_savevm("platform", 0, 2, xen_pci_save, xen_pci_load, d);
253 printf("Done register platform.\n");
254 }