blob: cb01ab9aad91a384b5d3024df2074858a934d5d1 [file] [log] [blame]
Anthony PERARD3285cf42010-08-19 12:27:56 +01001/*
2 * Copyright (C) 2010 Citrix Ltd.
3 *
4 * This work is licensed under the terms of the GNU GPL, version 2. See
5 * the COPYING file in the top-level directory.
6 *
7 */
8
Anthony PERARD41445302010-07-16 14:55:39 +01009#include "hw/pci.h"
Anthony PERARD3285cf42010-08-19 12:27:56 +010010#include "hw/xen_common.h"
11#include "hw/xen_backend.h"
12
Jun Nakajima432d2682010-08-31 16:41:25 +010013#include "xen-mapcache.h"
14#include "trace.h"
15
Anthony PERARD41445302010-07-16 14:55:39 +010016/* Xen specific function for piix pci */
17
18int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
19{
20 return irq_num + ((pci_dev->devfn >> 3) << 2);
21}
22
23void xen_piix3_set_irq(void *opaque, int irq_num, int level)
24{
25 xc_hvm_set_pci_intx_level(xen_xc, xen_domid, 0, 0, irq_num >> 2,
26 irq_num & 3, level);
27}
28
29void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
30{
31 int i;
32
33 /* Scan for updates to PCI link routes (0x60-0x63). */
34 for (i = 0; i < len; i++) {
35 uint8_t v = (val >> (8 * i)) & 0xff;
36 if (v & 0x80) {
37 v = 0;
38 }
39 v &= 0xf;
40 if (((address + i) >= 0x60) && ((address + i) <= 0x63)) {
41 xc_hvm_set_pci_link_route(xen_xc, xen_domid, address + i - 0x60, v);
42 }
43 }
44}
45
Anthony PERARD9c11a8a2010-06-30 17:50:10 +010046/* Xen Interrupt Controller */
47
48static void xen_set_irq(void *opaque, int irq, int level)
49{
50 xc_hvm_set_isa_irq_level(xen_xc, xen_domid, irq, level);
51}
52
53qemu_irq *xen_interrupt_controller_init(void)
54{
55 return qemu_allocate_irqs(xen_set_irq, NULL, 16);
56}
57
Jun Nakajima432d2682010-08-31 16:41:25 +010058/* Memory Ops */
59
60static void xen_ram_init(ram_addr_t ram_size)
61{
62 RAMBlock *new_block;
63 ram_addr_t below_4g_mem_size, above_4g_mem_size = 0;
64
65 new_block = qemu_mallocz(sizeof (*new_block));
66 pstrcpy(new_block->idstr, sizeof (new_block->idstr), "xen.ram");
67 new_block->host = NULL;
68 new_block->offset = 0;
69 new_block->length = ram_size;
70
71 QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);
72
73 ram_list.phys_dirty = qemu_realloc(ram_list.phys_dirty,
74 new_block->length >> TARGET_PAGE_BITS);
75 memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),
76 0xff, new_block->length >> TARGET_PAGE_BITS);
77
78 if (ram_size >= 0xe0000000 ) {
79 above_4g_mem_size = ram_size - 0xe0000000;
80 below_4g_mem_size = 0xe0000000;
81 } else {
82 below_4g_mem_size = ram_size;
83 }
84
85 cpu_register_physical_memory(0, below_4g_mem_size, new_block->offset);
86#if TARGET_PHYS_ADDR_BITS > 32
87 if (above_4g_mem_size > 0) {
88 cpu_register_physical_memory(0x100000000ULL, above_4g_mem_size,
89 new_block->offset + below_4g_mem_size);
90 }
91#endif
92}
93
94void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size)
95{
96 unsigned long nr_pfn;
97 xen_pfn_t *pfn_list;
98 int i;
99
100 trace_xen_ram_alloc(ram_addr, size);
101
102 nr_pfn = size >> TARGET_PAGE_BITS;
103 pfn_list = qemu_malloc(sizeof (*pfn_list) * nr_pfn);
104
105 for (i = 0; i < nr_pfn; i++) {
106 pfn_list[i] = (ram_addr >> TARGET_PAGE_BITS) + i;
107 }
108
109 if (xc_domain_populate_physmap_exact(xen_xc, xen_domid, nr_pfn, 0, 0, pfn_list)) {
110 hw_error("xen: failed to populate ram at %lx", ram_addr);
111 }
112
113 qemu_free(pfn_list);
114}
115
116
Anthony PERARD29d3ccd2010-06-30 12:58:34 +0100117/* VCPU Operations, MMIO, IO ring ... */
118
119static void xen_reset_vcpu(void *opaque)
120{
121 CPUState *env = opaque;
122
123 env->halted = 1;
124}
125
126void xen_vcpu_init(void)
127{
128 CPUState *first_cpu;
129
130 if ((first_cpu = qemu_get_cpu(0))) {
131 qemu_register_reset(xen_reset_vcpu, first_cpu);
132 xen_reset_vcpu(first_cpu);
133 }
134}
135
Anthony PERARD3285cf42010-08-19 12:27:56 +0100136/* Initialise Xen */
137
138int xen_init(void)
139{
140 xen_xc = xen_xc_interface_open(0, 0, 0);
141 if (xen_xc == XC_HANDLER_INITIAL_VALUE) {
142 xen_be_printf(NULL, 0, "can't open xen interface\n");
143 return -1;
144 }
145
146 return 0;
147}
Anthony PERARD29d3ccd2010-06-30 12:58:34 +0100148
149int xen_hvm_init(void)
150{
Jun Nakajima432d2682010-08-31 16:41:25 +0100151 /* Init RAM management */
152 qemu_map_cache_init();
153 xen_ram_init(ram_size);
154
Anthony PERARD29d3ccd2010-06-30 12:58:34 +0100155 return 0;
156}