Index: head/sys/i386/acpica/acpi_machdep.c =================================================================== --- head/sys/i386/acpica/acpi_machdep.c (revision 326259) +++ head/sys/i386/acpica/acpi_machdep.c (revision 326260) @@ -1,387 +1,389 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 Mitsuru IWASAKI * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include uint32_t acpi_resume_beep; SYSCTL_UINT(_debug_acpi, OID_AUTO, resume_beep, CTLFLAG_RWTUN, &acpi_resume_beep, 0, "Beep the PC speaker when resuming"); uint32_t acpi_reset_video; TUNABLE_INT("hw.acpi.reset_video", &acpi_reset_video); static int intr_model = ACPI_INTR_PIC; int acpi_machdep_init(device_t dev) { struct acpi_softc *sc; sc = device_get_softc(dev); acpi_apm_init(sc); acpi_install_wakeup_handler(sc); if (intr_model == ACPI_INTR_PIC) BUS_CONFIG_INTR(dev, AcpiGbl_FADT.SciInterrupt, INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW); else acpi_SetIntrModel(intr_model); SYSCTL_ADD_UINT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), OID_AUTO, "reset_video", CTLFLAG_RW, &acpi_reset_video, 0, "Call the VESA reset BIOS vector on the resume path"); return (0); } void acpi_SetDefaultIntrModel(int model) { intr_model = model; } /* Check BIOS date. If 1998 or older, disable ACPI. */ int acpi_machdep_quirks(int *quirks) { char *va; int year; /* BIOS address 0xffff5 contains the date in the format mm/dd/yy. */ va = pmap_mapbios(0xffff0, 16); sscanf(va + 11, "%2d", &year); pmap_unmapbios((vm_offset_t)va, 16); /* * Date must be >= 1/1/1999 or we don't trust ACPI. Note that this * check must be changed by my 114th birthday. */ if (year > 90 && year < 99) *quirks = ACPI_Q_BROKEN; return (0); } /* * Support for mapping ACPI tables during early boot. This abuses the * crashdump map because the kernel cannot allocate KVA in * pmap_mapbios() when this is used. This makes the following * assumptions about how we use this KVA: pages 0 and 1 are used to * map in the header of each table found via the RSDT or XSDT and * pages 2 to n are used to map in the RSDT or XSDT. This has to use * 2 pages for the table headers in case a header spans a page * boundary. * * XXX: We don't ensure the table fits in the available address space * in the crashdump map. */ /* * Map some memory using the crashdump map. 'offset' is an offset in * pages into the crashdump map to use for the start of the mapping. */ static void * table_map(vm_paddr_t pa, int offset, vm_offset_t length) { vm_offset_t va, off; void *data; off = pa & PAGE_MASK; length = round_page(length + off); pa = pa & PG_FRAME; va = (vm_offset_t)pmap_kenter_temporary(pa, offset) + (offset * PAGE_SIZE); data = (void *)(va + off); length -= PAGE_SIZE; while (length > 0) { va += PAGE_SIZE; pa += PAGE_SIZE; length -= PAGE_SIZE; pmap_kenter(va, pa); invlpg(va); } return (data); } /* Unmap memory previously mapped with table_map(). */ static void table_unmap(void *data, vm_offset_t length) { vm_offset_t va, off; va = (vm_offset_t)data; off = va & PAGE_MASK; length = round_page(length + off); va &= ~PAGE_MASK; while (length > 0) { pmap_kremove(va); invlpg(va); va += PAGE_SIZE; length -= PAGE_SIZE; } } /* * Map a table at a given offset into the crashdump map. It first * maps the header to determine the table length and then maps the * entire table. */ static void * map_table(vm_paddr_t pa, int offset, const char *sig) { ACPI_TABLE_HEADER *header; vm_offset_t length; void *table; header = table_map(pa, offset, sizeof(ACPI_TABLE_HEADER)); if (strncmp(header->Signature, sig, ACPI_NAME_SIZE) != 0) { table_unmap(header, sizeof(ACPI_TABLE_HEADER)); return (NULL); } length = header->Length; table_unmap(header, sizeof(ACPI_TABLE_HEADER)); table = table_map(pa, offset, length); if (ACPI_FAILURE(AcpiTbChecksum(table, length))) { if (bootverbose) printf("ACPI: Failed checksum for table %s\n", sig); #if (ACPI_CHECKSUM_ABORT) table_unmap(table, length); return (NULL); #endif } return (table); } /* * See if a given ACPI table is the requested table. Returns the * length of the able if it matches or zero on failure. */ static int probe_table(vm_paddr_t address, const char *sig) { ACPI_TABLE_HEADER *table; table = table_map(address, 0, sizeof(ACPI_TABLE_HEADER)); if (table == NULL) { if (bootverbose) printf("ACPI: Failed to map table at 0x%jx\n", (uintmax_t)address); return (0); } if (bootverbose) printf("Table '%.4s' at 0x%jx\n", table->Signature, (uintmax_t)address); if (strncmp(table->Signature, sig, ACPI_NAME_SIZE) != 0) { table_unmap(table, sizeof(ACPI_TABLE_HEADER)); return (0); } table_unmap(table, sizeof(ACPI_TABLE_HEADER)); return (1); } /* * Try to map a table at a given physical address previously returned * by acpi_find_table(). */ void * acpi_map_table(vm_paddr_t pa, const char *sig) { return (map_table(pa, 0, sig)); } /* Unmap a table previously mapped via acpi_map_table(). */ void acpi_unmap_table(void *table) { ACPI_TABLE_HEADER *header; header = (ACPI_TABLE_HEADER *)table; table_unmap(table, header->Length); } /* * Return the physical address of the requested table or zero if one * is not found. */ vm_paddr_t acpi_find_table(const char *sig) { ACPI_PHYSICAL_ADDRESS rsdp_ptr; ACPI_TABLE_RSDP *rsdp; ACPI_TABLE_RSDT *rsdt; ACPI_TABLE_XSDT *xsdt; ACPI_TABLE_HEADER *table; vm_paddr_t addr; int i, count; if (resource_disabled("acpi", 0)) return (0); /* * Map in the RSDP. Since ACPI uses AcpiOsMapMemory() which in turn * calls pmap_mapbios() to find the RSDP, we assume that we can use * pmap_mapbios() to map the RSDP. */ if ((rsdp_ptr = AcpiOsGetRootPointer()) == 0) return (0); rsdp = pmap_mapbios(rsdp_ptr, sizeof(ACPI_TABLE_RSDP)); if (rsdp == NULL) { if (bootverbose) printf("ACPI: Failed to map RSDP\n"); return (0); } /* * For ACPI >= 2.0, use the XSDT if it is available. * Otherwise, use the RSDT. We map the XSDT or RSDT at page 2 * in the crashdump area. Pages 0 and 1 are used to map in the * headers of candidate ACPI tables. */ addr = 0; if (rsdp->Revision >= 2 && rsdp->XsdtPhysicalAddress != 0) { /* * AcpiOsGetRootPointer only verifies the checksum for * the version 1.0 portion of the RSDP. Version 2.0 has * an additional checksum that we verify first. */ if (AcpiTbChecksum((UINT8 *)rsdp, ACPI_RSDP_XCHECKSUM_LENGTH)) { if (bootverbose) printf("ACPI: RSDP failed extended checksum\n"); return (0); } xsdt = map_table(rsdp->XsdtPhysicalAddress, 2, ACPI_SIG_XSDT); if (xsdt == NULL) { if (bootverbose) printf("ACPI: Failed to map XSDT\n"); return (0); } count = (xsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) / sizeof(UINT64); for (i = 0; i < count; i++) if (probe_table(xsdt->TableOffsetEntry[i], sig)) { addr = xsdt->TableOffsetEntry[i]; break; } acpi_unmap_table(xsdt); } else { rsdt = map_table(rsdp->RsdtPhysicalAddress, 2, ACPI_SIG_RSDT); if (rsdt == NULL) { if (bootverbose) printf("ACPI: Failed to map RSDT\n"); return (0); } count = (rsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) / sizeof(UINT32); for (i = 0; i < count; i++) if (probe_table(rsdt->TableOffsetEntry[i], sig)) { addr = rsdt->TableOffsetEntry[i]; break; } acpi_unmap_table(rsdt); } pmap_unmapbios((vm_offset_t)rsdp, sizeof(ACPI_TABLE_RSDP)); if (addr == 0) { if (bootverbose) printf("ACPI: No %s table found\n", sig); return (0); } if (bootverbose) printf("%s: Found table at 0x%jx\n", sig, (uintmax_t)addr); /* * Verify that we can map the full table and that its checksum is * correct, etc. */ table = map_table(addr, 0, sig); if (table == NULL) return (0); acpi_unmap_table(table); return (addr); } /* * ACPI nexus(4) driver. */ static int nexus_acpi_probe(device_t dev) { int error; error = acpi_identify(); if (error) return (error); return (BUS_PROBE_DEFAULT); } static int nexus_acpi_attach(device_t dev) { nexus_init_resources(); bus_generic_probe(dev); if (BUS_ADD_CHILD(dev, 10, "acpi", 0) == NULL) panic("failed to add acpi0 device"); return (bus_generic_attach(dev)); } static device_method_t nexus_acpi_methods[] = { /* Device interface */ DEVMETHOD(device_probe, nexus_acpi_probe), DEVMETHOD(device_attach, nexus_acpi_attach), { 0, 0 } }; DEFINE_CLASS_1(nexus, nexus_acpi_driver, nexus_acpi_methods, 1, nexus_driver); static devclass_t nexus_devclass; DRIVER_MODULE(nexus_acpi, root, nexus_acpi_driver, nexus_devclass, 0, 0); Index: head/sys/i386/bios/smapi.c =================================================================== --- head/sys/i386/bios/smapi.c (revision 326259) +++ head/sys/i386/bios/smapi.c (revision 326260) @@ -1,321 +1,323 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2003 Matthew N. Dodd * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include /* And all this for BIOS_PADDRTOVADDR() */ #include #include #include #include #include #include #define SMAPI_START 0xf0000 #define SMAPI_STEP 0x10 #define SMAPI_OFF 0 #define SMAPI_LEN 4 #define SMAPI_SIG "$SMB" #define RES2HDR(res) ((struct smapi_bios_header *)rman_get_virtual(res)) #define ADDR2HDR(addr) ((struct smapi_bios_header *)BIOS_PADDRTOVADDR(addr)) struct smapi_softc { struct cdev * cdev; device_t dev; struct resource * res; int rid; u_int32_t smapi32_entry; struct smapi_bios_header *header; }; extern u_long smapi32_offset; extern u_short smapi32_segment; devclass_t smapi_devclass; static d_ioctl_t smapi_ioctl; static struct cdevsw smapi_cdevsw = { .d_version = D_VERSION, .d_ioctl = smapi_ioctl, .d_name = "smapi", .d_flags = D_NEEDGIANT, }; static void smapi_identify(driver_t *, device_t); static int smapi_probe(device_t); static int smapi_attach(device_t); static int smapi_detach(device_t); static int smapi_modevent(module_t, int, void *); static int smapi_header_cksum(struct smapi_bios_header *); extern int smapi32(struct smapi_bios_parameter *, struct smapi_bios_parameter *); extern int smapi32_new(u_long, u_short, struct smapi_bios_parameter *, struct smapi_bios_parameter *); static int smapi_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td) { struct smapi_softc *sc; int error; error = 0; sc = devclass_get_softc(smapi_devclass, dev2unit(dev)); if (sc == NULL) { error = ENXIO; goto fail; } switch (cmd) { case SMAPIOGHEADER: bcopy((caddr_t)sc->header, data, sizeof(struct smapi_bios_header)); error = 0; break; case SMAPIOCGFUNCTION: smapi32_offset = sc->smapi32_entry; error = smapi32((struct smapi_bios_parameter *)data, (struct smapi_bios_parameter *)data); break; default: error = ENOTTY; } fail: return (error); } static int smapi_header_cksum (struct smapi_bios_header *header) { u_int8_t *ptr; u_int8_t cksum; int i; ptr = (u_int8_t *)header; cksum = 0; for (i = 0; i < header->length; i++) { cksum += ptr[i]; } return (cksum); } static void smapi_identify (driver_t *driver, device_t parent) { device_t child; u_int32_t addr; int length; int rid; if (!device_is_alive(parent)) return; addr = bios_sigsearch(SMAPI_START, SMAPI_SIG, SMAPI_LEN, SMAPI_STEP, SMAPI_OFF); if (addr != 0) { rid = 0; length = ADDR2HDR(addr)->length; child = BUS_ADD_CHILD(parent, 5, "smapi", -1); device_set_driver(child, driver); bus_set_resource(child, SYS_RES_MEMORY, rid, addr, length); device_set_desc(child, "SMAPI BIOS"); } return; } static int smapi_probe (device_t dev) { struct resource *res; int rid; int error; error = 0; rid = 0; res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (res == NULL) { device_printf(dev, "Unable to allocate memory resource.\n"); error = ENOMEM; goto bad; } if (smapi_header_cksum(RES2HDR(res))) { device_printf(dev, "SMAPI header checksum failed.\n"); error = ENXIO; goto bad; } bad: if (res) bus_release_resource(dev, SYS_RES_MEMORY, rid, res); return (error); } static int smapi_attach (device_t dev) { struct smapi_softc *sc; int error; sc = device_get_softc(dev); error = 0; sc->dev = dev; sc->rid = 0; sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid, RF_ACTIVE); if (sc->res == NULL) { device_printf(dev, "Unable to allocate memory resource.\n"); error = ENOMEM; goto bad; } sc->header = (struct smapi_bios_header *)rman_get_virtual(sc->res); sc->smapi32_entry = (u_int32_t)BIOS_PADDRTOVADDR( sc->header->prot32_segment + sc->header->prot32_offset); sc->cdev = make_dev(&smapi_cdevsw, device_get_unit(sc->dev), UID_ROOT, GID_WHEEL, 0600, "%s%d", smapi_cdevsw.d_name, device_get_unit(sc->dev)); device_printf(dev, "Version: %d.%02d, Length: %d, Checksum: 0x%02x\n", bcd2bin(sc->header->version_major), bcd2bin(sc->header->version_minor), sc->header->length, sc->header->checksum); device_printf(dev, "Information=0x%b\n", sc->header->information, "\020" "\001REAL_VM86" "\002PROTECTED_16" "\003PROTECTED_32"); if (bootverbose) { if (sc->header->information & SMAPI_REAL_VM86) device_printf(dev, "Real/VM86 mode: Segment 0x%04x, Offset 0x%04x\n", sc->header->real16_segment, sc->header->real16_offset); if (sc->header->information & SMAPI_PROT_16BIT) device_printf(dev, "16-bit Protected mode: Segment 0x%08x, Offset 0x%04x\n", sc->header->prot16_segment, sc->header->prot16_offset); if (sc->header->information & SMAPI_PROT_32BIT) device_printf(dev, "32-bit Protected mode: Segment 0x%08x, Offset 0x%08x\n", sc->header->prot32_segment, sc->header->prot32_offset); } return (0); bad: if (sc->res) bus_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->res); return (error); } static int smapi_detach (device_t dev) { struct smapi_softc *sc; sc = device_get_softc(dev); destroy_dev(sc->cdev); if (sc->res) bus_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->res); return (0); } static int smapi_modevent (module_t mod, int what, void *arg) { device_t * devs; int count; int i; switch (what) { case MOD_LOAD: break; case MOD_UNLOAD: devclass_get_devices(smapi_devclass, &devs, &count); for (i = 0; i < count; i++) { device_delete_child(device_get_parent(devs[i]), devs[i]); } free(devs, M_TEMP); break; default: break; } return (0); } static device_method_t smapi_methods[] = { /* Device interface */ DEVMETHOD(device_identify, smapi_identify), DEVMETHOD(device_probe, smapi_probe), DEVMETHOD(device_attach, smapi_attach), DEVMETHOD(device_detach, smapi_detach), { 0, 0 } }; static driver_t smapi_driver = { "smapi", smapi_methods, sizeof(struct smapi_softc), }; DRIVER_MODULE(smapi, nexus, smapi_driver, smapi_devclass, smapi_modevent, 0); MODULE_VERSION(smapi, 1); Index: head/sys/i386/i386/atomic.c =================================================================== --- head/sys/i386/i386/atomic.c (revision 326259) +++ head/sys/i386/i386/atomic.c (revision 326260) @@ -1,49 +1,51 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1999 Peter Jeremy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* This file creates publically callable functions to perform various * simple arithmetic on memory which is atomic in the presence of * interrupts and multiple processors. */ #include /* Firstly make atomic.h generate prototypes as it will for kernel modules */ #define KLD_MODULE #include #undef _MACHINE_ATOMIC_H_ /* forget we included it */ #undef KLD_MODULE #undef ATOMIC_ASM /* Make atomic.h generate public functions */ #define WANT_FUNCTIONS #define static #undef __inline #define __inline #include Index: head/sys/i386/i386/bios.c =================================================================== --- head/sys/i386/i386/bios.c (revision 326259) +++ head/sys/i386/i386/bios.c (revision 326260) @@ -1,768 +1,770 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1997 Michael Smith * Copyright (c) 1998 Jonathan Lemon * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Code for dealing with the BIOS in x86 PC systems. */ #include "opt_isa.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef DEV_ISA #include #include #include #endif #define BIOS_START 0xe0000 #define BIOS_SIZE 0x20000 /* exported lookup results */ struct bios32_SDentry PCIbios; static struct PnPBIOS_table *PnPBIOStable; static u_int bios32_SDCI; /* start fairly early */ static void bios32_init(void *junk); SYSINIT(bios32, SI_SUB_CPU, SI_ORDER_ANY, bios32_init, NULL); /* * bios32_init * * Locate various bios32 entities. */ static void bios32_init(void *junk) { u_long sigaddr; struct bios32_SDheader *sdh; struct PnPBIOS_table *pt; u_int8_t ck, *cv; int i; char *p; /* * BIOS32 Service Directory, PCI BIOS */ /* look for the signature */ if ((sigaddr = bios_sigsearch(0, "_32_", 4, 16, 0)) != 0) { /* get a virtual pointer to the structure */ sdh = (struct bios32_SDheader *)(uintptr_t)BIOS_PADDRTOVADDR(sigaddr); for (cv = (u_int8_t *)sdh, ck = 0, i = 0; i < (sdh->len * 16); i++) { ck += cv[i]; } /* If checksum is OK, enable use of the entrypoint */ if ((ck == 0) && (BIOS_START <= sdh->entry ) && (sdh->entry < (BIOS_START + BIOS_SIZE))) { bios32_SDCI = BIOS_PADDRTOVADDR(sdh->entry); if (bootverbose) { printf("bios32: Found BIOS32 Service Directory header at %p\n", sdh); printf("bios32: Entry = 0x%x (%x) Rev = %d Len = %d\n", sdh->entry, bios32_SDCI, sdh->revision, sdh->len); } /* Allow user override of PCI BIOS search */ if (((p = kern_getenv("machdep.bios.pci")) == NULL) || strcmp(p, "disable")) { /* See if there's a PCI BIOS entrypoint here */ PCIbios.ident.id = 0x49435024; /* PCI systems should have this */ if (!bios32_SDlookup(&PCIbios) && bootverbose) printf("pcibios: PCI BIOS entry at 0x%x+0x%x\n", PCIbios.base, PCIbios.entry); } if (p != NULL) freeenv(p); } else { printf("bios32: Bad BIOS32 Service Directory\n"); } } /* * PnP BIOS * * Allow user override of PnP BIOS search */ if ((((p = kern_getenv("machdep.bios.pnp")) == NULL) || strcmp(p, "disable")) && ((sigaddr = bios_sigsearch(0, "$PnP", 4, 16, 0)) != 0)) { /* get a virtual pointer to the structure */ pt = (struct PnPBIOS_table *)(uintptr_t)BIOS_PADDRTOVADDR(sigaddr); for (cv = (u_int8_t *)pt, ck = 0, i = 0; i < pt->len; i++) { ck += cv[i]; } /* If checksum is OK, enable use of the entrypoint */ if (ck == 0) { PnPBIOStable = pt; if (bootverbose) { printf("pnpbios: Found PnP BIOS data at %p\n", pt); printf("pnpbios: Entry = %x:%x Rev = %d.%d\n", pt->pmentrybase, pt->pmentryoffset, pt->version >> 4, pt->version & 0xf); if ((pt->control & 0x3) == 0x01) printf("pnpbios: Event flag at %x\n", pt->evflagaddr); if (pt->oemdevid != 0) printf("pnpbios: OEM ID %x\n", pt->oemdevid); } } else { printf("pnpbios: Bad PnP BIOS data checksum\n"); } } if (p != NULL) freeenv(p); if (bootverbose) { /* look for other know signatures */ printf("Other BIOS signatures found:\n"); } } /* * bios32_SDlookup * * Query the BIOS32 Service Directory for the service named in (ent), * returns nonzero if the lookup fails. The caller must fill in * (ent->ident), the remainder are populated on a successful lookup. */ int bios32_SDlookup(struct bios32_SDentry *ent) { struct bios_regs args; if (bios32_SDCI == 0) return (1); args.eax = ent->ident.id; /* set up arguments */ args.ebx = args.ecx = args.edx = 0; bios32(&args, bios32_SDCI, GSEL(GCODE_SEL, SEL_KPL)); if ((args.eax & 0xff) == 0) { /* success? */ ent->base = args.ebx; ent->len = args.ecx; ent->entry = args.edx; ent->ventry = BIOS_PADDRTOVADDR(ent->base + ent->entry); return (0); /* all OK */ } return (1); /* failed */ } /* * bios_sigsearch * * Search some or all of the BIOS region for a signature string. * * (start) Optional offset returned from this function * (for searching for multiple matches), or NULL * to start the search from the base of the BIOS. * Note that this will be a _physical_ address in * the range 0xe0000 - 0xfffff. * (sig) is a pointer to the byte(s) of the signature. * (siglen) number of bytes in the signature. * (paralen) signature paragraph (alignment) size. * (sigofs) offset of the signature within the paragraph. * * Returns the _physical_ address of the found signature, 0 if the * signature was not found. */ u_int32_t bios_sigsearch(u_int32_t start, u_char *sig, int siglen, int paralen, int sigofs) { u_char *sp, *end; /* compute the starting address */ if ((start >= BIOS_START) && (start <= (BIOS_START + BIOS_SIZE))) { sp = (char *)BIOS_PADDRTOVADDR(start); } else if (start == 0) { sp = (char *)BIOS_PADDRTOVADDR(BIOS_START); } else { return 0; /* bogus start address */ } /* compute the end address */ end = (u_char *)BIOS_PADDRTOVADDR(BIOS_START + BIOS_SIZE); /* loop searching */ while ((sp + sigofs + siglen) < end) { /* compare here */ if (!bcmp(sp + sigofs, sig, siglen)) { /* convert back to physical address */ return((u_int32_t)BIOS_VADDRTOPADDR(sp)); } sp += paralen; } return(0); } /* * do not staticize, used by bioscall.s */ union { struct { u_short offset; u_short segment; } vec16; struct { u_int offset; u_short segment; } vec32; } bioscall_vector; /* bios jump vector */ void set_bios_selectors(struct bios_segments *seg, int flags) { struct soft_segment_descriptor ssd = { 0, /* segment base address (overwritten) */ 0, /* length (overwritten) */ SDT_MEMERA, /* segment type (overwritten) */ 0, /* priority level */ 1, /* descriptor present */ 0, 0, 1, /* descriptor size (overwritten) */ 0 /* granularity == byte units */ }; union descriptor *p_gdt; #ifdef SMP p_gdt = &gdt[PCPU_GET(cpuid) * NGDT]; #else p_gdt = gdt; #endif ssd.ssd_base = seg->code32.base; ssd.ssd_limit = seg->code32.limit; ssdtosd(&ssd, &p_gdt[GBIOSCODE32_SEL].sd); ssd.ssd_def32 = 0; if (flags & BIOSCODE_FLAG) { ssd.ssd_base = seg->code16.base; ssd.ssd_limit = seg->code16.limit; ssdtosd(&ssd, &p_gdt[GBIOSCODE16_SEL].sd); } ssd.ssd_type = SDT_MEMRWA; if (flags & BIOSDATA_FLAG) { ssd.ssd_base = seg->data.base; ssd.ssd_limit = seg->data.limit; ssdtosd(&ssd, &p_gdt[GBIOSDATA_SEL].sd); } if (flags & BIOSUTIL_FLAG) { ssd.ssd_base = seg->util.base; ssd.ssd_limit = seg->util.limit; ssdtosd(&ssd, &p_gdt[GBIOSUTIL_SEL].sd); } if (flags & BIOSARGS_FLAG) { ssd.ssd_base = seg->args.base; ssd.ssd_limit = seg->args.limit; ssdtosd(&ssd, &p_gdt[GBIOSARGS_SEL].sd); } } extern int vm86pa; extern void bios16_jmp(void); /* * this routine is really greedy with selectors, and uses 5: * * 32-bit code selector: to return to kernel * 16-bit code selector: for running code * data selector: for 16-bit data * util selector: extra utility selector * args selector: to handle pointers * * the util selector is set from the util16 entry in bios16_args, if a * "U" specifier is seen. * * See for description of format specifiers */ int bios16(struct bios_args *args, char *fmt, ...) { char *p, *stack, *stack_top; va_list ap; int flags = BIOSCODE_FLAG | BIOSDATA_FLAG; u_int i, arg_start, arg_end; pt_entry_t *pte; pd_entry_t *ptd; arg_start = 0xffffffff; arg_end = 0; /* * Some BIOS entrypoints attempt to copy the largest-case * argument frame (in order to generalise handling for * different entry types). If our argument frame is * smaller than this, the BIOS will reach off the top of * our constructed stack segment. Pad the top of the stack * with some garbage to avoid this. */ stack = (caddr_t)PAGE_SIZE - 32; va_start(ap, fmt); for (p = fmt; p && *p; p++) { switch (*p) { case 'p': /* 32-bit pointer */ i = va_arg(ap, u_int); arg_start = min(arg_start, i); arg_end = max(arg_end, i); flags |= BIOSARGS_FLAG; stack -= 4; break; case 'i': /* 32-bit integer */ i = va_arg(ap, u_int); stack -= 4; break; case 'U': /* 16-bit selector */ flags |= BIOSUTIL_FLAG; /* FALLTHROUGH */ case 'D': /* 16-bit selector */ case 'C': /* 16-bit selector */ stack -= 2; break; case 's': /* 16-bit integer passed as an int */ i = va_arg(ap, int); stack -= 2; break; default: va_end(ap); return (EINVAL); } } va_end(ap); if (flags & BIOSARGS_FLAG) { if (arg_end - arg_start > ctob(16)) return (EACCES); args->seg.args.base = arg_start; args->seg.args.limit = 0xffff; } args->seg.code32.base = (u_int)&bios16_jmp & PG_FRAME; args->seg.code32.limit = 0xffff; ptd = (pd_entry_t *)rcr3(); #if defined(PAE) || defined(PAE_TABLES) if (ptd == IdlePDPT) #else if (ptd == IdlePTD) #endif { /* * no page table, so create one and install it. */ pte = (pt_entry_t *)malloc(PAGE_SIZE, M_TEMP, M_WAITOK); ptd = (pd_entry_t *)((u_int)IdlePTD + KERNBASE); *pte = (vm86pa - PAGE_SIZE) | PG_RW | PG_V; *ptd = vtophys(pte) | PG_RW | PG_V; } else { /* * this is a user-level page table */ pte = PTmap; *pte = (vm86pa - PAGE_SIZE) | PG_RW | PG_V; } pmap_invalidate_all(kernel_pmap); /* XXX insurance for now */ stack_top = stack; va_start(ap, fmt); for (p = fmt; p && *p; p++) { switch (*p) { case 'p': /* 32-bit pointer */ i = va_arg(ap, u_int); *(u_int *)stack = (i - arg_start) | (GSEL(GBIOSARGS_SEL, SEL_KPL) << 16); stack += 4; break; case 'i': /* 32-bit integer */ i = va_arg(ap, u_int); *(u_int *)stack = i; stack += 4; break; case 'U': /* 16-bit selector */ *(u_short *)stack = GSEL(GBIOSUTIL_SEL, SEL_KPL); stack += 2; break; case 'D': /* 16-bit selector */ *(u_short *)stack = GSEL(GBIOSDATA_SEL, SEL_KPL); stack += 2; break; case 'C': /* 16-bit selector */ *(u_short *)stack = GSEL(GBIOSCODE16_SEL, SEL_KPL); stack += 2; break; case 's': /* 16-bit integer passed as an int */ i = va_arg(ap, int); *(u_short *)stack = i; stack += 2; break; default: va_end(ap); return (EINVAL); } } va_end(ap); set_bios_selectors(&args->seg, flags); bioscall_vector.vec16.offset = (u_short)args->entry; bioscall_vector.vec16.segment = GSEL(GBIOSCODE16_SEL, SEL_KPL); i = bios16_call(&args->r, stack_top); if (pte == PTmap) { *pte = 0; /* remove entry */ /* * XXX only needs to be invlpg(0) but that doesn't work on the 386 */ pmap_invalidate_all(kernel_pmap); } else { *ptd = 0; /* remove page table */ /* * XXX only needs to be invlpg(0) but that doesn't work on the 386 */ pmap_invalidate_all(kernel_pmap); free(pte, M_TEMP); /* ... and free it */ } return (i); } int bios_oem_strings(struct bios_oem *oem, u_char *buffer, size_t maxlen) { size_t idx = 0; struct bios_oem_signature *sig; u_int from, to; u_char c, *s, *se, *str, *bios_str; size_t i, off, len, tot; if ( !oem || !buffer || maxlen<2 ) return(-1); sig = oem->signature; if (!sig) return(-2); from = oem->range.from; to = oem->range.to; if ( (to<=from) || (from(BIOS_START+BIOS_SIZE)) ) return(-3); while (sig->anchor != NULL) { str = sig->anchor; len = strlen(str); off = sig->offset; tot = sig->totlen; /* make sure offset doesn't go beyond bios area */ if ( (to+off)>(BIOS_START+BIOS_SIZE) || ((from+off) maxlen - 1) { printf("sys/i386/i386/bios.c: sig '%s' " "idx %d + tot %d = %d > maxlen-1 %d\n", str, idx, tot, idx+tot, maxlen-1); return(-5); } bios_str = NULL; s = (u_char *)BIOS_PADDRTOVADDR(from); se = (u_char *)BIOS_PADDRTOVADDR(to-len); for (; s 0x7E) ) c = ' '; if (idx == 0) { if (c != ' ') buffer[idx++] = c; } else if ( (c != ' ') || ((c == ' ') && (buffer[idx-1] != ' ')) ) buffer[idx++] = c; } } sig++; } /* remove a final trailing space */ if ( (idx > 1) && (buffer[idx-1] == ' ') ) idx--; buffer[idx] = '\0'; return (idx); } #ifdef DEV_ISA /* * PnP BIOS interface; enumerate devices only known to the system * BIOS and save information about them for later use. */ struct pnp_sysdev { u_int16_t size; u_int8_t handle; u_int32_t devid; u_int8_t type[3]; u_int16_t attrib; #define PNPATTR_NODISABLE (1<<0) /* can't be disabled */ #define PNPATTR_NOCONFIG (1<<1) /* can't be configured */ #define PNPATTR_OUTPUT (1<<2) /* can be primary output */ #define PNPATTR_INPUT (1<<3) /* can be primary input */ #define PNPATTR_BOOTABLE (1<<4) /* can be booted from */ #define PNPATTR_DOCK (1<<5) /* is a docking station */ #define PNPATTR_REMOVEABLE (1<<6) /* device is removeable */ #define PNPATTR_CONFIG_STATIC (0) #define PNPATTR_CONFIG_DYNAMIC (1) #define PNPATTR_CONFIG_DYNONLY (3) #define PNPATTR_CONFIG(a) (((a) >> 7) & 0x3) /* device-specific data comes here */ u_int8_t devdata[0]; } __packed; /* We have to cluster arguments within a 64k range for the bios16 call */ struct pnp_sysdevargs { u_int16_t next; struct pnp_sysdev node; }; /* * This function is called after the bus has assigned resource * locations for a logical device. */ static void pnpbios_set_config(void *arg, struct isa_config *config, int enable) { } /* * Quiz the PnP BIOS, build a list of PNP IDs and resource data. */ static void pnpbios_identify(driver_t *driver, device_t parent) { struct PnPBIOS_table *pt = PnPBIOStable; struct bios_args args; struct pnp_sysdev *pd; struct pnp_sysdevargs *pda; u_int16_t ndevs, bigdev; int error, currdev; u_int8_t *devnodebuf, tag; u_int32_t *devid, *compid; int idx, left; device_t dev; /* no PnP BIOS information */ if (pt == NULL) return; /* Check to see if ACPI is already active. */ dev = devclass_get_device(devclass_find("acpi"), 0); if (dev != NULL && device_is_attached(dev)) return; /* get count of PnP devices */ bzero(&args, sizeof(args)); args.seg.code16.base = BIOS_PADDRTOVADDR(pt->pmentrybase); args.seg.code16.limit = 0xffff; /* XXX ? */ args.seg.data.base = BIOS_PADDRTOVADDR(pt->pmdataseg); args.seg.data.limit = 0xffff; args.entry = pt->pmentryoffset; if ((error = bios16(&args, PNP_COUNT_DEVNODES, &ndevs, &bigdev)) || (args.r.eax & 0xff)) { printf("pnpbios: error %d/%x getting device count/size limit\n", error, args.r.eax); return; } ndevs &= 0xff; /* clear high byte garbage */ if (bootverbose) printf("pnpbios: %d devices, largest %d bytes\n", ndevs, bigdev); devnodebuf = malloc(bigdev + (sizeof(struct pnp_sysdevargs) - sizeof(struct pnp_sysdev)), M_DEVBUF, M_NOWAIT); if (devnodebuf == NULL) { printf("pnpbios: cannot allocate memory, bailing\n"); return; } pda = (struct pnp_sysdevargs *)devnodebuf; pd = &pda->node; for (currdev = 0, left = ndevs; (currdev != 0xff) && (left > 0); left--) { bzero(pd, bigdev); pda->next = currdev; /* get current configuration */ if ((error = bios16(&args, PNP_GET_DEVNODE, &pda->next, &pda->node, 1))) { printf("pnpbios: error %d making BIOS16 call\n", error); break; } if ((error = (args.r.eax & 0xff))) { if (bootverbose) printf("pnpbios: %s 0x%x fetching node %d\n", error & 0x80 ? "error" : "warning", error, currdev); if (error & 0x80) break; } currdev = pda->next; if (pd->size < sizeof(struct pnp_sysdev)) { printf("pnpbios: bogus system node data, aborting scan\n"); break; } /* * Ignore PICs so that we don't have to worry about the PICs * claiming IRQs to prevent their use. The PIC drivers * already ensure that invalid IRQs are not used. */ if (!strcmp(pnp_eisaformat(pd->devid), "PNP0000")) /* ISA PIC */ continue; if (!strcmp(pnp_eisaformat(pd->devid), "PNP0003")) /* APIC */ continue; /* Add the device and parse its resources */ dev = BUS_ADD_CHILD(parent, ISA_ORDER_PNPBIOS, NULL, -1); isa_set_vendorid(dev, pd->devid); isa_set_logicalid(dev, pd->devid); /* * It appears that some PnP BIOS doesn't allow us to re-enable * the embedded system device once it is disabled. We shall * mark all system device nodes as "cannot be disabled", regardless * of actual settings in the device attribute byte. * XXX isa_set_configattr(dev, ((pd->attrib & PNPATTR_NODISABLE) ? 0 : ISACFGATTR_CANDISABLE) | ((!(pd->attrib & PNPATTR_NOCONFIG) && PNPATTR_CONFIG(pd->attrib) != PNPATTR_CONFIG_STATIC) ? ISACFGATTR_DYNAMIC : 0)); */ isa_set_configattr(dev, (!(pd->attrib & PNPATTR_NOCONFIG) && PNPATTR_CONFIG(pd->attrib) != PNPATTR_CONFIG_STATIC) ? ISACFGATTR_DYNAMIC : 0); isa_set_pnpbios_handle(dev, pd->handle); ISA_SET_CONFIG_CALLBACK(parent, dev, pnpbios_set_config, 0); pnp_parse_resources(dev, &pd->devdata[0], pd->size - sizeof(struct pnp_sysdev), 0); if (!device_get_desc(dev)) device_set_desc_copy(dev, pnp_eisaformat(pd->devid)); /* Find device IDs */ devid = &pd->devid; compid = NULL; /* look for a compatible device ID too */ left = pd->size - sizeof(struct pnp_sysdev); idx = 0; while (idx < left) { tag = pd->devdata[idx++]; if (PNP_RES_TYPE(tag) == 0) { /* Small resource */ switch (PNP_SRES_NUM(tag)) { case PNP_TAG_COMPAT_DEVICE: compid = (u_int32_t *)(pd->devdata + idx); if (bootverbose) printf("pnpbios: node %d compat ID 0x%08x\n", pd->handle, *compid); /* FALLTHROUGH */ case PNP_TAG_END: idx = left; break; default: idx += PNP_SRES_LEN(tag); break; } } else /* Large resource, skip it */ idx += *(u_int16_t *)(pd->devdata + idx) + 2; } if (bootverbose) { printf("pnpbios: handle %d device ID %s (%08x)", pd->handle, pnp_eisaformat(*devid), *devid); if (compid != NULL) printf(" compat ID %s (%08x)", pnp_eisaformat(*compid), *compid); printf("\n"); } } } static device_method_t pnpbios_methods[] = { /* Device interface */ DEVMETHOD(device_identify, pnpbios_identify), { 0, 0 } }; static driver_t pnpbios_driver = { "pnpbios", pnpbios_methods, 1, /* no softc */ }; static devclass_t pnpbios_devclass; DRIVER_MODULE(pnpbios, isa, pnpbios_driver, pnpbios_devclass, 0, 0); #endif /* DEV_ISA */ Index: head/sys/i386/i386/elf_machdep.c =================================================================== --- head/sys/i386/i386/elf_machdep.c (revision 326259) +++ head/sys/i386/i386/elf_machdep.c (revision 326260) @@ -1,281 +1,283 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright 1996-1998 John D. Polstra. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_cpu.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct sysentvec elf32_freebsd_sysvec = { .sv_size = SYS_MAXSYSCALL, .sv_table = sysent, .sv_mask = 0, .sv_errsize = 0, .sv_errtbl = NULL, .sv_transtrap = NULL, .sv_fixup = __elfN(freebsd_fixup), .sv_sendsig = sendsig, .sv_sigcode = sigcode, .sv_szsigcode = &szsigcode, .sv_name = "FreeBSD ELF32", .sv_coredump = __elfN(coredump), .sv_imgact_try = NULL, .sv_minsigstksz = MINSIGSTKSZ, .sv_pagesize = PAGE_SIZE, .sv_minuser = VM_MIN_ADDRESS, .sv_maxuser = VM_MAXUSER_ADDRESS, .sv_usrstack = USRSTACK, .sv_psstrings = PS_STRINGS, .sv_stackprot = VM_PROT_ALL, .sv_copyout_strings = exec_copyout_strings, .sv_setregs = exec_setregs, .sv_fixlimit = NULL, .sv_maxssiz = NULL, .sv_flags = SV_ABI_FREEBSD | SV_IA32 | SV_ILP32 | SV_SHP | SV_TIMEKEEP, .sv_set_syscall_retval = cpu_set_syscall_retval, .sv_fetch_syscall_args = cpu_fetch_syscall_args, .sv_syscallnames = syscallnames, .sv_shared_page_base = SHAREDPAGE, .sv_shared_page_len = PAGE_SIZE, .sv_schedtail = NULL, .sv_thread_detach = NULL, .sv_trap = NULL, }; INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec); static Elf32_Brandinfo freebsd_brand_info = { .brand = ELFOSABI_FREEBSD, .machine = EM_386, .compat_3_brand = "FreeBSD", .emul_path = NULL, .interp_path = "/libexec/ld-elf.so.1", .sysvec = &elf32_freebsd_sysvec, .interp_newpath = NULL, .brand_note = &elf32_freebsd_brandnote, .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE }; SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_FIRST, (sysinit_cfunc_t) elf32_insert_brand_entry, &freebsd_brand_info); static Elf32_Brandinfo freebsd_brand_oinfo = { .brand = ELFOSABI_FREEBSD, .machine = EM_386, .compat_3_brand = "FreeBSD", .emul_path = NULL, .interp_path = "/usr/libexec/ld-elf.so.1", .sysvec = &elf32_freebsd_sysvec, .interp_newpath = NULL, .brand_note = &elf32_freebsd_brandnote, .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE }; SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY, (sysinit_cfunc_t) elf32_insert_brand_entry, &freebsd_brand_oinfo); static Elf32_Brandinfo kfreebsd_brand_info = { .brand = ELFOSABI_FREEBSD, .machine = EM_386, .compat_3_brand = "FreeBSD", .emul_path = NULL, .interp_path = "/lib/ld.so.1", .sysvec = &elf32_freebsd_sysvec, .interp_newpath = NULL, .brand_note = &elf32_kfreebsd_brandnote, .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE_MANDATORY }; SYSINIT(kelf32, SI_SUB_EXEC, SI_ORDER_ANY, (sysinit_cfunc_t) elf32_insert_brand_entry, &kfreebsd_brand_info); void elf32_dump_thread(struct thread *td, void *dst, size_t *off) { void *buf; size_t len; len = 0; if (use_xsave) { if (dst != NULL) { npxgetregs(td); len += elf32_populate_note(NT_X86_XSTATE, get_pcb_user_save_td(td), dst, cpu_max_ext_state_size, &buf); *(uint64_t *)((char *)buf + X86_XSTATE_XCR0_OFFSET) = xsave_mask; } else len += elf32_populate_note(NT_X86_XSTATE, NULL, NULL, cpu_max_ext_state_size, NULL); } *off = len; } /* Process one elf relocation with addend. */ static int elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, int local, elf_lookup_fn lookup) { Elf_Addr *where; Elf_Addr addr; Elf_Addr addend; Elf_Word rtype, symidx; const Elf_Rel *rel; const Elf_Rela *rela; int error; switch (type) { case ELF_RELOC_REL: rel = (const Elf_Rel *)data; where = (Elf_Addr *) (relocbase + rel->r_offset); addend = *where; rtype = ELF_R_TYPE(rel->r_info); symidx = ELF_R_SYM(rel->r_info); break; case ELF_RELOC_RELA: rela = (const Elf_Rela *)data; where = (Elf_Addr *) (relocbase + rela->r_offset); addend = rela->r_addend; rtype = ELF_R_TYPE(rela->r_info); symidx = ELF_R_SYM(rela->r_info); break; default: panic("unknown reloc type %d\n", type); } if (local) { if (rtype == R_386_RELATIVE) { /* A + B */ addr = elf_relocaddr(lf, relocbase + addend); if (*where != addr) *where = addr; } return (0); } switch (rtype) { case R_386_NONE: /* none */ break; case R_386_32: /* S + A */ error = lookup(lf, symidx, 1, &addr); if (error != 0) return -1; addr += addend; if (*where != addr) *where = addr; break; case R_386_PC32: /* S + A - P */ error = lookup(lf, symidx, 1, &addr); if (error != 0) return -1; addr += addend - (Elf_Addr)where; if (*where != addr) *where = addr; break; case R_386_COPY: /* none */ /* * There shouldn't be copy relocations in kernel * objects. */ printf("kldload: unexpected R_COPY relocation\n"); return -1; break; case R_386_GLOB_DAT: /* S */ error = lookup(lf, symidx, 1, &addr); if (error != 0) return -1; if (*where != addr) *where = addr; break; case R_386_RELATIVE: break; default: printf("kldload: unexpected relocation type %d\n", rtype); return -1; } return(0); } int elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, elf_lookup_fn lookup) { return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup)); } int elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, elf_lookup_fn lookup) { return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup)); } int elf_cpu_load_file(linker_file_t lf __unused) { return (0); } int elf_cpu_unload_file(linker_file_t lf __unused) { return (0); } Index: head/sys/i386/i386/gdb_machdep.c =================================================================== --- head/sys/i386/i386/gdb_machdep.c (revision 326259) +++ head/sys/i386/i386/gdb_machdep.c (revision 326260) @@ -1,117 +1,119 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2004 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include void * gdb_cpu_getreg(int regnum, size_t *regsz) { static uint32_t _kcodesel = GSEL(GCODE_SEL, SEL_KPL); static uint32_t _kdatasel = GSEL(GDATA_SEL, SEL_KPL); static uint32_t _kprivsel = GSEL(GPRIV_SEL, SEL_KPL); *regsz = gdb_cpu_regsz(regnum); if (kdb_thread == curthread) { switch (regnum) { case 0: return (&kdb_frame->tf_eax); case 1: return (&kdb_frame->tf_ecx); case 2: return (&kdb_frame->tf_edx); case 9: return (&kdb_frame->tf_eflags); case 10: return (&kdb_frame->tf_cs); case 12: return (&kdb_frame->tf_ds); case 13: return (&kdb_frame->tf_es); case 14: return (&kdb_frame->tf_fs); } } switch (regnum) { case 3: return (&kdb_thrctx->pcb_ebx); case 4: return (&kdb_thrctx->pcb_esp); case 5: return (&kdb_thrctx->pcb_ebp); case 6: return (&kdb_thrctx->pcb_esi); case 7: return (&kdb_thrctx->pcb_edi); case 8: return (&kdb_thrctx->pcb_eip); case 10: return (&_kcodesel); case 11: return (&_kdatasel); case 12: return (&_kdatasel); case 13: return (&_kdatasel); case 14: return (&_kprivsel); case 15: return (&kdb_thrctx->pcb_gs); } return (NULL); } void gdb_cpu_setreg(int regnum, void *val) { switch (regnum) { case GDB_REG_PC: kdb_thrctx->pcb_eip = *(register_t *)val; if (kdb_thread == curthread) kdb_frame->tf_eip = *(register_t *)val; } } int gdb_cpu_signal(int type, int code) { switch (type & ~T_USER) { case 0: return (SIGFPE); /* Divide by zero. */ case 1: return (SIGTRAP); /* Debug exception. */ case 3: return (SIGTRAP); /* Breakpoint. */ case 4: return (SIGURG); /* into instr. (overflow). */ case 5: return (SIGURG); /* bound instruction. */ case 6: return (SIGILL); /* Invalid opcode. */ case 7: return (SIGFPE); /* Coprocessor not present. */ case 8: return (SIGEMT); /* Double fault. */ case 9: return (SIGSEGV); /* Coprocessor segment overrun. */ case 10: return (SIGTRAP); /* Invalid TSS (also single-step). */ case 11: return (SIGSEGV); /* Segment not present. */ case 12: return (SIGSEGV); /* Stack exception. */ case 13: return (SIGSEGV); /* General protection. */ case 14: return (SIGSEGV); /* Page fault. */ case 16: return (SIGEMT); /* Coprocessor error. */ } return (SIGEMT); } Index: head/sys/i386/i386/geode.c =================================================================== --- head/sys/i386/i386/geode.c (revision 326259) +++ head/sys/i386/i386/geode.c (revision 326260) @@ -1,383 +1,385 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2003-2004 Poul-Henning Kamp * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include static struct bios_oem bios_soekris = { { 0xf0000, 0xf1000 }, { { "Soekris", 0, 8 }, /* Soekris Engineering. */ { "net4", 0, 8 }, /* net45xx */ { "comBIOS", 0, 54 }, /* comBIOS ver. 1.26a 20040819 ... */ { NULL, 0, 0 }, } }; static struct bios_oem bios_soekris_55 = { { 0xf0000, 0xf1000 }, { { "Soekris", 0, 8 }, /* Soekris Engineering. */ { "net5", 0, 8 }, /* net5xxx */ { "comBIOS", 0, 54 }, /* comBIOS ver. 1.26a 20040819 ... */ { NULL, 0, 0 }, } }; static struct bios_oem bios_pcengines = { { 0xf9000, 0xfa000 }, { { "PC Engines WRAP", 0, 28 }, /* PC Engines WRAP.1C v1.03 */ { "tinyBIOS", 0, 28 }, /* tinyBIOS V1.4a (C)1997-2003 */ { NULL, 0, 0 }, } }; static struct bios_oem bios_pcengines_55 = { { 0xf9000, 0xfa000 }, { { "PC Engines ALIX", 0, 28 }, /* PC Engines ALIX */ { "tinyBIOS", 0, 28 }, /* tinyBIOS V1.4a (C)1997-2005 */ { NULL, 0, 0 }, } }; static struct bios_oem bios_advantech = { { 0xfe000, 0xff000 }, { { "**** PCM-582", 5, 33 }, /* PCM-5823 BIOS V1.12 ... */ { "GXm-Cx5530", -11, 35 }, /* 06/07/2002-GXm-Cx5530... */ { NULL, 0, 0 }, } }; static unsigned cba; static unsigned gpio; static unsigned geode_counter; static struct cdev *led1, *led2, *led3; static int led1b, led2b, led3b; static void led_func(void *ptr, int onoff) { uint32_t u; int bit; bit = *(int *)ptr; if (bit < 0) { bit = -bit; onoff = !onoff; } u = inl(gpio + 4); if (onoff) u |= 1 << bit; else u &= ~(1 << bit); outl(gpio, u); } static void cs5536_led_func(void *ptr, int onoff) { int bit; uint16_t a; bit = *(int *)ptr; if (bit < 0) { bit = -bit; onoff = !onoff; } a = rdmsr(0x5140000c); if (bit >= 16) { a += 0x80; bit -= 16; } if (onoff) outl(a, 1 << bit); else outl(a, 1 << (bit + 16)); } static unsigned geode_get_timecount(struct timecounter *tc) { return (inl(geode_counter)); } static struct timecounter geode_timecounter = { geode_get_timecount, NULL, 0xffffffff, 27000000, "Geode", 1000 }; static uint64_t geode_cputicks(void) { unsigned c; static unsigned last; static uint64_t offset; c = inl(geode_counter); if (c < last) offset += (1LL << 32); last = c; return (offset | c); } /* * The GEODE watchdog runs from a 32kHz frequency. One period of that is * 31250 nanoseconds which we round down to 2^14 nanoseconds. The watchdog * consists of a power-of-two prescaler and a 16 bit counter, so the math * is quite simple. The max timeout is 14 + 16 + 13 = 2^43 nsec ~= 2h26m. */ static void geode_watchdog(void *foo __unused, u_int cmd, int *error) { u_int u, p, r; u = cmd & WD_INTERVAL; if (u >= 14 && u <= 43) { u -= 14; if (u > 16) { p = u - 16; u -= p; } else { p = 0; } if (u == 16) u = (1 << u) - 1; else u = 1 << u; r = inw(cba + 2) & 0xff00; outw(cba + 2, p | 0xf0 | r); outw(cba, u); *error = 0; } else { outw(cba, 0); } } /* * We run MFGPT0 off the 32kHz frequency and prescale by 16384 giving a * period of half a second. * Range becomes 2^30 (= 1 sec) to 2^44 (almost 5 hours) */ static void cs5536_watchdog(void *foo __unused, u_int cmd, int *error) { u_int u, p, s; uint16_t a; uint32_t m; a = rdmsr(0x5140000d); u = cmd & WD_INTERVAL; if (u >= 30 && u <= 44) { p = 1 << (u - 29); /* Set up MFGPT0, 32khz, prescaler 16k, C2 event */ outw(a + 6, 0x030e); /* set comparator 2 */ outw(a + 2, p); /* reset counter */ outw(a + 4, 0); /* Arm reset mechanism */ m = rdmsr(0x51400029); m |= (1 << 24); wrmsr(0x51400029, m); /* Start counter */ outw(a + 6, 0x8000); *error = 0; } else { /* * MFGPT_SETUP is write-once * Check if the counter has been setup */ s = inw(a + 6); if (s & (1 << 12)) { /* Stop and reset counter */ outw(a + 6, 0); outw(a + 4, 0); } } } /* * The Advantech PCM-582x watchdog expects 0x1 at I/O port 0x0443 * every 1.6 secs +/- 30%. Writing 0x0 disables the watchdog * NB: reading the I/O port enables the timer as well */ static void advantech_watchdog(void *foo __unused, u_int cmd, int *error) { u_int u; u = cmd & WD_INTERVAL; if (u > 0 && u <= WD_TO_1SEC) { outb(0x0443, 1); *error = 0; } else { outb(0x0443, 0); } } static int geode_probe(device_t self) { #define BIOS_OEM_MAXLEN 80 static u_char bios_oem[BIOS_OEM_MAXLEN] = "\0"; switch (pci_get_devid(self)) { case 0x0515100b: if (geode_counter == 0) { /* * The address of the CBA is written to this register * by the bios, see p161 in data sheet. */ cba = pci_read_config(self, 0x64, 4); if (bootverbose) printf("Geode CBA@ 0x%x\n", cba); geode_counter = cba + 0x08; outl(cba + 0x0d, 2); if (bootverbose) printf("Geode rev: %02x %02x\n", inb(cba + 0x3c), inb(cba + 0x3d)); tc_init(&geode_timecounter); EVENTHANDLER_REGISTER(watchdog_list, geode_watchdog, NULL, 0); set_cputicker(geode_cputicks, 27000000, 0); } break; case 0x0510100b: gpio = pci_read_config(self, PCIR_BAR(0), 4); gpio &= ~0x1f; if (bootverbose) printf("Geode GPIO@ = %x\n", gpio); if (bios_oem_strings(&bios_soekris, bios_oem, sizeof bios_oem) > 0 ) { led1b = 20; led1 = led_create(led_func, &led1b, "error"); } else if (bios_oem_strings(&bios_pcengines, bios_oem, sizeof bios_oem) > 0 ) { led1b = -2; led2b = -3; led3b = -18; led1 = led_create(led_func, &led1b, "led1"); led2 = led_create(led_func, &led2b, "led2"); led3 = led_create(led_func, &led3b, "led3"); /* * Turn on first LED so we don't make * people think their box just died. */ led_func(&led1b, 1); } if (*bios_oem) printf("Geode %s\n", bios_oem); break; case 0x01011078: if (bios_oem_strings(&bios_advantech, bios_oem, sizeof bios_oem) > 0 ) { printf("Geode %s\n", bios_oem); EVENTHANDLER_REGISTER(watchdog_list, advantech_watchdog, NULL, 0); } break; case 0x20801022: if (bios_oem_strings(&bios_soekris_55, bios_oem, sizeof bios_oem) > 0 ) { led1b = 6; led1 = led_create(cs5536_led_func, &led1b, "error"); } else if (bios_oem_strings(&bios_pcengines_55, bios_oem, sizeof bios_oem) > 0 ) { led1b = -6; led2b = -25; led3b = -27; led1 = led_create(cs5536_led_func, &led1b, "led1"); led2 = led_create(cs5536_led_func, &led2b, "led2"); led3 = led_create(cs5536_led_func, &led3b, "led3"); /* * Turn on first LED so we don't make * people think their box just died. */ cs5536_led_func(&led1b, 1); } if (*bios_oem) printf("Geode LX: %s\n", bios_oem); if (bootverbose) printf("MFGPT bar: %jx\n", rdmsr(0x5140000d)); EVENTHANDLER_REGISTER(watchdog_list, cs5536_watchdog, NULL, 0); break; } return (ENXIO); } static int geode_attach(device_t self) { return(ENODEV); } static device_method_t geode_methods[] = { /* Device interface */ DEVMETHOD(device_probe, geode_probe), DEVMETHOD(device_attach, geode_attach), DEVMETHOD(device_suspend, bus_generic_suspend), DEVMETHOD(device_resume, bus_generic_resume), DEVMETHOD(device_shutdown, bus_generic_shutdown), {0, 0} }; static driver_t geode_driver = { "geode", geode_methods, 0, }; static devclass_t geode_devclass; DRIVER_MODULE(geode, pci, geode_driver, geode_devclass, 0, 0); Index: head/sys/i386/i386/initcpu.c =================================================================== --- head/sys/i386/i386/initcpu.c (revision 326259) +++ head/sys/i386/i386/initcpu.c (revision 326260) @@ -1,983 +1,985 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) KATO Takenori, 1997, 1998. * * All rights reserved. Unpublished rights reserved under the copyright * laws of Japan. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer as * the first lines of this file unmodified. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_cpu.h" #include #include #include #include #include #include #include #include #include #ifdef I486_CPU static void init_5x86(void); static void init_bluelightning(void); static void init_486dlc(void); static void init_cy486dx(void); #ifdef CPU_I486_ON_386 static void init_i486_on_386(void); #endif static void init_6x86(void); #endif /* I486_CPU */ #if defined(I586_CPU) && defined(CPU_WT_ALLOC) static void enable_K5_wt_alloc(void); static void enable_K6_wt_alloc(void); static void enable_K6_2_wt_alloc(void); #endif #ifdef I686_CPU static void init_6x86MX(void); static void init_ppro(void); static void init_mendocino(void); #endif static int hw_instruction_sse; SYSCTL_INT(_hw, OID_AUTO, instruction_sse, CTLFLAG_RD, &hw_instruction_sse, 0, "SIMD/MMX2 instructions available in CPU"); /* * -1: automatic (default) * 0: keep enable CLFLUSH * 1: force disable CLFLUSH */ static int hw_clflush_disable = -1; u_int cyrix_did; /* Device ID of Cyrix CPU */ #ifdef I486_CPU /* * IBM Blue Lightning */ static void init_bluelightning(void) { register_t saveintr; saveintr = intr_disable(); load_cr0(rcr0() | CR0_CD | CR0_NW); invd(); #ifdef CPU_BLUELIGHTNING_FPU_OP_CACHE wrmsr(0x1000, 0x9c92LL); /* FP operand can be cacheable on Cyrix FPU */ #else wrmsr(0x1000, 0x1c92LL); /* Intel FPU */ #endif /* Enables 13MB and 0-640KB cache. */ wrmsr(0x1001, (0xd0LL << 32) | 0x3ff); #ifdef CPU_BLUELIGHTNING_3X wrmsr(0x1002, 0x04000000LL); /* Enables triple-clock mode. */ #else wrmsr(0x1002, 0x03000000LL); /* Enables double-clock mode. */ #endif /* Enable caching in CR0. */ load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); /* CD = 0 and NW = 0 */ invd(); intr_restore(saveintr); } /* * Cyrix 486SLC/DLC/SR/DR series */ static void init_486dlc(void) { register_t saveintr; u_char ccr0; saveintr = intr_disable(); invd(); ccr0 = read_cyrix_reg(CCR0); #ifndef CYRIX_CACHE_WORKS ccr0 |= CCR0_NC1 | CCR0_BARB; write_cyrix_reg(CCR0, ccr0); invd(); #else ccr0 &= ~CCR0_NC0; #ifndef CYRIX_CACHE_REALLY_WORKS ccr0 |= CCR0_NC1 | CCR0_BARB; #else ccr0 |= CCR0_NC1; #endif #ifdef CPU_DIRECT_MAPPED_CACHE ccr0 |= CCR0_CO; /* Direct mapped mode. */ #endif write_cyrix_reg(CCR0, ccr0); /* Clear non-cacheable region. */ write_cyrix_reg(NCR1+2, NCR_SIZE_0K); write_cyrix_reg(NCR2+2, NCR_SIZE_0K); write_cyrix_reg(NCR3+2, NCR_SIZE_0K); write_cyrix_reg(NCR4+2, NCR_SIZE_0K); write_cyrix_reg(0, 0); /* dummy write */ /* Enable caching in CR0. */ load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); /* CD = 0 and NW = 0 */ invd(); #endif /* !CYRIX_CACHE_WORKS */ intr_restore(saveintr); } /* * Cyrix 486S/DX series */ static void init_cy486dx(void) { register_t saveintr; u_char ccr2; saveintr = intr_disable(); invd(); ccr2 = read_cyrix_reg(CCR2); #ifdef CPU_SUSP_HLT ccr2 |= CCR2_SUSP_HLT; #endif write_cyrix_reg(CCR2, ccr2); intr_restore(saveintr); } /* * Cyrix 5x86 */ static void init_5x86(void) { register_t saveintr; u_char ccr2, ccr3, ccr4, pcr0; saveintr = intr_disable(); load_cr0(rcr0() | CR0_CD | CR0_NW); wbinvd(); (void)read_cyrix_reg(CCR3); /* dummy */ /* Initialize CCR2. */ ccr2 = read_cyrix_reg(CCR2); ccr2 |= CCR2_WB; #ifdef CPU_SUSP_HLT ccr2 |= CCR2_SUSP_HLT; #else ccr2 &= ~CCR2_SUSP_HLT; #endif ccr2 |= CCR2_WT1; write_cyrix_reg(CCR2, ccr2); /* Initialize CCR4. */ ccr3 = read_cyrix_reg(CCR3); write_cyrix_reg(CCR3, CCR3_MAPEN0); ccr4 = read_cyrix_reg(CCR4); ccr4 |= CCR4_DTE; ccr4 |= CCR4_MEM; #ifdef CPU_FASTER_5X86_FPU ccr4 |= CCR4_FASTFPE; #else ccr4 &= ~CCR4_FASTFPE; #endif ccr4 &= ~CCR4_IOMASK; /******************************************************************** * WARNING: The "BIOS Writers Guide" mentions that I/O recovery time * should be 0 for errata fix. ********************************************************************/ #ifdef CPU_IORT ccr4 |= CPU_IORT & CCR4_IOMASK; #endif write_cyrix_reg(CCR4, ccr4); /* Initialize PCR0. */ /**************************************************************** * WARNING: RSTK_EN and LOOP_EN could make your system unstable. * BTB_EN might make your system unstable. ****************************************************************/ pcr0 = read_cyrix_reg(PCR0); #ifdef CPU_RSTK_EN pcr0 |= PCR0_RSTK; #else pcr0 &= ~PCR0_RSTK; #endif #ifdef CPU_BTB_EN pcr0 |= PCR0_BTB; #else pcr0 &= ~PCR0_BTB; #endif #ifdef CPU_LOOP_EN pcr0 |= PCR0_LOOP; #else pcr0 &= ~PCR0_LOOP; #endif /**************************************************************** * WARNING: if you use a memory mapped I/O device, don't use * DISABLE_5X86_LSSER option, which may reorder memory mapped * I/O access. * IF YOUR MOTHERBOARD HAS PCI BUS, DON'T DISABLE LSSER. ****************************************************************/ #ifdef CPU_DISABLE_5X86_LSSER pcr0 &= ~PCR0_LSSER; #else pcr0 |= PCR0_LSSER; #endif write_cyrix_reg(PCR0, pcr0); /* Restore CCR3. */ write_cyrix_reg(CCR3, ccr3); (void)read_cyrix_reg(0x80); /* dummy */ /* Unlock NW bit in CR0. */ write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW); load_cr0((rcr0() & ~CR0_CD) | CR0_NW); /* CD = 0, NW = 1 */ /* Lock NW bit in CR0. */ write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW); intr_restore(saveintr); } #ifdef CPU_I486_ON_386 /* * There are i486 based upgrade products for i386 machines. * In this case, BIOS doesn't enable CPU cache. */ static void init_i486_on_386(void) { register_t saveintr; saveintr = intr_disable(); load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); /* CD = 0, NW = 0 */ intr_restore(saveintr); } #endif /* * Cyrix 6x86 * * XXX - What should I do here? Please let me know. */ static void init_6x86(void) { register_t saveintr; u_char ccr3, ccr4; saveintr = intr_disable(); load_cr0(rcr0() | CR0_CD | CR0_NW); wbinvd(); /* Initialize CCR0. */ write_cyrix_reg(CCR0, read_cyrix_reg(CCR0) | CCR0_NC1); /* Initialize CCR1. */ #ifdef CPU_CYRIX_NO_LOCK write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) | CCR1_NO_LOCK); #else write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) & ~CCR1_NO_LOCK); #endif /* Initialize CCR2. */ #ifdef CPU_SUSP_HLT write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_SUSP_HLT); #else write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_SUSP_HLT); #endif ccr3 = read_cyrix_reg(CCR3); write_cyrix_reg(CCR3, CCR3_MAPEN0); /* Initialize CCR4. */ ccr4 = read_cyrix_reg(CCR4); ccr4 |= CCR4_DTE; ccr4 &= ~CCR4_IOMASK; #ifdef CPU_IORT write_cyrix_reg(CCR4, ccr4 | (CPU_IORT & CCR4_IOMASK)); #else write_cyrix_reg(CCR4, ccr4 | 7); #endif /* Initialize CCR5. */ #ifdef CPU_WT_ALLOC write_cyrix_reg(CCR5, read_cyrix_reg(CCR5) | CCR5_WT_ALLOC); #endif /* Restore CCR3. */ write_cyrix_reg(CCR3, ccr3); /* Unlock NW bit in CR0. */ write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW); /* * Earlier revision of the 6x86 CPU could crash the system if * L1 cache is in write-back mode. */ if ((cyrix_did & 0xff00) > 0x1600) load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); /* CD = 0 and NW = 0 */ else { /* Revision 2.6 and lower. */ #ifdef CYRIX_CACHE_REALLY_WORKS load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); /* CD = 0 and NW = 0 */ #else load_cr0((rcr0() & ~CR0_CD) | CR0_NW); /* CD = 0 and NW = 1 */ #endif } /* Lock NW bit in CR0. */ write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW); intr_restore(saveintr); } #endif /* I486_CPU */ #ifdef I586_CPU /* * Rise mP6 */ static void init_rise(void) { /* * The CMPXCHG8B instruction is always available but hidden. */ cpu_feature |= CPUID_CX8; } /* * IDT WinChip C6/2/2A/2B/3 * * http://www.centtech.com/winchip_bios_writers_guide_v4_0.pdf */ static void init_winchip(void) { u_int regs[4]; uint64_t fcr; fcr = rdmsr(0x0107); /* * Set ECX8, DSMC, DTLOCK/EDCTLB, EMMX, and ERETSTK and clear DPDC. */ fcr |= (1 << 1) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 16); fcr &= ~(1ULL << 11); /* * Additionally, set EBRPRED, E2MMX and EAMD3D for WinChip 2 and 3. */ if (CPUID_TO_MODEL(cpu_id) >= 8) fcr |= (1 << 12) | (1 << 19) | (1 << 20); wrmsr(0x0107, fcr); do_cpuid(1, regs); cpu_feature = regs[3]; } #endif #ifdef I686_CPU /* * Cyrix 6x86MX (code-named M2) * * XXX - What should I do here? Please let me know. */ static void init_6x86MX(void) { register_t saveintr; u_char ccr3, ccr4; saveintr = intr_disable(); load_cr0(rcr0() | CR0_CD | CR0_NW); wbinvd(); /* Initialize CCR0. */ write_cyrix_reg(CCR0, read_cyrix_reg(CCR0) | CCR0_NC1); /* Initialize CCR1. */ #ifdef CPU_CYRIX_NO_LOCK write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) | CCR1_NO_LOCK); #else write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) & ~CCR1_NO_LOCK); #endif /* Initialize CCR2. */ #ifdef CPU_SUSP_HLT write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_SUSP_HLT); #else write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_SUSP_HLT); #endif ccr3 = read_cyrix_reg(CCR3); write_cyrix_reg(CCR3, CCR3_MAPEN0); /* Initialize CCR4. */ ccr4 = read_cyrix_reg(CCR4); ccr4 &= ~CCR4_IOMASK; #ifdef CPU_IORT write_cyrix_reg(CCR4, ccr4 | (CPU_IORT & CCR4_IOMASK)); #else write_cyrix_reg(CCR4, ccr4 | 7); #endif /* Initialize CCR5. */ #ifdef CPU_WT_ALLOC write_cyrix_reg(CCR5, read_cyrix_reg(CCR5) | CCR5_WT_ALLOC); #endif /* Restore CCR3. */ write_cyrix_reg(CCR3, ccr3); /* Unlock NW bit in CR0. */ write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW); load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); /* CD = 0 and NW = 0 */ /* Lock NW bit in CR0. */ write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW); intr_restore(saveintr); } static int ppro_apic_used = -1; static void init_ppro(void) { u_int64_t apicbase; /* * Local APIC should be disabled if it is not going to be used. */ if (ppro_apic_used != 1) { apicbase = rdmsr(MSR_APICBASE); apicbase &= ~APICBASE_ENABLED; wrmsr(MSR_APICBASE, apicbase); ppro_apic_used = 0; } } /* * If the local APIC is going to be used after being disabled above, * re-enable it and don't disable it in the future. */ void ppro_reenable_apic(void) { u_int64_t apicbase; if (ppro_apic_used == 0) { apicbase = rdmsr(MSR_APICBASE); apicbase |= APICBASE_ENABLED; wrmsr(MSR_APICBASE, apicbase); ppro_apic_used = 1; } } /* * Initialize BBL_CR_CTL3 (Control register 3: used to configure the * L2 cache). */ static void init_mendocino(void) { #ifdef CPU_PPRO2CELERON register_t saveintr; u_int64_t bbl_cr_ctl3; saveintr = intr_disable(); load_cr0(rcr0() | CR0_CD | CR0_NW); wbinvd(); bbl_cr_ctl3 = rdmsr(MSR_BBL_CR_CTL3); /* If the L2 cache is configured, do nothing. */ if (!(bbl_cr_ctl3 & 1)) { bbl_cr_ctl3 = 0x134052bLL; /* Set L2 Cache Latency (Default: 5). */ #ifdef CPU_CELERON_L2_LATENCY #if CPU_L2_LATENCY > 15 #error invalid CPU_L2_LATENCY. #endif bbl_cr_ctl3 |= CPU_L2_LATENCY << 1; #else bbl_cr_ctl3 |= 5 << 1; #endif wrmsr(MSR_BBL_CR_CTL3, bbl_cr_ctl3); } load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); intr_restore(saveintr); #endif /* CPU_PPRO2CELERON */ } /* * Initialize special VIA features */ static void init_via(void) { u_int regs[4], val; uint64_t fcr; /* * Explicitly enable CX8 and PGE on C3. * * http://www.via.com.tw/download/mainboards/6/13/VIA_C3_EBGA%20datasheet110.pdf */ if (CPUID_TO_MODEL(cpu_id) <= 9) fcr = (1 << 1) | (1 << 7); else fcr = 0; /* * Check extended CPUID for PadLock features. * * http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/programming_guide.pdf */ do_cpuid(0xc0000000, regs); if (regs[0] >= 0xc0000001) { do_cpuid(0xc0000001, regs); val = regs[3]; } else val = 0; /* Enable RNG if present. */ if ((val & VIA_CPUID_HAS_RNG) != 0) { via_feature_rng = VIA_HAS_RNG; wrmsr(0x110B, rdmsr(0x110B) | VIA_CPUID_DO_RNG); } /* Enable PadLock if present. */ if ((val & VIA_CPUID_HAS_ACE) != 0) via_feature_xcrypt |= VIA_HAS_AES; if ((val & VIA_CPUID_HAS_ACE2) != 0) via_feature_xcrypt |= VIA_HAS_AESCTR; if ((val & VIA_CPUID_HAS_PHE) != 0) via_feature_xcrypt |= VIA_HAS_SHA; if ((val & VIA_CPUID_HAS_PMM) != 0) via_feature_xcrypt |= VIA_HAS_MM; if (via_feature_xcrypt != 0) fcr |= 1 << 28; wrmsr(0x1107, rdmsr(0x1107) | fcr); } #endif /* I686_CPU */ #if defined(I586_CPU) || defined(I686_CPU) static void init_transmeta(void) { u_int regs[0]; /* Expose all hidden features. */ wrmsr(0x80860004, rdmsr(0x80860004) | ~0UL); do_cpuid(1, regs); cpu_feature = regs[3]; } #endif extern int elf32_nxstack; void initializecpu(void) { switch (cpu) { #ifdef I486_CPU case CPU_BLUE: init_bluelightning(); break; case CPU_486DLC: init_486dlc(); break; case CPU_CY486DX: init_cy486dx(); break; case CPU_M1SC: init_5x86(); break; #ifdef CPU_I486_ON_386 case CPU_486: init_i486_on_386(); break; #endif case CPU_M1: init_6x86(); break; #endif /* I486_CPU */ #ifdef I586_CPU case CPU_586: switch (cpu_vendor_id) { case CPU_VENDOR_AMD: #ifdef CPU_WT_ALLOC if (((cpu_id & 0x0f0) > 0) && ((cpu_id & 0x0f0) < 0x60) && ((cpu_id & 0x00f) > 3)) enable_K5_wt_alloc(); else if (((cpu_id & 0x0f0) > 0x80) || (((cpu_id & 0x0f0) == 0x80) && (cpu_id & 0x00f) > 0x07)) enable_K6_2_wt_alloc(); else if ((cpu_id & 0x0f0) > 0x50) enable_K6_wt_alloc(); #endif if ((cpu_id & 0xf0) == 0xa0) /* * Make sure the TSC runs through * suspension, otherwise we can't use * it as timecounter */ wrmsr(0x1900, rdmsr(0x1900) | 0x20ULL); break; case CPU_VENDOR_CENTAUR: init_winchip(); break; case CPU_VENDOR_TRANSMETA: init_transmeta(); break; case CPU_VENDOR_RISE: init_rise(); break; } break; #endif #ifdef I686_CPU case CPU_M2: init_6x86MX(); break; case CPU_686: switch (cpu_vendor_id) { case CPU_VENDOR_INTEL: switch (cpu_id & 0xff0) { case 0x610: init_ppro(); break; case 0x660: init_mendocino(); break; } break; #ifdef CPU_ATHLON_SSE_HACK case CPU_VENDOR_AMD: /* * Sometimes the BIOS doesn't enable SSE instructions. * According to AMD document 20734, the mobile * Duron, the (mobile) Athlon 4 and the Athlon MP * support SSE. These correspond to cpu_id 0x66X * or 0x67X. */ if ((cpu_feature & CPUID_XMM) == 0 && ((cpu_id & ~0xf) == 0x660 || (cpu_id & ~0xf) == 0x670 || (cpu_id & ~0xf) == 0x680)) { u_int regs[4]; wrmsr(MSR_HWCR, rdmsr(MSR_HWCR) & ~0x08000); do_cpuid(1, regs); cpu_feature = regs[3]; } break; #endif case CPU_VENDOR_CENTAUR: init_via(); break; case CPU_VENDOR_TRANSMETA: init_transmeta(); break; } break; #endif default: break; } if ((cpu_feature & CPUID_XMM) && (cpu_feature & CPUID_FXSR)) { load_cr4(rcr4() | CR4_FXSR | CR4_XMM); cpu_fxsr = hw_instruction_sse = 1; } #if defined(PAE) || defined(PAE_TABLES) if ((amd_feature & AMDID_NX) != 0) { uint64_t msr; msr = rdmsr(MSR_EFER) | EFER_NXE; wrmsr(MSR_EFER, msr); pg_nx = PG_NX; elf32_nxstack = 1; } #endif } void initializecpucache(void) { /* * CPUID with %eax = 1, %ebx returns * Bits 15-8: CLFLUSH line size * (Value * 8 = cache line size in bytes) */ if ((cpu_feature & CPUID_CLFSH) != 0) cpu_clflush_line_size = ((cpu_procinfo >> 8) & 0xff) * 8; /* * XXXKIB: (temporary) hack to work around traps generated * when CLFLUSHing APIC register window under virtualization * environments. These environments tend to disable the * CPUID_SS feature even though the native CPU supports it. */ TUNABLE_INT_FETCH("hw.clflush_disable", &hw_clflush_disable); if (vm_guest != VM_GUEST_NO && hw_clflush_disable == -1) { cpu_feature &= ~CPUID_CLFSH; cpu_stdext_feature &= ~CPUID_STDEXT_CLFLUSHOPT; } /* * The kernel's use of CLFLUSH{,OPT} can be disabled manually * by setting the hw.clflush_disable tunable. */ if (hw_clflush_disable == 1) { cpu_feature &= ~CPUID_CLFSH; cpu_stdext_feature &= ~CPUID_STDEXT_CLFLUSHOPT; } } #if defined(I586_CPU) && defined(CPU_WT_ALLOC) /* * Enable write allocate feature of AMD processors. * Following two functions require the Maxmem variable being set. */ static void enable_K5_wt_alloc(void) { u_int64_t msr; register_t saveintr; /* * Write allocate is supported only on models 1, 2, and 3, with * a stepping of 4 or greater. */ if (((cpu_id & 0xf0) > 0) && ((cpu_id & 0x0f) > 3)) { saveintr = intr_disable(); msr = rdmsr(0x83); /* HWCR */ wrmsr(0x83, msr & !(0x10)); /* * We have to tell the chip where the top of memory is, * since video cards could have frame bufferes there, * memory-mapped I/O could be there, etc. */ if(Maxmem > 0) msr = Maxmem / 16; else msr = 0; msr |= AMD_WT_ALLOC_TME | AMD_WT_ALLOC_FRE; /* * There is no way to know wheter 15-16M hole exists or not. * Therefore, we disable write allocate for this range. */ wrmsr(0x86, 0x0ff00f0); msr |= AMD_WT_ALLOC_PRE; wrmsr(0x85, msr); msr=rdmsr(0x83); wrmsr(0x83, msr|0x10); /* enable write allocate */ intr_restore(saveintr); } } static void enable_K6_wt_alloc(void) { quad_t size; u_int64_t whcr; register_t saveintr; saveintr = intr_disable(); wbinvd(); #ifdef CPU_DISABLE_CACHE /* * Certain K6-2 box becomes unstable when write allocation is * enabled. */ /* * The AMD-K6 processer provides the 64-bit Test Register 12(TR12), * but only the Cache Inhibit(CI) (bit 3 of TR12) is suppported. * All other bits in TR12 have no effect on the processer's operation. * The I/O Trap Restart function (bit 9 of TR12) is always enabled * on the AMD-K6. */ wrmsr(0x0000000e, (u_int64_t)0x0008); #endif /* Don't assume that memory size is aligned with 4M. */ if (Maxmem > 0) size = ((Maxmem >> 8) + 3) >> 2; else size = 0; /* Limit is 508M bytes. */ if (size > 0x7f) size = 0x7f; whcr = (rdmsr(0xc0000082) & ~(0x7fLL << 1)) | (size << 1); #if defined(NO_MEMORY_HOLE) if (whcr & (0x7fLL << 1)) whcr |= 0x0001LL; #else /* * There is no way to know wheter 15-16M hole exists or not. * Therefore, we disable write allocate for this range. */ whcr &= ~0x0001LL; #endif wrmsr(0x0c0000082, whcr); intr_restore(saveintr); } static void enable_K6_2_wt_alloc(void) { quad_t size; u_int64_t whcr; register_t saveintr; saveintr = intr_disable(); wbinvd(); #ifdef CPU_DISABLE_CACHE /* * Certain K6-2 box becomes unstable when write allocation is * enabled. */ /* * The AMD-K6 processer provides the 64-bit Test Register 12(TR12), * but only the Cache Inhibit(CI) (bit 3 of TR12) is suppported. * All other bits in TR12 have no effect on the processer's operation. * The I/O Trap Restart function (bit 9 of TR12) is always enabled * on the AMD-K6. */ wrmsr(0x0000000e, (u_int64_t)0x0008); #endif /* Don't assume that memory size is aligned with 4M. */ if (Maxmem > 0) size = ((Maxmem >> 8) + 3) >> 2; else size = 0; /* Limit is 4092M bytes. */ if (size > 0x3fff) size = 0x3ff; whcr = (rdmsr(0xc0000082) & ~(0x3ffLL << 22)) | (size << 22); #if defined(NO_MEMORY_HOLE) if (whcr & (0x3ffLL << 22)) whcr |= 1LL << 16; #else /* * There is no way to know wheter 15-16M hole exists or not. * Therefore, we disable write allocate for this range. */ whcr &= ~(1LL << 16); #endif wrmsr(0x0c0000082, whcr); intr_restore(saveintr); } #endif /* I585_CPU && CPU_WT_ALLOC */ #include "opt_ddb.h" #ifdef DDB #include DB_SHOW_COMMAND(cyrixreg, cyrixreg) { register_t saveintr; u_int cr0; u_char ccr1, ccr2, ccr3; u_char ccr0 = 0, ccr4 = 0, ccr5 = 0, pcr0 = 0; cr0 = rcr0(); if (cpu_vendor_id == CPU_VENDOR_CYRIX) { saveintr = intr_disable(); if ((cpu != CPU_M1SC) && (cpu != CPU_CY486DX)) { ccr0 = read_cyrix_reg(CCR0); } ccr1 = read_cyrix_reg(CCR1); ccr2 = read_cyrix_reg(CCR2); ccr3 = read_cyrix_reg(CCR3); if ((cpu == CPU_M1SC) || (cpu == CPU_M1) || (cpu == CPU_M2)) { write_cyrix_reg(CCR3, CCR3_MAPEN0); ccr4 = read_cyrix_reg(CCR4); if ((cpu == CPU_M1) || (cpu == CPU_M2)) ccr5 = read_cyrix_reg(CCR5); else pcr0 = read_cyrix_reg(PCR0); write_cyrix_reg(CCR3, ccr3); /* Restore CCR3. */ } intr_restore(saveintr); if ((cpu != CPU_M1SC) && (cpu != CPU_CY486DX)) printf("CCR0=%x, ", (u_int)ccr0); printf("CCR1=%x, CCR2=%x, CCR3=%x", (u_int)ccr1, (u_int)ccr2, (u_int)ccr3); if ((cpu == CPU_M1SC) || (cpu == CPU_M1) || (cpu == CPU_M2)) { printf(", CCR4=%x, ", (u_int)ccr4); if (cpu == CPU_M1SC) printf("PCR0=%x\n", pcr0); else printf("CCR5=%x\n", ccr5); } } printf("CR0=%x\n", cr0); } #endif /* DDB */ Index: head/sys/i386/i386/io.c =================================================================== --- head/sys/i386/i386/io.c (revision 326259) +++ head/sys/i386/i386/io.c (revision 326260) @@ -1,59 +1,61 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2004 Mark R V Murray * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include int iodev_open(struct thread *td) { td->td_frame->tf_eflags |= PSL_IOPL; return (0); } int iodev_close(struct thread *td) { td->td_frame->tf_eflags &= ~PSL_IOPL; return (0); } /* ARGSUSED */ int iodev_ioctl(u_long cmd __unused, caddr_t data __unused) { return (ENOIOCTL); } Index: head/sys/i386/i386/k6_mem.c =================================================================== --- head/sys/i386/i386/k6_mem.c (revision 326259) +++ head/sys/i386/i386/k6_mem.c (revision 326260) @@ -1,189 +1,191 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1999 Brian Fundakowski Feldman * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include /* * A K6-2 MTRR is defined as the highest 15 bits having the address, the next * 15 having the mask, the 1st bit being "write-combining" and the 0th bit * being "uncacheable". * * Address Mask WC UC * | XXXXXXXXXXXXXXX | XXXXXXXXXXXXXXX | X | X | * * There are two of these in the 64-bit UWCCR. */ #define UWCCR 0xc0000085 #define K6_REG_GET(reg, addr, mask, wc, uc) do { \ addr = (reg) & 0xfffe0000; \ mask = ((reg) & 0x1fffc) >> 2; \ wc = ((reg) & 0x2) >> 1; \ uc = (reg) & 0x1; \ } while (0) #define K6_REG_MAKE(addr, mask, wc, uc) \ ((addr) | ((mask) << 2) | ((wc) << 1) | uc) static void k6_mrinit(struct mem_range_softc *sc); static int k6_mrset(struct mem_range_softc *, struct mem_range_desc *, int *); static __inline int k6_mrmake(struct mem_range_desc *, u_int32_t *); static void k6_mem_drvinit(void *); static struct mem_range_ops k6_mrops = { k6_mrinit, k6_mrset, NULL, NULL }; static __inline int k6_mrmake(struct mem_range_desc *desc, u_int32_t *mtrr) { u_int32_t len = 0, wc, uc; int bit; if (desc->mr_base &~ 0xfffe0000) return (EINVAL); if (desc->mr_len < 131072 || !powerof2(desc->mr_len)) return (EINVAL); if (desc->mr_flags &~ (MDF_WRITECOMBINE|MDF_UNCACHEABLE|MDF_FORCE)) return (EOPNOTSUPP); for (bit = ffs(desc->mr_len >> 17) - 1; bit < 15; bit++) len |= 1 << bit; wc = (desc->mr_flags & MDF_WRITECOMBINE) ? 1 : 0; uc = (desc->mr_flags & MDF_UNCACHEABLE) ? 1 : 0; *mtrr = K6_REG_MAKE(desc->mr_base, len, wc, uc); return (0); } static void k6_mrinit(struct mem_range_softc *sc) { u_int64_t reg; u_int32_t addr, mask, wc, uc; int d; sc->mr_cap = 0; sc->mr_ndesc = 2; /* XXX (BFF) For now, we only have one msr for this */ sc->mr_desc = malloc(sc->mr_ndesc * sizeof(struct mem_range_desc), M_MEMDESC, M_NOWAIT | M_ZERO); if (sc->mr_desc == NULL) panic("k6_mrinit: malloc returns NULL"); reg = rdmsr(UWCCR); for (d = 0; d < sc->mr_ndesc; d++) { u_int32_t one = (reg & (0xffffffff << (32 * d))) >> (32 * d); K6_REG_GET(one, addr, mask, wc, uc); sc->mr_desc[d].mr_base = addr; sc->mr_desc[d].mr_len = ffs(mask) << 17; if (wc) sc->mr_desc[d].mr_flags |= MDF_WRITECOMBINE; if (uc) sc->mr_desc[d].mr_flags |= MDF_UNCACHEABLE; } printf("K6-family MTRR support enabled (%d registers)\n", sc->mr_ndesc); } static int k6_mrset(struct mem_range_softc *sc, struct mem_range_desc *desc, int *arg) { u_int64_t reg; u_int32_t mtrr; int error, d; switch (*arg) { case MEMRANGE_SET_UPDATE: error = k6_mrmake(desc, &mtrr); if (error) return (error); for (d = 0; d < sc->mr_ndesc; d++) { if (!sc->mr_desc[d].mr_len) { sc->mr_desc[d] = *desc; goto out; } if (sc->mr_desc[d].mr_base == desc->mr_base && sc->mr_desc[d].mr_len == desc->mr_len) return (EEXIST); } return (ENOSPC); case MEMRANGE_SET_REMOVE: mtrr = 0; for (d = 0; d < sc->mr_ndesc; d++) if (sc->mr_desc[d].mr_base == desc->mr_base && sc->mr_desc[d].mr_len == desc->mr_len) { bzero(&sc->mr_desc[d], sizeof(sc->mr_desc[d])); goto out; } return (ENOENT); default: return (EOPNOTSUPP); } out: disable_intr(); wbinvd(); reg = rdmsr(UWCCR); reg &= ~(0xffffffff << (32 * d)); reg |= mtrr << (32 * d); wrmsr(UWCCR, reg); wbinvd(); enable_intr(); return (0); } static void k6_mem_drvinit(void *unused) { if (cpu_vendor_id != CPU_VENDOR_AMD) return; if ((cpu_id & 0xf00) != 0x500) return; if ((cpu_id & 0xf0) < 0x80 || ((cpu_id & 0xf0) == 0x80 && (cpu_id & 0xf) <= 0x7)) return; mem_range_softc.mr_op = &k6_mrops; } SYSINIT(k6memdev, SI_SUB_DRIVERS, SI_ORDER_FIRST, k6_mem_drvinit, NULL); Index: head/sys/i386/i386/minidump_machdep.c =================================================================== --- head/sys/i386/i386/minidump_machdep.c (revision 326259) +++ head/sys/i386/i386/minidump_machdep.c (revision 326260) @@ -1,375 +1,377 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2006 Peter Wemm * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_watchdog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include CTASSERT(sizeof(struct kerneldumpheader) == 512); #define MD_ALIGN(x) (((off_t)(x) + PAGE_MASK) & ~PAGE_MASK) #define DEV_ALIGN(x) roundup2((off_t)(x), DEV_BSIZE) uint32_t *vm_page_dump; int vm_page_dump_size; static struct kerneldumpheader kdh; /* Handle chunked writes. */ static size_t fragsz; static void *dump_va; static uint64_t counter, progress; CTASSERT(sizeof(*vm_page_dump) == 4); static int is_dumpable(vm_paddr_t pa) { int i; for (i = 0; dump_avail[i] != 0 || dump_avail[i + 1] != 0; i += 2) { if (pa >= dump_avail[i] && pa < dump_avail[i + 1]) return (1); } return (0); } #define PG2MB(pgs) (((pgs) + (1 << 8) - 1) >> 8) static int blk_flush(struct dumperinfo *di) { int error; if (fragsz == 0) return (0); error = dump_append(di, dump_va, 0, fragsz); fragsz = 0; return (error); } static int blk_write(struct dumperinfo *di, char *ptr, vm_paddr_t pa, size_t sz) { size_t len; int error, i, c; u_int maxdumpsz; maxdumpsz = min(di->maxiosize, MAXDUMPPGS * PAGE_SIZE); if (maxdumpsz == 0) /* seatbelt */ maxdumpsz = PAGE_SIZE; error = 0; if ((sz % PAGE_SIZE) != 0) { printf("size not page aligned\n"); return (EINVAL); } if (ptr != NULL && pa != 0) { printf("cant have both va and pa!\n"); return (EINVAL); } if (pa != 0 && (((uintptr_t)ptr) % PAGE_SIZE) != 0) { printf("address not page aligned\n"); return (EINVAL); } if (ptr != NULL) { /* If we're doing a virtual dump, flush any pre-existing pa pages */ error = blk_flush(di); if (error) return (error); } while (sz) { len = maxdumpsz - fragsz; if (len > sz) len = sz; counter += len; progress -= len; if (counter >> 24) { printf(" %lld", PG2MB(progress >> PAGE_SHIFT)); counter &= (1<<24) - 1; } wdog_kern_pat(WD_LASTVAL); if (ptr) { error = dump_append(di, ptr, 0, len); if (error) return (error); ptr += len; sz -= len; } else { for (i = 0; i < len; i += PAGE_SIZE) dump_va = pmap_kenter_temporary(pa + i, (i + fragsz) >> PAGE_SHIFT); fragsz += len; pa += len; sz -= len; if (fragsz == maxdumpsz) { error = blk_flush(di); if (error) return (error); } } /* Check for user abort. */ c = cncheckc(); if (c == 0x03) return (ECANCELED); if (c != -1) printf(" (CTRL-C to abort) "); } return (0); } /* A fake page table page, to avoid having to handle both 4K and 2M pages */ static pt_entry_t fakept[NPTEPG]; int minidumpsys(struct dumperinfo *di) { uint64_t dumpsize; uint32_t ptesize; vm_offset_t va; int error; uint32_t bits; uint64_t pa; pd_entry_t *pd; pt_entry_t *pt; int i, j, k, bit; struct minidumphdr mdhdr; counter = 0; /* Walk page table pages, set bits in vm_page_dump */ ptesize = 0; for (va = KERNBASE; va < kernel_vm_end; va += NBPDR) { /* * We always write a page, even if it is zero. Each * page written corresponds to 2MB of space */ ptesize += PAGE_SIZE; pd = (pd_entry_t *)((uintptr_t)IdlePTD + KERNBASE); /* always mapped! */ j = va >> PDRSHIFT; if ((pd[j] & (PG_PS | PG_V)) == (PG_PS | PG_V)) { /* This is an entire 2M page. */ pa = pd[j] & PG_PS_FRAME; for (k = 0; k < NPTEPG; k++) { if (is_dumpable(pa)) dump_add_page(pa); pa += PAGE_SIZE; } continue; } if ((pd[j] & PG_V) == PG_V) { /* set bit for each valid page in this 2MB block */ pt = pmap_kenter_temporary(pd[j] & PG_FRAME, 0); for (k = 0; k < NPTEPG; k++) { if ((pt[k] & PG_V) == PG_V) { pa = pt[k] & PG_FRAME; if (is_dumpable(pa)) dump_add_page(pa); } } } else { /* nothing, we're going to dump a null page */ } } /* Calculate dump size. */ dumpsize = ptesize; dumpsize += round_page(msgbufp->msg_size); dumpsize += round_page(vm_page_dump_size); for (i = 0; i < vm_page_dump_size / sizeof(*vm_page_dump); i++) { bits = vm_page_dump[i]; while (bits) { bit = bsfl(bits); pa = (((uint64_t)i * sizeof(*vm_page_dump) * NBBY) + bit) * PAGE_SIZE; /* Clear out undumpable pages now if needed */ if (is_dumpable(pa)) { dumpsize += PAGE_SIZE; } else { dump_drop_page(pa); } bits &= ~(1ul << bit); } } dumpsize += PAGE_SIZE; progress = dumpsize; /* Initialize mdhdr */ bzero(&mdhdr, sizeof(mdhdr)); strcpy(mdhdr.magic, MINIDUMP_MAGIC); mdhdr.version = MINIDUMP_VERSION; mdhdr.msgbufsize = msgbufp->msg_size; mdhdr.bitmapsize = vm_page_dump_size; mdhdr.ptesize = ptesize; mdhdr.kernbase = KERNBASE; #if defined(PAE) || defined(PAE_TABLES) mdhdr.paemode = 1; #endif dump_init_header(di, &kdh, KERNELDUMPMAGIC, KERNELDUMP_I386_VERSION, dumpsize); printf("Physical memory: %ju MB\n", ptoa((uintmax_t)physmem) / 1048576); printf("Dumping %llu MB:", (long long)dumpsize >> 20); error = dump_start(di, &kdh); if (error != 0) goto fail; /* Dump my header */ bzero(&fakept, sizeof(fakept)); bcopy(&mdhdr, &fakept, sizeof(mdhdr)); error = blk_write(di, (char *)&fakept, 0, PAGE_SIZE); if (error) goto fail; /* Dump msgbuf up front */ error = blk_write(di, (char *)msgbufp->msg_ptr, 0, round_page(msgbufp->msg_size)); if (error) goto fail; /* Dump bitmap */ error = blk_write(di, (char *)vm_page_dump, 0, round_page(vm_page_dump_size)); if (error) goto fail; /* Dump kernel page table pages */ for (va = KERNBASE; va < kernel_vm_end; va += NBPDR) { /* We always write a page, even if it is zero */ pd = (pd_entry_t *)((uintptr_t)IdlePTD + KERNBASE); /* always mapped! */ j = va >> PDRSHIFT; if ((pd[j] & (PG_PS | PG_V)) == (PG_PS | PG_V)) { /* This is a single 2M block. Generate a fake PTP */ pa = pd[j] & PG_PS_FRAME; for (k = 0; k < NPTEPG; k++) { fakept[k] = (pa + (k * PAGE_SIZE)) | PG_V | PG_RW | PG_A | PG_M; } error = blk_write(di, (char *)&fakept, 0, PAGE_SIZE); if (error) goto fail; /* flush, in case we reuse fakept in the same block */ error = blk_flush(di); if (error) goto fail; continue; } if ((pd[j] & PG_V) == PG_V) { pa = pd[j] & PG_FRAME; error = blk_write(di, 0, pa, PAGE_SIZE); if (error) goto fail; } else { bzero(fakept, sizeof(fakept)); error = blk_write(di, (char *)&fakept, 0, PAGE_SIZE); if (error) goto fail; /* flush, in case we reuse fakept in the same block */ error = blk_flush(di); if (error) goto fail; } } /* Dump memory chunks */ /* XXX cluster it up and use blk_dump() */ for (i = 0; i < vm_page_dump_size / sizeof(*vm_page_dump); i++) { bits = vm_page_dump[i]; while (bits) { bit = bsfl(bits); pa = (((uint64_t)i * sizeof(*vm_page_dump) * NBBY) + bit) * PAGE_SIZE; error = blk_write(di, 0, pa, PAGE_SIZE); if (error) goto fail; bits &= ~(1ul << bit); } } error = blk_flush(di); if (error) goto fail; error = dump_finish(di, &kdh); if (error != 0) goto fail; printf("\nDump complete\n"); return (0); fail: if (error < 0) error = -error; if (error == ECANCELED) printf("\nDump aborted\n"); else if (error == E2BIG || error == ENOSPC) printf("\nDump failed. Partition too small.\n"); else printf("\n** DUMP FAILED (ERROR %d) **\n", error); return (error); } void dump_add_page(vm_paddr_t pa) { int idx, bit; pa >>= PAGE_SHIFT; idx = pa >> 5; /* 2^5 = 32 */ bit = pa & 31; atomic_set_int(&vm_page_dump[idx], 1ul << bit); } void dump_drop_page(vm_paddr_t pa) { int idx, bit; pa >>= PAGE_SHIFT; idx = pa >> 5; /* 2^5 = 32 */ bit = pa & 31; atomic_clear_int(&vm_page_dump[idx], 1ul << bit); } Index: head/sys/i386/i386/mp_machdep.c =================================================================== --- head/sys/i386/i386/mp_machdep.c (revision 326259) +++ head/sys/i386/i386/mp_machdep.c (revision 326260) @@ -1,469 +1,471 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1996, by Steve Passe * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. The name of the developer may NOT be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_apic.h" #include "opt_cpu.h" #include "opt_kstack_pages.h" #include "opt_pmap.h" #include "opt_sched.h" #include "opt_smp.h" #if !defined(lint) #if !defined(SMP) #error How did you get here? #endif #ifndef DEV_APIC #error The apic device is required for SMP, add "device apic" to your config file. #endif #endif /* not lint */ #include #include #include #include /* cngetc() */ #include #ifdef GPROF #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define WARMBOOT_TARGET 0 #define WARMBOOT_OFF (KERNBASE + 0x0467) #define WARMBOOT_SEG (KERNBASE + 0x0469) #define CMOS_REG (0x70) #define CMOS_DATA (0x71) #define BIOS_RESET (0x0f) #define BIOS_WARM (0x0a) /* * this code MUST be enabled here and in mpboot.s. * it follows the very early stages of AP boot by placing values in CMOS ram. * it NORMALLY will never be needed and thus the primitive method for enabling. * #define CHECK_POINTS */ #if defined(CHECK_POINTS) #define CHECK_READ(A) (outb(CMOS_REG, (A)), inb(CMOS_DATA)) #define CHECK_WRITE(A,D) (outb(CMOS_REG, (A)), outb(CMOS_DATA, (D))) #define CHECK_INIT(D); \ CHECK_WRITE(0x34, (D)); \ CHECK_WRITE(0x35, (D)); \ CHECK_WRITE(0x36, (D)); \ CHECK_WRITE(0x37, (D)); \ CHECK_WRITE(0x38, (D)); \ CHECK_WRITE(0x39, (D)); #define CHECK_PRINT(S); \ printf("%s: %d, %d, %d, %d, %d, %d\n", \ (S), \ CHECK_READ(0x34), \ CHECK_READ(0x35), \ CHECK_READ(0x36), \ CHECK_READ(0x37), \ CHECK_READ(0x38), \ CHECK_READ(0x39)); #else /* CHECK_POINTS */ #define CHECK_INIT(D) #define CHECK_PRINT(S) #define CHECK_WRITE(A, D) #endif /* CHECK_POINTS */ extern struct pcpu __pcpu[]; /* * Local data and functions. */ static void install_ap_tramp(void); static int start_all_aps(void); static int start_ap(int apic_id); static u_int boot_address; /* * Calculate usable address in base memory for AP trampoline code. */ u_int mp_bootaddress(u_int basemem) { boot_address = trunc_page(basemem); /* round down to 4k boundary */ if ((basemem - boot_address) < bootMP_size) boot_address -= PAGE_SIZE; /* not enough, lower by 4k */ return boot_address; } /* * Initialize the IPI handlers and start up the AP's. */ void cpu_mp_start(void) { int i; /* Initialize the logical ID to APIC ID table. */ for (i = 0; i < MAXCPU; i++) { cpu_apic_ids[i] = -1; cpu_ipi_pending[i] = 0; } /* Install an inter-CPU IPI for TLB invalidation */ setidt(IPI_INVLTLB, IDTVEC(invltlb), SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(IPI_INVLPG, IDTVEC(invlpg), SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(IPI_INVLRNG, IDTVEC(invlrng), SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); /* Install an inter-CPU IPI for cache invalidation. */ setidt(IPI_INVLCACHE, IDTVEC(invlcache), SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); /* Install an inter-CPU IPI for all-CPU rendezvous */ setidt(IPI_RENDEZVOUS, IDTVEC(rendezvous), SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); /* Install generic inter-CPU IPI handler */ setidt(IPI_BITMAP_VECTOR, IDTVEC(ipi_intr_bitmap_handler), SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); /* Install an inter-CPU IPI for CPU stop/restart */ setidt(IPI_STOP, IDTVEC(cpustop), SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); /* Install an inter-CPU IPI for CPU suspend/resume */ setidt(IPI_SUSPEND, IDTVEC(cpususpend), SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); /* Set boot_cpu_id if needed. */ if (boot_cpu_id == -1) { boot_cpu_id = PCPU_GET(apic_id); cpu_info[boot_cpu_id].cpu_bsp = 1; } else KASSERT(boot_cpu_id == PCPU_GET(apic_id), ("BSP's APIC ID doesn't match boot_cpu_id")); /* Probe logical/physical core configuration. */ topo_probe(); assign_cpu_ids(); /* Start each Application Processor */ start_all_aps(); set_interrupt_apic_ids(); } /* * AP CPU's call this to initialize themselves. */ void init_secondary(void) { struct pcpu *pc; vm_offset_t addr; int gsel_tss; int x, myid; u_int cr0; /* bootAP is set in start_ap() to our ID. */ myid = bootAP; /* Get per-cpu data */ pc = &__pcpu[myid]; /* prime data page for it to use */ pcpu_init(pc, myid, sizeof(struct pcpu)); dpcpu_init(dpcpu, myid); pc->pc_apic_id = cpu_apic_ids[myid]; pc->pc_prvspace = pc; pc->pc_curthread = 0; fix_cpuid(); gdt_segs[GPRIV_SEL].ssd_base = (int) pc; gdt_segs[GPROC0_SEL].ssd_base = (int) &pc->pc_common_tss; for (x = 0; x < NGDT; x++) { ssdtosd(&gdt_segs[x], &gdt[myid * NGDT + x].sd); } r_gdt.rd_limit = NGDT * sizeof(gdt[0]) - 1; r_gdt.rd_base = (int) &gdt[myid * NGDT]; lgdt(&r_gdt); /* does magic intra-segment return */ lidt(&r_idt); lldt(_default_ldt); PCPU_SET(currentldt, _default_ldt); gsel_tss = GSEL(GPROC0_SEL, SEL_KPL); gdt[myid * NGDT + GPROC0_SEL].sd.sd_type = SDT_SYS386TSS; PCPU_SET(common_tss.tss_esp0, 0); /* not used until after switch */ PCPU_SET(common_tss.tss_ss0, GSEL(GDATA_SEL, SEL_KPL)); PCPU_SET(common_tss.tss_ioopt, (sizeof (struct i386tss)) << 16); PCPU_SET(tss_gdt, &gdt[myid * NGDT + GPROC0_SEL].sd); PCPU_SET(common_tssd, *PCPU_GET(tss_gdt)); ltr(gsel_tss); PCPU_SET(fsgs_gdt, &gdt[myid * NGDT + GUFS_SEL].sd); /* * Set to a known state: * Set by mpboot.s: CR0_PG, CR0_PE * Set by cpu_setregs: CR0_NE, CR0_MP, CR0_TS, CR0_WP, CR0_AM */ cr0 = rcr0(); cr0 &= ~(CR0_CD | CR0_NW | CR0_EM); load_cr0(cr0); CHECK_WRITE(0x38, 5); /* signal our startup to the BSP. */ mp_naps++; CHECK_WRITE(0x39, 6); /* Spin until the BSP releases the AP's. */ while (atomic_load_acq_int(&aps_ready) == 0) ia32_pause(); /* BSP may have changed PTD while we were waiting */ invltlb(); for (addr = 0; addr < NKPT * NBPDR - 1; addr += PAGE_SIZE) invlpg(addr); #if defined(I586_CPU) && !defined(NO_F00F_HACK) lidt(&r_idt); #endif init_secondary_tail(); } /* * start each AP in our list */ /* Lowest 1MB is already mapped: don't touch*/ #define TMPMAP_START 1 static int start_all_aps(void) { u_char mpbiosreason; u_int32_t mpbioswarmvec; int apic_id, cpu, i; mtx_init(&ap_boot_mtx, "ap boot", NULL, MTX_SPIN); /* install the AP 1st level boot code */ install_ap_tramp(); /* save the current value of the warm-start vector */ mpbioswarmvec = *((u_int32_t *) WARMBOOT_OFF); outb(CMOS_REG, BIOS_RESET); mpbiosreason = inb(CMOS_DATA); /* set up temporary P==V mapping for AP boot */ /* XXX this is a hack, we should boot the AP on its own stack/PTD */ for (i = TMPMAP_START; i < NKPT; i++) PTD[i] = PTD[KPTDI + i]; invltlb(); /* start each AP */ for (cpu = 1; cpu < mp_ncpus; cpu++) { apic_id = cpu_apic_ids[cpu]; /* allocate and set up a boot stack data page */ bootstacks[cpu] = (char *)kmem_malloc(kernel_arena, kstack_pages * PAGE_SIZE, M_WAITOK | M_ZERO); dpcpu = (void *)kmem_malloc(kernel_arena, DPCPU_SIZE, M_WAITOK | M_ZERO); /* setup a vector to our boot code */ *((volatile u_short *) WARMBOOT_OFF) = WARMBOOT_TARGET; *((volatile u_short *) WARMBOOT_SEG) = (boot_address >> 4); outb(CMOS_REG, BIOS_RESET); outb(CMOS_DATA, BIOS_WARM); /* 'warm-start' */ bootSTK = (char *)bootstacks[cpu] + kstack_pages * PAGE_SIZE - 4; bootAP = cpu; /* attempt to start the Application Processor */ CHECK_INIT(99); /* setup checkpoints */ if (!start_ap(apic_id)) { printf("AP #%d (PHY# %d) failed!\n", cpu, apic_id); CHECK_PRINT("trace"); /* show checkpoints */ /* better panic as the AP may be running loose */ printf("panic y/n? [y] "); if (cngetc() != 'n') panic("bye-bye"); } CHECK_PRINT("trace"); /* show checkpoints */ CPU_SET(cpu, &all_cpus); /* record AP in CPU map */ } /* restore the warmstart vector */ *(u_int32_t *) WARMBOOT_OFF = mpbioswarmvec; outb(CMOS_REG, BIOS_RESET); outb(CMOS_DATA, mpbiosreason); /* Undo V==P hack from above */ for (i = TMPMAP_START; i < NKPT; i++) PTD[i] = 0; pmap_invalidate_range(kernel_pmap, 0, NKPT * NBPDR - 1); /* number of APs actually started */ return mp_naps; } /* * load the 1st level AP boot code into base memory. */ /* targets for relocation */ extern void bigJump(void); extern void bootCodeSeg(void); extern void bootDataSeg(void); extern void MPentry(void); extern u_int MP_GDT; extern u_int mp_gdtbase; static void install_ap_tramp(void) { int x; int size = *(int *) ((u_long) & bootMP_size); vm_offset_t va = boot_address + KERNBASE; u_char *src = (u_char *) ((u_long) bootMP); u_char *dst = (u_char *) va; u_int boot_base = (u_int) bootMP; u_int8_t *dst8; u_int16_t *dst16; u_int32_t *dst32; KASSERT (size <= PAGE_SIZE, ("'size' do not fit into PAGE_SIZE, as expected.")); pmap_kenter(va, boot_address); pmap_invalidate_page (kernel_pmap, va); for (x = 0; x < size; ++x) *dst++ = *src++; /* * modify addresses in code we just moved to basemem. unfortunately we * need fairly detailed info about mpboot.s for this to work. changes * to mpboot.s might require changes here. */ /* boot code is located in KERNEL space */ dst = (u_char *) va; /* modify the lgdt arg */ dst32 = (u_int32_t *) (dst + ((u_int) & mp_gdtbase - boot_base)); *dst32 = boot_address + ((u_int) & MP_GDT - boot_base); /* modify the ljmp target for MPentry() */ dst32 = (u_int32_t *) (dst + ((u_int) bigJump - boot_base) + 1); *dst32 = ((u_int) MPentry - KERNBASE); /* modify the target for boot code segment */ dst16 = (u_int16_t *) (dst + ((u_int) bootCodeSeg - boot_base)); dst8 = (u_int8_t *) (dst16 + 1); *dst16 = (u_int) boot_address & 0xffff; *dst8 = ((u_int) boot_address >> 16) & 0xff; /* modify the target for boot data segment */ dst16 = (u_int16_t *) (dst + ((u_int) bootDataSeg - boot_base)); dst8 = (u_int8_t *) (dst16 + 1); *dst16 = (u_int) boot_address & 0xffff; *dst8 = ((u_int) boot_address >> 16) & 0xff; } /* * This function starts the AP (application processor) identified * by the APIC ID 'physicalCpu'. It does quite a "song and dance" * to accomplish this. This is necessary because of the nuances * of the different hardware we might encounter. It isn't pretty, * but it seems to work. */ static int start_ap(int apic_id) { int vector, ms; int cpus; /* calculate the vector */ vector = (boot_address >> 12) & 0xff; /* used as a watchpoint to signal AP startup */ cpus = mp_naps; ipi_startup(apic_id, vector); /* Wait up to 5 seconds for it to start. */ for (ms = 0; ms < 5000; ms++) { if (mp_naps > cpus) return 1; /* return SUCCESS */ DELAY(1000); } return 0; /* return FAILURE */ } Index: head/sys/i386/i386/ptrace_machdep.c =================================================================== --- head/sys/i386/i386/ptrace_machdep.c (revision 326259) +++ head/sys/i386/i386/ptrace_machdep.c (revision 326260) @@ -1,196 +1,198 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2005 Doug Rabson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include __FBSDID("$FreeBSD$"); #include "opt_cpu.h" #include #include #include #include #include #include #include #include static int cpu_ptrace_xstate(struct thread *td, int req, void *addr, int data) { struct ptrace_xstate_info info; char *savefpu; int error; if (!use_xsave) return (EOPNOTSUPP); switch (req) { case PT_GETXSTATE_OLD: npxgetregs(td); savefpu = (char *)(get_pcb_user_save_td(td) + 1); error = copyout(savefpu, addr, cpu_max_ext_state_size - sizeof(union savefpu)); break; case PT_SETXSTATE_OLD: if (data > cpu_max_ext_state_size - sizeof(union savefpu)) { error = EINVAL; break; } savefpu = malloc(data, M_TEMP, M_WAITOK); error = copyin(addr, savefpu, data); if (error == 0) { npxgetregs(td); error = npxsetxstate(td, savefpu, data); } free(savefpu, M_TEMP); break; case PT_GETXSTATE_INFO: if (data != sizeof(info)) { error = EINVAL; break; } info.xsave_len = cpu_max_ext_state_size; info.xsave_mask = xsave_mask; error = copyout(&info, addr, data); break; case PT_GETXSTATE: npxgetregs(td); savefpu = (char *)(get_pcb_user_save_td(td)); error = copyout(savefpu, addr, cpu_max_ext_state_size); break; case PT_SETXSTATE: if (data < sizeof(union savefpu) || data > cpu_max_ext_state_size) { error = EINVAL; break; } savefpu = malloc(data, M_TEMP, M_WAITOK); error = copyin(addr, savefpu, data); if (error == 0) error = npxsetregs(td, (union savefpu *)savefpu, savefpu + sizeof(union savefpu), data - sizeof(union savefpu)); free(savefpu, M_TEMP); break; default: error = EINVAL; break; } return (error); } static int cpu_ptrace_xmm(struct thread *td, int req, void *addr, int data) { struct savexmm *fpstate; int error; if (!cpu_fxsr) return (EINVAL); fpstate = &get_pcb_user_save_td(td)->sv_xmm; switch (req) { case PT_GETXMMREGS: npxgetregs(td); error = copyout(fpstate, addr, sizeof(*fpstate)); break; case PT_SETXMMREGS: npxgetregs(td); error = copyin(addr, fpstate, sizeof(*fpstate)); fpstate->sv_env.en_mxcsr &= cpu_mxcsr_mask; break; case PT_GETXSTATE_OLD: case PT_SETXSTATE_OLD: case PT_GETXSTATE_INFO: case PT_GETXSTATE: case PT_SETXSTATE: error = cpu_ptrace_xstate(td, req, addr, data); break; default: return (EINVAL); } return (error); } int cpu_ptrace(struct thread *td, int req, void *addr, int data) { struct segment_descriptor *sdp, sd; register_t r; int error; switch (req) { case PT_GETXMMREGS: case PT_SETXMMREGS: case PT_GETXSTATE_OLD: case PT_SETXSTATE_OLD: case PT_GETXSTATE_INFO: case PT_GETXSTATE: case PT_SETXSTATE: error = cpu_ptrace_xmm(td, req, addr, data); break; case PT_GETFSBASE: case PT_GETGSBASE: sdp = req == PT_GETFSBASE ? &td->td_pcb->pcb_fsd : &td->td_pcb->pcb_gsd; r = sdp->sd_hibase << 24 | sdp->sd_lobase; error = copyout(&r, addr, sizeof(r)); break; case PT_SETFSBASE: case PT_SETGSBASE: error = copyin(addr, &r, sizeof(r)); if (error != 0) break; fill_based_sd(&sd, r); if (req == PT_SETFSBASE) { td->td_pcb->pcb_fsd = sd; td->td_frame->tf_fs = GSEL(GUFS_SEL, SEL_UPL); } else { td->td_pcb->pcb_gsd = sd; td->td_pcb->pcb_gs = GSEL(GUGS_SEL, SEL_UPL); } break; default: return (EINVAL); } return (error); } Index: head/sys/i386/i386/vm86.c =================================================================== --- head/sys/i386/i386/vm86.c (revision 326259) +++ head/sys/i386/i386/vm86.c (revision 326260) @@ -1,730 +1,732 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1997 Jonathan Lemon * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern int vm86pa; extern struct pcb *vm86pcb; static struct mtx vm86_lock; extern int vm86_bioscall(struct vm86frame *); extern void vm86_biosret(struct vm86frame *); void vm86_prepcall(struct vm86frame *); struct system_map { int type; vm_offset_t start; vm_offset_t end; }; #define HLT 0xf4 #define CLI 0xfa #define STI 0xfb #define PUSHF 0x9c #define POPF 0x9d #define INTn 0xcd #define IRET 0xcf #define CALLm 0xff #define OPERAND_SIZE_PREFIX 0x66 #define ADDRESS_SIZE_PREFIX 0x67 #define PUSH_MASK ~(PSL_VM | PSL_RF | PSL_I) #define POP_MASK ~(PSL_VIP | PSL_VIF | PSL_VM | PSL_RF | PSL_IOPL) static __inline caddr_t MAKE_ADDR(u_short sel, u_short off) { return ((caddr_t)((sel << 4) + off)); } static __inline void GET_VEC(u_int vec, u_short *sel, u_short *off) { *sel = vec >> 16; *off = vec & 0xffff; } static __inline u_int MAKE_VEC(u_short sel, u_short off) { return ((sel << 16) | off); } static __inline void PUSH(u_short x, struct vm86frame *vmf) { vmf->vmf_sp -= 2; suword16(MAKE_ADDR(vmf->vmf_ss, vmf->vmf_sp), x); } static __inline void PUSHL(u_int x, struct vm86frame *vmf) { vmf->vmf_sp -= 4; suword(MAKE_ADDR(vmf->vmf_ss, vmf->vmf_sp), x); } static __inline u_short POP(struct vm86frame *vmf) { u_short x = fuword16(MAKE_ADDR(vmf->vmf_ss, vmf->vmf_sp)); vmf->vmf_sp += 2; return (x); } static __inline u_int POPL(struct vm86frame *vmf) { u_int x = fuword(MAKE_ADDR(vmf->vmf_ss, vmf->vmf_sp)); vmf->vmf_sp += 4; return (x); } int vm86_emulate(vmf) struct vm86frame *vmf; { struct vm86_kernel *vm86; caddr_t addr; u_char i_byte; u_int temp_flags; int inc_ip = 1; int retcode = 0; /* * pcb_ext contains the address of the extension area, or zero if * the extension is not present. (This check should not be needed, * as we can't enter vm86 mode until we set up an extension area) */ if (curpcb->pcb_ext == 0) return (SIGBUS); vm86 = &curpcb->pcb_ext->ext_vm86; if (vmf->vmf_eflags & PSL_T) retcode = SIGTRAP; addr = MAKE_ADDR(vmf->vmf_cs, vmf->vmf_ip); i_byte = fubyte(addr); if (i_byte == ADDRESS_SIZE_PREFIX) { i_byte = fubyte(++addr); inc_ip++; } if (vm86->vm86_has_vme) { switch (i_byte) { case OPERAND_SIZE_PREFIX: i_byte = fubyte(++addr); inc_ip++; switch (i_byte) { case PUSHF: if (vmf->vmf_eflags & PSL_VIF) PUSHL((vmf->vmf_eflags & PUSH_MASK) | PSL_IOPL | PSL_I, vmf); else PUSHL((vmf->vmf_eflags & PUSH_MASK) | PSL_IOPL, vmf); vmf->vmf_ip += inc_ip; return (retcode); case POPF: temp_flags = POPL(vmf) & POP_MASK; vmf->vmf_eflags = (vmf->vmf_eflags & ~POP_MASK) | temp_flags | PSL_VM | PSL_I; vmf->vmf_ip += inc_ip; if (temp_flags & PSL_I) { vmf->vmf_eflags |= PSL_VIF; if (vmf->vmf_eflags & PSL_VIP) break; } else { vmf->vmf_eflags &= ~PSL_VIF; } return (retcode); } break; /* VME faults here if VIP is set, but does not set VIF. */ case STI: vmf->vmf_eflags |= PSL_VIF; vmf->vmf_ip += inc_ip; if ((vmf->vmf_eflags & PSL_VIP) == 0) { uprintf("fatal sti\n"); return (SIGKILL); } break; /* VME if no redirection support */ case INTn: break; /* VME if trying to set PSL_T, or PSL_I when VIP is set */ case POPF: temp_flags = POP(vmf) & POP_MASK; vmf->vmf_flags = (vmf->vmf_flags & ~POP_MASK) | temp_flags | PSL_VM | PSL_I; vmf->vmf_ip += inc_ip; if (temp_flags & PSL_I) { vmf->vmf_eflags |= PSL_VIF; if (vmf->vmf_eflags & PSL_VIP) break; } else { vmf->vmf_eflags &= ~PSL_VIF; } return (retcode); /* VME if trying to set PSL_T, or PSL_I when VIP is set */ case IRET: vmf->vmf_ip = POP(vmf); vmf->vmf_cs = POP(vmf); temp_flags = POP(vmf) & POP_MASK; vmf->vmf_flags = (vmf->vmf_flags & ~POP_MASK) | temp_flags | PSL_VM | PSL_I; if (temp_flags & PSL_I) { vmf->vmf_eflags |= PSL_VIF; if (vmf->vmf_eflags & PSL_VIP) break; } else { vmf->vmf_eflags &= ~PSL_VIF; } return (retcode); } return (SIGBUS); } switch (i_byte) { case OPERAND_SIZE_PREFIX: i_byte = fubyte(++addr); inc_ip++; switch (i_byte) { case PUSHF: if (vm86->vm86_eflags & PSL_VIF) PUSHL((vmf->vmf_flags & PUSH_MASK) | PSL_IOPL | PSL_I, vmf); else PUSHL((vmf->vmf_flags & PUSH_MASK) | PSL_IOPL, vmf); vmf->vmf_ip += inc_ip; return (retcode); case POPF: temp_flags = POPL(vmf) & POP_MASK; vmf->vmf_eflags = (vmf->vmf_eflags & ~POP_MASK) | temp_flags | PSL_VM | PSL_I; vmf->vmf_ip += inc_ip; if (temp_flags & PSL_I) { vm86->vm86_eflags |= PSL_VIF; if (vm86->vm86_eflags & PSL_VIP) break; } else { vm86->vm86_eflags &= ~PSL_VIF; } return (retcode); } return (SIGBUS); case CLI: vm86->vm86_eflags &= ~PSL_VIF; vmf->vmf_ip += inc_ip; return (retcode); case STI: /* if there is a pending interrupt, go to the emulator */ vm86->vm86_eflags |= PSL_VIF; vmf->vmf_ip += inc_ip; if (vm86->vm86_eflags & PSL_VIP) break; return (retcode); case PUSHF: if (vm86->vm86_eflags & PSL_VIF) PUSH((vmf->vmf_flags & PUSH_MASK) | PSL_IOPL | PSL_I, vmf); else PUSH((vmf->vmf_flags & PUSH_MASK) | PSL_IOPL, vmf); vmf->vmf_ip += inc_ip; return (retcode); case INTn: i_byte = fubyte(addr + 1); if ((vm86->vm86_intmap[i_byte >> 3] & (1 << (i_byte & 7))) != 0) break; if (vm86->vm86_eflags & PSL_VIF) PUSH((vmf->vmf_flags & PUSH_MASK) | PSL_IOPL | PSL_I, vmf); else PUSH((vmf->vmf_flags & PUSH_MASK) | PSL_IOPL, vmf); PUSH(vmf->vmf_cs, vmf); PUSH(vmf->vmf_ip + inc_ip + 1, vmf); /* increment IP */ GET_VEC(fuword((caddr_t)(i_byte * 4)), &vmf->vmf_cs, &vmf->vmf_ip); vmf->vmf_flags &= ~PSL_T; vm86->vm86_eflags &= ~PSL_VIF; return (retcode); case IRET: vmf->vmf_ip = POP(vmf); vmf->vmf_cs = POP(vmf); temp_flags = POP(vmf) & POP_MASK; vmf->vmf_flags = (vmf->vmf_flags & ~POP_MASK) | temp_flags | PSL_VM | PSL_I; if (temp_flags & PSL_I) { vm86->vm86_eflags |= PSL_VIF; if (vm86->vm86_eflags & PSL_VIP) break; } else { vm86->vm86_eflags &= ~PSL_VIF; } return (retcode); case POPF: temp_flags = POP(vmf) & POP_MASK; vmf->vmf_flags = (vmf->vmf_flags & ~POP_MASK) | temp_flags | PSL_VM | PSL_I; vmf->vmf_ip += inc_ip; if (temp_flags & PSL_I) { vm86->vm86_eflags |= PSL_VIF; if (vm86->vm86_eflags & PSL_VIP) break; } else { vm86->vm86_eflags &= ~PSL_VIF; } return (retcode); } return (SIGBUS); } #define PGTABLE_SIZE ((1024 + 64) * 1024 / PAGE_SIZE) #define INTMAP_SIZE 32 #define IOMAP_SIZE ctob(IOPAGES) #define TSS_SIZE \ (sizeof(struct pcb_ext) - sizeof(struct segment_descriptor) + \ INTMAP_SIZE + IOMAP_SIZE + 1) struct vm86_layout { pt_entry_t vml_pgtbl[PGTABLE_SIZE]; struct pcb vml_pcb; struct pcb_ext vml_ext; char vml_intmap[INTMAP_SIZE]; char vml_iomap[IOMAP_SIZE]; char vml_iomap_trailer; }; void vm86_initialize(void) { int i; u_int *addr; struct vm86_layout *vml = (struct vm86_layout *)vm86paddr; struct pcb *pcb; struct pcb_ext *ext; struct soft_segment_descriptor ssd = { 0, /* segment base address (overwritten) */ 0, /* length (overwritten) */ SDT_SYS386TSS, /* segment type */ 0, /* priority level */ 1, /* descriptor present */ 0, 0, 0, /* default 16 size */ 0 /* granularity */ }; /* * this should be a compile time error, but cpp doesn't grok sizeof(). */ if (sizeof(struct vm86_layout) > ctob(3)) panic("struct vm86_layout exceeds space allocated in locore.s"); /* * Below is the memory layout that we use for the vm86 region. * * +--------+ * | | * | | * | page 0 | * | | +--------+ * | | | stack | * +--------+ +--------+ <--------- vm86paddr * | | |Page Tbl| 1M + 64K = 272 entries = 1088 bytes * | | +--------+ * | | | PCB | size: ~240 bytes * | page 1 | |PCB Ext | size: ~140 bytes (includes TSS) * | | +--------+ * | | |int map | * | | +--------+ * +--------+ | | * | page 2 | | I/O | * +--------+ | bitmap | * | page 3 | | | * | | +--------+ * +--------+ */ /* * A rudimentary PCB must be installed, in order to get to the * PCB extension area. We use the PCB area as a scratchpad for * data storage, the layout of which is shown below. * * pcb_esi = new PTD entry 0 * pcb_ebp = pointer to frame on vm86 stack * pcb_esp = stack frame pointer at time of switch * pcb_ebx = va of vm86 page table * pcb_eip = argument pointer to initial call * pcb_spare[0] = saved TSS descriptor, word 0 * pcb_space[1] = saved TSS descriptor, word 1 */ #define new_ptd pcb_esi #define vm86_frame pcb_ebp #define pgtable_va pcb_ebx pcb = &vml->vml_pcb; ext = &vml->vml_ext; mtx_init(&vm86_lock, "vm86 lock", NULL, MTX_DEF); bzero(pcb, sizeof(struct pcb)); pcb->new_ptd = vm86pa | PG_V | PG_RW | PG_U; pcb->vm86_frame = vm86paddr - sizeof(struct vm86frame); pcb->pgtable_va = vm86paddr; pcb->pcb_flags = PCB_VM86CALL; pcb->pcb_ext = ext; bzero(ext, sizeof(struct pcb_ext)); ext->ext_tss.tss_esp0 = vm86paddr; ext->ext_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL); ext->ext_tss.tss_ioopt = ((u_int)vml->vml_iomap - (u_int)&ext->ext_tss) << 16; ext->ext_iomap = vml->vml_iomap; ext->ext_vm86.vm86_intmap = vml->vml_intmap; if (cpu_feature & CPUID_VME) ext->ext_vm86.vm86_has_vme = (rcr4() & CR4_VME ? 1 : 0); addr = (u_int *)ext->ext_vm86.vm86_intmap; for (i = 0; i < (INTMAP_SIZE + IOMAP_SIZE) / sizeof(u_int); i++) *addr++ = 0; vml->vml_iomap_trailer = 0xff; ssd.ssd_base = (u_int)&ext->ext_tss; ssd.ssd_limit = TSS_SIZE - 1; ssdtosd(&ssd, &ext->ext_tssd); vm86pcb = pcb; #if 0 /* * use whatever is leftover of the vm86 page layout as a * message buffer so we can capture early output. */ msgbufinit((vm_offset_t)vm86paddr + sizeof(struct vm86_layout), ctob(3) - sizeof(struct vm86_layout)); #endif } vm_offset_t vm86_getpage(struct vm86context *vmc, int pagenum) { int i; for (i = 0; i < vmc->npages; i++) if (vmc->pmap[i].pte_num == pagenum) return (vmc->pmap[i].kva); return (0); } vm_offset_t vm86_addpage(struct vm86context *vmc, int pagenum, vm_offset_t kva) { int i, flags = 0; for (i = 0; i < vmc->npages; i++) if (vmc->pmap[i].pte_num == pagenum) goto overlap; if (vmc->npages == VM86_PMAPSIZE) goto full; /* XXX grow map? */ if (kva == 0) { kva = (vm_offset_t)malloc(PAGE_SIZE, M_TEMP, M_WAITOK); flags = VMAP_MALLOC; } i = vmc->npages++; vmc->pmap[i].flags = flags; vmc->pmap[i].kva = kva; vmc->pmap[i].pte_num = pagenum; return (kva); overlap: panic("vm86_addpage: overlap"); full: panic("vm86_addpage: not enough room"); } /* * called from vm86_bioscall, while in vm86 address space, to finalize setup. */ void vm86_prepcall(struct vm86frame *vmf) { struct vm86_kernel *vm86; uint32_t *stack; uint8_t *code; code = (void *)0xa00; stack = (void *)(0x1000 - 2); /* keep aligned */ if ((vmf->vmf_trapno & PAGE_MASK) <= 0xff) { /* interrupt call requested */ code[0] = INTn; code[1] = vmf->vmf_trapno & 0xff; code[2] = HLT; vmf->vmf_ip = (uintptr_t)code; vmf->vmf_cs = 0; } else { code[0] = HLT; stack--; stack[0] = MAKE_VEC(0, (uintptr_t)code); } vmf->vmf_sp = (uintptr_t)stack; vmf->vmf_ss = 0; vmf->kernel_fs = vmf->kernel_es = vmf->kernel_ds = 0; vmf->vmf_eflags = PSL_VIF | PSL_VM | PSL_USER; vm86 = &curpcb->pcb_ext->ext_vm86; if (!vm86->vm86_has_vme) vm86->vm86_eflags = vmf->vmf_eflags; /* save VIF, VIP */ } /* * vm86 trap handler; determines whether routine succeeded or not. * Called while in vm86 space, returns to calling process. */ void vm86_trap(struct vm86frame *vmf) { caddr_t addr; /* "should not happen" */ if ((vmf->vmf_eflags & PSL_VM) == 0) panic("vm86_trap called, but not in vm86 mode"); addr = MAKE_ADDR(vmf->vmf_cs, vmf->vmf_ip); if (*(u_char *)addr == HLT) vmf->vmf_trapno = vmf->vmf_eflags & PSL_C; else vmf->vmf_trapno = vmf->vmf_trapno << 16; vm86_biosret(vmf); } int vm86_intcall(int intnum, struct vm86frame *vmf) { int retval; if (intnum < 0 || intnum > 0xff) return (EINVAL); vmf->vmf_trapno = intnum; mtx_lock(&vm86_lock); critical_enter(); retval = vm86_bioscall(vmf); critical_exit(); mtx_unlock(&vm86_lock); return (retval); } /* * struct vm86context contains the page table to use when making * vm86 calls. If intnum is a valid interrupt number (0-255), then * the "interrupt trampoline" will be used, otherwise we use the * caller's cs:ip routine. */ int vm86_datacall(intnum, vmf, vmc) int intnum; struct vm86frame *vmf; struct vm86context *vmc; { pt_entry_t *pte = (pt_entry_t *)vm86paddr; vm_paddr_t page; int i, entry, retval; mtx_lock(&vm86_lock); for (i = 0; i < vmc->npages; i++) { page = vtophys(vmc->pmap[i].kva & PG_FRAME); entry = vmc->pmap[i].pte_num; vmc->pmap[i].old_pte = pte[entry]; pte[entry] = page | PG_V | PG_RW | PG_U; pmap_invalidate_page(kernel_pmap, vmc->pmap[i].kva); } vmf->vmf_trapno = intnum; critical_enter(); retval = vm86_bioscall(vmf); critical_exit(); for (i = 0; i < vmc->npages; i++) { entry = vmc->pmap[i].pte_num; pte[entry] = vmc->pmap[i].old_pte; pmap_invalidate_page(kernel_pmap, vmc->pmap[i].kva); } mtx_unlock(&vm86_lock); return (retval); } vm_offset_t vm86_getaddr(struct vm86context *vmc, u_short sel, u_short off) { int i, page; vm_offset_t addr; addr = (vm_offset_t)MAKE_ADDR(sel, off); page = addr >> PAGE_SHIFT; for (i = 0; i < vmc->npages; i++) if (page == vmc->pmap[i].pte_num) return (vmc->pmap[i].kva + (addr & PAGE_MASK)); return (0); } int vm86_getptr(vmc, kva, sel, off) struct vm86context *vmc; vm_offset_t kva; u_short *sel; u_short *off; { int i; for (i = 0; i < vmc->npages; i++) if (kva >= vmc->pmap[i].kva && kva < vmc->pmap[i].kva + PAGE_SIZE) { *off = kva - vmc->pmap[i].kva; *sel = vmc->pmap[i].pte_num << 8; return (1); } return (0); } int vm86_sysarch(td, args) struct thread *td; char *args; { int error = 0; struct i386_vm86_args ua; struct vm86_kernel *vm86; if ((error = copyin(args, &ua, sizeof(struct i386_vm86_args))) != 0) return (error); if (td->td_pcb->pcb_ext == 0) if ((error = i386_extend_pcb(td)) != 0) return (error); vm86 = &td->td_pcb->pcb_ext->ext_vm86; switch (ua.sub_op) { case VM86_INIT: { struct vm86_init_args sa; if ((error = copyin(ua.sub_args, &sa, sizeof(sa))) != 0) return (error); if (cpu_feature & CPUID_VME) vm86->vm86_has_vme = (rcr4() & CR4_VME ? 1 : 0); else vm86->vm86_has_vme = 0; vm86->vm86_inited = 1; vm86->vm86_debug = sa.debug; bcopy(&sa.int_map, vm86->vm86_intmap, 32); } break; #if 0 case VM86_SET_VME: { struct vm86_vme_args sa; if ((cpu_feature & CPUID_VME) == 0) return (ENODEV); if (error = copyin(ua.sub_args, &sa, sizeof(sa))) return (error); if (sa.state) load_cr4(rcr4() | CR4_VME); else load_cr4(rcr4() & ~CR4_VME); } break; #endif case VM86_GET_VME: { struct vm86_vme_args sa; sa.state = (rcr4() & CR4_VME ? 1 : 0); error = copyout(&sa, ua.sub_args, sizeof(sa)); } break; case VM86_INTCALL: { struct vm86_intcall_args sa; if ((error = priv_check(td, PRIV_VM86_INTCALL))) return (error); if ((error = copyin(ua.sub_args, &sa, sizeof(sa)))) return (error); if ((error = vm86_intcall(sa.intnum, &sa.vmf))) return (error); error = copyout(&sa, ua.sub_args, sizeof(sa)); } break; default: error = EINVAL; } return (error); } Index: head/sys/i386/ibcs2/coff.h =================================================================== --- head/sys/i386/ibcs2/coff.h (revision 326259) +++ head/sys/i386/ibcs2/coff.h (revision 326260) @@ -1,106 +1,108 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1994 Sean Eric Fagan * Copyright (c) 1994 Søren Schmidt * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _COFF_H #define _COFF_H struct filehdr { unsigned short f_magic; /* magic number */ unsigned short f_nscns; /* # of sections */ long f_timdat; /* time stamp */ long f_symptr; /* symbol table offset */ long f_nsyms; /* # of symbols */ unsigned short f_opthdr; /* size of system header */ unsigned short f_flags; /* flags, see below */ }; enum filehdr_flags { F_RELFLG = 0x01, /* relocs have been stripped */ F_EXEC = 0x02, /* executable file (or shlib) */ F_LNNO = 0x04, /* line numbers have been stripped */ F_LSYMS = 0x08, /* symbols have been stripped */ F_SWABD = 0x40, /* swabbed byte names */ F_AR16WR = 0x80, /* 16-bit, byte reversed words */ F_AR32WR = 0x100 /* 32-bit, byte reversed words */ }; struct aouthdr { short magic; /* magic number -- see below */ short vstamp; /* artifacts from a by-gone day */ long tsize; /* */ long dsize; /* */ long bsize; /* */ long entry; /* Entry point -- offset into file */ long tstart; /* artifacts from a by-gone day */ long dstart; /* */ }; #define I386_COFF 0x14c #define COFF_OMAGIC 0407 /* impure format */ #define COFF_NMAGIC 0410 /* read-only text */ #define COFF_ZMAGIC 0413 /* pagable from disk */ #define COFF_SHLIB 0443 /* a shared library */ struct scnhdr { char s_name[8]; /* name of section (e.g., ".text") */ long s_paddr; /* physical addr, used for standalone */ long s_vaddr; /* virtual address */ long s_size; /* size of section */ long s_scnptr; /* file offset of section */ long s_relptr; /* points to relocs for section */ long s_lnnoptr; /* points to line numbers for section */ unsigned short s_nreloc; /* # of relocs */ unsigned short s_nlnno; /* # of line no's */ long s_flags; /* section flags -- see below */ }; enum scnhdr_flags { STYP_REG = 0x00, /* regular (alloc'ed, reloc'ed, loaded) */ STYP_DSECT = 0x01, /* dummy (reloc'd) */ STYP_NOLOAD = 0x02, /* no-load (reloc'd) */ STYP_GROUP = 0x04, /* grouped */ STYP_PAD = 0x08, /* padding (loaded) */ STYP_COPY = 0x10, /* ??? */ STYP_TEXT = 0x20, /* text */ STYP_DATA = 0x40, /* data */ STYP_BSS = 0x80, /* bss */ STYP_INFO = 0x200, /* comment (!loaded, !alloc'ed, !reloc'd) */ STYP_OVER = 0x400, /* overlay (!allocated, reloc'd, !loaded) */ STYP_LIB = 0x800 /* lists shared library files */ }; struct slhdr { long entry_length; long path_index; char *shlib_name; }; #endif /* _COFF_H */ Index: head/sys/i386/ibcs2/ibcs2_dirent.h =================================================================== --- head/sys/i386/ibcs2/ibcs2_dirent.h (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_dirent.h (revision 326260) @@ -1,58 +1,60 @@ /* $NetBSD: ibcs2_dirent.h,v 1.2 1994/10/26 02:52:51 cgd Exp $ */ /* $FreeBSD$ */ /*- + * SPDX-License-Identifier: BSD-4-Clause + * * Copyright (c) 1994 Scott Bartram * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Scott Bartram. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _IBCS2_DIRENT_H #define _IBCS2_DIRENT_H 1 #include #define IBCS2_MAXNAMLEN 512 #define IBCS2_DIRBUF 1048 typedef struct { int dd_fd; int dd_loc; int dd_size; char *dd_buf; } IBCS2_DIR; struct ibcs2_dirent { ibcs2_ino_t d_ino; short d_pad; ibcs2_off_t d_off; u_short d_reclen; char d_name[1]; }; #endif /* _IBCS2_DIRENT_H */ Index: head/sys/i386/ibcs2/ibcs2_errno.c =================================================================== --- head/sys/i386/ibcs2/ibcs2_errno.c (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_errno.c (revision 326260) @@ -1,127 +1,129 @@ /*- * ibcs2_errno.c + * SPDX-License-Identifier: BSD-4-Clause + * * Copyright (c) 1995 Scott Bartram * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Scott Bartram. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include int bsd_to_ibcs2_errno[ELAST + 1] = { 0, /* 0 */ IBCS2_EPERM, /* 1 */ IBCS2_ENOENT, /* 2 */ IBCS2_ESRCH, /* 3 */ IBCS2_EINTR, /* 4 */ IBCS2_EIO, /* 5 */ IBCS2_ENXIO, /* 6 */ IBCS2_E2BIG, /* 7 */ IBCS2_ENOEXEC, /* 8 */ IBCS2_EBADF, /* 9 */ IBCS2_ECHILD, /* 10 */ IBCS2_EDEADLK, /* 11 */ IBCS2_ENOMEM, /* 12 */ IBCS2_EACCES, /* 13 */ IBCS2_EFAULT, /* 14 */ IBCS2_ENOTBLK, /* 15 */ IBCS2_EBUSY, /* 16 */ IBCS2_EEXIST, /* 17 */ IBCS2_EXDEV, /* 18 */ IBCS2_ENODEV, /* 19 */ IBCS2_ENOTDIR, /* 20 */ IBCS2_EISDIR, /* 21 */ IBCS2_EINVAL, /* 22 */ IBCS2_ENFILE, /* 23 */ IBCS2_EMFILE, /* 24 */ IBCS2_ENOTTY, /* 25 */ IBCS2_ETXTBSY, /* 26 */ IBCS2_EFBIG, /* 27 */ IBCS2_ENOSPC, /* 28 */ IBCS2_ESPIPE, /* 29 */ IBCS2_EROFS, /* 30 */ IBCS2_EMLINK, /* 31 */ IBCS2_EPIPE, /* 32 */ IBCS2_EDOM, /* 33 */ IBCS2_ERANGE, /* 34 */ IBCS2_EAGAIN, /* 35 */ IBCS2_EINPROGRESS, /* 36 */ IBCS2_EALREADY, /* 37 */ IBCS2_ENOTSOCK, /* 38 */ IBCS2_EDESTADDRREQ, /* 39 */ IBCS2_EMSGSIZE, /* 40 */ IBCS2_EPROTOTYPE, /* 41 */ IBCS2_ENOPROTOOPT, /* 42 */ IBCS2_EPROTONOSUPPORT, /* 43 */ IBCS2_ESOCKTNOSUPPORT, /* 44 */ IBCS2_EOPNOTSUPP, /* 45 */ IBCS2_EPFNOSUPPORT, /* 46 */ IBCS2_EAFNOSUPPORT, /* 47 */ IBCS2_EADDRINUSE, /* 48 */ IBCS2_EADDRNOTAVAIL, /* 49 */ IBCS2_ENETDOWN, /* 50 */ IBCS2_ENETUNREACH, /* 51 */ IBCS2_ENETRESET, /* 52 */ IBCS2_ECONNABORTED, /* 53 */ IBCS2_ECONNRESET, /* 54 */ IBCS2_ENOBUFS, /* 55 */ IBCS2_EISCONN, /* 56 */ IBCS2_ENOTCONN, /* 57 */ IBCS2_ESHUTDOWN, /* 58 */ IBCS2_ETOOMANYREFS, /* 59 */ IBCS2_ETIMEDOUT, /* 60 */ IBCS2_ECONNREFUSED, /* 61 */ IBCS2_ELOOP, /* 62 */ IBCS2_ENAMETOOLONG, /* 63 */ IBCS2_EHOSTDOWN, /* 64 */ IBCS2_EHOSTUNREACH, /* 65 */ IBCS2_ENOTEMPTY, /* 66 */ 0, /* 67 */ 0, /* 68 */ 0, /* 69 */ IBCS2_ESTALE, /* 70 */ IBCS2_EREMOTE, /* 71 */ 0, /* 72 */ 0, /* 73 */ 0, /* 74 */ 0, /* 75 */ 0, /* 76 */ IBCS2_ENOLCK, /* 77 */ IBCS2_ENOSYS, /* 78 */ 0, /* 79 */ 0, /* 80 */ 0, /* 81 */ IBCS2_EIDRM, /* 82 */ IBCS2_ENOMSG, /* 83 */ IBCS2_EOVERFLOW, /* 84 */ 0, /* 85 */ IBCS2_EILSEQ, /* 86 */ }; Index: head/sys/i386/ibcs2/ibcs2_errno.h =================================================================== --- head/sys/i386/ibcs2/ibcs2_errno.h (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_errno.h (revision 326260) @@ -1,155 +1,157 @@ /*- * ibcs2_errno.h + * SPDX-License-Identifier: BSD-4-Clause + * * Copyright (c) 1995 Scott Bartram * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Scott Bartram. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _IBCS2_ERRNO_H #define _IBCS2_ERRNO_H #define _SCO_NET 1 #define IBCS2_EPERM 1 #define IBCS2_ENOENT 2 #define IBCS2_ESRCH 3 #define IBCS2_EINTR 4 #define IBCS2_EIO 5 #define IBCS2_ENXIO 6 #define IBCS2_E2BIG 7 #define IBCS2_ENOEXEC 8 #define IBCS2_EBADF 9 #define IBCS2_ECHILD 10 #define IBCS2_EAGAIN 11 #define IBCS2_ENOMEM 12 #define IBCS2_EACCES 13 #define IBCS2_EFAULT 14 #define IBCS2_ENOTBLK 15 #define IBCS2_EBUSY 16 #define IBCS2_EEXIST 17 #define IBCS2_EXDEV 18 #define IBCS2_ENODEV 19 #define IBCS2_ENOTDIR 20 #define IBCS2_EISDIR 21 #define IBCS2_EINVAL 22 #define IBCS2_ENFILE 23 #define IBCS2_EMFILE 24 #define IBCS2_ENOTTY 25 #define IBCS2_ETXTBSY 26 #define IBCS2_EFBIG 27 #define IBCS2_ENOSPC 28 #define IBCS2_ESPIPE 29 #define IBCS2_EROFS 30 #define IBCS2_EMLINK 31 #define IBCS2_EPIPE 32 #define IBCS2_EDOM 33 #define IBCS2_ERANGE 34 #define IBCS2_ENOMSG 35 #define IBCS2_EIDRM 36 #define IBCS2_ECHRNG 37 #define IBCS2_EL2NSYNC 38 #define IBCS2_EL3HLT 39 #define IBCS2_EL3RST 40 #define IBCS2_ELNRNG 41 #define IBCS2_EUNATCH 42 #define IBCS2_ENOCSI 43 #define IBCS2_EL2HLT 44 #define IBCS2_EDEADLK 45 #define IBCS2_ENOLCK 46 #define IBCS2_ENOSTR 60 #define IBCS2_ENODATA 61 #define IBCS2_ETIME 62 #define IBCS2_ENOSR 63 #define IBCS2_ENONET 64 #define IBCS2_ENOPKG 65 #define IBCS2_EREMOTE 66 #define IBCS2_ENOLINK 67 #define IBCS2_EADV 68 #define IBCS2_ESRMNT 69 #define IBCS2_ECOMM 70 #define IBCS2_EPROTO 71 #define IBCS2_EMULTIHOP 74 #define IBCS2_ELBIN 75 #define IBCS2_EDOTDOT 76 #define IBCS2_EBADMSG 77 #define IBCS2_ENAMETOOLONG 78 #define IBCS2_EOVERFLOW 79 #define IBCS2_ENOTUNIQ 80 #define IBCS2_EBADFD 81 #define IBCS2_EREMCHG 82 #define IBCS2_EILSEQ 88 #define IBCS2_ENOSYS 89 #if defined(_SCO_NET) /* not strict iBCS2 */ #define IBCS2_EWOULDBLOCK 90 #define IBCS2_EINPROGRESS 91 #define IBCS2_EALREADY 92 #define IBCS2_ENOTSOCK 93 #define IBCS2_EDESTADDRREQ 94 #define IBCS2_EMSGSIZE 95 #define IBCS2_EPROTOTYPE 96 #define IBCS2_EPROTONOSUPPORT 97 #define IBCS2_ESOCKTNOSUPPORT 98 #define IBCS2_EOPNOTSUPP 99 #define IBCS2_EPFNOSUPPORT 100 #define IBCS2_EAFNOSUPPORT 101 #define IBCS2_EADDRINUSE 102 #define IBCS2_EADDRNOTAVAIL 103 #define IBCS2_ENETDOWN 104 #define IBCS2_ENETUNREACH 105 #define IBCS2_ENETRESET 106 #define IBCS2_ECONNABORTED 107 #define IBCS2_ECONNRESET 108 #define IBCS2_ENOBUFS IBCS2_ENOSR #define IBCS2_EISCONN 110 #define IBCS2_ENOTCONN 111 #define IBCS2_ESHUTDOWN 112 #define IBCS2_ETOOMANYREFS 113 #define IBCS2_ETIMEDOUT 114 #define IBCS2_ECONNREFUSED 115 #define IBCS2_EHOSTDOWN 116 #define IBCS2_EHOSTUNREACH 117 #define IBCS2_ENOPROTOOPT 118 #define IBCS2_ENOTEMPTY 145 #define IBCS2_ELOOP 150 #else #define IBCS2_ELOOP 90 #define IBCS2_EWOULDBLOCK 90 #define IBCS2_ERESTART 91 #define IBCS2_ESTRPIPE 92 #define IBCS2_ENOTEMPTY 93 #define IBCS2_EUSERS 94 #endif #define IBCS2_ESTALE 151 #define IBCS2_EIORESID 500 extern int bsd2ibcs_errno[]; #endif /* _IBCS2_ERRNO_H */ Index: head/sys/i386/ibcs2/ibcs2_fcntl.c =================================================================== --- head/sys/i386/ibcs2/ibcs2_fcntl.c (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_fcntl.c (revision 326260) @@ -1,317 +1,319 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1995 Scott Bartram * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_spx_hack.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void cvt_iflock2flock(struct ibcs2_flock *, struct flock *); static void cvt_flock2iflock(struct flock *, struct ibcs2_flock *); static int cvt_o_flags(int); static int oflags2ioflags(int); static int ioflags2oflags(int); static int cvt_o_flags(flags) int flags; { int r = 0; /* convert mode into NetBSD mode */ if (flags & IBCS2_O_WRONLY) r |= O_WRONLY; if (flags & IBCS2_O_RDWR) r |= O_RDWR; if (flags & (IBCS2_O_NDELAY | IBCS2_O_NONBLOCK)) r |= O_NONBLOCK; if (flags & IBCS2_O_APPEND) r |= O_APPEND; if (flags & IBCS2_O_SYNC) r |= O_FSYNC; if (flags & IBCS2_O_CREAT) r |= O_CREAT; if (flags & IBCS2_O_TRUNC) r |= O_TRUNC /* | O_CREAT ??? */; if (flags & IBCS2_O_EXCL) r |= O_EXCL; if (flags & IBCS2_O_RDONLY) r |= O_RDONLY; if (flags & IBCS2_O_PRIV) r |= O_EXLOCK; if (flags & IBCS2_O_NOCTTY) r |= O_NOCTTY; return r; } static void cvt_flock2iflock(flp, iflp) struct flock *flp; struct ibcs2_flock *iflp; { switch (flp->l_type) { case F_RDLCK: iflp->l_type = IBCS2_F_RDLCK; break; case F_WRLCK: iflp->l_type = IBCS2_F_WRLCK; break; case F_UNLCK: iflp->l_type = IBCS2_F_UNLCK; break; } iflp->l_whence = (short)flp->l_whence; iflp->l_start = (ibcs2_off_t)flp->l_start; iflp->l_len = (ibcs2_off_t)flp->l_len; iflp->l_sysid = flp->l_sysid; iflp->l_pid = (ibcs2_pid_t)flp->l_pid; } #ifdef DEBUG_IBCS2 static void print_flock(struct flock *flp) { printf("flock: start=%x len=%x pid=%d type=%d whence=%d\n", (int)flp->l_start, (int)flp->l_len, (int)flp->l_pid, flp->l_type, flp->l_whence); } #endif static void cvt_iflock2flock(iflp, flp) struct ibcs2_flock *iflp; struct flock *flp; { flp->l_start = (off_t)iflp->l_start; flp->l_len = (off_t)iflp->l_len; flp->l_pid = (pid_t)iflp->l_pid; switch (iflp->l_type) { case IBCS2_F_RDLCK: flp->l_type = F_RDLCK; break; case IBCS2_F_WRLCK: flp->l_type = F_WRLCK; break; case IBCS2_F_UNLCK: flp->l_type = F_UNLCK; break; } flp->l_whence = iflp->l_whence; flp->l_sysid = iflp->l_sysid; } /* convert iBCS2 mode into NetBSD mode */ static int ioflags2oflags(flags) int flags; { int r = 0; if (flags & IBCS2_O_RDONLY) r |= O_RDONLY; if (flags & IBCS2_O_WRONLY) r |= O_WRONLY; if (flags & IBCS2_O_RDWR) r |= O_RDWR; if (flags & IBCS2_O_NDELAY) r |= O_NONBLOCK; if (flags & IBCS2_O_APPEND) r |= O_APPEND; if (flags & IBCS2_O_SYNC) r |= O_FSYNC; if (flags & IBCS2_O_NONBLOCK) r |= O_NONBLOCK; if (flags & IBCS2_O_CREAT) r |= O_CREAT; if (flags & IBCS2_O_TRUNC) r |= O_TRUNC; if (flags & IBCS2_O_EXCL) r |= O_EXCL; if (flags & IBCS2_O_NOCTTY) r |= O_NOCTTY; return r; } /* convert NetBSD mode into iBCS2 mode */ static int oflags2ioflags(flags) int flags; { int r = 0; if (flags & O_RDONLY) r |= IBCS2_O_RDONLY; if (flags & O_WRONLY) r |= IBCS2_O_WRONLY; if (flags & O_RDWR) r |= IBCS2_O_RDWR; if (flags & O_NDELAY) r |= IBCS2_O_NONBLOCK; if (flags & O_APPEND) r |= IBCS2_O_APPEND; if (flags & O_FSYNC) r |= IBCS2_O_SYNC; if (flags & O_NONBLOCK) r |= IBCS2_O_NONBLOCK; if (flags & O_CREAT) r |= IBCS2_O_CREAT; if (flags & O_TRUNC) r |= IBCS2_O_TRUNC; if (flags & O_EXCL) r |= IBCS2_O_EXCL; if (flags & O_NOCTTY) r |= IBCS2_O_NOCTTY; return r; } int ibcs2_open(td, uap) struct thread *td; struct ibcs2_open_args *uap; { struct proc *p; char *path; int flags, noctty, ret; p = td->td_proc; noctty = uap->flags & IBCS2_O_NOCTTY; flags = cvt_o_flags(uap->flags); if (uap->flags & O_CREAT) CHECKALTCREAT(td, uap->path, &path); else CHECKALTEXIST(td, uap->path, &path); ret = kern_openat(td, AT_FDCWD, path, UIO_SYSSPACE, flags, uap->mode); #ifdef SPX_HACK if (ret == ENXIO) { if (!strcmp(path, "/compat/ibcs2/dev/spx")) ret = spx_open(td); free(path, M_TEMP); } else #endif /* SPX_HACK */ free(path, M_TEMP); PROC_LOCK(p); if (!ret && !noctty && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) { cap_rights_t rights; struct file *fp; int error; error = fget(td, td->td_retval[0], cap_rights_init(&rights, CAP_IOCTL), &fp); PROC_UNLOCK(p); if (error) return (EBADF); /* ignore any error, just give it a try */ if (fp->f_type == DTYPE_VNODE) fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td->td_ucred, td); fdrop(fp, td); } else PROC_UNLOCK(p); return ret; } int ibcs2_creat(td, uap) struct thread *td; struct ibcs2_creat_args *uap; { char *path; int error; CHECKALTCREAT(td, uap->path, &path); error = kern_openat(td, AT_FDCWD, path, UIO_SYSSPACE, O_WRONLY | O_CREAT | O_TRUNC, uap->mode); free(path, M_TEMP); return (error); } int ibcs2_access(td, uap) struct thread *td; struct ibcs2_access_args *uap; { char *path; int error; CHECKALTEXIST(td, uap->path, &path); error = kern_accessat(td, AT_FDCWD, path, UIO_SYSSPACE, 0, uap->amode); free(path, M_TEMP); return (error); } int ibcs2_fcntl(td, uap) struct thread *td; struct ibcs2_fcntl_args *uap; { intptr_t arg; int error; struct flock fl; struct ibcs2_flock ifl; arg = (intptr_t)uap->arg; switch(uap->cmd) { case IBCS2_F_DUPFD: return (kern_fcntl(td, uap->fd, F_DUPFD, arg)); case IBCS2_F_GETFD: return (kern_fcntl(td, uap->fd, F_GETFD, arg)); case IBCS2_F_SETFD: return (kern_fcntl(td, uap->fd, F_SETFD, arg)); case IBCS2_F_GETFL: error = kern_fcntl(td, uap->fd, F_GETFL, arg); if (error) return error; td->td_retval[0] = oflags2ioflags(td->td_retval[0]); return error; case IBCS2_F_SETFL: return (kern_fcntl(td, uap->fd, F_SETFL, ioflags2oflags(arg))); case IBCS2_F_GETLK: { error = copyin((caddr_t)uap->arg, (caddr_t)&ifl, ibcs2_flock_len); if (error) return error; cvt_iflock2flock(&ifl, &fl); error = kern_fcntl(td, uap->fd, F_GETLK, (intptr_t)&fl); if (error) return error; cvt_flock2iflock(&fl, &ifl); return copyout((caddr_t)&ifl, (caddr_t)uap->arg, ibcs2_flock_len); } case IBCS2_F_SETLK: { error = copyin((caddr_t)uap->arg, (caddr_t)&ifl, ibcs2_flock_len); if (error) return error; cvt_iflock2flock(&ifl, &fl); return (kern_fcntl(td, uap->fd, F_SETLK, (intptr_t)&fl)); } case IBCS2_F_SETLKW: { error = copyin((caddr_t)uap->arg, (caddr_t)&ifl, ibcs2_flock_len); if (error) return error; cvt_iflock2flock(&ifl, &fl); return (kern_fcntl(td, uap->fd, F_SETLKW, (intptr_t)&fl)); } } return ENOSYS; } Index: head/sys/i386/ibcs2/ibcs2_fcntl.h =================================================================== --- head/sys/i386/ibcs2/ibcs2_fcntl.h (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_fcntl.h (revision 326260) @@ -1,78 +1,80 @@ /* $NetBSD: ibcs2_fcntl.h,v 1.2 1994/10/26 02:52:54 cgd Exp $ */ /* $FreeBSD$ */ /*- + * SPDX-License-Identifier: BSD-4-Clause + * * Copyright (c) 1994 Scott Bartram * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Scott Bartram. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _IBCS2_FCNTL_H #define _IBCS2_FCNTL_H 1 #include #define IBCS2_O_RDONLY 0x0000 #define IBCS2_O_WRONLY 0x0001 #define IBCS2_O_RDWR 0x0002 #define IBCS2_O_NDELAY 0x0004 #define IBCS2_O_APPEND 0x0008 #define IBCS2_O_SYNC 0x0010 #define IBCS2_O_NONBLOCK 0x0080 #define IBCS2_O_CREAT 0x0100 #define IBCS2_O_TRUNC 0x0200 #define IBCS2_O_EXCL 0x0400 #define IBCS2_O_NOCTTY 0x0800 #define IBCS2_O_PRIV 0x1000 #define IBCS2_F_DUPFD 0 #define IBCS2_F_GETFD 1 #define IBCS2_F_SETFD 2 #define IBCS2_F_GETFL 3 #define IBCS2_F_SETFL 4 #define IBCS2_F_GETLK 5 #define IBCS2_F_SETLK 6 #define IBCS2_F_SETLKW 7 struct ibcs2_flock { short l_type; short l_whence; ibcs2_off_t l_start; ibcs2_off_t l_len; short l_sysid; ibcs2_pid_t l_pid; }; #define ibcs2_flock_len (sizeof(struct ibcs2_flock)) #define IBCS2_F_RDLCK 1 #define IBCS2_F_WRLCK 2 #define IBCS2_F_UNLCK 3 #define IBCS2_O_ACCMODE 3 #define IBCS2_FD_CLOEXEC 1 #endif /* _IBCS2_FCNTL_H */ Index: head/sys/i386/ibcs2/ibcs2_ioctl.c =================================================================== --- head/sys/i386/ibcs2/ibcs2_ioctl.c (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_ioctl.c (revision 326260) @@ -1,689 +1,691 @@ /* $NetBSD: ibcs2_ioctl.c,v 1.6 1995/03/14 15:12:28 scottb Exp $ */ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 1994, 1995 Scott Bartram * All rights reserved. * * based on compat/sunos/sun_ioctl.c * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void stios2btios(struct ibcs2_termios *, struct termios *); static void btios2stios(struct termios *, struct ibcs2_termios *); static void stios2stio(struct ibcs2_termios *, struct ibcs2_termio *); static void stio2stios(struct ibcs2_termio *, struct ibcs2_termios *); /* * iBCS2 ioctl calls. */ struct speedtab { int sp_speed; /* Speed. */ int sp_code; /* Code. */ }; static struct speedtab sptab[] = { { 0, 0 }, { 50, 1 }, { 75, 2 }, { 110, 3 }, { 134, 4 }, { 135, 4 }, { 150, 5 }, { 200, 6 }, { 300, 7 }, { 600, 8 }, { 1200, 9 }, { 1800, 10 }, { 2400, 11 }, { 4800, 12 }, { 9600, 13 }, { 19200, 14 }, { 38400, 15 }, { -1, -1 } }; static u_long s2btab[] = { 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, }; static int ttspeedtab(int speed, struct speedtab *table) { for ( ; table->sp_speed != -1; table++) if (table->sp_speed == speed) return (table->sp_code); return (-1); } static void stios2btios(st, bt) struct ibcs2_termios *st; struct termios *bt; { register u_long l, r; l = st->c_iflag; r = 0; if (l & IBCS2_IGNBRK) r |= IGNBRK; if (l & IBCS2_BRKINT) r |= BRKINT; if (l & IBCS2_IGNPAR) r |= IGNPAR; if (l & IBCS2_PARMRK) r |= PARMRK; if (l & IBCS2_INPCK) r |= INPCK; if (l & IBCS2_ISTRIP) r |= ISTRIP; if (l & IBCS2_INLCR) r |= INLCR; if (l & IBCS2_IGNCR) r |= IGNCR; if (l & IBCS2_ICRNL) r |= ICRNL; if (l & IBCS2_IXON) r |= IXON; if (l & IBCS2_IXANY) r |= IXANY; if (l & IBCS2_IXOFF) r |= IXOFF; if (l & IBCS2_IMAXBEL) r |= IMAXBEL; bt->c_iflag = r; l = st->c_oflag; r = 0; if (l & IBCS2_OPOST) r |= OPOST; if (l & IBCS2_ONLCR) r |= ONLCR; if (l & IBCS2_TAB3) r |= TAB3; bt->c_oflag = r; l = st->c_cflag; r = 0; switch (l & IBCS2_CSIZE) { case IBCS2_CS5: r |= CS5; break; case IBCS2_CS6: r |= CS6; break; case IBCS2_CS7: r |= CS7; break; case IBCS2_CS8: r |= CS8; break; } if (l & IBCS2_CSTOPB) r |= CSTOPB; if (l & IBCS2_CREAD) r |= CREAD; if (l & IBCS2_PARENB) r |= PARENB; if (l & IBCS2_PARODD) r |= PARODD; if (l & IBCS2_HUPCL) r |= HUPCL; if (l & IBCS2_CLOCAL) r |= CLOCAL; bt->c_cflag = r; bt->c_ispeed = bt->c_ospeed = s2btab[l & 0x0000000f]; l = st->c_lflag; r = 0; if (l & IBCS2_ISIG) r |= ISIG; if (l & IBCS2_ICANON) r |= ICANON; if (l & IBCS2_ECHO) r |= ECHO; if (l & IBCS2_ECHOE) r |= ECHOE; if (l & IBCS2_ECHOK) r |= ECHOK; if (l & IBCS2_ECHONL) r |= ECHONL; if (l & IBCS2_NOFLSH) r |= NOFLSH; if (l & IBCS2_TOSTOP) r |= TOSTOP; bt->c_lflag = r; bt->c_cc[VINTR] = st->c_cc[IBCS2_VINTR] ? st->c_cc[IBCS2_VINTR] : _POSIX_VDISABLE; bt->c_cc[VQUIT] = st->c_cc[IBCS2_VQUIT] ? st->c_cc[IBCS2_VQUIT] : _POSIX_VDISABLE; bt->c_cc[VERASE] = st->c_cc[IBCS2_VERASE] ? st->c_cc[IBCS2_VERASE] : _POSIX_VDISABLE; bt->c_cc[VKILL] = st->c_cc[IBCS2_VKILL] ? st->c_cc[IBCS2_VKILL] : _POSIX_VDISABLE; if (bt->c_lflag & ICANON) { bt->c_cc[VEOF] = st->c_cc[IBCS2_VEOF] ? st->c_cc[IBCS2_VEOF] : _POSIX_VDISABLE; bt->c_cc[VEOL] = st->c_cc[IBCS2_VEOL] ? st->c_cc[IBCS2_VEOL] : _POSIX_VDISABLE; } else { bt->c_cc[VMIN] = st->c_cc[IBCS2_VMIN]; bt->c_cc[VTIME] = st->c_cc[IBCS2_VTIME]; } bt->c_cc[VEOL2] = st->c_cc[IBCS2_VEOL2] ? st->c_cc[IBCS2_VEOL2] : _POSIX_VDISABLE; #if 0 bt->c_cc[VSWTCH] = st->c_cc[IBCS2_VSWTCH] ? st->c_cc[IBCS2_VSWTCH] : _POSIX_VDISABLE; #endif bt->c_cc[VSTART] = st->c_cc[IBCS2_VSTART] ? st->c_cc[IBCS2_VSTART] : _POSIX_VDISABLE; bt->c_cc[VSTOP] = st->c_cc[IBCS2_VSTOP] ? st->c_cc[IBCS2_VSTOP] : _POSIX_VDISABLE; bt->c_cc[VSUSP] = st->c_cc[IBCS2_VSUSP] ? st->c_cc[IBCS2_VSUSP] : _POSIX_VDISABLE; bt->c_cc[VDSUSP] = _POSIX_VDISABLE; bt->c_cc[VREPRINT] = _POSIX_VDISABLE; bt->c_cc[VDISCARD] = _POSIX_VDISABLE; bt->c_cc[VWERASE] = _POSIX_VDISABLE; bt->c_cc[VLNEXT] = _POSIX_VDISABLE; bt->c_cc[VSTATUS] = _POSIX_VDISABLE; } static void btios2stios(bt, st) struct termios *bt; struct ibcs2_termios *st; { register u_long l, r; l = bt->c_iflag; r = 0; if (l & IGNBRK) r |= IBCS2_IGNBRK; if (l & BRKINT) r |= IBCS2_BRKINT; if (l & IGNPAR) r |= IBCS2_IGNPAR; if (l & PARMRK) r |= IBCS2_PARMRK; if (l & INPCK) r |= IBCS2_INPCK; if (l & ISTRIP) r |= IBCS2_ISTRIP; if (l & INLCR) r |= IBCS2_INLCR; if (l & IGNCR) r |= IBCS2_IGNCR; if (l & ICRNL) r |= IBCS2_ICRNL; if (l & IXON) r |= IBCS2_IXON; if (l & IXANY) r |= IBCS2_IXANY; if (l & IXOFF) r |= IBCS2_IXOFF; if (l & IMAXBEL) r |= IBCS2_IMAXBEL; st->c_iflag = r; l = bt->c_oflag; r = 0; if (l & OPOST) r |= IBCS2_OPOST; if (l & ONLCR) r |= IBCS2_ONLCR; if (l & TAB3) r |= IBCS2_TAB3; st->c_oflag = r; l = bt->c_cflag; r = 0; switch (l & CSIZE) { case CS5: r |= IBCS2_CS5; break; case CS6: r |= IBCS2_CS6; break; case CS7: r |= IBCS2_CS7; break; case CS8: r |= IBCS2_CS8; break; } if (l & CSTOPB) r |= IBCS2_CSTOPB; if (l & CREAD) r |= IBCS2_CREAD; if (l & PARENB) r |= IBCS2_PARENB; if (l & PARODD) r |= IBCS2_PARODD; if (l & HUPCL) r |= IBCS2_HUPCL; if (l & CLOCAL) r |= IBCS2_CLOCAL; st->c_cflag = r; l = bt->c_lflag; r = 0; if (l & ISIG) r |= IBCS2_ISIG; if (l & ICANON) r |= IBCS2_ICANON; if (l & ECHO) r |= IBCS2_ECHO; if (l & ECHOE) r |= IBCS2_ECHOE; if (l & ECHOK) r |= IBCS2_ECHOK; if (l & ECHONL) r |= IBCS2_ECHONL; if (l & NOFLSH) r |= IBCS2_NOFLSH; if (l & TOSTOP) r |= IBCS2_TOSTOP; st->c_lflag = r; l = ttspeedtab(bt->c_ospeed, sptab); if ((int)l >= 0) st->c_cflag |= l; st->c_cc[IBCS2_VINTR] = bt->c_cc[VINTR] != _POSIX_VDISABLE ? bt->c_cc[VINTR] : 0; st->c_cc[IBCS2_VQUIT] = bt->c_cc[VQUIT] != _POSIX_VDISABLE ? bt->c_cc[VQUIT] : 0; st->c_cc[IBCS2_VERASE] = bt->c_cc[VERASE] != _POSIX_VDISABLE ? bt->c_cc[VERASE] : 0; st->c_cc[IBCS2_VKILL] = bt->c_cc[VKILL] != _POSIX_VDISABLE ? bt->c_cc[VKILL] : 0; if (bt->c_lflag & ICANON) { st->c_cc[IBCS2_VEOF] = bt->c_cc[VEOF] != _POSIX_VDISABLE ? bt->c_cc[VEOF] : 0; st->c_cc[IBCS2_VEOL] = bt->c_cc[VEOL] != _POSIX_VDISABLE ? bt->c_cc[VEOL] : 0; } else { st->c_cc[IBCS2_VMIN] = bt->c_cc[VMIN]; st->c_cc[IBCS2_VTIME] = bt->c_cc[VTIME]; } st->c_cc[IBCS2_VEOL2] = bt->c_cc[VEOL2] != _POSIX_VDISABLE ? bt->c_cc[VEOL2] : 0; st->c_cc[IBCS2_VSWTCH] = 0; st->c_cc[IBCS2_VSUSP] = bt->c_cc[VSUSP] != _POSIX_VDISABLE ? bt->c_cc[VSUSP] : 0; st->c_cc[IBCS2_VSTART] = bt->c_cc[VSTART] != _POSIX_VDISABLE ? bt->c_cc[VSTART] : 0; st->c_cc[IBCS2_VSTOP] = bt->c_cc[VSTOP] != _POSIX_VDISABLE ? bt->c_cc[VSTOP] : 0; st->c_line = 0; } static void stios2stio(ts, t) struct ibcs2_termios *ts; struct ibcs2_termio *t; { t->c_iflag = ts->c_iflag; t->c_oflag = ts->c_oflag; t->c_cflag = ts->c_cflag; t->c_lflag = ts->c_lflag; t->c_line = ts->c_line; bcopy(ts->c_cc, t->c_cc, IBCS2_NCC); } static void stio2stios(t, ts) struct ibcs2_termio *t; struct ibcs2_termios *ts; { ts->c_iflag = t->c_iflag; ts->c_oflag = t->c_oflag; ts->c_cflag = t->c_cflag; ts->c_lflag = t->c_lflag; ts->c_line = t->c_line; bcopy(t->c_cc, ts->c_cc, IBCS2_NCC); } int ibcs2_ioctl(td, uap) struct thread *td; struct ibcs2_ioctl_args *uap; { struct proc *p = td->td_proc; cap_rights_t rights; struct file *fp; int error; error = fget(td, uap->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); if (error != 0) { DPRINTF(("ibcs2_ioctl(%d): bad fd %d ", p->p_pid, uap->fd)); return EBADF; } if ((fp->f_flag & (FREAD|FWRITE)) == 0) { fdrop(fp, td); DPRINTF(("ibcs2_ioctl(%d): bad fp flag ", p->p_pid)); return EBADF; } switch (uap->cmd) { case IBCS2_TCGETA: case IBCS2_XCGETA: case IBCS2_OXCGETA: { struct termios bts; struct ibcs2_termios sts; struct ibcs2_termio st; if ((error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bts, td->td_ucred, td)) != 0) break; btios2stios (&bts, &sts); if (uap->cmd == IBCS2_TCGETA) { stios2stio (&sts, &st); error = copyout((caddr_t)&st, uap->data, sizeof (st)); #ifdef DEBUG_IBCS2 if (error) DPRINTF(("ibcs2_ioctl(%d): copyout failed ", p->p_pid)); #endif break; } else { error = copyout((caddr_t)&sts, uap->data, sizeof (sts)); break; } /*NOTREACHED*/ } case IBCS2_TCSETA: case IBCS2_TCSETAW: case IBCS2_TCSETAF: { struct termios bts; struct ibcs2_termios sts; struct ibcs2_termio st; if ((error = copyin(uap->data, (caddr_t)&st, sizeof(st))) != 0) { DPRINTF(("ibcs2_ioctl(%d): TCSET copyin failed ", p->p_pid)); break; } /* get full BSD termios so we don't lose information */ if ((error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bts, td->td_ucred, td)) != 0) { DPRINTF(("ibcs2_ioctl(%d): TCSET ctl failed fd %d ", p->p_pid, uap->fd)); break; } /* * convert to iBCS2 termios, copy in information from * termio, and convert back, then set new values. */ btios2stios(&bts, &sts); stio2stios(&st, &sts); stios2btios(&sts, &bts); error = fo_ioctl(fp, uap->cmd - IBCS2_TCSETA + TIOCSETA, (caddr_t)&bts, td->td_ucred, td); break; } case IBCS2_XCSETA: case IBCS2_XCSETAW: case IBCS2_XCSETAF: { struct termios bts; struct ibcs2_termios sts; if ((error = copyin(uap->data, (caddr_t)&sts, sizeof (sts))) != 0) break; stios2btios (&sts, &bts); error = fo_ioctl(fp, uap->cmd - IBCS2_XCSETA + TIOCSETA, (caddr_t)&bts, td->td_ucred, td); break; } case IBCS2_OXCSETA: case IBCS2_OXCSETAW: case IBCS2_OXCSETAF: { struct termios bts; struct ibcs2_termios sts; if ((error = copyin(uap->data, (caddr_t)&sts, sizeof (sts))) != 0) break; stios2btios (&sts, &bts); error = fo_ioctl(fp, uap->cmd - IBCS2_OXCSETA + TIOCSETA, (caddr_t)&bts, td->td_ucred, td); break; } case IBCS2_TCSBRK: DPRINTF(("ibcs2_ioctl(%d): TCSBRK ", p->p_pid)); error = ENOSYS; break; case IBCS2_TCXONC: { switch ((int)uap->data) { case 0: case 1: DPRINTF(("ibcs2_ioctl(%d): TCXONC ", p->p_pid)); error = ENOSYS; break; case 2: error = fo_ioctl(fp, TIOCSTOP, (caddr_t)0, td->td_ucred, td); break; case 3: error = fo_ioctl(fp, TIOCSTART, (caddr_t)1, td->td_ucred, td); break; default: error = EINVAL; break; } break; } case IBCS2_TCFLSH: { int arg; switch ((int)uap->data) { case 0: arg = FREAD; break; case 1: arg = FWRITE; break; case 2: arg = FREAD | FWRITE; break; default: fdrop(fp, td); return EINVAL; } error = fo_ioctl(fp, TIOCFLUSH, (caddr_t)&arg, td->td_ucred, td); break; } case IBCS2_TIOCGWINSZ: uap->cmd = TIOCGWINSZ; error = sys_ioctl(td, (struct ioctl_args *)uap); break; case IBCS2_TIOCSWINSZ: uap->cmd = TIOCSWINSZ; error = sys_ioctl(td, (struct ioctl_args *)uap); break; case IBCS2_TIOCGPGRP: { pid_t pg_id; PROC_LOCK(p); pg_id = p->p_pgrp->pg_id; PROC_UNLOCK(p); error = copyout((caddr_t)&pg_id, uap->data, sizeof(pg_id)); break; } case IBCS2_TIOCSPGRP: /* XXX - is uap->data a pointer to pgid? */ { struct setpgid_args sa; sa.pid = 0; sa.pgid = (int)uap->data; error = sys_setpgid(td, &sa); break; } case IBCS2_TCGETSC: /* SCO console - get scancode flags */ error = EINTR; /* ENOSYS; */ break; case IBCS2_TCSETSC: /* SCO console - set scancode flags */ error = 0; /* ENOSYS; */ break; case IBCS2_JWINSIZE: /* Unix to Jerq I/O control */ { struct ibcs2_jwinsize { char bytex, bytey; short bitx, bity; } ibcs2_jwinsize; PROC_LOCK(p); SESS_LOCK(p->p_session); ibcs2_jwinsize.bytex = 80; /* p->p_session->s_ttyp->t_winsize.ws_col; XXX */ ibcs2_jwinsize.bytey = 25; /* p->p_session->s_ttyp->t_winsize.ws_row; XXX */ ibcs2_jwinsize.bitx = p->p_session->s_ttyp->t_winsize.ws_xpixel; ibcs2_jwinsize.bity = p->p_session->s_ttyp->t_winsize.ws_ypixel; SESS_UNLOCK(p->p_session); PROC_UNLOCK(p); error = copyout((caddr_t)&ibcs2_jwinsize, uap->data, sizeof(ibcs2_jwinsize)); break; } /* keyboard and display ioctl's -- type 'K' */ case IBCS2_KDGKBMODE: /* get keyboard translation mode */ uap->cmd = KDGKBMODE; /* printf("ioctl KDGKBMODE = %x\n", uap->cmd);*/ error = sys_ioctl(td, (struct ioctl_args *)uap); break; case IBCS2_KDSKBMODE: /* set keyboard translation mode */ uap->cmd = KDSKBMODE; error = sys_ioctl(td, (struct ioctl_args *)uap); break; case IBCS2_KDMKTONE: /* sound tone */ uap->cmd = KDMKTONE; error = sys_ioctl(td, (struct ioctl_args *)uap); break; case IBCS2_KDGETMODE: /* get text/graphics mode */ uap->cmd = KDGETMODE; error = sys_ioctl(td, (struct ioctl_args *)uap); break; case IBCS2_KDSETMODE: /* set text/graphics mode */ uap->cmd = KDSETMODE; error = sys_ioctl(td, (struct ioctl_args *)uap); break; case IBCS2_KDSBORDER: /* set ega color border */ uap->cmd = KDSBORDER; error = sys_ioctl(td, (struct ioctl_args *)uap); break; case IBCS2_KDGKBSTATE: uap->cmd = KDGKBSTATE; error = sys_ioctl(td, (struct ioctl_args *)uap); break; case IBCS2_KDSETRAD: uap->cmd = KDSETRAD; error = sys_ioctl(td, (struct ioctl_args *)uap); break; case IBCS2_KDENABIO: /* enable direct I/O to ports */ uap->cmd = KDENABIO; error = sys_ioctl(td, (struct ioctl_args *)uap); break; case IBCS2_KDDISABIO: /* disable direct I/O to ports */ uap->cmd = KDDISABIO; error = sys_ioctl(td, (struct ioctl_args *)uap); break; case IBCS2_KIOCSOUND: /* start sound generation */ uap->cmd = KIOCSOUND; error = sys_ioctl(td, (struct ioctl_args *)uap); break; case IBCS2_KDGKBTYPE: /* get keyboard type */ uap->cmd = KDGKBTYPE; error = sys_ioctl(td, (struct ioctl_args *)uap); break; case IBCS2_KDGETLED: /* get keyboard LED status */ uap->cmd = KDGETLED; error = sys_ioctl(td, (struct ioctl_args *)uap); break; case IBCS2_KDSETLED: /* set keyboard LED status */ uap->cmd = KDSETLED; error = sys_ioctl(td, (struct ioctl_args *)uap); break; /* Xenix keyboard and display ioctl's from sys/kd.h -- type 'k' */ case IBCS2_GETFKEY: /* Get function key */ uap->cmd = GETFKEY; error = sys_ioctl(td, (struct ioctl_args *)uap); break; case IBCS2_SETFKEY: /* Set function key */ uap->cmd = SETFKEY; error = sys_ioctl(td, (struct ioctl_args *)uap); break; case IBCS2_GIO_SCRNMAP: /* Get screen output map table */ uap->cmd = GIO_SCRNMAP; error = sys_ioctl(td, (struct ioctl_args *)uap); break; case IBCS2_PIO_SCRNMAP: /* Set screen output map table */ uap->cmd = PIO_SCRNMAP; error = sys_ioctl(td, (struct ioctl_args *)uap); break; case IBCS2_GIO_KEYMAP: /* Get keyboard map table */ uap->cmd = OGIO_KEYMAP; error = sys_ioctl(td, (struct ioctl_args *)uap); break; case IBCS2_PIO_KEYMAP: /* Set keyboard map table */ uap->cmd = OPIO_KEYMAP; error = sys_ioctl(td, (struct ioctl_args *)uap); break; /* socksys */ case IBCS2_SIOCSOCKSYS: error = ibcs2_socksys(td, (struct ibcs2_socksys_args *)uap); break; case IBCS2_FIONREAD: case IBCS2_I_NREAD: /* STREAMS */ uap->cmd = FIONREAD; error = sys_ioctl(td, (struct ioctl_args *)uap); break; default: DPRINTF(("ibcs2_ioctl(%d): unknown cmd 0x%lx ", td->proc->p_pid, uap->cmd)); error = ENOSYS; break; } fdrop(fp, td); return error; } Index: head/sys/i386/ibcs2/ibcs2_ipc.c =================================================================== --- head/sys/i386/ibcs2/ibcs2_ipc.c (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_ipc.c (revision 326260) @@ -1,560 +1,562 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1995 Scott Bartram * Copyright (c) 1995 Steven Wallace * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #define IBCS2_IPC_RMID 0 #define IBCS2_IPC_SET 1 #define IBCS2_IPC_STAT 2 #define IBCS2_SETVAL 8 static void cvt_msqid2imsqid(struct msqid_ds *, struct ibcs2_msqid_ds *); static void cvt_imsqid2msqid(struct ibcs2_msqid_ds *, struct msqid_ds *); #ifdef unused static void cvt_sem2isem(struct sem *, struct ibcs2_sem *); static void cvt_isem2sem(struct ibcs2_sem *, struct sem *); #endif static void cvt_semid2isemid(struct semid_ds *, struct ibcs2_semid_ds *); static void cvt_isemid2semid(struct ibcs2_semid_ds *, struct semid_ds *); static void cvt_shmid2ishmid(struct shmid_ds *, struct ibcs2_shmid_ds *); static void cvt_ishmid2shmid(struct ibcs2_shmid_ds *, struct shmid_ds *); static void cvt_perm2iperm(struct ipc_perm *, struct ibcs2_ipc_perm *); static void cvt_iperm2perm(struct ibcs2_ipc_perm *, struct ipc_perm *); /* * iBCS2 msgsys call */ static void cvt_msqid2imsqid(bp, ibp) struct msqid_ds *bp; struct ibcs2_msqid_ds *ibp; { cvt_perm2iperm(&bp->msg_perm, &ibp->msg_perm); ibp->msg_first = bp->msg_first; ibp->msg_last = bp->msg_last; ibp->msg_cbytes = (u_short)bp->msg_cbytes; ibp->msg_qnum = (u_short)bp->msg_qnum; ibp->msg_qbytes = (u_short)bp->msg_qbytes; ibp->msg_lspid = (u_short)bp->msg_lspid; ibp->msg_lrpid = (u_short)bp->msg_lrpid; ibp->msg_stime = bp->msg_stime; ibp->msg_rtime = bp->msg_rtime; ibp->msg_ctime = bp->msg_ctime; return; } static void cvt_imsqid2msqid(ibp, bp) struct ibcs2_msqid_ds *ibp; struct msqid_ds *bp; { cvt_iperm2perm(&ibp->msg_perm, &bp->msg_perm); bp->msg_first = ibp->msg_first; bp->msg_last = ibp->msg_last; bp->msg_cbytes = ibp->msg_cbytes; bp->msg_qnum = ibp->msg_qnum; bp->msg_qbytes = ibp->msg_qbytes; bp->msg_lspid = ibp->msg_lspid; bp->msg_lrpid = ibp->msg_lrpid; bp->msg_stime = ibp->msg_stime; bp->msg_rtime = ibp->msg_rtime; bp->msg_ctime = ibp->msg_ctime; return; } struct ibcs2_msgget_args { int what; ibcs2_key_t key; int msgflg; }; static int ibcs2_msgget(struct thread *td, void *v) { struct ibcs2_msgget_args *uap = v; struct msgget_args ap; ap.key = uap->key; ap.msgflg = uap->msgflg; return sys_msgget(td, &ap); } struct ibcs2_msgctl_args { int what; int msqid; int cmd; struct ibcs2_msqid_ds *buf; }; static int ibcs2_msgctl(struct thread *td, void *v) { struct ibcs2_msgctl_args *uap = v; struct ibcs2_msqid_ds is; struct msqid_ds bs; int error; switch (uap->cmd) { case IBCS2_IPC_STAT: error = kern_msgctl(td, uap->msqid, IPC_STAT, &bs); if (!error) { cvt_msqid2imsqid(&bs, &is); error = copyout(&is, uap->buf, sizeof(is)); } return (error); case IBCS2_IPC_SET: error = copyin(uap->buf, &is, sizeof(is)); if (error) return (error); cvt_imsqid2msqid(&is, &bs); return (kern_msgctl(td, uap->msqid, IPC_SET, &bs)); case IBCS2_IPC_RMID: return (kern_msgctl(td, uap->msqid, IPC_RMID, NULL)); } return (EINVAL); } struct ibcs2_msgrcv_args { int what; int msqid; void *msgp; size_t msgsz; long msgtyp; int msgflg; }; static int ibcs2_msgrcv(struct thread *td, void *v) { struct ibcs2_msgrcv_args *uap = v; struct msgrcv_args ap; ap.msqid = uap->msqid; ap.msgp = uap->msgp; ap.msgsz = uap->msgsz; ap.msgtyp = uap->msgtyp; ap.msgflg = uap->msgflg; return (sys_msgrcv(td, &ap)); } struct ibcs2_msgsnd_args { int what; int msqid; void *msgp; size_t msgsz; int msgflg; }; static int ibcs2_msgsnd(struct thread *td, void *v) { struct ibcs2_msgsnd_args *uap = v; struct msgsnd_args ap; ap.msqid = uap->msqid; ap.msgp = uap->msgp; ap.msgsz = uap->msgsz; ap.msgflg = uap->msgflg; return (sys_msgsnd(td, &ap)); } int ibcs2_msgsys(td, uap) struct thread *td; struct ibcs2_msgsys_args *uap; { switch (uap->which) { case 0: return (ibcs2_msgget(td, uap)); case 1: return (ibcs2_msgctl(td, uap)); case 2: return (ibcs2_msgrcv(td, uap)); case 3: return (ibcs2_msgsnd(td, uap)); default: return (EINVAL); } } /* * iBCS2 semsys call */ #ifdef unused static void cvt_sem2isem(bp, ibp) struct sem *bp; struct ibcs2_sem *ibp; { ibp->semval = bp->semval; ibp->sempid = bp->sempid; ibp->semncnt = bp->semncnt; ibp->semzcnt = bp->semzcnt; return; } static void cvt_isem2sem(ibp, bp) struct ibcs2_sem *ibp; struct sem *bp; { bp->semval = ibp->semval; bp->sempid = ibp->sempid; bp->semncnt = ibp->semncnt; bp->semzcnt = ibp->semzcnt; return; } #endif static void cvt_iperm2perm(ipp, pp) struct ibcs2_ipc_perm *ipp; struct ipc_perm *pp; { pp->uid = ipp->uid; pp->gid = ipp->gid; pp->cuid = ipp->cuid; pp->cgid = ipp->cgid; pp->mode = ipp->mode; pp->seq = ipp->seq; pp->key = ipp->key; } static void cvt_perm2iperm(pp, ipp) struct ipc_perm *pp; struct ibcs2_ipc_perm *ipp; { ipp->uid = pp->uid; ipp->gid = pp->gid; ipp->cuid = pp->cuid; ipp->cgid = pp->cgid; ipp->mode = pp->mode; ipp->seq = pp->seq; ipp->key = pp->key; } static void cvt_semid2isemid(bp, ibp) struct semid_ds *bp; struct ibcs2_semid_ds *ibp; { cvt_perm2iperm(&bp->sem_perm, &ibp->sem_perm); ibp->sem_base = (struct ibcs2_sem *)bp->sem_base; ibp->sem_nsems = bp->sem_nsems; ibp->sem_otime = bp->sem_otime; ibp->sem_ctime = bp->sem_ctime; return; } static void cvt_isemid2semid(ibp, bp) struct ibcs2_semid_ds *ibp; struct semid_ds *bp; { cvt_iperm2perm(&ibp->sem_perm, &bp->sem_perm); bp->sem_base = (struct sem *)ibp->sem_base; bp->sem_nsems = ibp->sem_nsems; bp->sem_otime = ibp->sem_otime; bp->sem_ctime = ibp->sem_ctime; return; } struct ibcs2_semctl_args { int what; int semid; int semnum; int cmd; union semun arg; }; static int ibcs2_semctl(struct thread *td, void *v) { struct ibcs2_semctl_args *uap = v; struct ibcs2_semid_ds is; struct semid_ds bs; union semun semun; register_t rval; int error; switch(uap->cmd) { case IBCS2_IPC_STAT: semun.buf = &bs; error = kern_semctl(td, uap->semid, uap->semnum, IPC_STAT, &semun, &rval); if (error) return (error); cvt_semid2isemid(&bs, &is); error = copyout(&is, uap->arg.buf, sizeof(is)); if (error == 0) td->td_retval[0] = rval; return (error); case IBCS2_IPC_SET: error = copyin(uap->arg.buf, &is, sizeof(is)); if (error) return (error); cvt_isemid2semid(&is, &bs); semun.buf = &bs; return (kern_semctl(td, uap->semid, uap->semnum, IPC_SET, &semun, td->td_retval)); } return (kern_semctl(td, uap->semid, uap->semnum, uap->cmd, &uap->arg, td->td_retval)); } struct ibcs2_semget_args { int what; ibcs2_key_t key; int nsems; int semflg; }; static int ibcs2_semget(struct thread *td, void *v) { struct ibcs2_semget_args *uap = v; struct semget_args ap; ap.key = uap->key; ap.nsems = uap->nsems; ap.semflg = uap->semflg; return (sys_semget(td, &ap)); } struct ibcs2_semop_args { int what; int semid; struct sembuf *sops; size_t nsops; }; static int ibcs2_semop(struct thread *td, void *v) { struct ibcs2_semop_args *uap = v; struct semop_args ap; ap.semid = uap->semid; ap.sops = uap->sops; ap.nsops = uap->nsops; return (sys_semop(td, &ap)); } int ibcs2_semsys(td, uap) struct thread *td; struct ibcs2_semsys_args *uap; { switch (uap->which) { case 0: return (ibcs2_semctl(td, uap)); case 1: return (ibcs2_semget(td, uap)); case 2: return (ibcs2_semop(td, uap)); } return (EINVAL); } /* * iBCS2 shmsys call */ static void cvt_shmid2ishmid(bp, ibp) struct shmid_ds *bp; struct ibcs2_shmid_ds *ibp; { cvt_perm2iperm(&bp->shm_perm, &ibp->shm_perm); ibp->shm_segsz = bp->shm_segsz; ibp->shm_lpid = bp->shm_lpid; ibp->shm_cpid = bp->shm_cpid; if (bp->shm_nattch > SHRT_MAX) ibp->shm_nattch = SHRT_MAX; else ibp->shm_nattch = bp->shm_nattch; ibp->shm_cnattch = 0; /* ignored anyway */ ibp->shm_atime = bp->shm_atime; ibp->shm_dtime = bp->shm_dtime; ibp->shm_ctime = bp->shm_ctime; return; } static void cvt_ishmid2shmid(ibp, bp) struct ibcs2_shmid_ds *ibp; struct shmid_ds *bp; { cvt_iperm2perm(&ibp->shm_perm, &bp->shm_perm); bp->shm_segsz = ibp->shm_segsz; bp->shm_lpid = ibp->shm_lpid; bp->shm_cpid = ibp->shm_cpid; bp->shm_nattch = ibp->shm_nattch; bp->shm_atime = ibp->shm_atime; bp->shm_dtime = ibp->shm_dtime; bp->shm_ctime = ibp->shm_ctime; return; } struct ibcs2_shmat_args { int what; int shmid; const void *shmaddr; int shmflg; }; static int ibcs2_shmat(struct thread *td, void *v) { struct ibcs2_shmat_args *uap = v; struct shmat_args ap; ap.shmid = uap->shmid; ap.shmaddr = uap->shmaddr; ap.shmflg = uap->shmflg; return (sys_shmat(td, &ap)); } struct ibcs2_shmctl_args { int what; int shmid; int cmd; struct ibcs2_shmid_ds *buf; }; static int ibcs2_shmctl(struct thread *td, void *v) { struct ibcs2_shmctl_args *uap = v; struct ibcs2_shmid_ds is; struct shmid_ds bs; int error; switch(uap->cmd) { case IBCS2_IPC_STAT: error = kern_shmctl(td, uap->shmid, IPC_STAT, &bs, NULL); if (error) return (error); cvt_shmid2ishmid(&bs, &is); return (copyout(&is, uap->buf, sizeof(is))); case IBCS2_IPC_SET: error = copyin(uap->buf, &is, sizeof(is)); if (error) return (error); cvt_ishmid2shmid(&is, &bs); return (kern_shmctl(td, uap->shmid, IPC_SET, &bs, NULL)); case IPC_INFO: case SHM_INFO: case SHM_STAT: /* XXX: */ return (EINVAL); } return (kern_shmctl(td, uap->shmid, uap->cmd, NULL, NULL)); } struct ibcs2_shmdt_args { int what; const void *shmaddr; }; static int ibcs2_shmdt(struct thread *td, void *v) { struct ibcs2_shmdt_args *uap = v; struct shmdt_args ap; ap.shmaddr = uap->shmaddr; return (sys_shmdt(td, &ap)); } struct ibcs2_shmget_args { int what; ibcs2_key_t key; size_t size; int shmflg; }; static int ibcs2_shmget(struct thread *td, void *v) { struct ibcs2_shmget_args *uap = v; struct shmget_args ap; ap.key = uap->key; ap.size = uap->size; ap.shmflg = uap->shmflg; return (sys_shmget(td, &ap)); } int ibcs2_shmsys(td, uap) struct thread *td; struct ibcs2_shmsys_args *uap; { switch (uap->which) { case 0: return (ibcs2_shmat(td, uap)); case 1: return (ibcs2_shmctl(td, uap)); case 2: return (ibcs2_shmdt(td, uap)); case 3: return (ibcs2_shmget(td, uap)); } return (EINVAL); } MODULE_DEPEND(ibcs2, sysvmsg, 1, 1, 1); MODULE_DEPEND(ibcs2, sysvsem, 1, 1, 1); MODULE_DEPEND(ibcs2, sysvshm, 1, 1, 1); Index: head/sys/i386/ibcs2/ibcs2_ipc.h =================================================================== --- head/sys/i386/ibcs2/ibcs2_ipc.h (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_ipc.h (revision 326260) @@ -1,85 +1,87 @@ /*- + * SPDX-License-Identifier: BSD-4-Clause + * * Copyright (c) 1995 Steven Wallace * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Steven Wallace. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ struct ibcs2_ipc_perm { u_short uid; /* user id */ u_short gid; /* group id */ u_short cuid; /* creator user id */ u_short cgid; /* creator group id */ u_short mode; /* r/w permission */ u_short seq; /* sequence # (to generate unique msg/sem/shm id) */ ibcs2_key_t key; /* user specified msg/sem/shm key */ }; struct ibcs2_msqid_ds { struct ibcs2_ipc_perm msg_perm; struct msg *msg_first; struct msg *msg_last; u_short msg_cbytes; u_short msg_qnum; u_short msg_qbytes; u_short msg_lspid; u_short msg_lrpid; ibcs2_time_t msg_stime; ibcs2_time_t msg_rtime; ibcs2_time_t msg_ctime; }; struct ibcs2_semid_ds { struct ibcs2_ipc_perm sem_perm; struct ibcs2_sem *sem_base; u_short sem_nsems; ibcs2_time_t sem_otime; ibcs2_time_t sem_ctime; }; struct ibcs2_sem { u_short semval; ibcs2_pid_t sempid; u_short semncnt; u_short semzcnt; }; struct ibcs2_shmid_ds { struct ibcs2_ipc_perm shm_perm; int shm_segsz; int pad1; char pad2[4]; u_short shm_lpid; u_short shm_cpid; u_short shm_nattch; u_short shm_cnattch; ibcs2_time_t shm_atime; ibcs2_time_t shm_dtime; ibcs2_time_t shm_ctime; }; Index: head/sys/i386/ibcs2/ibcs2_isc.c =================================================================== --- head/sys/i386/ibcs2/ibcs2_isc.c (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_isc.c (revision 326260) @@ -1,66 +1,68 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1994 Søren Schmidt * Copyright (c) 1994 Sean Eric Fagan * Copyright (c) 1995 Steven Wallace * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include extern struct sysent isc_sysent[]; int ibcs2_isc(struct thread *td, struct ibcs2_isc_args *uap) { struct trapframe *tf = td->td_frame; struct sysent *callp; u_int code; int error; code = (tf->tf_eax & 0xffffff00) >> 8; callp = &isc_sysent[code]; if (code < IBCS2_ISC_MAXSYSCALL) error = (*callp->sy_call)(td, (void *)uap); else error = ENOSYS; return (error); } Index: head/sys/i386/ibcs2/ibcs2_mount.h =================================================================== --- head/sys/i386/ibcs2/ibcs2_mount.h (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_mount.h (revision 326260) @@ -1,42 +1,44 @@ /* $NetBSD: ibcs2_mount.h,v 1.2 1994/10/26 02:53:00 cgd Exp $ */ /* $FreeBSD$ */ /*- + * SPDX-License-Identifier: BSD-4-Clause + * * Copyright (c) 1994 Scott Bartram * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Scott Bartram. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _IBCS2_MOUNT_H #define _IBCS2_MOUNT_H #define IBCS2_MS_RDONLY 0x01 #define IBCS2_MS_FSS 0x02 #define IBCS2_MS_DATA 0x04 #define IBCS2_MS_CACHE 0x08 #endif /* _IBCS2_MOUNT_H */ Index: head/sys/i386/ibcs2/ibcs2_msg.c =================================================================== --- head/sys/i386/ibcs2/ibcs2_msg.c (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_msg.c (revision 326260) @@ -1,58 +1,60 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1995 Steven Wallace * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * IBCS2 message compatibility module. * */ #include #include #include #include #include #include #include #include int ibcs2_getmsg(td, uap) struct thread *td; struct ibcs2_getmsg_args *uap; { return 0; /* fake */ } int ibcs2_putmsg(td, uap) struct thread *td; struct ibcs2_putmsg_args *uap; { return 0; /* fake */ } Index: head/sys/i386/ibcs2/ibcs2_other.c =================================================================== --- head/sys/i386/ibcs2/ibcs2_other.c (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_other.c (revision 326260) @@ -1,119 +1,121 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1995 Steven Wallace * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * IBCS2 compatibility module. */ #include "opt_spx_hack.h" #include #include #include #include #include #include #include #include #include #include #include #include #define IBCS2_SECURE_GETLUID 1 #define IBCS2_SECURE_SETLUID 2 int ibcs2_secure(struct thread *td, struct ibcs2_secure_args *uap) { switch (uap->cmd) { case IBCS2_SECURE_GETLUID: /* get login uid */ td->td_retval[0] = td->td_ucred->cr_uid; return 0; case IBCS2_SECURE_SETLUID: /* set login uid */ return EPERM; default: printf("IBCS2: 'secure' cmd=%d not implemented\n", uap->cmd); } return EINVAL; } int ibcs2_lseek(struct thread *td, struct ibcs2_lseek_args *uap) { struct lseek_args largs; int error; largs.fd = uap->fd; largs.offset = uap->offset; largs.whence = uap->whence; error = sys_lseek(td, &largs); return (error); } #ifdef SPX_HACK #include #include int spx_open(struct thread *td) { struct socket_args sock; struct sockaddr_un sun; int fd, error; /* obtain a socket. */ DPRINTF(("SPX: open socket\n")); sock.domain = AF_UNIX; sock.type = SOCK_STREAM; sock.protocol = 0; error = sys_socket(td, &sock); if (error) return error; fd = td->td_retval[0]; /* connect the socket to standard X socket */ DPRINTF(("SPX: connect to /tmp/X11-unix/X0\n")); sun.sun_family = AF_UNIX; strcpy(sun.sun_path, "/tmp/.X11-unix/X0"); sun.sun_len = sizeof(struct sockaddr_un) - sizeof(sun.sun_path) + strlen(sun.sun_path) + 1; error = kern_connectat(td, AT_FDCWD, fd, (struct sockaddr *)&sun); if (error) { kern_close(td, fd); return error; } td->td_retval[0] = fd; return 0; } #endif /* SPX_HACK */ Index: head/sys/i386/ibcs2/ibcs2_signal.c =================================================================== --- head/sys/i386/ibcs2/ibcs2_signal.c (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_signal.c (revision 326260) @@ -1,427 +1,429 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1995 Scott Bartram * Copyright (c) 1995 Steven Wallace * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #define sigemptyset(s) SIGEMPTYSET(*(s)) #define sigismember(s, n) SIGISMEMBER(*(s), n) #define sigaddset(s, n) SIGADDSET(*(s), n) #define ibcs2_sigmask(n) (1 << ((n) - 1)) #define ibcs2_sigemptyset(s) bzero((s), sizeof(*(s))) #define ibcs2_sigismember(s, n) (*(s) & ibcs2_sigmask(n)) #define ibcs2_sigaddset(s, n) (*(s) |= ibcs2_sigmask(n)) static void ibcs2_to_bsd_sigset(const ibcs2_sigset_t *, sigset_t *); static void bsd_to_ibcs2_sigset(const sigset_t *, ibcs2_sigset_t *); static void ibcs2_to_bsd_sigaction(struct ibcs2_sigaction *, struct sigaction *); static void bsd_to_ibcs2_sigaction(struct sigaction *, struct ibcs2_sigaction *); int bsd_to_ibcs2_sig[IBCS2_SIGTBLSZ] = { IBCS2_SIGHUP, /* 1 */ IBCS2_SIGINT, /* 2 */ IBCS2_SIGQUIT, /* 3 */ IBCS2_SIGILL, /* 4 */ IBCS2_SIGTRAP, /* 5 */ IBCS2_SIGABRT, /* 6 */ IBCS2_SIGEMT, /* 7 */ IBCS2_SIGFPE, /* 8 */ IBCS2_SIGKILL, /* 9 */ IBCS2_SIGBUS, /* 10 */ IBCS2_SIGSEGV, /* 11 */ IBCS2_SIGSYS, /* 12 */ IBCS2_SIGPIPE, /* 13 */ IBCS2_SIGALRM, /* 14 */ IBCS2_SIGTERM, /* 15 */ 0, /* 16 - SIGURG */ IBCS2_SIGSTOP, /* 17 */ IBCS2_SIGTSTP, /* 18 */ IBCS2_SIGCONT, /* 19 */ IBCS2_SIGCLD, /* 20 */ IBCS2_SIGTTIN, /* 21 */ IBCS2_SIGTTOU, /* 22 */ IBCS2_SIGPOLL, /* 23 */ 0, /* 24 - SIGXCPU */ 0, /* 25 - SIGXFSZ */ IBCS2_SIGVTALRM, /* 26 */ IBCS2_SIGPROF, /* 27 */ IBCS2_SIGWINCH, /* 28 */ 0, /* 29 */ IBCS2_SIGUSR1, /* 30 */ IBCS2_SIGUSR2, /* 31 */ 0 /* 32 */ }; static int ibcs2_to_bsd_sig[IBCS2_SIGTBLSZ] = { SIGHUP, /* 1 */ SIGINT, /* 2 */ SIGQUIT, /* 3 */ SIGILL, /* 4 */ SIGTRAP, /* 5 */ SIGABRT, /* 6 */ SIGEMT, /* 7 */ SIGFPE, /* 8 */ SIGKILL, /* 9 */ SIGBUS, /* 10 */ SIGSEGV, /* 11 */ SIGSYS, /* 12 */ SIGPIPE, /* 13 */ SIGALRM, /* 14 */ SIGTERM, /* 15 */ SIGUSR1, /* 16 */ SIGUSR2, /* 17 */ SIGCHLD, /* 18 */ 0, /* 19 - SIGPWR */ SIGWINCH, /* 20 */ 0, /* 21 */ SIGIO, /* 22 */ SIGSTOP, /* 23 */ SIGTSTP, /* 24 */ SIGCONT, /* 25 */ SIGTTIN, /* 26 */ SIGTTOU, /* 27 */ SIGVTALRM, /* 28 */ SIGPROF, /* 29 */ 0, /* 30 */ 0, /* 31 */ 0 /* 32 */ }; void ibcs2_to_bsd_sigset(iss, bss) const ibcs2_sigset_t *iss; sigset_t *bss; { int i, newsig; sigemptyset(bss); for (i = 1; i <= IBCS2_SIGTBLSZ; i++) { if (ibcs2_sigismember(iss, i)) { newsig = ibcs2_to_bsd_sig[_SIG_IDX(i)]; if (newsig) sigaddset(bss, newsig); } } } static void bsd_to_ibcs2_sigset(bss, iss) const sigset_t *bss; ibcs2_sigset_t *iss; { int i, newsig; ibcs2_sigemptyset(iss); for (i = 1; i <= IBCS2_SIGTBLSZ; i++) { if (sigismember(bss, i)) { newsig = bsd_to_ibcs2_sig[_SIG_IDX(i)]; if (newsig) ibcs2_sigaddset(iss, newsig); } } } static void ibcs2_to_bsd_sigaction(isa, bsa) struct ibcs2_sigaction *isa; struct sigaction *bsa; { bsa->sa_handler = isa->isa_handler; ibcs2_to_bsd_sigset(&isa->isa_mask, &bsa->sa_mask); bsa->sa_flags = 0; /* ??? SA_NODEFER */ if ((isa->isa_flags & IBCS2_SA_NOCLDSTOP) != 0) bsa->sa_flags |= SA_NOCLDSTOP; } static void bsd_to_ibcs2_sigaction(bsa, isa) struct sigaction *bsa; struct ibcs2_sigaction *isa; { isa->isa_handler = bsa->sa_handler; bsd_to_ibcs2_sigset(&bsa->sa_mask, &isa->isa_mask); isa->isa_flags = 0; if ((bsa->sa_flags & SA_NOCLDSTOP) != 0) isa->isa_flags |= IBCS2_SA_NOCLDSTOP; } int ibcs2_sigaction(struct thread *td, struct ibcs2_sigaction_args *uap) { struct ibcs2_sigaction isa; struct sigaction nbsa, obsa; struct sigaction *nbsap; int error; if (uap->act != NULL) { if ((error = copyin(uap->act, &isa, sizeof(isa))) != 0) return (error); ibcs2_to_bsd_sigaction(&isa, &nbsa); nbsap = &nbsa; } else nbsap = NULL; if (uap->sig <= 0 || uap->sig > IBCS2_NSIG) return (EINVAL); error = kern_sigaction(td, ibcs2_to_bsd_sig[_SIG_IDX(uap->sig)], &nbsa, &obsa, 0); if (error == 0 && uap->oact != NULL) { bsd_to_ibcs2_sigaction(&obsa, &isa); error = copyout(&isa, uap->oact, sizeof(isa)); } return (error); } int ibcs2_sigsys(struct thread *td, struct ibcs2_sigsys_args *uap) { struct proc *p = td->td_proc; struct sigaction sa; int signum = IBCS2_SIGNO(uap->sig); int error; if (signum <= 0 || signum > IBCS2_NSIG) { if (IBCS2_SIGCALL(uap->sig) == IBCS2_SIGNAL_MASK || IBCS2_SIGCALL(uap->sig) == IBCS2_SIGSET_MASK) td->td_retval[0] = (int)IBCS2_SIG_ERR; return EINVAL; } signum = ibcs2_to_bsd_sig[_SIG_IDX(signum)]; switch (IBCS2_SIGCALL(uap->sig)) { case IBCS2_SIGSET_MASK: /* * Check for SIG_HOLD action. * Otherwise, perform signal() except with different sa_flags. */ if (uap->fp != IBCS2_SIG_HOLD) { /* add sig to mask before exececuting signal handler */ sa.sa_flags = 0; goto ibcs2_sigset; } /* else FALLTHROUGH to sighold */ case IBCS2_SIGHOLD_MASK: { sigset_t mask; SIGEMPTYSET(mask); SIGADDSET(mask, signum); return (kern_sigprocmask(td, SIG_BLOCK, &mask, NULL, 0)); } case IBCS2_SIGNAL_MASK: { struct sigaction osa; /* do not automatically block signal */ sa.sa_flags = SA_NODEFER; #ifdef SA_RESETHAND if((signum != IBCS2_SIGILL) && (signum != IBCS2_SIGTRAP) && (signum != IBCS2_SIGPWR)) /* set to SIG_DFL before executing handler */ sa.sa_flags |= SA_RESETHAND; #endif ibcs2_sigset: sa.sa_handler = uap->fp; sigemptyset(&sa.sa_mask); #if 0 if (signum != SIGALRM) sa.sa_flags |= SA_RESTART; #endif error = kern_sigaction(td, signum, &sa, &osa, 0); if (error != 0) { DPRINTF(("signal: sigaction failed: %d\n", error)); td->td_retval[0] = (int)IBCS2_SIG_ERR; return (error); } td->td_retval[0] = (int)osa.sa_handler; /* special sigset() check */ if(IBCS2_SIGCALL(uap->sig) == IBCS2_SIGSET_MASK) { PROC_LOCK(p); /* check to make sure signal is not blocked */ if(sigismember(&td->td_sigmask, signum)) { /* return SIG_HOLD and unblock signal*/ td->td_retval[0] = (int)IBCS2_SIG_HOLD; SIGDELSET(td->td_sigmask, signum); signotify(td); } PROC_UNLOCK(p); } return 0; } case IBCS2_SIGRELSE_MASK: { sigset_t mask; SIGEMPTYSET(mask); SIGADDSET(mask, signum); return (kern_sigprocmask(td, SIG_UNBLOCK, &mask, NULL, 0)); } case IBCS2_SIGIGNORE_MASK: { sa.sa_handler = SIG_IGN; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; error = kern_sigaction(td, signum, &sa, NULL, 0); if (error != 0) DPRINTF(("sigignore: sigaction failed\n")); return (error); } case IBCS2_SIGPAUSE_MASK: { sigset_t mask; PROC_LOCK(p); mask = td->td_sigmask; PROC_UNLOCK(p); SIGDELSET(mask, signum); return kern_sigsuspend(td, mask); } default: return ENOSYS; } } int ibcs2_sigprocmask(struct thread *td, struct ibcs2_sigprocmask_args *uap) { ibcs2_sigset_t iss; sigset_t oss, nss; sigset_t *nssp; int error, how; switch (uap->how) { case IBCS2_SIG_BLOCK: how = SIG_BLOCK; break; case IBCS2_SIG_UNBLOCK: how = SIG_UNBLOCK; break; case IBCS2_SIG_SETMASK: how = SIG_SETMASK; break; default: return (EINVAL); } if (uap->set != NULL) { if ((error = copyin(uap->set, &iss, sizeof(iss))) != 0) return error; ibcs2_to_bsd_sigset(&iss, &nss); nssp = &nss; } else nssp = NULL; error = kern_sigprocmask(td, how, nssp, &oss, 0); if (error == 0 && uap->oset != NULL) { bsd_to_ibcs2_sigset(&oss, &iss); error = copyout(&iss, uap->oset, sizeof(iss)); } return (error); } int ibcs2_sigpending(struct thread *td, struct ibcs2_sigpending_args *uap) { struct proc *p = td->td_proc; sigset_t bss; ibcs2_sigset_t iss; PROC_LOCK(p); bss = td->td_siglist; SIGSETOR(bss, p->p_siglist); SIGSETAND(bss, td->td_sigmask); PROC_UNLOCK(p); bsd_to_ibcs2_sigset(&bss, &iss); return copyout(&iss, uap->mask, sizeof(iss)); } int ibcs2_sigsuspend(struct thread *td, struct ibcs2_sigsuspend_args *uap) { ibcs2_sigset_t sss; sigset_t bss; int error; if ((error = copyin(uap->mask, &sss, sizeof(sss))) != 0) return error; ibcs2_to_bsd_sigset(&sss, &bss); return kern_sigsuspend(td, bss); } int ibcs2_pause(struct thread *td, struct ibcs2_pause_args *uap) { sigset_t mask; PROC_LOCK(td->td_proc); mask = td->td_sigmask; PROC_UNLOCK(td->td_proc); return kern_sigsuspend(td, mask); } int ibcs2_kill(struct thread *td, struct ibcs2_kill_args *uap) { struct kill_args ka; if (uap->signo <= 0 || uap->signo > IBCS2_NSIG) return (EINVAL); ka.pid = uap->pid; ka.signum = ibcs2_to_bsd_sig[_SIG_IDX(uap->signo)]; return sys_kill(td, &ka); } Index: head/sys/i386/ibcs2/ibcs2_signal.h =================================================================== --- head/sys/i386/ibcs2/ibcs2_signal.h (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_signal.h (revision 326260) @@ -1,110 +1,112 @@ /* $NetBSD: ibcs2_signal.h,v 1.7 1995/08/14 02:26:01 mycroft Exp $ */ /*- + * SPDX-License-Identifier: BSD-4-Clause + * * Copyright (c) 1994, 1995 Scott Bartram * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Scott Bartram. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _IBCS2_SIGNAL_H #define _IBCS2_SIGNAL_H #define IBCS2_SIGHUP 1 #define IBCS2_SIGINT 2 #define IBCS2_SIGQUIT 3 #define IBCS2_SIGILL 4 #define IBCS2_SIGTRAP 5 #define IBCS2_SIGIOT 6 #define IBCS2_SIGABRT 6 #define IBCS2_SIGEMT 7 #define IBCS2_SIGFPE 8 #define IBCS2_SIGKILL 9 #define IBCS2_SIGBUS 10 #define IBCS2_SIGSEGV 11 #define IBCS2_SIGSYS 12 #define IBCS2_SIGPIPE 13 #define IBCS2_SIGALRM 14 #define IBCS2_SIGTERM 15 #define IBCS2_SIGUSR1 16 #define IBCS2_SIGUSR2 17 #define IBCS2_SIGCLD 18 #define IBCS2_SIGPWR 19 #define IBCS2_SIGWINCH 20 #define IBCS2_SIGPOLL 22 #define IBCS2_NSIG 32 #define IBCS2_SIGTBLSZ 32 /* * SCO-specific */ #define IBCS2_SIGSTOP 23 #define IBCS2_SIGTSTP 24 #define IBCS2_SIGCONT 25 #define IBCS2_SIGTTIN 26 #define IBCS2_SIGTTOU 27 #define IBCS2_SIGVTALRM 28 #define IBCS2_SIGPROF 29 #define IBCS2_SIGNO_MASK 0x00FF #define IBCS2_SIGNAL_MASK 0x0000 #define IBCS2_SIGSET_MASK 0x0100 #define IBCS2_SIGHOLD_MASK 0x0200 #define IBCS2_SIGRELSE_MASK 0x0400 #define IBCS2_SIGIGNORE_MASK 0x0800 #define IBCS2_SIGPAUSE_MASK 0x1000 #define IBCS2_SIGNO(x) ((x) & IBCS2_SIGNO_MASK) #define IBCS2_SIGCALL(x) ((x) & ~IBCS2_SIGNO_MASK) typedef long ibcs2_sigset_t; typedef void (*ibcs2_sig_t)(int); struct ibcs2_sigaction { ibcs2_sig_t isa_handler; ibcs2_sigset_t isa_mask; int isa_flags; }; #define IBCS2_SIG_DFL ((ibcs2_sig_t)0) #define IBCS2_SIG_ERR ((ibcs2_sig_t)-1) #define IBCS2_SIG_IGN ((ibcs2_sig_t)1) #define IBCS2_SIG_HOLD ((ibcs2_sig_t)2) #define IBCS2_SIG_SETMASK 0 #define IBCS2_SIG_BLOCK 1 #define IBCS2_SIG_UNBLOCK 2 /* sa_flags */ #define IBCS2_SA_NOCLDSTOP 1 #define IBCS2_MINSIGSTKSZ 8192 extern int bsd_to_ibcs2_sig[]; #endif /* _IBCS2_SIGNAL_H */ Index: head/sys/i386/ibcs2/ibcs2_socksys.c =================================================================== --- head/sys/i386/ibcs2/ibcs2_socksys.c (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_socksys.c (revision 326260) @@ -1,204 +1,206 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1994, 1995 Scott Bartram * Copyright (c) 1994 Arne H Juul * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include /* Local structures */ struct getipdomainname_args { char *ipdomainname; int len; }; struct setipdomainname_args { char *ipdomainname; int len; }; /* Local prototypes */ static int ibcs2_getipdomainname(struct thread *, struct getipdomainname_args *); static int ibcs2_setipdomainname(struct thread *, struct setipdomainname_args *); /* * iBCS2 socksys calls. */ int ibcs2_socksys(struct thread *td, struct ibcs2_socksys_args *uap) { int error; int realargs[7]; /* 1 for command, 6 for recvfrom */ void *passargs; /* * SOCKET should only be legal on /dev/socksys. * GETIPDOMAINNAME should only be legal on /dev/socksys ? * The others are (and should be) only legal on sockets. */ if ((error = copyin(uap->argsp, (caddr_t)realargs, sizeof(realargs))) != 0) return error; DPRINTF(("ibcs2_socksys: %08x %08x %08x %08x %08x %08x %08x\n", realargs[0], realargs[1], realargs[2], realargs[3], realargs[4], realargs[5], realargs[6])); passargs = (void *)(realargs + 1); switch (realargs[0]) { case SOCKSYS_ACCEPT: return sys_accept(td, passargs); case SOCKSYS_BIND: return sys_bind(td, passargs); case SOCKSYS_CONNECT: return sys_connect(td, passargs); case SOCKSYS_GETPEERNAME: return sys_getpeername(td, passargs); case SOCKSYS_GETSOCKNAME: return sys_getsockname(td, passargs); case SOCKSYS_GETSOCKOPT: return sys_getsockopt(td, passargs); case SOCKSYS_LISTEN: return sys_listen(td, passargs); case SOCKSYS_RECV: realargs[5] = realargs[6] = 0; /* FALLTHROUGH */ case SOCKSYS_RECVFROM: return sys_recvfrom(td, passargs); case SOCKSYS_SEND: realargs[5] = realargs[6] = 0; /* FALLTHROUGH */ case SOCKSYS_SENDTO: return sys_sendto(td, passargs); case SOCKSYS_SETSOCKOPT: return sys_setsockopt(td, passargs); case SOCKSYS_SHUTDOWN: return sys_shutdown(td, passargs); case SOCKSYS_SOCKET: return sys_socket(td, passargs); case SOCKSYS_SELECT: return sys_select(td, passargs); case SOCKSYS_GETIPDOMAIN: return ibcs2_getipdomainname(td, passargs); case SOCKSYS_SETIPDOMAIN: return ibcs2_setipdomainname(td, passargs); case SOCKSYS_ADJTIME: return sys_adjtime(td, passargs); case SOCKSYS_SETREUID: return sys_setreuid(td, passargs); case SOCKSYS_SETREGID: return sys_setregid(td, passargs); case SOCKSYS_GETTIME: return sys_gettimeofday(td, passargs); case SOCKSYS_SETTIME: return sys_settimeofday(td, passargs); case SOCKSYS_GETITIMER: return sys_getitimer(td, passargs); case SOCKSYS_SETITIMER: return sys_setitimer(td, passargs); default: printf("socksys unknown %08x %08x %08x %08x %08x %08x %08x\n", realargs[0], realargs[1], realargs[2], realargs[3], realargs[4], realargs[5], realargs[6]); return EINVAL; } /* NOTREACHED */ } /* ARGSUSED */ static int ibcs2_getipdomainname(struct thread *td, struct getipdomainname_args *uap) { char hname[MAXHOSTNAMELEN], *dptr; int len; /* Get the domain name. */ getcredhostname(td->td_ucred, hname, sizeof(hname)); dptr = strchr(hname, '.'); if ( dptr ) dptr++; else /* Make it effectively an empty string */ dptr = hname + strlen(hname); len = strlen(dptr) + 1; if ((u_int)uap->len > len + 1) uap->len = len + 1; return (copyout((caddr_t)dptr, (caddr_t)uap->ipdomainname, uap->len)); } /* ARGSUSED */ static int ibcs2_setipdomainname(struct thread *td, struct setipdomainname_args *uap) { char hname[MAXHOSTNAMELEN], *ptr; int error, sctl[2], hlen; /* Get the domain name */ getcredhostname(td->td_ucred, hname, sizeof(hname)); /* W/out a hostname a domain-name is nonsense */ if ( strlen(hname) == 0 ) return EINVAL; /* Get the host's unqualified name (strip off the domain) */ ptr = strchr(hname, '.'); if ( ptr != NULL ) { ptr++; *ptr = '\0'; } else { if (strlcat(hname, ".", sizeof(hname)) >= sizeof(hname)) return (EINVAL); } /* Set ptr to the end of the string so we can append to it */ hlen = strlen(hname); ptr = hname + hlen; if ((u_int)uap->len > (sizeof (hname) - hlen - 1)) return EINVAL; /* Append the ipdomain to the end */ error = copyinstr((caddr_t)uap->ipdomainname, ptr, uap->len, NULL); if (error) return (error); /* 'sethostname' with the new information */ sctl[0] = CTL_KERN; sctl[1] = KERN_HOSTNAME; hlen = strlen(hname) + 1; return (kernel_sysctl(td, sctl, 2, 0, 0, hname, hlen, 0, 0)); } Index: head/sys/i386/ibcs2/ibcs2_socksys.h =================================================================== --- head/sys/i386/ibcs2/ibcs2_socksys.h (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_socksys.h (revision 326260) @@ -1,128 +1,130 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1994, 1995 Scott Bartram * Copyright (c) 1994 Arne H Juul * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _I386_IBCS2_IBCS2_SOCKSYS_H_ #define _I386_IBCS2_IBCS2_SOCKSYS_H_ #include #include #define SOCKSYS_ACCEPT 1 #define SOCKSYS_BIND 2 #define SOCKSYS_CONNECT 3 #define SOCKSYS_GETPEERNAME 4 #define SOCKSYS_GETSOCKNAME 5 #define SOCKSYS_GETSOCKOPT 6 #define SOCKSYS_LISTEN 7 #define SOCKSYS_RECV 8 #define SOCKSYS_RECVFROM 9 #define SOCKSYS_SEND 10 #define SOCKSYS_SENDTO 11 #define SOCKSYS_SETSOCKOPT 12 #define SOCKSYS_SHUTDOWN 13 #define SOCKSYS_SOCKET 14 #define SOCKSYS_SELECT 15 #define SOCKSYS_GETIPDOMAIN 16 #define SOCKSYS_SETIPDOMAIN 17 #define SOCKSYS_ADJTIME 18 #define SOCKSYS_SETREUID 19 #define SOCKSYS_SETREGID 20 #define SOCKSYS_GETTIME 21 #define SOCKSYS_SETTIME 22 #define SOCKSYS_GETITIMER 23 #define SOCKSYS_SETITIMER 24 #define IBCS2_SIOCSHIWAT _IOW('S', 1, int) #define IBCS2_SIOCGHIWAT _IOR('S', 2, int) #define IBCS2_SIOCSLOWAT _IOW('S', 3, int) #define IBCS2_SIOCGLOWAT _IOR('S', 4, int) #define IBCS2_SIOCATMARK _IOR('S', 5, int) #define IBCS2_SIOCSPGRP _IOW('S', 6, int) #define IBCS2_SIOCGPGRP _IOR('S', 7, int) #define IBCS2_FIONREAD _IOR('S', 8, int) #define IBCS2_FIONBIO _IOW('S', 9, int) #define IBCS2_FIOASYNC _IOW('S', 10, int) #define IBCS2_SIOCPROTO _IOW('S', 11, struct socknewproto) #define IBCS2_SIOCGETNAME _IOR('S', 12, struct sockaddr) #define IBCS2_SIOCGETPEER _IOR('S', 13, struct sockaddr) #define IBCS2_IF_UNITSEL _IOW('S', 14, int) #define IBCS2_SIOCXPROTO _IO('S', 15) #define IBCS2_SIOCADDRT _IOW('R', 9, struct rtentry) #define IBCS2_SIOCDELRT _IOW('R', 10, struct rtentry) #define IBCS2_SIOCSIFADDR _IOW('I', 11, struct ifreq) #define IBCS2_SIOCGIFADDR _IOWR('I', 12, struct ifreq) #define IBCS2_SIOCSIFDSTADDR _IOW('I', 13, struct ifreq) #define IBCS2_SIOCGIFDSTADDR _IOWR('I', 14, struct ifreq) #define IBCS2_SIOCSIFFLAGS _IOW('I', 15, struct ifreq) #define IBCS2_SIOCGIFFLAGS _IOWR('I', 16, struct ifreq) #define IBCS2_SIOCGIFCONF _IOWR('I', 17, struct ifconf) #define IBCS2_SIOCSIFMTU _IOW('I', 21, struct ifreq) #define IBCS2_SIOCGIFMTU _IOWR('I', 22, struct ifreq) #define IBCS2_SIOCIFDETACH _IOW('I', 26, struct ifreq) #define IBCS2_SIOCGENPSTATS _IOWR('I', 27, struct ifreq) #define IBCS2_SIOCX25XMT _IOWR('I', 29, struct ifreq) #define IBCS2_SIOCX25RCV _IOWR('I', 30, struct ifreq) #define IBCS2_SIOCX25TBL _IOWR('I', 31, struct ifreq) #define IBCS2_SIOCGIFBRDADDR _IOWR('I', 32, struct ifreq) #define IBCS2_SIOCSIFBRDADDR _IOW('I', 33, struct ifreq) #define IBCS2_SIOCGIFNETMASK _IOWR('I', 34, struct ifreq) #define IBCS2_SIOCSIFNETMASK _IOW('I', 35, struct ifreq) #define IBCS2_SIOCGIFMETRIC _IOWR('I', 36, struct ifreq) #define IBCS2_SIOCSIFMETRIC _IOW('I', 37, struct ifreq) #define IBCS2_SIOCSARP _IOW('I', 38, struct arpreq) #define IBCS2_SIOCGARP _IOWR('I', 39, struct arpreq) #define IBCS2_SIOCDARP _IOW('I', 40, struct arpreq) #define IBCS2_SIOCSIFNAME _IOW('I', 41, struct ifreq) #define IBCS2_SIOCGIFONEP _IOWR('I', 42, struct ifreq) #define IBCS2_SIOCSIFONEP _IOW('I', 43, struct ifreq) #define IBCS2_SIOCGENADDR _IOWR('I', 65, struct ifreq) #define IBCS2_SIOCSOCKSYS _IOW('I', 66, struct socksysreq) struct socksysreq { int realargs[7]; }; struct socknewproto { int family; int type; int proto; ibcs2_dev_t dev; int flags; }; struct ibcs2_socksys_args { int fd; int magic; caddr_t argsp; }; int ibcs2_socksys(struct thread *, struct ibcs2_socksys_args *); #endif /* !_I386_IBCS2_IBCS2_SOCKSYS_H_ */ Index: head/sys/i386/ibcs2/ibcs2_stat.c =================================================================== --- head/sys/i386/ibcs2/ibcs2_stat.c (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_stat.c (revision 326260) @@ -1,243 +1,245 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1995 Scott Bartram * Copyright (c) 1995 Steven Wallace * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void bsd_stat2ibcs_stat(struct stat *, struct ibcs2_stat *); static int cvt_statfs(struct statfs *, caddr_t, int); static void bsd_stat2ibcs_stat(st, st4) struct stat *st; struct ibcs2_stat *st4; { bzero(st4, sizeof(*st4)); st4->st_dev = (ibcs2_dev_t)st->st_dev; st4->st_ino = (ibcs2_ino_t)st->st_ino; st4->st_mode = (ibcs2_mode_t)st->st_mode; st4->st_nlink= (ibcs2_nlink_t)st->st_nlink; st4->st_uid = (ibcs2_uid_t)st->st_uid; st4->st_gid = (ibcs2_gid_t)st->st_gid; st4->st_rdev = (ibcs2_dev_t)st->st_rdev; if (st->st_size < (quad_t)1 << 32) st4->st_size = (ibcs2_off_t)st->st_size; else st4->st_size = -2; st4->st_atim = (ibcs2_time_t)st->st_atim.tv_sec; st4->st_mtim = (ibcs2_time_t)st->st_mtim.tv_sec; st4->st_ctim = (ibcs2_time_t)st->st_ctim.tv_sec; } static int cvt_statfs(sp, buf, len) struct statfs *sp; caddr_t buf; int len; { struct ibcs2_statfs ssfs; if (len < 0) return (EINVAL); else if (len > sizeof(ssfs)) len = sizeof(ssfs); bzero(&ssfs, sizeof ssfs); ssfs.f_fstyp = 0; ssfs.f_bsize = sp->f_bsize; ssfs.f_frsize = 0; ssfs.f_blocks = sp->f_blocks; ssfs.f_bfree = sp->f_bfree; ssfs.f_files = sp->f_files; ssfs.f_ffree = sp->f_ffree; ssfs.f_fname[0] = 0; ssfs.f_fpack[0] = 0; return copyout((caddr_t)&ssfs, buf, len); } int ibcs2_statfs(td, uap) struct thread *td; struct ibcs2_statfs_args *uap; { struct statfs *sf; char *path; int error; CHECKALTEXIST(td, uap->path, &path); sf = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK); error = kern_statfs(td, path, UIO_SYSSPACE, sf); free(path, M_TEMP); if (error == 0) error = cvt_statfs(sf, (caddr_t)uap->buf, uap->len); free(sf, M_STATFS); return (error); } int ibcs2_fstatfs(td, uap) struct thread *td; struct ibcs2_fstatfs_args *uap; { struct statfs *sf; int error; sf = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK); error = kern_fstatfs(td, uap->fd, sf); if (error == 0) error = cvt_statfs(sf, (caddr_t)uap->buf, uap->len); free(sf, M_STATFS); return (error); } int ibcs2_stat(td, uap) struct thread *td; struct ibcs2_stat_args *uap; { struct ibcs2_stat ibcs2_st; struct stat st; char *path; int error; CHECKALTEXIST(td, uap->path, &path); error = kern_statat(td, 0, AT_FDCWD, path, UIO_SYSSPACE, &st, NULL); free(path, M_TEMP); if (error) return (error); bsd_stat2ibcs_stat(&st, &ibcs2_st); return copyout((caddr_t)&ibcs2_st, (caddr_t)uap->st, ibcs2_stat_len); } int ibcs2_lstat(td, uap) struct thread *td; struct ibcs2_lstat_args *uap; { struct ibcs2_stat ibcs2_st; struct stat st; char *path; int error; CHECKALTEXIST(td, uap->path, &path); error = kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, path, UIO_SYSSPACE, &st, NULL); free(path, M_TEMP); if (error) return (error); bsd_stat2ibcs_stat(&st, &ibcs2_st); return copyout((caddr_t)&ibcs2_st, (caddr_t)uap->st, ibcs2_stat_len); } int ibcs2_fstat(td, uap) struct thread *td; struct ibcs2_fstat_args *uap; { struct ibcs2_stat ibcs2_st; struct stat st; int error; error = kern_fstat(td, uap->fd, &st); if (error) return (error); bsd_stat2ibcs_stat(&st, &ibcs2_st); return copyout((caddr_t)&ibcs2_st, (caddr_t)uap->st, ibcs2_stat_len); } int ibcs2_utssys(td, uap) struct thread *td; struct ibcs2_utssys_args *uap; { switch (uap->flag) { case 0: /* uname(2) */ { char machine_name[9], *p; struct ibcs2_utsname sut; bzero(&sut, ibcs2_utsname_len); strncpy(sut.sysname, IBCS2_UNAME_SYSNAME, sizeof(sut.sysname) - 1); strncpy(sut.release, IBCS2_UNAME_RELEASE, sizeof(sut.release) - 1); strncpy(sut.version, IBCS2_UNAME_VERSION, sizeof(sut.version) - 1); getcredhostname(td->td_ucred, machine_name, sizeof(machine_name) - 1); p = strchr(machine_name, '.'); if ( p ) *p = '\0'; strncpy(sut.nodename, machine_name, sizeof(sut.nodename) - 1); strncpy(sut.machine, machine, sizeof(sut.machine) - 1); DPRINTF(("IBCS2 uname: sys=%s rel=%s ver=%s node=%s mach=%s\n", sut.sysname, sut.release, sut.version, sut.nodename, sut.machine)); return copyout((caddr_t)&sut, (caddr_t)uap->a1, ibcs2_utsname_len); } case 2: /* ustat(2) */ { return ENOSYS; /* XXX - TODO */ } default: return ENOSYS; } } Index: head/sys/i386/ibcs2/ibcs2_stat.h =================================================================== --- head/sys/i386/ibcs2/ibcs2_stat.h (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_stat.h (revision 326260) @@ -1,90 +1,92 @@ /* $NetBSD: ibcs2_stat.h,v 1.2 1994/10/26 02:53:03 cgd Exp $ */ /* $FreeBSD$ */ /*- + * SPDX-License-Identifier: BSD-4-Clause + * * Copyright (c) 1994 Scott Bartram * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Scott Bartram. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _IBCS2_STAT_H #define _IBCS2_STAT_H #include struct ibcs2_stat { ibcs2_dev_t st_dev; ibcs2_ino_t st_ino; ibcs2_mode_t st_mode; ibcs2_nlink_t st_nlink; ibcs2_uid_t st_uid; ibcs2_gid_t st_gid; ibcs2_dev_t st_rdev; ibcs2_off_t st_size; ibcs2_time_t st_atim; ibcs2_time_t st_mtim; ibcs2_time_t st_ctim; }; #define ibcs2_stat_len (sizeof(struct ibcs2_stat)) #define IBCS2_S_IFMT 0xf000 #define IBCS2_S_IFIFO 0x1000 #define IBCS2_S_IFCHR 0x2000 #define IBCS2_S_IFDIR 0x4000 #define IBCS2_S_IFBLK 0x6000 #define IBCS2_S_IFREG 0x8000 #define IBCS2_S_IFSOCK 0xc000 #define IBCS2_S_IFNAM 0x5000 #define IBCS2_S_IFLNK 0xa000 #define IBCS2_S_ISUID 0x0800 #define IBCS2_S_ISGID 0x0400 #define IBCS2_S_ISVTX 0x0200 #define IBCS2_S_IRWXU 0x01c0 #define IBCS2_S_IRUSR 0x0100 #define IBCS2_S_IWUSR 0x0080 #define IBCS2_S_IXUSR 0x0040 #define IBCS2_S_IRWXG 0x0038 #define IBCS2_S_IRGRP 0x0020 #define IBCS2_S_IWGRP 0x000f #define IBCS2_S_IXGRP 0x0008 #define IBCS2_S_IRWXO 0x0007 #define IBCS2_S_IROTH 0x0004 #define IBCS2_S_IWOTH 0x0002 #define IBCS2_S_IXOTH 0x0001 #define IBCS2_S_ISFIFO(mode) (((mode) & IBCS2_S_IFMT) == IBCS2_S_IFIFO) #define IBCS2_S_ISCHR(mode) (((mode) & IBCS2_S_IFMT) == IBCS2_S_IFCHR) #define IBCS2_S_ISDIR(mode) (((mode) & IBCS2_S_IFMT) == IBCS2_S_IFDIR) #define IBCS2_S_ISBLK(mode) (((mode) & IBCS2_S_IFMT) == IBCS2_S_IFBLK) #define IBCS2_S_ISREG(mode) (((mode) & IBCS2_S_IFMT) == IBCS2_S_IFREG) #define IBCS2_S_ISSOCK(mode) (((mode) & IBCS2_S_IFMT) == IBCS2_S_IFSOCK) #endif /* _IBCS2_STAT_H */ Index: head/sys/i386/ibcs2/ibcs2_statfs.h =================================================================== --- head/sys/i386/ibcs2/ibcs2_statfs.h (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_statfs.h (revision 326260) @@ -1,49 +1,51 @@ /* $NetBSD: ibcs2_statfs.h,v 1.2 1994/10/26 02:53:06 cgd Exp $ */ /* $FreeBSD$ */ /*- + * SPDX-License-Identifier: BSD-4-Clause + * * Copyright (c) 1994 Scott Bartram * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Scott Bartram. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _IBCS2_STATFS_H #define _IBCS2_STATFS_H struct ibcs2_statfs { short f_fstyp; long f_bsize; long f_frsize; long f_blocks; long f_bfree; long f_files; long f_ffree; char f_fname[6]; char f_fpack[6]; }; #endif /* _IBCS2_STATFS_H */ Index: head/sys/i386/ibcs2/ibcs2_stropts.h =================================================================== --- head/sys/i386/ibcs2/ibcs2_stropts.h (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_stropts.h (revision 326260) @@ -1,50 +1,52 @@ /*- * ibcs2_stropts.h + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1995 Scott Bartram * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _IBCS2_STROPTS_H #define _IBCS2_STROPTS_H #define IBCS2_STR ('S'<<8) #define IBCS2_I_NREAD (IBCS2_STR|01) #define IBCS2_I_PUSH (IBCS2_STR|02) #define IBCS2_I_POP (IBCS2_STR|03) #define IBCS2_I_LOOK (IBCS2_STR|04) #define IBCS2_I_FLUSH (IBCS2_STR|05) #define IBCS2_I_SRDOPT (IBCS2_STR|06) #define IBCS2_I_GRDOPT (IBCS2_STR|07) #define IBCS2_I_STR (IBCS2_STR|010) #define IBCS2_I_SETSIG (IBCS2_STR|011) #define IBCS2_I_GETSIG (IBCS2_STR|012) #define IBCS2_I_FIND (IBCS2_STR|013) #define IBCS2_I_LINK (IBCS2_STR|014) #define IBCS2_I_UNLINK (IBCS2_STR|015) #define IBCS2_I_PEEK (IBCS2_STR|017) #define IBCS2_I_FDINSERT (IBCS2_STR|020) #define IBCS2_I_SENDFD (IBCS2_STR|021) #define IBCS2_I_RECVFD (IBCS2_STR|022) #endif /* _IBCS2_STROPTS_H */ Index: head/sys/i386/ibcs2/ibcs2_sysi86.c =================================================================== --- head/sys/i386/ibcs2/ibcs2_sysi86.c (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_sysi86.c (revision 326260) @@ -1,96 +1,98 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1994 Søren Schmidt * Copyright (c) 1995 Steven Wallace * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #define IBCS2_FP_NO 0 /* no fp support */ #define IBCS2_FP_SW 1 /* software emulator */ #define IBCS2_FP_287 2 /* 80287 FPU */ #define IBCS2_FP_387 3 /* 80387 FPU */ #define SI86_FPHW 40 #define STIME 54 #define SETNAME 56 #define SI86_MEM 65 extern int hw_float; int ibcs2_sysi86(struct thread *td, struct ibcs2_sysi86_args *args) { switch (args->cmd) { case SI86_FPHW: { /* Floating Point information */ int val, error; if (hw_float) val = IBCS2_FP_387; else val = IBCS2_FP_NO; if ((error = copyout(&val, args->arg, sizeof(val))) != 0) return error; return 0; } case STIME: /* set the system time given pointer to long */ /* gettimeofday; time.tv_sec = *args->arg; settimeofday */ return EINVAL; case SETNAME: { /* set hostname given string w/ len <= 7 chars */ int name[2]; name[0] = CTL_KERN; name[1] = KERN_HOSTNAME; return (userland_sysctl(td, name, 2, 0, 0, 0, args->arg, 7, 0, 0)); } case SI86_MEM: /* size of physical memory */ td->td_retval[0] = ctob(physmem); return 0; default: #ifdef DIAGNOSTIC printf("IBCS2: 'sysi86' function %d(0x%x) " "not implemented yet\n", args->cmd, args->cmd); #endif return EINVAL; } } Index: head/sys/i386/ibcs2/ibcs2_sysvec.c =================================================================== --- head/sys/i386/ibcs2/ibcs2_sysvec.c (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_sysvec.c (revision 326260) @@ -1,138 +1,140 @@ /*- + * SPDX-License-Identifier: BSD-4-Clause + * * Copyright (c) 1995 Steven Wallace * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Steven Wallace. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include MODULE_VERSION(ibcs2, 1); extern int bsd_to_ibcs2_errno[]; extern struct sysent ibcs2_sysent[IBCS2_SYS_MAXSYSCALL]; static int ibcs2_fixup(register_t **, struct image_params *); struct sysentvec ibcs2_svr3_sysvec = { .sv_size = nitems(ibcs2_sysent), .sv_table = ibcs2_sysent, .sv_mask = 0xff, .sv_sigsize = IBCS2_SIGTBLSZ, .sv_sigtbl = bsd_to_ibcs2_sig, .sv_errsize = ELAST + 1, .sv_errtbl = bsd_to_ibcs2_errno, .sv_transtrap = NULL, .sv_fixup = ibcs2_fixup, .sv_sendsig = sendsig, .sv_sigcode = sigcode, /* use generic trampoline */ .sv_szsigcode = &szsigcode, .sv_prepsyscall = NULL, .sv_name = "IBCS2 COFF", .sv_coredump = NULL, /* we don't have a COFF coredump function */ .sv_imgact_try = NULL, .sv_minsigstksz = IBCS2_MINSIGSTKSZ, .sv_pagesize = PAGE_SIZE, .sv_minuser = VM_MIN_ADDRESS, .sv_maxuser = VM_MAXUSER_ADDRESS, .sv_usrstack = USRSTACK, .sv_psstrings = PS_STRINGS, .sv_stackprot = VM_PROT_ALL, .sv_copyout_strings = exec_copyout_strings, .sv_setregs = exec_setregs, .sv_fixlimit = NULL, .sv_maxssiz = NULL, .sv_flags = SV_ABI_UNDEF | SV_IA32 | SV_ILP32, .sv_set_syscall_retval = cpu_set_syscall_retval, .sv_fetch_syscall_args = cpu_fetch_syscall_args, .sv_syscallnames = NULL, .sv_schedtail = NULL, .sv_thread_detach = NULL, .sv_trap = NULL, }; static int ibcs2_fixup(register_t **stack_base, struct image_params *imgp) { return (suword(--(*stack_base), imgp->args->argc)); } /* * Create an "ibcs2" module that does nothing but allow checking for * the presence of the subsystem. */ static int ibcs2_modevent(module_t mod, int type, void *unused) { struct proc *p = NULL; int rval = 0; switch(type) { case MOD_LOAD: break; case MOD_UNLOAD: /* if this was an ELF module we'd use elf_brand_inuse()... */ sx_slock(&allproc_lock); FOREACH_PROC_IN_SYSTEM(p) { if (p->p_sysent == &ibcs2_svr3_sysvec) { rval = EBUSY; break; } } sx_sunlock(&allproc_lock); break; default: rval = EOPNOTSUPP; break; } return (rval); } static moduledata_t ibcs2_mod = { "ibcs2", ibcs2_modevent, 0 }; DECLARE_MODULE_TIED(ibcs2, ibcs2_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); Index: head/sys/i386/ibcs2/ibcs2_termios.h =================================================================== --- head/sys/i386/ibcs2/ibcs2_termios.h (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_termios.h (revision 326260) @@ -1,236 +1,238 @@ /* $NetBSD: ibcs2_termios.h,v 1.3 1994/10/26 02:53:07 cgd Exp $ */ /* $FreeBSD$ */ /*- + * SPDX-License-Identifier: BSD-4-Clause + * * Copyright (c) 1994 Scott Bartram * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Scott Bartram. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _IBCS2_TERMIOS_H #define _IBCS2_TERMIOS_H 1 #include #define IBCS2_NCC 8 #define IBCS2_NCCS 13 typedef u_short ibcs2_tcflag_t; typedef u_char ibcs2_cc_t; typedef u_long ibcs2_speed_t; struct ibcs2_termio { u_short c_iflag; u_short c_oflag; u_short c_cflag; u_short c_lflag; char c_line; u_char c_cc[IBCS2_NCC]; }; struct ibcs2_termios { ibcs2_tcflag_t c_iflag; ibcs2_tcflag_t c_oflag; ibcs2_tcflag_t c_cflag; ibcs2_tcflag_t c_lflag; char c_line; ibcs2_cc_t c_cc[IBCS2_NCCS]; char c_ispeed; char c_ospeed; }; #define IBCS2_VINTR 0 #define IBCS2_VQUIT 1 #define IBCS2_VERASE 2 #define IBCS2_VKILL 3 #define IBCS2_VEOF 4 #define IBCS2_VEOL 5 #define IBCS2_VEOL2 6 #define IBCS2_VMIN 4 #define IBCS2_VTIME 5 #define IBCS2_VSWTCH 7 #define IBCS2_VSUSP 10 #define IBCS2_VSTART 11 #define IBCS2_VSTOP 12 #define IBCS2_CNUL 0 #define IBCS2_CDEL 0377 #define IBCS2_CESC '\\' #define IBCS2_CINTR 0177 #define IBCS2_CQUIT 034 #define IBCS2_CERASE '#' #define IBCS2_CKILL '@' #define IBCS2_CSTART 021 #define IBCS2_CSTOP 023 #define IBCS2_CSWTCH 032 #define IBCS2_CNSWTCH 0 #define IBCS2_CSUSP 032 #define IBCS2_IGNBRK 0000001 #define IBCS2_BRKINT 0000002 #define IBCS2_IGNPAR 0000004 #define IBCS2_PARMRK 0000010 #define IBCS2_INPCK 0000020 #define IBCS2_ISTRIP 0000040 #define IBCS2_INLCR 0000100 #define IBCS2_IGNCR 0000200 #define IBCS2_ICRNL 0000400 #define IBCS2_IUCLC 0001000 #define IBCS2_IXON 0002000 #define IBCS2_IXANY 0004000 #define IBCS2_IXOFF 0010000 #define IBCS2_IMAXBEL 0020000 #define IBCS2_DOSMODE 0100000 #define IBCS2_OPOST 0000001 #define IBCS2_OLCUC 0000002 #define IBCS2_ONLCR 0000004 #define IBCS2_OCRNL 0000010 #define IBCS2_ONOCR 0000020 #define IBCS2_ONLRET 0000040 #define IBCS2_OFILL 0000100 #define IBCS2_OFDEL 0000200 #define IBCS2_NLDLY 0000400 #define IBCS2_NL0 0000000 #define IBCS2_NL1 0000400 #define IBCS2_CRDLY 0003000 #define IBCS2_CR0 0000000 #define IBCS2_CR1 0001000 #define IBCS2_CR2 0002000 #define IBCS2_CR3 0003000 #define IBCS2_TABDLY 0014000 #define IBCS2_TAB0 0000000 #define IBCS2_TAB1 0004000 #define IBCS2_TAB2 0010000 #define IBCS2_TAB3 0014000 #define IBCS2_BSDLY 0020000 #define IBCS2_BS0 0000000 #define IBCS2_BS1 0020000 #define IBCS2_VTDLY 0040000 #define IBCS2_VT0 0000000 #define IBCS2_VT1 0040000 #define IBCS2_FFDLY 0100000 #define IBCS2_FF0 0000000 #define IBCS2_FF1 0100000 #define IBCS2_CBAUD 0000017 #define IBCS2_CSIZE 0000060 #define IBCS2_CS5 0000000 #define IBCS2_CS6 0000020 #define IBCS2_CS7 0000040 #define IBCS2_CS8 0000060 #define IBCS2_CSTOPB 0000100 #define IBCS2_CREAD 0000200 #define IBCS2_PARENB 0000400 #define IBCS2_PARODD 0001000 #define IBCS2_HUPCL 0002000 #define IBCS2_CLOCAL 0004000 #define IBCS2_RCV1EN 0010000 #define IBCS2_XMT1EN 0020000 #define IBCS2_LOBLK 0040000 #define IBCS2_XCLUDE 0100000 #define IBCS2_ISIG 0000001 #define IBCS2_ICANON 0000002 #define IBCS2_XCASE 0000004 #define IBCS2_ECHO 0000010 #define IBCS2_ECHOE 0000020 #define IBCS2_ECHOK 0000040 #define IBCS2_ECHONL 0000100 #define IBCS2_NOFLSH 0000200 #define IBCS2_IEXTEN 0000400 #define IBCS2_TOSTOP 0001000 #define IBCS2_XIOC (('i'<<24)|('X'<<16)) #define IBCS2_XCGETA (IBCS2_XIOC|1) #define IBCS2_XCSETA (IBCS2_XIOC|2) #define IBCS2_XCSETAW (IBCS2_XIOC|3) #define IBCS2_XCSETAF (IBCS2_XIOC|4) #define IBCS2_OXIOC ('x'<<8) #define IBCS2_OXCGETA (IBCS2_OXIOC|1) #define IBCS2_OXCSETA (IBCS2_OXIOC|2) #define IBCS2_OXCSETAW (IBCS2_OXIOC|3) #define IBCS2_OXCSETAF (IBCS2_OXIOC|4) #define IBCS2_TIOC ('T'<<8) #define IBCS2_TCGETA (IBCS2_TIOC|1) #define IBCS2_TCSETA (IBCS2_TIOC|2) #define IBCS2_TCSETAW (IBCS2_TIOC|3) #define IBCS2_TCSETAF (IBCS2_TIOC|4) #define IBCS2_TCSBRK (IBCS2_TIOC|5) #define IBCS2_TCXONC (IBCS2_TIOC|6) #define IBCS2_TCFLSH (IBCS2_TIOC|7) #define IBCS2_TCGETSC (IBCS2_TIOC|34) #define IBCS2_TCSETSC (IBCS2_TIOC|35) #define IBCS2_TIOCSWINSZ (IBCS2_TIOC|103) #define IBCS2_TIOCGWINSZ (IBCS2_TIOC|104) #define IBCS2_TIOCSPGRP (IBCS2_TIOC|118) #define IBCS2_TIOCGPGRP (IBCS2_TIOC|119) #define IBCS2_TCSANOW IBCS2_XCSETA #define IBCS2_TCSADRAIN IBCS2_XCSETAW #define IBCS2_TCSAFLUSH IBCS2_XCSETAF #define IBCS2_TCSADFLUSH IBCS2_XCSETAF #define IBCS2_TCIFLUSH 0 #define IBCS2_TCOFLUSH 1 #define IBCS2_TCIOFLUSH 2 #define IBCS2_TCOOFF 0 #define IBCS2_TCOON 1 #define IBCS2_TCIOFF 2 #define IBCS2_TCION 3 #define IBCS2_B0 0 #define IBCS2_B50 1 #define IBCS2_B75 2 #define IBCS2_B110 3 #define IBCS2_B134 4 #define IBCS2_B150 5 #define IBCS2_B200 6 #define IBCS2_B300 7 #define IBCS2_B600 8 #define IBCS2_B1200 9 #define IBCS2_B1800 10 #define IBCS2_B2400 11 #define IBCS2_B4800 12 #define IBCS2_B9600 13 #define IBCS2_B19200 14 #define IBCS2_B38400 15 struct ibcs2_winsize { u_short ws_row; u_short ws_col; u_short ws_xpixel; u_short ws_ypixel; }; #endif /* _IBCS2_H_ */ Index: head/sys/i386/ibcs2/ibcs2_time.h =================================================================== --- head/sys/i386/ibcs2/ibcs2_time.h (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_time.h (revision 326260) @@ -1,51 +1,53 @@ /* $NetBSD: ibcs2_time.h,v 1.2 1994/10/26 02:53:08 cgd Exp $ */ /* $FreeBSD$ */ /*- + * SPDX-License-Identifier: BSD-4-Clause + * * Copyright (c) 1994 Scott Bartram * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Scott Bartram. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _IBCS2_TIME_H #define _IBCS2_TIME_H #include struct ibcs2_tm { int tm_sec; int tm_min; int tm_hour; int tm_mday; int tm_mon; int tm_year; int tm_wday; int tm_yday; int tm_isdst; }; #endif /* _IBCS2_TIME_H */ Index: head/sys/i386/ibcs2/ibcs2_types.h =================================================================== --- head/sys/i386/ibcs2/ibcs2_types.h (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_types.h (revision 326260) @@ -1,55 +1,57 @@ /* $NetBSD: ibcs2_types.h,v 1.5 1995/08/14 01:11:54 mycroft Exp $ */ /* $FreeBSD$ */ /*- + * SPDX-License-Identifier: BSD-4-Clause + * * Copyright (c) 1994 Scott Bartram * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Scott Bartram. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _IBCS2_TYPES_H #define _IBCS2_TYPES_H typedef unsigned char ibcs2_uchar_t; typedef unsigned long ibcs2_ulong_t; typedef char * ibcs2_caddr_t; typedef long ibcs2_daddr_t; typedef long ibcs2_off_t; typedef long ibcs2_key_t; typedef unsigned short ibcs2_uid_t; typedef unsigned short ibcs2_gid_t; typedef short ibcs2_nlink_t; typedef short ibcs2_dev_t; typedef unsigned short ibcs2_ino_t; typedef unsigned int ibcs2_size_t; typedef long ibcs2_time_t; typedef long ibcs2_clock_t; typedef unsigned short ibcs2_mode_t; typedef short ibcs2_pid_t; #endif /* _IBCS2_TYPES_H */ Index: head/sys/i386/ibcs2/ibcs2_unistd.h =================================================================== --- head/sys/i386/ibcs2/ibcs2_unistd.h (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_unistd.h (revision 326260) @@ -1,76 +1,78 @@ /* $NetBSD: ibcs2_unistd.h,v 1.2 1994/10/26 02:53:11 cgd Exp $ */ /* $FreeBSD$ */ /*- + * SPDX-License-Identifier: BSD-4-Clause + * * Copyright (c) 1994 Scott Bartram * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Scott Bartram. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _IBCS2_UNISTD_H #define _IBCS2_UNISTD_H #define IBCS2_R_OK 4 #define IBCS2_W_OK 2 #define IBCS2_X_OK 1 #define IBCS2_F_OK 0 #define IBCS2_F_ULOCK 0 #define IBCS2_F_LOCK 1 #define IBCS2_F_TLOCK 2 #define IBCS2_F_TEST 3 #define IBCS2_SEEK_SET 0 #define IBCS2_SEEK_CUR 1 #define IBCS2_SEEK_END 2 #define IBCS2_SC_ARG_MAX 0 #define IBCS2_SC_CHILD_MAX 1 #define IBCS2_SC_CLK_TCK 2 #define IBCS2_SC_NGROUPS_MAX 3 #define IBCS2_SC_OPEN_MAX 4 #define IBCS2_SC_JOB_CONTROL 5 #define IBCS2_SC_SAVED_IDS 6 #define IBCS2_SC_VERSION 7 #define IBCS2_SC_PASS_MAX 8 #define IBCS2_SC_XOPEN_VERSION 9 #define IBCS2_PC_LINK_MAX 0 #define IBCS2_PC_MAX_CANON 1 #define IBCS2_PC_MAX_INPUT 2 #define IBCS2_PC_NAME_MAX 3 #define IBCS2_PC_PATH_MAX 4 #define IBCS2_PC_PIPE_BUF 5 #define IBCS2_PC_CHOWN_RESTRICTED 6 #define IBCS2_PC_NO_TRUNC 7 #define IBCS2_PC_VDISABLE 8 #define IBCS2_STDIN_FILENO 0 #define IBCS2_STDOUT_FILENO 1 #define IBCS2_STDERR_FILENO 2 #endif /* _IBCS2_UNISTD_H */ Index: head/sys/i386/ibcs2/ibcs2_ustat.h =================================================================== --- head/sys/i386/ibcs2/ibcs2_ustat.h (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_ustat.h (revision 326260) @@ -1,47 +1,49 @@ /* $NetBSD: ibcs2_ustat.h,v 1.2 1994/10/26 02:53:13 cgd Exp $ */ /* $FreeBSD$ */ /*- + * SPDX-License-Identifier: BSD-4-Clause + * * Copyright (c) 1994 Scott Bartram * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Scott Bartram. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _IBCS2_USTAT_H #define _IBCS2_USTAT_H 1 #include struct ibcs2_ustat { long f_tfree; ibcs2_ino_t f_tinode; char f_fname[6]; char f_fpack[6]; }; #define ibcs2_ustat_len (sizeof(struct ibcs2_ustat)) #endif /* _IBCS2_USTAT_H */ Index: head/sys/i386/ibcs2/ibcs2_util.c =================================================================== --- head/sys/i386/ibcs2/ibcs2_util.c (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_util.c (revision 326260) @@ -1,60 +1,62 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1994 Christos Zoulas * Copyright (c) 1995 Frank van der Linden * Copyright (c) 1995 Scott Bartram * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * from: svr4_util.c,v 1.5 1995/01/22 23:44:50 christos Exp */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include const char ibcs2_emul_path[] = "/compat/ibcs2"; /* * Search an alternate path before passing pathname arguments on * to system calls. Useful for keeping a separate 'emulation tree'. * * If cflag is set, we check if an attempt can be made to create * the named file, i.e. we check if the directory it should * be in exists. */ int ibcs2_emul_find(struct thread *td, char *path, enum uio_seg pathseg, char **pbuf, int cflag) { return (kern_alternate_path(td, ibcs2_emul_path, path, pathseg, pbuf, cflag, AT_FDCWD)); } Index: head/sys/i386/ibcs2/ibcs2_util.h =================================================================== --- head/sys/i386/ibcs2/ibcs2_util.h (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_util.h (revision 326260) @@ -1,72 +1,74 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1994 Christos Zoulas * Copyright (c) 1995 Frank van der Linden * Copyright (c) 1995 Scott Bartram * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * from: svr4_util.h,v 1.5 1994/11/18 02:54:31 christos Exp * from: linux_util.h,v 1.2 1995/03/05 23:23:50 fvdl Exp * * $FreeBSD$ */ /* * This file is pretty much the same as Christos' svr4_util.h * (for now). */ #ifndef _IBCS2_UTIL_H_ #define _IBCS2_UTIL_H_ #include #include #ifdef DEBUG_IBCS2 #define DPRINTF(a) printf a; #else #define DPRINTF(a) #endif extern const char ibcs2_emul_path[]; int ibcs2_emul_find(struct thread *, char *, enum uio_seg, char **, int); #define CHECKALT(td, upath, pathp, i) \ do { \ int _error; \ \ _error = ibcs2_emul_find(td, upath, UIO_USERSPACE, pathp, i); \ if (*(pathp) == NULL) \ return (_error); \ } while (0) #define CHECKALTEXIST(td, upath, pathp) CHECKALT(td, upath, pathp, 0) #define CHECKALTCREAT(td, upath, pathp) CHECKALT(td, upath, pathp, 1) #ifdef SPX_HACK int spx_open(struct thread *td); #endif #endif /* !_IBCS2_UTIL_H_ */ Index: head/sys/i386/ibcs2/ibcs2_utime.h =================================================================== --- head/sys/i386/ibcs2/ibcs2_utime.h (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_utime.h (revision 326260) @@ -1,43 +1,45 @@ /*- + * SPDX-License-Identifier: BSD-4-Clause + * * Copyright (c) 1995 Scott Bartram * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Scott Bartram. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _IBCS2_UTIME_H #define _IBCS2_UTIME_H #include struct ibcs2_utimbuf { ibcs2_time_t actime; ibcs2_time_t modtime; }; #endif /* _IBCS2_UTIME_H */ Index: head/sys/i386/ibcs2/ibcs2_utsname.h =================================================================== --- head/sys/i386/ibcs2/ibcs2_utsname.h (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_utsname.h (revision 326260) @@ -1,58 +1,60 @@ /* $NetBSD: ibcs2_utsname.h,v 1.2 1994/10/26 02:53:14 cgd Exp $ */ /* $FreeBSD$ */ /*- + * SPDX-License-Identifier: BSD-4-Clause + * * Copyright (c) 1994 Scott Bartram * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Scott Bartram. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _IBCS2_UTSNAME_H #define _IBCS2_UTSNAME_H #ifndef IBCS2_UNAME_SYSNAME #define IBCS2_UNAME_SYSNAME ostype #endif #ifndef IBCS2_UNAME_RELEASE #define IBCS2_UNAME_RELEASE "3.2" #endif #ifndef IBCS2_UNAME_VERSION #define IBCS2_UNAME_VERSION "2.0" #endif struct ibcs2_utsname { char sysname[9]; char nodename[9]; char release[9]; char version[9]; char machine[9]; }; #define ibcs2_utsname_len (sizeof(struct ibcs2_utsname)) #endif /* _IBCS2_UTSNAME_H */ Index: head/sys/i386/ibcs2/ibcs2_xenix.c =================================================================== --- head/sys/i386/ibcs2/ibcs2_xenix.c (revision 326259) +++ head/sys/i386/ibcs2/ibcs2_xenix.c (revision 326260) @@ -1,217 +1,219 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1994 Sean Eric Fagan * Copyright (c) 1994 Søren Schmidt * Copyright (c) 1995 Steven Wallace * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern struct sysent xenix_sysent[]; int ibcs2_xenix(struct thread *td, struct ibcs2_xenix_args *uap) { struct trapframe *tf = td->td_frame; struct sysent *callp; u_int code; int error; code = (tf->tf_eax & 0xff00) >> 8; callp = &xenix_sysent[code]; if (code < IBCS2_XENIX_MAXSYSCALL) error = ((*callp->sy_call)(td, (void *)uap)); else error = ENOSYS; return (error); } int xenix_rdchk(td, uap) struct thread *td; struct xenix_rdchk_args *uap; { int data, error; DPRINTF(("IBCS2: 'xenix rdchk'\n")); error = kern_ioctl(td, uap->fd, FIONREAD, (caddr_t)&data); if (error) return (error); td->td_retval[0] = data ? 1 : 0; return (0); } int xenix_chsize(td, uap) struct thread *td; struct xenix_chsize_args *uap; { struct ftruncate_args sa; DPRINTF(("IBCS2: 'xenix chsize'\n")); sa.fd = uap->fd; sa.length = uap->size; return sys_ftruncate(td, &sa); } int xenix_ftime(td, uap) struct thread *td; struct xenix_ftime_args *uap; { struct timeval tv; struct ibcs2_timeb { unsigned long time __packed; unsigned short millitm; short timezone; short dstflag; } itb; DPRINTF(("IBCS2: 'xenix ftime'\n")); microtime(&tv); itb.time = tv.tv_sec; itb.millitm = (tv.tv_usec / 1000); itb.timezone = tz_minuteswest; itb.dstflag = tz_dsttime != DST_NONE; return copyout((caddr_t)&itb, (caddr_t)uap->tp, sizeof(struct ibcs2_timeb)); } int xenix_nap(struct thread *td, struct xenix_nap_args *uap) { long period; DPRINTF(("IBCS2: 'xenix nap %d ms'\n", uap->millisec)); period = (long)uap->millisec / (1000/hz); if (period) pause("nap", period); return 0; } int xenix_utsname(struct thread *td, struct xenix_utsname_args *uap) { struct ibcs2_sco_utsname { char sysname[9]; char nodename[9]; char release[16]; char kernelid[20]; char machine[9]; char bustype[9]; char sysserial[10]; unsigned short sysorigin; unsigned short sysoem; char numusers[9]; unsigned short numcpu; } ibcs2_sco_uname; DPRINTF(("IBCS2: 'xenix sco_utsname'\n")); bzero(&ibcs2_sco_uname, sizeof(struct ibcs2_sco_utsname)); strncpy(ibcs2_sco_uname.sysname, ostype, sizeof(ibcs2_sco_uname.sysname) - 1); getcredhostname(td->td_ucred, ibcs2_sco_uname.nodename, sizeof(ibcs2_sco_uname.nodename) - 1); strncpy(ibcs2_sco_uname.release, osrelease, sizeof(ibcs2_sco_uname.release) - 1); strncpy(ibcs2_sco_uname.kernelid, version, sizeof(ibcs2_sco_uname.kernelid) - 1); strncpy(ibcs2_sco_uname.machine, machine, sizeof(ibcs2_sco_uname.machine) - 1); strncpy(ibcs2_sco_uname.bustype, "ISA/EISA", sizeof(ibcs2_sco_uname.bustype) - 1); strncpy(ibcs2_sco_uname.sysserial, "no charge", sizeof(ibcs2_sco_uname.sysserial) - 1); strncpy(ibcs2_sco_uname.numusers, "unlim", sizeof(ibcs2_sco_uname.numusers) - 1); ibcs2_sco_uname.sysorigin = 0xFFFF; ibcs2_sco_uname.sysoem = 0xFFFF; ibcs2_sco_uname.numcpu = 1; return copyout((caddr_t)&ibcs2_sco_uname, (caddr_t)(void *)(intptr_t)uap->addr, sizeof(struct ibcs2_sco_utsname)); } int xenix_scoinfo(struct thread *td, struct xenix_scoinfo_args *uap) { /* scoinfo (not documented) */ td->td_retval[0] = 0; return 0; } int xenix_eaccess(struct thread *td, struct xenix_eaccess_args *uap) { char *path; int error, bsd_flags; bsd_flags = 0; if (uap->flags & IBCS2_R_OK) bsd_flags |= R_OK; if (uap->flags & IBCS2_W_OK) bsd_flags |= W_OK; if (uap->flags & IBCS2_X_OK) bsd_flags |= X_OK; CHECKALTEXIST(td, uap->path, &path); error = kern_accessat(td, AT_FDCWD, path, UIO_SYSSPACE, AT_EACCESS, bsd_flags); free(path, M_TEMP); return (error); } Index: head/sys/i386/ibcs2/imgact_coff.c =================================================================== --- head/sys/i386/ibcs2/imgact_coff.c (revision 326259) +++ head/sys/i386/ibcs2/imgact_coff.c (revision 326260) @@ -1,493 +1,495 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1994 Sean Eric Fagan * Copyright (c) 1994 Søren Schmidt * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include MODULE_DEPEND(coff, ibcs2, 1, 1, 1); extern struct sysentvec ibcs2_svr3_sysvec; static int coff_load_file(struct thread *td, char *name); static int exec_coff_imgact(struct image_params *imgp); static int load_coff_section(struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot); static int load_coff_section(struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot) { size_t map_len; vm_offset_t map_offset; vm_offset_t map_addr; int error; unsigned char *data_buf = NULL; size_t copy_len; map_offset = trunc_page(offset); map_addr = trunc_page((vm_offset_t)vmaddr); if (memsz > filsz) { /* * We have the stupid situation that * the section is longer than it is on file, * which means it has zero-filled areas, and * we have to work for it. Stupid iBCS! */ map_len = trunc_page(offset + filsz) - trunc_page(map_offset); } else { /* * The only stuff we care about is on disk, and we * don't care if we map in more than is really there. */ map_len = round_page(offset + filsz) - trunc_page(map_offset); } DPRINTF(("%s(%d): vm_mmap(&vmspace->vm_map, &0x%08jx, 0x%x, 0x%x, " "VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED, OBJT_VNODE, vp, 0x%x)\n", __FILE__, __LINE__, (uintmax_t)map_addr, map_len, prot, map_offset)); if ((error = vm_mmap(&vmspace->vm_map, &map_addr, map_len, prot, VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED, OBJT_VNODE, vp, map_offset)) != 0) return error; if (memsz == filsz) { /* We're done! */ return 0; } /* * Now we have screwball stuff, to accomodate stupid COFF. * We have to map the remaining bit of the file into the kernel's * memory map, allocate some anonymous memory, copy that last * bit into it, and then we're done. *sigh* * For clean-up reasons, we actally map in the file last. */ copy_len = (offset + filsz) - trunc_page(offset + filsz); map_addr = trunc_page((vm_offset_t)vmaddr + filsz); map_len = round_page((vm_offset_t)vmaddr + memsz) - map_addr; DPRINTF(("%s(%d): vm_map_find(&vmspace->vm_map, NULL, 0, &0x%08jx,0x%x, VMFS_NO_SPACE, VM_PROT_ALL, VM_PROT_ALL, 0)\n", __FILE__, __LINE__, (uintmax_t)map_addr, map_len)); if (map_len != 0) { error = vm_map_find(&vmspace->vm_map, NULL, 0, &map_addr, map_len, 0, VMFS_NO_SPACE, VM_PROT_ALL, VM_PROT_ALL, 0); if (error) return (vm_mmap_to_errno(error)); } if ((error = vm_mmap(exec_map, (vm_offset_t *) &data_buf, PAGE_SIZE, VM_PROT_READ, VM_PROT_READ, 0, OBJT_VNODE, vp, trunc_page(offset + filsz))) != 0) return error; error = copyout(data_buf, (caddr_t) map_addr, copy_len); kmap_free_wakeup(exec_map, (vm_offset_t)data_buf, PAGE_SIZE); return error; } static int coff_load_file(struct thread *td, char *name) { struct proc *p = td->td_proc; struct vmspace *vmspace = p->p_vmspace; int error; struct nameidata nd; struct vnode *vp; struct vattr attr; struct filehdr *fhdr; struct aouthdr *ahdr; struct scnhdr *scns; char *ptr = NULL; int nscns; unsigned long text_offset = 0, text_address = 0, text_size = 0; unsigned long data_offset = 0, data_address = 0, data_size = 0; unsigned long bss_size = 0; int i, writecount; NDINIT(&nd, LOOKUP, ISOPEN | LOCKLEAF | FOLLOW | SAVENAME, UIO_SYSSPACE, name, td); error = namei(&nd); if (error) return error; vp = nd.ni_vp; if (vp == NULL) return ENOEXEC; error = VOP_GET_WRITECOUNT(vp, &writecount); if (error != 0) goto fail; if (writecount != 0) { error = ETXTBSY; goto fail; } if ((error = VOP_GETATTR(vp, &attr, td->td_ucred)) != 0) goto fail; if ((vp->v_mount->mnt_flag & MNT_NOEXEC) || ((attr.va_mode & 0111) == 0) || (attr.va_type != VREG)) goto fail; if (attr.va_size == 0) { error = ENOEXEC; goto fail; } if ((error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td)) != 0) goto fail; if ((error = VOP_OPEN(vp, FREAD, td->td_ucred, td, NULL)) != 0) goto fail; /* * Lose the lock on the vnode. It's no longer needed, and must not * exist for the pagefault paging to work below. */ VOP_UNLOCK(vp, 0); if ((error = vm_mmap(exec_map, (vm_offset_t *) &ptr, PAGE_SIZE, VM_PROT_READ, VM_PROT_READ, 0, OBJT_VNODE, vp, 0)) != 0) goto unlocked_fail; fhdr = (struct filehdr *)ptr; if (fhdr->f_magic != I386_COFF) { error = ENOEXEC; goto dealloc_and_fail; } nscns = fhdr->f_nscns; if ((nscns * sizeof(struct scnhdr)) > PAGE_SIZE) { /* * XXX -- just fail. I'm so lazy. */ error = ENOEXEC; goto dealloc_and_fail; } ahdr = (struct aouthdr*)(ptr + sizeof(struct filehdr)); scns = (struct scnhdr*)(ptr + sizeof(struct filehdr) + sizeof(struct aouthdr)); for (i = 0; i < nscns; i++) { if (scns[i].s_flags & STYP_NOLOAD) continue; else if (scns[i].s_flags & STYP_TEXT) { text_address = scns[i].s_vaddr; text_size = scns[i].s_size; text_offset = scns[i].s_scnptr; } else if (scns[i].s_flags & STYP_DATA) { data_address = scns[i].s_vaddr; data_size = scns[i].s_size; data_offset = scns[i].s_scnptr; } else if (scns[i].s_flags & STYP_BSS) { bss_size = scns[i].s_size; } } if ((error = load_coff_section(vmspace, vp, text_offset, (caddr_t)(void *)(uintptr_t)text_address, text_size, text_size, VM_PROT_READ | VM_PROT_EXECUTE)) != 0) { goto dealloc_and_fail; } if ((error = load_coff_section(vmspace, vp, data_offset, (caddr_t)(void *)(uintptr_t)data_address, data_size + bss_size, data_size, VM_PROT_ALL)) != 0) { goto dealloc_and_fail; } error = 0; dealloc_and_fail: kmap_free_wakeup(exec_map, (vm_offset_t)ptr, PAGE_SIZE); fail: VOP_UNLOCK(vp, 0); unlocked_fail: NDFREE(&nd, NDF_ONLY_PNBUF); vrele(nd.ni_vp); return error; } static int exec_coff_imgact(imgp) struct image_params *imgp; { const struct filehdr *fhdr = (const struct filehdr*)imgp->image_header; const struct aouthdr *ahdr; const struct scnhdr *scns; int i; struct vmspace *vmspace; int nscns; int error; unsigned long text_offset = 0, text_address = 0, text_size = 0; unsigned long data_offset = 0, data_address = 0, data_size = 0; unsigned long bss_size = 0; vm_offset_t hole; if (fhdr->f_magic != I386_COFF || !(fhdr->f_flags & F_EXEC)) { DPRINTF(("%s(%d): return -1\n", __FILE__, __LINE__)); return -1; } nscns = fhdr->f_nscns; if ((nscns * sizeof(struct scnhdr)) > PAGE_SIZE) { /* * For now, return an error -- need to be able to * read in all of the section structures. */ DPRINTF(("%s(%d): return -1\n", __FILE__, __LINE__)); return -1; } ahdr = (const struct aouthdr*) ((const char*)(imgp->image_header) + sizeof(struct filehdr)); imgp->entry_addr = ahdr->entry; scns = (const struct scnhdr*) ((const char*)(imgp->image_header) + sizeof(struct filehdr) + sizeof(struct aouthdr)); VOP_UNLOCK(imgp->vp, 0); error = exec_new_vmspace(imgp, &ibcs2_svr3_sysvec); if (error) goto fail; vmspace = imgp->proc->p_vmspace; for (i = 0; i < nscns; i++) { DPRINTF(("i = %d, s_name = %s, s_vaddr = %08lx, " "s_scnptr = %ld s_size = %lx\n", i, scns[i].s_name, scns[i].s_vaddr, scns[i].s_scnptr, scns[i].s_size)); if (scns[i].s_flags & STYP_NOLOAD) { /* * A section that is not loaded, for whatever * reason. It takes precedance over other flag * bits... */ continue; } else if (scns[i].s_flags & STYP_TEXT) { text_address = scns[i].s_vaddr; text_size = scns[i].s_size; text_offset = scns[i].s_scnptr; } else if (scns[i].s_flags & STYP_DATA) { /* .data section */ data_address = scns[i].s_vaddr; data_size = scns[i].s_size; data_offset = scns[i].s_scnptr; } else if (scns[i].s_flags & STYP_BSS) { /* .bss section */ bss_size = scns[i].s_size; } else if (scns[i].s_flags & STYP_LIB) { char *buf = NULL; int foff = trunc_page(scns[i].s_scnptr); int off = scns[i].s_scnptr - foff; int len = round_page(scns[i].s_size + PAGE_SIZE); int j; if ((error = vm_mmap(exec_map, (vm_offset_t *) &buf, len, VM_PROT_READ, VM_PROT_READ, MAP_SHARED, OBJT_VNODE, imgp->vp, foff)) != 0) { error = ENOEXEC; goto fail; } if(scns[i].s_size) { char *libbuf; int emul_path_len = strlen(ibcs2_emul_path); libbuf = malloc(MAXPATHLEN + emul_path_len, M_TEMP, M_WAITOK); strcpy(libbuf, ibcs2_emul_path); for (j = off; j < scns[i].s_size + off;) { long stroff, nextoff; char *libname; nextoff = 4 * *(long *)(buf + j); stroff = 4 * *(long *)(buf + j + sizeof(long)); libname = buf + j + stroff; j += nextoff; DPRINTF(("%s(%d): shared library %s\n", __FILE__, __LINE__, libname)); strlcpy(&libbuf[emul_path_len], libname, MAXPATHLEN); error = coff_load_file( FIRST_THREAD_IN_PROC(imgp->proc), libbuf); if (error) error = coff_load_file( FIRST_THREAD_IN_PROC(imgp->proc), libname); if (error) { printf( "error %d loading coff shared library %s\n", error, libname); break; } } free(libbuf, M_TEMP); } kmap_free_wakeup(exec_map, (vm_offset_t)buf, len); if (error) goto fail; } } /* * Map in .text now */ DPRINTF(("%s(%d): load_coff_section(vmspace, " "imgp->vp, %08lx, %08lx, 0x%lx, 0x%lx, 0x%x)\n", __FILE__, __LINE__, text_offset, text_address, text_size, text_size, VM_PROT_READ | VM_PROT_EXECUTE)); if ((error = load_coff_section(vmspace, imgp->vp, text_offset, (caddr_t)(void *)(uintptr_t)text_address, text_size, text_size, VM_PROT_READ | VM_PROT_EXECUTE)) != 0) { DPRINTF(("%s(%d): error = %d\n", __FILE__, __LINE__, error)); goto fail; } /* * Map in .data and .bss now */ DPRINTF(("%s(%d): load_coff_section(vmspace, " "imgp->vp, 0x%08lx, 0x%08lx, 0x%lx, 0x%lx, 0x%x)\n", __FILE__, __LINE__, data_offset, data_address, data_size + bss_size, data_size, VM_PROT_ALL)); if ((error = load_coff_section(vmspace, imgp->vp, data_offset, (caddr_t)(void *)(uintptr_t)data_address, data_size + bss_size, data_size, VM_PROT_ALL)) != 0) { DPRINTF(("%s(%d): error = %d\n", __FILE__, __LINE__, error)); goto fail; } imgp->interpreted = 0; imgp->proc->p_sysent = &ibcs2_svr3_sysvec; vmspace->vm_tsize = round_page(text_size) >> PAGE_SHIFT; vmspace->vm_dsize = round_page(data_size + bss_size) >> PAGE_SHIFT; vmspace->vm_taddr = (caddr_t)(void *)(uintptr_t)text_address; vmspace->vm_daddr = (caddr_t)(void *)(uintptr_t)data_address; hole = trunc_page((vm_offset_t)vmspace->vm_daddr + ctob(vmspace->vm_dsize)); DPRINTF(("%s(%d): vm_map_find(&vmspace->vm_map, NULL, 0, &0x%jx, PAGE_SIZE, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0)\n", __FILE__, __LINE__, (uintmax_t)hole)); DPRINTF(("imgact: error = %d\n", error)); vm_map_find(&vmspace->vm_map, NULL, 0, (vm_offset_t *)&hole, PAGE_SIZE, 0, VMFS_NO_SPACE, VM_PROT_ALL, VM_PROT_ALL, 0); DPRINTF(("IBCS2: start vm_dsize = 0x%x, vm_daddr = 0x%p end = 0x%p\n", ctob(vmspace->vm_dsize), vmspace->vm_daddr, ctob(vmspace->vm_dsize) + vmspace->vm_daddr )); DPRINTF(("%s(%d): returning %d!\n", __FILE__, __LINE__, error)); fail: vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY); return (error); } /* * Tell kern_execve.c about it, with a little help from the linker. */ static struct execsw coff_execsw = { exec_coff_imgact, "coff" }; EXEC_SET(coff, coff_execsw); Index: head/sys/i386/include/_bus.h =================================================================== --- head/sys/i386/include/_bus.h (revision 326259) +++ head/sys/i386/include/_bus.h (revision 326260) @@ -1,50 +1,52 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2005 M. Warner Losh. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer, * without modification, immediately at the beginning of the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef I386_INCLUDE__BUS_H #define I386_INCLUDE__BUS_H /* * Bus address and size types */ #ifdef PAE typedef uint64_t bus_addr_t; #else typedef uint32_t bus_addr_t; #endif typedef uint32_t bus_size_t; /* * Access methods for bus resources and address space. */ typedef int bus_space_tag_t; typedef u_int bus_space_handle_t; #endif /* I386_INCLUDE__BUS_H */ Index: head/sys/i386/include/atomic.h =================================================================== --- head/sys/i386/include/atomic.h (revision 326259) +++ head/sys/i386/include/atomic.h (revision 326260) @@ -1,866 +1,868 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1998 Doug Rabson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_ATOMIC_H_ #define _MACHINE_ATOMIC_H_ #ifndef _SYS_CDEFS_H_ #error this file needs sys/cdefs.h as a prerequisite #endif #ifdef _KERNEL #include #include #endif #ifndef __OFFSETOF_MONITORBUF /* * __OFFSETOF_MONITORBUF == __pcpu_offset(pc_monitorbuf). * * The open-coded number is used instead of the symbolic expression to * avoid a dependency on sys/pcpu.h in machine/atomic.h consumers. * An assertion in i386/vm_machdep.c ensures that the value is correct. */ #define __OFFSETOF_MONITORBUF 0x80 static __inline void __mbk(void) { __asm __volatile("lock; addl $0,%%fs:%0" : "+m" (*(u_int *)__OFFSETOF_MONITORBUF) : : "memory", "cc"); } static __inline void __mbu(void) { __asm __volatile("lock; addl $0,(%%esp)" : : : "memory", "cc"); } #endif /* * Various simple operations on memory, each of which is atomic in the * presence of interrupts and multiple processors. * * atomic_set_char(P, V) (*(u_char *)(P) |= (V)) * atomic_clear_char(P, V) (*(u_char *)(P) &= ~(V)) * atomic_add_char(P, V) (*(u_char *)(P) += (V)) * atomic_subtract_char(P, V) (*(u_char *)(P) -= (V)) * * atomic_set_short(P, V) (*(u_short *)(P) |= (V)) * atomic_clear_short(P, V) (*(u_short *)(P) &= ~(V)) * atomic_add_short(P, V) (*(u_short *)(P) += (V)) * atomic_subtract_short(P, V) (*(u_short *)(P) -= (V)) * * atomic_set_int(P, V) (*(u_int *)(P) |= (V)) * atomic_clear_int(P, V) (*(u_int *)(P) &= ~(V)) * atomic_add_int(P, V) (*(u_int *)(P) += (V)) * atomic_subtract_int(P, V) (*(u_int *)(P) -= (V)) * atomic_swap_int(P, V) (return (*(u_int *)(P)); *(u_int *)(P) = (V);) * atomic_readandclear_int(P) (return (*(u_int *)(P)); *(u_int *)(P) = 0;) * * atomic_set_long(P, V) (*(u_long *)(P) |= (V)) * atomic_clear_long(P, V) (*(u_long *)(P) &= ~(V)) * atomic_add_long(P, V) (*(u_long *)(P) += (V)) * atomic_subtract_long(P, V) (*(u_long *)(P) -= (V)) * atomic_swap_long(P, V) (return (*(u_long *)(P)); *(u_long *)(P) = (V);) * atomic_readandclear_long(P) (return (*(u_long *)(P)); *(u_long *)(P) = 0;) */ /* * The above functions are expanded inline in the statically-linked * kernel. Lock prefixes are generated if an SMP kernel is being * built. * * Kernel modules call real functions which are built into the kernel. * This allows kernel modules to be portable between UP and SMP systems. */ #if defined(KLD_MODULE) || !defined(__GNUCLIKE_ASM) #define ATOMIC_ASM(NAME, TYPE, OP, CONS, V) \ void atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v); \ void atomic_##NAME##_barr_##TYPE(volatile u_##TYPE *p, u_##TYPE v) int atomic_cmpset_char(volatile u_char *dst, u_char expect, u_char src); int atomic_cmpset_short(volatile u_short *dst, u_short expect, u_short src); int atomic_cmpset_int(volatile u_int *dst, u_int expect, u_int src); int atomic_fcmpset_char(volatile u_char *dst, u_char *expect, u_char src); int atomic_fcmpset_short(volatile u_short *dst, u_short *expect, u_short src); int atomic_fcmpset_int(volatile u_int *dst, u_int *expect, u_int src); u_int atomic_fetchadd_int(volatile u_int *p, u_int v); int atomic_testandset_int(volatile u_int *p, u_int v); int atomic_testandclear_int(volatile u_int *p, u_int v); void atomic_thread_fence_acq(void); void atomic_thread_fence_acq_rel(void); void atomic_thread_fence_rel(void); void atomic_thread_fence_seq_cst(void); #define ATOMIC_LOAD(TYPE) \ u_##TYPE atomic_load_acq_##TYPE(volatile u_##TYPE *p) #define ATOMIC_STORE(TYPE) \ void atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v) int atomic_cmpset_64(volatile uint64_t *, uint64_t, uint64_t); uint64_t atomic_load_acq_64(volatile uint64_t *); void atomic_store_rel_64(volatile uint64_t *, uint64_t); uint64_t atomic_swap_64(volatile uint64_t *, uint64_t); uint64_t atomic_fetchadd_64(volatile uint64_t *, uint64_t); #else /* !KLD_MODULE && __GNUCLIKE_ASM */ /* * For userland, always use lock prefixes so that the binaries will run * on both SMP and !SMP systems. */ #if defined(SMP) || !defined(_KERNEL) #define MPLOCKED "lock ; " #else #define MPLOCKED #endif /* * The assembly is volatilized to avoid code chunk removal by the compiler. * GCC aggressively reorders operations and memory clobbering is necessary * in order to avoid that for memory barriers. */ #define ATOMIC_ASM(NAME, TYPE, OP, CONS, V) \ static __inline void \ atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\ { \ __asm __volatile(MPLOCKED OP \ : "+m" (*p) \ : CONS (V) \ : "cc"); \ } \ \ static __inline void \ atomic_##NAME##_barr_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\ { \ __asm __volatile(MPLOCKED OP \ : "+m" (*p) \ : CONS (V) \ : "memory", "cc"); \ } \ struct __hack /* * Atomic compare and set, used by the mutex functions. * * cmpset: * if (*dst == expect) * *dst = src * * fcmpset: * if (*dst == *expect) * *dst = src * else * *expect = *dst * * Returns 0 on failure, non-zero on success. */ #define ATOMIC_CMPSET(TYPE, CONS) \ static __inline int \ atomic_cmpset_##TYPE(volatile u_##TYPE *dst, u_##TYPE expect, u_##TYPE src) \ { \ u_char res; \ \ __asm __volatile( \ " " MPLOCKED " " \ " cmpxchg %3,%1 ; " \ " sete %0 ; " \ "# atomic_cmpset_" #TYPE " " \ : "=q" (res), /* 0 */ \ "+m" (*dst), /* 1 */ \ "+a" (expect) /* 2 */ \ : CONS (src) /* 3 */ \ : "memory", "cc"); \ return (res); \ } \ \ static __inline int \ atomic_fcmpset_##TYPE(volatile u_##TYPE *dst, u_##TYPE *expect, u_##TYPE src) \ { \ u_char res; \ \ __asm __volatile( \ " " MPLOCKED " " \ " cmpxchg %3,%1 ; " \ " sete %0 ; " \ "# atomic_fcmpset_" #TYPE " " \ : "=q" (res), /* 0 */ \ "+m" (*dst), /* 1 */ \ "+a" (*expect) /* 2 */ \ : CONS (src) /* 3 */ \ : "memory", "cc"); \ return (res); \ } ATOMIC_CMPSET(char, "q"); ATOMIC_CMPSET(short, "r"); ATOMIC_CMPSET(int, "r"); /* * Atomically add the value of v to the integer pointed to by p and return * the previous value of *p. */ static __inline u_int atomic_fetchadd_int(volatile u_int *p, u_int v) { __asm __volatile( " " MPLOCKED " " " xaddl %0,%1 ; " "# atomic_fetchadd_int" : "+r" (v), /* 0 */ "+m" (*p) /* 1 */ : : "cc"); return (v); } static __inline int atomic_testandset_int(volatile u_int *p, u_int v) { u_char res; __asm __volatile( " " MPLOCKED " " " btsl %2,%1 ; " " setc %0 ; " "# atomic_testandset_int" : "=q" (res), /* 0 */ "+m" (*p) /* 1 */ : "Ir" (v & 0x1f) /* 2 */ : "cc"); return (res); } static __inline int atomic_testandclear_int(volatile u_int *p, u_int v) { u_char res; __asm __volatile( " " MPLOCKED " " " btrl %2,%1 ; " " setc %0 ; " "# atomic_testandclear_int" : "=q" (res), /* 0 */ "+m" (*p) /* 1 */ : "Ir" (v & 0x1f) /* 2 */ : "cc"); return (res); } /* * We assume that a = b will do atomic loads and stores. Due to the * IA32 memory model, a simple store guarantees release semantics. * * However, a load may pass a store if they are performed on distinct * addresses, so we need Store/Load barrier for sequentially * consistent fences in SMP kernels. We use "lock addl $0,mem" for a * Store/Load barrier, as recommended by the AMD Software Optimization * Guide, and not mfence. In the kernel, we use a private per-cpu * cache line for "mem", to avoid introducing false data * dependencies. In user space, we use the word at the top of the * stack. * * For UP kernels, however, the memory of the single processor is * always consistent, so we only need to stop the compiler from * reordering accesses in a way that violates the semantics of acquire * and release. */ #if defined(_KERNEL) #if defined(SMP) #define __storeload_barrier() __mbk() #else /* _KERNEL && UP */ #define __storeload_barrier() __compiler_membar() #endif /* SMP */ #else /* !_KERNEL */ #define __storeload_barrier() __mbu() #endif /* _KERNEL*/ #define ATOMIC_LOAD(TYPE) \ static __inline u_##TYPE \ atomic_load_acq_##TYPE(volatile u_##TYPE *p) \ { \ u_##TYPE res; \ \ res = *p; \ __compiler_membar(); \ return (res); \ } \ struct __hack #define ATOMIC_STORE(TYPE) \ static __inline void \ atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v) \ { \ \ __compiler_membar(); \ *p = v; \ } \ struct __hack static __inline void atomic_thread_fence_acq(void) { __compiler_membar(); } static __inline void atomic_thread_fence_rel(void) { __compiler_membar(); } static __inline void atomic_thread_fence_acq_rel(void) { __compiler_membar(); } static __inline void atomic_thread_fence_seq_cst(void) { __storeload_barrier(); } #ifdef _KERNEL #ifdef WANT_FUNCTIONS int atomic_cmpset_64_i386(volatile uint64_t *, uint64_t, uint64_t); int atomic_cmpset_64_i586(volatile uint64_t *, uint64_t, uint64_t); uint64_t atomic_load_acq_64_i386(volatile uint64_t *); uint64_t atomic_load_acq_64_i586(volatile uint64_t *); void atomic_store_rel_64_i386(volatile uint64_t *, uint64_t); void atomic_store_rel_64_i586(volatile uint64_t *, uint64_t); uint64_t atomic_swap_64_i386(volatile uint64_t *, uint64_t); uint64_t atomic_swap_64_i586(volatile uint64_t *, uint64_t); #endif /* I486 does not support SMP or CMPXCHG8B. */ static __inline int atomic_cmpset_64_i386(volatile uint64_t *dst, uint64_t expect, uint64_t src) { volatile uint32_t *p; u_char res; p = (volatile uint32_t *)dst; __asm __volatile( " pushfl ; " " cli ; " " xorl %1,%%eax ; " " xorl %2,%%edx ; " " orl %%edx,%%eax ; " " jne 1f ; " " movl %4,%1 ; " " movl %5,%2 ; " "1: " " sete %3 ; " " popfl" : "+A" (expect), /* 0 */ "+m" (*p), /* 1 */ "+m" (*(p + 1)), /* 2 */ "=q" (res) /* 3 */ : "r" ((uint32_t)src), /* 4 */ "r" ((uint32_t)(src >> 32)) /* 5 */ : "memory", "cc"); return (res); } static __inline uint64_t atomic_load_acq_64_i386(volatile uint64_t *p) { volatile uint32_t *q; uint64_t res; q = (volatile uint32_t *)p; __asm __volatile( " pushfl ; " " cli ; " " movl %1,%%eax ; " " movl %2,%%edx ; " " popfl" : "=&A" (res) /* 0 */ : "m" (*q), /* 1 */ "m" (*(q + 1)) /* 2 */ : "memory"); return (res); } static __inline void atomic_store_rel_64_i386(volatile uint64_t *p, uint64_t v) { volatile uint32_t *q; q = (volatile uint32_t *)p; __asm __volatile( " pushfl ; " " cli ; " " movl %%eax,%0 ; " " movl %%edx,%1 ; " " popfl" : "=m" (*q), /* 0 */ "=m" (*(q + 1)) /* 1 */ : "A" (v) /* 2 */ : "memory"); } static __inline uint64_t atomic_swap_64_i386(volatile uint64_t *p, uint64_t v) { volatile uint32_t *q; uint64_t res; q = (volatile uint32_t *)p; __asm __volatile( " pushfl ; " " cli ; " " movl %1,%%eax ; " " movl %2,%%edx ; " " movl %4,%2 ; " " movl %3,%1 ; " " popfl" : "=&A" (res), /* 0 */ "+m" (*q), /* 1 */ "+m" (*(q + 1)) /* 2 */ : "r" ((uint32_t)v), /* 3 */ "r" ((uint32_t)(v >> 32))); /* 4 */ return (res); } static __inline int atomic_cmpset_64_i586(volatile uint64_t *dst, uint64_t expect, uint64_t src) { u_char res; __asm __volatile( " " MPLOCKED " " " cmpxchg8b %1 ; " " sete %0" : "=q" (res), /* 0 */ "+m" (*dst), /* 1 */ "+A" (expect) /* 2 */ : "b" ((uint32_t)src), /* 3 */ "c" ((uint32_t)(src >> 32)) /* 4 */ : "memory", "cc"); return (res); } static __inline uint64_t atomic_load_acq_64_i586(volatile uint64_t *p) { uint64_t res; __asm __volatile( " movl %%ebx,%%eax ; " " movl %%ecx,%%edx ; " " " MPLOCKED " " " cmpxchg8b %1" : "=&A" (res), /* 0 */ "+m" (*p) /* 1 */ : : "memory", "cc"); return (res); } static __inline void atomic_store_rel_64_i586(volatile uint64_t *p, uint64_t v) { __asm __volatile( " movl %%eax,%%ebx ; " " movl %%edx,%%ecx ; " "1: " " " MPLOCKED " " " cmpxchg8b %0 ; " " jne 1b" : "+m" (*p), /* 0 */ "+A" (v) /* 1 */ : : "ebx", "ecx", "memory", "cc"); } static __inline uint64_t atomic_swap_64_i586(volatile uint64_t *p, uint64_t v) { __asm __volatile( " movl %%eax,%%ebx ; " " movl %%edx,%%ecx ; " "1: " " " MPLOCKED " " " cmpxchg8b %0 ; " " jne 1b" : "+m" (*p), /* 0 */ "+A" (v) /* 1 */ : : "ebx", "ecx", "memory", "cc"); return (v); } static __inline int atomic_cmpset_64(volatile uint64_t *dst, uint64_t expect, uint64_t src) { if ((cpu_feature & CPUID_CX8) == 0) return (atomic_cmpset_64_i386(dst, expect, src)); else return (atomic_cmpset_64_i586(dst, expect, src)); } static __inline uint64_t atomic_load_acq_64(volatile uint64_t *p) { if ((cpu_feature & CPUID_CX8) == 0) return (atomic_load_acq_64_i386(p)); else return (atomic_load_acq_64_i586(p)); } static __inline void atomic_store_rel_64(volatile uint64_t *p, uint64_t v) { if ((cpu_feature & CPUID_CX8) == 0) atomic_store_rel_64_i386(p, v); else atomic_store_rel_64_i586(p, v); } static __inline uint64_t atomic_swap_64(volatile uint64_t *p, uint64_t v) { if ((cpu_feature & CPUID_CX8) == 0) return (atomic_swap_64_i386(p, v)); else return (atomic_swap_64_i586(p, v)); } static __inline uint64_t atomic_fetchadd_64(volatile uint64_t *p, uint64_t v) { for (;;) { uint64_t t = *p; if (atomic_cmpset_64(p, t, t + v)) return (t); } } #endif /* _KERNEL */ #endif /* KLD_MODULE || !__GNUCLIKE_ASM */ ATOMIC_ASM(set, char, "orb %b1,%0", "iq", v); ATOMIC_ASM(clear, char, "andb %b1,%0", "iq", ~v); ATOMIC_ASM(add, char, "addb %b1,%0", "iq", v); ATOMIC_ASM(subtract, char, "subb %b1,%0", "iq", v); ATOMIC_ASM(set, short, "orw %w1,%0", "ir", v); ATOMIC_ASM(clear, short, "andw %w1,%0", "ir", ~v); ATOMIC_ASM(add, short, "addw %w1,%0", "ir", v); ATOMIC_ASM(subtract, short, "subw %w1,%0", "ir", v); ATOMIC_ASM(set, int, "orl %1,%0", "ir", v); ATOMIC_ASM(clear, int, "andl %1,%0", "ir", ~v); ATOMIC_ASM(add, int, "addl %1,%0", "ir", v); ATOMIC_ASM(subtract, int, "subl %1,%0", "ir", v); ATOMIC_ASM(set, long, "orl %1,%0", "ir", v); ATOMIC_ASM(clear, long, "andl %1,%0", "ir", ~v); ATOMIC_ASM(add, long, "addl %1,%0", "ir", v); ATOMIC_ASM(subtract, long, "subl %1,%0", "ir", v); #define ATOMIC_LOADSTORE(TYPE) \ ATOMIC_LOAD(TYPE); \ ATOMIC_STORE(TYPE) ATOMIC_LOADSTORE(char); ATOMIC_LOADSTORE(short); ATOMIC_LOADSTORE(int); ATOMIC_LOADSTORE(long); #undef ATOMIC_ASM #undef ATOMIC_LOAD #undef ATOMIC_STORE #undef ATOMIC_LOADSTORE #ifndef WANT_FUNCTIONS static __inline int atomic_cmpset_long(volatile u_long *dst, u_long expect, u_long src) { return (atomic_cmpset_int((volatile u_int *)dst, (u_int)expect, (u_int)src)); } static __inline u_long atomic_fetchadd_long(volatile u_long *p, u_long v) { return (atomic_fetchadd_int((volatile u_int *)p, (u_int)v)); } static __inline int atomic_testandset_long(volatile u_long *p, u_int v) { return (atomic_testandset_int((volatile u_int *)p, v)); } static __inline int atomic_testandclear_long(volatile u_long *p, u_int v) { return (atomic_testandclear_int((volatile u_int *)p, v)); } /* Read the current value and store a new value in the destination. */ #ifdef __GNUCLIKE_ASM static __inline u_int atomic_swap_int(volatile u_int *p, u_int v) { __asm __volatile( " xchgl %1,%0 ; " "# atomic_swap_int" : "+r" (v), /* 0 */ "+m" (*p)); /* 1 */ return (v); } static __inline u_long atomic_swap_long(volatile u_long *p, u_long v) { return (atomic_swap_int((volatile u_int *)p, (u_int)v)); } #else /* !__GNUCLIKE_ASM */ u_int atomic_swap_int(volatile u_int *p, u_int v); u_long atomic_swap_long(volatile u_long *p, u_long v); #endif /* __GNUCLIKE_ASM */ #define atomic_set_acq_char atomic_set_barr_char #define atomic_set_rel_char atomic_set_barr_char #define atomic_clear_acq_char atomic_clear_barr_char #define atomic_clear_rel_char atomic_clear_barr_char #define atomic_add_acq_char atomic_add_barr_char #define atomic_add_rel_char atomic_add_barr_char #define atomic_subtract_acq_char atomic_subtract_barr_char #define atomic_subtract_rel_char atomic_subtract_barr_char #define atomic_cmpset_acq_char atomic_cmpset_char #define atomic_cmpset_rel_char atomic_cmpset_char #define atomic_fcmpset_acq_char atomic_fcmpset_char #define atomic_fcmpset_rel_char atomic_fcmpset_char #define atomic_set_acq_short atomic_set_barr_short #define atomic_set_rel_short atomic_set_barr_short #define atomic_clear_acq_short atomic_clear_barr_short #define atomic_clear_rel_short atomic_clear_barr_short #define atomic_add_acq_short atomic_add_barr_short #define atomic_add_rel_short atomic_add_barr_short #define atomic_subtract_acq_short atomic_subtract_barr_short #define atomic_subtract_rel_short atomic_subtract_barr_short #define atomic_cmpset_acq_short atomic_cmpset_short #define atomic_cmpset_rel_short atomic_cmpset_short #define atomic_fcmpset_acq_short atomic_fcmpset_short #define atomic_fcmpset_rel_short atomic_fcmpset_short #define atomic_set_acq_int atomic_set_barr_int #define atomic_set_rel_int atomic_set_barr_int #define atomic_clear_acq_int atomic_clear_barr_int #define atomic_clear_rel_int atomic_clear_barr_int #define atomic_add_acq_int atomic_add_barr_int #define atomic_add_rel_int atomic_add_barr_int #define atomic_subtract_acq_int atomic_subtract_barr_int #define atomic_subtract_rel_int atomic_subtract_barr_int #define atomic_cmpset_acq_int atomic_cmpset_int #define atomic_cmpset_rel_int atomic_cmpset_int #define atomic_fcmpset_acq_int atomic_fcmpset_int #define atomic_fcmpset_rel_int atomic_fcmpset_int #define atomic_set_acq_long atomic_set_barr_long #define atomic_set_rel_long atomic_set_barr_long #define atomic_clear_acq_long atomic_clear_barr_long #define atomic_clear_rel_long atomic_clear_barr_long #define atomic_add_acq_long atomic_add_barr_long #define atomic_add_rel_long atomic_add_barr_long #define atomic_subtract_acq_long atomic_subtract_barr_long #define atomic_subtract_rel_long atomic_subtract_barr_long #define atomic_cmpset_acq_long atomic_cmpset_long #define atomic_cmpset_rel_long atomic_cmpset_long #define atomic_fcmpset_acq_long atomic_fcmpset_long #define atomic_fcmpset_rel_long atomic_fcmpset_long #define atomic_readandclear_int(p) atomic_swap_int(p, 0) #define atomic_readandclear_long(p) atomic_swap_long(p, 0) /* Operations on 8-bit bytes. */ #define atomic_set_8 atomic_set_char #define atomic_set_acq_8 atomic_set_acq_char #define atomic_set_rel_8 atomic_set_rel_char #define atomic_clear_8 atomic_clear_char #define atomic_clear_acq_8 atomic_clear_acq_char #define atomic_clear_rel_8 atomic_clear_rel_char #define atomic_add_8 atomic_add_char #define atomic_add_acq_8 atomic_add_acq_char #define atomic_add_rel_8 atomic_add_rel_char #define atomic_subtract_8 atomic_subtract_char #define atomic_subtract_acq_8 atomic_subtract_acq_char #define atomic_subtract_rel_8 atomic_subtract_rel_char #define atomic_load_acq_8 atomic_load_acq_char #define atomic_store_rel_8 atomic_store_rel_char #define atomic_cmpset_8 atomic_cmpset_char #define atomic_cmpset_acq_8 atomic_cmpset_acq_char #define atomic_cmpset_rel_8 atomic_cmpset_rel_char #define atomic_fcmpset_8 atomic_fcmpset_char #define atomic_fcmpset_acq_8 atomic_fcmpset_acq_char #define atomic_fcmpset_rel_8 atomic_fcmpset_rel_char /* Operations on 16-bit words. */ #define atomic_set_16 atomic_set_short #define atomic_set_acq_16 atomic_set_acq_short #define atomic_set_rel_16 atomic_set_rel_short #define atomic_clear_16 atomic_clear_short #define atomic_clear_acq_16 atomic_clear_acq_short #define atomic_clear_rel_16 atomic_clear_rel_short #define atomic_add_16 atomic_add_short #define atomic_add_acq_16 atomic_add_acq_short #define atomic_add_rel_16 atomic_add_rel_short #define atomic_subtract_16 atomic_subtract_short #define atomic_subtract_acq_16 atomic_subtract_acq_short #define atomic_subtract_rel_16 atomic_subtract_rel_short #define atomic_load_acq_16 atomic_load_acq_short #define atomic_store_rel_16 atomic_store_rel_short #define atomic_cmpset_16 atomic_cmpset_short #define atomic_cmpset_acq_16 atomic_cmpset_acq_short #define atomic_cmpset_rel_16 atomic_cmpset_rel_short #define atomic_fcmpset_16 atomic_fcmpset_short #define atomic_fcmpset_acq_16 atomic_fcmpset_acq_short #define atomic_fcmpset_rel_16 atomic_fcmpset_rel_short /* Operations on 32-bit double words. */ #define atomic_set_32 atomic_set_int #define atomic_set_acq_32 atomic_set_acq_int #define atomic_set_rel_32 atomic_set_rel_int #define atomic_clear_32 atomic_clear_int #define atomic_clear_acq_32 atomic_clear_acq_int #define atomic_clear_rel_32 atomic_clear_rel_int #define atomic_add_32 atomic_add_int #define atomic_add_acq_32 atomic_add_acq_int #define atomic_add_rel_32 atomic_add_rel_int #define atomic_subtract_32 atomic_subtract_int #define atomic_subtract_acq_32 atomic_subtract_acq_int #define atomic_subtract_rel_32 atomic_subtract_rel_int #define atomic_load_acq_32 atomic_load_acq_int #define atomic_store_rel_32 atomic_store_rel_int #define atomic_cmpset_32 atomic_cmpset_int #define atomic_cmpset_acq_32 atomic_cmpset_acq_int #define atomic_cmpset_rel_32 atomic_cmpset_rel_int #define atomic_fcmpset_32 atomic_fcmpset_int #define atomic_fcmpset_acq_32 atomic_fcmpset_acq_int #define atomic_fcmpset_rel_32 atomic_fcmpset_rel_int #define atomic_swap_32 atomic_swap_int #define atomic_readandclear_32 atomic_readandclear_int #define atomic_fetchadd_32 atomic_fetchadd_int #define atomic_testandset_32 atomic_testandset_int #define atomic_testandclear_32 atomic_testandclear_int /* Operations on pointers. */ #define atomic_set_ptr(p, v) \ atomic_set_int((volatile u_int *)(p), (u_int)(v)) #define atomic_set_acq_ptr(p, v) \ atomic_set_acq_int((volatile u_int *)(p), (u_int)(v)) #define atomic_set_rel_ptr(p, v) \ atomic_set_rel_int((volatile u_int *)(p), (u_int)(v)) #define atomic_clear_ptr(p, v) \ atomic_clear_int((volatile u_int *)(p), (u_int)(v)) #define atomic_clear_acq_ptr(p, v) \ atomic_clear_acq_int((volatile u_int *)(p), (u_int)(v)) #define atomic_clear_rel_ptr(p, v) \ atomic_clear_rel_int((volatile u_int *)(p), (u_int)(v)) #define atomic_add_ptr(p, v) \ atomic_add_int((volatile u_int *)(p), (u_int)(v)) #define atomic_add_acq_ptr(p, v) \ atomic_add_acq_int((volatile u_int *)(p), (u_int)(v)) #define atomic_add_rel_ptr(p, v) \ atomic_add_rel_int((volatile u_int *)(p), (u_int)(v)) #define atomic_subtract_ptr(p, v) \ atomic_subtract_int((volatile u_int *)(p), (u_int)(v)) #define atomic_subtract_acq_ptr(p, v) \ atomic_subtract_acq_int((volatile u_int *)(p), (u_int)(v)) #define atomic_subtract_rel_ptr(p, v) \ atomic_subtract_rel_int((volatile u_int *)(p), (u_int)(v)) #define atomic_load_acq_ptr(p) \ atomic_load_acq_int((volatile u_int *)(p)) #define atomic_store_rel_ptr(p, v) \ atomic_store_rel_int((volatile u_int *)(p), (v)) #define atomic_cmpset_ptr(dst, old, new) \ atomic_cmpset_int((volatile u_int *)(dst), (u_int)(old), (u_int)(new)) #define atomic_cmpset_acq_ptr(dst, old, new) \ atomic_cmpset_acq_int((volatile u_int *)(dst), (u_int)(old), \ (u_int)(new)) #define atomic_cmpset_rel_ptr(dst, old, new) \ atomic_cmpset_rel_int((volatile u_int *)(dst), (u_int)(old), \ (u_int)(new)) #define atomic_fcmpset_ptr(dst, old, new) \ atomic_fcmpset_int((volatile u_int *)(dst), (u_int *)(old), (u_int)(new)) #define atomic_fcmpset_acq_ptr(dst, old, new) \ atomic_fcmpset_acq_int((volatile u_int *)(dst), (u_int *)(old), \ (u_int)(new)) #define atomic_fcmpset_rel_ptr(dst, old, new) \ atomic_fcmpset_rel_int((volatile u_int *)(dst), (u_int *)(old), \ (u_int)(new)) #define atomic_swap_ptr(p, v) \ atomic_swap_int((volatile u_int *)(p), (u_int)(v)) #define atomic_readandclear_ptr(p) \ atomic_readandclear_int((volatile u_int *)(p)) #endif /* !WANT_FUNCTIONS */ #if defined(_KERNEL) #define mb() __mbk() #define wmb() __mbk() #define rmb() __mbk() #else #define mb() __mbu() #define wmb() __mbu() #define rmb() __mbu() #endif #endif /* !_MACHINE_ATOMIC_H_ */ Index: head/sys/i386/include/bootinfo.h =================================================================== --- head/sys/i386/include/bootinfo.h (revision 326259) +++ head/sys/i386/include/bootinfo.h (revision 326260) @@ -1,119 +1,121 @@ /*- + * SPDX-License-Identifier: BSD-4-Clause + * * Copyright (C) 1994 by Rodney W. Grimes, Milwaukie, Oregon 97222 * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer as * the first lines of this file unmodified. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Rodney W. Grimes. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY RODNEY W. GRIMES ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL RODNEY W. GRIMES BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_BOOTINFO_H_ #define _MACHINE_BOOTINFO_H_ /* Only change the version number if you break compatibility. */ #define BOOTINFO_VERSION 1 #define N_BIOS_GEOM 8 /* * A zero bootinfo field often means that there is no info available. * Flags are used to indicate the validity of fields where zero is a * normal value. */ struct bootinfo { u_int32_t bi_version; u_int32_t bi_kernelname; /* represents a char * */ u_int32_t bi_nfs_diskless; /* struct nfs_diskless * */ /* End of fields that are always present. */ #define bi_endcommon bi_n_bios_used u_int32_t bi_n_bios_used; u_int32_t bi_bios_geom[N_BIOS_GEOM]; u_int32_t bi_size; u_int8_t bi_memsizes_valid; u_int8_t bi_bios_dev; /* bootdev BIOS unit number */ u_int8_t bi_pad[2]; u_int32_t bi_basemem; u_int32_t bi_extmem; u_int32_t bi_symtab; /* struct symtab * */ u_int32_t bi_esymtab; /* struct symtab * */ /* Items below only from advanced bootloader */ u_int32_t bi_kernend; /* end of kernel space */ u_int32_t bi_envp; /* environment */ u_int32_t bi_modulep; /* preloaded modules */ uint32_t bi_memdesc_version; /* EFI memory desc version */ uint64_t bi_memdesc_size; /* sizeof EFI memory desc */ uint64_t bi_memmap; /* pa of EFI memory map */ uint64_t bi_memmap_size; /* size of EFI memory map */ uint64_t bi_hcdp; /* DIG64 HCDP table */ uint64_t bi_fpswa; /* FPSWA interface */ uint64_t bi_systab; /* pa of EFI system table */ }; #ifdef _KERNEL extern struct bootinfo bootinfo; #endif /* * Constants for converting boot-style device number to type, * adaptor (uba, mba, etc), unit number and partition number. * Type (== major device number) is in the low byte * for backward compatibility. Except for that of the "magic * number", each mask applies to the shifted value. * Format: * (4) (8) (4) (8) (8) * -------------------------------- * |MA | SLICE | UN| PART | TYPE | * -------------------------------- */ #define B_SLICESHIFT 20 #define B_SLICEMASK 0xff #define B_SLICE(val) (((val)>>B_SLICESHIFT) & B_SLICEMASK) #define B_UNITSHIFT 16 #define B_UNITMASK 0xf #define B_UNIT(val) (((val) >> B_UNITSHIFT) & B_UNITMASK) #define B_PARTITIONSHIFT 8 #define B_PARTITIONMASK 0xff #define B_PARTITION(val) (((val) >> B_PARTITIONSHIFT) & B_PARTITIONMASK) #define B_TYPESHIFT 0 #define B_TYPEMASK 0xff #define B_TYPE(val) (((val) >> B_TYPESHIFT) & B_TYPEMASK) #define B_MAGICMASK 0xf0000000 #define B_DEVMAGIC 0xa0000000 #define MAKEBOOTDEV(type, slice, unit, partition) \ (((type) << B_TYPESHIFT) | ((slice) << B_SLICESHIFT) | \ ((unit) << B_UNITSHIFT) | ((partition) << B_PARTITIONSHIFT) | \ B_DEVMAGIC) #define BASE_SLICE 2 #define COMPATIBILITY_SLICE 0 #define MAX_SLICES 32 #define WHOLE_DISK_SLICE 1 #endif /* !_MACHINE_BOOTINFO_H_ */ Index: head/sys/i386/include/bus_dma.h =================================================================== --- head/sys/i386/include/bus_dma.h (revision 326259) +++ head/sys/i386/include/bus_dma.h (revision 326260) @@ -1,34 +1,36 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2005 Scott Long * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* $FreeBSD$ */ #ifndef _I386_BUS_DMA_H_ #define _I386_BUS_DMA_H_ #include #endif /* _I386_BUS_DMA_H_ */ Index: head/sys/i386/include/counter.h =================================================================== --- head/sys/i386/include/counter.h (revision 326259) +++ head/sys/i386/include/counter.h (revision 326260) @@ -1,180 +1,182 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2012 Konstantin Belousov * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef __MACHINE_COUNTER_H__ #define __MACHINE_COUNTER_H__ #include #ifdef INVARIANTS #include #endif #include #include extern struct pcpu __pcpu[]; #define EARLY_COUNTER &__pcpu[0].pc_early_dummy_counter #define counter_enter() do { \ if ((cpu_feature & CPUID_CX8) == 0) \ critical_enter(); \ } while (0) #define counter_exit() do { \ if ((cpu_feature & CPUID_CX8) == 0) \ critical_exit(); \ } while (0) static inline void counter_64_inc_8b(uint64_t *p, int64_t inc) { __asm __volatile( "movl %%fs:(%%esi),%%eax\n\t" "movl %%fs:4(%%esi),%%edx\n" "1:\n\t" "movl %%eax,%%ebx\n\t" "movl %%edx,%%ecx\n\t" "addl (%%edi),%%ebx\n\t" "adcl 4(%%edi),%%ecx\n\t" "cmpxchg8b %%fs:(%%esi)\n\t" "jnz 1b" : : "S" ((char *)p - (char *)&__pcpu[0]), "D" (&inc) : "memory", "cc", "eax", "edx", "ebx", "ecx"); } #ifdef IN_SUBR_COUNTER_C static inline uint64_t counter_u64_read_one_8b(uint64_t *p) { uint32_t res_lo, res_high; __asm __volatile( "movl %%eax,%%ebx\n\t" "movl %%edx,%%ecx\n\t" "cmpxchg8b (%2)" : "=a" (res_lo), "=d"(res_high) : "SD" (p) : "cc", "ebx", "ecx"); return (res_lo + ((uint64_t)res_high << 32)); } static inline uint64_t counter_u64_fetch_inline(uint64_t *p) { uint64_t res; int i; res = 0; if ((cpu_feature & CPUID_CX8) == 0) { /* * The machines without cmpxchg8b are not SMP. * Disabling the preemption provides atomicity of the * counter reading, since update is done in the * critical section as well. */ critical_enter(); CPU_FOREACH(i) { res += *(uint64_t *)((char *)p + sizeof(struct pcpu) * i); } critical_exit(); } else { CPU_FOREACH(i) res += counter_u64_read_one_8b((uint64_t *)((char *)p + sizeof(struct pcpu) * i)); } return (res); } static inline void counter_u64_zero_one_8b(uint64_t *p) { __asm __volatile( "movl (%0),%%eax\n\t" "movl 4(%0),%%edx\n" "xorl %%ebx,%%ebx\n\t" "xorl %%ecx,%%ecx\n\t" "1:\n\t" "cmpxchg8b (%0)\n\t" "jnz 1b" : : "SD" (p) : "memory", "cc", "eax", "edx", "ebx", "ecx"); } static void counter_u64_zero_one_cpu(void *arg) { uint64_t *p; p = (uint64_t *)((char *)arg + sizeof(struct pcpu) * PCPU_GET(cpuid)); counter_u64_zero_one_8b(p); } static inline void counter_u64_zero_inline(counter_u64_t c) { int i; if ((cpu_feature & CPUID_CX8) == 0) { critical_enter(); CPU_FOREACH(i) *(uint64_t *)((char *)c + sizeof(struct pcpu) * i) = 0; critical_exit(); } else { smp_rendezvous(smp_no_rendezvous_barrier, counter_u64_zero_one_cpu, smp_no_rendezvous_barrier, c); } } #endif #define counter_u64_add_protected(c, inc) do { \ if ((cpu_feature & CPUID_CX8) == 0) { \ CRITICAL_ASSERT(curthread); \ *(uint64_t *)zpcpu_get(c) += (inc); \ } else \ counter_64_inc_8b((c), (inc)); \ } while (0) static inline void counter_u64_add(counter_u64_t c, int64_t inc) { if ((cpu_feature & CPUID_CX8) == 0) { critical_enter(); *(uint64_t *)zpcpu_get(c) += inc; critical_exit(); } else { counter_64_inc_8b(c, inc); } } #endif /* ! __MACHINE_COUNTER_H__ */ Index: head/sys/i386/include/cputypes.h =================================================================== --- head/sys/i386/include/cputypes.h (revision 326259) +++ head/sys/i386/include/cputypes.h (revision 326260) @@ -1,71 +1,73 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1993 Christopher G. Demetriou * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_CPUTYPES_H_ #define _MACHINE_CPUTYPES_H_ #include /* * Classes of processor. */ #define CPUCLASS_286 0 #define CPUCLASS_386 1 #define CPUCLASS_486 2 #define CPUCLASS_586 3 #define CPUCLASS_686 4 /* * Kinds of processor. */ #define CPU_286 0 /* Intel 80286 */ #define CPU_386SX 1 /* Intel 80386SX */ #define CPU_386 2 /* Intel 80386DX */ #define CPU_486SX 3 /* Intel 80486SX */ #define CPU_486 4 /* Intel 80486DX */ #define CPU_586 5 /* Intel Pentium */ #define CPU_486DLC 6 /* Cyrix 486DLC */ #define CPU_686 7 /* Pentium Pro */ #define CPU_M1SC 8 /* Cyrix M1sc (aka 5x86) */ #define CPU_M1 9 /* Cyrix M1 (aka 6x86) */ #define CPU_BLUE 10 /* IBM BlueLighting CPU */ #define CPU_M2 11 /* Cyrix M2 (enhanced 6x86 with MMX) */ #define CPU_NX586 12 /* NexGen (now AMD) 586 */ #define CPU_CY486DX 13 /* Cyrix 486S/DX/DX2/DX4 */ #define CPU_PII 14 /* Intel Pentium II */ #define CPU_PIII 15 /* Intel Pentium III */ #define CPU_P4 16 /* Intel Pentium 4 */ #define CPU_GEODE1100 17 /* NS Geode SC1100 */ #ifndef LOCORE extern int cpu; extern int cpu_class; #endif #endif /* !_MACHINE_CPUTYPES_H_ */ Index: head/sys/i386/include/elan_mmcr.h =================================================================== --- head/sys/i386/include/elan_mmcr.h (revision 326259) +++ head/sys/i386/include/elan_mmcr.h (revision 326260) @@ -1,300 +1,302 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2004 John Birrell * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* AMD Elan SC520 Memory Mapped Configuration Region (MMCR). * * The layout of this structure is documented by AMD in the Elan SC520 * Microcontroller Register Set Manual. The field names match those * described in that document. The overall structure size must be 4096 * bytes. Ignore fields with the 'pad' prefix - they are only present for * alignment purposes. * * $FreeBSD$ */ #ifndef _MACHINE_ELAN_MMCR_H_ #define _MACHINE_ELAN_MMCR_H_ 1 struct elan_mmcr { /* CPU */ u_int16_t REVID; u_int8_t CPUCTL; u_int8_t pad_0x003[0xd]; /* SDRAM Controller */ u_int16_t DRCCTL; u_int16_t DRCTMCTL; u_int16_t DRCCFG; u_int16_t DRCBENDADR; u_int8_t pad_0x01a[0x6]; u_int8_t ECCCTL; u_int8_t ECCSTA; u_int8_t ECCCKBPOS; u_int8_t ECCCKTEST; u_int32_t ECCSBADD; u_int32_t ECCMBADD; u_int8_t pad_0x02c[0x14]; /* SDRAM Buffer */ u_int8_t DBCTL; u_int8_t pad_0x041[0xf]; /* ROM/Flash Controller */ u_int16_t BOOTCSCTL; u_int8_t pad_0x052[0x2]; u_int16_t ROMCS1CTL; u_int16_t ROMCS2CTL; u_int8_t pad_0x058[0x8]; /* PCI Bus Host Bridge */ u_int16_t HBCTL; u_int16_t HBTGTIRQCTL; u_int16_t HBTGTIRQSTA; u_int16_t HBMSTIRQCTL; u_int16_t HBMSTIRQSTA; u_int8_t pad_0x06a[0x2]; u_int32_t MSTINTADD; /* System Arbitration */ u_int8_t SYSARBCTL; u_int8_t PCIARBSTA; u_int16_t SYSARBMENB; u_int32_t ARBPRICTL; u_int8_t pad_0x078[0x8]; /* System Address Mapping */ u_int32_t ADDDECCTL; u_int32_t WPVSTA; u_int32_t PAR0; u_int32_t PAR1; u_int32_t PAR2; u_int32_t PAR3; u_int32_t PAR4; u_int32_t PAR5; u_int32_t PAR6; u_int32_t PAR7; u_int32_t PAR8; u_int32_t PAR9; u_int32_t PAR10; u_int32_t PAR11; u_int32_t PAR12; u_int32_t PAR13; u_int32_t PAR14; u_int32_t PAR15; u_int8_t pad_0x0c8[0xb38]; /* GP Bus Controller */ u_int8_t GPECHO; u_int8_t GPCSDW; u_int16_t GPCSQUAL; u_int8_t pad_0xc04[0x4]; u_int8_t GPCSRT; u_int8_t GPCSPW; u_int8_t GPCSOFF; u_int8_t GPRDW; u_int8_t GPRDOFF; u_int8_t GPWRW; u_int8_t GPWROFF; u_int8_t GPALEW; u_int8_t GPALEOFF; u_int8_t pad_0xc11[0xf]; /* Programmable Input/Output */ u_int16_t PIOPFS15_0; u_int16_t PIOPFS31_16; u_int8_t CSPFS; u_int8_t pad_0xc25; u_int8_t CLKSEL; u_int8_t pad_0xc27; u_int16_t DSCTL; u_int16_t PIODIR15_0; u_int16_t PIODIR31_16; u_int8_t pad_0xc2e[0x2]; u_int16_t PIODATA15_0; u_int16_t PIODATA31_16; u_int16_t PIOSET15_0; u_int16_t PIOSET31_16; u_int16_t PIOCLR15_0; u_int16_t PIOCLR31_16; u_int8_t pad_0xc3c[0x24]; /* Software Timer */ u_int16_t SWTMRMILLI; u_int16_t SWTMRMICRO; u_int8_t SWTMRCFG; u_int8_t pad_0xc65[0xb]; /* General-Purpose Timers */ u_int8_t GPTMRSTA; u_int8_t pad_0xc71; u_int16_t GPTMR0CTL; u_int16_t GPTMR0CNT; u_int16_t GPTMR0MAXCMPA; u_int16_t GPTMR0MAXCMPB; u_int16_t GPTMR1CTL; u_int16_t GPTMR1CNT; u_int16_t GPTMR1MAXCMPA; u_int16_t GPTMR1MAXCMPB; u_int16_t GPTMR2CTL; u_int16_t GPTMR2CNT; u_int8_t pad_0xc86[0x8]; u_int16_t GPTMR2MAXCMPA; u_int8_t pad_0xc90[0x20]; /* Watchdog Timer */ u_int16_t WDTMRCTL; u_int16_t WDTMRCNTL; u_int16_t WDTMRCNTH; u_int8_t pad_0xcb6[0xa]; /* UART Serial Ports */ u_int8_t UART1CTL; u_int8_t UART1STA; u_int8_t UART1FCRSHAD; u_int8_t pad_0xcc3; u_int8_t UART2CTL; u_int8_t UART2STA; u_int8_t UART2FCRSHAD; u_int8_t pad_0xcc7[0x9]; /* Synchronous Serial Interface */ u_int8_t SSICTL; u_int8_t SSIXMIT; u_int8_t SSICMD; u_int8_t SSISTA; u_int8_t SSIRCV; u_int8_t pad_0xcd5[0x2b]; /* Programmable Interrupt Controller */ u_int8_t PICICR; u_int8_t pad_0xd01; u_int8_t MPICMODE; u_int8_t SL1PICMODE; u_int8_t SL2PICMODE; u_int8_t pad_0xd05[0x3]; u_int16_t SWINT16_1; u_int8_t SWINT22_17; u_int8_t pad_0xd0b[0x5]; u_int16_t INTPINPOL; u_int8_t pad_0xd12[0x2]; u_int16_t PCIHOSTMAP; u_int8_t pad_0xd16[0x2]; u_int16_t ECCMAP; u_int8_t GPTMR0MAP; u_int8_t GPTMR1MAP; u_int8_t GPTMR2MAP; u_int8_t pad_0xd1d[0x3]; u_int8_t PIT0MAP; u_int8_t PIT1MAP; u_int8_t PIT2MAP; u_int8_t pad_0xd23[0x5]; u_int8_t UART1MAP; u_int8_t UART2MAP; u_int8_t pad_0xd2a[0x6]; u_int8_t PCIINTAMAP; u_int8_t PCIINTBMAP; u_int8_t PCIINTCMAP; u_int8_t PCIINTDMAP; u_int8_t pad_0xd34[0xc]; u_int8_t DMABCINTMAP; u_int8_t SSIMAP; u_int8_t WDTMAP; u_int8_t RTCMAP; u_int8_t WPVMAP; u_int8_t ICEMAP; u_int8_t FERRMAP; u_int8_t pad_0xd47[0x9]; u_int8_t GP0IMAP; u_int8_t GP1IMAP; u_int8_t GP2IMAP; u_int8_t GP3IMAP; u_int8_t GP4IMAP; u_int8_t GP5IMAP; u_int8_t GP6IMAP; u_int8_t GP7IMAP; u_int8_t GP8IMAP; u_int8_t GP9IMAP; u_int8_t GP10IMAP; u_int8_t pad_0xd5b[0x15]; /* Reset Generation */ u_int8_t SYSINFO; u_int8_t pad_0xd71; u_int8_t RESCFG; u_int8_t pad_0xd73; u_int8_t RESSTA; u_int8_t pad_0xd75[0xb]; /* GP DMA Controller */ u_int8_t GPDMACTL; u_int8_t GPDMAMMIO; u_int16_t GPDMAEXTCHMAPA; u_int16_t GPDMAEXTCHMAPB; u_int8_t GPDMAEXTPG0; u_int8_t GPDMAEXTPG1; u_int8_t GPDMAEXTPG2; u_int8_t GPDMAEXTPG3; u_int8_t GPDMAEXTPG5; u_int8_t GPDMAEXTPG6; u_int8_t GPDMAEXTPG7; u_int8_t pad_0xd8d[0x3]; u_int8_t GPDMAEXTTC3; u_int8_t GPDMAEXTTC5; u_int8_t GPDMAEXTTC6; u_int8_t GPDMAEXTTC7; u_int8_t pad_0xd94[0x4]; u_int8_t GPDMABCCTL; u_int8_t GPDMABCSTA; u_int8_t GPDMABSINTENB; u_int8_t GPDMABCVAL; u_int8_t pad_0xd9c[0x4]; u_int16_t GPDMANXTADDL3; u_int16_t GPDMANXTADDH3; u_int16_t GPDMANXTADDL5; u_int16_t GPDMANXTADDH5; u_int16_t GPDMANXTADDL6; u_int16_t GPDMANXTADDH6; u_int16_t GPDMANXTADDL7; u_int16_t GPDMANXTADDH7; u_int16_t GPDMANXTTCL3; u_int8_t GPDMANXTTCH3; u_int8_t pad_0xdb3; u_int16_t GPDMANXTTCL5; u_int8_t GPDMANXTTCH5; u_int8_t pad_0xdb7; u_int16_t GPDMANXTTCL6; u_int8_t GPDMANXTTCH6; u_int8_t pad_0xdbb; u_int16_t GPDMANXTTCL7; u_int8_t GPDMANXTTCH7; u_int8_t pad_0xdc0[0x240]; }; CTASSERT(sizeof(struct elan_mmcr) == 4096); extern volatile struct elan_mmcr * elan_mmcr; #endif /* _MACHINE_ELAN_MMCR_H_ */ Index: head/sys/i386/include/gdb_machdep.h =================================================================== --- head/sys/i386/include/gdb_machdep.h (revision 326259) +++ head/sys/i386/include/gdb_machdep.h (revision 326260) @@ -1,52 +1,54 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2004 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_GDB_MACHDEP_H_ #define _MACHINE_GDB_MACHDEP_H_ #define GDB_BUFSZ 400 #define GDB_NREGS 16 #define GDB_REG_PC 8 static __inline size_t gdb_cpu_regsz(int regnum __unused) { return (sizeof(int)); } static __inline int gdb_cpu_query(void) { return (0); } void *gdb_cpu_getreg(int, size_t *); void gdb_cpu_setreg(int, void *); int gdb_cpu_signal(int, int); #endif /* !_MACHINE_GDB_MACHDEP_H_ */ Index: head/sys/i386/include/if_wl_wavelan.h =================================================================== --- head/sys/i386/include/if_wl_wavelan.h (revision 326259) +++ head/sys/i386/include/if_wl_wavelan.h (revision 326260) @@ -1,167 +1,169 @@ /* $FreeBSD$ */ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain all copyright * notices, this list of conditions and the following disclaimer. * 2. The names of the authors may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef _CHIPS_WAVELAN_H #define _CHIPS_WAVELAN_H /* This file contains definitions that are common for all versions of * the NCR WaveLAN */ #define WAVELAN_ADDR_SIZE 6 /* Size of a MAC address */ #define WAVELAN_MTU 1500 /* Maximum size of Wavelan packet */ /* Modem Management Controler write commands */ #define MMC_ENCR_KEY 0x00 /* to 0x07 */ #define MMC_ENCR_ENABLE 0x08 #define MMC_DES_IO_INVERT 0x0a #define MMC_LOOPT_SEL 0x10 #define MMC_JABBER_ENABLE 0x11 #define MMC_FREEZE 0x12 #define MMC_ANTEN_SEL 0x13 #define MMC_IFS 0x14 #define MMC_MOD_DELAY 0x15 #define MMC_JAM_TIME 0x16 #define MMC_THR_PRE_SET 0x18 #define MMC_DECAY_PRM 0x19 #define MMC_DECAY_UPDAT_PRM 0x1a #define MMC_QUALITY_THR 0x1b #define MMC_NETW_ID_L 0x1c #define MMC_NETW_ID_H 0x1d #define MMC_MODE_SEL 0x1e #define MMC_EECTRL 0x20 /* 2.4 Gz */ #define MMC_EEADDR 0x21 /* 2.4 Gz */ #define MMC_EEDATAL 0x22 /* 2.4 Gz */ #define MMC_EEDATAH 0x23 /* 2.4 Gz */ #define MMC_ANALCTRL 0x24 /* 2.4 Gz */ /* fields in MMC registers that relate to EEPROM in WaveMODEM daughtercard */ #define MMC_EECTRL_EEPRE 0x10 /* 2.4 Gz EEPROM Protect Reg Enable */ #define MMC_EECTRL_DWLD 0x08 /* 2.4 Gz EEPROM Download Synths */ #define MMC_EECTRL_EEOP 0x07 /* 2.4 Gz EEPROM Opcode mask */ #define MMC_EECTRL_EEOP_READ 0x06 /* 2.4 Gz EEPROM Read Opcode */ #define MMC_EEADDR_CHAN 0xf0 /* 2.4 Gz EEPROM Channel # mask */ #define MMC_EEADDR_WDCNT 0x0f /* 2.4 Gz EEPROM DNLD WordCount-1 */ #define MMC_ANALCTRL_ANTPOL 0x02 /* 2.4 Gz Antenna Polarity mask */ #define MMC_ANALCTRL_EXTANT 0x01 /* 2.4 Gz External Antenna mask */ /* MMC read register names */ #define MMC_DCE_STATUS 0x10 #define MMC_CORRECT_NWID_L 0x14 #define MMC_CORRECT_NWID_H 0x15 #define MMC_WRONG_NWID_L 0x16 #define MMC_WRONG_NWID_H 0x17 #define MMC_THR_PRE_SET 0x18 #define MMC_SIGNAL_LVL 0x19 #define MMC_SILENCE_LVL 0x1a #define MMC_SIGN_QUAL 0x1b #define MMC_DES_AVAIL 0x09 #define MMC_EECTRLstat 0x20 /* 2.4 Gz EEPROM r/w/dwld status */ #define MMC_EEDATALrv 0x22 /* 2.4 Gz EEPROM read value */ #define MMC_EEDATAHrv 0x23 /* 2.4 Gz EEPROM read value */ /* fields in MMC registers that relate to EEPROM in WaveMODEM daughtercard */ #define MMC_EECTRLstat_ID24 0xf0 /* 2.4 Gz =A0 rev-A, =B0 rev-B */ #define MMC_EECTRLstat_DWLD 0x08 /* 2.4 Gz Synth/Tx-Pwr DWLD busy */ #define MMC_EECTRLstat_EEBUSY 0x04 /* 2.4 Gz EEPROM busy */ /* additional socket ioctl params for wl card * see sys/sockio.h for numbers. The 2nd params here * must be greater than any values in sockio.h */ #define SIOCGWLCNWID _IOWR('i', 60, struct ifreq) /* get wlan current nwid */ #define SIOCSWLCNWID _IOWR('i', 61, struct ifreq) /* set wlan current nwid */ #define SIOCGWLPSA _IOWR('i', 62, struct ifreq) /* get wlan PSA (all) */ #define SIOCSWLPSA _IOWR('i', 63, struct ifreq) /* set wlan PSA (all) */ #define SIOCDWLCACHE _IOW('i', 64, struct ifreq) /* clear SNR cache */ #define SIOCSWLTHR _IOW('i', 65, struct ifreq) /* set new quality threshold */ #define SIOCGWLEEPROM _IOWR('i', 66, struct ifreq) /* get modem EEPROM */ #define SIOCGWLCACHE _IOWR('i', 67, struct ifreq) /* get SNR cache */ #define SIOCGWLCITEM _IOWR('i', 68, struct ifreq) /* get cache element count */ /* PSA address definitions */ #define WLPSA_ID 0x0 /* ID byte (0 for ISA, 0x14 for MCA) */ #define WLPSA_IO1 0x1 /* I/O address 1 */ #define WLPSA_IO2 0x2 /* I/O address 2 */ #define WLPSA_IO3 0x3 /* I/O address 3 */ #define WLPSA_BR1 0x4 /* Bootrom address 1 */ #define WLPSA_BR2 0x5 /* Bootrom address 2 */ #define WLPSA_BR3 0x6 /* Bootrom address 3 */ #define WLPSA_HWCONF 0x7 /* HW config bits */ #define WLPSA_IRQNO 0x8 /* IRQ value */ #define WLPSA_UNIMAC 0x10 /* Universal MAC address */ #define WLPSA_LOCALMAC 0x16 /* Locally configured MAC address */ #define WLPSA_MACSEL 0x1c /* MAC selector */ #define WLPSA_COMPATNO 0x1d /* compatibility number */ #define WLPSA_THRESH 0x1e /* RF modem threshold preset */ #define WLPSA_FEATSEL 0x1f /* feature select */ #define WLPSA_SUBBAND 0x20 /* subband selector */ #define WLPSA_QUALTHRESH 0x21 /* RF modem quality threshold preset */ #define WLPSA_HWVERSION 0x22 /* hardware version indicator */ #define WLPSA_NWID 0x23 /* network ID */ #define WLPSA_NWIDENABLE 0x24 /* network ID enable */ #define WLPSA_SECURITY 0x25 /* datalink security enable */ #define WLPSA_DESKEY 0x26 /* datalink security DES key */ #define WLPSA_DBWIDTH 0x2f /* databus width select */ #define WLPSA_CALLCODE 0x30 /* call code (japan only) */ #define WLPSA_CONFIGURED 0x3c /* configuration status */ #define WLPSA_CRCLOW 0x3d /* CRC-16 (lowbyte) */ #define WLPSA_CRCHIGH 0x3e /* (highbyte) */ #define WLPSA_CRCOK 0x3f /* CRC OK flag */ #define WLPSA_COMPATNO_WL24B 0x04 /* 2.4 Gz WaveMODEM ISA rev-B */ /* * signal strength cache * * driver (wlp only at the moment) keeps cache of last * IP (only) packets to arrive including signal strength info. * daemons may read this with kvm. See if_wlp.c for globals * that may be accessed through kvm. * * Each entry in the w_sigcache has a unique macsrc and age. * Each entry is identified by its macsrc field. * Age of the packet is identified by its age field. */ #define MAXCACHEITEMS 10 #ifndef INT_MAX #define INT_MAX 2147483647 #endif #define MAX_AGE (INT_MAX - MAXCACHEITEMS) /* signal is 7 bits, 0..63, although it doesn't seem to get to 63. * silence is 7 bits, 0..63 * quality is 4 bits, 0..15 */ struct w_sigcache { char macsrc[6]; /* unique MAC address for entry */ int ipsrc; /* ip address associated with packet */ int signal; /* signal strength of the packet */ int silence; /* silence of the packet */ int quality; /* quality of the packet */ int snr; /* packet has unique age between 1 to MAX_AGE - 1 */ }; #endif /* _CHIPS_WAVELAN_H */ Index: head/sys/i386/include/intr_machdep.h =================================================================== --- head/sys/i386/include/intr_machdep.h (revision 326259) +++ head/sys/i386/include/intr_machdep.h (revision 326260) @@ -1,186 +1,188 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2003 John Baldwin * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef __MACHINE_INTR_MACHDEP_H__ #define __MACHINE_INTR_MACHDEP_H__ #ifdef _KERNEL /* * The maximum number of I/O interrupts we allow. This number is rather * arbitrary as it is just the maximum IRQ resource value. The interrupt * source for a given IRQ maps that I/O interrupt to device interrupt * source whether it be a pin on an interrupt controller or an MSI interrupt. * The 16 ISA IRQs are assigned fixed IDT vectors, but all other device * interrupts allocate IDT vectors on demand. Currently we have 191 IDT * vectors available for device interrupts. On many systems with I/O APICs, * a lot of the IRQs are not used, so this number can be much larger than * 191 and still be safe since only interrupt sources in actual use will * allocate IDT vectors. * * The first 255 IRQs (0 - 254) are reserved for ISA IRQs and PCI intline IRQs. * IRQ values from 256 to 767 are used by MSI. When running under the Xen * Hypervisor, IRQ values from 768 to 4863 are available for binding to * event channel events. We leave 255 unused to avoid confusion since 255 is * used in PCI to indicate an invalid IRQ. */ #define NUM_MSI_INTS 512 #define FIRST_MSI_INT 256 #ifdef XENHVM #include #include #define NUM_EVTCHN_INTS NR_EVENT_CHANNELS #define FIRST_EVTCHN_INT \ (FIRST_MSI_INT + NUM_MSI_INTS) #define LAST_EVTCHN_INT \ (FIRST_EVTCHN_INT + NUM_EVTCHN_INTS - 1) #else /* !XENHVM */ #define NUM_EVTCHN_INTS 0 #endif #define NUM_IO_INTS (FIRST_MSI_INT + NUM_MSI_INTS + NUM_EVTCHN_INTS) /* * Default base address for MSI messages on x86 platforms. */ #define MSI_INTEL_ADDR_BASE 0xfee00000 /* * - 1 ??? dummy counter. * - 2 counters for each I/O interrupt. * - 1 counter for each CPU for lapic timer. * - 9 counters for each CPU for IPI counters for SMP. */ #ifdef SMP #define INTRCNT_COUNT (1 + NUM_IO_INTS * 2 + (1 + 9) * MAXCPU) #else #define INTRCNT_COUNT (1 + NUM_IO_INTS * 2 + 1) #endif #ifndef LOCORE typedef void inthand_t(void); #define IDTVEC(name) __CONCAT(X,name) struct intsrc; /* * Methods that a PIC provides to mask/unmask a given interrupt source, * "turn on" the interrupt on the CPU side by setting up an IDT entry, and * return the vector associated with this source. */ struct pic { void (*pic_enable_source)(struct intsrc *); void (*pic_disable_source)(struct intsrc *, int); void (*pic_eoi_source)(struct intsrc *); void (*pic_enable_intr)(struct intsrc *); void (*pic_disable_intr)(struct intsrc *); int (*pic_vector)(struct intsrc *); int (*pic_source_pending)(struct intsrc *); void (*pic_suspend)(struct pic *); void (*pic_resume)(struct pic *, bool suspend_cancelled); int (*pic_config_intr)(struct intsrc *, enum intr_trigger, enum intr_polarity); int (*pic_assign_cpu)(struct intsrc *, u_int apic_id); void (*pic_reprogram_pin)(struct intsrc *); TAILQ_ENTRY(pic) pics; }; /* Flags for pic_disable_source() */ enum { PIC_EOI, PIC_NO_EOI, }; /* * An interrupt source. The upper-layer code uses the PIC methods to * control a given source. The lower-layer PIC drivers can store additional * private data in a given interrupt source such as an interrupt pin number * or an I/O APIC pointer. */ struct intsrc { struct pic *is_pic; struct intr_event *is_event; u_long *is_count; u_long *is_straycount; u_int is_index; u_int is_handlers; u_int is_cpu; }; struct trapframe; #ifdef SMP extern cpuset_t intr_cpus; #endif extern struct mtx icu_lock; extern int elcr_found; #ifdef SMP extern int msix_disable_migration; #endif #ifndef DEV_ATPIC void atpic_reset(void); #endif /* XXX: The elcr_* prototypes probably belong somewhere else. */ int elcr_probe(void); enum intr_trigger elcr_read_trigger(u_int irq); void elcr_resume(void); void elcr_write_trigger(u_int irq, enum intr_trigger trigger); #ifdef SMP void intr_add_cpu(u_int cpu); #endif int intr_add_handler(const char *name, int vector, driver_filter_t filter, driver_intr_t handler, void *arg, enum intr_type flags, void **cookiep); #ifdef SMP int intr_bind(u_int vector, u_char cpu); #endif int intr_config_intr(int vector, enum intr_trigger trig, enum intr_polarity pol); int intr_describe(u_int vector, void *ih, const char *descr); void intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame); u_int intr_next_cpu(void); struct intsrc *intr_lookup_source(int vector); int intr_register_pic(struct pic *pic); int intr_register_source(struct intsrc *isrc); int intr_remove_handler(void *cookie); void intr_resume(bool suspend_cancelled); void intr_suspend(void); void intr_reprogram(void); void intrcnt_add(const char *name, u_long **countp); void nexus_add_irq(u_long irq); int msi_alloc(device_t dev, int count, int maxcount, int *irqs); void msi_init(void); int msi_map(int irq, uint64_t *addr, uint32_t *data); int msi_release(int* irqs, int count); int msix_alloc(device_t dev, int *irq); int msix_release(int irq); #endif /* !LOCORE */ #endif /* _KERNEL */ #endif /* !__MACHINE_INTR_MACHDEP_H__ */ Index: head/sys/i386/include/ioctl_bt848.h =================================================================== --- head/sys/i386/include/ioctl_bt848.h (revision 326259) +++ head/sys/i386/include/ioctl_bt848.h (revision 326260) @@ -1,40 +1,42 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2003 David O'Brien * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_IOCTL_BT848_H_ #define _MACHINE_IOCTL_BT848_H_ #include #ifdef __CC_SUPPORTS_WARNING #warning Include dev/bktr/ioctl_bt848.h instead of this header. #endif #include #endif /* _MACHINE_IOCTL_BT848_H_ */ Index: head/sys/i386/include/ioctl_meteor.h =================================================================== --- head/sys/i386/include/ioctl_meteor.h (revision 326259) +++ head/sys/i386/include/ioctl_meteor.h (revision 326260) @@ -1,40 +1,42 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2003 David O'Brien * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_IOCTL_METEOR_H_ #define _MACHINE_IOCTL_METEOR_H_ #include #ifdef __CC_SUPPORTS_WARNING #warning Include dev/bktr/ioctl_meteor.h instead of this header. #endif #include #endif /* _MACHINE_IOCTL_METEOR_H_ */ Index: head/sys/i386/include/iodev.h =================================================================== --- head/sys/i386/include/iodev.h (revision 326259) +++ head/sys/i386/include/iodev.h (revision 326260) @@ -1,46 +1,48 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2004 Mark R V Murray * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_IODEV_H_ #define _MACHINE_IODEV_H_ #ifdef _KERNEL #include #define iodev_read_1 inb #define iodev_read_2 inw #define iodev_read_4 inl #define iodev_write_1 outb #define iodev_write_2 outw #define iodev_write_4 outl int iodev_open(struct thread *td); int iodev_close(struct thread *td); int iodev_ioctl(u_long cmd, caddr_t data); #endif /* _KERNEL */ #endif /* _MACHINE_IODEV_H_ */ Index: head/sys/i386/include/kdb.h =================================================================== --- head/sys/i386/include/kdb.h (revision 326259) +++ head/sys/i386/include/kdb.h (revision 326260) @@ -1,59 +1,61 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2004 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_KDB_H_ #define _MACHINE_KDB_H_ #include #include #define KDB_STOPPEDPCB(pc) &stoppcbs[pc->pc_cpuid] static __inline void kdb_cpu_clear_singlestep(void) { kdb_frame->tf_eflags &= ~PSL_T; } static __inline void kdb_cpu_set_singlestep(void) { kdb_frame->tf_eflags |= PSL_T; } static __inline void kdb_cpu_sync_icache(unsigned char *addr, size_t size) { } static __inline void kdb_cpu_trap(int type, int code) { } #endif /* _MACHINE_KDB_H_ */ Index: head/sys/i386/include/memdev.h =================================================================== --- head/sys/i386/include/memdev.h (revision 326259) +++ head/sys/i386/include/memdev.h (revision 326260) @@ -1,40 +1,42 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2004 Mark R V Murray * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_MEMDEV_H_ #define _MACHINE_MEMDEV_H_ #define CDEV_MINOR_MEM 0 #define CDEV_MINOR_KMEM 1 d_open_t memopen; d_read_t memrw; d_ioctl_t memioctl; d_mmap_t memmmap; #endif /* _MACHINE_MEMDEV_H_ */ Index: head/sys/i386/include/minidump.h =================================================================== --- head/sys/i386/include/minidump.h (revision 326259) +++ head/sys/i386/include/minidump.h (revision 326260) @@ -1,45 +1,47 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2006 Peter Wemm * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_MINIDUMP_H_ #define _MACHINE_MINIDUMP_H_ 1 #define MINIDUMP_MAGIC "minidump FreeBSD/i386" #define MINIDUMP_VERSION 1 struct minidumphdr { char magic[24]; uint32_t version; uint32_t msgbufsize; uint32_t bitmapsize; uint32_t ptesize; uint32_t kernbase; uint32_t paemode; }; #endif /* _MACHINE_MINIDUMP_H_ */ Index: head/sys/i386/include/mp_watchdog.h =================================================================== --- head/sys/i386/include/mp_watchdog.h (revision 326259) +++ head/sys/i386/include/mp_watchdog.h (revision 326260) @@ -1,34 +1,36 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2004 Robert N. M. Watson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_MP_WATCHDOG_H_ #define _MACHINE_MP_WATCHDOG_H_ void ap_watchdog(u_int cpuid); #endif /* !_MACHINE_MP_WATCHDOG_H_ */ Index: head/sys/i386/include/pc/bios.h =================================================================== --- head/sys/i386/include/pc/bios.h (revision 326259) +++ head/sys/i386/include/pc/bios.h (revision 326260) @@ -1,353 +1,355 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1997 Michael Smith * Copyright (c) 1998 Jonathan Lemon * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_PC_BIOS_H_ #define _MACHINE_PC_BIOS_H_ /* * Signature structure for the BIOS32 Service Directory header */ struct bios32_SDheader { u_int8_t sig[4]; u_int32_t entry; u_int8_t revision; u_int8_t len; u_int8_t cksum; u_int8_t pad[5]; }; /* * PnP BIOS presence structure */ struct PnPBIOS_table { u_int8_t sig[4]; /* "$PnP */ u_int8_t version; /* should be 0x10 */ u_int8_t len; /* total structure length */ u_int16_t control; /* BIOS feature flags */ u_int8_t cksum; /* checksum */ u_int32_t evflagaddr; /* address of event notificaton flag */ u_int16_t rmentryoffset; /* real-mode entry offset */ u_int16_t rmentryseg; /* segment */ u_int16_t pmentryoffset; /* protected-mode entry offset */ u_int32_t pmentrybase; /* segment base */ u_int32_t oemdevid; /* motherboard EISA ID */ u_int16_t rmbiosseg; /* real-mode BIOS segment */ u_int32_t pmdataseg; /* protected-mode data segment */ } __packed; /* * PnP BIOS return codes */ #define PNP_SUCCESS 0x00 #define PNP_NOT_SET_STATICALLY 0x7f #define PNP_UNKNOWN_FUNCTION 0x81 #define PNP_FUNCTION_NOT_SUPPORTED 0x82 #define PNP_INVALID_HANDLE 0x83 #define PNP_BAD_PARAMETER 0x84 #define PNP_SET_FAILED 0x85 #define PNP_EVENTS_NOT_PENDING 0x86 #define PNP_SYSTEM_NOT_DOCKED 0x87 #define PNP_NO_ISA_PNP_CARDS 0x88 #define PNP_UNABLE_TO_DETERMINE_DOCK_CAPABILITIES 0x89 #define PNP_CONFIG_CHANGE_FAILED_NO_BATTERY 0x8a #define PNP_CONFIG_CHANGE_FAILED_RESOURCE_CONFLICT 0x8b #define PNP_BUFFER_TOO_SMALL 0x8c #define PNP_USE_ESCD_SUPPORT 0x8d #define PNP_MESSAGE_NOT_SUPPORTED 0x8e #define PNP_HARDWARE_ERROR 0x8f /* * DMI return codes */ #define DMI_SUCCESS 0x00 #define DMI_UNKNOWN_FUNCTION 0x81 #define DMI_FUNCTION_NOT_SUPPORTED 0x82 #define DMI_INVALID_HANDLE 0x83 #define DMI_BAD_PARAMETER 0x84 #define DMI_INVALID_SUBFUNCTION 0x85 #define DMI_NO_CHANGE 0x86 #define DMI_ADD_STRUCTURE_FAILED 0x87 #define DMI_READ_ONLY 0x8d #define DMI_LOCK_NOT_SUPPORTED 0x90 #define DMI_CURRENTLY_LOCKED 0x91 #define DMI_INVALID_LOCK 0x92 /* * format specifiers and defines for bios16() * s = short (16 bits) * i = int (32 bits) * p = pointer (converted to seg:offset) * C,D,U = selector (corresponding to code/data/utility segment) */ #define PNP_COUNT_DEVNODES "sppD", 0x00 #define PNP_GET_DEVNODE "sppsD", 0x01 #define PNP_SET_DEVNODE "sspsD", 0x02 #define PNP_GET_EVENT "spD", 0x03 #define PNP_SEND_MSG "ssD", 0x04 #define PNP_GET_DOCK_INFO "spD", 0x05 #define PNP_SEL_PRIBOOT "ssiiisspD", 0x07 #define PNP_GET_PRIBOOT "sspppppD", 0x08 #define PNP_SET_RESINFO "spD", 0x09 #define PNP_GET_RESINFO "spD", 0x0A #define PNP_GET_APM_ID "sppD", 0x0B #define PNP_GET_ISA_INFO "spD", 0x40 #define PNP_GET_ECSD_INFO "spppD", 0x41 #define PNP_READ_ESCD "spUD", 0x42 #define PNP_WRITE_ESCD "spUD", 0x43 #define PNP_GET_DMI_INFO "spppppD", 0x50 #define PNP_GET_DMI_STRUCTURE "sppUD", 0x51 #define PNP_SET_DMI_STRUCTURE "sppsUD" 0x52 #define PNP_GET_DMI_CHANGE "spUD" 0x53 #define PNP_DMI_CONTROL "sspsUD" 0x54 #define PNP_GET_GPNV_INFO "sppppD" 0x55 #define PNP_READ_GPNV_DATA "ssppUD" 0x56 #define PNP_WRITE_GPNV_DATA "sspsUD" 0x57 #define PNP_BOOT_CHECK "sp", 0x60 #define PNP_COUNT_IPL "sppp", 0x61 #define PNP_GET_BOOTPRI "spp", 0x62 #define PNP_SET_BOOTPRI "sp", 0x63 #define PNP_GET_LASTBOOT "sp", 0x64 #define PNP_GET_BOOTFIRST "sp", 0x65 #define PNP_SET_BOOTFIRST "sp", 0x66 /* * PCI BIOS functions */ #define PCIBIOS_BIOS_PRESENT 0xb101 #define PCIBIOS_READ_CONFIG_BYTE 0xb108 #define PCIBIOS_READ_CONFIG_WORD 0xb109 #define PCIBIOS_READ_CONFIG_DWORD 0xb10a #define PCIBIOS_WRITE_CONFIG_BYTE 0xb10b #define PCIBIOS_WRITE_CONFIG_WORD 0xb10c #define PCIBIOS_WRITE_CONFIG_DWORD 0xb10d #define PCIBIOS_GET_IRQ_ROUTING 0xb10e #define PCIBIOS_ROUTE_INTERRUPT 0xb10f /* * PCI interrupt routing table. * * $PIR in the BIOS segment contains a PIR_table * int 1a:b106 returns PIR_table in buffer at es:(e)di * int 1a:b18e returns PIR_table in buffer at es:(e)di * int 1a:b406 returns es:di pointing to the BIOS PIR_table */ struct PIR_header { int8_t ph_signature[4]; u_int16_t ph_version; u_int16_t ph_length; u_int8_t ph_router_bus; u_int8_t ph_router_dev_fn; u_int16_t ph_pci_irqs; u_int16_t ph_router_vendor; u_int16_t ph_router_device; u_int32_t ph_miniport; u_int8_t ph_res[11]; u_int8_t ph_checksum; } __packed; struct PIR_intpin { u_int8_t link; u_int16_t irqs; } __packed; struct PIR_entry { u_int8_t pe_bus; u_int8_t pe_res1:3; u_int8_t pe_device:5; struct PIR_intpin pe_intpin[4]; u_int8_t pe_slot; u_int8_t pe_res3; } __packed; struct PIR_table { struct PIR_header pt_header; struct PIR_entry pt_entry[0]; } __packed; /* * Int 15:E820 'SMAP' structure */ #define SMAP_SIG 0x534D4150 /* 'SMAP' */ #define SMAP_TYPE_MEMORY 1 #define SMAP_TYPE_RESERVED 2 #define SMAP_TYPE_ACPI_RECLAIM 3 #define SMAP_TYPE_ACPI_NVS 4 #define SMAP_TYPE_ACPI_ERROR 5 #define SMAP_TYPE_DISABLED 6 #define SMAP_TYPE_PMEM 7 #define SMAP_TYPE_PRAM 12 #define SMAP_XATTR_ENABLED 0x00000001 #define SMAP_XATTR_NON_VOLATILE 0x00000002 #define SMAP_XATTR_MASK (SMAP_XATTR_ENABLED | SMAP_XATTR_NON_VOLATILE) struct bios_smap { u_int64_t base; u_int64_t length; u_int32_t type; } __packed; /* Structure extended to include extended attribute field in ACPI 3.0. */ struct bios_smap_xattr { u_int64_t base; u_int64_t length; u_int32_t type; u_int32_t xattr; } __packed; /* * System Management BIOS */ #define SMBIOS_START 0xf0000 #define SMBIOS_STEP 0x10 #define SMBIOS_OFF 0 #define SMBIOS_LEN 4 #define SMBIOS_SIG "_SM_" struct smbios_eps { uint8_t anchor_string[4]; /* '_SM_' */ uint8_t checksum; uint8_t length; uint8_t major_version; uint8_t minor_version; uint16_t maximum_structure_size; uint8_t entry_point_revision; uint8_t formatted_area[5]; uint8_t intermediate_anchor_string[5]; /* '_DMI_' */ uint8_t intermediate_checksum; uint16_t structure_table_length; uint32_t structure_table_address; uint16_t number_structures; uint8_t BCD_revision; }; struct smbios_structure_header { uint8_t type; uint8_t length; uint16_t handle; }; #ifdef _KERNEL #define BIOS_PADDRTOVADDR(x) ((x) + KERNBASE) #define BIOS_VADDRTOPADDR(x) ((x) - KERNBASE) struct bios_oem_signature { char * anchor; /* search anchor string in BIOS memory */ size_t offset; /* offset from anchor (may be negative) */ size_t totlen; /* total length of BIOS string to copy */ } __packed; struct bios_oem_range { u_int from; /* shouldn't be below 0xe0000 */ u_int to; /* shouldn't be above 0xfffff */ } __packed; struct bios_oem { struct bios_oem_range range; struct bios_oem_signature signature[]; } __packed; struct segment_info { u_int base; u_int limit; }; #define BIOSCODE_FLAG 0x01 #define BIOSDATA_FLAG 0x02 #define BIOSUTIL_FLAG 0x04 #define BIOSARGS_FLAG 0x08 struct bios_segments { struct segment_info code32; /* 32-bit code (mandatory) */ struct segment_info code16; /* 16-bit code */ struct segment_info data; /* 16-bit data */ struct segment_info util; /* 16-bit utility */ struct segment_info args; /* 16-bit args */ }; struct bios_regs { u_int eax; u_int ebx; u_int ecx; u_int edx; u_int esi; u_int edi; }; struct bios_args { u_int entry; /* entry point of routine */ struct bios_regs r; struct bios_segments seg; }; /* * BIOS32 Service Directory entry. Caller supplies name, bios32_SDlookup * fills in the rest of the details. */ struct bios32_SDentry { union { u_int8_t name[4]; /* service identifier */ u_int32_t id; /* as a 32-bit value */ } ident; u_int32_t base; /* base of service */ u_int32_t len; /* service length */ u_int32_t entry; /* entrypoint offset from base */ vm_offset_t ventry; /* entrypoint in kernel virtual segment */ }; /* * Exported lookup results */ extern struct bios32_SDentry PCIbios; int bios_oem_strings(struct bios_oem *oem, u_char *buffer, size_t maxlen); uint32_t bios_sigsearch(uint32_t start, u_char *sig, int siglen, int paralen, int sigofs); int bios16(struct bios_args *, char *, ...); int bios16_call(struct bios_regs *, char *); int bios32(struct bios_regs *, u_int, u_short); int bios32_SDlookup(struct bios32_SDentry *ent); void set_bios_selectors(struct bios_segments *, int); #endif #endif /* _MACHINE_PC_BIOS_H_ */ Index: head/sys/i386/include/pcaudioio.h =================================================================== --- head/sys/i386/include/pcaudioio.h (revision 326259) +++ head/sys/i386/include/pcaudioio.h (revision 326260) @@ -1,82 +1,84 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1994 Søren Schmidt * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_PCAUDIOIO_H_ #define _MACHINE_PCAUDIOIO_H_ #include typedef struct audio_prinfo { unsigned sample_rate; /* samples per second */ unsigned channels; /* # of channels (interleaved) */ unsigned precision; /* sample size in bits */ unsigned encoding; /* encoding method used */ unsigned gain; /* volume level: 0 - 255 */ unsigned port; /* input/output device */ unsigned _fill1[4]; unsigned samples; /* samples played */ unsigned eof; /* ?!? */ unsigned char pause; /* !=0 pause, ==0 continue */ unsigned char error; /* !=0 if overflow/underflow */ unsigned char waiting; /* !=0 if others wants access */ unsigned char _fill2[3]; unsigned char open; /* is device open */ unsigned char active; /* !=0 if sound hardware is active */ } audio_prinfo_t; typedef struct audio_info { audio_prinfo_t play; audio_prinfo_t record; unsigned monitor_gain; unsigned _fill[4]; } audio_info_t; #define AUDIO_ENCODING_ULAW (1) /* u-law encoding */ #define AUDIO_ENCODING_ALAW (2) /* A-law encoding */ #define AUDIO_ENCODING_RAW (3) /* linear encoding */ #define AUDIO_MIN_GAIN (0) /* minimum volume value */ #define AUDIO_MAX_GAIN (255) /* maximum volume value */ #define AUDIO_INITINFO(i) memset((void*)i, 0xff, sizeof(audio_info_t)) #define AUDIO_GETINFO _IOR('A', 1, audio_info_t) #define AUDIO_SETINFO _IOWR('A', 2, audio_info_t) #define AUDIO_DRAIN _IO('A', 3) #define AUDIO_FLUSH _IO('A', 4) /* compatibility to /dev/audio */ #define AUDIO_COMPAT_DRAIN _IO('P', 1) #define AUDIO_COMPAT_FLUSH _IO('P', 0) #endif /* !_MACHINE_PCAUDIOIO_H_ */ Index: head/sys/i386/include/pcb_ext.h =================================================================== --- head/sys/i386/include/pcb_ext.h (revision 326259) +++ head/sys/i386/include/pcb_ext.h (revision 326260) @@ -1,53 +1,55 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1997 Jonathan Lemon * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _I386_PCB_EXT_H_ #define _I386_PCB_EXT_H_ /* * Extension to the 386 process control block */ #include #include #include struct pcb_ext { struct segment_descriptor ext_tssd; /* tss descriptor */ struct i386tss ext_tss; /* per-process i386tss */ caddr_t ext_iomap; /* i/o permission bitmap */ struct vm86_kernel ext_vm86; /* vm86 area */ }; #ifdef _KERNEL extern int private_tss; int i386_extend_pcb(struct thread *); #endif #endif /* _I386_PCB_EXT_H_ */ Index: head/sys/i386/include/pcpu.h =================================================================== --- head/sys/i386/include/pcpu.h (revision 326259) +++ head/sys/i386/include/pcpu.h (revision 326260) @@ -1,242 +1,244 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) Peter Wemm * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_PCPU_H_ #define _MACHINE_PCPU_H_ #ifndef _SYS_CDEFS_H_ #error "sys/cdefs.h is a prerequisite for this file" #endif #include #include #include #include /* * The SMP parts are setup in pmap.c and locore.s for the BSP, and * mp_machdep.c sets up the data for the AP's to "see" when they awake. * The reason for doing it via a struct is so that an array of pointers * to each CPU's data can be set up for things like "check curproc on all * other processors" */ #define PCPU_MD_FIELDS \ char pc_monitorbuf[128] __aligned(128); /* cache line */ \ struct pcpu *pc_prvspace; /* Self-reference */ \ struct pmap *pc_curpmap; \ struct i386tss pc_common_tss; \ struct segment_descriptor pc_common_tssd; \ struct segment_descriptor *pc_tss_gdt; \ struct segment_descriptor *pc_fsgs_gdt; \ int pc_currentldt; \ u_int pc_acpi_id; /* ACPI CPU id */ \ u_int pc_apic_id; \ int pc_private_tss; /* Flag indicating private tss*/\ u_int pc_cmci_mask; /* MCx banks for CMCI */ \ u_int pc_vcpu_id; /* Xen vCPU ID */ \ struct mtx pc_cmap_lock; \ void *pc_cmap_pte1; \ void *pc_cmap_pte2; \ caddr_t pc_cmap_addr1; \ caddr_t pc_cmap_addr2; \ vm_offset_t pc_qmap_addr; /* KVA for temporary mappings */\ uint32_t pc_smp_tlb_done; /* TLB op acknowledgement */ \ char __pad[445] #ifdef _KERNEL #if defined(__GNUCLIKE_ASM) && defined(__GNUCLIKE___TYPEOF) /* * Evaluates to the byte offset of the per-cpu variable name. */ #define __pcpu_offset(name) \ __offsetof(struct pcpu, name) /* * Evaluates to the type of the per-cpu variable name. */ #define __pcpu_type(name) \ __typeof(((struct pcpu *)0)->name) /* * Evaluates to the address of the per-cpu variable name. */ #define __PCPU_PTR(name) __extension__ ({ \ __pcpu_type(name) *__p; \ \ __asm __volatile("movl %%fs:%1,%0; addl %2,%0" \ : "=r" (__p) \ : "m" (*(struct pcpu *)(__pcpu_offset(pc_prvspace))), \ "i" (__pcpu_offset(name))); \ \ __p; \ }) /* * Evaluates to the value of the per-cpu variable name. */ #define __PCPU_GET(name) __extension__ ({ \ __pcpu_type(name) __res; \ struct __s { \ u_char __b[MIN(sizeof(__res), 4)]; \ } __s; \ \ if (sizeof(__res) == 1 || sizeof(__res) == 2 || \ sizeof(__res) == 4) { \ __asm __volatile("mov %%fs:%1,%0" \ : "=r" (__s) \ : "m" (*(struct __s *)(__pcpu_offset(name)))); \ *(struct __s *)(void *)&__res = __s; \ } else { \ __res = *__PCPU_PTR(name); \ } \ __res; \ }) /* * Adds a value of the per-cpu counter name. The implementation * must be atomic with respect to interrupts. */ #define __PCPU_ADD(name, val) do { \ __pcpu_type(name) __val; \ struct __s { \ u_char __b[MIN(sizeof(__val), 4)]; \ } __s; \ \ __val = (val); \ if (sizeof(__val) == 1 || sizeof(__val) == 2 || \ sizeof(__val) == 4) { \ __s = *(struct __s *)(void *)&__val; \ __asm __volatile("add %1,%%fs:%0" \ : "=m" (*(struct __s *)(__pcpu_offset(name))) \ : "r" (__s)); \ } else \ *__PCPU_PTR(name) += __val; \ } while (0) /* * Increments the value of the per-cpu counter name. The implementation * must be atomic with respect to interrupts. */ #define __PCPU_INC(name) do { \ CTASSERT(sizeof(__pcpu_type(name)) == 1 || \ sizeof(__pcpu_type(name)) == 2 || \ sizeof(__pcpu_type(name)) == 4); \ if (sizeof(__pcpu_type(name)) == 1) { \ __asm __volatile("incb %%fs:%0" \ : "=m" (*(__pcpu_type(name) *)(__pcpu_offset(name)))\ : "m" (*(__pcpu_type(name) *)(__pcpu_offset(name))));\ } else if (sizeof(__pcpu_type(name)) == 2) { \ __asm __volatile("incw %%fs:%0" \ : "=m" (*(__pcpu_type(name) *)(__pcpu_offset(name)))\ : "m" (*(__pcpu_type(name) *)(__pcpu_offset(name))));\ } else if (sizeof(__pcpu_type(name)) == 4) { \ __asm __volatile("incl %%fs:%0" \ : "=m" (*(__pcpu_type(name) *)(__pcpu_offset(name)))\ : "m" (*(__pcpu_type(name) *)(__pcpu_offset(name))));\ } \ } while (0) /* * Sets the value of the per-cpu variable name to value val. */ #define __PCPU_SET(name, val) do { \ __pcpu_type(name) __val; \ struct __s { \ u_char __b[MIN(sizeof(__val), 4)]; \ } __s; \ \ __val = (val); \ if (sizeof(__val) == 1 || sizeof(__val) == 2 || \ sizeof(__val) == 4) { \ __s = *(struct __s *)(void *)&__val; \ __asm __volatile("mov %1,%%fs:%0" \ : "=m" (*(struct __s *)(__pcpu_offset(name))) \ : "r" (__s)); \ } else { \ *__PCPU_PTR(name) = __val; \ } \ } while (0) #define get_pcpu() __extension__ ({ \ struct pcpu *__pc; \ \ __asm __volatile("movl %%fs:%1,%0" \ : "=r" (__pc) \ : "m" (*(struct pcpu *)(__pcpu_offset(pc_prvspace)))); \ __pc; \ }) #define PCPU_GET(member) __PCPU_GET(pc_ ## member) #define PCPU_ADD(member, val) __PCPU_ADD(pc_ ## member, val) #define PCPU_INC(member) __PCPU_INC(pc_ ## member) #define PCPU_PTR(member) __PCPU_PTR(pc_ ## member) #define PCPU_SET(member, val) __PCPU_SET(pc_ ## member, val) #define OFFSETOF_CURTHREAD 0 #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wnull-dereference" #endif static __inline __pure2 struct thread * __curthread(void) { struct thread *td; __asm("movl %%fs:%1,%0" : "=r" (td) : "m" (*(char *)OFFSETOF_CURTHREAD)); return (td); } #ifdef __clang__ #pragma clang diagnostic pop #endif #define curthread (__curthread()) #define OFFSETOF_CURPCB 16 static __inline __pure2 struct pcb * __curpcb(void) { struct pcb *pcb; __asm("movl %%fs:%1,%0" : "=r" (pcb) : "m" (*(char *)OFFSETOF_CURPCB)); return (pcb); } #define curpcb (__curpcb()) #else /* defined(__GNUCLIKE_ASM) && defined(__GNUCLIKE___TYPEOF) */ #error "this file needs to be ported to your compiler" #endif /* __GNUCLIKE_ASM etc. */ #endif /* _KERNEL */ #endif /* !_MACHINE_PCPU_H_ */ Index: head/sys/i386/include/pmc_mdep.h =================================================================== --- head/sys/i386/include/pmc_mdep.h (revision 326259) +++ head/sys/i386/include/pmc_mdep.h (revision 326260) @@ -1,177 +1,179 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2003-2005,2008 Joseph Koshy * Copyright (c) 2007 The FreeBSD Foundation * All rights reserved. * * Portions of this software were developed by A. Joseph Koshy under * sponsorship from the FreeBSD Foundation and Google, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_PMC_MDEP_H #define _MACHINE_PMC_MDEP_H 1 #ifdef _KERNEL struct pmc_mdep; #endif /* * On the i386 platform we support the following PMCs. * * TSC The timestamp counter * K7 AMD Athlon XP/MP and other 32 bit processors. * K8 AMD Athlon64 and Opteron PMCs in 32 bit mode. * PIV Intel P4/HTT and P4/EMT64 * PPRO Intel Pentium Pro, Pentium-II, Pentium-III, Celeron and * Pentium-M processors * PENTIUM Intel Pentium MMX. * IAP Intel Core/Core2/Atom programmable PMCs. * IAF Intel fixed-function PMCs. * UCP Intel Uncore programmable PMCs. * UCF Intel Uncore fixed-function PMCs. */ #include /* K7 and K8 */ #include #include #include #include #include #include /* * Intel processors implementing V2 and later of the Intel performance * measurement architecture have PMCs of the following classes: TSC, * IAF, IAP, UCF and UCP. */ #define PMC_MDEP_CLASS_INDEX_TSC 1 #define PMC_MDEP_CLASS_INDEX_K7 2 #define PMC_MDEP_CLASS_INDEX_K8 2 #define PMC_MDEP_CLASS_INDEX_P4 2 #define PMC_MDEP_CLASS_INDEX_P5 2 #define PMC_MDEP_CLASS_INDEX_P6 2 #define PMC_MDEP_CLASS_INDEX_IAP 2 #define PMC_MDEP_CLASS_INDEX_IAF 3 #define PMC_MDEP_CLASS_INDEX_UCP 4 #define PMC_MDEP_CLASS_INDEX_UCF 5 /* * Architecture specific extensions to structures. */ union pmc_md_op_pmcallocate { struct pmc_md_amd_op_pmcallocate pm_amd; struct pmc_md_iaf_op_pmcallocate pm_iaf; struct pmc_md_iap_op_pmcallocate pm_iap; struct pmc_md_ucf_op_pmcallocate pm_ucf; struct pmc_md_ucp_op_pmcallocate pm_ucp; struct pmc_md_p4_op_pmcallocate pm_p4; struct pmc_md_pentium_op_pmcallocate pm_pentium; struct pmc_md_ppro_op_pmcallocate pm_ppro; uint64_t __pad[4]; }; /* Logging */ #define PMCLOG_READADDR PMCLOG_READ32 #define PMCLOG_EMITADDR PMCLOG_EMIT32 #ifdef _KERNEL /* MD extension for 'struct pmc' */ union pmc_md_pmc { struct pmc_md_amd_pmc pm_amd; struct pmc_md_iaf_pmc pm_iaf; struct pmc_md_iap_pmc pm_iap; struct pmc_md_ucf_pmc pm_ucf; struct pmc_md_ucp_pmc pm_ucp; struct pmc_md_p4_pmc pm_p4; struct pmc_md_pentium_pmc pm_pentium; struct pmc_md_ppro_pmc pm_ppro; }; struct pmc; struct pmc_mdep; #define PMC_TRAPFRAME_TO_PC(TF) ((TF)->tf_eip) #define PMC_TRAPFRAME_TO_FP(TF) ((TF)->tf_ebp) /* * The layout of the stack frame on entry into the NMI handler depends on * whether a privilege level change (and consequent stack switch) was * required for entry. * * When processing an interrupt when in user mode, the processor switches * stacks, and saves the user mode stack pointer on the kernel stack. The * user mode stack pointer is then available to the interrupt handler * at frame->tf_esp. * * When processing an interrupt while in kernel mode, the processor * continues to use the existing (kernel) stack. Therefore we determine * the stack pointer for the interrupted kernel procedure by adding an * offset to the current frame pointer. */ #define PMC_TRAPFRAME_TO_USER_SP(TF) ((TF)->tf_esp) #define PMC_TRAPFRAME_TO_KERNEL_SP(TF) ((uintptr_t) &((TF)->tf_esp)) #define PMC_IN_KERNEL_STACK(S,START,END) \ ((S) >= (START) && (S) < (END)) #define PMC_IN_KERNEL(va) INKERNEL(va) #define PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS) #define PMC_IN_TRAP_HANDLER(PC) \ ((PC) >= (uintptr_t) start_exceptions && \ (PC) < (uintptr_t) end_exceptions) #define PMC_AT_FUNCTION_PROLOGUE_PUSH_BP(I) \ (((I) & 0x00ffffff) == 0xe58955) /* pushl %ebp; movl %esp,%ebp */ #define PMC_AT_FUNCTION_PROLOGUE_MOV_SP_BP(I) \ (((I) & 0x0000ffff) == 0xe589) /* movl %esp,%ebp */ #define PMC_AT_FUNCTION_EPILOGUE_RET(I) \ (((I) & 0xFF) == 0xC3) /* ret */ /* Build a fake kernel trapframe from current instruction pointer. */ #define PMC_FAKE_TRAPFRAME(TF) \ do { \ (TF)->tf_cs = 0; (TF)->tf_eflags = 0; \ __asm __volatile("movl %%ebp,%0" : "=r" ((TF)->tf_ebp)); \ __asm __volatile("movl %%esp,%0" : "=r" ((TF)->tf_esp)); \ __asm __volatile("call 1f \n\t1: pop %0" : "=r"((TF)->tf_eip)); \ } while (0) /* * Prototypes */ void start_exceptions(void), end_exceptions(void); struct pmc_mdep *pmc_amd_initialize(void); void pmc_amd_finalize(struct pmc_mdep *_md); struct pmc_mdep *pmc_intel_initialize(void); void pmc_intel_finalize(struct pmc_mdep *_md); #endif /* _KERNEL */ #endif /* _MACHINE_PMC_MDEP_H */ Index: head/sys/i386/include/ppireg.h =================================================================== --- head/sys/i386/include/ppireg.h (revision 326259) +++ head/sys/i386/include/ppireg.h (revision 326260) @@ -1,49 +1,51 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (C) 2005 TAKAHASHI Yoshihiro. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_PPIREG_H_ #define _MACHINE_PPIREG_H_ #ifdef _KERNEL #define IO_PPI 0x61 /* Programmable Peripheral Interface */ /* * PPI speaker control values */ #define PIT_ENABLETMR2 0x01 /* Enable timer/counter 2 */ #define PIT_SPKRDATA 0x02 /* Direct to speaker */ #define PIT_SPKR (PIT_ENABLETMR2 | PIT_SPKRDATA) #define ppi_spkr_on() outb(IO_PPI, inb(IO_PPI) | PIT_SPKR) #define ppi_spkr_off() outb(IO_PPI, inb(IO_PPI) & ~PIT_SPKR) #endif /* _KERNEL */ #endif /* _MACHINE_PPIREG_H_ */ Index: head/sys/i386/include/runq.h =================================================================== --- head/sys/i386/include/runq.h (revision 326259) +++ head/sys/i386/include/runq.h (revision 326260) @@ -1,46 +1,48 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 Jake Burkholder * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_RUNQ_H_ #define _MACHINE_RUNQ_H_ #define RQB_LEN (2) /* Number of priority status words. */ #define RQB_L2BPW (5) /* Log2(sizeof(rqb_word_t) * NBBY)). */ #define RQB_BPW (1<> RQB_L2BPW) #define RQB_FFS(word) (ffs(word) - 1) /* * Type of run queue status word. */ typedef u_int32_t rqb_word_t; #endif Index: head/sys/i386/include/sf_buf.h =================================================================== --- head/sys/i386/include/sf_buf.h (revision 326259) +++ head/sys/i386/include/sf_buf.h (revision 326260) @@ -1,36 +1,38 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2014 Gleb Smirnoff * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_SF_BUF_H_ #define _MACHINE_SF_BUF_H_ void sf_buf_map(struct sf_buf *, int); int sf_buf_unmap(struct sf_buf *); boolean_t sf_buf_invalidate_cache(vm_page_t); #endif /* !_MACHINE_SF_BUF_H_ */ Index: head/sys/i386/include/sigframe.h =================================================================== --- head/sys/i386/include/sigframe.h (revision 326259) +++ head/sys/i386/include/sigframe.h (revision 326260) @@ -1,94 +1,96 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1999 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_SIGFRAME_H_ #define _MACHINE_SIGFRAME_H_ /* * Signal frames, arguments passed to application signal handlers. */ #ifdef _KERNEL #ifdef COMPAT_43 struct osigframe { /* * The first four members may be used by applications. */ register_t sf_signum; /* * Either 'int' for old-style FreeBSD handler or 'siginfo_t *' * pointing to sf_siginfo for SA_SIGINFO handlers. */ register_t sf_arg2; /* Points to sf_siginfo.si_sc. */ register_t sf_scp; register_t sf_addr; /* * The following arguments are not constrained by the * function call protocol. * Applications are not supposed to access these members, * except using the pointers we provide in the first three * arguments. */ union { __osiginfohandler_t *sf_action; __sighandler_t *sf_handler; } sf_ahu; /* In the SA_SIGINFO case, sf_arg2 points here. */ osiginfo_t sf_siginfo; }; #endif #ifdef COMPAT_FREEBSD4 /* FreeBSD 4.x */ struct sigframe4 { register_t sf_signum; register_t sf_siginfo; /* code or pointer to sf_si */ register_t sf_ucontext; /* points to sf_uc */ register_t sf_addr; /* undocumented 4th arg */ union { __siginfohandler_t *sf_action; __sighandler_t *sf_handler; } sf_ahu; struct ucontext4 sf_uc; /* = *sf_ucontext */ siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case) */ }; #endif #endif #include #endif /* !_MACHINE_SIGFRAME_H_ */ Index: head/sys/i386/include/smapi.h =================================================================== --- head/sys/i386/include/smapi.h (revision 326259) +++ head/sys/i386/include/smapi.h (revision 326260) @@ -1,91 +1,93 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2003 Matthew N. Dodd * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_SMAPI_H_ #define _MACHINE_SMAPI_H_ #ifndef _KERNEL #include #endif #include struct smapi_bios_header { u_int8_t signature[4]; /* '$SMB' */ u_int8_t version_major; u_int8_t version_minor; u_int8_t length; u_int8_t checksum; u_int16_t information; #define SMAPI_REAL_VM86 0x0001 #define SMAPI_PROT_16BIT 0x0002 #define SMAPI_PROT_32BIT 0x0004 u_int16_t reserved1; u_int16_t real16_offset; u_int16_t real16_segment; u_int16_t reserved2; u_int16_t prot16_offset; u_int32_t prot16_segment; u_int32_t prot32_offset; u_int32_t prot32_segment; } __packed; struct smapi_bios_parameter { union { struct { u_int8_t func; u_int8_t sub_func; } in; struct { u_int8_t rc; u_int8_t sub_rc; } out; } type; u_int16_t param1; u_int16_t param2; u_int16_t param3; u_int32_t param4; u_int32_t param5; } __packed; #define cmd_func type.in.func #define cmd_sub_func type.in.sub_func #define rsp_rc type.out.rc #define rsp_sub_rc type.out.sub_rc #define SMAPIOGHEADER _IOR('$', 0, struct smapi_bios_header) #define SMAPIOCGFUNCTION _IOWR('$', 1, struct smapi_bios_parameter) #endif /* _MACHINE_SMAPI_H_ */ Index: head/sys/i386/include/timerreg.h =================================================================== --- head/sys/i386/include/timerreg.h (revision 326259) +++ head/sys/i386/include/timerreg.h (revision 326260) @@ -1,54 +1,56 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (C) 2005 TAKAHASHI Yoshihiro. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ /* * The outputs of the three timers are connected as follows: * * timer 0 -> irq 0 * timer 1 -> dma chan 0 (for dram refresh) * timer 2 -> speaker (via keyboard controller) * * Timer 0 is used to call hardclock. * Timer 2 is used to generate console beeps. */ #ifndef _MACHINE_TIMERREG_H_ #define _MACHINE_TIMERREG_H_ #ifdef _KERNEL #include #define IO_TIMER1 0x40 /* 8253 Timer #1 */ #define TIMER_CNTR0 (IO_TIMER1 + TIMER_REG_CNTR0) #define TIMER_CNTR1 (IO_TIMER1 + TIMER_REG_CNTR1) #define TIMER_CNTR2 (IO_TIMER1 + TIMER_REG_CNTR2) #define TIMER_MODE (IO_TIMER1 + TIMER_REG_MODE) #endif /* _KERNEL */ #endif /* _MACHINE_TIMERREG_H_ */ Index: head/sys/i386/include/ucontext.h =================================================================== --- head/sys/i386/include/ucontext.h (revision 326259) +++ head/sys/i386/include/ucontext.h (revision 326260) @@ -1,63 +1,65 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1999 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_UCONTEXT_H_ #define _MACHINE_UCONTEXT_H_ #if defined(_KERNEL) && defined(COMPAT_FREEBSD4) struct mcontext4 { __register_t mc_onstack; /* XXX - sigcontext compat. */ __register_t mc_gs; /* machine state (struct trapframe) */ __register_t mc_fs; __register_t mc_es; __register_t mc_ds; __register_t mc_edi; __register_t mc_esi; __register_t mc_ebp; __register_t mc_isp; __register_t mc_ebx; __register_t mc_edx; __register_t mc_ecx; __register_t mc_eax; __register_t mc_trapno; __register_t mc_err; __register_t mc_eip; __register_t mc_cs; __register_t mc_eflags; __register_t mc_esp; /* machine state */ __register_t mc_ss; __register_t mc_fpregs[28]; /* env87 + fpacc87 + u_long */ __register_t __spare__[17]; }; #endif #include #endif /* !_MACHINE_UCONTEXT_H_ */ Index: head/sys/i386/include/vm.h =================================================================== --- head/sys/i386/include/vm.h (revision 326259) +++ head/sys/i386/include/vm.h (revision 326260) @@ -1,45 +1,47 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2009 Hudson River Trading LLC * Written by: John H. Baldwin * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_VM_H_ #define _MACHINE_VM_H_ #include /* Memory attributes. */ #define VM_MEMATTR_UNCACHEABLE ((vm_memattr_t)PAT_UNCACHEABLE) #define VM_MEMATTR_WRITE_COMBINING ((vm_memattr_t)PAT_WRITE_COMBINING) #define VM_MEMATTR_WRITE_THROUGH ((vm_memattr_t)PAT_WRITE_THROUGH) #define VM_MEMATTR_WRITE_PROTECTED ((vm_memattr_t)PAT_WRITE_PROTECTED) #define VM_MEMATTR_WRITE_BACK ((vm_memattr_t)PAT_WRITE_BACK) #define VM_MEMATTR_WEAK_UNCACHEABLE ((vm_memattr_t)PAT_UNCACHED) #define VM_MEMATTR_DEFAULT VM_MEMATTR_WRITE_BACK #endif /* !_MACHINE_VM_H_ */ Index: head/sys/i386/include/vm86.h =================================================================== --- head/sys/i386/include/vm86.h (revision 326259) +++ head/sys/i386/include/vm86.h (revision 326260) @@ -1,165 +1,167 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1997 Jonathan Lemon * All rights reserved. * * Derived from register.h, which is * Copyright (c) 1996 Michael Smith. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_VM86_H_ #define _MACHINE_VM86_H_ 1 /* standard register representation */ typedef union { u_int r_ex; struct { u_short r_x; u_int :16; } r_w; struct { u_char r_l; u_char r_h; u_int :16; } r_b; } reg86_t; /* layout must match definition of struct trapframe_vm86 in */ struct vm86frame { int kernel_fs; int kernel_es; int kernel_ds; reg86_t edi; reg86_t esi; reg86_t ebp; reg86_t isp; reg86_t ebx; reg86_t edx; reg86_t ecx; reg86_t eax; int vmf_trapno; int vmf_err; reg86_t eip; reg86_t cs; reg86_t eflags; reg86_t esp; reg86_t ss; reg86_t es; reg86_t ds; reg86_t fs; reg86_t gs; #define vmf_ah eax.r_b.r_h #define vmf_al eax.r_b.r_l #define vmf_ax eax.r_w.r_x #define vmf_eax eax.r_ex #define vmf_bh ebx.r_b.r_h #define vmf_bl ebx.r_b.r_l #define vmf_bx ebx.r_w.r_x #define vmf_ebx ebx.r_ex #define vmf_ch ecx.r_b.r_h #define vmf_cl ecx.r_b.r_l #define vmf_cx ecx.r_w.r_x #define vmf_ecx ecx.r_ex #define vmf_dh edx.r_b.r_h #define vmf_dl edx.r_b.r_l #define vmf_dx edx.r_w.r_x #define vmf_edx edx.r_ex #define vmf_si esi.r_w.r_x #define vmf_di edi.r_w.r_x #define vmf_cs cs.r_w.r_x #define vmf_ds ds.r_w.r_x #define vmf_es es.r_w.r_x #define vmf_ss ss.r_w.r_x #define vmf_bp ebp.r_w.r_x #define vmf_sp esp.r_w.r_x #define vmf_ip eip.r_w.r_x #define vmf_flags eflags.r_w.r_x #define vmf_eflags eflags.r_ex }; #define VM86_PMAPSIZE 24 #define VMAP_MALLOC 1 /* page was malloced by us */ struct vm86context { int npages; struct vm86pmap { int flags; int pte_num; vm_offset_t kva; u_int old_pte; } pmap[VM86_PMAPSIZE]; }; #define VM_USERCHANGE (PSL_USERCHANGE) #define VME_USERCHANGE (VM_USERCHANGE | PSL_VIP | PSL_VIF) struct vm86_kernel { caddr_t vm86_intmap; /* interrupt map */ u_int vm86_eflags; /* emulated flags */ int vm86_has_vme; /* VME support */ int vm86_inited; /* we were initialized */ int vm86_debug; caddr_t vm86_sproc; /* address of sproc */ }; #define VM86_INIT 1 #define VM86_SET_VME 2 #define VM86_GET_VME 3 #define VM86_INTCALL 4 struct vm86_init_args { int debug; /* debug flag */ int cpu_type; /* cpu type to emulate */ u_char int_map[32]; /* interrupt map */ }; struct vm86_vme_args { int state; /* status */ }; struct vm86_intcall_args { int intnum; struct vm86frame vmf; }; #ifdef _KERNEL extern int vm86paddr; struct thread; extern int vm86_emulate(struct vm86frame *); extern int vm86_sysarch(struct thread *, char *); extern void vm86_trap(struct vm86frame *); extern int vm86_intcall(int, struct vm86frame *); extern int vm86_datacall(int, struct vm86frame *, struct vm86context *); extern void vm86_initialize(void); extern vm_offset_t vm86_getpage(struct vm86context *, int); extern vm_offset_t vm86_addpage(struct vm86context *, int, vm_offset_t); extern int vm86_getptr(struct vm86context *, vm_offset_t, u_short *, u_short *); extern vm_offset_t vm86_getaddr(struct vm86context *, u_short, u_short); #endif /* _KERNEL */ #endif /* _MACHINE_VM86_H_ */ Index: head/sys/i386/isa/ccbque.h =================================================================== --- head/sys/i386/isa/ccbque.h (revision 326259) +++ head/sys/i386/isa/ccbque.h (revision 326260) @@ -1,122 +1,124 @@ /* $NetBSD$ */ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * [NetBSD for NEC PC98 series] * Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ /* * Common command control queue funcs. * Written by N. Honda. */ #ifndef _CCBQUE_H_ #define _CCBQUE_H_ #define CCB_MWANTED 0x01 /* (I) structure and prototype */ #define GENERIC_CCB_ASSERT(DEV, CCBTYPE) \ TAILQ_HEAD(CCBTYPE##tab, CCBTYPE); \ struct CCBTYPE##que { \ struct CCBTYPE##tab CCBTYPE##tab; \ int count; \ int maxccb; \ u_int flags; \ }; \ \ void DEV##_init_ccbque(int); \ struct CCBTYPE *DEV##_get_ccb(void); \ void DEV##_free_ccb(struct CCBTYPE *); /* (II) static allocated memory */ #define GENERIC_CCB_STATIC_ALLOC(DEV, CCBTYPE) \ static struct CCBTYPE##que CCBTYPE##que; /* (III) functions */ #define GENERIC_CCB(DEV, CCBTYPE, CHAIN) \ \ void \ DEV##_init_ccbque(count) \ int count; \ { \ if (CCBTYPE##que.maxccb == 0) \ TAILQ_INIT(&CCBTYPE##que.CCBTYPE##tab); \ CCBTYPE##que.maxccb += count; \ } \ \ struct CCBTYPE * \ DEV##_get_ccb() \ { \ struct CCBTYPE *cb; \ int s = splcam(); \ \ if (CCBTYPE##que.count < CCBTYPE##que.maxccb) \ { \ CCBTYPE##que.count ++; \ cb = TAILQ_FIRST(&(CCBTYPE##que.CCBTYPE##tab)); \ if (cb != NULL) \ { \ TAILQ_REMOVE(&CCBTYPE##que.CCBTYPE##tab, cb, CHAIN);\ goto out; \ } \ else \ { \ cb = malloc(sizeof(*cb), M_DEVBUF, M_NOWAIT); \ if (cb != NULL) \ { \ bzero(cb, sizeof(*cb)); \ goto out; \ } \ } \ CCBTYPE##que.count --; \ } \ \ cb = NULL; \ \ out: \ splx(s); \ return cb; \ } \ \ void \ DEV##_free_ccb(cb) \ struct CCBTYPE *cb; \ { \ int s = splcam(); \ \ TAILQ_INSERT_TAIL(&CCBTYPE##que.CCBTYPE##tab, cb, CHAIN); \ CCBTYPE##que.count --; \ \ if (CCBTYPE##que.flags & CCB_MWANTED) \ { \ CCBTYPE##que.flags &= ~CCB_MWANTED; \ wakeup ((caddr_t) &CCBTYPE##que.count); \ } \ splx(s); \ } #endif /* !_CCBQUE_H_ */ Index: head/sys/i386/isa/elink.c =================================================================== --- head/sys/i386/isa/elink.c (revision 326259) +++ head/sys/i386/isa/elink.c (revision 326260) @@ -1,94 +1,96 @@ /*- + * SPDX-License-Identifier: BSD-4-Clause + * * Copyright (c) 1994 Charles Hannum. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Charles Hannum. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Common code for dealing with 3COM ethernet cards. */ #include #include #include #include #include #include /* * Issue a `global reset' to all cards. We have to be careful to do this only * once during autoconfig, to prevent resetting boards that have already been * configured. */ void elink_reset() { static int x = 0; if (x == 0) { x = 1; outb(ELINK_ID_PORT, ELINK_RESET); } outb(ELINK_ID_PORT, 0); outb(ELINK_ID_PORT, 0); return; } /* * The `ID sequence' is really just snapshots of an 8-bit CRC register as 0 * bits are shifted in. Different board types use different polynomials. */ void elink_idseq(u_char p) { int i; u_char c; c = 0xff; for (i = 255; i; i--) { outb(ELINK_ID_PORT, c); if (c & 0x80) { c <<= 1; c ^= p; } else c <<= 1; } } static moduledata_t elink_mod = { "elink",/* module name */ NULL, /* event handler */ 0 /* extra data */ }; DECLARE_MODULE(elink, elink_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); MODULE_VERSION(elink, 1); Index: head/sys/i386/isa/elink.h =================================================================== --- head/sys/i386/isa/elink.h (revision 326259) +++ head/sys/i386/isa/elink.h (revision 326260) @@ -1,40 +1,42 @@ /*- + * SPDX-License-Identifier: BSD-4-Clause + * * Copyright (c) 1994 Charles Hannum. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Charles Hannum. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #define ELINK_ID_PORT 0x100 #define ELINK_RESET 0xc0 #define ELINK_507_POLY 0xe7 #define ELINK_509_POLY 0xcf #define TLINK_619_POLY 0x63 void elink_reset(void); void elink_idseq(u_char p); Index: head/sys/i386/isa/pmtimer.c =================================================================== --- head/sys/i386/isa/pmtimer.c (revision 326259) +++ head/sys/i386/isa/pmtimer.c (revision 326260) @@ -1,156 +1,158 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2000 Mitsuru IWASAKI * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Timer device driver for power management events. * The code for suspend/resume is derived from APM device driver. */ #include #include #include #include #include #include #include #include #include static devclass_t pmtimer_devclass; /* reject any PnP devices for now */ static struct isa_pnp_id pmtimer_ids[] = { {0} }; static void pmtimer_identify(driver_t *driver, device_t parent) { device_t child; /* * Only add a child if one doesn't exist already. */ child = devclass_get_device(pmtimer_devclass, 0); if (child == NULL) { child = BUS_ADD_CHILD(parent, 0, "pmtimer", 0); if (child == NULL) panic("pmtimer_identify"); } } static int pmtimer_probe(device_t dev) { if (ISA_PNP_PROBE(device_get_parent(dev), dev, pmtimer_ids) == ENXIO) return (ENXIO); /* only one instance always */ return (device_get_unit(dev)); } static struct timeval suspend_time; static struct timeval diff_time; static int pmtimer_suspend(device_t dev) { if (power_pm_get_type() == POWER_PM_TYPE_ACPI) return (0); microtime(&diff_time); inittodr(0); microtime(&suspend_time); timevalsub(&diff_time, &suspend_time); return (0); } static int pmtimer_resume(device_t dev) { u_int second, minute, hour; struct timeval resume_time, tmp_time; if (power_pm_get_type() == POWER_PM_TYPE_ACPI) return (0); /* modified for adjkerntz */ timer_restore(); /* restore the all timers */ inittodr(0); /* adjust time to RTC */ microtime(&resume_time); getmicrotime(&tmp_time); timevaladd(&tmp_time, &diff_time); #ifdef FIXME /* XXX THIS DOESN'T WORK!!! */ time = tmp_time; #endif #ifdef PMTIMER_FIXUP_CALLTODO /* Calculate the delta time suspended */ timevalsub(&resume_time, &suspend_time); /* Fixup the calltodo list with the delta time. */ adjust_timeout_calltodo(&resume_time); /* * We've already calculated resume_time to be the delta between * the suspend and the resume. */ second = resume_time.tv_sec; #else /* !PMTIMER_FIXUP_CALLTODO */ second = resume_time.tv_sec - suspend_time.tv_sec; #endif /* PMTIMER_FIXUP_CALLTODO */ hour = second / 3600; second %= 3600; minute = second / 60; second %= 60; log(LOG_NOTICE, "wakeup from sleeping state (slept %02d:%02d:%02d)\n", hour, minute, second); return (0); } static device_method_t pmtimer_methods[] = { /* Device interface */ DEVMETHOD(device_identify, pmtimer_identify), DEVMETHOD(device_probe, pmtimer_probe), DEVMETHOD(device_attach, bus_generic_attach), DEVMETHOD(device_suspend, pmtimer_suspend), DEVMETHOD(device_resume, pmtimer_resume), { 0, 0 } }; static driver_t pmtimer_driver = { "pmtimer", pmtimer_methods, 1, /* no softc */ }; DRIVER_MODULE(pmtimer, isa, pmtimer_driver, pmtimer_devclass, 0, 0); Index: head/sys/i386/isa/prof_machdep.c =================================================================== --- head/sys/i386/isa/prof_machdep.c (revision 326259) +++ head/sys/i386/isa/prof_machdep.c (revision 326260) @@ -1,376 +1,378 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1996 Bruce D. Evans. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #ifdef GUPROF #include "opt_i586_guprof.h" #include "opt_perfmon.h" #include #include #include #include #include #include #include #include #include #include #include #include #define CPUTIME_CLOCK_UNINITIALIZED 0 #define CPUTIME_CLOCK_I8254 1 #define CPUTIME_CLOCK_TSC 2 #define CPUTIME_CLOCK_I586_PMC 3 #define CPUTIME_CLOCK_I8254_SHIFT 7 int cputime_bias = 1; /* initialize for locality of reference */ static int cputime_clock = CPUTIME_CLOCK_UNINITIALIZED; #if defined(PERFMON) && defined(I586_PMC_GUPROF) static u_int cputime_clock_pmc_conf = I586_PMC_GUPROF; static int cputime_clock_pmc_init; static struct gmonparam saved_gmp; #endif #if defined(I586_CPU) || defined(I686_CPU) static int cputime_prof_active; #endif #endif /* GUPROF */ #ifdef __GNUCLIKE_ASM __asm(" \n\ GM_STATE = 0 \n\ GMON_PROF_OFF = 3 \n\ \n\ .text \n\ .p2align 4,0x90 \n\ .globl __mcount \n\ .type __mcount,@function \n\ __mcount: \n\ # \n\ # Check that we are profiling. Do it early for speed. \n\ # \n\ cmpl $GMON_PROF_OFF,_gmonparam+GM_STATE \n\ je .mcount_exit \n\ # \n\ # __mcount is the same as [.]mcount except the caller \n\ # hasn't changed the stack except to call here, so the \n\ # caller's raddr is above our raddr. \n\ # \n\ movl 4(%esp),%edx \n\ jmp .got_frompc \n\ \n\ .p2align 4,0x90 \n\ .globl .mcount \n\ .mcount: \n\ cmpl $GMON_PROF_OFF,_gmonparam+GM_STATE \n\ je .mcount_exit \n\ # \n\ # The caller's stack frame has already been built, so \n\ # %ebp is the caller's frame pointer. The caller's \n\ # raddr is in the caller's frame following the caller's \n\ # caller's frame pointer. \n\ # \n\ movl 4(%ebp),%edx \n\ .got_frompc: \n\ # \n\ # Our raddr is the caller's pc. \n\ # \n\ movl (%esp),%eax \n\ \n\ pushfl \n\ pushl %eax \n\ pushl %edx \n\ cli \n\ call mcount \n\ addl $8,%esp \n\ popfl \n\ .mcount_exit: \n\ ret $0 \n\ "); #else /* !__GNUCLIKE_ASM */ #error "this file needs to be ported to your compiler" #endif /* __GNUCLIKE_ASM */ #ifdef GUPROF /* * [.]mexitcount saves the return register(s), loads selfpc and calls * mexitcount(selfpc) to do the work. Someday it should be in a machine * dependent file together with cputime(), __mcount and [.]mcount. cputime() * can't just be put in machdep.c because it has to be compiled without -pg. */ #ifdef __GNUCLIKE_ASM __asm(" \n\ .text \n\ # \n\ # Dummy label to be seen when gprof -u hides [.]mexitcount. \n\ # \n\ .p2align 4,0x90 \n\ .globl __mexitcount \n\ .type __mexitcount,@function \n\ __mexitcount: \n\ nop \n\ \n\ GMON_PROF_HIRES = 4 \n\ \n\ .p2align 4,0x90 \n\ .globl .mexitcount \n\ .mexitcount: \n\ cmpl $GMON_PROF_HIRES,_gmonparam+GM_STATE \n\ jne .mexitcount_exit \n\ pushl %edx \n\ pushl %eax \n\ movl 8(%esp),%eax \n\ pushfl \n\ pushl %eax \n\ cli \n\ call mexitcount \n\ addl $4,%esp \n\ popfl \n\ popl %eax \n\ popl %edx \n\ .mexitcount_exit: \n\ ret $0 \n\ "); #endif /* __GNUCLIKE_ASM */ /* * Return the time elapsed since the last call. The units are machine- * dependent. */ int cputime() { u_int count; int delta; #if (defined(I586_CPU) || defined(I686_CPU)) && \ defined(PERFMON) && defined(I586_PMC_GUPROF) && !defined(SMP) u_quad_t event_count; #endif u_char high, low; static u_int prev_count; #if defined(I586_CPU) || defined(I686_CPU) if (cputime_clock == CPUTIME_CLOCK_TSC) { /* * Scale the TSC a little to make cputime()'s frequency * fit in an int, assuming that the TSC frequency fits * in a u_int. Use a fixed scale since dynamic scaling * would be slower and we can't really use the low bit * of precision. */ count = (u_int)rdtsc() & ~1u; delta = (int)(count - prev_count) >> 1; prev_count = count; return (delta); } #if defined(PERFMON) && defined(I586_PMC_GUPROF) && !defined(SMP) if (cputime_clock == CPUTIME_CLOCK_I586_PMC) { /* * XXX permon_read() should be inlined so that the * perfmon module doesn't need to be compiled with * profiling disabled and so that it is fast. */ perfmon_read(0, &event_count); count = (u_int)event_count; delta = (int)(count - prev_count); prev_count = count; return (delta); } #endif /* PERFMON && I586_PMC_GUPROF && !SMP */ #endif /* I586_CPU || I686_CPU */ /* * Read the current value of the 8254 timer counter 0. */ outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); low = inb(TIMER_CNTR0); high = inb(TIMER_CNTR0); count = ((high << 8) | low) << CPUTIME_CLOCK_I8254_SHIFT; /* * The timer counts down from TIMER_CNTR0_MAX to 0 and then resets. * While profiling is enabled, this routine is called at least twice * per timer reset (for mcounting and mexitcounting hardclock()), * so at most one reset has occurred since the last call, and one * has occurred iff the current count is larger than the previous * count. This allows counter underflow to be detected faster * than in microtime(). */ delta = prev_count - count; prev_count = count; if ((int) delta <= 0) return (delta + (i8254_max_count << CPUTIME_CLOCK_I8254_SHIFT)); return (delta); } static int sysctl_machdep_cputime_clock(SYSCTL_HANDLER_ARGS) { int clock; int error; #if defined(PERFMON) && defined(I586_PMC_GUPROF) int event; struct pmc pmc; #endif clock = cputime_clock; #if defined(PERFMON) && defined(I586_PMC_GUPROF) if (clock == CPUTIME_CLOCK_I586_PMC) { pmc.pmc_val = cputime_clock_pmc_conf; clock += pmc.pmc_event; } #endif error = sysctl_handle_opaque(oidp, &clock, sizeof clock, req); if (error == 0 && req->newptr != NULL) { #if defined(PERFMON) && defined(I586_PMC_GUPROF) if (clock >= CPUTIME_CLOCK_I586_PMC) { event = clock - CPUTIME_CLOCK_I586_PMC; if (event >= 256) return (EINVAL); pmc.pmc_num = 0; pmc.pmc_event = event; pmc.pmc_unit = 0; pmc.pmc_flags = PMCF_E | PMCF_OS | PMCF_USR; pmc.pmc_mask = 0; cputime_clock_pmc_conf = pmc.pmc_val; cputime_clock = CPUTIME_CLOCK_I586_PMC; } else #endif { if (clock < 0 || clock >= CPUTIME_CLOCK_I586_PMC) return (EINVAL); cputime_clock = clock; } } return (error); } SYSCTL_PROC(_machdep, OID_AUTO, cputime_clock, CTLTYPE_INT | CTLFLAG_RW, 0, sizeof(u_int), sysctl_machdep_cputime_clock, "I", ""); /* * The start and stop routines need not be here since we turn off profiling * before calling them. They are here for convenience. */ void startguprof(gp) struct gmonparam *gp; { #if defined(I586_CPU) || defined(I686_CPU) uint64_t freq; freq = atomic_load_acq_64(&tsc_freq); if (cputime_clock == CPUTIME_CLOCK_UNINITIALIZED) { if (freq != 0 && mp_ncpus == 1) cputime_clock = CPUTIME_CLOCK_TSC; else cputime_clock = CPUTIME_CLOCK_I8254; } if (cputime_clock == CPUTIME_CLOCK_TSC) { gp->profrate = freq >> 1; cputime_prof_active = 1; } else gp->profrate = i8254_freq << CPUTIME_CLOCK_I8254_SHIFT; #if defined(PERFMON) && defined(I586_PMC_GUPROF) if (cputime_clock == CPUTIME_CLOCK_I586_PMC) { if (perfmon_avail() && perfmon_setup(0, cputime_clock_pmc_conf) == 0) { if (perfmon_start(0) != 0) perfmon_fini(0); else { /* XXX 1 event == 1 us. */ gp->profrate = 1000000; saved_gmp = *gp; /* Zap overheads. They are invalid. */ gp->cputime_overhead = 0; gp->mcount_overhead = 0; gp->mcount_post_overhead = 0; gp->mcount_pre_overhead = 0; gp->mexitcount_overhead = 0; gp->mexitcount_post_overhead = 0; gp->mexitcount_pre_overhead = 0; cputime_clock_pmc_init = TRUE; } } } #endif /* PERFMON && I586_PMC_GUPROF */ #else /* !(I586_CPU || I686_CPU) */ if (cputime_clock == CPUTIME_CLOCK_UNINITIALIZED) cputime_clock = CPUTIME_CLOCK_I8254; gp->profrate = i8254_freq << CPUTIME_CLOCK_I8254_SHIFT; #endif /* I586_CPU || I686_CPU */ cputime_bias = 0; cputime(); } void stopguprof(gp) struct gmonparam *gp; { #if defined(PERFMON) && defined(I586_PMC_GUPROF) if (cputime_clock_pmc_init) { *gp = saved_gmp; perfmon_fini(0); cputime_clock_pmc_init = FALSE; } #endif #if defined(I586_CPU) || defined(I686_CPU) if (cputime_clock == CPUTIME_CLOCK_TSC) cputime_prof_active = 0; #endif } #if defined(I586_CPU) || defined(I686_CPU) /* If the cpu frequency changed while profiling, report a warning. */ static void tsc_freq_changed(void *arg, const struct cf_level *level, int status) { /* * If there was an error during the transition or * TSC is P-state invariant, don't do anything. */ if (status != 0 || tsc_is_invariant) return; if (cputime_prof_active && cputime_clock == CPUTIME_CLOCK_TSC) printf("warning: cpu freq changed while profiling active\n"); } EVENTHANDLER_DEFINE(cpufreq_post_change, tsc_freq_changed, NULL, EVENTHANDLER_PRI_ANY); #endif /* I586_CPU || I686_CPU */ #endif /* GUPROF */ Index: head/sys/i386/linux/imgact_linux.c =================================================================== --- head/sys/i386/linux/imgact_linux.c (revision 326259) +++ head/sys/i386/linux/imgact_linux.c (revision 326260) @@ -1,239 +1,241 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1994-1996 Søren Schmidt * All rights reserved. * * Based heavily on /sys/kern/imgact_aout.c which is: * Copyright (c) 1993, David Greenman * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int exec_linux_imgact(struct image_params *iparams); static int exec_linux_imgact(struct image_params *imgp) { const struct exec *a_out = (const struct exec *) imgp->image_header; struct vmspace *vmspace; vm_offset_t vmaddr; unsigned long virtual_offset, file_offset; unsigned long bss_size; ssize_t aresid; int error; if (((a_out->a_magic >> 16) & 0xff) != 0x64) return -1; /* * Set file/virtual offset based on a.out variant. */ switch ((int)(a_out->a_magic & 0xffff)) { case 0413: virtual_offset = 0; file_offset = 1024; break; case 0314: virtual_offset = 4096; file_offset = 0; break; default: return (-1); } bss_size = round_page(a_out->a_bss); #ifdef DEBUG printf("imgact: text: %08lx, data: %08lx, bss: %08lx\n", (u_long)a_out->a_text, (u_long)a_out->a_data, bss_size); #endif /* * Check various fields in header for validity/bounds. */ if (a_out->a_entry < virtual_offset || a_out->a_entry >= virtual_offset + a_out->a_text || a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) return (-1); /* text + data can't exceed file size */ if (a_out->a_data + a_out->a_text > imgp->attr->va_size) return (EFAULT); /* * text/data/bss must not exceed limits */ PROC_LOCK(imgp->proc); if (a_out->a_text > maxtsiz || a_out->a_data + bss_size > lim_cur_proc(imgp->proc, RLIMIT_DATA) || racct_set(imgp->proc, RACCT_DATA, a_out->a_data + bss_size) != 0) { PROC_UNLOCK(imgp->proc); return (ENOMEM); } PROC_UNLOCK(imgp->proc); VOP_UNLOCK(imgp->vp, 0); /* * Destroy old process VM and create a new one (with a new stack) */ error = exec_new_vmspace(imgp, &linux_sysvec); if (error) goto fail; vmspace = imgp->proc->p_vmspace; /* * Check if file_offset page aligned,. * Currently we cannot handle misaligned file offsets, * and so we read in the entire image (what a waste). */ if (file_offset & PAGE_MASK) { #ifdef DEBUG printf("imgact: Non page aligned binary %lu\n", file_offset); #endif /* * Map text+data+bss read/write/execute */ vmaddr = virtual_offset; error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr, a_out->a_text + a_out->a_data + bss_size, 0, VMFS_NO_SPACE, VM_PROT_ALL, VM_PROT_ALL, 0); if (error) goto fail; error = vn_rdwr(UIO_READ, imgp->vp, (void *)vmaddr, file_offset, a_out->a_text + a_out->a_data, UIO_USERSPACE, 0, curthread->td_ucred, NOCRED, &aresid, curthread); if (error != 0) goto fail; if (aresid != 0) { error = ENOEXEC; goto fail; } /* * remove write enable on the 'text' part */ error = vm_map_protect(&vmspace->vm_map, vmaddr, vmaddr + a_out->a_text, VM_PROT_EXECUTE|VM_PROT_READ, TRUE); if (error) goto fail; } else { #ifdef DEBUG printf("imgact: Page aligned binary %lu\n", file_offset); #endif /* * Map text+data read/execute */ vmaddr = virtual_offset; error = vm_mmap(&vmspace->vm_map, &vmaddr, a_out->a_text + a_out->a_data, VM_PROT_READ | VM_PROT_EXECUTE, VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED, OBJT_VNODE, imgp->vp, file_offset); if (error) goto fail; #ifdef DEBUG printf("imgact: startaddr=%08lx, length=%08lx\n", (u_long)vmaddr, (u_long)a_out->a_text + (u_long)a_out->a_data); #endif /* * allow read/write of data */ error = vm_map_protect(&vmspace->vm_map, vmaddr + a_out->a_text, vmaddr + a_out->a_text + a_out->a_data, VM_PROT_ALL, FALSE); if (error) goto fail; /* * Allocate anon demand-zeroed area for uninitialized data */ if (bss_size != 0) { vmaddr = virtual_offset + a_out->a_text + a_out->a_data; error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr, bss_size, 0, VMFS_NO_SPACE, VM_PROT_ALL, VM_PROT_ALL, 0); if (error) goto fail; #ifdef DEBUG printf("imgact: bssaddr=%08lx, length=%08lx\n", (u_long)vmaddr, bss_size); #endif } } /* Fill in process VM information */ vmspace->vm_tsize = round_page(a_out->a_text) >> PAGE_SHIFT; vmspace->vm_dsize = round_page(a_out->a_data + bss_size) >> PAGE_SHIFT; vmspace->vm_taddr = (caddr_t)(void *)(uintptr_t)virtual_offset; vmspace->vm_daddr = (caddr_t)(void *)(uintptr_t) (virtual_offset + a_out->a_text); /* Fill in image_params */ imgp->interpreted = 0; imgp->entry_addr = a_out->a_entry; imgp->proc->p_sysent = &linux_sysvec; fail: vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY); return (error); } /* * Tell kern_execve.c about it, with a little help from the linker. */ static struct execsw linux_execsw = { exec_linux_imgact, "linux a.out" }; EXEC_SET(linuxaout, linux_execsw); Index: head/sys/i386/linux/linux.h =================================================================== --- head/sys/i386/linux/linux.h (revision 326259) +++ head/sys/i386/linux/linux.h (revision 326260) @@ -1,613 +1,615 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1994-1996 Søren Schmidt * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _I386_LINUX_H_ #define _I386_LINUX_H_ #include /* for sigval union */ #include #include /* * debugging support */ extern u_char linux_debug_map[]; #define ldebug(name) isclr(linux_debug_map, LINUX_SYS_linux_ ## name) #define ARGS(nm, fmt) "linux(%ld/%ld): "#nm"("fmt")\n", \ (long)td->td_proc->p_pid, (long)td->td_tid #define LMSG(fmt) "linux(%ld/%ld): "fmt"\n", \ (long)td->td_proc->p_pid, (long)td->td_tid #define LINUX_DTRACE linuxulator #define LINUX_SHAREDPAGE (VM_MAXUSER_ADDRESS - PAGE_SIZE) #define LINUX_USRSTACK LINUX_SHAREDPAGE #define PTRIN(v) (void *)(v) #define PTROUT(v) (l_uintptr_t)(v) #define CP(src,dst,fld) do { (dst).fld = (src).fld; } while (0) #define CP2(src,dst,sfld,dfld) do { (dst).dfld = (src).sfld; } while (0) #define PTRIN_CP(src,dst,fld) \ do { (dst).fld = PTRIN((src).fld); } while (0) /* * Provide a separate set of types for the Linux types. */ typedef int l_int; typedef int32_t l_long; typedef int64_t l_longlong; typedef short l_short; typedef unsigned int l_uint; typedef uint32_t l_ulong; typedef uint64_t l_ulonglong; typedef unsigned short l_ushort; typedef char *l_caddr_t; typedef l_ulong l_uintptr_t; typedef l_long l_clock_t; typedef l_int l_daddr_t; typedef l_ushort l_dev_t; typedef l_uint l_gid_t; typedef l_ushort l_gid16_t; typedef l_ulong l_ino_t; typedef l_int l_key_t; typedef l_longlong l_loff_t; typedef l_ushort l_mode_t; typedef l_long l_off_t; typedef l_int l_pid_t; typedef l_uint l_size_t; typedef l_long l_suseconds_t; typedef l_long l_time_t; typedef l_uint l_uid_t; typedef l_ushort l_uid16_t; typedef l_int l_timer_t; typedef l_int l_mqd_t; typedef l_ulong l_fd_mask; typedef struct { l_int val[2]; } l_fsid_t; typedef struct { l_time_t tv_sec; l_suseconds_t tv_usec; } l_timeval; #define l_fd_set fd_set /* * Miscellaneous */ #define LINUX_AT_COUNT 20 /* Count of used aux entry types. * Keep this synchronized with * elf_linux_fixup() code. */ struct l___sysctl_args { l_int *name; l_int nlen; void *oldval; l_size_t *oldlenp; void *newval; l_size_t newlen; l_ulong __spare[4]; }; /* Resource limits */ #define LINUX_RLIMIT_CPU 0 #define LINUX_RLIMIT_FSIZE 1 #define LINUX_RLIMIT_DATA 2 #define LINUX_RLIMIT_STACK 3 #define LINUX_RLIMIT_CORE 4 #define LINUX_RLIMIT_RSS 5 #define LINUX_RLIMIT_NPROC 6 #define LINUX_RLIMIT_NOFILE 7 #define LINUX_RLIMIT_MEMLOCK 8 #define LINUX_RLIMIT_AS 9 /* Address space limit */ #define LINUX_RLIM_NLIMITS 10 struct l_rlimit { l_ulong rlim_cur; l_ulong rlim_max; }; struct l_mmap_argv { l_uintptr_t addr; l_size_t len; l_int prot; l_int flags; l_int fd; l_off_t pgoff; } __packed; /* * stat family of syscalls */ struct l_timespec { l_time_t tv_sec; l_long tv_nsec; }; struct l_newstat { l_ushort st_dev; l_ushort __pad1; l_ulong st_ino; l_ushort st_mode; l_ushort st_nlink; l_ushort st_uid; l_ushort st_gid; l_ushort st_rdev; l_ushort __pad2; l_ulong st_size; l_ulong st_blksize; l_ulong st_blocks; struct l_timespec st_atim; struct l_timespec st_mtim; struct l_timespec st_ctim; l_ulong __unused4; l_ulong __unused5; }; struct l_stat { l_ushort st_dev; l_ulong st_ino; l_ushort st_mode; l_ushort st_nlink; l_ushort st_uid; l_ushort st_gid; l_ushort st_rdev; l_long st_size; struct l_timespec st_atim; struct l_timespec st_mtim; struct l_timespec st_ctim; l_long st_blksize; l_long st_blocks; l_ulong st_flags; l_ulong st_gen; }; struct l_stat64 { l_ushort st_dev; u_char __pad0[10]; l_ulong __st_ino; l_uint st_mode; l_uint st_nlink; l_ulong st_uid; l_ulong st_gid; l_ushort st_rdev; u_char __pad3[10]; l_longlong st_size; l_ulong st_blksize; l_ulong st_blocks; l_ulong __pad4; struct l_timespec st_atim; struct l_timespec st_mtim; struct l_timespec st_ctim; l_ulonglong st_ino; }; struct l_statfs64 { l_int f_type; l_int f_bsize; uint64_t f_blocks; uint64_t f_bfree; uint64_t f_bavail; uint64_t f_files; uint64_t f_ffree; l_fsid_t f_fsid; l_int f_namelen; l_int f_frsize; l_int f_flags; l_int f_spare[4]; }; #define LINUX_NSIG_WORDS 2 /* sigaction flags */ #define LINUX_SA_NOCLDSTOP 0x00000001 #define LINUX_SA_NOCLDWAIT 0x00000002 #define LINUX_SA_SIGINFO 0x00000004 #define LINUX_SA_RESTORER 0x04000000 #define LINUX_SA_ONSTACK 0x08000000 #define LINUX_SA_RESTART 0x10000000 #define LINUX_SA_INTERRUPT 0x20000000 #define LINUX_SA_NOMASK 0x40000000 #define LINUX_SA_ONESHOT 0x80000000 /* sigprocmask actions */ #define LINUX_SIG_BLOCK 0 #define LINUX_SIG_UNBLOCK 1 #define LINUX_SIG_SETMASK 2 /* sigaltstack */ #define LINUX_MINSIGSTKSZ 2048 typedef void (*l_handler_t)(l_int); typedef l_ulong l_osigset_t; typedef struct { l_handler_t lsa_handler; l_osigset_t lsa_mask; l_ulong lsa_flags; void (*lsa_restorer)(void); } l_osigaction_t; typedef struct { l_handler_t lsa_handler; l_ulong lsa_flags; void (*lsa_restorer)(void); l_sigset_t lsa_mask; } l_sigaction_t; typedef struct { void *ss_sp; l_int ss_flags; l_size_t ss_size; } l_stack_t; /* The Linux sigcontext, pretty much a standard 386 trapframe. */ struct l_sigcontext { l_int sc_gs; l_int sc_fs; l_int sc_es; l_int sc_ds; l_int sc_edi; l_int sc_esi; l_int sc_ebp; l_int sc_esp; l_int sc_ebx; l_int sc_edx; l_int sc_ecx; l_int sc_eax; l_int sc_trapno; l_int sc_err; l_int sc_eip; l_int sc_cs; l_int sc_eflags; l_int sc_esp_at_signal; l_int sc_ss; l_int sc_387; l_int sc_mask; l_int sc_cr2; }; struct l_ucontext { l_ulong uc_flags; void *uc_link; l_stack_t uc_stack; struct l_sigcontext uc_mcontext; l_sigset_t uc_sigmask; }; #define LINUX_SI_MAX_SIZE 128 #define LINUX_SI_PAD_SIZE ((LINUX_SI_MAX_SIZE/sizeof(l_int)) - 3) typedef union l_sigval { l_int sival_int; l_uintptr_t sival_ptr; } l_sigval_t; typedef struct l_siginfo { l_int lsi_signo; l_int lsi_errno; l_int lsi_code; union { l_int _pad[LINUX_SI_PAD_SIZE]; struct { l_pid_t _pid; l_uid_t _uid; } _kill; struct { l_timer_t _tid; l_int _overrun; char _pad[sizeof(l_uid_t) - sizeof(l_int)]; l_sigval_t _sigval; l_int _sys_private; } _timer; struct { l_pid_t _pid; /* sender's pid */ l_uid_t _uid; /* sender's uid */ l_sigval_t _sigval; } _rt; struct { l_pid_t _pid; /* which child */ l_uid_t _uid; /* sender's uid */ l_int _status; /* exit code */ l_clock_t _utime; l_clock_t _stime; } _sigchld; struct { l_uintptr_t _addr; /* Faulting insn/memory ref. */ } _sigfault; struct { l_long _band; /* POLL_IN,POLL_OUT,POLL_MSG */ l_int _fd; } _sigpoll; } _sifields; } l_siginfo_t; #define lsi_pid _sifields._kill._pid #define lsi_uid _sifields._kill._uid #define lsi_tid _sifields._timer._tid #define lsi_overrun _sifields._timer._overrun #define lsi_sys_private _sifields._timer._sys_private #define lsi_status _sifields._sigchld._status #define lsi_utime _sifields._sigchld._utime #define lsi_stime _sifields._sigchld._stime #define lsi_value _sifields._rt._sigval #define lsi_int _sifields._rt._sigval.sival_int #define lsi_ptr _sifields._rt._sigval.sival_ptr #define lsi_addr _sifields._sigfault._addr #define lsi_band _sifields._sigpoll._band #define lsi_fd _sifields._sigpoll._fd struct l_fpreg { u_int16_t significand[4]; u_int16_t exponent; }; struct l_fpxreg { u_int16_t significand[4]; u_int16_t exponent; u_int16_t padding[3]; }; struct l_xmmreg { u_int32_t element[4]; }; struct l_fpstate { /* Regular FPU environment */ u_int32_t cw; u_int32_t sw; u_int32_t tag; u_int32_t ipoff; u_int32_t cssel; u_int32_t dataoff; u_int32_t datasel; struct l_fpreg _st[8]; u_int16_t status; u_int16_t magic; /* 0xffff = regular FPU data */ /* FXSR FPU environment */ u_int32_t _fxsr_env[6]; /* env is ignored. */ u_int32_t mxcsr; u_int32_t reserved; struct l_fpxreg _fxsr_st[8]; /* reg data is ignored. */ struct l_xmmreg _xmm[8]; u_int32_t padding[56]; }; /* * We make the stack look like Linux expects it when calling a signal * handler, but use the BSD way of calling the handler and sigreturn(). * This means that we need to pass the pointer to the handler too. * It is appended to the frame to not interfere with the rest of it. */ struct l_sigframe { l_int sf_sig; struct l_sigcontext sf_sc; struct l_fpstate sf_fpstate; l_uint sf_extramask[LINUX_NSIG_WORDS-1]; l_handler_t sf_handler; }; struct l_rt_sigframe { l_int sf_sig; l_siginfo_t *sf_siginfo; struct l_ucontext *sf_ucontext; l_siginfo_t sf_si; struct l_ucontext sf_sc; l_handler_t sf_handler; }; extern struct sysentvec linux_sysvec; /* * arch specific open/fcntl flags */ #define LINUX_F_GETLK64 12 #define LINUX_F_SETLK64 13 #define LINUX_F_SETLKW64 14 union l_semun { l_int val; struct l_semid_ds *buf; l_ushort *array; struct l_seminfo *__buf; void *__pad; }; struct l_sockaddr { l_ushort sa_family; char sa_data[14]; }; struct l_ifmap { l_ulong mem_start; l_ulong mem_end; l_ushort base_addr; u_char irq; u_char dma; u_char port; }; #define LINUX_IFHWADDRLEN 6 #define LINUX_IFNAMSIZ 16 struct l_ifreq { union { char ifrn_name[LINUX_IFNAMSIZ]; } ifr_ifrn; union { struct l_sockaddr ifru_addr; struct l_sockaddr ifru_dstaddr; struct l_sockaddr ifru_broadaddr; struct l_sockaddr ifru_netmask; struct l_sockaddr ifru_hwaddr; l_short ifru_flags[1]; l_int ifru_ivalue; l_int ifru_mtu; struct l_ifmap ifru_map; char ifru_slave[LINUX_IFNAMSIZ]; l_caddr_t ifru_data; } ifr_ifru; }; #define ifr_name ifr_ifrn.ifrn_name /* Interface name */ #define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ #define ifr_ifindex ifr_ifru.ifru_ivalue /* Interface index */ /* * poll() */ #define LINUX_POLLIN 0x0001 #define LINUX_POLLPRI 0x0002 #define LINUX_POLLOUT 0x0004 #define LINUX_POLLERR 0x0008 #define LINUX_POLLHUP 0x0010 #define LINUX_POLLNVAL 0x0020 #define LINUX_POLLRDNORM 0x0040 #define LINUX_POLLRDBAND 0x0080 #define LINUX_POLLWRNORM 0x0100 #define LINUX_POLLWRBAND 0x0200 #define LINUX_POLLMSG 0x0400 struct l_pollfd { l_int fd; l_short events; l_short revents; }; struct l_user_desc { l_uint entry_number; l_uint base_addr; l_uint limit; l_uint seg_32bit:1; l_uint contents:2; l_uint read_exec_only:1; l_uint limit_in_pages:1; l_uint seg_not_present:1; l_uint useable:1; }; struct l_desc_struct { unsigned long a, b; }; #define LINUX_LOWERWORD 0x0000ffff /* * Macros which does the same thing as those in Linux include/asm-um/ldt-i386.h. * These convert Linux user space descriptor to machine one. */ #define LINUX_LDT_entry_a(info) \ ((((info)->base_addr & LINUX_LOWERWORD) << 16) | \ ((info)->limit & LINUX_LOWERWORD)) #define LINUX_ENTRY_B_READ_EXEC_ONLY 9 #define LINUX_ENTRY_B_CONTENTS 10 #define LINUX_ENTRY_B_SEG_NOT_PRESENT 15 #define LINUX_ENTRY_B_BASE_ADDR 16 #define LINUX_ENTRY_B_USEABLE 20 #define LINUX_ENTRY_B_SEG32BIT 22 #define LINUX_ENTRY_B_LIMIT 23 #define LINUX_LDT_entry_b(info) \ (((info)->base_addr & 0xff000000) | \ ((info)->limit & 0xf0000) | \ ((info)->contents << LINUX_ENTRY_B_CONTENTS) | \ (((info)->seg_not_present == 0) << LINUX_ENTRY_B_SEG_NOT_PRESENT) | \ (((info)->base_addr & 0x00ff0000) >> LINUX_ENTRY_B_BASE_ADDR) | \ (((info)->read_exec_only == 0) << LINUX_ENTRY_B_READ_EXEC_ONLY) | \ ((info)->seg_32bit << LINUX_ENTRY_B_SEG32BIT) | \ ((info)->useable << LINUX_ENTRY_B_USEABLE) | \ ((info)->limit_in_pages << LINUX_ENTRY_B_LIMIT) | 0x7000) #define LINUX_LDT_empty(info) \ ((info)->base_addr == 0 && \ (info)->limit == 0 && \ (info)->contents == 0 && \ (info)->seg_not_present == 1 && \ (info)->read_exec_only == 1 && \ (info)->seg_32bit == 0 && \ (info)->limit_in_pages == 0 && \ (info)->useable == 0) /* * Macros for converting segments. * They do the same as those in arch/i386/kernel/process.c in Linux. */ #define LINUX_GET_BASE(desc) \ ((((desc)->a >> 16) & LINUX_LOWERWORD) | \ (((desc)->b << 16) & 0x00ff0000) | \ ((desc)->b & 0xff000000)) #define LINUX_GET_LIMIT(desc) \ (((desc)->a & LINUX_LOWERWORD) | \ ((desc)->b & 0xf0000)) #define LINUX_GET_32BIT(desc) \ (((desc)->b >> LINUX_ENTRY_B_SEG32BIT) & 1) #define LINUX_GET_CONTENTS(desc) \ (((desc)->b >> LINUX_ENTRY_B_CONTENTS) & 3) #define LINUX_GET_WRITABLE(desc) \ (((desc)->b >> LINUX_ENTRY_B_READ_EXEC_ONLY) & 1) #define LINUX_GET_LIMIT_PAGES(desc) \ (((desc)->b >> LINUX_ENTRY_B_LIMIT) & 1) #define LINUX_GET_PRESENT(desc) \ (((desc)->b >> LINUX_ENTRY_B_SEG_NOT_PRESENT) & 1) #define LINUX_GET_USEABLE(desc) \ (((desc)->b >> LINUX_ENTRY_B_USEABLE) & 1) #define linux_copyout_rusage(r, u) copyout(r, u, sizeof(*r)) /* robust futexes */ struct linux_robust_list { struct linux_robust_list *next; }; struct linux_robust_list_head { struct linux_robust_list list; l_long futex_offset; struct linux_robust_list *pending_list; }; #endif /* !_I386_LINUX_H_ */ Index: head/sys/i386/linux/linux_dummy.c =================================================================== --- head/sys/i386/linux/linux_dummy.c (revision 326259) +++ head/sys/i386/linux/linux_dummy.c (revision 326260) @@ -1,182 +1,184 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1994-1995 Søren Schmidt * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_compat.h" #include #include #include #include #include #include #include #include #include /* DTrace init */ LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE); UNIMPLEMENTED(afs_syscall); UNIMPLEMENTED(break); UNIMPLEMENTED(create_module); /* added in linux 1.0 removed in 2.6 */ UNIMPLEMENTED(ftime); UNIMPLEMENTED(get_kernel_syms); /* added in linux 1.0 removed in 2.6 */ UNIMPLEMENTED(getpmsg); UNIMPLEMENTED(gtty); UNIMPLEMENTED(stty); UNIMPLEMENTED(lock); UNIMPLEMENTED(mpx); UNIMPLEMENTED(nfsservctl); /* added in linux 2.2 removed in 3.1 */ UNIMPLEMENTED(prof); UNIMPLEMENTED(profil); UNIMPLEMENTED(putpmsg); UNIMPLEMENTED(query_module); /* added in linux 2.2 removed in 2.6 */ UNIMPLEMENTED(ulimit); UNIMPLEMENTED(vserver); DUMMY(stime); DUMMY(fstat); DUMMY(olduname); DUMMY(syslog); DUMMY(uname); DUMMY(vhangup); DUMMY(vm86old); DUMMY(swapoff); DUMMY(adjtimex); DUMMY(init_module); DUMMY(delete_module); DUMMY(quotactl); DUMMY(bdflush); DUMMY(sysfs); DUMMY(vm86); DUMMY(sendfile); /* different semantics */ DUMMY(setfsuid); DUMMY(setfsgid); DUMMY(pivot_root); DUMMY(lookup_dcookie); DUMMY(remap_file_pages); DUMMY(mbind); DUMMY(get_mempolicy); DUMMY(set_mempolicy); DUMMY(kexec_load); /* linux 2.6.11: */ DUMMY(add_key); DUMMY(request_key); DUMMY(keyctl); /* linux 2.6.13: */ DUMMY(ioprio_set); DUMMY(ioprio_get); DUMMY(inotify_init); DUMMY(inotify_add_watch); DUMMY(inotify_rm_watch); /* linux 2.6.16: */ DUMMY(migrate_pages); DUMMY(unshare); /* linux 2.6.17: */ DUMMY(splice); DUMMY(sync_file_range); DUMMY(tee); DUMMY(vmsplice); /* linux 2.6.18: */ DUMMY(move_pages); /* linux 2.6.19: */ DUMMY(getcpu); /* linux 2.6.22: */ DUMMY(signalfd); /* linux 2.6.27: */ DUMMY(signalfd4); DUMMY(inotify_init1); /* linux 2.6.31: */ DUMMY(perf_event_open); /* linux 2.6.33: */ DUMMY(fanotify_init); DUMMY(fanotify_mark); /* linux 2.6.39: */ DUMMY(name_to_handle_at); DUMMY(open_by_handle_at); DUMMY(clock_adjtime); /* linux 3.0: */ DUMMY(setns); /* linux 3.2: */ DUMMY(process_vm_readv); DUMMY(process_vm_writev); /* linux 3.5: */ DUMMY(kcmp); /* linux 3.8: */ DUMMY(finit_module); DUMMY(sched_setattr); DUMMY(sched_getattr); /* linux 3.14: */ DUMMY(renameat2); /* linux 3.15: */ DUMMY(seccomp); DUMMY(memfd_create); /* linux 3.18: */ DUMMY(bpf); /* linux 3.19: */ DUMMY(execveat); /* linux 4.2: */ DUMMY(userfaultfd); /* linux 4.3: */ DUMMY(membarrier); /* linux 4.4: */ DUMMY(mlock2); /* linux 4.5: */ DUMMY(copy_file_range); /* linux 4.6: */ DUMMY(preadv2); DUMMY(pwritev2); /* linux 4.8: */ DUMMY(pkey_mprotect); DUMMY(pkey_alloc); DUMMY(pkey_free); #define DUMMY_XATTR(s) \ int \ linux_ ## s ## xattr( \ struct thread *td, struct linux_ ## s ## xattr_args *arg) \ { \ \ return (ENOATTR); \ } DUMMY_XATTR(set); DUMMY_XATTR(lset); DUMMY_XATTR(fset); DUMMY_XATTR(get); DUMMY_XATTR(lget); DUMMY_XATTR(fget); DUMMY_XATTR(list); DUMMY_XATTR(llist); DUMMY_XATTR(flist); DUMMY_XATTR(remove); DUMMY_XATTR(lremove); DUMMY_XATTR(fremove); Index: head/sys/i386/linux/linux_machdep.c =================================================================== --- head/sys/i386/linux/linux_machdep.c (revision 326259) +++ head/sys/i386/linux/linux_machdep.c (revision 326260) @@ -1,832 +1,834 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2000 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* needed for pcb definition in linux_set_thread_area */ #include "opt_posix.h" extern struct sysentvec elf32_freebsd_sysvec; /* defined in i386/i386/elf_machdep.c */ struct l_descriptor { l_uint entry_number; l_ulong base_addr; l_uint limit; l_uint seg_32bit:1; l_uint contents:2; l_uint read_exec_only:1; l_uint limit_in_pages:1; l_uint seg_not_present:1; l_uint useable:1; }; struct l_old_select_argv { l_int nfds; l_fd_set *readfds; l_fd_set *writefds; l_fd_set *exceptfds; struct l_timeval *timeout; }; int linux_execve(struct thread *td, struct linux_execve_args *args) { struct image_args eargs; char *newpath; int error; LCONVPATHEXIST(td, args->path, &newpath); #ifdef DEBUG if (ldebug(execve)) printf(ARGS(execve, "%s"), newpath); #endif error = exec_copyin_args(&eargs, newpath, UIO_SYSSPACE, args->argp, args->envp); free(newpath, M_TEMP); if (error == 0) error = linux_common_execve(td, &eargs); return (error); } struct l_ipc_kludge { struct l_msgbuf *msgp; l_long msgtyp; }; int linux_ipc(struct thread *td, struct linux_ipc_args *args) { switch (args->what & 0xFFFF) { case LINUX_SEMOP: { struct linux_semop_args a; a.semid = args->arg1; a.tsops = args->ptr; a.nsops = args->arg2; return (linux_semop(td, &a)); } case LINUX_SEMGET: { struct linux_semget_args a; a.key = args->arg1; a.nsems = args->arg2; a.semflg = args->arg3; return (linux_semget(td, &a)); } case LINUX_SEMCTL: { struct linux_semctl_args a; int error; a.semid = args->arg1; a.semnum = args->arg2; a.cmd = args->arg3; error = copyin(args->ptr, &a.arg, sizeof(a.arg)); if (error) return (error); return (linux_semctl(td, &a)); } case LINUX_MSGSND: { struct linux_msgsnd_args a; a.msqid = args->arg1; a.msgp = args->ptr; a.msgsz = args->arg2; a.msgflg = args->arg3; return (linux_msgsnd(td, &a)); } case LINUX_MSGRCV: { struct linux_msgrcv_args a; a.msqid = args->arg1; a.msgsz = args->arg2; a.msgflg = args->arg3; if ((args->what >> 16) == 0) { struct l_ipc_kludge tmp; int error; if (args->ptr == NULL) return (EINVAL); error = copyin(args->ptr, &tmp, sizeof(tmp)); if (error) return (error); a.msgp = tmp.msgp; a.msgtyp = tmp.msgtyp; } else { a.msgp = args->ptr; a.msgtyp = args->arg5; } return (linux_msgrcv(td, &a)); } case LINUX_MSGGET: { struct linux_msgget_args a; a.key = args->arg1; a.msgflg = args->arg2; return (linux_msgget(td, &a)); } case LINUX_MSGCTL: { struct linux_msgctl_args a; a.msqid = args->arg1; a.cmd = args->arg2; a.buf = args->ptr; return (linux_msgctl(td, &a)); } case LINUX_SHMAT: { struct linux_shmat_args a; a.shmid = args->arg1; a.shmaddr = args->ptr; a.shmflg = args->arg2; a.raddr = (l_ulong *)args->arg3; return (linux_shmat(td, &a)); } case LINUX_SHMDT: { struct linux_shmdt_args a; a.shmaddr = args->ptr; return (linux_shmdt(td, &a)); } case LINUX_SHMGET: { struct linux_shmget_args a; a.key = args->arg1; a.size = args->arg2; a.shmflg = args->arg3; return (linux_shmget(td, &a)); } case LINUX_SHMCTL: { struct linux_shmctl_args a; a.shmid = args->arg1; a.cmd = args->arg2; a.buf = args->ptr; return (linux_shmctl(td, &a)); } default: break; } return (EINVAL); } int linux_old_select(struct thread *td, struct linux_old_select_args *args) { struct l_old_select_argv linux_args; struct linux_select_args newsel; int error; #ifdef DEBUG if (ldebug(old_select)) printf(ARGS(old_select, "%p"), args->ptr); #endif error = copyin(args->ptr, &linux_args, sizeof(linux_args)); if (error) return (error); newsel.nfds = linux_args.nfds; newsel.readfds = linux_args.readfds; newsel.writefds = linux_args.writefds; newsel.exceptfds = linux_args.exceptfds; newsel.timeout = linux_args.timeout; return (linux_select(td, &newsel)); } int linux_set_cloned_tls(struct thread *td, void *desc) { struct segment_descriptor sd; struct l_user_desc info; int idx, error; int a[2]; error = copyin(desc, &info, sizeof(struct l_user_desc)); if (error) { printf(LMSG("copyin failed!")); } else { idx = info.entry_number; /* * looks like we're getting the idx we returned * in the set_thread_area() syscall */ if (idx != 6 && idx != 3) { printf(LMSG("resetting idx!")); idx = 3; } /* this doesnt happen in practice */ if (idx == 6) { /* we might copy out the entry_number as 3 */ info.entry_number = 3; error = copyout(&info, desc, sizeof(struct l_user_desc)); if (error) printf(LMSG("copyout failed!")); } a[0] = LINUX_LDT_entry_a(&info); a[1] = LINUX_LDT_entry_b(&info); memcpy(&sd, &a, sizeof(a)); #ifdef DEBUG if (ldebug(clone)) printf("Segment created in clone with " "CLONE_SETTLS: lobase: %x, hibase: %x, " "lolimit: %x, hilimit: %x, type: %i, " "dpl: %i, p: %i, xx: %i, def32: %i, " "gran: %i\n", sd.sd_lobase, sd.sd_hibase, sd.sd_lolimit, sd.sd_hilimit, sd.sd_type, sd.sd_dpl, sd.sd_p, sd.sd_xx, sd.sd_def32, sd.sd_gran); #endif /* set %gs */ td->td_pcb->pcb_gsd = sd; td->td_pcb->pcb_gs = GSEL(GUGS_SEL, SEL_UPL); } return (error); } int linux_set_upcall_kse(struct thread *td, register_t stack) { if (stack) td->td_frame->tf_esp = stack; /* * The newly created Linux thread returns * to the user space by the same path that a parent do. */ td->td_frame->tf_eax = 0; return (0); } int linux_mmap2(struct thread *td, struct linux_mmap2_args *args) { #ifdef DEBUG if (ldebug(mmap2)) printf(ARGS(mmap2, "%p, %d, %d, 0x%08x, %d, %d"), (void *)args->addr, args->len, args->prot, args->flags, args->fd, args->pgoff); #endif return (linux_mmap_common(td, args->addr, args->len, args->prot, args->flags, args->fd, (uint64_t)(uint32_t)args->pgoff * PAGE_SIZE)); } int linux_mmap(struct thread *td, struct linux_mmap_args *args) { int error; struct l_mmap_argv linux_args; error = copyin(args->ptr, &linux_args, sizeof(linux_args)); if (error) return (error); #ifdef DEBUG if (ldebug(mmap)) printf(ARGS(mmap, "%p, %d, %d, 0x%08x, %d, %d"), (void *)linux_args.addr, linux_args.len, linux_args.prot, linux_args.flags, linux_args.fd, linux_args.pgoff); #endif return (linux_mmap_common(td, linux_args.addr, linux_args.len, linux_args.prot, linux_args.flags, linux_args.fd, (uint32_t)linux_args.pgoff)); } int linux_mprotect(struct thread *td, struct linux_mprotect_args *uap) { return (linux_mprotect_common(td, PTROUT(uap->addr), uap->len, uap->prot)); } int linux_ioperm(struct thread *td, struct linux_ioperm_args *args) { int error; struct i386_ioperm_args iia; iia.start = args->start; iia.length = args->length; iia.enable = args->enable; error = i386_set_ioperm(td, &iia); return (error); } int linux_iopl(struct thread *td, struct linux_iopl_args *args) { int error; if (args->level < 0 || args->level > 3) return (EINVAL); if ((error = priv_check(td, PRIV_IO)) != 0) return (error); if ((error = securelevel_gt(td->td_ucred, 0)) != 0) return (error); td->td_frame->tf_eflags = (td->td_frame->tf_eflags & ~PSL_IOPL) | (args->level * (PSL_IOPL / 3)); return (0); } int linux_modify_ldt(struct thread *td, struct linux_modify_ldt_args *uap) { int error; struct i386_ldt_args ldt; struct l_descriptor ld; union descriptor desc; int size, written; switch (uap->func) { case 0x00: /* read_ldt */ ldt.start = 0; ldt.descs = uap->ptr; ldt.num = uap->bytecount / sizeof(union descriptor); error = i386_get_ldt(td, &ldt); td->td_retval[0] *= sizeof(union descriptor); break; case 0x02: /* read_default_ldt = 0 */ size = 5*sizeof(struct l_desc_struct); if (size > uap->bytecount) size = uap->bytecount; for (written = error = 0; written < size && error == 0; written++) error = subyte((char *)uap->ptr + written, 0); td->td_retval[0] = written; break; case 0x01: /* write_ldt */ case 0x11: /* write_ldt */ if (uap->bytecount != sizeof(ld)) return (EINVAL); error = copyin(uap->ptr, &ld, sizeof(ld)); if (error) return (error); ldt.start = ld.entry_number; ldt.descs = &desc; ldt.num = 1; desc.sd.sd_lolimit = (ld.limit & 0x0000ffff); desc.sd.sd_hilimit = (ld.limit & 0x000f0000) >> 16; desc.sd.sd_lobase = (ld.base_addr & 0x00ffffff); desc.sd.sd_hibase = (ld.base_addr & 0xff000000) >> 24; desc.sd.sd_type = SDT_MEMRO | ((ld.read_exec_only ^ 1) << 1) | (ld.contents << 2); desc.sd.sd_dpl = 3; desc.sd.sd_p = (ld.seg_not_present ^ 1); desc.sd.sd_xx = 0; desc.sd.sd_def32 = ld.seg_32bit; desc.sd.sd_gran = ld.limit_in_pages; error = i386_set_ldt(td, &ldt, &desc); break; default: error = ENOSYS; break; } if (error == EOPNOTSUPP) { printf("linux: modify_ldt needs kernel option USER_LDT\n"); error = ENOSYS; } return (error); } int linux_sigaction(struct thread *td, struct linux_sigaction_args *args) { l_osigaction_t osa; l_sigaction_t act, oact; int error; #ifdef DEBUG if (ldebug(sigaction)) printf(ARGS(sigaction, "%d, %p, %p"), args->sig, (void *)args->nsa, (void *)args->osa); #endif if (args->nsa != NULL) { error = copyin(args->nsa, &osa, sizeof(l_osigaction_t)); if (error) return (error); act.lsa_handler = osa.lsa_handler; act.lsa_flags = osa.lsa_flags; act.lsa_restorer = osa.lsa_restorer; LINUX_SIGEMPTYSET(act.lsa_mask); act.lsa_mask.__mask = osa.lsa_mask; } error = linux_do_sigaction(td, args->sig, args->nsa ? &act : NULL, args->osa ? &oact : NULL); if (args->osa != NULL && !error) { osa.lsa_handler = oact.lsa_handler; osa.lsa_flags = oact.lsa_flags; osa.lsa_restorer = oact.lsa_restorer; osa.lsa_mask = oact.lsa_mask.__mask; error = copyout(&osa, args->osa, sizeof(l_osigaction_t)); } return (error); } /* * Linux has two extra args, restart and oldmask. We dont use these, * but it seems that "restart" is actually a context pointer that * enables the signal to happen with a different register set. */ int linux_sigsuspend(struct thread *td, struct linux_sigsuspend_args *args) { sigset_t sigmask; l_sigset_t mask; #ifdef DEBUG if (ldebug(sigsuspend)) printf(ARGS(sigsuspend, "%08lx"), (unsigned long)args->mask); #endif LINUX_SIGEMPTYSET(mask); mask.__mask = args->mask; linux_to_bsd_sigset(&mask, &sigmask); return (kern_sigsuspend(td, sigmask)); } int linux_rt_sigsuspend(struct thread *td, struct linux_rt_sigsuspend_args *uap) { l_sigset_t lmask; sigset_t sigmask; int error; #ifdef DEBUG if (ldebug(rt_sigsuspend)) printf(ARGS(rt_sigsuspend, "%p, %d"), (void *)uap->newset, uap->sigsetsize); #endif if (uap->sigsetsize != sizeof(l_sigset_t)) return (EINVAL); error = copyin(uap->newset, &lmask, sizeof(l_sigset_t)); if (error) return (error); linux_to_bsd_sigset(&lmask, &sigmask); return (kern_sigsuspend(td, sigmask)); } int linux_pause(struct thread *td, struct linux_pause_args *args) { struct proc *p = td->td_proc; sigset_t sigmask; #ifdef DEBUG if (ldebug(pause)) printf(ARGS(pause, "")); #endif PROC_LOCK(p); sigmask = td->td_sigmask; PROC_UNLOCK(p); return (kern_sigsuspend(td, sigmask)); } int linux_sigaltstack(struct thread *td, struct linux_sigaltstack_args *uap) { stack_t ss, oss; l_stack_t lss; int error; #ifdef DEBUG if (ldebug(sigaltstack)) printf(ARGS(sigaltstack, "%p, %p"), uap->uss, uap->uoss); #endif if (uap->uss != NULL) { error = copyin(uap->uss, &lss, sizeof(l_stack_t)); if (error) return (error); ss.ss_sp = lss.ss_sp; ss.ss_size = lss.ss_size; ss.ss_flags = linux_to_bsd_sigaltstack(lss.ss_flags); } error = kern_sigaltstack(td, (uap->uss != NULL) ? &ss : NULL, (uap->uoss != NULL) ? &oss : NULL); if (!error && uap->uoss != NULL) { lss.ss_sp = oss.ss_sp; lss.ss_size = oss.ss_size; lss.ss_flags = bsd_to_linux_sigaltstack(oss.ss_flags); error = copyout(&lss, uap->uoss, sizeof(l_stack_t)); } return (error); } int linux_ftruncate64(struct thread *td, struct linux_ftruncate64_args *args) { #ifdef DEBUG if (ldebug(ftruncate64)) printf(ARGS(ftruncate64, "%u, %jd"), args->fd, (intmax_t)args->length); #endif return (kern_ftruncate(td, args->fd, args->length)); } int linux_set_thread_area(struct thread *td, struct linux_set_thread_area_args *args) { struct l_user_desc info; int error; int idx; int a[2]; struct segment_descriptor sd; error = copyin(args->desc, &info, sizeof(struct l_user_desc)); if (error) return (error); #ifdef DEBUG if (ldebug(set_thread_area)) printf(ARGS(set_thread_area, "%i, %x, %x, %i, %i, %i, %i, %i, %i\n"), info.entry_number, info.base_addr, info.limit, info.seg_32bit, info.contents, info.read_exec_only, info.limit_in_pages, info.seg_not_present, info.useable); #endif idx = info.entry_number; /* * Semantics of linux version: every thread in the system has array of * 3 tls descriptors. 1st is GLIBC TLS, 2nd is WINE, 3rd unknown. This * syscall loads one of the selected tls decriptors with a value and * also loads GDT descriptors 6, 7 and 8 with the content of the * per-thread descriptors. * * Semantics of fbsd version: I think we can ignore that linux has 3 * per-thread descriptors and use just the 1st one. The tls_array[] * is used only in set/get-thread_area() syscalls and for loading the * GDT descriptors. In fbsd we use just one GDT descriptor for TLS so * we will load just one. * * XXX: this doesn't work when a user space process tries to use more * than 1 TLS segment. Comment in the linux sources says wine might do * this. */ /* * we support just GLIBC TLS now * we should let 3 proceed as well because we use this segment so * if code does two subsequent calls it should succeed */ if (idx != 6 && idx != -1 && idx != 3) return (EINVAL); /* * we have to copy out the GDT entry we use * FreeBSD uses GDT entry #3 for storing %gs so load that * * XXX: what if a user space program doesn't check this value and tries * to use 6, 7 or 8? */ idx = info.entry_number = 3; error = copyout(&info, args->desc, sizeof(struct l_user_desc)); if (error) return (error); if (LINUX_LDT_empty(&info)) { a[0] = 0; a[1] = 0; } else { a[0] = LINUX_LDT_entry_a(&info); a[1] = LINUX_LDT_entry_b(&info); } memcpy(&sd, &a, sizeof(a)); #ifdef DEBUG if (ldebug(set_thread_area)) printf("Segment created in set_thread_area: lobase: %x, hibase: %x, lolimit: %x, hilimit: %x, type: %i, dpl: %i, p: %i, xx: %i, def32: %i, gran: %i\n", sd.sd_lobase, sd.sd_hibase, sd.sd_lolimit, sd.sd_hilimit, sd.sd_type, sd.sd_dpl, sd.sd_p, sd.sd_xx, sd.sd_def32, sd.sd_gran); #endif /* this is taken from i386 version of cpu_set_user_tls() */ critical_enter(); /* set %gs */ td->td_pcb->pcb_gsd = sd; PCPU_GET(fsgs_gdt)[1] = sd; load_gs(GSEL(GUGS_SEL, SEL_UPL)); critical_exit(); return (0); } int linux_get_thread_area(struct thread *td, struct linux_get_thread_area_args *args) { struct l_user_desc info; int error; int idx; struct l_desc_struct desc; struct segment_descriptor sd; #ifdef DEBUG if (ldebug(get_thread_area)) printf(ARGS(get_thread_area, "%p"), args->desc); #endif error = copyin(args->desc, &info, sizeof(struct l_user_desc)); if (error) return (error); idx = info.entry_number; /* XXX: I am not sure if we want 3 to be allowed too. */ if (idx != 6 && idx != 3) return (EINVAL); idx = 3; memset(&info, 0, sizeof(info)); sd = PCPU_GET(fsgs_gdt)[1]; memcpy(&desc, &sd, sizeof(desc)); info.entry_number = idx; info.base_addr = LINUX_GET_BASE(&desc); info.limit = LINUX_GET_LIMIT(&desc); info.seg_32bit = LINUX_GET_32BIT(&desc); info.contents = LINUX_GET_CONTENTS(&desc); info.read_exec_only = !LINUX_GET_WRITABLE(&desc); info.limit_in_pages = LINUX_GET_LIMIT_PAGES(&desc); info.seg_not_present = !LINUX_GET_PRESENT(&desc); info.useable = LINUX_GET_USEABLE(&desc); error = copyout(&info, args->desc, sizeof(struct l_user_desc)); if (error) return (EFAULT); return (0); } /* XXX: this wont work with module - convert it */ int linux_mq_open(struct thread *td, struct linux_mq_open_args *args) { #ifdef P1003_1B_MQUEUE return sys_kmq_open(td, (struct kmq_open_args *) args); #else return (ENOSYS); #endif } int linux_mq_unlink(struct thread *td, struct linux_mq_unlink_args *args) { #ifdef P1003_1B_MQUEUE return sys_kmq_unlink(td, (struct kmq_unlink_args *) args); #else return (ENOSYS); #endif } int linux_mq_timedsend(struct thread *td, struct linux_mq_timedsend_args *args) { #ifdef P1003_1B_MQUEUE return sys_kmq_timedsend(td, (struct kmq_timedsend_args *) args); #else return (ENOSYS); #endif } int linux_mq_timedreceive(struct thread *td, struct linux_mq_timedreceive_args *args) { #ifdef P1003_1B_MQUEUE return sys_kmq_timedreceive(td, (struct kmq_timedreceive_args *) args); #else return (ENOSYS); #endif } int linux_mq_notify(struct thread *td, struct linux_mq_notify_args *args) { #ifdef P1003_1B_MQUEUE return sys_kmq_notify(td, (struct kmq_notify_args *) args); #else return (ENOSYS); #endif } int linux_mq_getsetattr(struct thread *td, struct linux_mq_getsetattr_args *args) { #ifdef P1003_1B_MQUEUE return sys_kmq_setattr(td, (struct kmq_setattr_args *) args); #else return (ENOSYS); #endif } Index: head/sys/i386/linux/linux_ptrace.c =================================================================== --- head/sys/i386/linux/linux_ptrace.c (revision 326259) +++ head/sys/i386/linux/linux_ptrace.c (revision 326260) @@ -1,474 +1,476 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001 Alexander Kabaev * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_cpu.h" #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Linux ptrace requests numbers. Mostly identical to FreeBSD, * except for MD ones and PT_ATTACH/PT_DETACH. */ #define PTRACE_TRACEME 0 #define PTRACE_PEEKTEXT 1 #define PTRACE_PEEKDATA 2 #define PTRACE_PEEKUSR 3 #define PTRACE_POKETEXT 4 #define PTRACE_POKEDATA 5 #define PTRACE_POKEUSR 6 #define PTRACE_CONT 7 #define PTRACE_KILL 8 #define PTRACE_SINGLESTEP 9 #define PTRACE_ATTACH 16 #define PTRACE_DETACH 17 #define LINUX_PTRACE_SYSCALL 24 #define PTRACE_GETREGS 12 #define PTRACE_SETREGS 13 #define PTRACE_GETFPREGS 14 #define PTRACE_SETFPREGS 15 #define PTRACE_GETFPXREGS 18 #define PTRACE_SETFPXREGS 19 #define PTRACE_SETOPTIONS 21 /* * Linux keeps debug registers at the following * offset in the user struct */ #define LINUX_DBREG_OFFSET 252 #define LINUX_DBREG_SIZE (8*sizeof(l_int)) static __inline int map_signum(int signum) { signum = linux_to_bsd_signal(signum); return ((signum == SIGSTOP)? 0 : signum); } struct linux_pt_reg { l_long ebx; l_long ecx; l_long edx; l_long esi; l_long edi; l_long ebp; l_long eax; l_int xds; l_int xes; l_int xfs; l_int xgs; l_long orig_eax; l_long eip; l_int xcs; l_long eflags; l_long esp; l_int xss; }; /* * Translate i386 ptrace registers between Linux and FreeBSD formats. * The translation is pretty straighforward, for all registers, but * orig_eax on Linux side and r_trapno and r_err in FreeBSD */ static void map_regs_to_linux(struct reg *bsd_r, struct linux_pt_reg *linux_r) { linux_r->ebx = bsd_r->r_ebx; linux_r->ecx = bsd_r->r_ecx; linux_r->edx = bsd_r->r_edx; linux_r->esi = bsd_r->r_esi; linux_r->edi = bsd_r->r_edi; linux_r->ebp = bsd_r->r_ebp; linux_r->eax = bsd_r->r_eax; linux_r->xds = bsd_r->r_ds; linux_r->xes = bsd_r->r_es; linux_r->xfs = bsd_r->r_fs; linux_r->xgs = bsd_r->r_gs; linux_r->orig_eax = bsd_r->r_eax; linux_r->eip = bsd_r->r_eip; linux_r->xcs = bsd_r->r_cs; linux_r->eflags = bsd_r->r_eflags; linux_r->esp = bsd_r->r_esp; linux_r->xss = bsd_r->r_ss; } static void map_regs_from_linux(struct reg *bsd_r, struct linux_pt_reg *linux_r) { bsd_r->r_ebx = linux_r->ebx; bsd_r->r_ecx = linux_r->ecx; bsd_r->r_edx = linux_r->edx; bsd_r->r_esi = linux_r->esi; bsd_r->r_edi = linux_r->edi; bsd_r->r_ebp = linux_r->ebp; bsd_r->r_eax = linux_r->eax; bsd_r->r_ds = linux_r->xds; bsd_r->r_es = linux_r->xes; bsd_r->r_fs = linux_r->xfs; bsd_r->r_gs = linux_r->xgs; bsd_r->r_eip = linux_r->eip; bsd_r->r_cs = linux_r->xcs; bsd_r->r_eflags = linux_r->eflags; bsd_r->r_esp = linux_r->esp; bsd_r->r_ss = linux_r->xss; } struct linux_pt_fpreg { l_long cwd; l_long swd; l_long twd; l_long fip; l_long fcs; l_long foo; l_long fos; l_long st_space[2*10]; }; static void map_fpregs_to_linux(struct fpreg *bsd_r, struct linux_pt_fpreg *linux_r) { linux_r->cwd = bsd_r->fpr_env[0]; linux_r->swd = bsd_r->fpr_env[1]; linux_r->twd = bsd_r->fpr_env[2]; linux_r->fip = bsd_r->fpr_env[3]; linux_r->fcs = bsd_r->fpr_env[4]; linux_r->foo = bsd_r->fpr_env[5]; linux_r->fos = bsd_r->fpr_env[6]; bcopy(bsd_r->fpr_acc, linux_r->st_space, sizeof(linux_r->st_space)); } static void map_fpregs_from_linux(struct fpreg *bsd_r, struct linux_pt_fpreg *linux_r) { bsd_r->fpr_env[0] = linux_r->cwd; bsd_r->fpr_env[1] = linux_r->swd; bsd_r->fpr_env[2] = linux_r->twd; bsd_r->fpr_env[3] = linux_r->fip; bsd_r->fpr_env[4] = linux_r->fcs; bsd_r->fpr_env[5] = linux_r->foo; bsd_r->fpr_env[6] = linux_r->fos; bcopy(bsd_r->fpr_acc, linux_r->st_space, sizeof(bsd_r->fpr_acc)); } struct linux_pt_fpxreg { l_ushort cwd; l_ushort swd; l_ushort twd; l_ushort fop; l_long fip; l_long fcs; l_long foo; l_long fos; l_long mxcsr; l_long reserved; l_long st_space[32]; l_long xmm_space[32]; l_long padding[56]; }; static int linux_proc_read_fpxregs(struct thread *td, struct linux_pt_fpxreg *fpxregs) { PROC_LOCK_ASSERT(td->td_proc, MA_OWNED); if (cpu_fxsr == 0 || (td->td_proc->p_flag & P_INMEM) == 0) return (EIO); bcopy(&get_pcb_user_save_td(td)->sv_xmm, fpxregs, sizeof(*fpxregs)); return (0); } static int linux_proc_write_fpxregs(struct thread *td, struct linux_pt_fpxreg *fpxregs) { PROC_LOCK_ASSERT(td->td_proc, MA_OWNED); if (cpu_fxsr == 0 || (td->td_proc->p_flag & P_INMEM) == 0) return (EIO); bcopy(fpxregs, &get_pcb_user_save_td(td)->sv_xmm, sizeof(*fpxregs)); return (0); } int linux_ptrace(struct thread *td, struct linux_ptrace_args *uap) { union { struct linux_pt_reg reg; struct linux_pt_fpreg fpreg; struct linux_pt_fpxreg fpxreg; } r; union { struct reg bsd_reg; struct fpreg bsd_fpreg; struct dbreg bsd_dbreg; } u; void *addr; pid_t pid; int error, req; error = 0; /* by default, just copy data intact */ req = uap->req; pid = (pid_t)uap->pid; addr = (void *)uap->addr; switch (req) { case PTRACE_TRACEME: case PTRACE_POKETEXT: case PTRACE_POKEDATA: case PTRACE_KILL: error = kern_ptrace(td, req, pid, addr, uap->data); break; case PTRACE_PEEKTEXT: case PTRACE_PEEKDATA: { /* need to preserve return value */ int rval = td->td_retval[0]; error = kern_ptrace(td, req, pid, addr, 0); if (error == 0) error = copyout(td->td_retval, (void *)uap->data, sizeof(l_int)); td->td_retval[0] = rval; break; } case PTRACE_DETACH: error = kern_ptrace(td, PT_DETACH, pid, (void *)1, map_signum(uap->data)); break; case PTRACE_SINGLESTEP: case PTRACE_CONT: error = kern_ptrace(td, req, pid, (void *)1, map_signum(uap->data)); break; case PTRACE_ATTACH: error = kern_ptrace(td, PT_ATTACH, pid, addr, uap->data); break; case PTRACE_GETREGS: /* Linux is using data where FreeBSD is using addr */ error = kern_ptrace(td, PT_GETREGS, pid, &u.bsd_reg, 0); if (error == 0) { map_regs_to_linux(&u.bsd_reg, &r.reg); error = copyout(&r.reg, (void *)uap->data, sizeof(r.reg)); } break; case PTRACE_SETREGS: /* Linux is using data where FreeBSD is using addr */ error = copyin((void *)uap->data, &r.reg, sizeof(r.reg)); if (error == 0) { map_regs_from_linux(&u.bsd_reg, &r.reg); error = kern_ptrace(td, PT_SETREGS, pid, &u.bsd_reg, 0); } break; case PTRACE_GETFPREGS: /* Linux is using data where FreeBSD is using addr */ error = kern_ptrace(td, PT_GETFPREGS, pid, &u.bsd_fpreg, 0); if (error == 0) { map_fpregs_to_linux(&u.bsd_fpreg, &r.fpreg); error = copyout(&r.fpreg, (void *)uap->data, sizeof(r.fpreg)); } break; case PTRACE_SETFPREGS: /* Linux is using data where FreeBSD is using addr */ error = copyin((void *)uap->data, &r.fpreg, sizeof(r.fpreg)); if (error == 0) { map_fpregs_from_linux(&u.bsd_fpreg, &r.fpreg); error = kern_ptrace(td, PT_SETFPREGS, pid, &u.bsd_fpreg, 0); } break; case PTRACE_SETFPXREGS: error = copyin((void *)uap->data, &r.fpxreg, sizeof(r.fpxreg)); if (error) break; /* FALL THROUGH */ case PTRACE_GETFPXREGS: { struct proc *p; struct thread *td2; if (sizeof(struct linux_pt_fpxreg) != sizeof(struct savexmm)) { static int once = 0; if (!once) { printf("linux: savexmm != linux_pt_fpxreg\n"); once = 1; } error = EIO; break; } if ((p = pfind(uap->pid)) == NULL) { error = ESRCH; break; } /* Exiting processes can't be debugged. */ if ((p->p_flag & P_WEXIT) != 0) { error = ESRCH; goto fail; } if ((error = p_candebug(td, p)) != 0) goto fail; /* System processes can't be debugged. */ if ((p->p_flag & P_SYSTEM) != 0) { error = EINVAL; goto fail; } /* not being traced... */ if ((p->p_flag & P_TRACED) == 0) { error = EPERM; goto fail; } /* not being traced by YOU */ if (p->p_pptr != td->td_proc) { error = EBUSY; goto fail; } /* not currently stopped */ if (!P_SHOULDSTOP(p) || (p->p_flag & P_WAITED) == 0) { error = EBUSY; goto fail; } if (req == PTRACE_GETFPXREGS) { _PHOLD(p); /* may block */ td2 = FIRST_THREAD_IN_PROC(p); error = linux_proc_read_fpxregs(td2, &r.fpxreg); _PRELE(p); PROC_UNLOCK(p); if (error == 0) error = copyout(&r.fpxreg, (void *)uap->data, sizeof(r.fpxreg)); } else { /* clear dangerous bits exactly as Linux does*/ r.fpxreg.mxcsr &= 0xffbf; _PHOLD(p); /* may block */ td2 = FIRST_THREAD_IN_PROC(p); error = linux_proc_write_fpxregs(td2, &r.fpxreg); _PRELE(p); PROC_UNLOCK(p); } break; fail: PROC_UNLOCK(p); break; } case PTRACE_PEEKUSR: case PTRACE_POKEUSR: { error = EIO; /* check addr for alignment */ if (uap->addr < 0 || uap->addr & (sizeof(l_int) - 1)) break; /* * Allow linux programs to access register values in * user struct. We simulate this through PT_GET/SETREGS * as necessary. */ if (uap->addr < sizeof(struct linux_pt_reg)) { error = kern_ptrace(td, PT_GETREGS, pid, &u.bsd_reg, 0); if (error != 0) break; map_regs_to_linux(&u.bsd_reg, &r.reg); if (req == PTRACE_PEEKUSR) { error = copyout((char *)&r.reg + uap->addr, (void *)uap->data, sizeof(l_int)); break; } *(l_int *)((char *)&r.reg + uap->addr) = (l_int)uap->data; map_regs_from_linux(&u.bsd_reg, &r.reg); error = kern_ptrace(td, PT_SETREGS, pid, &u.bsd_reg, 0); } /* * Simulate debug registers access */ if (uap->addr >= LINUX_DBREG_OFFSET && uap->addr <= LINUX_DBREG_OFFSET + LINUX_DBREG_SIZE) { error = kern_ptrace(td, PT_GETDBREGS, pid, &u.bsd_dbreg, 0); if (error != 0) break; uap->addr -= LINUX_DBREG_OFFSET; if (req == PTRACE_PEEKUSR) { error = copyout((char *)&u.bsd_dbreg + uap->addr, (void *)uap->data, sizeof(l_int)); break; } *(l_int *)((char *)&u.bsd_dbreg + uap->addr) = uap->data; error = kern_ptrace(td, PT_SETDBREGS, pid, &u.bsd_dbreg, 0); } break; } case LINUX_PTRACE_SYSCALL: /* fall through */ default: printf("linux: ptrace(%u, ...) not implemented\n", (unsigned int)uap->req); error = EINVAL; break; } return (error); } Index: head/sys/i386/linux/linux_sysvec.c =================================================================== --- head/sys/i386/linux/linux_sysvec.c (revision 326259) +++ head/sys/i386/linux/linux_sysvec.c (revision 326260) @@ -1,1215 +1,1217 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1994-1996 Søren Schmidt * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include MODULE_VERSION(linux, 1); #if BYTE_ORDER == LITTLE_ENDIAN #define SHELLMAGIC 0x2123 /* #! */ #else #define SHELLMAGIC 0x2321 #endif #if defined(DEBUG) SYSCTL_PROC(_compat_linux, OID_AUTO, debug, CTLTYPE_STRING | CTLFLAG_RW, 0, 0, linux_sysctl_debug, "A", "Linux debugging control"); #endif /* * Allow the sendsig functions to use the ldebug() facility * even though they are not syscalls themselves. Map them * to syscall 0. This is slightly less bogus than using * ldebug(sigreturn). */ #define LINUX_SYS_linux_rt_sendsig 0 #define LINUX_SYS_linux_sendsig 0 #define LINUX_PS_STRINGS (LINUX_USRSTACK - sizeof(struct ps_strings)) static int linux_szsigcode; static vm_object_t linux_shared_page_obj; static char *linux_shared_page_mapping; extern char _binary_linux_locore_o_start; extern char _binary_linux_locore_o_end; extern struct sysent linux_sysent[LINUX_SYS_MAXSYSCALL]; SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler); static int linux_fixup(register_t **stack_base, struct image_params *iparams); static int elf_linux_fixup(register_t **stack_base, struct image_params *iparams); static void linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask); static void exec_linux_setregs(struct thread *td, struct image_params *imgp, u_long stack); static register_t *linux_copyout_strings(struct image_params *imgp); static boolean_t linux_trans_osrel(const Elf_Note *note, int32_t *osrel); static void linux_vdso_install(void *param); static void linux_vdso_deinstall(void *param); static int linux_szplatform; const char *linux_kplatform; static eventhandler_tag linux_exit_tag; static eventhandler_tag linux_exec_tag; static eventhandler_tag linux_thread_dtor_tag; /* * Linux syscalls return negative errno's, we do positive and map them * Reference: * FreeBSD: src/sys/sys/errno.h * Linux: linux-2.6.17.8/include/asm-generic/errno-base.h * linux-2.6.17.8/include/asm-generic/errno.h */ static int bsd_to_linux_errno[ELAST + 1] = { -0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -35, -12, -13, -14, -15, -16, -17, -18, -19, -20, -21, -22, -23, -24, -25, -26, -27, -28, -29, -30, -31, -32, -33, -34, -11,-115,-114, -88, -89, -90, -91, -92, -93, -94, -95, -96, -97, -98, -99, -100,-101,-102,-103,-104,-105,-106,-107,-108,-109, -110,-111, -40, -36,-112,-113, -39, -11, -87,-122, -116, -66, -6, -6, -6, -6, -6, -37, -38, -9, -6, -6, -43, -42, -75,-125, -84, -95, -16, -74, -72, -67, -71 }; #define LINUX_T_UNKNOWN 255 static int _bsd_to_linux_trapcode[] = { LINUX_T_UNKNOWN, /* 0 */ 6, /* 1 T_PRIVINFLT */ LINUX_T_UNKNOWN, /* 2 */ 3, /* 3 T_BPTFLT */ LINUX_T_UNKNOWN, /* 4 */ LINUX_T_UNKNOWN, /* 5 */ 16, /* 6 T_ARITHTRAP */ 254, /* 7 T_ASTFLT */ LINUX_T_UNKNOWN, /* 8 */ 13, /* 9 T_PROTFLT */ 1, /* 10 T_TRCTRAP */ LINUX_T_UNKNOWN, /* 11 */ 14, /* 12 T_PAGEFLT */ LINUX_T_UNKNOWN, /* 13 */ 17, /* 14 T_ALIGNFLT */ LINUX_T_UNKNOWN, /* 15 */ LINUX_T_UNKNOWN, /* 16 */ LINUX_T_UNKNOWN, /* 17 */ 0, /* 18 T_DIVIDE */ 2, /* 19 T_NMI */ 4, /* 20 T_OFLOW */ 5, /* 21 T_BOUND */ 7, /* 22 T_DNA */ 8, /* 23 T_DOUBLEFLT */ 9, /* 24 T_FPOPFLT */ 10, /* 25 T_TSSFLT */ 11, /* 26 T_SEGNPFLT */ 12, /* 27 T_STKFLT */ 18, /* 28 T_MCHK */ 19, /* 29 T_XMMFLT */ 15 /* 30 T_RESERVED */ }; #define bsd_to_linux_trapcode(code) \ ((code)args->argc + 1); (*stack_base)--; suword(*stack_base, (intptr_t)(void *)envp); (*stack_base)--; suword(*stack_base, (intptr_t)(void *)argv); (*stack_base)--; suword(*stack_base, imgp->args->argc); return (0); } static int elf_linux_fixup(register_t **stack_base, struct image_params *imgp) { struct proc *p; Elf32_Auxargs *args; Elf32_Addr *uplatform; struct ps_strings *arginfo; register_t *pos; int issetugid; KASSERT(curthread->td_proc == imgp->proc, ("unsafe elf_linux_fixup(), should be curproc")); p = imgp->proc; issetugid = imgp->proc->p_flag & P_SUGID ? 1 : 0; arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings; uplatform = (Elf32_Addr *)((caddr_t)arginfo - linux_szplatform); args = (Elf32_Auxargs *)imgp->auxargs; pos = *stack_base + (imgp->args->argc + imgp->args->envc + 2); AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO_EHDR, imgp->proc->p_sysent->sv_shared_page_base); AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO, linux_vsyscall); AUXARGS_ENTRY(pos, LINUX_AT_HWCAP, cpu_feature); /* * Do not export AT_CLKTCK when emulating Linux kernel prior to 2.4.0, * as it has appeared in the 2.4.0-rc7 first time. * Being exported, AT_CLKTCK is returned by sysconf(_SC_CLK_TCK), * glibc falls back to the hard-coded CLK_TCK value when aux entry * is not present. * Also see linux_times() implementation. */ if (linux_kernver(curthread) >= LINUX_KERNVER_2004000) AUXARGS_ENTRY(pos, LINUX_AT_CLKTCK, stclohz); AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); AUXARGS_ENTRY(pos, AT_PHENT, args->phent); AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz); AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); AUXARGS_ENTRY(pos, AT_BASE, args->base); AUXARGS_ENTRY(pos, LINUX_AT_SECURE, issetugid); AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid); AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid); AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid); AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid); AUXARGS_ENTRY(pos, LINUX_AT_PLATFORM, PTROUT(uplatform)); AUXARGS_ENTRY(pos, LINUX_AT_RANDOM, imgp->canary); if (imgp->execpathp != 0) AUXARGS_ENTRY(pos, LINUX_AT_EXECFN, imgp->execpathp); if (args->execfd != -1) AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); AUXARGS_ENTRY(pos, AT_NULL, 0); free(imgp->auxargs, M_TEMP); imgp->auxargs = NULL; (*stack_base)--; suword(*stack_base, (register_t)imgp->args->argc); return (0); } /* * Copied from kern/kern_exec.c */ static register_t * linux_copyout_strings(struct image_params *imgp) { int argc, envc; char **vectp; char *stringp, *destp; register_t *stack_base; struct ps_strings *arginfo; char canary[LINUX_AT_RANDOM_LEN]; size_t execpath_len; struct proc *p; /* * Calculate string base and vector table pointers. */ p = imgp->proc; if (imgp->execpath != NULL && imgp->auxargs != NULL) execpath_len = strlen(imgp->execpath) + 1; else execpath_len = 0; arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings; destp = (caddr_t)arginfo - SPARE_USRSPACE - linux_szplatform - roundup(sizeof(canary), sizeof(char *)) - roundup(execpath_len, sizeof(char *)) - roundup(ARG_MAX - imgp->args->stringspace, sizeof(char *)); /* * install LINUX_PLATFORM */ copyout(linux_kplatform, ((caddr_t)arginfo - linux_szplatform), linux_szplatform); if (execpath_len != 0) { imgp->execpathp = (uintptr_t)arginfo - linux_szplatform - execpath_len; copyout(imgp->execpath, (void *)imgp->execpathp, execpath_len); } /* * Prepare the canary for SSP. */ arc4rand(canary, sizeof(canary), 0); imgp->canary = (uintptr_t)arginfo - linux_szplatform - roundup(execpath_len, sizeof(char *)) - roundup(sizeof(canary), sizeof(char *)); copyout(canary, (void *)imgp->canary, sizeof(canary)); /* * If we have a valid auxargs ptr, prepare some room * on the stack. */ if (imgp->auxargs) { /* * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for * lower compatibility. */ imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size : (LINUX_AT_COUNT * 2); /* * The '+ 2' is for the null pointers at the end of each of * the arg and env vector sets,and imgp->auxarg_size is room * for argument of Runtime loader. */ vectp = (char **)(destp - (imgp->args->argc + imgp->args->envc + 2 + imgp->auxarg_size) * sizeof(char *)); } else { /* * The '+ 2' is for the null pointers at the end of each of * the arg and env vector sets */ vectp = (char **)(destp - (imgp->args->argc + imgp->args->envc + 2) * sizeof(char *)); } /* * vectp also becomes our initial stack base */ stack_base = (register_t *)vectp; stringp = imgp->args->begin_argv; argc = imgp->args->argc; envc = imgp->args->envc; /* * Copy out strings - arguments and environment. */ copyout(stringp, destp, ARG_MAX - imgp->args->stringspace); /* * Fill in "ps_strings" struct for ps, w, etc. */ suword(&arginfo->ps_argvstr, (long)(intptr_t)vectp); suword(&arginfo->ps_nargvstr, argc); /* * Fill in argument portion of vector table. */ for (; argc > 0; --argc) { suword(vectp++, (long)(intptr_t)destp); while (*stringp++ != 0) destp++; destp++; } /* a null vector table pointer separates the argp's from the envp's */ suword(vectp++, 0); suword(&arginfo->ps_envstr, (long)(intptr_t)vectp); suword(&arginfo->ps_nenvstr, envc); /* * Fill in environment portion of vector table. */ for (; envc > 0; --envc) { suword(vectp++, (long)(intptr_t)destp); while (*stringp++ != 0) destp++; destp++; } /* end of vector table is a null pointer */ suword(vectp, 0); return (stack_base); } static void linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) { struct thread *td = curthread; struct proc *p = td->td_proc; struct sigacts *psp; struct trapframe *regs; struct l_rt_sigframe *fp, frame; int sig, code; int oonstack; sig = ksi->ksi_signo; code = ksi->ksi_code; PROC_LOCK_ASSERT(p, MA_OWNED); psp = p->p_sigacts; mtx_assert(&psp->ps_mtx, MA_OWNED); regs = td->td_frame; oonstack = sigonstack(regs->tf_esp); #ifdef DEBUG if (ldebug(rt_sendsig)) printf(ARGS(rt_sendsig, "%p, %d, %p, %u"), catcher, sig, (void*)mask, code); #endif /* * Allocate space for the signal handler context. */ if ((td->td_pflags & TDP_ALTSTACK) && !oonstack && SIGISMEMBER(psp->ps_sigonstack, sig)) { fp = (struct l_rt_sigframe *)((uintptr_t)td->td_sigstk.ss_sp + td->td_sigstk.ss_size - sizeof(struct l_rt_sigframe)); } else fp = (struct l_rt_sigframe *)regs->tf_esp - 1; mtx_unlock(&psp->ps_mtx); /* * Build the argument list for the signal handler. */ sig = bsd_to_linux_signal(sig); bzero(&frame, sizeof(frame)); frame.sf_handler = catcher; frame.sf_sig = sig; frame.sf_siginfo = &fp->sf_si; frame.sf_ucontext = &fp->sf_sc; /* Fill in POSIX parts */ ksiginfo_to_lsiginfo(ksi, &frame.sf_si, sig); /* * Build the signal context to be used by sigreturn. */ frame.sf_sc.uc_flags = 0; /* XXX ??? */ frame.sf_sc.uc_link = NULL; /* XXX ??? */ frame.sf_sc.uc_stack.ss_sp = td->td_sigstk.ss_sp; frame.sf_sc.uc_stack.ss_size = td->td_sigstk.ss_size; frame.sf_sc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) ? ((oonstack) ? LINUX_SS_ONSTACK : 0) : LINUX_SS_DISABLE; PROC_UNLOCK(p); bsd_to_linux_sigset(mask, &frame.sf_sc.uc_sigmask); frame.sf_sc.uc_mcontext.sc_mask = frame.sf_sc.uc_sigmask.__mask; frame.sf_sc.uc_mcontext.sc_gs = rgs(); frame.sf_sc.uc_mcontext.sc_fs = regs->tf_fs; frame.sf_sc.uc_mcontext.sc_es = regs->tf_es; frame.sf_sc.uc_mcontext.sc_ds = regs->tf_ds; frame.sf_sc.uc_mcontext.sc_edi = regs->tf_edi; frame.sf_sc.uc_mcontext.sc_esi = regs->tf_esi; frame.sf_sc.uc_mcontext.sc_ebp = regs->tf_ebp; frame.sf_sc.uc_mcontext.sc_ebx = regs->tf_ebx; frame.sf_sc.uc_mcontext.sc_esp = regs->tf_esp; frame.sf_sc.uc_mcontext.sc_edx = regs->tf_edx; frame.sf_sc.uc_mcontext.sc_ecx = regs->tf_ecx; frame.sf_sc.uc_mcontext.sc_eax = regs->tf_eax; frame.sf_sc.uc_mcontext.sc_eip = regs->tf_eip; frame.sf_sc.uc_mcontext.sc_cs = regs->tf_cs; frame.sf_sc.uc_mcontext.sc_eflags = regs->tf_eflags; frame.sf_sc.uc_mcontext.sc_esp_at_signal = regs->tf_esp; frame.sf_sc.uc_mcontext.sc_ss = regs->tf_ss; frame.sf_sc.uc_mcontext.sc_err = regs->tf_err; frame.sf_sc.uc_mcontext.sc_cr2 = (register_t)ksi->ksi_addr; frame.sf_sc.uc_mcontext.sc_trapno = bsd_to_linux_trapcode(code); #ifdef DEBUG if (ldebug(rt_sendsig)) printf(LMSG("rt_sendsig flags: 0x%x, sp: %p, ss: 0x%x, mask: 0x%x"), frame.sf_sc.uc_stack.ss_flags, td->td_sigstk.ss_sp, td->td_sigstk.ss_size, frame.sf_sc.uc_mcontext.sc_mask); #endif if (copyout(&frame, fp, sizeof(frame)) != 0) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ #ifdef DEBUG if (ldebug(rt_sendsig)) printf(LMSG("rt_sendsig: bad stack %p, oonstack=%x"), fp, oonstack); #endif PROC_LOCK(p); sigexit(td, SIGILL); } /* * Build context to run handler in. */ regs->tf_esp = (int)fp; regs->tf_eip = linux_rt_sigcode; regs->tf_eflags &= ~(PSL_T | PSL_VM | PSL_D); regs->tf_cs = _ucodesel; regs->tf_ds = _udatasel; regs->tf_es = _udatasel; regs->tf_fs = _udatasel; regs->tf_ss = _udatasel; PROC_LOCK(p); mtx_lock(&psp->ps_mtx); } /* * Send an interrupt to process. * * Stack is set up to allow sigcode stored * in u. to call routine, followed by kcall * to sigreturn routine below. After sigreturn * resets the signal mask, the stack, and the * frame pointer, it returns to the user * specified pc, psl. */ static void linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) { struct thread *td = curthread; struct proc *p = td->td_proc; struct sigacts *psp; struct trapframe *regs; struct l_sigframe *fp, frame; l_sigset_t lmask; int sig, code; int oonstack; PROC_LOCK_ASSERT(p, MA_OWNED); psp = p->p_sigacts; sig = ksi->ksi_signo; code = ksi->ksi_code; mtx_assert(&psp->ps_mtx, MA_OWNED); if (SIGISMEMBER(psp->ps_siginfo, sig)) { /* Signal handler installed with SA_SIGINFO. */ linux_rt_sendsig(catcher, ksi, mask); return; } regs = td->td_frame; oonstack = sigonstack(regs->tf_esp); #ifdef DEBUG if (ldebug(sendsig)) printf(ARGS(sendsig, "%p, %d, %p, %u"), catcher, sig, (void*)mask, code); #endif /* * Allocate space for the signal handler context. */ if ((td->td_pflags & TDP_ALTSTACK) && !oonstack && SIGISMEMBER(psp->ps_sigonstack, sig)) { fp = (struct l_sigframe *)((uintptr_t)td->td_sigstk.ss_sp + td->td_sigstk.ss_size - sizeof(struct l_sigframe)); } else fp = (struct l_sigframe *)regs->tf_esp - 1; mtx_unlock(&psp->ps_mtx); PROC_UNLOCK(p); /* * Build the argument list for the signal handler. */ sig = bsd_to_linux_signal(sig); bzero(&frame, sizeof(frame)); frame.sf_handler = catcher; frame.sf_sig = sig; bsd_to_linux_sigset(mask, &lmask); /* * Build the signal context to be used by sigreturn. */ frame.sf_sc.sc_mask = lmask.__mask; frame.sf_sc.sc_gs = rgs(); frame.sf_sc.sc_fs = regs->tf_fs; frame.sf_sc.sc_es = regs->tf_es; frame.sf_sc.sc_ds = regs->tf_ds; frame.sf_sc.sc_edi = regs->tf_edi; frame.sf_sc.sc_esi = regs->tf_esi; frame.sf_sc.sc_ebp = regs->tf_ebp; frame.sf_sc.sc_ebx = regs->tf_ebx; frame.sf_sc.sc_esp = regs->tf_esp; frame.sf_sc.sc_edx = regs->tf_edx; frame.sf_sc.sc_ecx = regs->tf_ecx; frame.sf_sc.sc_eax = regs->tf_eax; frame.sf_sc.sc_eip = regs->tf_eip; frame.sf_sc.sc_cs = regs->tf_cs; frame.sf_sc.sc_eflags = regs->tf_eflags; frame.sf_sc.sc_esp_at_signal = regs->tf_esp; frame.sf_sc.sc_ss = regs->tf_ss; frame.sf_sc.sc_err = regs->tf_err; frame.sf_sc.sc_cr2 = (register_t)ksi->ksi_addr; frame.sf_sc.sc_trapno = bsd_to_linux_trapcode(ksi->ksi_trapno); frame.sf_extramask[0] = lmask.__mask; if (copyout(&frame, fp, sizeof(frame)) != 0) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ PROC_LOCK(p); sigexit(td, SIGILL); } /* * Build context to run handler in. */ regs->tf_esp = (int)fp; regs->tf_eip = linux_sigcode; regs->tf_eflags &= ~(PSL_T | PSL_VM | PSL_D); regs->tf_cs = _ucodesel; regs->tf_ds = _udatasel; regs->tf_es = _udatasel; regs->tf_fs = _udatasel; regs->tf_ss = _udatasel; PROC_LOCK(p); mtx_lock(&psp->ps_mtx); } /* * System call to cleanup state after a signal * has been taken. Reset signal mask and * stack state from context left by sendsig (above). * Return to previous pc and psl as specified by * context left by sendsig. Check carefully to * make sure that the user has not modified the * psl to gain improper privileges or to cause * a machine fault. */ int linux_sigreturn(struct thread *td, struct linux_sigreturn_args *args) { struct l_sigframe frame; struct trapframe *regs; l_sigset_t lmask; sigset_t bmask; int eflags; ksiginfo_t ksi; regs = td->td_frame; #ifdef DEBUG if (ldebug(sigreturn)) printf(ARGS(sigreturn, "%p"), (void *)args->sfp); #endif /* * The trampoline code hands us the sigframe. * It is unsafe to keep track of it ourselves, in the event that a * program jumps out of a signal handler. */ if (copyin(args->sfp, &frame, sizeof(frame)) != 0) return (EFAULT); /* * Check for security violations. */ #define EFLAGS_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) eflags = frame.sf_sc.sc_eflags; if (!EFLAGS_SECURE(eflags, regs->tf_eflags)) return (EINVAL); /* * Don't allow users to load a valid privileged %cs. Let the * hardware check for invalid selectors, excess privilege in * other selectors, invalid %eip's and invalid %esp's. */ #define CS_SECURE(cs) (ISPL(cs) == SEL_UPL) if (!CS_SECURE(frame.sf_sc.sc_cs)) { ksiginfo_init_trap(&ksi); ksi.ksi_signo = SIGBUS; ksi.ksi_code = BUS_OBJERR; ksi.ksi_trapno = T_PROTFLT; ksi.ksi_addr = (void *)regs->tf_eip; trapsignal(td, &ksi); return (EINVAL); } lmask.__mask = frame.sf_sc.sc_mask; linux_to_bsd_sigset(&lmask, &bmask); kern_sigprocmask(td, SIG_SETMASK, &bmask, NULL, 0); /* * Restore signal context. */ /* %gs was restored by the trampoline. */ regs->tf_fs = frame.sf_sc.sc_fs; regs->tf_es = frame.sf_sc.sc_es; regs->tf_ds = frame.sf_sc.sc_ds; regs->tf_edi = frame.sf_sc.sc_edi; regs->tf_esi = frame.sf_sc.sc_esi; regs->tf_ebp = frame.sf_sc.sc_ebp; regs->tf_ebx = frame.sf_sc.sc_ebx; regs->tf_edx = frame.sf_sc.sc_edx; regs->tf_ecx = frame.sf_sc.sc_ecx; regs->tf_eax = frame.sf_sc.sc_eax; regs->tf_eip = frame.sf_sc.sc_eip; regs->tf_cs = frame.sf_sc.sc_cs; regs->tf_eflags = eflags; regs->tf_esp = frame.sf_sc.sc_esp_at_signal; regs->tf_ss = frame.sf_sc.sc_ss; return (EJUSTRETURN); } /* * System call to cleanup state after a signal * has been taken. Reset signal mask and * stack state from context left by rt_sendsig (above). * Return to previous pc and psl as specified by * context left by sendsig. Check carefully to * make sure that the user has not modified the * psl to gain improper privileges or to cause * a machine fault. */ int linux_rt_sigreturn(struct thread *td, struct linux_rt_sigreturn_args *args) { struct l_ucontext uc; struct l_sigcontext *context; sigset_t bmask; l_stack_t *lss; stack_t ss; struct trapframe *regs; int eflags; ksiginfo_t ksi; regs = td->td_frame; #ifdef DEBUG if (ldebug(rt_sigreturn)) printf(ARGS(rt_sigreturn, "%p"), (void *)args->ucp); #endif /* * The trampoline code hands us the ucontext. * It is unsafe to keep track of it ourselves, in the event that a * program jumps out of a signal handler. */ if (copyin(args->ucp, &uc, sizeof(uc)) != 0) return (EFAULT); context = &uc.uc_mcontext; /* * Check for security violations. */ #define EFLAGS_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) eflags = context->sc_eflags; if (!EFLAGS_SECURE(eflags, regs->tf_eflags)) return (EINVAL); /* * Don't allow users to load a valid privileged %cs. Let the * hardware check for invalid selectors, excess privilege in * other selectors, invalid %eip's and invalid %esp's. */ #define CS_SECURE(cs) (ISPL(cs) == SEL_UPL) if (!CS_SECURE(context->sc_cs)) { ksiginfo_init_trap(&ksi); ksi.ksi_signo = SIGBUS; ksi.ksi_code = BUS_OBJERR; ksi.ksi_trapno = T_PROTFLT; ksi.ksi_addr = (void *)regs->tf_eip; trapsignal(td, &ksi); return (EINVAL); } linux_to_bsd_sigset(&uc.uc_sigmask, &bmask); kern_sigprocmask(td, SIG_SETMASK, &bmask, NULL, 0); /* * Restore signal context */ /* %gs was restored by the trampoline. */ regs->tf_fs = context->sc_fs; regs->tf_es = context->sc_es; regs->tf_ds = context->sc_ds; regs->tf_edi = context->sc_edi; regs->tf_esi = context->sc_esi; regs->tf_ebp = context->sc_ebp; regs->tf_ebx = context->sc_ebx; regs->tf_edx = context->sc_edx; regs->tf_ecx = context->sc_ecx; regs->tf_eax = context->sc_eax; regs->tf_eip = context->sc_eip; regs->tf_cs = context->sc_cs; regs->tf_eflags = eflags; regs->tf_esp = context->sc_esp_at_signal; regs->tf_ss = context->sc_ss; /* * call sigaltstack & ignore results.. */ lss = &uc.uc_stack; ss.ss_sp = lss->ss_sp; ss.ss_size = lss->ss_size; ss.ss_flags = linux_to_bsd_sigaltstack(lss->ss_flags); #ifdef DEBUG if (ldebug(rt_sigreturn)) printf(LMSG("rt_sigret flags: 0x%x, sp: %p, ss: 0x%x, mask: 0x%x"), ss.ss_flags, ss.ss_sp, ss.ss_size, context->sc_mask); #endif (void)kern_sigaltstack(td, &ss, NULL); return (EJUSTRETURN); } static int linux_fetch_syscall_args(struct thread *td) { struct proc *p; struct trapframe *frame; struct syscall_args *sa; p = td->td_proc; frame = td->td_frame; sa = &td->td_sa; sa->code = frame->tf_eax; sa->args[0] = frame->tf_ebx; sa->args[1] = frame->tf_ecx; sa->args[2] = frame->tf_edx; sa->args[3] = frame->tf_esi; sa->args[4] = frame->tf_edi; sa->args[5] = frame->tf_ebp; /* Unconfirmed */ if (sa->code >= p->p_sysent->sv_size) /* nosys */ sa->callp = &p->p_sysent->sv_table[p->p_sysent->sv_size - 1]; else sa->callp = &p->p_sysent->sv_table[sa->code]; sa->narg = sa->callp->sy_narg; td->td_retval[0] = 0; td->td_retval[1] = frame->tf_edx; return (0); } /* * If a linux binary is exec'ing something, try this image activator * first. We override standard shell script execution in order to * be able to modify the interpreter path. We only do this if a linux * binary is doing the exec, so we do not create an EXEC module for it. */ static int exec_linux_imgact_try(struct image_params *iparams); static int exec_linux_imgact_try(struct image_params *imgp) { const char *head = (const char *)imgp->image_header; char *rpath; int error = -1; /* * The interpreter for shell scripts run from a linux binary needs * to be located in /compat/linux if possible in order to recursively * maintain linux path emulation. */ if (((const short *)head)[0] == SHELLMAGIC) { /* * Run our normal shell image activator. If it succeeds attempt * to use the alternate path for the interpreter. If an alternate * path is found, use our stringspace to store it. */ if ((error = exec_shell_imgact(imgp)) == 0) { linux_emul_convpath(FIRST_THREAD_IN_PROC(imgp->proc), imgp->interpreter_name, UIO_SYSSPACE, &rpath, 0, AT_FDCWD); if (rpath != NULL) imgp->args->fname_buf = imgp->interpreter_name = rpath; } } return (error); } /* * exec_setregs may initialize some registers differently than Linux * does, thus potentially confusing Linux binaries. If necessary, we * override the exec_setregs default(s) here. */ static void exec_linux_setregs(struct thread *td, struct image_params *imgp, u_long stack) { struct pcb *pcb = td->td_pcb; exec_setregs(td, imgp, stack); /* Linux sets %gs to 0, we default to _udatasel */ pcb->pcb_gs = 0; load_gs(0); pcb->pcb_initial_npxcw = __LINUX_NPXCW__; } static void linux_get_machine(const char **dst) { switch (cpu_class) { case CPUCLASS_686: *dst = "i686"; break; case CPUCLASS_586: *dst = "i586"; break; case CPUCLASS_486: *dst = "i486"; break; default: *dst = "i386"; } } struct sysentvec linux_sysvec = { .sv_size = LINUX_SYS_MAXSYSCALL, .sv_table = linux_sysent, .sv_mask = 0, .sv_errsize = ELAST + 1, .sv_errtbl = bsd_to_linux_errno, .sv_transtrap = translate_traps, .sv_fixup = linux_fixup, .sv_sendsig = linux_sendsig, .sv_sigcode = &_binary_linux_locore_o_start, .sv_szsigcode = &linux_szsigcode, .sv_name = "Linux a.out", .sv_coredump = NULL, .sv_imgact_try = exec_linux_imgact_try, .sv_minsigstksz = LINUX_MINSIGSTKSZ, .sv_pagesize = PAGE_SIZE, .sv_minuser = VM_MIN_ADDRESS, .sv_maxuser = VM_MAXUSER_ADDRESS, .sv_usrstack = LINUX_USRSTACK, .sv_psstrings = PS_STRINGS, .sv_stackprot = VM_PROT_ALL, .sv_copyout_strings = exec_copyout_strings, .sv_setregs = exec_linux_setregs, .sv_fixlimit = NULL, .sv_maxssiz = NULL, .sv_flags = SV_ABI_LINUX | SV_AOUT | SV_IA32 | SV_ILP32, .sv_set_syscall_retval = cpu_set_syscall_retval, .sv_fetch_syscall_args = linux_fetch_syscall_args, .sv_syscallnames = NULL, .sv_shared_page_base = LINUX_SHAREDPAGE, .sv_shared_page_len = PAGE_SIZE, .sv_schedtail = linux_schedtail, .sv_thread_detach = linux_thread_detach, .sv_trap = NULL, }; INIT_SYSENTVEC(aout_sysvec, &linux_sysvec); struct sysentvec elf_linux_sysvec = { .sv_size = LINUX_SYS_MAXSYSCALL, .sv_table = linux_sysent, .sv_mask = 0, .sv_errsize = ELAST + 1, .sv_errtbl = bsd_to_linux_errno, .sv_transtrap = translate_traps, .sv_fixup = elf_linux_fixup, .sv_sendsig = linux_sendsig, .sv_sigcode = &_binary_linux_locore_o_start, .sv_szsigcode = &linux_szsigcode, .sv_name = "Linux ELF", .sv_coredump = elf32_coredump, .sv_imgact_try = exec_linux_imgact_try, .sv_minsigstksz = LINUX_MINSIGSTKSZ, .sv_pagesize = PAGE_SIZE, .sv_minuser = VM_MIN_ADDRESS, .sv_maxuser = VM_MAXUSER_ADDRESS, .sv_usrstack = LINUX_USRSTACK, .sv_psstrings = LINUX_PS_STRINGS, .sv_stackprot = VM_PROT_ALL, .sv_copyout_strings = linux_copyout_strings, .sv_setregs = exec_linux_setregs, .sv_fixlimit = NULL, .sv_maxssiz = NULL, .sv_flags = SV_ABI_LINUX | SV_IA32 | SV_ILP32 | SV_SHP, .sv_set_syscall_retval = cpu_set_syscall_retval, .sv_fetch_syscall_args = linux_fetch_syscall_args, .sv_syscallnames = NULL, .sv_shared_page_base = LINUX_SHAREDPAGE, .sv_shared_page_len = PAGE_SIZE, .sv_schedtail = linux_schedtail, .sv_thread_detach = linux_thread_detach, .sv_trap = NULL, }; static void linux_vdso_install(void *param) { linux_szsigcode = (&_binary_linux_locore_o_end - &_binary_linux_locore_o_start); if (linux_szsigcode > elf_linux_sysvec.sv_shared_page_len) panic("Linux invalid vdso size\n"); __elfN(linux_vdso_fixup)(&elf_linux_sysvec); linux_shared_page_obj = __elfN(linux_shared_page_init) (&linux_shared_page_mapping); __elfN(linux_vdso_reloc)(&elf_linux_sysvec); bcopy(elf_linux_sysvec.sv_sigcode, linux_shared_page_mapping, linux_szsigcode); elf_linux_sysvec.sv_shared_page_obj = linux_shared_page_obj; } SYSINIT(elf_linux_vdso_init, SI_SUB_EXEC, SI_ORDER_ANY, (sysinit_cfunc_t)linux_vdso_install, NULL); static void linux_vdso_deinstall(void *param) { __elfN(linux_shared_page_fini)(linux_shared_page_obj); }; SYSUNINIT(elf_linux_vdso_uninit, SI_SUB_EXEC, SI_ORDER_FIRST, (sysinit_cfunc_t)linux_vdso_deinstall, NULL); static char GNU_ABI_VENDOR[] = "GNU"; static int GNULINUX_ABI_DESC = 0; static boolean_t linux_trans_osrel(const Elf_Note *note, int32_t *osrel) { const Elf32_Word *desc; uintptr_t p; p = (uintptr_t)(note + 1); p += roundup2(note->n_namesz, sizeof(Elf32_Addr)); desc = (const Elf32_Word *)p; if (desc[0] != GNULINUX_ABI_DESC) return (FALSE); /* * For linux we encode osrel as follows (see linux_mib.c): * VVVMMMIII (version, major, minor), see linux_mib.c. */ *osrel = desc[1] * 1000000 + desc[2] * 1000 + desc[3]; return (TRUE); } static Elf_Brandnote linux_brandnote = { .hdr.n_namesz = sizeof(GNU_ABI_VENDOR), .hdr.n_descsz = 16, /* XXX at least 16 */ .hdr.n_type = 1, .vendor = GNU_ABI_VENDOR, .flags = BN_TRANSLATE_OSREL, .trans_osrel = linux_trans_osrel }; static Elf32_Brandinfo linux_brand = { .brand = ELFOSABI_LINUX, .machine = EM_386, .compat_3_brand = "Linux", .emul_path = "/compat/linux", .interp_path = "/lib/ld-linux.so.1", .sysvec = &elf_linux_sysvec, .interp_newpath = NULL, .brand_note = &linux_brandnote, .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE }; static Elf32_Brandinfo linux_glibc2brand = { .brand = ELFOSABI_LINUX, .machine = EM_386, .compat_3_brand = "Linux", .emul_path = "/compat/linux", .interp_path = "/lib/ld-linux.so.2", .sysvec = &elf_linux_sysvec, .interp_newpath = NULL, .brand_note = &linux_brandnote, .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE }; static Elf32_Brandinfo linux_muslbrand = { .brand = ELFOSABI_LINUX, .machine = EM_386, .compat_3_brand = "Linux", .emul_path = "/compat/linux", .interp_path = "/lib/ld-musl-i386.so.1", .sysvec = &elf_linux_sysvec, .interp_newpath = NULL, .brand_note = &linux_brandnote, .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE }; Elf32_Brandinfo *linux_brandlist[] = { &linux_brand, &linux_glibc2brand, &linux_muslbrand, NULL }; static int linux_elf_modevent(module_t mod, int type, void *data) { Elf32_Brandinfo **brandinfo; int error; struct linux_ioctl_handler **lihp; error = 0; switch(type) { case MOD_LOAD: for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL; ++brandinfo) if (elf32_insert_brand_entry(*brandinfo) < 0) error = EINVAL; if (error == 0) { SET_FOREACH(lihp, linux_ioctl_handler_set) linux_ioctl_register_handler(*lihp); LIST_INIT(&futex_list); mtx_init(&futex_mtx, "ftllk", NULL, MTX_DEF); linux_exit_tag = EVENTHANDLER_REGISTER(process_exit, linux_proc_exit, NULL, 1000); linux_exec_tag = EVENTHANDLER_REGISTER(process_exec, linux_proc_exec, NULL, 1000); linux_thread_dtor_tag = EVENTHANDLER_REGISTER(thread_dtor, linux_thread_dtor, NULL, EVENTHANDLER_PRI_ANY); linux_get_machine(&linux_kplatform); linux_szplatform = roundup(strlen(linux_kplatform) + 1, sizeof(char *)); linux_osd_jail_register(); stclohz = (stathz ? stathz : hz); if (bootverbose) printf("Linux ELF exec handler installed\n"); } else printf("cannot insert Linux ELF brand handler\n"); break; case MOD_UNLOAD: for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL; ++brandinfo) if (elf32_brand_inuse(*brandinfo)) error = EBUSY; if (error == 0) { for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL; ++brandinfo) if (elf32_remove_brand_entry(*brandinfo) < 0) error = EINVAL; } if (error == 0) { SET_FOREACH(lihp, linux_ioctl_handler_set) linux_ioctl_unregister_handler(*lihp); mtx_destroy(&futex_mtx); EVENTHANDLER_DEREGISTER(process_exit, linux_exit_tag); EVENTHANDLER_DEREGISTER(process_exec, linux_exec_tag); EVENTHANDLER_DEREGISTER(thread_dtor, linux_thread_dtor_tag); linux_osd_jail_deregister(); if (bootverbose) printf("Linux ELF exec handler removed\n"); } else printf("Could not deinstall ELF interpreter entry\n"); break; default: return (EOPNOTSUPP); } return (error); } static moduledata_t linux_elf_mod = { "linuxelf", linux_elf_modevent, 0 }; DECLARE_MODULE_TIED(linuxelf, linux_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY); FEATURE(linux, "Linux 32bit support"); Index: head/sys/i386/pci/pci_cfgreg.c =================================================================== --- head/sys/i386/pci/pci_cfgreg.c (revision 326259) +++ head/sys/i386/pci/pci_cfgreg.c (revision 326260) @@ -1,678 +1,680 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1997, Stefan Esser * Copyright (c) 2000, Michael Smith * Copyright (c) 2000, BSDi * Copyright (c) 2004, Scott Long * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define PRVERB(a) do { \ if (bootverbose) \ printf a ; \ } while(0) #define PCIE_CACHE 8 struct pcie_cfg_elem { TAILQ_ENTRY(pcie_cfg_elem) elem; vm_offset_t vapage; vm_paddr_t papage; }; enum { CFGMECH_NONE = 0, CFGMECH_1, CFGMECH_2, CFGMECH_PCIE, }; SYSCTL_DECL(_hw_pci); static TAILQ_HEAD(pcie_cfg_list, pcie_cfg_elem) pcie_list[MAXCPU]; static uint64_t pcie_base; static int pcie_minbus, pcie_maxbus; static uint32_t pcie_badslots; static int cfgmech; static int devmax; static struct mtx pcicfg_mtx; static int mcfg_enable = 1; SYSCTL_INT(_hw_pci, OID_AUTO, mcfg, CTLFLAG_RDTUN, &mcfg_enable, 0, "Enable support for PCI-e memory mapped config access"); static uint32_t pci_docfgregread(int bus, int slot, int func, int reg, int bytes); static int pcireg_cfgread(int bus, int slot, int func, int reg, int bytes); static void pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes); static int pcireg_cfgopen(void); static int pciereg_cfgread(int bus, unsigned slot, unsigned func, unsigned reg, unsigned bytes); static void pciereg_cfgwrite(int bus, unsigned slot, unsigned func, unsigned reg, int data, unsigned bytes); /* * Some BIOS writers seem to want to ignore the spec and put * 0 in the intline rather than 255 to indicate none. Some use * numbers in the range 128-254 to indicate something strange and * apparently undocumented anywhere. Assume these are completely bogus * and map them to 255, which means "none". */ static __inline int pci_i386_map_intline(int line) { if (line == 0 || line >= 128) return (PCI_INVALID_IRQ); return (line); } static u_int16_t pcibios_get_version(void) { struct bios_regs args; if (PCIbios.ventry == 0) { PRVERB(("pcibios: No call entry point\n")); return (0); } args.eax = PCIBIOS_BIOS_PRESENT; if (bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL))) { PRVERB(("pcibios: BIOS_PRESENT call failed\n")); return (0); } if (args.edx != 0x20494350) { PRVERB(("pcibios: BIOS_PRESENT didn't return 'PCI ' in edx\n")); return (0); } return (args.ebx & 0xffff); } /* * Initialise access to PCI configuration space */ int pci_cfgregopen(void) { static int opened = 0; uint64_t pciebar; u_int16_t vid, did; u_int16_t v; if (opened) return (1); if (cfgmech == CFGMECH_NONE && pcireg_cfgopen() == 0) return (0); v = pcibios_get_version(); if (v > 0) PRVERB(("pcibios: BIOS version %x.%02x\n", (v & 0xff00) >> 8, v & 0xff)); mtx_init(&pcicfg_mtx, "pcicfg", NULL, MTX_SPIN); opened = 1; /* $PIR requires PCI BIOS 2.10 or greater. */ if (v >= 0x0210) pci_pir_open(); if (cfgmech == CFGMECH_PCIE) return (1); /* * Grope around in the PCI config space to see if this is a * chipset that is capable of doing memory-mapped config cycles. * This also implies that it can do PCIe extended config cycles. */ /* Check for supported chipsets */ vid = pci_cfgregread(0, 0, 0, PCIR_VENDOR, 2); did = pci_cfgregread(0, 0, 0, PCIR_DEVICE, 2); switch (vid) { case 0x8086: switch (did) { case 0x3590: case 0x3592: /* Intel 7520 or 7320 */ pciebar = pci_cfgregread(0, 0, 0, 0xce, 2) << 16; pcie_cfgregopen(pciebar, 0, 255); break; case 0x2580: case 0x2584: case 0x2590: /* Intel 915, 925, or 915GM */ pciebar = pci_cfgregread(0, 0, 0, 0x48, 4); pcie_cfgregopen(pciebar, 0, 255); break; } } return(1); } static uint32_t pci_docfgregread(int bus, int slot, int func, int reg, int bytes) { if (cfgmech == CFGMECH_PCIE && (bus >= pcie_minbus && bus <= pcie_maxbus) && (bus != 0 || !(1 << slot & pcie_badslots))) return (pciereg_cfgread(bus, slot, func, reg, bytes)); else return (pcireg_cfgread(bus, slot, func, reg, bytes)); } /* * Read configuration space register */ u_int32_t pci_cfgregread(int bus, int slot, int func, int reg, int bytes) { uint32_t line; /* * Some BIOS writers seem to want to ignore the spec and put * 0 in the intline rather than 255 to indicate none. The rest of * the code uses 255 as an invalid IRQ. */ if (reg == PCIR_INTLINE && bytes == 1) { line = pci_docfgregread(bus, slot, func, PCIR_INTLINE, 1); return (pci_i386_map_intline(line)); } return (pci_docfgregread(bus, slot, func, reg, bytes)); } /* * Write configuration space register */ void pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes) { if (cfgmech == CFGMECH_PCIE && (bus >= pcie_minbus && bus <= pcie_maxbus) && (bus != 0 || !(1 << slot & pcie_badslots))) pciereg_cfgwrite(bus, slot, func, reg, data, bytes); else pcireg_cfgwrite(bus, slot, func, reg, data, bytes); } /* * Configuration space access using direct register operations */ /* enable configuration space accesses and return data port address */ static int pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes) { int dataport = 0; if (bus <= PCI_BUSMAX && slot < devmax && func <= PCI_FUNCMAX && (unsigned)reg <= PCI_REGMAX && bytes != 3 && (unsigned)bytes <= 4 && (reg & (bytes - 1)) == 0) { switch (cfgmech) { case CFGMECH_PCIE: case CFGMECH_1: outl(CONF1_ADDR_PORT, (1U << 31) | (bus << 16) | (slot << 11) | (func << 8) | (reg & ~0x03)); dataport = CONF1_DATA_PORT + (reg & 0x03); break; case CFGMECH_2: outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1)); outb(CONF2_FORWARD_PORT, bus); dataport = 0xc000 | (slot << 8) | reg; break; } } return (dataport); } /* disable configuration space accesses */ static void pci_cfgdisable(void) { switch (cfgmech) { case CFGMECH_PCIE: case CFGMECH_1: /* * Do nothing for the config mechanism 1 case. * Writing a 0 to the address port can apparently * confuse some bridges and cause spurious * access failures. */ break; case CFGMECH_2: outb(CONF2_ENABLE_PORT, 0); break; } } static int pcireg_cfgread(int bus, int slot, int func, int reg, int bytes) { int data = -1; int port; mtx_lock_spin(&pcicfg_mtx); port = pci_cfgenable(bus, slot, func, reg, bytes); if (port != 0) { switch (bytes) { case 1: data = inb(port); break; case 2: data = inw(port); break; case 4: data = inl(port); break; } pci_cfgdisable(); } mtx_unlock_spin(&pcicfg_mtx); return (data); } static void pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes) { int port; mtx_lock_spin(&pcicfg_mtx); port = pci_cfgenable(bus, slot, func, reg, bytes); if (port != 0) { switch (bytes) { case 1: outb(port, data); break; case 2: outw(port, data); break; case 4: outl(port, data); break; } pci_cfgdisable(); } mtx_unlock_spin(&pcicfg_mtx); } /* check whether the configuration mechanism has been correctly identified */ static int pci_cfgcheck(int maxdev) { uint32_t id, class; uint8_t header; uint8_t device; int port; if (bootverbose) printf("pci_cfgcheck:\tdevice "); for (device = 0; device < maxdev; device++) { if (bootverbose) printf("%d ", device); port = pci_cfgenable(0, device, 0, 0, 4); id = inl(port); if (id == 0 || id == 0xffffffff) continue; port = pci_cfgenable(0, device, 0, 8, 4); class = inl(port) >> 8; if (bootverbose) printf("[class=%06x] ", class); if (class == 0 || (class & 0xf870ff) != 0) continue; port = pci_cfgenable(0, device, 0, 14, 1); header = inb(port); if (bootverbose) printf("[hdr=%02x] ", header); if ((header & 0x7e) != 0) continue; if (bootverbose) printf("is there (id=%08x)\n", id); pci_cfgdisable(); return (1); } if (bootverbose) printf("-- nothing found\n"); pci_cfgdisable(); return (0); } static int pcireg_cfgopen(void) { uint32_t mode1res, oldval1; uint8_t mode2res, oldval2; /* Check for type #1 first. */ oldval1 = inl(CONF1_ADDR_PORT); if (bootverbose) { printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08x\n", oldval1); } cfgmech = CFGMECH_1; devmax = 32; outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK); DELAY(1); mode1res = inl(CONF1_ADDR_PORT); outl(CONF1_ADDR_PORT, oldval1); if (bootverbose) printf("pci_open(1a):\tmode1res=0x%08x (0x%08lx)\n", mode1res, CONF1_ENABLE_CHK); if (mode1res) { if (pci_cfgcheck(32)) return (cfgmech); } outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1); mode1res = inl(CONF1_ADDR_PORT); outl(CONF1_ADDR_PORT, oldval1); if (bootverbose) printf("pci_open(1b):\tmode1res=0x%08x (0x%08lx)\n", mode1res, CONF1_ENABLE_CHK1); if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) { if (pci_cfgcheck(32)) return (cfgmech); } /* Type #1 didn't work, so try type #2. */ oldval2 = inb(CONF2_ENABLE_PORT); if (bootverbose) { printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n", oldval2); } if ((oldval2 & 0xf0) == 0) { cfgmech = CFGMECH_2; devmax = 16; outb(CONF2_ENABLE_PORT, CONF2_ENABLE_CHK); mode2res = inb(CONF2_ENABLE_PORT); outb(CONF2_ENABLE_PORT, oldval2); if (bootverbose) printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n", mode2res, CONF2_ENABLE_CHK); if (mode2res == CONF2_ENABLE_RES) { if (bootverbose) printf("pci_open(2a):\tnow trying mechanism 2\n"); if (pci_cfgcheck(16)) return (cfgmech); } } /* Nothing worked, so punt. */ cfgmech = CFGMECH_NONE; devmax = 0; return (cfgmech); } int pcie_cfgregopen(uint64_t base, uint8_t minbus, uint8_t maxbus) { struct pcie_cfg_list *pcielist; struct pcie_cfg_elem *pcie_array, *elem; #ifdef SMP struct pcpu *pc; #endif vm_offset_t va; uint32_t val1, val2; int i, slot; if (!mcfg_enable) return (0); if (minbus != 0) return (0); #ifndef PAE if (base >= 0x100000000) { if (bootverbose) printf( "PCI: Memory Mapped PCI configuration area base 0x%jx too high\n", (uintmax_t)base); return (0); } #endif if (bootverbose) printf("PCIe: Memory Mapped configuration base @ 0x%jx\n", (uintmax_t)base); #ifdef SMP STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) #endif { pcie_array = malloc(sizeof(struct pcie_cfg_elem) * PCIE_CACHE, M_DEVBUF, M_NOWAIT); if (pcie_array == NULL) return (0); va = kva_alloc(PCIE_CACHE * PAGE_SIZE); if (va == 0) { free(pcie_array, M_DEVBUF); return (0); } #ifdef SMP pcielist = &pcie_list[pc->pc_cpuid]; #else pcielist = &pcie_list[0]; #endif TAILQ_INIT(pcielist); for (i = 0; i < PCIE_CACHE; i++) { elem = &pcie_array[i]; elem->vapage = va + (i * PAGE_SIZE); elem->papage = 0; TAILQ_INSERT_HEAD(pcielist, elem, elem); } } pcie_base = base; pcie_minbus = minbus; pcie_maxbus = maxbus; cfgmech = CFGMECH_PCIE; devmax = 32; /* * On some AMD systems, some of the devices on bus 0 are * inaccessible using memory-mapped PCI config access. Walk * bus 0 looking for such devices. For these devices, we will * fall back to using type 1 config access instead. */ if (pci_cfgregopen() != 0) { for (slot = 0; slot <= PCI_SLOTMAX; slot++) { val1 = pcireg_cfgread(0, slot, 0, 0, 4); if (val1 == 0xffffffff) continue; val2 = pciereg_cfgread(0, slot, 0, 0, 4); if (val2 != val1) pcie_badslots |= (1 << slot); } } return (1); } #define PCIE_PADDR(base, reg, bus, slot, func) \ ((base) + \ ((((bus) & 0xff) << 20) | \ (((slot) & 0x1f) << 15) | \ (((func) & 0x7) << 12) | \ ((reg) & 0xfff))) static __inline vm_offset_t pciereg_findaddr(int bus, unsigned slot, unsigned func, unsigned reg) { struct pcie_cfg_list *pcielist; struct pcie_cfg_elem *elem; vm_paddr_t pa, papage; pa = PCIE_PADDR(pcie_base, reg, bus, slot, func); papage = pa & ~PAGE_MASK; /* * Find an element in the cache that matches the physical page desired, * or create a new mapping from the least recently used element. * A very simple LRU algorithm is used here, does it need to be more * efficient? */ pcielist = &pcie_list[PCPU_GET(cpuid)]; TAILQ_FOREACH(elem, pcielist, elem) { if (elem->papage == papage) break; } if (elem == NULL) { elem = TAILQ_LAST(pcielist, pcie_cfg_list); if (elem->papage != 0) { pmap_kremove(elem->vapage); invlpg(elem->vapage); } pmap_kenter(elem->vapage, papage); elem->papage = papage; } if (elem != TAILQ_FIRST(pcielist)) { TAILQ_REMOVE(pcielist, elem, elem); TAILQ_INSERT_HEAD(pcielist, elem, elem); } return (elem->vapage | (pa & PAGE_MASK)); } /* * AMD BIOS And Kernel Developer's Guides for CPU families starting with 10h * have a requirement that all accesses to the memory mapped PCI configuration * space are done using AX class of registers. * Since other vendors do not currently have any contradicting requirements * the AMD access pattern is applied universally. */ static int pciereg_cfgread(int bus, unsigned slot, unsigned func, unsigned reg, unsigned bytes) { vm_offset_t va; int data = -1; if (bus < pcie_minbus || bus > pcie_maxbus || slot > PCI_SLOTMAX || func > PCI_FUNCMAX || reg > PCIE_REGMAX) return (-1); critical_enter(); va = pciereg_findaddr(bus, slot, func, reg); switch (bytes) { case 4: __asm("movl %1, %0" : "=a" (data) : "m" (*(volatile uint32_t *)va)); break; case 2: __asm("movzwl %1, %0" : "=a" (data) : "m" (*(volatile uint16_t *)va)); break; case 1: __asm("movzbl %1, %0" : "=a" (data) : "m" (*(volatile uint8_t *)va)); break; } critical_exit(); return (data); } static void pciereg_cfgwrite(int bus, unsigned slot, unsigned func, unsigned reg, int data, unsigned bytes) { vm_offset_t va; if (bus < pcie_minbus || bus > pcie_maxbus || slot > PCI_SLOTMAX || func > PCI_FUNCMAX || reg > PCIE_REGMAX) return; critical_enter(); va = pciereg_findaddr(bus, slot, func, reg); switch (bytes) { case 4: __asm("movl %1, %0" : "=m" (*(volatile uint32_t *)va) : "a" (data)); break; case 2: __asm("movw %1, %0" : "=m" (*(volatile uint16_t *)va) : "a" ((uint16_t)data)); break; case 1: __asm("movb %1, %0" : "=m" (*(volatile uint8_t *)va) : "a" ((uint8_t)data)); break; } critical_exit(); } Index: head/sys/i386/pci/pci_pir.c =================================================================== --- head/sys/i386/pci/pci_pir.c (revision 326259) +++ head/sys/i386/pci/pci_pir.c (revision 326260) @@ -1,742 +1,744 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1997, Stefan Esser * Copyright (c) 2000, Michael Smith * Copyright (c) 2000, BSDi * Copyright (c) 2004, John Baldwin * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define NUM_ISA_INTERRUPTS 16 /* * A link device. Loosely based on the ACPI PCI link device. This doesn't * try to support priorities for different ISA interrupts. */ struct pci_link { TAILQ_ENTRY(pci_link) pl_links; uint8_t pl_id; uint8_t pl_irq; uint16_t pl_irqmask; int pl_references; int pl_routed; }; struct pci_link_lookup { struct pci_link **pci_link_ptr; int bus; int device; int pin; }; struct pci_dev_lookup { uint8_t link; int bus; int device; int pin; }; typedef void pir_entry_handler(struct PIR_entry *entry, struct PIR_intpin* intpin, void *arg); static void pci_print_irqmask(u_int16_t irqs); static int pci_pir_biosroute(int bus, int device, int func, int pin, int irq); static int pci_pir_choose_irq(struct pci_link *pci_link, int irqmask); static void pci_pir_create_links(struct PIR_entry *entry, struct PIR_intpin *intpin, void *arg); static void pci_pir_dump_links(void); static struct pci_link *pci_pir_find_link(uint8_t link_id); static void pci_pir_find_link_handler(struct PIR_entry *entry, struct PIR_intpin *intpin, void *arg); static void pci_pir_initial_irqs(struct PIR_entry *entry, struct PIR_intpin *intpin, void *arg); static void pci_pir_parse(void); static uint8_t pci_pir_search_irq(int bus, int device, int pin); static int pci_pir_valid_irq(struct pci_link *pci_link, int irq); static void pci_pir_walk_table(pir_entry_handler *handler, void *arg); static MALLOC_DEFINE(M_PIR, "$PIR", "$PIR structures"); static struct PIR_table *pci_route_table; static device_t pir_device; static int pci_route_count, pir_bios_irqs, pir_parsed; static TAILQ_HEAD(, pci_link) pci_links; static int pir_interrupt_weight[NUM_ISA_INTERRUPTS]; /* sysctl vars */ SYSCTL_DECL(_hw_pci); /* XXX this likely should live in a header file */ /* IRQs 3, 4, 5, 6, 7, 9, 10, 11, 12, 14, 15 */ #define PCI_IRQ_OVERRIDE_MASK 0xdef8 static uint32_t pci_irq_override_mask = PCI_IRQ_OVERRIDE_MASK; SYSCTL_INT(_hw_pci, OID_AUTO, irq_override_mask, CTLFLAG_RDTUN, &pci_irq_override_mask, PCI_IRQ_OVERRIDE_MASK, "Mask of allowed irqs to try to route when it has no good clue about\n" "which irqs it should use."); /* * Look for the interrupt routing table. * * We use PCI BIOS's PIR table if it's available. $PIR is the standard way * to do this. Sadly, some machines are not standards conforming and have * _PIR instead. We shrug and cope by looking for both. */ void pci_pir_open(void) { struct PIR_table *pt; uint32_t sigaddr; int i; uint8_t ck, *cv; /* Don't try if we've already found a table. */ if (pci_route_table != NULL) return; /* Look for $PIR and then _PIR. */ sigaddr = bios_sigsearch(0, "$PIR", 4, 16, 0); if (sigaddr == 0) sigaddr = bios_sigsearch(0, "_PIR", 4, 16, 0); if (sigaddr == 0) return; /* If we found something, check the checksum and length. */ /* XXX - Use pmap_mapdev()? */ pt = (struct PIR_table *)(uintptr_t)BIOS_PADDRTOVADDR(sigaddr); if (pt->pt_header.ph_length <= sizeof(struct PIR_header)) return; for (cv = (u_int8_t *)pt, ck = 0, i = 0; i < (pt->pt_header.ph_length); i++) ck += cv[i]; if (ck != 0) return; /* Ok, we've got a valid table. */ pci_route_table = pt; pci_route_count = (pt->pt_header.ph_length - sizeof(struct PIR_header)) / sizeof(struct PIR_entry); } /* * Find the pci_link structure for a given link ID. */ static struct pci_link * pci_pir_find_link(uint8_t link_id) { struct pci_link *pci_link; TAILQ_FOREACH(pci_link, &pci_links, pl_links) { if (pci_link->pl_id == link_id) return (pci_link); } return (NULL); } /* * Find the link device associated with a PCI device in the table. */ static void pci_pir_find_link_handler(struct PIR_entry *entry, struct PIR_intpin *intpin, void *arg) { struct pci_link_lookup *lookup; lookup = (struct pci_link_lookup *)arg; if (entry->pe_bus == lookup->bus && entry->pe_device == lookup->device && intpin - entry->pe_intpin == lookup->pin) *lookup->pci_link_ptr = pci_pir_find_link(intpin->link); } /* * Check to see if a possible IRQ setting is valid. */ static int pci_pir_valid_irq(struct pci_link *pci_link, int irq) { if (!PCI_INTERRUPT_VALID(irq)) return (0); return (pci_link->pl_irqmask & (1 << irq)); } /* * Walk the $PIR executing the worker function for each valid intpin entry * in the table. The handler is passed a pointer to both the entry and * the intpin in the entry. */ static void pci_pir_walk_table(pir_entry_handler *handler, void *arg) { struct PIR_entry *entry; struct PIR_intpin *intpin; int i, pin; entry = &pci_route_table->pt_entry[0]; for (i = 0; i < pci_route_count; i++, entry++) { intpin = &entry->pe_intpin[0]; for (pin = 0; pin < 4; pin++, intpin++) if (intpin->link != 0) handler(entry, intpin, arg); } } static void pci_pir_create_links(struct PIR_entry *entry, struct PIR_intpin *intpin, void *arg) { struct pci_link *pci_link; pci_link = pci_pir_find_link(intpin->link); if (pci_link != NULL) { pci_link->pl_references++; if (intpin->irqs != pci_link->pl_irqmask) { if (bootverbose) printf( "$PIR: Entry %d.%d.INT%c has different mask for link %#x, merging\n", entry->pe_bus, entry->pe_device, (intpin - entry->pe_intpin) + 'A', pci_link->pl_id); pci_link->pl_irqmask &= intpin->irqs; } } else { pci_link = malloc(sizeof(struct pci_link), M_PIR, M_WAITOK); pci_link->pl_id = intpin->link; pci_link->pl_irqmask = intpin->irqs; pci_link->pl_irq = PCI_INVALID_IRQ; pci_link->pl_references = 1; pci_link->pl_routed = 0; TAILQ_INSERT_TAIL(&pci_links, pci_link, pl_links); } } /* * Look to see if any of the function on the PCI device at bus/device have * an interrupt routed to intpin 'pin' by the BIOS. */ static uint8_t pci_pir_search_irq(int bus, int device, int pin) { uint32_t value; uint8_t func, maxfunc; /* See if we have a valid device at function 0. */ value = pci_cfgregread(bus, device, 0, PCIR_HDRTYPE, 1); if ((value & PCIM_HDRTYPE) > PCI_MAXHDRTYPE) return (PCI_INVALID_IRQ); if (value & PCIM_MFDEV) maxfunc = PCI_FUNCMAX; else maxfunc = 0; /* Scan all possible functions at this device. */ for (func = 0; func <= maxfunc; func++) { value = pci_cfgregread(bus, device, func, PCIR_DEVVENDOR, 4); if (value == 0xffffffff) continue; value = pci_cfgregread(bus, device, func, PCIR_INTPIN, 1); /* * See if it uses the pin in question. Note that the passed * in pin uses 0 for A, .. 3 for D whereas the intpin * register uses 0 for no interrupt, 1 for A, .. 4 for D. */ if (value != pin + 1) continue; value = pci_cfgregread(bus, device, func, PCIR_INTLINE, 1); if (bootverbose) printf( "$PIR: Found matching pin for %d.%d.INT%c at func %d: %d\n", bus, device, pin + 'A', func, value); if (value != PCI_INVALID_IRQ) return (value); } return (PCI_INVALID_IRQ); } /* * Try to initialize IRQ based on this device's IRQ. */ static void pci_pir_initial_irqs(struct PIR_entry *entry, struct PIR_intpin *intpin, void *arg) { struct pci_link *pci_link; uint8_t irq, pin; pin = intpin - entry->pe_intpin; pci_link = pci_pir_find_link(intpin->link); irq = pci_pir_search_irq(entry->pe_bus, entry->pe_device, pin); if (irq == PCI_INVALID_IRQ || irq == pci_link->pl_irq) return; /* Don't trust any BIOS IRQs greater than 15. */ if (irq >= NUM_ISA_INTERRUPTS) { printf( "$PIR: Ignoring invalid BIOS IRQ %d from %d.%d.INT%c for link %#x\n", irq, entry->pe_bus, entry->pe_device, pin + 'A', pci_link->pl_id); return; } /* * If we don't have an IRQ for this link yet, then we trust the * BIOS, even if it seems invalid from the $PIR entries. */ if (pci_link->pl_irq == PCI_INVALID_IRQ) { if (!pci_pir_valid_irq(pci_link, irq)) printf( "$PIR: Using invalid BIOS IRQ %d from %d.%d.INT%c for link %#x\n", irq, entry->pe_bus, entry->pe_device, pin + 'A', pci_link->pl_id); pci_link->pl_irq = irq; pci_link->pl_routed = 1; return; } /* * We have an IRQ and it doesn't match the current IRQ for this * link. If the new IRQ is invalid, then warn about it and ignore * it. If the old IRQ is invalid and the new IRQ is valid, then * prefer the new IRQ instead. If both IRQs are valid, then just * use the first one. Note that if we ever get into this situation * we are having to guess which setting the BIOS actually routed. * Perhaps we should just give up instead. */ if (!pci_pir_valid_irq(pci_link, irq)) { printf( "$PIR: BIOS IRQ %d for %d.%d.INT%c is not valid for link %#x\n", irq, entry->pe_bus, entry->pe_device, pin + 'A', pci_link->pl_id); } else if (!pci_pir_valid_irq(pci_link, pci_link->pl_irq)) { printf( "$PIR: Preferring valid BIOS IRQ %d from %d.%d.INT%c for link %#x to IRQ %d\n", irq, entry->pe_bus, entry->pe_device, pin + 'A', pci_link->pl_id, pci_link->pl_irq); pci_link->pl_irq = irq; pci_link->pl_routed = 1; } else printf( "$PIR: BIOS IRQ %d for %d.%d.INT%c does not match link %#x irq %d\n", irq, entry->pe_bus, entry->pe_device, pin + 'A', pci_link->pl_id, pci_link->pl_irq); } /* * Parse $PIR to enumerate link devices and attempt to determine their * initial state. This could perhaps be cleaner if we had drivers for the * various interrupt routers as they could read the initial IRQ for each * link. */ static void pci_pir_parse(void) { char tunable_buffer[64]; struct pci_link *pci_link; int i, irq; /* Only parse once. */ if (pir_parsed) return; pir_parsed = 1; /* Enumerate link devices. */ TAILQ_INIT(&pci_links); pci_pir_walk_table(pci_pir_create_links, NULL); if (bootverbose) { printf("$PIR: Links after initial probe:\n"); pci_pir_dump_links(); } /* * Check to see if the BIOS has already routed any of the links by * checking each device connected to each link to see if it has a * valid IRQ. */ pci_pir_walk_table(pci_pir_initial_irqs, NULL); if (bootverbose) { printf("$PIR: Links after initial IRQ discovery:\n"); pci_pir_dump_links(); } /* * Allow the user to override the IRQ for a given link device. We * allow invalid IRQs to be specified but warn about them. An IRQ * of 255 or 0 clears any preset IRQ. */ i = 0; TAILQ_FOREACH(pci_link, &pci_links, pl_links) { snprintf(tunable_buffer, sizeof(tunable_buffer), "hw.pci.link.%#x.irq", pci_link->pl_id); if (getenv_int(tunable_buffer, &irq) == 0) continue; if (irq == 0) irq = PCI_INVALID_IRQ; if (irq != PCI_INVALID_IRQ && !pci_pir_valid_irq(pci_link, irq) && bootverbose) printf( "$PIR: Warning, IRQ %d for link %#x is not listed as valid\n", irq, pci_link->pl_id); pci_link->pl_routed = 0; pci_link->pl_irq = irq; i = 1; } if (bootverbose && i) { printf("$PIR: Links after tunable overrides:\n"); pci_pir_dump_links(); } /* * Build initial interrupt weights as well as bitmap of "known-good" * IRQs that the BIOS has already used for PCI link devices. */ TAILQ_FOREACH(pci_link, &pci_links, pl_links) { if (!PCI_INTERRUPT_VALID(pci_link->pl_irq)) continue; pir_bios_irqs |= 1 << pci_link->pl_irq; pir_interrupt_weight[pci_link->pl_irq] += pci_link->pl_references; } if (bootverbose) { printf("$PIR: IRQs used by BIOS: "); pci_print_irqmask(pir_bios_irqs); printf("\n"); printf("$PIR: Interrupt Weights:\n[ "); for (i = 0; i < NUM_ISA_INTERRUPTS; i++) printf(" %3d", i); printf(" ]\n[ "); for (i = 0; i < NUM_ISA_INTERRUPTS; i++) printf(" %3d", pir_interrupt_weight[i]); printf(" ]\n"); } } /* * Use the PCI BIOS to route an interrupt for a given device. * * Input: * AX = PCIBIOS_ROUTE_INTERRUPT * BH = bus * BL = device [7:3] / function [2:0] * CH = IRQ * CL = Interrupt Pin (0x0A = A, ... 0x0D = D) */ static int pci_pir_biosroute(int bus, int device, int func, int pin, int irq) { struct bios_regs args; args.eax = PCIBIOS_ROUTE_INTERRUPT; args.ebx = (bus << 8) | (device << 3) | func; args.ecx = (irq << 8) | (0xa + pin); return (bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL))); } /* * Route a PCI interrupt using a link device from the $PIR. */ int pci_pir_route_interrupt(int bus, int device, int func, int pin) { struct pci_link_lookup lookup; struct pci_link *pci_link; int error, irq; if (pci_route_table == NULL) return (PCI_INVALID_IRQ); /* Lookup link device for this PCI device/pin. */ pci_link = NULL; lookup.bus = bus; lookup.device = device; lookup.pin = pin - 1; lookup.pci_link_ptr = &pci_link; pci_pir_walk_table(pci_pir_find_link_handler, &lookup); if (pci_link == NULL) { printf("$PIR: No matching entry for %d.%d.INT%c\n", bus, device, pin - 1 + 'A'); return (PCI_INVALID_IRQ); } /* * Pick a new interrupt if we don't have one already. We look * for an interrupt from several different sets. First, if * this link only has one valid IRQ, use that. Second, we * check the set of PCI only interrupts from the $PIR. Third, * we check the set of known-good interrupts that the BIOS has * already used. Lastly, we check the "all possible valid * IRQs" set. */ if (!PCI_INTERRUPT_VALID(pci_link->pl_irq)) { if (pci_link->pl_irqmask != 0 && powerof2(pci_link->pl_irqmask)) irq = ffs(pci_link->pl_irqmask) - 1; else irq = pci_pir_choose_irq(pci_link, pci_route_table->pt_header.ph_pci_irqs); if (!PCI_INTERRUPT_VALID(irq)) irq = pci_pir_choose_irq(pci_link, pir_bios_irqs); if (!PCI_INTERRUPT_VALID(irq)) irq = pci_pir_choose_irq(pci_link, pci_irq_override_mask); if (!PCI_INTERRUPT_VALID(irq)) { if (bootverbose) printf( "$PIR: Failed to route interrupt for %d:%d INT%c\n", bus, device, pin - 1 + 'A'); return (PCI_INVALID_IRQ); } pci_link->pl_irq = irq; } /* Ask the BIOS to route this IRQ if we haven't done so already. */ if (!pci_link->pl_routed) { error = pci_pir_biosroute(bus, device, func, pin - 1, pci_link->pl_irq); /* Ignore errors when routing a unique interrupt. */ if (error && !powerof2(pci_link->pl_irqmask)) { printf("$PIR: ROUTE_INTERRUPT failed.\n"); return (PCI_INVALID_IRQ); } pci_link->pl_routed = 1; /* Ensure the interrupt is set to level/low trigger. */ KASSERT(pir_device != NULL, ("missing pir device")); BUS_CONFIG_INTR(pir_device, pci_link->pl_irq, INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW); } if (bootverbose) printf("$PIR: %d:%d INT%c routed to irq %d\n", bus, device, pin - 1 + 'A', pci_link->pl_irq); return (pci_link->pl_irq); } /* * Try to pick an interrupt for the specified link from the interrupts * set in the mask. */ static int pci_pir_choose_irq(struct pci_link *pci_link, int irqmask) { int i, irq, realmask; /* XXX: Need to have a #define of known bad IRQs to also mask out? */ realmask = pci_link->pl_irqmask & irqmask; if (realmask == 0) return (PCI_INVALID_IRQ); /* Find IRQ with lowest weight. */ irq = PCI_INVALID_IRQ; for (i = 0; i < NUM_ISA_INTERRUPTS; i++) { if (!(realmask & 1 << i)) continue; if (irq == PCI_INVALID_IRQ || pir_interrupt_weight[i] < pir_interrupt_weight[irq]) irq = i; } if (bootverbose && PCI_INTERRUPT_VALID(irq)) { printf("$PIR: Found IRQ %d for link %#x from ", irq, pci_link->pl_id); pci_print_irqmask(realmask); printf("\n"); } return (irq); } static void pci_print_irqmask(u_int16_t irqs) { int i, first; if (irqs == 0) { printf("none"); return; } first = 1; for (i = 0; i < 16; i++, irqs >>= 1) if (irqs & 1) { if (!first) printf(" "); else first = 0; printf("%d", i); } } /* * Display link devices. */ static void pci_pir_dump_links(void) { struct pci_link *pci_link; printf("Link IRQ Rtd Ref IRQs\n"); TAILQ_FOREACH(pci_link, &pci_links, pl_links) { printf("%#4x %3d %c %3d ", pci_link->pl_id, pci_link->pl_irq, pci_link->pl_routed ? 'Y' : 'N', pci_link->pl_references); pci_print_irqmask(pci_link->pl_irqmask); printf("\n"); } } /* * See if any interrupts for a given PCI bus are routed in the PIR. Don't * even bother looking if the BIOS doesn't support routing anyways. If we * are probing a PCI-PCI bridge, then require_parse will be true and we should * only succeed if a host-PCI bridge has already attached and parsed the PIR. */ int pci_pir_probe(int bus, int require_parse) { int i; if (pci_route_table == NULL || (require_parse && !pir_parsed)) return (0); for (i = 0; i < pci_route_count; i++) if (pci_route_table->pt_entry[i].pe_bus == bus) return (1); return (0); } /* * The driver for the new-bus psuedo device pir0 for the $PIR table. */ static int pir_probe(device_t dev) { char buf[64]; snprintf(buf, sizeof(buf), "PCI Interrupt Routing Table: %d Entries", pci_route_count); device_set_desc_copy(dev, buf); return (0); } static int pir_attach(device_t dev) { pci_pir_parse(); KASSERT(pir_device == NULL, ("Multiple pir devices")); pir_device = dev; return (0); } static void pir_resume_find_device(struct PIR_entry *entry, struct PIR_intpin *intpin, void *arg) { struct pci_dev_lookup *pd; pd = (struct pci_dev_lookup *)arg; if (intpin->link != pd->link || pd->bus != -1) return; pd->bus = entry->pe_bus; pd->device = entry->pe_device; pd->pin = intpin - entry->pe_intpin; } static int pir_resume(device_t dev) { struct pci_dev_lookup pd; struct pci_link *pci_link; int error; /* Ask the BIOS to re-route each link that was already routed. */ TAILQ_FOREACH(pci_link, &pci_links, pl_links) { if (!PCI_INTERRUPT_VALID(pci_link->pl_irq)) { KASSERT(!pci_link->pl_routed, ("link %#x is routed but has invalid PCI IRQ", pci_link->pl_id)); continue; } if (pci_link->pl_routed) { pd.bus = -1; pd.link = pci_link->pl_id; pci_pir_walk_table(pir_resume_find_device, &pd); KASSERT(pd.bus != -1, ("did not find matching entry for link %#x in the $PIR table", pci_link->pl_id)); if (bootverbose) device_printf(dev, "Using %d.%d.INT%c to route link %#x to IRQ %d\n", pd.bus, pd.device, pd.pin + 'A', pci_link->pl_id, pci_link->pl_irq); error = pci_pir_biosroute(pd.bus, pd.device, 0, pd.pin, pci_link->pl_irq); if (error) device_printf(dev, "ROUTE_INTERRUPT on resume for link %#x failed.\n", pci_link->pl_id); } } return (0); } static device_method_t pir_methods[] = { /* Device interface */ DEVMETHOD(device_probe, pir_probe), DEVMETHOD(device_attach, pir_attach), DEVMETHOD(device_resume, pir_resume), { 0, 0 } }; static driver_t pir_driver = { "pir", pir_methods, 1, }; static devclass_t pir_devclass; DRIVER_MODULE(pir, legacy, pir_driver, pir_devclass, 0, 0);