14fe5b70cSMark Johnston /*- 24fe5b70cSMark Johnston * SPDX-License-Identifier: BSD-2-Clause 34fe5b70cSMark Johnston * 44fe5b70cSMark Johnston * Copyright (c) 2012 NetApp, Inc. 54fe5b70cSMark Johnston * All rights reserved. 64fe5b70cSMark Johnston * 74fe5b70cSMark Johnston * Redistribution and use in source and binary forms, with or without 84fe5b70cSMark Johnston * modification, are permitted provided that the following conditions 94fe5b70cSMark Johnston * are met: 104fe5b70cSMark Johnston * 1. Redistributions of source code must retain the above copyright 114fe5b70cSMark Johnston * notice, this list of conditions and the following disclaimer. 124fe5b70cSMark Johnston * 2. Redistributions in binary form must reproduce the above copyright 134fe5b70cSMark Johnston * notice, this list of conditions and the following disclaimer in the 144fe5b70cSMark Johnston * documentation and/or other materials provided with the distribution. 154fe5b70cSMark Johnston * 164fe5b70cSMark Johnston * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 174fe5b70cSMark Johnston * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 184fe5b70cSMark Johnston * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 194fe5b70cSMark Johnston * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 204fe5b70cSMark Johnston * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 214fe5b70cSMark Johnston * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 224fe5b70cSMark Johnston * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 234fe5b70cSMark Johnston * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 244fe5b70cSMark Johnston * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 254fe5b70cSMark Johnston * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 264fe5b70cSMark Johnston * SUCH DAMAGE. 274fe5b70cSMark Johnston */ 284fe5b70cSMark Johnston 294fe5b70cSMark Johnston #include <sys/types.h> 304fe5b70cSMark Johnston #include <sys/errno.h> 314fe5b70cSMark Johnston #include <x86/mptable.h> 324fe5b70cSMark Johnston 334fe5b70cSMark Johnston #include <stdio.h> 344fe5b70cSMark Johnston #include <string.h> 354fe5b70cSMark Johnston 364fe5b70cSMark Johnston #include "acpi.h" 374fe5b70cSMark Johnston #include "debug.h" 384fe5b70cSMark Johnston #include "bhyverun.h" 394fe5b70cSMark Johnston #include "mptbl.h" 404fe5b70cSMark Johnston #include "pci_emul.h" 414fe5b70cSMark Johnston 424fe5b70cSMark Johnston #define MPTABLE_BASE 0xF0000 434fe5b70cSMark Johnston 444fe5b70cSMark Johnston /* floating pointer length + maximum length of configuration table */ 454fe5b70cSMark Johnston #define MPTABLE_MAX_LENGTH (65536 + 16) 464fe5b70cSMark Johnston 474fe5b70cSMark Johnston #define LAPIC_PADDR 0xFEE00000 484fe5b70cSMark Johnston #define LAPIC_VERSION 16 494fe5b70cSMark Johnston 504fe5b70cSMark Johnston #define IOAPIC_PADDR 0xFEC00000 514fe5b70cSMark Johnston #define IOAPIC_VERSION 0x11 524fe5b70cSMark Johnston 534fe5b70cSMark Johnston #define MP_SPECREV 4 544fe5b70cSMark Johnston #define MPFP_SIG "_MP_" 554fe5b70cSMark Johnston 564fe5b70cSMark Johnston /* Configuration header defines */ 574fe5b70cSMark Johnston #define MPCH_SIG "PCMP" 584fe5b70cSMark Johnston #define MPCH_OEMID "BHyVe " 594fe5b70cSMark Johnston #define MPCH_OEMID_LEN 8 604fe5b70cSMark Johnston #define MPCH_PRODID "Hypervisor " 614fe5b70cSMark Johnston #define MPCH_PRODID_LEN 12 624fe5b70cSMark Johnston 634fe5b70cSMark Johnston /* Processor entry defines */ 644fe5b70cSMark Johnston #define MPEP_SIG_FAMILY 6 /* XXX bhyve should supply this */ 654fe5b70cSMark Johnston #define MPEP_SIG_MODEL 26 664fe5b70cSMark Johnston #define MPEP_SIG_STEPPING 5 674fe5b70cSMark Johnston #define MPEP_SIG \ 684fe5b70cSMark Johnston ((MPEP_SIG_FAMILY << 8) | \ 694fe5b70cSMark Johnston (MPEP_SIG_MODEL << 4) | \ 704fe5b70cSMark Johnston (MPEP_SIG_STEPPING)) 714fe5b70cSMark Johnston 724fe5b70cSMark Johnston #define MPEP_FEATURES (0xBFEBFBFF) /* XXX Intel i7 */ 734fe5b70cSMark Johnston 744fe5b70cSMark Johnston /* Number of local intr entries */ 754fe5b70cSMark Johnston #define MPEII_NUM_LOCAL_IRQ 2 764fe5b70cSMark Johnston 774fe5b70cSMark Johnston /* Bus entry defines */ 784fe5b70cSMark Johnston #define MPE_NUM_BUSES 2 794fe5b70cSMark Johnston #define MPE_BUSNAME_LEN 6 804fe5b70cSMark Johnston #define MPE_BUSNAME_ISA "ISA " 814fe5b70cSMark Johnston #define MPE_BUSNAME_PCI "PCI " 824fe5b70cSMark Johnston 834fe5b70cSMark Johnston static void *oem_tbl_start; 844fe5b70cSMark Johnston static int oem_tbl_size; 854fe5b70cSMark Johnston 864fe5b70cSMark Johnston static uint8_t 874fe5b70cSMark Johnston mpt_compute_checksum(void *base, size_t len) 884fe5b70cSMark Johnston { 894fe5b70cSMark Johnston uint8_t *bytes; 904fe5b70cSMark Johnston uint8_t sum; 914fe5b70cSMark Johnston 924fe5b70cSMark Johnston for(bytes = base, sum = 0; len > 0; len--) { 934fe5b70cSMark Johnston sum += *bytes++; 944fe5b70cSMark Johnston } 954fe5b70cSMark Johnston 964fe5b70cSMark Johnston return (256 - sum); 974fe5b70cSMark Johnston } 984fe5b70cSMark Johnston 994fe5b70cSMark Johnston static void 1004fe5b70cSMark Johnston mpt_build_mpfp(mpfps_t mpfp, vm_paddr_t gpa) 1014fe5b70cSMark Johnston { 1024fe5b70cSMark Johnston 1034fe5b70cSMark Johnston memset(mpfp, 0, sizeof(*mpfp)); 1044fe5b70cSMark Johnston memcpy(mpfp->signature, MPFP_SIG, 4); 1054fe5b70cSMark Johnston mpfp->pap = gpa + sizeof(*mpfp); 1064fe5b70cSMark Johnston mpfp->length = 1; 1074fe5b70cSMark Johnston mpfp->spec_rev = MP_SPECREV; 1084fe5b70cSMark Johnston mpfp->checksum = mpt_compute_checksum(mpfp, sizeof(*mpfp)); 1094fe5b70cSMark Johnston } 1104fe5b70cSMark Johnston 1114fe5b70cSMark Johnston static void 1124fe5b70cSMark Johnston mpt_build_mpch(mpcth_t mpch) 1134fe5b70cSMark Johnston { 1144fe5b70cSMark Johnston 1154fe5b70cSMark Johnston memset(mpch, 0, sizeof(*mpch)); 1164fe5b70cSMark Johnston memcpy(mpch->signature, MPCH_SIG, 4); 1174fe5b70cSMark Johnston mpch->spec_rev = MP_SPECREV; 1184fe5b70cSMark Johnston memcpy(mpch->oem_id, MPCH_OEMID, MPCH_OEMID_LEN); 1194fe5b70cSMark Johnston memcpy(mpch->product_id, MPCH_PRODID, MPCH_PRODID_LEN); 1204fe5b70cSMark Johnston mpch->apic_address = LAPIC_PADDR; 1214fe5b70cSMark Johnston } 1224fe5b70cSMark Johnston 1234fe5b70cSMark Johnston static void 1244fe5b70cSMark Johnston mpt_build_proc_entries(proc_entry_ptr mpep, int ncpu) 1254fe5b70cSMark Johnston { 1264fe5b70cSMark Johnston int i; 1274fe5b70cSMark Johnston 1284fe5b70cSMark Johnston for (i = 0; i < ncpu; i++) { 1294fe5b70cSMark Johnston memset(mpep, 0, sizeof(*mpep)); 1304fe5b70cSMark Johnston mpep->type = MPCT_ENTRY_PROCESSOR; 1314fe5b70cSMark Johnston mpep->apic_id = i; // XXX 1324fe5b70cSMark Johnston mpep->apic_version = LAPIC_VERSION; 1334fe5b70cSMark Johnston mpep->cpu_flags = PROCENTRY_FLAG_EN; 1344fe5b70cSMark Johnston if (i == 0) 1354fe5b70cSMark Johnston mpep->cpu_flags |= PROCENTRY_FLAG_BP; 1364fe5b70cSMark Johnston mpep->cpu_signature = MPEP_SIG; 1374fe5b70cSMark Johnston mpep->feature_flags = MPEP_FEATURES; 1384fe5b70cSMark Johnston mpep++; 1394fe5b70cSMark Johnston } 1404fe5b70cSMark Johnston } 1414fe5b70cSMark Johnston 1424fe5b70cSMark Johnston static void 1434fe5b70cSMark Johnston mpt_build_localint_entries(int_entry_ptr mpie) 1444fe5b70cSMark Johnston { 1454fe5b70cSMark Johnston 1464fe5b70cSMark Johnston /* Hardcode LINT0 as ExtINT on all CPUs. */ 1474fe5b70cSMark Johnston memset(mpie, 0, sizeof(*mpie)); 1484fe5b70cSMark Johnston mpie->type = MPCT_ENTRY_LOCAL_INT; 1494fe5b70cSMark Johnston mpie->int_type = INTENTRY_TYPE_EXTINT; 1504fe5b70cSMark Johnston mpie->int_flags = INTENTRY_FLAGS_POLARITY_CONFORM | 1514fe5b70cSMark Johnston INTENTRY_FLAGS_TRIGGER_CONFORM; 1524fe5b70cSMark Johnston mpie->dst_apic_id = 0xff; 1534fe5b70cSMark Johnston mpie->dst_apic_int = 0; 1544fe5b70cSMark Johnston mpie++; 1554fe5b70cSMark Johnston 1564fe5b70cSMark Johnston /* Hardcode LINT1 as NMI on all CPUs. */ 1574fe5b70cSMark Johnston memset(mpie, 0, sizeof(*mpie)); 1584fe5b70cSMark Johnston mpie->type = MPCT_ENTRY_LOCAL_INT; 1594fe5b70cSMark Johnston mpie->int_type = INTENTRY_TYPE_NMI; 1604fe5b70cSMark Johnston mpie->int_flags = INTENTRY_FLAGS_POLARITY_CONFORM | 1614fe5b70cSMark Johnston INTENTRY_FLAGS_TRIGGER_CONFORM; 1624fe5b70cSMark Johnston mpie->dst_apic_id = 0xff; 1634fe5b70cSMark Johnston mpie->dst_apic_int = 1; 1644fe5b70cSMark Johnston } 1654fe5b70cSMark Johnston 1664fe5b70cSMark Johnston static void 1674fe5b70cSMark Johnston mpt_build_bus_entries(bus_entry_ptr mpeb) 1684fe5b70cSMark Johnston { 1694fe5b70cSMark Johnston 1704fe5b70cSMark Johnston memset(mpeb, 0, sizeof(*mpeb)); 1714fe5b70cSMark Johnston mpeb->type = MPCT_ENTRY_BUS; 1724fe5b70cSMark Johnston mpeb->bus_id = 0; 1734fe5b70cSMark Johnston memcpy(mpeb->bus_type, MPE_BUSNAME_PCI, MPE_BUSNAME_LEN); 1744fe5b70cSMark Johnston mpeb++; 1754fe5b70cSMark Johnston 1764fe5b70cSMark Johnston memset(mpeb, 0, sizeof(*mpeb)); 1774fe5b70cSMark Johnston mpeb->type = MPCT_ENTRY_BUS; 1784fe5b70cSMark Johnston mpeb->bus_id = 1; 1794fe5b70cSMark Johnston memcpy(mpeb->bus_type, MPE_BUSNAME_ISA, MPE_BUSNAME_LEN); 1804fe5b70cSMark Johnston } 1814fe5b70cSMark Johnston 1824fe5b70cSMark Johnston static void 1834fe5b70cSMark Johnston mpt_build_ioapic_entries(io_apic_entry_ptr mpei, int id) 1844fe5b70cSMark Johnston { 1854fe5b70cSMark Johnston 1864fe5b70cSMark Johnston memset(mpei, 0, sizeof(*mpei)); 1874fe5b70cSMark Johnston mpei->type = MPCT_ENTRY_IOAPIC; 1884fe5b70cSMark Johnston mpei->apic_id = id; 1894fe5b70cSMark Johnston mpei->apic_version = IOAPIC_VERSION; 1904fe5b70cSMark Johnston mpei->apic_flags = IOAPICENTRY_FLAG_EN; 1914fe5b70cSMark Johnston mpei->apic_address = IOAPIC_PADDR; 1924fe5b70cSMark Johnston } 1934fe5b70cSMark Johnston 1944fe5b70cSMark Johnston static int 1954fe5b70cSMark Johnston mpt_count_ioint_entries(void) 1964fe5b70cSMark Johnston { 1974fe5b70cSMark Johnston int bus, count; 1984fe5b70cSMark Johnston 1994fe5b70cSMark Johnston count = 0; 2004fe5b70cSMark Johnston for (bus = 0; bus <= PCI_BUSMAX; bus++) 2014fe5b70cSMark Johnston count += pci_count_lintr(bus); 2024fe5b70cSMark Johnston 2034fe5b70cSMark Johnston /* 2044fe5b70cSMark Johnston * Always include entries for the first 16 pins along with a entry 2054fe5b70cSMark Johnston * for each active PCI INTx pin. 2064fe5b70cSMark Johnston */ 2074fe5b70cSMark Johnston return (16 + count); 2084fe5b70cSMark Johnston } 2094fe5b70cSMark Johnston 2104fe5b70cSMark Johnston static void 211*0efad4acSJessica Clarke mpt_generate_pci_int(int bus, int slot, int pin, struct pci_irq *irq, 212*0efad4acSJessica Clarke void *arg) 2134fe5b70cSMark Johnston { 2144fe5b70cSMark Johnston int_entry_ptr *mpiep, mpie; 2154fe5b70cSMark Johnston 2164fe5b70cSMark Johnston mpiep = arg; 2174fe5b70cSMark Johnston mpie = *mpiep; 2184fe5b70cSMark Johnston memset(mpie, 0, sizeof(*mpie)); 2194fe5b70cSMark Johnston 2204fe5b70cSMark Johnston /* 2214fe5b70cSMark Johnston * This is always after another I/O interrupt entry, so cheat 2224fe5b70cSMark Johnston * and fetch the I/O APIC ID from the prior entry. 2234fe5b70cSMark Johnston */ 2244fe5b70cSMark Johnston mpie->type = MPCT_ENTRY_INT; 2254fe5b70cSMark Johnston mpie->int_type = INTENTRY_TYPE_INT; 2264fe5b70cSMark Johnston mpie->src_bus_id = bus; 2274fe5b70cSMark Johnston mpie->src_bus_irq = slot << 2 | (pin - 1); 2284fe5b70cSMark Johnston mpie->dst_apic_id = mpie[-1].dst_apic_id; 229*0efad4acSJessica Clarke mpie->dst_apic_int = irq->ioapic_irq; 2304fe5b70cSMark Johnston 2314fe5b70cSMark Johnston *mpiep = mpie + 1; 2324fe5b70cSMark Johnston } 2334fe5b70cSMark Johnston 2344fe5b70cSMark Johnston static void 2354fe5b70cSMark Johnston mpt_build_ioint_entries(int_entry_ptr mpie, int id) 2364fe5b70cSMark Johnston { 2374fe5b70cSMark Johnston int pin, bus; 2384fe5b70cSMark Johnston 2394fe5b70cSMark Johnston /* 2404fe5b70cSMark Johnston * The following config is taken from kernel mptable.c 2414fe5b70cSMark Johnston * mptable_parse_default_config_ints(...), for now 2424fe5b70cSMark Johnston * just use the default config, tweek later if needed. 2434fe5b70cSMark Johnston */ 2444fe5b70cSMark Johnston 2454fe5b70cSMark Johnston /* First, generate the first 16 pins. */ 2464fe5b70cSMark Johnston for (pin = 0; pin < 16; pin++) { 2474fe5b70cSMark Johnston memset(mpie, 0, sizeof(*mpie)); 2484fe5b70cSMark Johnston mpie->type = MPCT_ENTRY_INT; 2494fe5b70cSMark Johnston mpie->src_bus_id = 1; 2504fe5b70cSMark Johnston mpie->dst_apic_id = id; 2514fe5b70cSMark Johnston 2524fe5b70cSMark Johnston /* 2534fe5b70cSMark Johnston * All default configs route IRQs from bus 0 to the first 16 2544fe5b70cSMark Johnston * pins of the first I/O APIC with an APIC ID of 2. 2554fe5b70cSMark Johnston */ 2564fe5b70cSMark Johnston mpie->dst_apic_int = pin; 2574fe5b70cSMark Johnston switch (pin) { 2584fe5b70cSMark Johnston case 0: 2594fe5b70cSMark Johnston /* Pin 0 is an ExtINT pin. */ 2604fe5b70cSMark Johnston mpie->int_type = INTENTRY_TYPE_EXTINT; 2614fe5b70cSMark Johnston break; 2624fe5b70cSMark Johnston case 2: 2634fe5b70cSMark Johnston /* IRQ 0 is routed to pin 2. */ 2644fe5b70cSMark Johnston mpie->int_type = INTENTRY_TYPE_INT; 2654fe5b70cSMark Johnston mpie->src_bus_irq = 0; 2664fe5b70cSMark Johnston break; 2674fe5b70cSMark Johnston case SCI_INT: 2684fe5b70cSMark Johnston /* ACPI SCI is level triggered and active-lo. */ 2694fe5b70cSMark Johnston mpie->int_flags = INTENTRY_FLAGS_POLARITY_ACTIVELO | 2704fe5b70cSMark Johnston INTENTRY_FLAGS_TRIGGER_LEVEL; 2714fe5b70cSMark Johnston mpie->int_type = INTENTRY_TYPE_INT; 2724fe5b70cSMark Johnston mpie->src_bus_irq = SCI_INT; 2734fe5b70cSMark Johnston break; 2744fe5b70cSMark Johnston default: 2754fe5b70cSMark Johnston /* All other pins are identity mapped. */ 2764fe5b70cSMark Johnston mpie->int_type = INTENTRY_TYPE_INT; 2774fe5b70cSMark Johnston mpie->src_bus_irq = pin; 2784fe5b70cSMark Johnston break; 2794fe5b70cSMark Johnston } 2804fe5b70cSMark Johnston mpie++; 2814fe5b70cSMark Johnston } 2824fe5b70cSMark Johnston 2834fe5b70cSMark Johnston /* Next, generate entries for any PCI INTx interrupts. */ 2844fe5b70cSMark Johnston for (bus = 0; bus <= PCI_BUSMAX; bus++) 2854fe5b70cSMark Johnston pci_walk_lintr(bus, mpt_generate_pci_int, &mpie); 2864fe5b70cSMark Johnston } 2874fe5b70cSMark Johnston 2884fe5b70cSMark Johnston void 2894fe5b70cSMark Johnston mptable_add_oemtbl(void *tbl, int tblsz) 2904fe5b70cSMark Johnston { 2914fe5b70cSMark Johnston 2924fe5b70cSMark Johnston oem_tbl_start = tbl; 2934fe5b70cSMark Johnston oem_tbl_size = tblsz; 2944fe5b70cSMark Johnston } 2954fe5b70cSMark Johnston 2964fe5b70cSMark Johnston int 2974fe5b70cSMark Johnston mptable_build(struct vmctx *ctx, int ncpu) 2984fe5b70cSMark Johnston { 2994fe5b70cSMark Johnston mpcth_t mpch; 3004fe5b70cSMark Johnston bus_entry_ptr mpeb; 3014fe5b70cSMark Johnston io_apic_entry_ptr mpei; 3024fe5b70cSMark Johnston proc_entry_ptr mpep; 3034fe5b70cSMark Johnston mpfps_t mpfp; 3044fe5b70cSMark Johnston int_entry_ptr mpie; 3054fe5b70cSMark Johnston int ioints, bus; 3064fe5b70cSMark Johnston char *curraddr; 3074fe5b70cSMark Johnston char *startaddr; 3084fe5b70cSMark Johnston 3094fe5b70cSMark Johnston startaddr = paddr_guest2host(ctx, MPTABLE_BASE, MPTABLE_MAX_LENGTH); 3104fe5b70cSMark Johnston if (startaddr == NULL) { 3114fe5b70cSMark Johnston EPRINTLN("mptable requires mapped mem"); 3124fe5b70cSMark Johnston return (ENOMEM); 3134fe5b70cSMark Johnston } 3144fe5b70cSMark Johnston 3154fe5b70cSMark Johnston /* 3164fe5b70cSMark Johnston * There is no way to advertise multiple PCI hierarchies via MPtable 3174fe5b70cSMark Johnston * so require that there is no PCI hierarchy with a non-zero bus 3184fe5b70cSMark Johnston * number. 3194fe5b70cSMark Johnston */ 3204fe5b70cSMark Johnston for (bus = 1; bus <= PCI_BUSMAX; bus++) { 3214fe5b70cSMark Johnston if (pci_bus_configured(bus)) { 3224fe5b70cSMark Johnston EPRINTLN("MPtable is incompatible with " 3234fe5b70cSMark Johnston "multiple PCI hierarchies."); 3244fe5b70cSMark Johnston EPRINTLN("MPtable generation can be disabled " 3254fe5b70cSMark Johnston "by passing the -Y option to bhyve(8)."); 3264fe5b70cSMark Johnston return (EINVAL); 3274fe5b70cSMark Johnston } 3284fe5b70cSMark Johnston } 3294fe5b70cSMark Johnston 3304fe5b70cSMark Johnston curraddr = startaddr; 3314fe5b70cSMark Johnston mpfp = (mpfps_t)curraddr; 3324fe5b70cSMark Johnston mpt_build_mpfp(mpfp, MPTABLE_BASE); 3334fe5b70cSMark Johnston curraddr += sizeof(*mpfp); 3344fe5b70cSMark Johnston 3354fe5b70cSMark Johnston mpch = (mpcth_t)curraddr; 3364fe5b70cSMark Johnston mpt_build_mpch(mpch); 3374fe5b70cSMark Johnston curraddr += sizeof(*mpch); 3384fe5b70cSMark Johnston 3394fe5b70cSMark Johnston mpep = (proc_entry_ptr)curraddr; 3404fe5b70cSMark Johnston mpt_build_proc_entries(mpep, ncpu); 3414fe5b70cSMark Johnston curraddr += sizeof(*mpep) * ncpu; 3424fe5b70cSMark Johnston mpch->entry_count += ncpu; 3434fe5b70cSMark Johnston 3444fe5b70cSMark Johnston mpeb = (bus_entry_ptr) curraddr; 3454fe5b70cSMark Johnston mpt_build_bus_entries(mpeb); 3464fe5b70cSMark Johnston curraddr += sizeof(*mpeb) * MPE_NUM_BUSES; 3474fe5b70cSMark Johnston mpch->entry_count += MPE_NUM_BUSES; 3484fe5b70cSMark Johnston 3494fe5b70cSMark Johnston mpei = (io_apic_entry_ptr)curraddr; 3504fe5b70cSMark Johnston mpt_build_ioapic_entries(mpei, 0); 3514fe5b70cSMark Johnston curraddr += sizeof(*mpei); 3524fe5b70cSMark Johnston mpch->entry_count++; 3534fe5b70cSMark Johnston 3544fe5b70cSMark Johnston mpie = (int_entry_ptr) curraddr; 3554fe5b70cSMark Johnston ioints = mpt_count_ioint_entries(); 3564fe5b70cSMark Johnston mpt_build_ioint_entries(mpie, 0); 3574fe5b70cSMark Johnston curraddr += sizeof(*mpie) * ioints; 3584fe5b70cSMark Johnston mpch->entry_count += ioints; 3594fe5b70cSMark Johnston 3604fe5b70cSMark Johnston mpie = (int_entry_ptr)curraddr; 3614fe5b70cSMark Johnston mpt_build_localint_entries(mpie); 3624fe5b70cSMark Johnston curraddr += sizeof(*mpie) * MPEII_NUM_LOCAL_IRQ; 3634fe5b70cSMark Johnston mpch->entry_count += MPEII_NUM_LOCAL_IRQ; 3644fe5b70cSMark Johnston 3654fe5b70cSMark Johnston if (oem_tbl_start) { 3664fe5b70cSMark Johnston mpch->oem_table_pointer = curraddr - startaddr + MPTABLE_BASE; 3674fe5b70cSMark Johnston mpch->oem_table_size = oem_tbl_size; 3684fe5b70cSMark Johnston memcpy(curraddr, oem_tbl_start, oem_tbl_size); 3694fe5b70cSMark Johnston } 3704fe5b70cSMark Johnston 3714fe5b70cSMark Johnston mpch->base_table_length = curraddr - (char *)mpch; 3724fe5b70cSMark Johnston mpch->checksum = mpt_compute_checksum(mpch, mpch->base_table_length); 3734fe5b70cSMark Johnston 3744fe5b70cSMark Johnston return (0); 3754fe5b70cSMark Johnston } 376