mptbl.c revision 239042
194536Sobrien/*- 294536Sobrien * Copyright (c) 2011 NetApp, Inc. 394536Sobrien * All rights reserved. 494536Sobrien * 594536Sobrien * Redistribution and use in source and binary forms, with or without 694536Sobrien * modification, are permitted provided that the following conditions 794536Sobrien * are met: 894536Sobrien * 1. Redistributions of source code must retain the above copyright 994536Sobrien * notice, this list of conditions and the following disclaimer. 1094536Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1194536Sobrien * notice, this list of conditions and the following disclaimer in the 1294536Sobrien * documentation and/or other materials provided with the distribution. 1394536Sobrien * 1494536Sobrien * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 1594536Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1694536Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1794536Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 1894536Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1994536Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2094536Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2194536Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2294536Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2394536Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2494536Sobrien * SUCH DAMAGE. 2594536Sobrien * 2694536Sobrien * $FreeBSD$ 2794536Sobrien */ 2894536Sobrien 2994536Sobrien#include <sys/cdefs.h> 3094536Sobrien__FBSDID("$FreeBSD$"); 3194536Sobrien 3294536Sobrien#include <sys/types.h> 3394536Sobrien#include <sys/mman.h> 3494536Sobrien 3592828Sobrien#include <stdio.h> 3692828Sobrien#include <string.h> 3792828Sobrien#include <machine/vmm.h> 3892828Sobrien#include <machine/vmm_dev.h> 3992828Sobrien 4092828Sobrien#include "vmmapi.h" 4192828Sobrien#include "mptable.h" 4292828Sobrien 4392828Sobrien#define LAPIC_PADDR (0xFEE00000) 4492828Sobrien#define LAPIC_VERSION (16) 4592828Sobrien 4692828Sobrien#define IOAPIC_PADDR (0xFEC00000) 4792828Sobrien#define IOAPIC_VERSION (0x11) 4892828Sobrien 4992828Sobrienextern int errno; 5092828Sobrien 5192828Sobrienstatic uint8_t 5292828Sobrienmp_compute_checksum(void *base, size_t len) 5392828Sobrien{ 5492828Sobrien uint8_t *bytes = base; 5592828Sobrien uint8_t sum = 0; 5692828Sobrien for(; len > 0; len--) { 5792828Sobrien sum += *bytes++; 5892828Sobrien } 5992828Sobrien return 256 - sum; 6092828Sobrien} 6192828Sobrien 6292828Sobrienstatic void 6392828Sobrienmp_build_mpfp(struct mp_floating_pointer *mpfp, vm_paddr_t mpfp_gpa) 6492828Sobrien{ 6592828Sobrien memset(mpfp, 0, sizeof(*mpfp)); 6692828Sobrien memcpy(mpfp->signature, MPFP_SIGNATURE, MPFP_SIGNATURE_LEN); 6792828Sobrien mpfp->mptable_paddr = mpfp_gpa + sizeof(*mpfp); 6891041Sobrien mpfp->specrev = MP_SPECREV; 6991041Sobrien mpfp->feature2 = 0; 7091041Sobrien mpfp->checksum = mp_compute_checksum(mpfp, sizeof(*mpfp)); 7191041Sobrien} 7291041Sobrien 7391041Sobrienstatic void 7491041Sobrienmp_build_mpch(struct mp_config_hdr *mpch) 7591041Sobrien{ 7691041Sobrien memset(mpch, 0, sizeof(*mpch)); 7791041Sobrien mpch->specrev = MP_SPECREV; 7891041Sobrien memcpy(mpch->signature, MPCH_SIGNATURE, MPCH_SIGNATURE_LEN); 7991041Sobrien memcpy(mpch->oemid, MPCH_OEMID, MPCH_OEMID_LEN); 8091041Sobrien memcpy(mpch->prodid, MPCH_PRODID, MPCH_PRODID_LEN); 8191041Sobrien mpch->lapic_paddr = LAPIC_PADDR; 8291041Sobrien 8391041Sobrien 8491041Sobrien} 8591041Sobrien 8691041Sobrienstatic void 8791041Sobrienmp_build_proc_entries(struct mpe_proc *mpep, int num_proc) 8891041Sobrien{ 8991041Sobrien int i; 9091041Sobrien 9191041Sobrien for (i = 0; i < num_proc; i++) { 9291041Sobrien memset(mpep, 0, sizeof(*mpep)); 9391041Sobrien mpep->entry_type = MP_ENTRY_PROC; 9491041Sobrien mpep->lapic_id = i; // XXX 9591041Sobrien mpep->lapic_version = LAPIC_VERSION; 9691041Sobrien mpep->proc_flags = (i == 0)?MPEP_FLAGS_BSP:0; 9791041Sobrien mpep->proc_flags |= MPEP_FLAGS_EN; 9891041Sobrien mpep->proc_signature = MPEP_SIGNATURE; 9991041Sobrien mpep->feature_flags = MPEP_FEATURES; 10091041Sobrien mpep++; 10191041Sobrien } 10291041Sobrien 10391041Sobrien} 10491041Sobrien 10591041Sobrienstatic void 10691041Sobrienmp_build_bus_entries(struct mpe_bus *mpeb) 10791041Sobrien{ 10891041Sobrien memset(mpeb, 0, sizeof(*mpeb)); 10991041Sobrien mpeb->entry_type = MP_ENTRY_BUS; 11091041Sobrien mpeb->busid = MPE_BUSID_ISA; 11191041Sobrien memcpy(mpeb->busname, MPE_BUSNAME_ISA, MPE_BUSNAME_LEN); 11291041Sobrien mpeb++; 11391041Sobrien 11491041Sobrien memset(mpeb, 0, sizeof(*mpeb)); 11591041Sobrien mpeb->entry_type = MP_ENTRY_BUS; 11691041Sobrien mpeb->busid = MPE_BUSID_PCI; 11791041Sobrien memcpy(mpeb->busname, MPE_BUSNAME_PCI, MPE_BUSNAME_LEN); 11891041Sobrien 11991041Sobrien} 12091041Sobrien 12191041Sobrienstatic void 12291041Sobrienmp_build_ioapic_entries(struct mpe_ioapic *mpei, int id) 12391041Sobrien{ 12491041Sobrien memset(mpei, 0, sizeof(*mpei)); 12591041Sobrien mpei->entry_type = MP_ENTRY_IOAPIC; 12691041Sobrien mpei->ioapic_id = id; 12791041Sobrien mpei->ioapic_version = IOAPIC_VERSION; 12891041Sobrien mpei->ioapic_flags = MPE_IOAPIC_FLAG_EN; 12991041Sobrien mpei->ioapic_paddr = IOAPIC_PADDR; 13091041Sobrien} 13191041Sobrien 13291041Sobrien#ifdef notyet 13391041Sobrienstatic void 13491041Sobrienmp_build_ioint_entries(struct mpe_ioint *mpeii, int num_pins, int id) 13591041Sobrien{ 13691041Sobrien int pin; 13791041Sobrien 13891041Sobrien /* 13991041Sobrien * The following config is taken from kernel mptable.c 14091041Sobrien * mptable_parse_default_config_ints(...), for now 14191041Sobrien * just use the default config, tweek later if needed. 14291041Sobrien */ 14391041Sobrien 14491041Sobrien 14591041Sobrien /* Run through all 16 pins. */ 14691041Sobrien for (pin = 0; pin < num_pins; pin++) { 14791041Sobrien memset(mpeii, 0, sizeof(*mpeii)); 14891041Sobrien mpeii->entry_type = MP_ENTRY_IOINT; 14991041Sobrien mpeii->src_bus_id = MPE_BUSID_ISA; 15091041Sobrien mpeii->dst_apic_id = id; 15191041Sobrien 15291041Sobrien /* 15391041Sobrien * All default configs route IRQs from bus 0 to the first 16 pins 15491041Sobrien * of the first I/O APIC with an APIC ID of 2. 15591041Sobrien */ 15691041Sobrien mpeii->dst_apic_intin = pin; 15791041Sobrien switch (pin) { 15891041Sobrien case 0: 15991041Sobrien /* Pin 0 is an ExtINT pin. */ 16091041Sobrien mpeii->intr_type = MPEII_INTR_EXTINT; 16191041Sobrien break; 16291041Sobrien case 2: 16391041Sobrien /* IRQ 0 is routed to pin 2. */ 16491041Sobrien mpeii->intr_type = MPEII_INTR_INT; 16591041Sobrien mpeii->src_bus_irq = 0; 16691041Sobrien break; 16791041Sobrien case 5: 16891041Sobrien case 10: 16991041Sobrien case 11: 17091041Sobrien /* 17191041Sobrien * PCI Irqs set to level triggered. 17291041Sobrien */ 17391041Sobrien mpeii->intr_flags = MPEII_FLAGS_TRIGMODE_LEVEL; 17491041Sobrien mpeii->src_bus_id = MPE_BUSID_PCI; 17591041Sobrien default: 17691041Sobrien /* All other pins are identity mapped. */ 17791041Sobrien mpeii->intr_type = MPEII_INTR_INT; 17891041Sobrien mpeii->src_bus_irq = pin; 17991041Sobrien break; 18091041Sobrien } 18191041Sobrien mpeii++; 18291041Sobrien } 18391041Sobrien 18491041Sobrien} 18591041Sobrien 18691041Sobrien#define COPYSTR(dest, src, bytes) \ 18791041Sobrien memcpy(dest, src, bytes); \ 18891041Sobrien str[bytes] = 0; 18991041Sobrien 19091041Sobrien 19191041Sobrienstatic void 19291041Sobrienmptable_dump(struct mp_floating_pointer *mpfp, struct mp_config_hdr *mpch) 19391041Sobrien{ 19491041Sobrien static char str[16]; 19591041Sobrien int i; 19691041Sobrien char *cur; 19791041Sobrien 19891041Sobrien union mpe { 19991041Sobrien struct mpe_proc *proc; 20091041Sobrien struct mpe_bus *bus; 20191041Sobrien struct mpe_ioapic *ioapic; 20291041Sobrien struct mpe_ioint *ioint; 20391041Sobrien struct mpe_lint *lnit; 20491041Sobrien char *p; 20591041Sobrien }; 20691041Sobrien 20791041Sobrien union mpe mpe; 20891041Sobrien 20991041Sobrien printf(" MP Floating Pointer :\n"); 21091041Sobrien COPYSTR(str, mpfp->signature, 4); 21191041Sobrien printf(" signature: %s\n", str); 21291041Sobrien printf(" mpch paddr: %x\n", mpfp->mptable_paddr); 21391041Sobrien printf(" length: %x\n", mpfp->length); 21491041Sobrien printf(" specrec: %x\n", mpfp->specrev); 21591041Sobrien printf(" checksum: %x\n", mpfp->checksum); 21691041Sobrien printf(" feature1: %x\n", mpfp->feature1); 21791041Sobrien printf(" feature2: %x\n", mpfp->feature2); 21891041Sobrien printf(" feature3: %x\n", mpfp->feature3); 21991041Sobrien printf(" feature4: %x\n", mpfp->feature4); 22091041Sobrien 22191041Sobrien printf(" MP Configuration Header :\n"); 22291041Sobrien COPYSTR(str, mpch->signature, 4); 22391041Sobrien printf(" signature: %s\n", str); 22491041Sobrien printf(" length: %x\n", mpch->length); 22591041Sobrien printf(" specrec: %x\n", mpch->specrev); 22691041Sobrien printf(" checksum: %x\n", mpch->checksum); 22789857Sobrien COPYSTR(str, mpch->oemid, MPCH_OEMID_LEN); 22885815Sobrien printf(" oemid: %s\n", str); 22989857Sobrien COPYSTR(str, mpch->prodid, MPCH_PRODID_LEN); 23085815Sobrien printf(" prodid: %s\n", str); 23189857Sobrien printf(" oem_ptr: %x\n", mpch->oem_ptr); 23289857Sobrien printf(" oem_sz: %x\n", mpch->oem_sz); 23389857Sobrien printf(" nr_entries: %x\n", mpch->nr_entries); 23489857Sobrien printf(" apic paddr: %x\n", mpch->lapic_paddr); 23589857Sobrien printf(" ext_length: %x\n", mpch->ext_length); 23689857Sobrien printf(" ext_checksum: %x\n", mpch->ext_checksum); 23789857Sobrien 23889857Sobrien cur = (char *)mpch + sizeof(*mpch); 23989857Sobrien for (i = 0; i < mpch->nr_entries; i++) { 24089857Sobrien mpe.p = cur; 24189857Sobrien switch(*mpe.p) { 24289857Sobrien case MP_ENTRY_PROC: 24389857Sobrien printf(" MP Processor Entry :\n"); 24489857Sobrien printf(" lapic_id: %x\n", mpe.proc->lapic_id); 24589857Sobrien printf(" lapic_version: %x\n", mpe.proc->lapic_version); 24689857Sobrien printf(" proc_flags: %x\n", mpe.proc->proc_flags); 24789857Sobrien printf(" proc_signature: %x\n", mpe.proc->proc_signature); 24889857Sobrien printf(" feature_flags: %x\n", mpe.proc->feature_flags); 24989857Sobrien cur += sizeof(struct mpe_proc); 25089857Sobrien break; 25189857Sobrien case MP_ENTRY_BUS: 25289857Sobrien printf(" MP Bus Entry :\n"); 25389857Sobrien printf(" busid: %x\n", mpe.bus->busid); 25489857Sobrien COPYSTR(str, mpe.bus->busname, MPE_BUSNAME_LEN); 25589857Sobrien printf(" busname: %s\n", str); 25689857Sobrien cur += sizeof(struct mpe_bus); 25789857Sobrien break; 25889857Sobrien case MP_ENTRY_IOAPIC: 25989857Sobrien printf(" MP IOAPIC Entry :\n"); 26089857Sobrien printf(" ioapi_id: %x\n", mpe.ioapic->ioapic_id); 26189857Sobrien printf(" ioapi_version: %x\n", mpe.ioapic->ioapic_version); 26289857Sobrien printf(" ioapi_flags: %x\n", mpe.ioapic->ioapic_flags); 26389857Sobrien printf(" ioapi_paddr: %x\n", mpe.ioapic->ioapic_paddr); 26489857Sobrien cur += sizeof(struct mpe_ioapic); 26589857Sobrien break; 26689857Sobrien case MP_ENTRY_IOINT: 26789857Sobrien printf(" MP IO Interrupt Entry :\n"); 26889857Sobrien printf(" intr_type: %x\n", mpe.ioint->intr_type); 26989857Sobrien printf(" intr_flags: %x\n", mpe.ioint->intr_flags); 27089857Sobrien printf(" src_bus_id: %x\n", mpe.ioint->src_bus_id); 27189857Sobrien printf(" src_bus_irq: %x\n", mpe.ioint->src_bus_irq); 27289857Sobrien printf(" dst_apic_id: %x\n", mpe.ioint->dst_apic_id); 27389857Sobrien printf(" dst_apic_intin: %x\n", mpe.ioint->dst_apic_intin); 27489857Sobrien cur += sizeof(struct mpe_ioint); 27589857Sobrien break; 27689857Sobrien case MP_ENTRY_LINT: 27789857Sobrien printf(" MP Local Interrupt Entry :\n"); 27889857Sobrien cur += sizeof(struct mpe_lint); 27989857Sobrien break; 28089857Sobrien } 28189857Sobrien 28289857Sobrien } 28389857Sobrien} 28489857Sobrien#endif 28589857Sobrien 28689857Sobrienint 28789857Sobrienvm_build_mptable(struct vmctx *ctx, vm_paddr_t gpa, int len, int ncpu, 28889857Sobrien int ioapic, void *oemp, int oemsz) 28989857Sobrien{ 29089857Sobrien struct mp_config_hdr *mpch; 29189857Sobrien char *mapaddr; 29289857Sobrien char *startaddr; 29389857Sobrien int error; 29489857Sobrien 29589857Sobrien mapaddr = vm_map_memory(ctx, gpa, len); 29689857Sobrien if (mapaddr == MAP_FAILED) { 29789857Sobrien printf("%s\n", strerror(errno)); 29889857Sobrien goto err; 29989857Sobrien } 30089857Sobrien startaddr = mapaddr; 30189857Sobrien 30289857Sobrien mp_build_mpfp((struct mp_floating_pointer*) mapaddr, gpa); 30389857Sobrien mapaddr += sizeof(struct mp_floating_pointer); 30489857Sobrien 30589857Sobrien mpch = (struct mp_config_hdr*)mapaddr; 30689857Sobrien mp_build_mpch(mpch); 30789857Sobrien mapaddr += sizeof(struct mp_config_hdr); 30889857Sobrien 30989857Sobrien mp_build_proc_entries((struct mpe_proc*) mapaddr, ncpu); 31089857Sobrien mapaddr += (sizeof(struct mpe_proc)*ncpu); 31189857Sobrien mpch->nr_entries += ncpu; 31289857Sobrien 31389857Sobrien mp_build_bus_entries((struct mpe_bus*)mapaddr); 31489857Sobrien mapaddr += (sizeof(struct mpe_bus)*MPE_NUM_BUSES); 31589857Sobrien mpch->nr_entries += MPE_NUM_BUSES; 31689857Sobrien 31789857Sobrien if (ioapic) { 31889857Sobrien mp_build_ioapic_entries((struct mpe_ioapic*)mapaddr, ncpu + 1); 31989857Sobrien mapaddr += sizeof(struct mpe_ioapic); 32089857Sobrien mpch->nr_entries++; 32189857Sobrien } 32289857Sobrien 32389857Sobrien#ifdef notyet 32489857Sobrien mp_build_ioint_entries((struct mpe_ioint*)mapaddr, MPEII_MAX_IRQ, 32589857Sobrien ncpu + 1); 32689857Sobrien mapaddr += sizeof(struct mpe_ioint)*MPEII_MAX_IRQ; 32789857Sobrien mpch->nr_entries += MPEII_MAX_IRQ; 32889857Sobrien 32989857Sobrien#endif 33089857Sobrien if (oemp) { 33189857Sobrien mpch->oem_ptr = mapaddr - startaddr + gpa; 33289857Sobrien mpch->oem_sz = oemsz; 33389857Sobrien memcpy(mapaddr, oemp, oemsz); 33489857Sobrien } 33589857Sobrien mpch->length = (mapaddr) - ((char*) mpch); 33689857Sobrien mpch->checksum = mp_compute_checksum(mpch, sizeof(*mpch)); 33789857Sobrien 33889857Sobrien 33989857Sobrien // mptable_dump((struct mp_floating_pointer*)startaddr, mpch); 34089857Sobrienerr: 34189857Sobrien return (error); 34289857Sobrien} 34389857Sobrien