mptbl.c revision 239042
1/*- 2 * Copyright (c) 2011 NetApp, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 29#include <sys/cdefs.h> 30__FBSDID("$FreeBSD$"); 31 32#include <sys/types.h> 33#include <sys/mman.h> 34 35#include <stdio.h> 36#include <string.h> 37#include <machine/vmm.h> 38#include <machine/vmm_dev.h> 39 40#include "vmmapi.h" 41#include "mptable.h" 42 43#define LAPIC_PADDR (0xFEE00000) 44#define LAPIC_VERSION (16) 45 46#define IOAPIC_PADDR (0xFEC00000) 47#define IOAPIC_VERSION (0x11) 48 49extern int errno; 50 51static uint8_t 52mp_compute_checksum(void *base, size_t len) 53{ 54 uint8_t *bytes = base; 55 uint8_t sum = 0; 56 for(; len > 0; len--) { 57 sum += *bytes++; 58 } 59 return 256 - sum; 60} 61 62static void 63mp_build_mpfp(struct mp_floating_pointer *mpfp, vm_paddr_t mpfp_gpa) 64{ 65 memset(mpfp, 0, sizeof(*mpfp)); 66 memcpy(mpfp->signature, MPFP_SIGNATURE, MPFP_SIGNATURE_LEN); 67 mpfp->mptable_paddr = mpfp_gpa + sizeof(*mpfp); 68 mpfp->specrev = MP_SPECREV; 69 mpfp->feature2 = 0; 70 mpfp->checksum = mp_compute_checksum(mpfp, sizeof(*mpfp)); 71} 72 73static void 74mp_build_mpch(struct mp_config_hdr *mpch) 75{ 76 memset(mpch, 0, sizeof(*mpch)); 77 mpch->specrev = MP_SPECREV; 78 memcpy(mpch->signature, MPCH_SIGNATURE, MPCH_SIGNATURE_LEN); 79 memcpy(mpch->oemid, MPCH_OEMID, MPCH_OEMID_LEN); 80 memcpy(mpch->prodid, MPCH_PRODID, MPCH_PRODID_LEN); 81 mpch->lapic_paddr = LAPIC_PADDR; 82 83 84} 85 86static void 87mp_build_proc_entries(struct mpe_proc *mpep, int num_proc) 88{ 89 int i; 90 91 for (i = 0; i < num_proc; i++) { 92 memset(mpep, 0, sizeof(*mpep)); 93 mpep->entry_type = MP_ENTRY_PROC; 94 mpep->lapic_id = i; // XXX 95 mpep->lapic_version = LAPIC_VERSION; 96 mpep->proc_flags = (i == 0)?MPEP_FLAGS_BSP:0; 97 mpep->proc_flags |= MPEP_FLAGS_EN; 98 mpep->proc_signature = MPEP_SIGNATURE; 99 mpep->feature_flags = MPEP_FEATURES; 100 mpep++; 101 } 102 103} 104 105static void 106mp_build_bus_entries(struct mpe_bus *mpeb) 107{ 108 memset(mpeb, 0, sizeof(*mpeb)); 109 mpeb->entry_type = MP_ENTRY_BUS; 110 mpeb->busid = MPE_BUSID_ISA; 111 memcpy(mpeb->busname, MPE_BUSNAME_ISA, MPE_BUSNAME_LEN); 112 mpeb++; 113 114 memset(mpeb, 0, sizeof(*mpeb)); 115 mpeb->entry_type = MP_ENTRY_BUS; 116 mpeb->busid = MPE_BUSID_PCI; 117 memcpy(mpeb->busname, MPE_BUSNAME_PCI, MPE_BUSNAME_LEN); 118 119} 120 121static void 122mp_build_ioapic_entries(struct mpe_ioapic *mpei, int id) 123{ 124 memset(mpei, 0, sizeof(*mpei)); 125 mpei->entry_type = MP_ENTRY_IOAPIC; 126 mpei->ioapic_id = id; 127 mpei->ioapic_version = IOAPIC_VERSION; 128 mpei->ioapic_flags = MPE_IOAPIC_FLAG_EN; 129 mpei->ioapic_paddr = IOAPIC_PADDR; 130} 131 132#ifdef notyet 133static void 134mp_build_ioint_entries(struct mpe_ioint *mpeii, int num_pins, int id) 135{ 136 int pin; 137 138 /* 139 * The following config is taken from kernel mptable.c 140 * mptable_parse_default_config_ints(...), for now 141 * just use the default config, tweek later if needed. 142 */ 143 144 145 /* Run through all 16 pins. */ 146 for (pin = 0; pin < num_pins; pin++) { 147 memset(mpeii, 0, sizeof(*mpeii)); 148 mpeii->entry_type = MP_ENTRY_IOINT; 149 mpeii->src_bus_id = MPE_BUSID_ISA; 150 mpeii->dst_apic_id = id; 151 152 /* 153 * All default configs route IRQs from bus 0 to the first 16 pins 154 * of the first I/O APIC with an APIC ID of 2. 155 */ 156 mpeii->dst_apic_intin = pin; 157 switch (pin) { 158 case 0: 159 /* Pin 0 is an ExtINT pin. */ 160 mpeii->intr_type = MPEII_INTR_EXTINT; 161 break; 162 case 2: 163 /* IRQ 0 is routed to pin 2. */ 164 mpeii->intr_type = MPEII_INTR_INT; 165 mpeii->src_bus_irq = 0; 166 break; 167 case 5: 168 case 10: 169 case 11: 170 /* 171 * PCI Irqs set to level triggered. 172 */ 173 mpeii->intr_flags = MPEII_FLAGS_TRIGMODE_LEVEL; 174 mpeii->src_bus_id = MPE_BUSID_PCI; 175 default: 176 /* All other pins are identity mapped. */ 177 mpeii->intr_type = MPEII_INTR_INT; 178 mpeii->src_bus_irq = pin; 179 break; 180 } 181 mpeii++; 182 } 183 184} 185 186#define COPYSTR(dest, src, bytes) \ 187 memcpy(dest, src, bytes); \ 188 str[bytes] = 0; 189 190 191static void 192mptable_dump(struct mp_floating_pointer *mpfp, struct mp_config_hdr *mpch) 193{ 194 static char str[16]; 195 int i; 196 char *cur; 197 198 union mpe { 199 struct mpe_proc *proc; 200 struct mpe_bus *bus; 201 struct mpe_ioapic *ioapic; 202 struct mpe_ioint *ioint; 203 struct mpe_lint *lnit; 204 char *p; 205 }; 206 207 union mpe mpe; 208 209 printf(" MP Floating Pointer :\n"); 210 COPYSTR(str, mpfp->signature, 4); 211 printf(" signature: %s\n", str); 212 printf(" mpch paddr: %x\n", mpfp->mptable_paddr); 213 printf(" length: %x\n", mpfp->length); 214 printf(" specrec: %x\n", mpfp->specrev); 215 printf(" checksum: %x\n", mpfp->checksum); 216 printf(" feature1: %x\n", mpfp->feature1); 217 printf(" feature2: %x\n", mpfp->feature2); 218 printf(" feature3: %x\n", mpfp->feature3); 219 printf(" feature4: %x\n", mpfp->feature4); 220 221 printf(" MP Configuration Header :\n"); 222 COPYSTR(str, mpch->signature, 4); 223 printf(" signature: %s\n", str); 224 printf(" length: %x\n", mpch->length); 225 printf(" specrec: %x\n", mpch->specrev); 226 printf(" checksum: %x\n", mpch->checksum); 227 COPYSTR(str, mpch->oemid, MPCH_OEMID_LEN); 228 printf(" oemid: %s\n", str); 229 COPYSTR(str, mpch->prodid, MPCH_PRODID_LEN); 230 printf(" prodid: %s\n", str); 231 printf(" oem_ptr: %x\n", mpch->oem_ptr); 232 printf(" oem_sz: %x\n", mpch->oem_sz); 233 printf(" nr_entries: %x\n", mpch->nr_entries); 234 printf(" apic paddr: %x\n", mpch->lapic_paddr); 235 printf(" ext_length: %x\n", mpch->ext_length); 236 printf(" ext_checksum: %x\n", mpch->ext_checksum); 237 238 cur = (char *)mpch + sizeof(*mpch); 239 for (i = 0; i < mpch->nr_entries; i++) { 240 mpe.p = cur; 241 switch(*mpe.p) { 242 case MP_ENTRY_PROC: 243 printf(" MP Processor Entry :\n"); 244 printf(" lapic_id: %x\n", mpe.proc->lapic_id); 245 printf(" lapic_version: %x\n", mpe.proc->lapic_version); 246 printf(" proc_flags: %x\n", mpe.proc->proc_flags); 247 printf(" proc_signature: %x\n", mpe.proc->proc_signature); 248 printf(" feature_flags: %x\n", mpe.proc->feature_flags); 249 cur += sizeof(struct mpe_proc); 250 break; 251 case MP_ENTRY_BUS: 252 printf(" MP Bus Entry :\n"); 253 printf(" busid: %x\n", mpe.bus->busid); 254 COPYSTR(str, mpe.bus->busname, MPE_BUSNAME_LEN); 255 printf(" busname: %s\n", str); 256 cur += sizeof(struct mpe_bus); 257 break; 258 case MP_ENTRY_IOAPIC: 259 printf(" MP IOAPIC Entry :\n"); 260 printf(" ioapi_id: %x\n", mpe.ioapic->ioapic_id); 261 printf(" ioapi_version: %x\n", mpe.ioapic->ioapic_version); 262 printf(" ioapi_flags: %x\n", mpe.ioapic->ioapic_flags); 263 printf(" ioapi_paddr: %x\n", mpe.ioapic->ioapic_paddr); 264 cur += sizeof(struct mpe_ioapic); 265 break; 266 case MP_ENTRY_IOINT: 267 printf(" MP IO Interrupt Entry :\n"); 268 printf(" intr_type: %x\n", mpe.ioint->intr_type); 269 printf(" intr_flags: %x\n", mpe.ioint->intr_flags); 270 printf(" src_bus_id: %x\n", mpe.ioint->src_bus_id); 271 printf(" src_bus_irq: %x\n", mpe.ioint->src_bus_irq); 272 printf(" dst_apic_id: %x\n", mpe.ioint->dst_apic_id); 273 printf(" dst_apic_intin: %x\n", mpe.ioint->dst_apic_intin); 274 cur += sizeof(struct mpe_ioint); 275 break; 276 case MP_ENTRY_LINT: 277 printf(" MP Local Interrupt Entry :\n"); 278 cur += sizeof(struct mpe_lint); 279 break; 280 } 281 282 } 283} 284#endif 285 286int 287vm_build_mptable(struct vmctx *ctx, vm_paddr_t gpa, int len, int ncpu, 288 int ioapic, void *oemp, int oemsz) 289{ 290 struct mp_config_hdr *mpch; 291 char *mapaddr; 292 char *startaddr; 293 int error; 294 295 mapaddr = vm_map_memory(ctx, gpa, len); 296 if (mapaddr == MAP_FAILED) { 297 printf("%s\n", strerror(errno)); 298 goto err; 299 } 300 startaddr = mapaddr; 301 302 mp_build_mpfp((struct mp_floating_pointer*) mapaddr, gpa); 303 mapaddr += sizeof(struct mp_floating_pointer); 304 305 mpch = (struct mp_config_hdr*)mapaddr; 306 mp_build_mpch(mpch); 307 mapaddr += sizeof(struct mp_config_hdr); 308 309 mp_build_proc_entries((struct mpe_proc*) mapaddr, ncpu); 310 mapaddr += (sizeof(struct mpe_proc)*ncpu); 311 mpch->nr_entries += ncpu; 312 313 mp_build_bus_entries((struct mpe_bus*)mapaddr); 314 mapaddr += (sizeof(struct mpe_bus)*MPE_NUM_BUSES); 315 mpch->nr_entries += MPE_NUM_BUSES; 316 317 if (ioapic) { 318 mp_build_ioapic_entries((struct mpe_ioapic*)mapaddr, ncpu + 1); 319 mapaddr += sizeof(struct mpe_ioapic); 320 mpch->nr_entries++; 321 } 322 323#ifdef notyet 324 mp_build_ioint_entries((struct mpe_ioint*)mapaddr, MPEII_MAX_IRQ, 325 ncpu + 1); 326 mapaddr += sizeof(struct mpe_ioint)*MPEII_MAX_IRQ; 327 mpch->nr_entries += MPEII_MAX_IRQ; 328 329#endif 330 if (oemp) { 331 mpch->oem_ptr = mapaddr - startaddr + gpa; 332 mpch->oem_sz = oemsz; 333 memcpy(mapaddr, oemp, oemsz); 334 } 335 mpch->length = (mapaddr) - ((char*) mpch); 336 mpch->checksum = mp_compute_checksum(mpch, sizeof(*mpch)); 337 338 339 // mptable_dump((struct mp_floating_pointer*)startaddr, mpch); 340err: 341 return (error); 342} 343