diff options
author | Dag-Erling Smørgrav <des@FreeBSD.org> | 2009-09-25 22:45:59 +0000 |
---|---|---|
committer | Dag-Erling Smørgrav <des@FreeBSD.org> | 2009-09-25 22:45:59 +0000 |
commit | 0fbc5fbedf3eeaac0575646816c8f9cf0e937861 (patch) | |
tree | 394fcfe01b613c0b5b5edbfc414a17c73481ad5d /sys | |
parent | 0bb2e5de607991a2c9d5ed9e27956ddd8d60fb35 (diff) | |
parent | ebb2b0f28aff46e1e7413fe370156c4a4a1d0874 (diff) | |
download | src-0fbc5fbedf3eeaac0575646816c8f9cf0e937861.tar.gz src-0fbc5fbedf3eeaac0575646816c8f9cf0e937861.zip |
Sync with head
Notes
Notes:
svn path=/projects/quota64/; revision=197507
Diffstat (limited to 'sys')
131 files changed, 3192 insertions, 1995 deletions
diff --git a/sys/amd64/acpica/acpi_machdep.c b/sys/amd64/acpica/acpi_machdep.c index b902c12e2055..0d866e898328 100644 --- a/sys/amd64/acpica/acpi_machdep.c +++ b/sys/amd64/acpica/acpi_machdep.c @@ -32,8 +32,12 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/module.h> #include <sys/sysctl.h> +#include <vm/vm.h> +#include <vm/pmap.h> #include <contrib/dev/acpica/include/acpi.h> +#include <contrib/dev/acpica/include/accommon.h> +#include <contrib/dev/acpica/include/actables.h> #include <dev/acpica/acpivar.h> @@ -100,6 +104,246 @@ acpi_cpu_c1() } /* + * Support for mapping ACPI tables during early boot. Currently this + * uses the crashdump map to map each table. However, the crashdump + * map is created in pmap_bootstrap() right after the direct map, so + * we should be able to just use pmap_mapbios() here instead. + * + * 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 = roundup(length + off, PAGE_SIZE); + 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 = roundup(length + off, PAGE_SIZE); + 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); + table_unmap(table, length); + return (NULL); + } + 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 diff --git a/sys/amd64/acpica/madt.c b/sys/amd64/acpica/madt.c index b27f8e4b26b9..a4096820bea3 100644 --- a/sys/amd64/acpica/madt.c +++ b/sys/amd64/acpica/madt.c @@ -36,27 +36,19 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/smp.h> - #include <vm/vm.h> -#include <vm/vm_param.h> #include <vm/pmap.h> #include <machine/apicreg.h> -#include <machine/frame.h> #include <machine/intr_machdep.h> #include <machine/apicvar.h> -#include <machine/md_var.h> -#include <machine/specialreg.h> #include <contrib/dev/acpica/include/acpi.h> -#include <contrib/dev/acpica/include/accommon.h> #include <contrib/dev/acpica/include/actables.h> #include <dev/acpica/acpivar.h> #include <dev/pci/pcivar.h> -typedef void madt_entry_handler(ACPI_SUBTABLE_HEADER *entry, void *arg); - /* These two arrays are indexed by APIC IDs. */ struct ioapic_info { void *io_apic; @@ -79,8 +71,6 @@ static enum intr_polarity interrupt_polarity(UINT16 IntiFlags, UINT8 Source); static enum intr_trigger interrupt_trigger(UINT16 IntiFlags, UINT8 Source); static int madt_find_cpu(u_int acpi_id, u_int *apic_id); static int madt_find_interrupt(int intr, void **apic, u_int *pin); -static void *madt_map(vm_paddr_t pa, int offset, vm_offset_t length); -static void *madt_map_table(vm_paddr_t pa, int offset, const char *sig); static void madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg); static void madt_parse_interrupt_override( ACPI_MADT_INTERRUPT_OVERRIDE *intr); @@ -92,13 +82,10 @@ static int madt_probe(void); static int madt_probe_cpus(void); static void madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg __unused); -static int madt_probe_table(vm_paddr_t address); static void madt_register(void *dummy); static int madt_setup_local(void); static int madt_setup_io(void); -static void madt_unmap(void *data, vm_offset_t length); -static void madt_unmap_table(void *table); -static void madt_walk_table(madt_entry_handler *handler, void *arg); +static void madt_walk_table(acpi_subtable_handler *handler, void *arg); static struct apic_enumerator madt_enumerator = { "MADT", @@ -109,224 +96,30 @@ static struct apic_enumerator madt_enumerator = { }; /* - * Code to abuse the crashdump map to map in the tables for the early - * probe. We cheat and make 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. We have to use 2 pages for the table headers - * in case a header spans a page boundary. The offset is in pages; - * the length is in bytes. - */ -static void * -madt_map(vm_paddr_t pa, int offset, vm_offset_t length) -{ - vm_offset_t va, off; - void *data; - - off = pa & PAGE_MASK; - length = roundup(length + off, PAGE_SIZE); - 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); -} - -static void -madt_unmap(void *data, vm_offset_t length) -{ - vm_offset_t va, off; - - va = (vm_offset_t)data; - off = va & PAGE_MASK; - length = roundup(length + off, PAGE_SIZE); - va &= ~PAGE_MASK; - while (length > 0) { - pmap_kremove(va); - invlpg(va); - va += PAGE_SIZE; - length -= PAGE_SIZE; - } -} - -static void * -madt_map_table(vm_paddr_t pa, int offset, const char *sig) -{ - ACPI_TABLE_HEADER *header; - vm_offset_t length; - void *table; - - header = madt_map(pa, offset, sizeof(ACPI_TABLE_HEADER)); - if (strncmp(header->Signature, sig, ACPI_NAME_SIZE) != 0) { - madt_unmap(header, sizeof(ACPI_TABLE_HEADER)); - return (NULL); - } - length = header->Length; - madt_unmap(header, sizeof(ACPI_TABLE_HEADER)); - table = madt_map(pa, offset, length); - if (ACPI_FAILURE(AcpiTbChecksum(table, length))) { - if (bootverbose) - printf("MADT: Failed checksum for table %s\n", sig); - madt_unmap(table, length); - return (NULL); - } - return (table); -} - -static void -madt_unmap_table(void *table) -{ - ACPI_TABLE_HEADER *header; - - header = (ACPI_TABLE_HEADER *)table; - madt_unmap(table, header->Length); -} - -/* * Look for an ACPI Multiple APIC Description Table ("APIC") */ static int madt_probe(void) { - ACPI_PHYSICAL_ADDRESS rsdp_ptr; - ACPI_TABLE_RSDP *rsdp; - ACPI_TABLE_RSDT *rsdt; - ACPI_TABLE_XSDT *xsdt; - int i, count; - if (resource_disabled("acpi", 0)) + madt_physaddr = acpi_find_table(ACPI_SIG_MADT); + if (madt_physaddr == 0) return (ENXIO); - - /* - * 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 (ENXIO); - rsdp = pmap_mapbios(rsdp_ptr, sizeof(ACPI_TABLE_RSDP)); - if (rsdp == NULL) { - if (bootverbose) - printf("MADT: Failed to map RSDP\n"); - return (ENXIO); - } - - /* - * For ACPI >= 2.0, use the XSDT if it is available. - * Otherwise, use the RSDT. We map the XSDT or RSDT at page 1 - * in the crashdump area. Page 0 is used to map in the - * headers of candidate ACPI tables. - */ - 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("MADT: RSDP failed extended checksum\n"); - return (ENXIO); - } - xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 2, - ACPI_SIG_XSDT); - if (xsdt == NULL) { - if (bootverbose) - printf("MADT: Failed to map XSDT\n"); - return (ENXIO); - } - count = (xsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) / - sizeof(UINT64); - for (i = 0; i < count; i++) - if (madt_probe_table(xsdt->TableOffsetEntry[i])) - break; - madt_unmap_table(xsdt); - } else { - rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 2, - ACPI_SIG_RSDT); - if (rsdt == NULL) { - if (bootverbose) - printf("MADT: Failed to map RSDT\n"); - return (ENXIO); - } - count = (rsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) / - sizeof(UINT32); - for (i = 0; i < count; i++) - if (madt_probe_table(rsdt->TableOffsetEntry[i])) - break; - madt_unmap_table(rsdt); - } - pmap_unmapbios((vm_offset_t)rsdp, sizeof(ACPI_TABLE_RSDP)); - if (madt_physaddr == 0) { - if (bootverbose) - printf("MADT: No MADT table found\n"); - return (ENXIO); - } - if (bootverbose) - printf("MADT: Found table at 0x%jx\n", - (uintmax_t)madt_physaddr); - - /* - * Verify that we can map the full table and that its checksum is - * correct, etc. - */ - madt = madt_map_table(madt_physaddr, 0, ACPI_SIG_MADT); - if (madt == NULL) - return (ENXIO); - madt_unmap_table(madt); - madt = NULL; - return (0); } /* - * See if a given ACPI table is the MADT. - */ -static int -madt_probe_table(vm_paddr_t address) -{ - ACPI_TABLE_HEADER *table; - - table = madt_map(address, 0, sizeof(ACPI_TABLE_HEADER)); - if (table == NULL) { - if (bootverbose) - printf("MADT: 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, ACPI_SIG_MADT, ACPI_NAME_SIZE) != 0) { - madt_unmap(table, sizeof(ACPI_TABLE_HEADER)); - return (0); - } - madt_physaddr = address; - madt_length = table->Length; - madt_unmap(table, sizeof(ACPI_TABLE_HEADER)); - return (1); -} - -/* * Run through the MP table enumerating CPUs. */ static int madt_probe_cpus(void) { - madt = madt_map_table(madt_physaddr, 0, ACPI_SIG_MADT); + madt = acpi_map_table(madt_physaddr, ACPI_SIG_MADT); + madt_length = madt->Header.Length; KASSERT(madt != NULL, ("Unable to re-map MADT")); madt_walk_table(madt_probe_cpus_handler, NULL); - madt_unmap_table(madt); + acpi_unmap_table(madt); madt = NULL; return (0); } @@ -417,17 +210,11 @@ SYSINIT(madt_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST, * Call the handler routine for each entry in the MADT table. */ static void -madt_walk_table(madt_entry_handler *handler, void *arg) +madt_walk_table(acpi_subtable_handler *handler, void *arg) { - ACPI_SUBTABLE_HEADER *entry; - u_char *p, *end; - - end = (u_char *)(madt) + madt->Header.Length; - for (p = (u_char *)(madt + 1); p < end; ) { - entry = (ACPI_SUBTABLE_HEADER *)p; - handler(entry, arg); - p += entry->Length; - } + + acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length, + handler, arg); } static void diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index 0bfd7ada6535..95db5d2d6053 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -1192,6 +1192,77 @@ isa_irq_pending(void) u_int basemem; +static int +add_smap_entry(struct bios_smap *smap, vm_paddr_t *physmap, int *physmap_idxp) +{ + int i, insert_idx, physmap_idx; + + physmap_idx = *physmap_idxp; + + if (boothowto & RB_VERBOSE) + printf("SMAP type=%02x base=%016lx len=%016lx\n", + smap->type, smap->base, smap->length); + + if (smap->type != SMAP_TYPE_MEMORY) + return (1); + + if (smap->length == 0) + return (0); + + /* + * Find insertion point while checking for overlap. Start off by + * assuming the new entry will be added to the end. + */ + insert_idx = physmap_idx + 2; + for (i = 0; i <= physmap_idx; i += 2) { + if (smap->base < physmap[i + 1]) { + if (smap->base + smap->length <= physmap[i]) { + insert_idx = i; + break; + } + if (boothowto & RB_VERBOSE) + printf( + "Overlapping memory regions, ignoring second region\n"); + return (1); + } + } + + /* See if we can prepend to the next entry. */ + if (insert_idx <= physmap_idx && + smap->base + smap->length == physmap[insert_idx]) { + physmap[insert_idx] = smap->base; + return (1); + } + + /* See if we can append to the previous entry. */ + if (insert_idx > 0 && smap->base == physmap[insert_idx - 1]) { + physmap[insert_idx - 1] += smap->length; + return (1); + } + + physmap_idx += 2; + *physmap_idxp = physmap_idx; + if (physmap_idx == PHYSMAP_SIZE) { + printf( + "Too many segments in the physical address map, giving up\n"); + return (0); + } + + /* + * Move the last 'N' entries down to make room for the new + * entry if needed. + */ + for (i = physmap_idx; i > insert_idx; i -= 2) { + physmap[i] = physmap[i - 2]; + physmap[i + 1] = physmap[i - 1]; + } + + /* Insert the new entry. */ + physmap[insert_idx] = smap->base; + physmap[insert_idx + 1] = smap->base + smap->length; + return (1); +} + /* * Populate the (physmap) array with base/bound pairs describing the * available physical memory in the system, then test this memory and @@ -1235,40 +1306,9 @@ getmemsize(caddr_t kmdp, u_int64_t first) smapsize = *((u_int32_t *)smapbase - 1); smapend = (struct bios_smap *)((uintptr_t)smapbase + smapsize); - for (smap = smapbase; smap < smapend; smap++) { - if (boothowto & RB_VERBOSE) - printf("SMAP type=%02x base=%016lx len=%016lx\n", - smap->type, smap->base, smap->length); - - if (smap->type != SMAP_TYPE_MEMORY) - continue; - - if (smap->length == 0) - continue; - - for (i = 0; i <= physmap_idx; i += 2) { - if (smap->base < physmap[i + 1]) { - if (boothowto & RB_VERBOSE) - printf( - "Overlapping or non-monotonic memory region, ignoring second region\n"); - continue; - } - } - - if (smap->base == physmap[physmap_idx + 1]) { - physmap[physmap_idx + 1] += smap->length; - continue; - } - - physmap_idx += 2; - if (physmap_idx == PHYSMAP_SIZE) { - printf( - "Too many segments in the physical address map, giving up\n"); + for (smap = smapbase; smap < smapend; smap++) + if (!add_smap_entry(smap, physmap, &physmap_idx)) break; - } - physmap[physmap_idx] = smap->base; - physmap[physmap_idx + 1] = smap->base + smap->length; - } /* * Find the 'base memory' segment for SMP diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c index 4febfb3b8866..1f377651e43c 100644 --- a/sys/amd64/amd64/pmap.c +++ b/sys/amd64/amd64/pmap.c @@ -701,6 +701,11 @@ pmap_init(void) * Are large page mappings enabled? */ TUNABLE_INT_FETCH("vm.pmap.pg_ps_enabled", &pg_ps_enabled); + if (pg_ps_enabled) { + KASSERT(MAXPAGESIZES > 1 && pagesizes[1] == 0, + ("pmap_init: can't assign to pagesizes[1]")); + pagesizes[1] = NBPDR; + } /* * Calculate the size of the pv head table for superpages. diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c index 65f761eaa4a6..c97985d44947 100644 --- a/sys/amd64/amd64/trap.c +++ b/sys/amd64/amd64/trap.c @@ -253,6 +253,11 @@ trap(struct trapframe *frame) } #endif + if (type == T_RESERVED) { + trap_fatal(frame, 0); + goto out; + } + #ifdef HWPMC_HOOKS /* * CPU PMCs interrupt using an NMI. If the PMC module is @@ -500,8 +505,11 @@ trap(struct trapframe *frame) * XXX this should be fatal unless the kernel has * registered such use. */ - fpudna(); printf("fpudna in kernel mode!\n"); +#ifdef KDB + kdb_backtrace(); +#endif + fpudna(); goto out; case T_STKFLT: /* stack fault */ diff --git a/sys/amd64/conf/NOTES b/sys/amd64/conf/NOTES index ada5e32c0bbc..f3619cfa717b 100644 --- a/sys/amd64/conf/NOTES +++ b/sys/amd64/conf/NOTES @@ -154,12 +154,17 @@ options AGP_DEBUG ##################################################################### # HARDWARE DEVICE CONFIGURATION -# To include support for VGA VESA video modes (depends on X86EMU) +# To include support for VGA VESA video modes options VESA # Turn on extra debugging checks and output for VESA support. options VESA_DEBUG +device dpms # DPMS suspend & resume via VESA BIOS + +# x86 real mode BIOS emulator, required by atkbdc/dpms/vesa +options X86BIOS + # # Optional devices: # @@ -219,6 +224,9 @@ options VGA_WIDTH90 # support 90 column modes # Debugging. options VGA_DEBUG +# Linear framebuffer driver for S3 VESA 1.2 cards. Works on top of VESA. +device s3pci + # 3Dfx Voodoo Graphics, Voodoo II /dev/3dfx CDEV support. This will create # the /dev/3dfx0 device to work with glide implementations. This should get # linked to /dev/3dfx and /dev/voodoo. Note that this is not the same as diff --git a/sys/amd64/include/acpica_machdep.h b/sys/amd64/include/acpica_machdep.h index 76cc69ef5681..9943af793f8f 100644 --- a/sys/amd64/include/acpica_machdep.h +++ b/sys/amd64/include/acpica_machdep.h @@ -77,5 +77,8 @@ extern int acpi_release_global_lock(uint32_t *lock); void acpi_SetDefaultIntrModel(int model); void acpi_cpu_c1(void); +void *acpi_map_table(vm_paddr_t pa, const char *sig); +void acpi_unmap_table(void *table); +vm_paddr_t acpi_find_table(const char *sig); #endif /* __ACPICA_MACHDEP_H__ */ diff --git a/sys/amd64/include/param.h b/sys/amd64/include/param.h index f9b6bd81d6fe..3ede6014adcc 100644 --- a/sys/amd64/include/param.h +++ b/sys/amd64/include/param.h @@ -108,6 +108,8 @@ #define NBPML4 (1ul<<PML4SHIFT)/* bytes/page map lev4 table */ #define PML4MASK (NBPML4-1) +#define MAXPAGESIZES 3 /* maximum number of supported page sizes */ + #define IOPAGES 2 /* pages of i/o permission bitmap */ #ifndef KSTACK_PAGES diff --git a/sys/amd64/pci/pci_cfgreg.c b/sys/amd64/pci/pci_cfgreg.c index be9e40488ee0..3e29a585be33 100644 --- a/sys/amd64/pci/pci_cfgreg.c +++ b/sys/amd64/pci/pci_cfgreg.c @@ -181,9 +181,9 @@ pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes) { int dataport = 0; - if (bus <= PCI_BUSMAX && slot < 32 && func <= PCI_FUNCMAX && - reg <= PCI_REGMAX && bytes != 3 && (unsigned) bytes <= 4 && - (reg & (bytes - 1)) == 0) { + if (bus <= PCI_BUSMAX && slot <= PCI_SLOTMAX && func <= PCI_FUNCMAX && + (unsigned)reg <= PCI_REGMAX && bytes != 3 && + (unsigned)bytes <= 4 && (reg & (bytes - 1)) == 0) { outl(CONF1_ADDR_PORT, (1 << 31) | (bus << 16) | (slot << 11) | (func << 8) | (reg & ~0x03)); dataport = CONF1_DATA_PORT + (reg & 0x03); @@ -281,7 +281,7 @@ pcie_cfgregopen(uint64_t base, uint8_t minbus, uint8_t maxbus) * fall back to using type 1 config access instead. */ if (pci_cfgregopen() != 0) { - for (slot = 0; slot < 32; slot++) { + for (slot = 0; slot <= PCI_SLOTMAX; slot++) { val1 = pcireg_cfgread(0, slot, 0, 0, 4); if (val1 == 0xffffffff) continue; @@ -309,8 +309,8 @@ pciereg_cfgread(int bus, unsigned slot, unsigned func, unsigned reg, volatile vm_offset_t va; int data = -1; - if (bus < pcie_minbus || bus > pcie_maxbus || slot >= 32 || - func > PCI_FUNCMAX || reg >= 0x1000) + if (bus < pcie_minbus || bus > pcie_maxbus || slot > PCI_SLOTMAX || + func > PCI_FUNCMAX || reg > PCIE_REGMAX) return (-1); va = PCIE_VADDR(pcie_base, reg, bus, slot, func); @@ -336,8 +336,8 @@ pciereg_cfgwrite(int bus, unsigned slot, unsigned func, unsigned reg, int data, { volatile vm_offset_t va; - if (bus < pcie_minbus || bus > pcie_maxbus || slot >= 32 || - func > PCI_FUNCMAX || reg >= 0x1000) + if (bus < pcie_minbus || bus > pcie_maxbus || slot > PCI_SLOTMAX || + func > PCI_FUNCMAX || reg > PCIE_REGMAX) return; va = PCIE_VADDR(pcie_base, reg, bus, slot, func); diff --git a/sys/arm/include/param.h b/sys/arm/include/param.h index 2161103a52e7..1694bc43c5ed 100644 --- a/sys/arm/include/param.h +++ b/sys/arm/include/param.h @@ -92,6 +92,8 @@ #define NBPDR (1 << PDR_SHIFT) #define NPDEPG (1 << (32 - PDR_SHIFT)) +#define MAXPAGESIZES 1 /* maximum number of supported page sizes */ + #ifndef KSTACK_PAGES #define KSTACK_PAGES 2 #endif /* !KSTACK_PAGES */ diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c index c4e0b0412ce3..9137c55d1061 100644 --- a/sys/cam/cam_periph.c +++ b/sys/cam/cam_periph.c @@ -1034,8 +1034,13 @@ camperiphdone(struct cam_periph *periph, union ccb *done_ccb) cam_error_print(saved_ccb, CAM_ESF_ALL, CAM_EPF_ALL); #endif - xpt_done_ccb = TRUE; + } else { + saved_ccb->ccb_h.status &= + ~CAM_STATUS_MASK; + saved_ccb->ccb_h.status |= + CAM_AUTOSENSE_FAIL; } + xpt_done_ccb = TRUE; } } bcopy(done_ccb->ccb_h.saved_ccb_ptr, done_ccb, diff --git a/sys/cam/scsi/scsi_target.c b/sys/cam/scsi/scsi_target.c index 428c97b34fee..939e3f70189b 100644 --- a/sys/cam/scsi/scsi_target.c +++ b/sys/cam/scsi/scsi_target.c @@ -42,6 +42,9 @@ __FBSDID("$FreeBSD$"); #include <sys/mutex.h> #include <sys/devicestat.h> #include <sys/proc.h> +/* Includes to support callout */ +#include <sys/types.h> +#include <sys/systm.h> #include <cam/cam.h> #include <cam/cam_ccb.h> @@ -50,6 +53,7 @@ __FBSDID("$FreeBSD$"); #include <cam/cam_sim.h> #include <cam/scsi/scsi_targetio.h> + /* Transaction information attached to each CCB sent by the user */ struct targ_cmd_descr { struct cam_periph_map_info mapinfo; @@ -92,6 +96,8 @@ struct targ_softc { targ_state state; struct selinfo read_select; struct devstat device_stats; + struct callout destroy_dev_callout; + struct mtx destroy_mtx; }; static d_open_t targopen; @@ -154,6 +160,7 @@ static void abort_all_pending(struct targ_softc *softc); static void notify_user(struct targ_softc *softc); static int targcamstatus(cam_status status); static size_t targccblen(xpt_opcode func_code); +static void targdestroy(void *); static struct periph_driver targdriver = { @@ -211,10 +218,18 @@ targclose(struct cdev *dev, int flag, int fmt, struct thread *td) int error; softc = (struct targ_softc *)dev->si_drv1; - if ((softc->periph == NULL) || - (softc->state & TARG_STATE_LUN_ENABLED) == 0) { + mtx_init(&softc->destroy_mtx, "targ_destroy", "SCSI Target dev destroy", MTX_DEF); + callout_init_mtx(&softc->destroy_dev_callout, &softc->destroy_mtx, CALLOUT_RETURNUNLOCKED); + if (softc->periph == NULL) { +#if 0 destroy_dev(dev); free(softc, M_TARG); +#endif + printf("%s: destroying non-enabled target\n", __func__); + mtx_lock(&softc->destroy_mtx); + callout_reset(&softc->destroy_dev_callout, hz / 2, + (void *)targdestroy, (void *)dev); + mtx_unlock(&softc->destroy_mtx); return (0); } @@ -226,18 +241,23 @@ targclose(struct cdev *dev, int flag, int fmt, struct thread *td) cam_periph_acquire(periph); cam_periph_lock(periph); error = targdisable(softc); - if (error == CAM_REQ_CMP) { - dev->si_drv1 = 0; - if (softc->periph != NULL) { - cam_periph_invalidate(softc->periph); - softc->periph = NULL; - } - destroy_dev(dev); - free(softc, M_TARG); + if (softc->periph != NULL) { + cam_periph_invalidate(softc->periph); + softc->periph = NULL; } cam_periph_unlock(periph); cam_periph_release(periph); +#if 0 + destroy_dev(dev); + free(softc, M_TARG); +#endif + + printf("%s: close finished error(%d)\n", __func__, error); + mtx_lock(&softc->destroy_mtx); + callout_reset(&softc->destroy_dev_callout, hz / 2, + (void *)targdestroy, (void *)dev); + mtx_unlock(&softc->destroy_mtx); return (error); } @@ -821,7 +841,9 @@ targdone(struct cam_periph *periph, union ccb *done_ccb) case XPT_CONT_TARGET_IO: TAILQ_INSERT_TAIL(&softc->user_ccb_queue, &done_ccb->ccb_h, periph_links.tqe); + cam_periph_unlock(softc->periph); notify_user(softc); + cam_periph_lock(softc->periph); break; default: panic("targdone: impossible xpt opcode %#x", @@ -969,13 +991,19 @@ targgetccb(struct targ_softc *softc, xpt_opcode type, int priority) int ccb_len; ccb_len = targccblen(type); - ccb = malloc(ccb_len, M_TARG, M_WAITOK); + ccb = malloc(ccb_len, M_TARG, M_NOWAIT); CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("getccb %p\n", ccb)); - + if (ccb == NULL) { + return (ccb); + } xpt_setup_ccb(&ccb->ccb_h, softc->path, priority); ccb->ccb_h.func_code = type; ccb->ccb_h.cbfcnp = targdone; ccb->ccb_h.targ_descr = targgetdescr(softc); + if (ccb->ccb_h.targ_descr == NULL) { + free (ccb, M_TARG); + ccb = NULL; + } return (ccb); } @@ -1013,8 +1041,10 @@ targgetdescr(struct targ_softc *softc) struct targ_cmd_descr *descr; descr = malloc(sizeof(*descr), M_TARG, - M_WAITOK); - descr->mapinfo.num_bufs_used = 0; + M_NOWAIT); + if (descr) { + descr->mapinfo.num_bufs_used = 0; + } return (descr); } @@ -1094,8 +1124,11 @@ abort_all_pending(struct targ_softc *softc) /* If we aborted anything from the work queue, wakeup user. */ if (!TAILQ_EMPTY(&softc->user_ccb_queue) - || !TAILQ_EMPTY(&softc->abort_queue)) + || !TAILQ_EMPTY(&softc->abort_queue)) { + cam_periph_unlock(softc->periph); notify_user(softc); + cam_periph_lock(softc->periph); + } } /* Notify the user that data is ready */ @@ -1188,3 +1221,25 @@ targccblen(xpt_opcode func_code) return (len); } + +/* + * work around to destroy targ device + * outside of targclose + */ +static void +targdestroy(void *dev) +{ + struct cdev *device = (struct cdev *)dev; + struct targ_softc *softc = (struct targ_softc *)device->si_drv1; + +#if 0 + callout_stop(&softc->destroy_dev_callout); +#endif + + mtx_unlock(&softc->destroy_mtx); + mtx_destroy(&softc->destroy_mtx); + free(softc, M_TARG); + device->si_drv1 = 0; + destroy_dev(device); + printf("%s: destroyed dev\n", __func__); +} diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/fletcher.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/fletcher.c index edda3c9a9d3d..54247d724d49 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/fletcher.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/fletcher.c @@ -19,11 +19,111 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Fletcher Checksums + * ------------------ + * + * ZFS's 2nd and 4th order Fletcher checksums are defined by the following + * recurrence relations: + * + * a = a + f + * i i-1 i-1 + * + * b = b + a + * i i-1 i + * + * c = c + b (fletcher-4 only) + * i i-1 i + * + * d = d + c (fletcher-4 only) + * i i-1 i + * + * Where + * a_0 = b_0 = c_0 = d_0 = 0 + * and + * f_0 .. f_(n-1) are the input data. + * + * Using standard techniques, these translate into the following series: + * + * __n_ __n_ + * \ | \ | + * a = > f b = > i * f + * n /___| n - i n /___| n - i + * i = 1 i = 1 + * + * + * __n_ __n_ + * \ | i*(i+1) \ | i*(i+1)*(i+2) + * c = > ------- f d = > ------------- f + * n /___| 2 n - i n /___| 6 n - i + * i = 1 i = 1 + * + * For fletcher-2, the f_is are 64-bit, and [ab]_i are 64-bit accumulators. + * Since the additions are done mod (2^64), errors in the high bits may not + * be noticed. For this reason, fletcher-2 is deprecated. + * + * For fletcher-4, the f_is are 32-bit, and [abcd]_i are 64-bit accumulators. + * A conservative estimate of how big the buffer can get before we overflow + * can be estimated using f_i = 0xffffffff for all i: + * + * % bc + * f=2^32-1;d=0; for (i = 1; d<2^64; i++) { d += f*i*(i+1)*(i+2)/6 }; (i-1)*4 + * 2264 + * quit + * % + * + * So blocks of up to 2k will not overflow. Our largest block size is + * 128k, which has 32k 4-byte words, so we can compute the largest possible + * accumulators, then divide by 2^64 to figure the max amount of overflow: + * + * % bc + * a=b=c=d=0; f=2^32-1; for (i=1; i<=32*1024; i++) { a+=f; b+=a; c+=b; d+=c } + * a/2^64;b/2^64;c/2^64;d/2^64 + * 0 + * 0 + * 1365 + * 11186858 + * quit + * % + * + * So a and b cannot overflow. To make sure each bit of input has some + * effect on the contents of c and d, we can look at what the factors of + * the coefficients in the equations for c_n and d_n are. The number of 2s + * in the factors determines the lowest set bit in the multiplier. Running + * through the cases for n*(n+1)/2 reveals that the highest power of 2 is + * 2^14, and for n*(n+1)*(n+2)/6 it is 2^15. So while some data may overflow + * the 64-bit accumulators, every bit of every f_i effects every accumulator, + * even for 128k blocks. + * + * If we wanted to make a stronger version of fletcher4 (fletcher4c?), + * we could do our calculations mod (2^32 - 1) by adding in the carries + * periodically, and store the number of carries in the top 32-bits. + * + * -------------------- + * Checksum Performance + * -------------------- + * + * There are two interesting components to checksum performance: cached and + * uncached performance. With cached data, fletcher-2 is about four times + * faster than fletcher-4. With uncached data, the performance difference is + * negligible, since the cost of a cache fill dominates the processing time. + * Even though fletcher-4 is slower than fletcher-2, it is still a pretty + * efficient pass over the data. + * + * In normal operation, the data which is being checksummed is in a buffer + * which has been filled either by: + * + * 1. a compression step, which will be mostly cached, or + * 2. a bcopy() or copyin(), which will be uncached (because the + * copy is cache-bypassing). + * + * For both cached and uncached data, both fletcher checksums are much faster + * than sha-256, and slower than 'off', which doesn't touch the data at all. + */ #include <sys/types.h> #include <sys/sysmacros.h> diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h index bb1c9da6be9a..185f7d246361 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h @@ -255,6 +255,7 @@ VTOZ(vnode_t *vp) /* * ZFS_ENTER() is called on entry to each ZFS vnode and vfs operation. + * ZFS_ENTER_NOERROR() is called when we can't return EIO. * ZFS_EXIT() must be called before exitting the vop. * ZFS_VERIFY_ZP() verifies the znode is valid. */ @@ -267,6 +268,9 @@ VTOZ(vnode_t *vp) } \ } +#define ZFS_ENTER_NOERROR(zfsvfs) \ + rrw_enter(&(zfsvfs)->z_teardown_lock, RW_READER, FTAG) + #define ZFS_EXIT(zfsvfs) rrw_exit(&(zfsvfs)->z_teardown_lock, FTAG) #define ZFS_VERIFY_ZP(zp) \ diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h index 6331567498b5..fbc8c454bdf3 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h @@ -76,7 +76,7 @@ enum zio_checksum { ZIO_CHECKSUM_FUNCTIONS }; -#define ZIO_CHECKSUM_ON_VALUE ZIO_CHECKSUM_FLETCHER_2 +#define ZIO_CHECKSUM_ON_VALUE ZIO_CHECKSUM_FLETCHER_4 #define ZIO_CHECKSUM_DEFAULT ZIO_CHECKSUM_ON enum zio_compress { diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_acl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_acl.c index d46627346a11..a43d85c709ea 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_acl.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_acl.c @@ -1841,7 +1841,7 @@ zfs_perm_init(znode_t *zp, znode_t *parent, int flag, fgid = zfs_fuid_create_cred(zfsvfs, ZFS_GROUP, tx, cr, fuidp); #ifdef __FreeBSD__ - gid = parent->z_phys->zp_gid; + gid = fgid = parent->z_phys->zp_gid; #else gid = crgetgid(cr); #endif diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c index 185d84b4c803..b9a4b2fd8938 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c @@ -864,7 +864,7 @@ zfs_root(vfs_t *vfsp, int flags, vnode_t **vpp) znode_t *rootzp; int error; - ZFS_ENTER(zfsvfs); + ZFS_ENTER_NOERROR(zfsvfs); error = zfs_zget(zfsvfs, zfsvfs->z_root, &rootzp); if (error == 0) { @@ -898,6 +898,9 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting) * 'z_parent' is self referential for non-snapshots. */ (void) dnlc_purge_vfsp(zfsvfs->z_parent->z_vfs, 0); +#ifdef FREEBSD_NAMECACHE + cache_purgevfs(zfsvfs->z_parent->z_vfs); +#endif } /* @@ -1027,6 +1030,17 @@ zfs_umount(vfs_t *vfsp, int fflag) ASSERT(zfsvfs->z_ctldir == NULL); } + if (fflag & MS_FORCE) { + /* + * Mark file system as unmounted before calling + * vflush(FORCECLOSE). This way we ensure no future vnops + * will be called and risk operating on DOOMED vnodes. + */ + rrw_enter(&zfsvfs->z_teardown_lock, RW_WRITER, FTAG); + zfsvfs->z_unmounted = B_TRUE; + rrw_exit(&zfsvfs->z_teardown_lock, FTAG); + } + /* * Flush all the files. */ diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c index 0753fe9c24be..a761c81da8b7 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c @@ -4860,7 +4860,7 @@ zfs_freebsd_getacl(ap) vsecattr_t vsecattr; if (ap->a_type != ACL_TYPE_NFS4) - return (EOPNOTSUPP); + return (EINVAL); vsecattr.vsa_mask = VSA_ACE | VSA_ACECNT; if (error = zfs_getsecattr(ap->a_vp, &vsecattr, 0, ap->a_cred, NULL)) @@ -4889,7 +4889,7 @@ zfs_freebsd_setacl(ap) aclent_t *aaclp; if (ap->a_type != ACL_TYPE_NFS4) - return (EOPNOTSUPP); + return (EINVAL); if (ap->a_aclp->acl_cnt < 1 || ap->a_aclp->acl_cnt > MAX_ACL_ENTRIES) return (EINVAL); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c index 082198f63d42..c43a8500818a 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c @@ -890,17 +890,25 @@ again: if (zp->z_unlinked) { err = ENOENT; } else { - if ((vp = ZTOV(zp)) != NULL) { - VI_LOCK(vp); + int dying = 0; + + vp = ZTOV(zp); + if (vp == NULL) + dying = 1; + else { + VN_HOLD(vp); if ((vp->v_iflag & VI_DOOMED) != 0) { - VI_UNLOCK(vp); - vp = NULL; - } else - VI_UNLOCK(vp); + dying = 1; + /* + * Don't VN_RELE() vnode here, because + * it can call vn_lock() which creates + * LOR between vnode lock and znode + * lock. We will VN_RELE() the vnode + * after droping znode lock. + */ + } } - if (vp != NULL) - VN_HOLD(vp); - else { + if (dying) { if (first) { ZFS_LOG(1, "dying znode detected (zp=%p)", zp); first = 0; @@ -912,6 +920,8 @@ again: dmu_buf_rele(db, NULL); mutex_exit(&zp->z_lock); ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); + if (vp != NULL) + VN_RELE(vp); tsleep(zp, 0, "zcollide", 1); goto again; } diff --git a/sys/compat/x86bios/x86bios.c b/sys/compat/x86bios/x86bios.c new file mode 100644 index 000000000000..b187ae9093fc --- /dev/null +++ b/sys/compat/x86bios/x86bios.c @@ -0,0 +1,196 @@ +/*- + * Written by paradox <ddkprog@yahoo.com> + * Public domain. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include "opt_x86bios.h" + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/module.h> +#include <sys/mutex.h> + +#include <vm/vm.h> +#include <vm/pmap.h> + +#include <machine/cpufunc.h> + +#include <contrib/x86emu/x86emu.h> +#include <contrib/x86emu/x86emu_regs.h> +#include <compat/x86bios/x86bios.h> + +u_char *pbiosMem = NULL; +static u_char *pbiosStack = NULL; + +int busySegMap[5]; + +static struct x86emu x86bios_emu; + +static struct mtx x86bios_lock; + +static uint8_t +x86bios_emu_inb(struct x86emu *emu, uint16_t port) +{ + + if (port == 0xb2) /* APM scratch register */ + return (0); + if (port >= 0x80 && port < 0x88) /* POST status register */ + return (0); + return (inb(port)); +} + +static uint16_t +x86bios_emu_inw(struct x86emu *emu, uint16_t port) +{ + + if (port >= 0x80 && port < 0x88) /* POST status register */ + return (0); + return (inw(port)); +} + +static uint32_t +x86bios_emu_inl(struct x86emu *emu, uint16_t port) +{ + + if (port >= 0x80 && port < 0x88) /* POST status register */ + return (0); + return (inl(port)); +} + +static void +x86bios_emu_outb(struct x86emu *emu, uint16_t port, uint8_t val) +{ + + if (port == 0xb2) /* APM scratch register */ + return; + if (port >= 0x80 && port < 0x88) /* POST status register */ + return; + outb(port, val); +} + +static void +x86bios_emu_outw(struct x86emu *emu, uint16_t port, uint16_t val) +{ + + if (port >= 0x80 && port < 0x88) /* POST status register */ + return; + outw(port, val); +} + +static void +x86bios_emu_outl(struct x86emu *emu, uint16_t port, uint32_t val) +{ + + if (port >= 0x80 && port < 0x88) /* POST status register */ + return; + outl(port, val); +} + +void +x86bios_intr(struct x86regs *regs, int intno) +{ + + if (intno < 0 || intno > 255) + return; + + if (bootverbose) + printf("Calling int 0x%x (ax=0x%04x bx=0x%04x " + "cx=0x%04x dx=0x%04x es=0x%04x di=0x%04x)\n", + intno, regs->R_AX, regs->R_BX, regs->R_CX, + regs->R_DX, regs->R_ES, regs->R_DI); + + mtx_lock_spin(&x86bios_lock); + + memcpy(&x86bios_emu.x86, regs, sizeof(*regs)); + x86emu_exec_intr(&x86bios_emu, intno); + memcpy(regs, &x86bios_emu.x86, sizeof(*regs)); + + mtx_unlock_spin(&x86bios_lock); + + if (bootverbose) + printf("Exiting int 0x%x (ax=0x%04x bx=0x%04x " + "cx=0x%04x dx=0x%04x es=0x%04x di=0x%04x)\n", + intno, regs->R_AX, regs->R_BX, regs->R_CX, + regs->R_DX, regs->R_ES, regs->R_DI); +} + +void * +x86bios_offset(uint32_t offs) +{ + + return (pbiosMem + offs); +} + +static void +x86bios_init(void *arg __unused) +{ + int offs; + + mtx_init(&x86bios_lock, "x86bios lock", NULL, MTX_SPIN); + + /* Can pbiosMem be NULL here? */ + pbiosMem = pmap_mapbios(0x0, MAPPED_MEMORY_SIZE); + + memset(&x86bios_emu, 0, sizeof(x86bios_emu)); + x86emu_init_default(&x86bios_emu); + + x86bios_emu.emu_inb = x86bios_emu_inb; + x86bios_emu.emu_inw = x86bios_emu_inw; + x86bios_emu.emu_inl = x86bios_emu_inl; + x86bios_emu.emu_outb = x86bios_emu_outb; + x86bios_emu.emu_outw = x86bios_emu_outw; + x86bios_emu.emu_outl = x86bios_emu_outl; + + x86bios_emu.mem_base = (char *)pbiosMem; + x86bios_emu.mem_size = MAPPED_MEMORY_SIZE; + + memset(busySegMap, 0, sizeof(busySegMap)); + + pbiosStack = x86bios_alloc(1, &offs); +} + +static void +x86bios_uninit(void *arg __unused) +{ + + x86bios_free(pbiosStack, 1); + + if (pbiosMem) + pmap_unmapdev((vm_offset_t)pbiosMem, + MAPPED_MEMORY_SIZE); + + mtx_destroy(&x86bios_lock); +} + +static int +x86bios_modevent(module_t mod __unused, int type, void *data __unused) +{ + int err = 0; + + switch (type) { + case MOD_LOAD: + x86bios_init(NULL); + break; + case MOD_UNLOAD: + x86bios_uninit(NULL); + break; + default: + err = ENOTSUP; + break; + } + + return (err); +} + +static moduledata_t x86bios_mod = { + "x86bios", + x86bios_modevent, + NULL, +}; + +DECLARE_MODULE(x86bios, x86bios_mod, SI_SUB_CPU, SI_ORDER_ANY); +MODULE_VERSION(x86bios, 1); diff --git a/sys/compat/x86bios/x86bios.h b/sys/compat/x86bios/x86bios.h new file mode 100644 index 000000000000..35cbbce8cfaa --- /dev/null +++ b/sys/compat/x86bios/x86bios.h @@ -0,0 +1,134 @@ +/*- + * Written by paradox <ddkprog@yahoo.com> + * Public domain. + * + * x86 registers were borrowed from x86emu.h x86emu_regs.h + * for compatability. + * + * $FreeBSD$ + */ + +#ifndef _X86BIOS_H_ +#define _X86BIOS_H_ + +#include <sys/types.h> +#include <sys/endian.h> +#include <sys/systm.h> + +#ifdef __BIG_ENDIAN__ + +struct x86_register32 { + uint32_t e_reg; +}; + +struct x86_register16 { + uint16_t filler0; + uint16_t x_reg; +}; + +struct x86_register8 { + uint8_t filler0, filler1; + uint8_t h_reg, l_reg; +}; + +#else /* !__BIG_ENDIAN__ */ + +struct x86_register32 { + uint32_t e_reg; +}; + +struct x86_register16 { + uint16_t x_reg; +}; + +struct x86_register8 { + uint8_t l_reg, h_reg; +}; + +#endif /* __BIG_ENDIAN__ */ + +union x86_register { + struct x86_register32 I32_reg; + struct x86_register16 I16_reg; + struct x86_register8 I8_reg; +}; + +struct x86regs { + uint16_t padding; /* CS is unused. */ + uint16_t register_ds; + uint16_t register_es; + uint16_t register_fs; + uint16_t register_gs; + uint16_t register_ss; + uint32_t register_flags; + union x86_register register_a; + union x86_register register_b; + union x86_register register_c; + union x86_register register_d; + + union x86_register register_sp; + union x86_register register_bp; + union x86_register register_si; + union x86_register register_di; +}; + +typedef struct x86regs x86regs_t; + +/* 8 bit registers */ +#define R_AH register_a.I8_reg.h_reg +#define R_AL register_a.I8_reg.l_reg +#define R_BH register_b.I8_reg.h_reg +#define R_BL register_b.I8_reg.l_reg +#define R_CH register_c.I8_reg.h_reg +#define R_CL register_c.I8_reg.l_reg +#define R_DH register_d.I8_reg.h_reg +#define R_DL register_d.I8_reg.l_reg + +/* 16 bit registers */ +#define R_AX register_a.I16_reg.x_reg +#define R_BX register_b.I16_reg.x_reg +#define R_CX register_c.I16_reg.x_reg +#define R_DX register_d.I16_reg.x_reg + +/* 32 bit extended registers */ +#define R_EAX register_a.I32_reg.e_reg +#define R_EBX register_b.I32_reg.e_reg +#define R_ECX register_c.I32_reg.e_reg +#define R_EDX register_d.I32_reg.e_reg + +/* special registers */ +#define R_SP register_sp.I16_reg.x_reg +#define R_BP register_bp.I16_reg.x_reg +#define R_SI register_si.I16_reg.x_reg +#define R_DI register_di.I16_reg.x_reg +#define R_FLG register_flags + +/* special registers */ +#define R_ESP register_sp.I32_reg.e_reg +#define R_EBP register_bp.I32_reg.e_reg +#define R_ESI register_si.I32_reg.e_reg +#define R_EDI register_di.I32_reg.e_reg +#define R_EFLG register_flags + +/* segment registers */ +#define R_DS register_ds +#define R_SS register_ss +#define R_ES register_es +#define R_FS register_fs +#define R_GS register_gs + +#define SEG_ADDR(x) (((x) >> 4) & 0x00F000) +#define SEG_OFF(x) ((x) & 0x0FFFF) +#define FARP(x) ((le32toh(x) & 0xffff) + ((le32toh(x) >> 12) & 0xffff00)) + +#define MAPPED_MEMORY_SIZE (1024 * 1024) +#define PAGE_RESERV (4096 * 5) + +__BEGIN_DECLS +void *x86bios_alloc(int count, int *segs); +void x86bios_free(void *pbuf, int count); +void x86bios_intr(struct x86regs *regs, int intno); +void *x86bios_offset(uint32_t offs); +__END_DECLS + +#endif /* !_X86BIOS_H_ */ diff --git a/sys/compat/x86bios/x86bios_alloc.c b/sys/compat/x86bios/x86bios_alloc.c new file mode 100644 index 000000000000..0a364e7e4e0a --- /dev/null +++ b/sys/compat/x86bios/x86bios_alloc.c @@ -0,0 +1,81 @@ +/*- + * Copyright (C) 1999 Egbert Eich + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of the authors not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The authors makes no + * representations about the suitability of this software for any purpose. + * It is provided "as is" without express or implied warranty. + * + * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * xserver/hw/xfree86/int10/generic.c + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> + +#include <compat/x86bios/x86bios.h> + +extern u_char *pbiosMem; +extern int busySegMap[5]; + +void * +x86bios_alloc(int count, int *segs) +{ + int i; + int j; + + /* find the free segblock of page */ + for (i = 0; i < (PAGE_RESERV - count); i++) + { + if (busySegMap[i] == 0) + { + /* find the capacity of segblock */ + for (j = i; j < (i + count); j++) + { + if (busySegMap[j] == 1) + break; + } + + if (j == (i + count)) + break; + i += count; + } + } + + if (i == (PAGE_RESERV - count)) + return NULL; + + /* make the segblock is used */ + for (j = i; j < (i + count); j++) + busySegMap[i] = 1; + + *segs = i * 4096; + + return (pbiosMem + *segs); +} + +void +x86bios_free(void *pbuf, int count) +{ + int i; + int busySeg; + + busySeg = ((u_char *)pbuf - pbiosMem) / 4096; + + for (i = busySeg; i < (busySeg + count); i++) + busySegMap[i] = 0; +} diff --git a/sys/conf/NOTES b/sys/conf/NOTES index 69a80a5ea577..1cba42f46437 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -2757,5 +2757,3 @@ options AAC_DEBUG # Debugging levels: options BROOKTREE_ALLOC_PAGES=(217*4+1) options MAXFILES=999 -# x86 real mode emulator -options X86EMU diff --git a/sys/conf/files b/sys/conf/files index c232c52edc16..b31249fc3dfe 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1792,6 +1792,7 @@ fs/procfs/procfs_ioctl.c optional procfs fs/procfs/procfs_map.c optional procfs fs/procfs/procfs_mem.c optional procfs fs/procfs/procfs_note.c optional procfs +fs/procfs/procfs_osrel.c optional procfs fs/procfs/procfs_regs.c optional procfs fs/procfs/procfs_rlimit.c optional procfs fs/procfs/procfs_status.c optional procfs @@ -2009,6 +2010,7 @@ kern/sched_ule.c optional sched_ule kern/serdev_if.m standard kern/stack_protector.c standard \ compile-with "${NORMAL_C:N-fstack-protector*}" +kern/subr_acl_nfs4.c standard kern/subr_acl_posix1e.c standard kern/subr_autoconf.c standard kern/subr_blist.c standard @@ -2633,7 +2635,7 @@ ufs/ufs/ufs_acl.c optional ffs ufs/ufs/ufs_bmap.c optional ffs ufs/ufs/ufs_dirhash.c optional ffs ufs/ufs/ufs_extattr.c optional ffs -ufs/ufs/ufs_gjournal.c optional ffs +ufs/ufs/ufs_gjournal.c optional ffs UFS_GJOURNAL ufs/ufs/ufs_inode.c optional ffs ufs/ufs/ufs_lookup.c optional ffs ufs/ufs/ufs_quota.c optional ffs @@ -2828,6 +2830,3 @@ dev/xen/netfront/netfront.c optional xen | xenhvm dev/xen/xenpci/xenpci.c optional xenpci dev/xen/xenpci/evtchn.c optional xenpci dev/xen/xenpci/machine_reboot.c optional xenpci -contrib/x86emu/x86emu.c optional x86emu -contrib/x86emu/x86emu_util.c optional x86emu - diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index 01f535592829..0721ea4ec3bc 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -162,7 +162,7 @@ dev/atkbdc/atkbdc_subr.c optional atkbdc dev/atkbdc/psm.c optional psm atkbdc dev/coretemp/coretemp.c optional coretemp dev/cpuctl/cpuctl.c optional cpuctl -dev/dpms/dpms.c optional dpms x86emu +dev/dpms/dpms.c optional dpms # There are no systems with isa slots, so all ed isa entries should go.. dev/ed/if_ed_3c503.c optional ed isa ed_3c503 dev/ed/if_ed_isa.c optional ed isa @@ -170,7 +170,8 @@ dev/ed/if_ed_wd80x3.c optional ed isa dev/ed/if_ed_hpp.c optional ed isa ed_hpp dev/ed/if_ed_sic.c optional ed isa ed_sic dev/fb/fb.c optional fb | vga -dev/fb/vesa.c optional vga vesa x86emu +dev/fb/s3_pci.c optional s3pci +dev/fb/vesa.c optional vga vesa dev/fb/vga.c optional vga dev/ichwd/ichwd.c optional ichwd dev/if_ndis/if_ndis.c optional ndis @@ -219,7 +220,7 @@ dev/sio/sio_puc.c optional sio puc dev/speaker/spkr.c optional speaker dev/syscons/apm/apm_saver.c optional apm_saver apm dev/syscons/scterm-teken.c optional sc -dev/syscons/scvesactl.c optional sc vga vesa x86emu +dev/syscons/scvesactl.c optional sc vga vesa dev/syscons/scvgarndr.c optional sc vga dev/syscons/scvtb.c optional sc dev/uart/uart_cpu_amd64.c optional uart @@ -293,3 +294,10 @@ i386/cpufreq/p4tcc.c optional cpufreq # libkern/memmove.c standard libkern/memset.c standard +# +# x86 real mode BIOS emulator, required by atkbdc/dpms/vesa +# +compat/x86bios/x86bios.c optional x86bios | atkbd | dpms | vesa +compat/x86bios/x86bios_alloc.c optional x86bios | atkbd | dpms | vesa +contrib/x86emu/x86emu.c optional x86bios | atkbd | dpms | vesa +contrib/x86emu/x86emu_util.c optional x86bios | atkbd | dpms | vesa diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index 0a16ceed9783..ef6d590b5f2e 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -150,14 +150,15 @@ dev/ctau/if_ct.c optional ctau dev/cx/csigma.c optional cx dev/cx/cxddk.c optional cx dev/cx/if_cx.c optional cx -dev/dpms/dpms.c optional dpms x86emu +dev/dpms/dpms.c optional dpms dev/ed/if_ed_3c503.c optional ed isa ed_3c503 dev/ed/if_ed_isa.c optional ed isa dev/ed/if_ed_wd80x3.c optional ed isa dev/ed/if_ed_hpp.c optional ed isa ed_hpp dev/ed/if_ed_sic.c optional ed isa ed_sic dev/fb/fb.c optional fb | vga -dev/fb/vesa.c optional vga vesa x86emu +dev/fb/s3_pci.c optional s3pci +dev/fb/vesa.c optional vga vesa dev/fb/vga.c optional vga dev/fdc/fdc.c optional fdc dev/fdc/fdc_acpi.c optional fdc @@ -219,7 +220,7 @@ dev/sio/sio_puc.c optional sio puc dev/speaker/spkr.c optional speaker dev/syscons/apm/apm_saver.c optional apm_saver apm dev/syscons/scterm-teken.c optional sc -dev/syscons/scvesactl.c optional sc vga vesa x86emu +dev/syscons/scvesactl.c optional sc vga vesa dev/syscons/scvgarndr.c optional sc vga dev/syscons/scvtb.c optional sc dev/uart/uart_cpu_i386.c optional uart @@ -377,3 +378,10 @@ i386/xbox/xbox.c optional xbox i386/xbox/xboxfb.c optional xboxfb dev/fb/boot_font.c optional xboxfb i386/xbox/pic16l.s optional xbox +# +# x86 real mode BIOS emulator, required by atkbdc/dpms/vesa +# +compat/x86bios/x86bios.c optional x86bios | atkbd | dpms | vesa +compat/x86bios/x86bios_alloc.c optional x86bios | atkbd | dpms | vesa +contrib/x86emu/x86emu.c optional x86bios | atkbd | dpms | vesa +contrib/x86emu/x86emu_util.c optional x86bios | atkbd | dpms | vesa diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh index 49e99fd3d6f1..cabee5a932ba 100644 --- a/sys/conf/newvers.sh +++ b/sys/conf/newvers.sh @@ -89,28 +89,54 @@ i=`${MAKE:-make} -V KERN_IDENT` case "$d" in */sys/*) + SRCDIR=${d##*obj} + if [ -n "$MACHINE" ]; then + SRCDIR=${SRCDIR##/$MACHINE} + fi + SRCDIR=${SRCDIR%%/sys/*} + for dir in /bin /usr/bin /usr/local/bin; do - if [ -x "${dir}/svnversion" ]; then + if [ -d "${SRCDIR}/sys/.svn" -a -x "${dir}/svnversion" ] ; then svnversion=${dir}/svnversion - SRCDIR=${d##*obj} - if [ -n "$MACHINE" ]; then - SRCDIR=${SRCDIR##/$MACHINE} - fi - SRCDIR=${SRCDIR%%/sys/*} + break + fi + if [ -d "${SRCDIR}/.git" -a -x "${dir}/git" ] ; then + git_cmd="${dir}/git --git-dir=${SRCDIR}/.git" break fi done - if [ -n "$svnversion" -a -d "${SRCDIR}/sys/.svn" ] ; then + if [ -n "$svnversion" ] ; then svn=" r`cd ${SRCDIR}/sys && $svnversion`" fi + if [ -n "$git_cmd" ] ; then + git=`$git_cmd rev-parse --verify --short HEAD 2>/dev/null` + svn=`$git_cmd svn find-rev $git 2>/dev/null` + if [ -n "$svn" ] ; then + svn=" r${svn}" + git="=${git}" + else + svn=`$git_cmd log | fgrep 'git-svn-id:' | head -1 | \ + sed -n 's/^.*@\([0-9][0-9]*\).*$/\1/p'` + if [ -n $svn ] ; then + svn=" r${svn}" + git="+${git}" + else + git=" ${git}" + fi + fi + if $git_cmd --work-tree=${SRCDIR} diff-index \ + --name-only HEAD | read dummy; then + git="${git}-dirty" + fi + fi ;; esac cat << EOF > vers.c $COPYRIGHT -#define SCCSSTR "@(#)${VERSION} #${v}${svn}: ${t}" -#define VERSTR "${VERSION} #${v}${svn}: ${t}\\n ${u}@${h}:${d}\\n" +#define SCCSSTR "@(#)${VERSION} #${v}${svn}${git}: ${t}" +#define VERSTR "${VERSION} #${v}${svn}${git}: ${t}\\n ${u}@${h}:${d}\\n" #define RELSTR "${RELEASE}" char sccs[sizeof(SCCSSTR) > 128 ? sizeof(SCCSSTR) : 128] = SCCSSTR; diff --git a/sys/conf/options b/sys/conf/options index 4752fb808709..1df09d7d0382 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -838,4 +838,4 @@ SND_FEEDER_RATE_HP opt_snd.h SND_PCM_64 opt_snd.h SND_OLDSTEREO opt_snd.h -X86EMU +X86BIOS diff --git a/sys/contrib/x86emu/x86emu.c b/sys/contrib/x86emu/x86emu.c index a26044a3167b..3e5a06ad98ed 100644 --- a/sys/contrib/x86emu/x86emu.c +++ b/sys/contrib/x86emu/x86emu.c @@ -1,6 +1,5 @@ /* $OpenBSD: x86emu.c,v 1.4 2009/06/18 14:19:21 pirofti Exp $ */ /* $NetBSD: x86emu.c,v 1.7 2009/02/03 19:26:29 joerg Exp $ */ -/* $FreeBSD$ */ /* * @@ -33,9 +32,8 @@ * */ -#include <sys/param.h> -#include <sys/kernel.h> -#include <sys/module.h> +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); #include <contrib/x86emu/x86emu.h> #include <contrib/x86emu/x86emu_regs.h> @@ -8335,32 +8333,3 @@ pop_long(struct x86emu *emu) emu->x86.R_SP += 4; return res; } - -static int -x86emu_modevent(module_t mod __unused, int type, void *data __unused) -{ - int err = 0; - - switch (type) { - case MOD_LOAD: - break; - - case MOD_UNLOAD: - break; - - default: - err = ENOTSUP; - break; - - } - return (err); -} - -static moduledata_t x86emu_mod = { - "x86emu", - x86emu_modevent, - NULL, -}; - -DECLARE_MODULE(x86emu, x86emu_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST); -MODULE_VERSION(x86emu, 1); diff --git a/sys/contrib/x86emu/x86emu_util.c b/sys/contrib/x86emu/x86emu_util.c index 41a9f72d1423..4172f94f135a 100644 --- a/sys/contrib/x86emu/x86emu_util.c +++ b/sys/contrib/x86emu/x86emu_util.c @@ -1,6 +1,5 @@ /* $OpenBSD: x86emu_util.c,v 1.5 2009/06/18 14:19:21 pirofti Exp $ */ /* $NetBSD: x86emu_util.c,v 1.2 2007/12/04 17:32:22 joerg Exp $ */ -/* $FreeBSD$ */ /* * @@ -33,6 +32,9 @@ * */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + #include <sys/param.h> #include <sys/endian.h> diff --git a/sys/dev/acpi_support/acpi_aiboost.c b/sys/dev/acpi_support/acpi_aiboost.c index 8fff8720597f..a8fe9cc4a45e 100644 --- a/sys/dev/acpi_support/acpi_aiboost.c +++ b/sys/dev/acpi_support/acpi_aiboost.c @@ -46,7 +46,6 @@ ACPI_MODULE_NAME("AIBOOST") #define DESCSTRLEN 32 struct acpi_aiboost_element{ - ACPI_HANDLE h; uint32_t id; char desc[DESCSTRLEN]; }; @@ -127,22 +126,23 @@ static ACPI_STATUS acpi_aiboost_getcomponent(device_t dev, char *name, struct a for(i = 1 ; i < o->Package.Count; i++){ elem = &o->Package.Elements[i]; - if(elem->Type != ACPI_TYPE_ANY){ - printf("NOREF\n"); - goto error; - } - c->elem[ i - 1].h = elem->Reference.Handle; - - buf2.Pointer = NULL; - buf2.Length = ACPI_ALLOCATE_BUFFER; - - status = AcpiEvaluateObject(c->elem[i - 1].h, NULL, NULL, - &buf2); - if(ACPI_FAILURE(status)){ - printf("FETCH OBJECT\n"); + if (elem->Type == ACPI_TYPE_ANY) { + buf2.Pointer = NULL; + buf2.Length = ACPI_ALLOCATE_BUFFER; + + status = AcpiEvaluateObject(elem->Reference.Handle, + NULL, NULL, &buf2); + if (ACPI_FAILURE(status)){ + printf("FETCH OBJECT\n"); + goto error; + } + subobj = buf2.Pointer; + } else if (elem->Type == ACPI_TYPE_PACKAGE) + subobj = elem; + else { + printf("NO PACKAGE\n"); goto error; } - subobj = buf2.Pointer; if(ACPI_FAILURE(acpi_PkgInt32(subobj,0, &c->elem[i -1].id))){ printf("ID FAILED\n"); goto error; @@ -151,15 +151,17 @@ static ACPI_STATUS acpi_aiboost_getcomponent(device_t dev, char *name, struct a sizeof(c->elem[i - 1].desc)); if(ACPI_FAILURE(status)){ if(status == E2BIG){ - c->elem[i-1].desc[DESCSTRLEN-1] = 0; + c->elem[i - 1].desc[DESCSTRLEN-1] = 0; }else{ printf("DESC FAILED %d\n", i-1); goto error; } } - if(buf2.Pointer) - AcpiOsFree(buf2.Pointer); + if (buf2.Pointer) { + AcpiOsFree(buf2.Pointer); + buf2.Pointer = NULL; + } } if(buf.Pointer) diff --git a/sys/dev/acpi_support/acpi_ibm.c b/sys/dev/acpi_support/acpi_ibm.c index 0bf340dd5ec7..25db9b0be961 100644 --- a/sys/dev/acpi_support/acpi_ibm.c +++ b/sys/dev/acpi_support/acpi_ibm.c @@ -288,7 +288,7 @@ static devclass_t acpi_ibm_devclass; DRIVER_MODULE(acpi_ibm, acpi, acpi_ibm_driver, acpi_ibm_devclass, 0, 0); MODULE_DEPEND(acpi_ibm, acpi, 1, 1, 1); -static char *ibm_ids[] = {"IBM0057", "IBM0068", NULL}; +static char *ibm_ids[] = {"IBM0068", NULL}; static void ibm_led(void *softc, int onoff) @@ -356,8 +356,6 @@ acpi_ibm_attach(device_t dev) } sc->ec_handle = acpi_get_handle(sc->ec_dev); - ACPI_SERIAL_BEGIN(ibm); - /* Get the sysctl tree */ sc->sysctl_ctx = device_get_sysctl_ctx(dev); sc->sysctl_tree = device_get_sysctl_tree(dev); @@ -404,8 +402,6 @@ acpi_ibm_attach(device_t dev) "Thermal zones"); } - ACPI_SERIAL_END(ibm); - /* Handle notifies */ AcpiInstallNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY, acpi_ibm_notify, dev); diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c index d40227432b2b..b31f1e7889e9 100644 --- a/sys/dev/acpica/acpi.c +++ b/sys/dev/acpica/acpi.c @@ -2244,6 +2244,28 @@ acpi_SetIntrModel(int model) } /* + * Walk subtables of a table and call a callback routine for each + * subtable. The caller should provide the first subtable and a + * pointer to the end of the table. This can be used to walk tables + * such as MADT and SRAT that use subtable entries. + */ +void +acpi_walk_subtables(void *first, void *end, acpi_subtable_handler *handler, + void *arg) +{ + ACPI_SUBTABLE_HEADER *entry; + + for (entry = first; (void *)entry < end; ) { + /* Avoid an infinite loop if we hit a bogus entry. */ + if (entry->Length < sizeof(ACPI_SUBTABLE_HEADER)) + return; + + handler(entry, arg); + entry = ACPI_ADD_PTR(ACPI_SUBTABLE_HEADER, entry, entry->Length); + } +} + +/* * DEPRECATED. This interface has serious deficiencies and will be * removed. * diff --git a/sys/dev/acpica/acpi_video.c b/sys/dev/acpica/acpi_video.c index c095a402642f..e7e7d66ce074 100644 --- a/sys/dev/acpica/acpi_video.c +++ b/sys/dev/acpica/acpi_video.c @@ -282,8 +282,7 @@ acpi_video_detach(device_t dev) acpi_video_notify_handler); ACPI_SERIAL_BEGIN(video); - for (vo = STAILQ_FIRST(&sc->vid_outputs); vo != NULL; vo = vn) { - vn = STAILQ_NEXT(vo, vo_next); + STAILQ_FOREACH_SAFE(vo, &sc->vid_outputs, vo_next, vn) { acpi_video_vo_destroy(vo); } ACPI_SERIAL_END(video); diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h index 63eadea693b4..f4d27e4738cf 100644 --- a/sys/dev/acpica/acpivar.h +++ b/sys/dev/acpica/acpivar.h @@ -307,6 +307,9 @@ void acpi_EnterDebugger(void); ACPI_DEVINFO_PRESENT(x, ACPI_STA_PRESENT | ACPI_STA_FUNCTIONAL | \ ACPI_STA_BATT_PRESENT) +/* Callback function type for walking subtables within a table. */ +typedef void acpi_subtable_handler(ACPI_SUBTABLE_HEADER *, void *); + BOOLEAN acpi_DeviceIsPresent(device_t dev); BOOLEAN acpi_BatteryIsPresent(device_t dev); ACPI_STATUS acpi_GetHandleInScope(ACPI_HANDLE parent, char *path, @@ -340,6 +343,8 @@ void acpi_UserNotify(const char *subsystem, ACPI_HANDLE h, int acpi_bus_alloc_gas(device_t dev, int *type, int *rid, ACPI_GENERIC_ADDRESS *gas, struct resource **res, u_int flags); +void acpi_walk_subtables(void *first, void *end, + acpi_subtable_handler *handler, void *arg); struct acpi_parse_resource_set { void (*set_init)(device_t dev, void *arg, void **context); diff --git a/sys/dev/ata/chipsets/ata-marvell.c b/sys/dev/ata/chipsets/ata-marvell.c index 0544e199ed0f..dd6b96fcbf3f 100644 --- a/sys/dev/ata/chipsets/ata-marvell.c +++ b/sys/dev/ata/chipsets/ata-marvell.c @@ -227,6 +227,8 @@ ata_marvell_edma_ch_attach(device_t dev) work = ch->dma.work_bus; /* clear work area */ bzero(ch->dma.work, 1024+256); + bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); /* set legacy ATA resources */ for (i = ATA_DATA; i <= ATA_COMMAND; i++) { @@ -310,7 +312,11 @@ ata_marvell_edma_ch_attach(device_t dev) static int ata_marvell_edma_ch_detach(device_t dev) { + struct ata_channel *ch = device_get_softc(dev); + if (ch->dma.work_tag && ch->dma.work_map) + bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); ata_dmafini(dev); return (0); } @@ -344,8 +350,6 @@ ata_marvell_edma_begin_transaction(struct ata_request *request) struct ata_channel *ch = device_get_softc(request->parent); u_int32_t req_in; u_int8_t *bytep; - u_int16_t *wordp; - u_int32_t *quadp; int i; int error, slot; @@ -374,13 +378,14 @@ ata_marvell_edma_begin_transaction(struct ata_request *request) slot = (((req_in & ~0xfffffc00) >> 5) + 0) & 0x1f; bytep = (u_int8_t *)(ch->dma.work); bytep += (slot << 5); - wordp = (u_int16_t *)bytep; - quadp = (u_int32_t *)bytep; /* fill in this request */ - quadp[0] = (long)request->dma->sg_bus & 0xffffffff; - quadp[1] = (u_int64_t)request->dma->sg_bus >> 32; - wordp[4] = (request->flags & ATA_R_READ ? 0x01 : 0x00) | (request->tag<<1); + le32enc(bytep + 0 * sizeof(u_int32_t), + request->dma->sg_bus & 0xffffffff); + le32enc(bytep + 1 * sizeof(u_int32_t), + (u_int64_t)request->dma->sg_bus >> 32); + le16enc(bytep + 4 * sizeof(u_int16_t), + (request->flags & ATA_R_READ ? 0x01 : 0x00) | (request->tag << 1)); i = 10; bytep[i++] = (request->u.ata.count >> 8) & 0xff; @@ -409,6 +414,9 @@ ata_marvell_edma_begin_transaction(struct ata_request *request) bytep[i++] = request->u.ata.command; bytep[i++] = 0x90 | ATA_COMMAND; + bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + /* enable EDMA machinery if needed */ if (!(ATA_INL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch)) & 0x00000001)) { ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000001); @@ -451,6 +459,8 @@ ata_marvell_edma_end_transaction(struct ata_request *request) slot = (((rsp_in & ~0xffffff00) >> 3)) & 0x1f; rsp_out &= 0xffffff00; rsp_out += (slot << 3); + bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); response = (struct ata_marvell_response *) (ch->dma.work + 1024 + (slot << 3)); @@ -525,6 +535,7 @@ ata_marvell_edma_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, prd[i].addrlo = htole32(segs[i].ds_addr); prd[i].count = htole32(segs[i].ds_len); prd[i].addrhi = htole32((u_int64_t)segs[i].ds_addr >> 32); + prd[i].reserved = 0; } prd[i - 1].count |= htole32(ATA_DMA_EOT); KASSERT(nsegs <= ATA_DMA_ENTRIES, ("too many DMA segment entries\n")); diff --git a/sys/dev/atkbdc/atkbd.c b/sys/dev/atkbdc/atkbd.c index 0aae1531b137..59d96322a62f 100644 --- a/sys/dev/atkbdc/atkbd.c +++ b/sys/dev/atkbdc/atkbd.c @@ -44,10 +44,10 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> #include <machine/resource.h> -#ifdef __i386__ +#if defined(__i386__) || defined(__amd64__) #include <machine/md_var.h> #include <machine/psl.h> -#include <machine/vm86.h> +#include <compat/x86bios/x86bios.h> #include <machine/pc/bios.h> #include <vm/vm.h> @@ -55,7 +55,7 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_param.h> #include <isa/isareg.h> -#endif /* __i386__ */ +#endif /* __i386__ || __amd64__ */ #include <sys/kbio.h> #include <dev/kbd/kbdreg.h> @@ -1089,34 +1089,42 @@ atkbd_shutdown_final(void *v) static int get_typematic(keyboard_t *kbd) { -#ifdef __i386__ +#if defined(__i386__) || defined(__amd64__) /* * Only some systems allow us to retrieve the keyboard repeat * rate previously set via the BIOS... */ - struct vm86frame vmf; - u_int32_t p; - - bzero(&vmf, sizeof(vmf)); - vmf.vmf_ax = 0xc000; - vm86_intcall(0x15, &vmf); - if ((vmf.vmf_eflags & PSL_C) || vmf.vmf_ah) - return ENODEV; - p = BIOS_PADDRTOVADDR(((u_int32_t)vmf.vmf_es << 4) + vmf.vmf_bx); - if ((readb(p + 6) & 0x40) == 0) /* int 16, function 0x09 supported? */ - return ENODEV; - vmf.vmf_ax = 0x0900; - vm86_intcall(0x16, &vmf); - if ((vmf.vmf_al & 0x08) == 0) /* int 16, function 0x0306 supported? */ - return ENODEV; - vmf.vmf_ax = 0x0306; - vm86_intcall(0x16, &vmf); - kbd->kb_delay1 = typematic_delay(vmf.vmf_bh << 5); - kbd->kb_delay2 = typematic_rate(vmf.vmf_bl); - return 0; + x86regs_t regs; + uint8_t *p; + + /* Is BIOS system configuration table supported? */ + bzero(®s, sizeof(regs)); + regs.R_AH = 0xc0; + x86bios_intr(®s, 0x15); + if ((regs.R_FLG & PSL_C) != 0 || regs.R_AH != 0) + return (ENODEV); + + /* Is int 16, function 0x09 supported? */ + p = x86bios_offset((regs.R_ES << 4) + regs.R_BX); + if (readw(p) < 5 || (readb(p + 6) & 0x40) == 0) + return (ENODEV); + + /* Is int 16, function 0x0306 supported? */ + bzero(®s, sizeof(regs)); + regs.R_AH = 0x09; + x86bios_intr(®s, 0x16); + if ((regs.R_AL & 0x08) == 0) + return (ENODEV); + + bzero(®s, sizeof(regs)); + regs.R_AX = 0x0306; + x86bios_intr(®s, 0x16); + kbd->kb_delay1 = typematic_delay(regs.R_BH << 5); + kbd->kb_delay2 = typematic_rate(regs.R_BL); + return (0); #else - return ENODEV; -#endif /* __i386__ */ + return (ENODEV); +#endif /* __i386__ || __amd64__ */ } static int diff --git a/sys/dev/de/if_de.c b/sys/dev/de/if_de.c index 2acf1a8a1c93..c3d283988aeb 100644 --- a/sys/dev/de/if_de.c +++ b/sys/dev/de/if_de.c @@ -160,7 +160,7 @@ static void tulip_dma_map_rxbuf(void *, bus_dma_segment_t *, int, static void tulip_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error) { - u_int32_t *paddr; + bus_addr_t *paddr; if (error) return; @@ -182,7 +182,7 @@ tulip_dma_map_rxbuf(void *arg, bus_dma_segment_t *segs, int nseg, KASSERT(nseg == 1, ("too many DMA segments")); KASSERT(segs[0].ds_len >= TULIP_RX_BUFLEN, ("receive buffer too small")); - desc->d_addr1 = segs[0].ds_addr; + desc->d_addr1 = segs[0].ds_addr & 0xffffffff; desc->d_length1 = TULIP_RX_BUFLEN; #ifdef not_needed /* These should already always be zero. */ @@ -3171,8 +3171,8 @@ tulip_reset(tulip_softc_t * const sc) sc->tulip_ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; } - TULIP_CSR_WRITE(sc, csr_txlist, sc->tulip_txinfo.ri_dma_addr); - TULIP_CSR_WRITE(sc, csr_rxlist, sc->tulip_rxinfo.ri_dma_addr); + TULIP_CSR_WRITE(sc, csr_txlist, sc->tulip_txinfo.ri_dma_addr & 0xffffffff); + TULIP_CSR_WRITE(sc, csr_rxlist, sc->tulip_rxinfo.ri_dma_addr & 0xffffffff); TULIP_CSR_WRITE(sc, csr_busmode, (1 << (3 /*pci_max_burst_len*/ + 8)) |TULIP_BUSMODE_CACHE_ALIGN8 @@ -3488,7 +3488,7 @@ tulip_rx_intr(tulip_softc_t * const sc) struct mbuf *m0; KASSERT(ms != NULL, ("no packet to accept")); -#if defined(TULIP_COPY_RXDATA) +#ifndef __NO_STRICT_ALIGNMENT /* * Copy the data into a new mbuf that is properly aligned. If * we fail to allocate a new mbuf, then drop the packet. We will @@ -3527,7 +3527,7 @@ tulip_rx_intr(tulip_softc_t * const sc) */ ms = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); -#if defined(TULIP_COPY_RXDATA) +#ifndef __NO_STRICT_ALIGNMENT skip_input: #endif if (ms == NULL) { @@ -4016,9 +4016,9 @@ tulip_txput(tulip_softc_t * const sc, struct mbuf *m) eop = nextout; eop->di_desc->d_flag &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN; eop->di_desc->d_status = d_status; - eop->di_desc->d_addr1 = segs[segcnt].ds_addr; + eop->di_desc->d_addr1 = segs[segcnt].ds_addr & 0xffffffff; eop->di_desc->d_length1 = segs[segcnt].ds_len; - eop->di_desc->d_addr2 = segs[segcnt+1].ds_addr; + eop->di_desc->d_addr2 = segs[segcnt+1].ds_addr & 0xffffffff; eop->di_desc->d_length2 = segs[segcnt+1].ds_len; d_status = TULIP_DSTS_OWNER; if (++nextout == ri->ri_last) @@ -4028,7 +4028,7 @@ tulip_txput(tulip_softc_t * const sc, struct mbuf *m) eop = nextout; eop->di_desc->d_flag &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN; eop->di_desc->d_status = d_status; - eop->di_desc->d_addr1 = segs[segcnt].ds_addr; + eop->di_desc->d_addr1 = segs[segcnt].ds_addr & 0xffffffff; eop->di_desc->d_length1 = segs[segcnt].ds_len; eop->di_desc->d_addr2 = 0; eop->di_desc->d_length2 = 0; @@ -4194,7 +4194,7 @@ tulip_txput_setup(tulip_softc_t * const sc) nextout->d_length2 = 0; nextout->d_addr2 = 0; nextout->d_length1 = sizeof(sc->tulip_setupdata); - nextout->d_addr1 = sc->tulip_setup_dma_addr; + nextout->d_addr1 = sc->tulip_setup_dma_addr & 0xffffffff; bus_dmamap_sync(sc->tulip_setup_tag, sc->tulip_setup_map, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); TULIP_TXDESC_PRESYNC(ri); @@ -4491,7 +4491,7 @@ tulip_busdma_freering(tulip_ringinfo_t *ri) /* Allocate memory for a single descriptor ring. */ static int tulip_busdma_allocring(device_t dev, tulip_softc_t * const sc, size_t count, - bus_size_t maxsize, int nsegs, tulip_ringinfo_t *ri, const char *name) + bus_size_t align, int nsegs, tulip_ringinfo_t *ri, const char *name) { size_t size; int error, i; @@ -4499,7 +4499,7 @@ tulip_busdma_allocring(device_t dev, tulip_softc_t * const sc, size_t count, /* First, setup a tag. */ ri->ri_max = count; size = count * sizeof(tulip_desc_t); - error = bus_dma_tag_create(NULL, PAGE_SIZE, 0, BUS_SPACE_MAXADDR_32BIT, + error = bus_dma_tag_create(NULL, 32, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, size, 1, size, 0, NULL, NULL, &ri->ri_ring_tag); if (error) { @@ -4527,9 +4527,9 @@ tulip_busdma_allocring(device_t dev, tulip_softc_t * const sc, size_t count, } /* Allocate a tag for the data buffers. */ - error = bus_dma_tag_create(NULL, 4, 0, + error = bus_dma_tag_create(NULL, align, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - maxsize, nsegs, TULIP_DATA_PER_DESC, 0, NULL, NULL, &ri->ri_data_tag); + MCLBYTES * nsegs, nsegs, MCLBYTES, 0, NULL, NULL, &ri->ri_data_tag); if (error) { device_printf(dev, "failed to allocate %s buffer dma tag\n", name); return (error); @@ -4563,6 +4563,7 @@ tulip_busdma_cleanup(tulip_softc_t * const sc) if (sc->tulip_setupbuf != NULL) { bus_dmamem_free(sc->tulip_setup_tag, sc->tulip_setupbuf, sc->tulip_setup_map); + bus_dmamap_destroy(sc->tulip_setup_tag, sc->tulip_setup_map); sc->tulip_setup_map = NULL; sc->tulip_setupbuf = NULL; } @@ -4586,8 +4587,8 @@ tulip_busdma_init(device_t dev, tulip_softc_t * const sc) /* * Allocate space and dmamap for transmit ring. */ - error = tulip_busdma_allocring(dev, sc, TULIP_TXDESCS, TULIP_DATA_PER_DESC, - TULIP_MAX_TXSEG, &sc->tulip_txinfo, "transmit"); + error = tulip_busdma_allocring(dev, sc, TULIP_TXDESCS, 1, TULIP_MAX_TXSEG, + &sc->tulip_txinfo, "transmit"); if (error) return (error); @@ -4598,7 +4599,7 @@ tulip_busdma_init(device_t dev, tulip_softc_t * const sc) * a waste in practice though as an ethernet frame can easily fit * in TULIP_RX_BUFLEN bytes. */ - error = tulip_busdma_allocring(dev, sc, TULIP_RXDESCS, MCLBYTES, 1, + error = tulip_busdma_allocring(dev, sc, TULIP_RXDESCS, 4, 1, &sc->tulip_rxinfo, "receive"); if (error) return (error); @@ -4606,7 +4607,7 @@ tulip_busdma_init(device_t dev, tulip_softc_t * const sc) /* * Allocate a DMA tag, memory, and map for setup descriptor */ - error = bus_dma_tag_create(NULL, 4, 0, + error = bus_dma_tag_create(NULL, 32, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, sizeof(sc->tulip_setupdata), 1, sizeof(sc->tulip_setupdata), 0, NULL, NULL, &sc->tulip_setup_tag); diff --git a/sys/dev/de/if_devar.h b/sys/dev/de/if_devar.h index 3fd341047a66..b4feebc12aaa 100644 --- a/sys/dev/de/if_devar.h +++ b/sys/dev/de/if_devar.h @@ -104,7 +104,7 @@ typedef struct { tulip_descinfo_t *ri_descinfo; bus_dma_tag_t ri_ring_tag; bus_dmamap_t ri_ring_map; - uint32_t ri_dma_addr; + bus_addr_t ri_dma_addr; bus_dma_tag_t ri_data_tag; bus_dmamap_t *ri_data_maps; } tulip_ringinfo_t; @@ -134,11 +134,7 @@ typedef struct { * architecture which can't handle unaligned accesses) because with * 100Mb/s cards the copying is just too much of a hit. */ -#if !defined(__i386__) -#define TULIP_COPY_RXDATA 1 -#endif -#define TULIP_DATA_PER_DESC 2032 #define TULIP_TXTIMER 4 #define TULIP_RXDESCS 48 #define TULIP_TXDESCS 128 @@ -560,7 +556,7 @@ struct tulip_softc { */ bus_dma_tag_t tulip_setup_tag; bus_dmamap_t tulip_setup_map; - uint32_t tulip_setup_dma_addr; + bus_addr_t tulip_setup_dma_addr; u_int32_t *tulip_setupbuf; u_int32_t tulip_setupdata[192 / sizeof(u_int32_t)]; char tulip_boardid[24]; diff --git a/sys/dev/dpms/dpms.c b/sys/dev/dpms/dpms.c index ac729f9edd06..c0476c5d36e7 100644 --- a/sys/dev/dpms/dpms.c +++ b/sys/dev/dpms/dpms.c @@ -67,11 +67,7 @@ __FBSDID("$FreeBSD$"); #include <sys/libkern.h> #include <sys/module.h> -#include <vm/vm.h> -#include <vm/pmap.h> - -#include <contrib/x86emu/x86emu.h> -#include <contrib/x86emu/x86emu_regs.h> +#include <compat/x86bios/x86bios.h> /* * VESA DPMS States @@ -94,9 +90,6 @@ struct dpms_softc { int dpms_initial_state; }; -static struct x86emu vesa_emu; -static unsigned char *emumem = NULL; - static int dpms_attach(device_t); static int dpms_detach(device_t); static int dpms_get_supported_states(int *); @@ -126,59 +119,7 @@ static driver_t dpms_driver = { static devclass_t dpms_devclass; DRIVER_MODULE(dpms, vgapci, dpms_driver, dpms_devclass, NULL, NULL); -MODULE_DEPEND(dpms, x86emu, 1, 1, 1); - -static uint8_t -vm86_emu_inb(struct x86emu *emu, uint16_t port) -{ - if (port == 0xb2) /* APM scratch register */ - return 0; - if (port >= 0x80 && port < 0x88) /* POST status register */ - return 0; - return inb(port); -} - -static uint16_t -vm86_emu_inw(struct x86emu *emu, uint16_t port) -{ - if (port >= 0x80 && port < 0x88) /* POST status register */ - return 0; - return inw(port); -} - -static uint32_t -vm86_emu_inl(struct x86emu *emu, uint16_t port) -{ - if (port >= 0x80 && port < 0x88) /* POST status register */ - return 0; - return inl(port); -} - -static void -vm86_emu_outb(struct x86emu *emu, uint16_t port, uint8_t val) -{ - if (port == 0xb2) /* APM scratch register */ - return; - if (port >= 0x80 && port < 0x88) /* POST status register */ - return; - outb(port, val); -} - -static void -vm86_emu_outw(struct x86emu *emu, uint16_t port, uint16_t val) -{ - if (port >= 0x80 && port < 0x88) /* POST status register */ - return; - outw(port, val); -} - -static void -vm86_emu_outl(struct x86emu *emu, uint16_t port, uint32_t val) -{ - if (port >= 0x80 && port < 0x88) /* POST status register */ - return; - outl(port, val); -} +MODULE_DEPEND(dpms, x86bios, 1, 1, 1); static void dpms_identify(driver_t *driver, device_t parent) @@ -192,7 +133,6 @@ dpms_identify(driver_t *driver, device_t parent) */ if (devclass_get_device(dpms_devclass, 0) == NULL) device_add_child(parent, "dpms", 0); - } static int @@ -200,21 +140,6 @@ dpms_probe(device_t dev) { int error, states; - emumem = pmap_mapbios(0x0, 0xc00000); - - memset(&vesa_emu, 0, sizeof(vesa_emu)); - x86emu_init_default(&vesa_emu); - - vesa_emu.emu_inb = vm86_emu_inb; - vesa_emu.emu_inw = vm86_emu_inw; - vesa_emu.emu_inl = vm86_emu_inl; - vesa_emu.emu_outb = vm86_emu_outb; - vesa_emu.emu_outw = vm86_emu_outw; - vesa_emu.emu_outl = vm86_emu_outl; - - vesa_emu.mem_base = (char *)emumem; - vesa_emu.mem_size = 1024 * 1024; - error = dpms_get_supported_states(&states); if (error) return (error); @@ -240,8 +165,6 @@ dpms_attach(device_t dev) static int dpms_detach(device_t dev) { - if (emumem) - pmap_unmapdev((vm_offset_t)emumem, 0xc00000); return (0); } @@ -267,17 +190,20 @@ dpms_resume(device_t dev) static int dpms_call_bios(int subfunction, int *bh) { - vesa_emu.x86.R_AX = VBE_DPMS_FUNCTION; - vesa_emu.x86.R_BL = subfunction; - vesa_emu.x86.R_BH = *bh; - vesa_emu.x86.R_ES = 0; - vesa_emu.x86.R_DI = 0; - x86emu_exec_intr(&vesa_emu, 0x10); - - if ((vesa_emu.x86.R_EAX & 0xffff) != 0x004f) + x86regs_t regs; + + bzero(®s, sizeof(regs)); + regs.R_AX = VBE_DPMS_FUNCTION; + regs.R_BL = subfunction; + regs.R_BH = *bh; + regs.R_ES = 0; + regs.R_DI = 0; + x86bios_intr(®s, 0x10); + + if ((regs.R_EAX & 0xffff) != 0x004f) return (ENXIO); - *bh = vesa_emu.x86.R_BH; + *bh = regs.R_BH; return (0); } diff --git a/sys/dev/fb/s3_pci.c b/sys/dev/fb/s3_pci.c index 45facc9efe2e..cfddf3041f09 100644 --- a/sys/dev/fb/s3_pci.c +++ b/sys/dev/fb/s3_pci.c @@ -54,7 +54,6 @@ __FBSDID("$FreeBSD$"); #include <dev/pci/pcivar.h> #include <machine/md_var.h> -#include <machine/vm86.h> #include <machine/pc/bios.h> #include <dev/fb/vesa.h> diff --git a/sys/dev/fb/vesa.c b/sys/dev/fb/vesa.c index 5a766dc2c216..8a6136828661 100644 --- a/sys/dev/fb/vesa.c +++ b/sys/dev/fb/vesa.c @@ -45,16 +45,15 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_param.h> #include <vm/pmap.h> +#include <machine/pc/bios.h> #include <dev/fb/vesa.h> #include <dev/fb/fbreg.h> #include <dev/fb/vgareg.h> #include <isa/isareg.h> -#include <machine/cpufunc.h> -#include <contrib/x86emu/x86emu.h> -#include <contrib/x86emu/x86emu_regs.h> +#include <compat/x86bios/x86bios.h> #define VESA_VIA_CLE266 "VIA CLE266\r\n" @@ -73,7 +72,7 @@ typedef struct adp_state adp_state_t; /* VESA video adapter */ static video_adapter_t *vesa_adp = NULL; static int vesa_state_buf_size = 0; -#define VESA_X86EMU_BUFSIZE (3 * PAGE_SIZE) +#define VESA_BIOS_BUFSIZE (3 * PAGE_SIZE) /* VESA functions */ #if 0 @@ -106,8 +105,6 @@ static vi_bitblt_t vesa_bitblt; static vi_diag_t vesa_diag; static int vesa_bios_info(int level); -static struct x86emu vesa_emu; - static video_switch_t vesavidsw = { vesa_probe, vesa_init, @@ -197,6 +194,7 @@ static int vesa_bios_set_start(int x, int y); static int vesa_map_gen_mode_num(int type, int color, int mode); static int vesa_translate_flags(u_int16_t vflags); static int vesa_translate_mmodel(u_int8_t vmodel); +static int vesa_get_line_width(video_info_t *info); static int vesa_bios_init(void); static void vesa_clear_modes(video_info_t *info, int color); static vm_offset_t vesa_map_buffer(u_int paddr, size_t size); @@ -206,77 +204,6 @@ static void vesa_unmap_buffer(vm_offset_t vaddr, size_t size); static int vesa_get_origin(video_adapter_t *adp, off_t *offset); #endif -#define SEG_ADDR(x) (((x) >> 4) & 0x00F000) -#define SEG_OFF(x) ((x) & 0x0FFFF) - -#if _BYTE_ORDER == _LITTLE_ENDIAN -#define B_O16(x) (x) -#define B_O32(x) (x) -#else -#define B_O16(x) ((((x) & 0xff) << 8) | (((x) & 0xff) >> 8)) -#define B_O32(x) ((((x) & 0xff) << 24) | (((x) & 0xff00) << 8) \ - | (((x) & 0xff0000) >> 8) | (((x) & 0xff000000) >> 24)) -#endif - -#define L_ADD(x) (B_O32(x) & 0xffff) + ((B_O32(x) >> 12) & 0xffff00) -#define FARP(p) (((unsigned)(p & 0xffff0000) >> 12) | (p & 0xffff)) - -#define REALOFF(x) (x*4096) - -static unsigned char *emumem = NULL; - -static uint8_t -vm86_emu_inb(struct x86emu *emu, uint16_t port) -{ - if (port == 0xb2) /* APM scratch register */ - return 0; - if (port >= 0x80 && port < 0x88) /* POST status register */ - return 0; - return inb(port); -} - -static uint16_t -vm86_emu_inw(struct x86emu *emu, uint16_t port) -{ - if (port >= 0x80 && port < 0x88) /* POST status register */ - return 0; - return inw(port); -} - -static uint32_t -vm86_emu_inl(struct x86emu *emu, uint16_t port) -{ - if (port >= 0x80 && port < 0x88) /* POST status register */ - return 0; - return inl(port); -} - -static void -vm86_emu_outb(struct x86emu *emu, uint16_t port, uint8_t val) -{ - if (port == 0xb2) /* APM scratch register */ - return; - if (port >= 0x80 && port < 0x88) /* POST status register */ - return; - outb(port, val); -} - -static void -vm86_emu_outw(struct x86emu *emu, uint16_t port, uint16_t val) -{ - if (port >= 0x80 && port < 0x88) /* POST status register */ - return; - outw(port, val); -} - -static void -vm86_emu_outl(struct x86emu *emu, uint16_t port, uint32_t val) -{ - if (port >= 0x80 && port < 0x88) /* POST status register */ - return; - outl(port, val); -} - static void dump_buffer(u_char *buf, size_t len) { @@ -293,8 +220,12 @@ dump_buffer(u_char *buf, size_t len) static int int10_set_mode(int mode) { - vesa_emu.x86.R_EAX = 0x0000 | mode; - x86emu_exec_intr(&vesa_emu, 0x10); + x86regs_t regs; + + bzero(®s, sizeof(regs)); + regs.R_EAX = 0x0000 | mode; + + x86bios_intr(®s, 0x10); return 0; } @@ -303,21 +234,29 @@ int10_set_mode(int mode) static int vesa_bios_get_mode(int mode, struct vesa_mode *vmode) { + x86regs_t regs; + int offs; u_char *buf; - vesa_emu.x86.R_EAX = 0x4f01; - vesa_emu.x86.R_ECX = mode; + bzero(®s, sizeof(regs)); + regs.R_EAX = 0x4f01; + regs.R_ECX = mode; + + buf = (u_char *)x86bios_alloc(1, &offs); - buf = (emumem + REALOFF(3)); - vesa_emu.x86.R_ES = SEG_ADDR(REALOFF(3)); - vesa_emu.x86.R_DI = SEG_OFF(REALOFF(3)); + regs.R_ES = SEG_ADDR(offs); + regs.R_DI = SEG_OFF(offs); - x86emu_exec_intr(&vesa_emu, 0x10); + x86bios_intr(®s, 0x10); - if ((vesa_emu.x86.R_AX & 0xff) != 0x4f) + if ((regs.R_AX & 0xff) != 0x4f) + { + x86bios_free(buf, 1); return 1; + } bcopy(buf, vmode, sizeof(*vmode)); + x86bios_free(buf, 1); return 0; } @@ -325,62 +264,77 @@ vesa_bios_get_mode(int mode, struct vesa_mode *vmode) static int vesa_bios_set_mode(int mode) { - vesa_emu.x86.R_EAX = 0x4f02; - vesa_emu.x86.R_EBX = mode; + x86regs_t regs; + + bzero(®s, sizeof(regs)); + regs.R_EAX = 0x4f02; + regs.R_EBX = mode; - x86emu_exec_intr(&vesa_emu, 0x10); + x86bios_intr(®s, 0x10); - return ((vesa_emu.x86.R_AX & 0xff) != 0x4f); + return ((regs.R_AX & 0xff) != 0x4f); } static int vesa_bios_get_dac(void) { - vesa_emu.x86.R_EAX = 0x4f08; - vesa_emu.x86.R_EBX = 1; + x86regs_t regs; - x86emu_exec_intr(&vesa_emu, 0x10); + bzero(®s, sizeof(regs)); + regs.R_EAX = 0x4f08; + regs.R_EBX = 1; - if ((vesa_emu.x86.R_AX & 0xff) != 0x4f) + x86bios_intr(®s, 0x10); + + if ((regs.R_AX & 0xff) != 0x4f) return 6; - return ((vesa_emu.x86.R_EBX >> 8) & 0x00ff); + return ((regs.R_EBX >> 8) & 0x00ff); } static int vesa_bios_set_dac(int bits) { - vesa_emu.x86.R_EAX = 0x4f08; - vesa_emu.x86.R_EBX = (bits << 8); + x86regs_t regs; + + bzero(®s, sizeof(regs)); + regs.R_EAX = 0x4f08; + regs.R_EBX = (bits << 8); - x86emu_exec_intr(&vesa_emu, 0x10); + x86bios_intr(®s, 0x10); - if ((vesa_emu.x86.R_AX & 0xff) != 0x4f) + if ((regs.R_AX & 0xff) != 0x4f) return 6; - return ((vesa_emu.x86.R_EBX >> 8) & 0x00ff); + return ((regs.R_EBX >> 8) & 0x00ff); } static int vesa_bios_save_palette(int start, int colors, u_char *palette, int bits) { + x86regs_t regs; + int offs; u_char *p; int i; - vesa_emu.x86.R_EAX = 0x4f09; - vesa_emu.x86.R_EBX = 1; - vesa_emu.x86.R_ECX = colors; - vesa_emu.x86.R_EDX = start; + bzero(®s, sizeof(regs)); + regs.R_EAX = 0x4f09; + regs.R_EBX = 1; + regs.R_ECX = colors; + regs.R_EDX = start; - vesa_emu.x86.R_ES = SEG_ADDR(REALOFF(2)); - vesa_emu.x86.R_DI = SEG_OFF(REALOFF(2)); + p = (u_char *)x86bios_alloc(1, &offs); - p = emumem + REALOFF(2); + regs.R_ES = SEG_ADDR(offs); + regs.R_DI = SEG_OFF(offs); - x86emu_exec_intr(&vesa_emu, 0x10); + x86bios_intr(®s, 0x10); - if ((vesa_emu.x86.R_AX & 0xff) != 0x4f) + if ((regs.R_AX & 0xff) != 0x4f) + { + x86bios_free(p, 1); return 1; + } bits = 8 - bits; for (i = 0; i < colors; ++i) { @@ -388,6 +342,8 @@ vesa_bios_save_palette(int start, int colors, u_char *palette, int bits) palette[i*3 + 1] = p[i*4 + 1] << bits; palette[i*3 + 2] = p[i*4] << bits; } + + x86bios_free(p, 1); return 0; } @@ -395,23 +351,29 @@ static int vesa_bios_save_palette2(int start, int colors, u_char *r, u_char *g, u_char *b, int bits) { + x86regs_t regs; + int offs; u_char *p; int i; - vesa_emu.x86.R_EAX = 0x4f09; - vesa_emu.x86.R_EBX = 1; - vesa_emu.x86.R_ECX = colors; - vesa_emu.x86.R_EDX = start; + bzero(®s, sizeof(regs)); + regs.R_EAX = 0x4f09; + regs.R_EBX = 1; + regs.R_ECX = colors; + regs.R_EDX = start; - vesa_emu.x86.R_ES = SEG_ADDR(REALOFF(2)); - vesa_emu.x86.R_DI = SEG_OFF(REALOFF(2)); + p = (u_char *)x86bios_alloc(1, &offs); - p = emumem + REALOFF(2); + regs.R_ES = SEG_ADDR(offs); + regs.R_DI = SEG_OFF(offs); - x86emu_exec_intr(&vesa_emu, 0x10); + x86bios_intr(®s, 0x10); - if ((vesa_emu.x86.R_AX & 0xff) != 0x4f) + if ((regs.R_AX & 0xff) != 0x4f) + { + x86bios_free(p, 1); return 1; + } bits = 8 - bits; for (i = 0; i < colors; ++i) { @@ -419,16 +381,20 @@ vesa_bios_save_palette2(int start, int colors, u_char *r, u_char *g, u_char *b, g[i] = p[i*4 + 1] << bits; b[i] = p[i*4] << bits; } + + x86bios_free(p, 1); return 0; } static int vesa_bios_load_palette(int start, int colors, u_char *palette, int bits) { + x86regs_t regs; + int offs; u_char *p; int i; - p = (emumem + REALOFF(2)); + p = (u_char *)x86bios_alloc(1, &offs); bits = 8 - bits; for (i = 0; i < colors; ++i) { @@ -438,17 +404,20 @@ vesa_bios_load_palette(int start, int colors, u_char *palette, int bits) p[i*4 + 3] = 0; } - vesa_emu.x86.R_EAX = 0x4f09; - vesa_emu.x86.R_EBX = 0; - vesa_emu.x86.R_ECX = colors; - vesa_emu.x86.R_EDX = start; + bzero(®s, sizeof(regs)); + regs.R_EAX = 0x4f09; + regs.R_EBX = 0; + regs.R_ECX = colors; + regs.R_EDX = start; + + regs.R_ES = SEG_ADDR(offs); + regs.R_DI = SEG_OFF(offs); - vesa_emu.x86.R_ES = SEG_ADDR(REALOFF(2)); - vesa_emu.x86.R_DI = SEG_OFF(REALOFF(2)); + x86bios_intr(®s, 0x10); - x86emu_exec_intr(&vesa_emu, 0x10); + x86bios_free(p, 1); - return ((vesa_emu.x86.R_AX & 0xff) != 0x4f); + return ((regs.R_AX & 0xff) != 0x4f); } #ifdef notyet @@ -456,10 +425,12 @@ static int vesa_bios_load_palette2(int start, int colors, u_char *r, u_char *g, u_char *b, int bits) { + x86regs_t regs; + int offs; u_char *p; int i; - p = (emumem + REALOFF(2)); + p = (u_char *)x86bios_alloc(1, &offs); bits = 8 - bits; for (i = 0; i < colors; ++i) { @@ -469,93 +440,111 @@ vesa_bios_load_palette2(int start, int colors, u_char *r, u_char *g, u_char *b, p[i*4 + 3] = 0; } - vesa_emu.x86.R_EAX = 0x4f09; - vesa_emu.x86.R_EBX = 0; - vesa_emu.x86.R_ECX = colors; - vesa_emu.x86.R_EDX = start; + bzero(®s, sizeof(regs)); + regs.R_EAX = 0x4f09; + regs.R_EBX = 0; + regs.R_ECX = colors; + regs.R_EDX = start; - vesa_emu.x86.R_ES = SEG_ADDR(REALOFF(2)); - vesa_emu.x86.R_DI = SEG_OFF(REALOFF(2)); + regs.R_ES = SEG_ADDR(offs); + regs.R_DI = SEG_OFF(offs); - x86emu_exec_intr(&vesa_emu, 0x10); + x86bios_intr(®s, 0x10); - return ((vesa_emu.x86.R_AX & 0xff) != 0x4f) + x86bios_free(p, 1); + + return ((regs.R_AX & 0xff) != 0x4f); } #endif static int vesa_bios_state_buf_size(void) { - vesa_emu.x86.R_EAX = 0x4f04; - vesa_emu.x86.R_ECX = STATE_ALL; - vesa_emu.x86.R_EDX = STATE_SIZE; + x86regs_t regs; + + bzero(®s, sizeof(regs)); + regs.R_EAX = 0x4f04; + regs.R_ECX = STATE_ALL; + regs.R_EDX = STATE_SIZE; - x86emu_exec_intr(&vesa_emu, 0x10); + x86bios_intr(®s, 0x10); - if ((vesa_emu.x86.R_AX & 0xff) != 0x4f) + if ((regs.R_AX & 0xff) != 0x4f) return 0; - return vesa_emu.x86.R_BX*64; + return regs.R_BX * 64; } static int vesa_bios_save_restore(int code, void *p, size_t size) { + x86regs_t regs; + int offs; u_char *buf; - if (size > VESA_X86EMU_BUFSIZE) + if (size > VESA_BIOS_BUFSIZE) return (1); - vesa_emu.x86.R_EAX = 0x4f04; - vesa_emu.x86.R_ECX = STATE_ALL; - vesa_emu.x86.R_EDX = code; + bzero(®s, sizeof(regs)); + regs.R_EAX = 0x4f04; + regs.R_ECX = STATE_ALL; + regs.R_EDX = code; - buf = emumem + REALOFF(2); + buf = (u_char *)x86bios_alloc(1, &offs); - vesa_emu.x86.R_ES = SEG_ADDR(REALOFF(2)); - vesa_emu.x86.R_DI = SEG_OFF(REALOFF(2)); + regs.R_ES = SEG_ADDR(offs); + regs.R_DI = SEG_OFF(offs); bcopy(p, buf, size); - x86emu_exec_intr(&vesa_emu, 0x10); + x86bios_intr(®s, 0x10); bcopy(buf, p, size); - return ((vesa_emu.x86.R_AX & 0xff) != 0x4f); + x86bios_free(p, 1); + + return ((regs.R_AX & 0xff) != 0x4f); } static int vesa_bios_get_line_length(void) { - vesa_emu.x86.R_EAX = 0x4f06; - vesa_emu.x86.R_EBX = 1; + x86regs_t regs; - x86emu_exec_intr(&vesa_emu, 0x10); + bzero(®s, sizeof(regs)); + regs.R_EAX = 0x4f06; + regs.R_EBX = 1; - if ((vesa_emu.x86.R_AX & 0xff) != 0x4f) + x86bios_intr(®s, 0x10); + + if ((regs.R_AX & 0xff) != 0x4f) return -1; - return vesa_emu.x86.R_BX; + + return regs.R_BX; } static int vesa_bios_set_line_length(int pixel, int *bytes, int *lines) { - vesa_emu.x86.R_EAX = 0x4f06; - vesa_emu.x86.R_EBX = 0; - vesa_emu.x86.R_ECX = pixel; + x86regs_t regs; + + bzero(®s, sizeof(regs)); + regs.R_EAX = 0x4f06; + regs.R_EBX = 0; + regs.R_ECX = pixel; - x86emu_exec_intr(&vesa_emu, 0x10); + x86bios_intr(®s, 0x10); #if VESA_DEBUG > 1 - printf("bx:%d, cx:%d, dx:%d\n", vesa_emu.x86.R_BX, vesa_emu.x86.R_CX, vesa_emu.x86.R_DX); + printf("bx:%d, cx:%d, dx:%d\n", regs.R_BX, regs.R_CX, regs.R_DX); #endif - if ((vesa_emu.x86.R_AX & 0xff) != 0x4f) + if ((regs.R_AX & 0xff) != 0x4f) return -1; if (bytes) - *bytes = vesa_emu.x86.R_BX; + *bytes = regs.R_BX; if (lines) - *lines = vesa_emu.x86.R_DX; + *lines = regs.R_DX; return 0; } @@ -564,16 +553,19 @@ vesa_bios_set_line_length(int pixel, int *bytes, int *lines) static int vesa_bios_get_start(int *x, int *y) { - vesa_emu.x86.R_EAX = 0x4f07; - vesa_emu.x86.R_EBX = 1; + x86regs_t regs; - x86emu_exec_intr(&vesa_emu, 0x10); + bzero(®s, sizeof(regs)); + regs.R_EAX = 0x4f07; + regs.R_EBX = 1; - if ((vesa_emu.x86.R_AX & 0xff) != 0x4f) + x86bios_intr(®s, 0x10); + + if ((regs.R_AX & 0xff) != 0x4f) return -1; - *x = vesa_emu.x86.R_CX; - *y = vesa_emu.x86.R_DX; + *x = regs.R_CX; + *y = regs.R_DX; return 0; } @@ -582,14 +574,17 @@ vesa_bios_get_start(int *x, int *y) static int vesa_bios_set_start(int x, int y) { - vesa_emu.x86.R_EAX = 0x4f07; - vesa_emu.x86.R_EBX = 0x80; - vesa_emu.x86.R_EDX = y; - vesa_emu.x86.R_ECX = x; + x86regs_t regs; + + bzero(®s, sizeof(regs)); + regs.R_EAX = 0x4f07; + regs.R_EBX = 0x80; + regs.R_EDX = y; + regs.R_ECX = x; - x86emu_exec_intr(&vesa_emu, 0x10); + x86bios_intr(®s, 0x10); - return ((vesa_emu.x86.R_AX & 0xff) != 0x4f); + return ((regs.R_AX & 0xff) != 0x4f); } /* map a generic video mode to a known mode */ @@ -660,11 +655,45 @@ vesa_translate_mmodel(u_int8_t vmodel) } static int +vesa_get_line_width(video_info_t *info) +{ + int len; + int width; + + width = info->vi_width; + + if (info->vi_flags & V_INFO_GRAPHICS) + switch (info->vi_depth / info->vi_planes) { + case 1: + return (width / 8); + case 2: + return (width / 4); + case 4: + return (width / 2); + case 8: + return (width); + case 15: + case 16: + return (width * 2); + case 24: + case 32: + return (width * 4); + } + + len = vesa_bios_get_line_length(); + + return (len > 0 ? len : width); +} + +static int vesa_bios_init(void) { static struct vesa_info buf; struct vesa_mode vmode; video_info_t *p; + x86regs_t regs; + size_t bsize; + int offs; u_char *vmbuf; int is_via_cle266; int modes; @@ -678,16 +707,17 @@ vesa_bios_init(void) vesa_vmode_max = 0; vesa_vmode[0].vi_mode = EOT; - vmbuf = (emumem + REALOFF(2)); + vmbuf = (u_char *)x86bios_alloc(1, &offs); bcopy("VBE2", vmbuf, 4); /* try for VBE2 data */ - vesa_emu.x86.R_EAX = 0x4f00; - vesa_emu.x86.R_ES = SEG_ADDR(REALOFF(2)); - vesa_emu.x86.R_DI = SEG_OFF(REALOFF(2)); + bzero(®s, sizeof(regs)); + regs.R_EAX = 0x4f00; + regs.R_ES = SEG_ADDR(offs); + regs.R_DI = SEG_OFF(offs); - x86emu_exec_intr(&vesa_emu, 0x10); + x86bios_intr(®s, 0x10); - if (((vesa_emu.x86.R_AX & 0xff) != 0x4f) || bcmp("VESA", vmbuf, 4)) + if (((regs.R_AX & 0xff) != 0x4f) || bcmp("VESA", vmbuf, 4)) return 1; bcopy(vmbuf, &buf, sizeof(buf)); @@ -707,17 +737,17 @@ vesa_bios_init(void) return 1; } - vesa_oemstr = (char *)(emumem + L_ADD(vesa_adp_info->v_oemstr)); + vesa_oemstr = (char *)x86bios_offset(FARP(vesa_adp_info->v_oemstr)); is_via_cle266 = strcmp(vesa_oemstr, VESA_VIA_CLE266) == 0; if (vesa_adp_info->v_version >= 0x0200) { - vesa_venderstr = (char *)(emumem+L_ADD(vesa_adp_info->v_venderstr)); - vesa_prodstr = (char *)(emumem+L_ADD(vesa_adp_info->v_prodstr)); - vesa_revstr = (char *)(emumem+L_ADD(vesa_adp_info->v_revstr)); + vesa_venderstr = (char *)x86bios_offset(FARP(vesa_adp_info->v_venderstr)); + vesa_prodstr = (char *)x86bios_offset(FARP(vesa_adp_info->v_prodstr)); + vesa_revstr = (char *)x86bios_offset(FARP(vesa_adp_info->v_revstr)); } - vesa_vmodetab = (u_int16_t *)(emumem+L_ADD(vesa_adp_info->v_modetable)); + vesa_vmodetab = (uint16_t *)x86bios_offset(FARP(vesa_adp_info->v_modetable)); if (vesa_vmodetab == NULL) return 1; @@ -802,7 +832,7 @@ vesa_bios_init(void) - vmode.v_lfb; else vesa_vmode[modes].vi_buffer_size - = vmode.v_offscreen + vmode.v_offscreensize*1024 + = vmode.v_offscreen + vmode.v_offscreensize * 1024; #endif vesa_vmode[modes].vi_mem_model = vesa_translate_mmodel(vmode.v_memmodel); @@ -840,9 +870,26 @@ vesa_bios_init(void) vesa_vmode[modes].vi_flags = vesa_translate_flags(vmode.v_modeattr) | V_INFO_VESA; + + /* Does it have enough memory to support this mode? */ + bsize = vesa_get_line_width(&vesa_vmode[modes]); + bsize *= vesa_vmode[modes].vi_height; + if (bsize > vesa_vmode[modes].vi_buffer_size) { +#if VESA_DEBUG > 1 + printf( + "Rejecting VESA %s mode: %d x %d x %d bpp attr = %x, not enough memory\n", + (vmode.v_modeattr & V_MODEGRAPHICS) != 0 ? "graphics" : "text", + vmode.v_width, vmode.v_height, vmode.v_bpp, vmode.v_modeattr); +#endif + continue; + } + ++modes; } vesa_vmode[modes].vi_mode = EOT; + + x86bios_free(vmbuf, 1); + if (bootverbose) printf("VESA: %d mode(s) found\n", modes); @@ -870,7 +917,8 @@ vesa_map_buffer(u_int paddr, size_t size) u_int off; off = paddr - trunc_page(paddr); - vaddr = (vm_offset_t)pmap_mapdev(paddr - off, size + off); + vaddr = (vm_offset_t)pmap_mapdev_attr(paddr - off, size + off, + PAT_WRITE_COMBINING); #if VESA_DEBUG > 1 printf("vesa_map_buffer: paddr:%x vaddr:%tx size:%zx off:%x\n", paddr, vaddr, size, off); @@ -1048,7 +1096,6 @@ static int vesa_set_mode(video_adapter_t *adp, int mode) { video_info_t info; - int len; if (adp != vesa_adp) return (*prevvidsw->set_mode)(adp, mode); @@ -1126,46 +1173,17 @@ vesa_set_mode(video_adapter_t *adp, int mode) } else { vesa_adp->va_buffer = 0; vesa_adp->va_buffer_size = info.vi_buffer_size; - vesa_adp->va_window = (vm_offset_t)(emumem+L_ADD(info.vi_window)); + vesa_adp->va_window = BIOS_PADDRTOVADDR(info.vi_window); vesa_adp->va_window_size = info.vi_window_size; vesa_adp->va_window_gran = info.vi_window_gran; } vesa_adp->va_window_orig = 0; - len = vesa_bios_get_line_length(); - if (len > 0) { - vesa_adp->va_line_width = len; - } else if (info.vi_flags & V_INFO_GRAPHICS) { - switch (info.vi_depth/info.vi_planes) { - case 1: - vesa_adp->va_line_width = info.vi_width/8; - break; - case 2: - vesa_adp->va_line_width = info.vi_width/4; - break; - case 4: - vesa_adp->va_line_width = info.vi_width/2; - break; - case 8: - default: /* shouldn't happen */ - vesa_adp->va_line_width = info.vi_width; - break; - case 15: - case 16: - vesa_adp->va_line_width = info.vi_width*2; - break; - case 24: - case 32: - vesa_adp->va_line_width = info.vi_width*4; - break; - } - } else { - vesa_adp->va_line_width = info.vi_width; - } + vesa_adp->va_line_width = vesa_get_line_width(&info); vesa_adp->va_disp_start.x = 0; vesa_adp->va_disp_start.y = 0; #if VESA_DEBUG > 0 - printf("vesa_set_mode(): vi_width:%d, len:%d, line_width:%d\n", - info.vi_width, len, vesa_adp->va_line_width); + printf("vesa_set_mode(): vi_width:%d, line_width:%d\n", + info.vi_width, vesa_adp->va_line_width); #endif bcopy(&info, &vesa_adp->va_info, sizeof(vesa_adp->va_info)); @@ -1275,14 +1293,17 @@ vesa_load_state(video_adapter_t *adp, void *p) static int vesa_get_origin(video_adapter_t *adp, off_t *offset) { - vesa_emu.x86.R_EAX = 0x4f05; - vesa_emu.x86.R_EBX = 0x10; + x86regs_t regs; + + bzero(®s, sizeof(regs)); + regs.R_EAX = 0x4f05; + regs.R_EBX = 0x10; - x86emu_exec_intr(&vesa_emu, 0x10); + x86bios_intr(®s, 0x10); - if ((vesa_emu.x86.R_AX & 0xff) != 0x4f) + if ((regs.R_AX & 0xff) != 0x4f) return 1; - *offset = vesa_emu.x86.DX*adp->va_window_gran; + *offset = regs.DX * adp->va_window_gran; return 0; } @@ -1291,6 +1312,8 @@ vesa_get_origin(video_adapter_t *adp, off_t *offset) static int vesa_set_origin(video_adapter_t *adp, off_t offset) { + x86regs_t regs; + /* * This function should return as quickly as possible to * maintain good performance of the system. For this reason, @@ -1307,18 +1330,20 @@ vesa_set_origin(video_adapter_t *adp, off_t offset) if (adp->va_window_gran == 0) return 1; - vesa_emu.x86.R_EAX = 0x4f05; - vesa_emu.x86.R_EBX = 0; - vesa_emu.x86.R_EDX = offset/adp->va_window_gran; - x86emu_exec_intr(&vesa_emu, 0x10); + bzero(®s, sizeof(regs)); + regs.R_EAX = 0x4f05; + regs.R_EBX = 0; + regs.R_EDX = offset / adp->va_window_gran; + x86bios_intr(®s, 0x10); - if ((vesa_emu.x86.R_AX & 0xff) != 0x4f) + if ((regs.R_AX & 0xff) != 0x4f) return 1; - vesa_emu.x86.R_EAX = 0x4f05; - vesa_emu.x86.R_EBX = 1; - vesa_emu.x86.R_EDX = offset/adp->va_window_gran; - x86emu_exec_intr(&vesa_emu, 0x10); + bzero(®s, sizeof(regs)); + regs.R_EAX = 0x4f05; + regs.R_EBX = 1; + regs.R_EDX = offset / adp->va_window_gran; + x86bios_intr(®s, 0x10); adp->va_window_orig = (offset/adp->va_window_gran)*adp->va_window_gran; return 0; /* XXX */ @@ -1653,22 +1678,6 @@ vesa_load(void) if (vesa_init_done) return 0; - /* Can `emumem' be NULL here? */ - emumem = pmap_mapbios(0x0, 0xc00000); - - memset(&vesa_emu, 0, sizeof(vesa_emu)); - x86emu_init_default(&vesa_emu); - - vesa_emu.emu_inb = vm86_emu_inb; - vesa_emu.emu_inw = vm86_emu_inw; - vesa_emu.emu_inl = vm86_emu_inl; - vesa_emu.emu_outb = vm86_emu_outb; - vesa_emu.emu_outw = vm86_emu_outw; - vesa_emu.emu_outl = vm86_emu_outl; - - vesa_emu.mem_base = (char *)emumem; - vesa_emu.mem_size = 1024 * 1024; - /* locate a VGA adapter */ s = spltty(); vesa_adp = NULL; @@ -1716,9 +1725,6 @@ vesa_unload(void) } splx(s); - if (emumem) - pmap_unmapdev((vm_offset_t)emumem, 0xc00000); - return error; } @@ -1743,6 +1749,6 @@ static moduledata_t vesa_mod = { }; DECLARE_MODULE(vesa, vesa_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); -MODULE_DEPEND(vesa, x86emu, 1, 1, 1); +MODULE_DEPEND(vesa, x86bios, 1, 1, 1); #endif /* VGA_NO_MODE_CHANGE */ diff --git a/sys/dev/hwpmc/pmc_events.h b/sys/dev/hwpmc/pmc_events.h index e7bc3497af20..45ebc21dd5dc 100644 --- a/sys/dev/hwpmc/pmc_events.h +++ b/sys/dev/hwpmc/pmc_events.h @@ -1979,6 +1979,30 @@ __PMC_EV_ALIAS("SIMD_INT_64.SHUFFLE_MOVE", IAP_EVENT_FDH_40H) #define PMC_EV_TSC_FIRST PMC_EV_TSC_TSC #define PMC_EV_TSC_LAST PMC_EV_TSC_TSC + +/* + * Intel XScale events from "Intel XScale Core Developer's Manual", + * January 2004, #27347302 + */ +#define __PMC_EV_XSCALE() \ + __PMC_EV(XSCALE, IC_FETCH) \ + __PMC_EV(XSCALE, IC_MISS) \ + __PMC_EV(XSCALE, DATA_DEPENDENCY_STALL) \ + __PMC_EV(XSCALE, ITLB_MISS) \ + __PMC_EV(XSCALE, DTLB_MISS) \ + __PMC_EV(XSCALE, BRANCH_EXECUTED) \ + __PMC_EV(XSCALE, BRANCH_MISPRED) \ + __PMC_EV(XSCALE, INSTR_EXECUTED) \ + __PMC_EV(XSCALE, DC_FULL_CYCLE) \ + __PMC_EV(XSCALE, DC_FULL_CONTIG) \ + __PMC_EV(XSCALE, DC_ACCESS) \ + __PMC_EV(XSCALE, DC_MISS) \ + __PMC_EV(XSCALE, DC_WRITEBACK) \ + __PMC_EV(XSCALE, PC_CHANGE) + +#define PMC_EV_XSCALE_FIRST PMC_EV_XSCALE_IC_FETCH +#define PMC_EV_XSCALE_LAST PMC_EV_XSCALE_PC_CHANGE + /* * All known PMC events. * @@ -1996,6 +2020,7 @@ __PMC_EV_ALIAS("SIMD_INT_64.SHUFFLE_MOVE", IAP_EVENT_FDH_40H) * 0x11000 0x0080 INTEL Pentium 4 events * 0x11080 0x0080 INTEL Pentium MMX events * 0x11100 0x0100 INTEL Pentium Pro/P-II/P-III/Pentium-M events + * 0x11200 0x00FF INTEL XScale events */ #define __PMC_EVENTS() \ __PMC_EV_BLOCK(TSC, 0x01000) \ @@ -2013,9 +2038,11 @@ __PMC_EV_ALIAS("SIMD_INT_64.SHUFFLE_MOVE", IAP_EVENT_FDH_40H) __PMC_EV_BLOCK(P5, 0x11080) \ __PMC_EV_P5() \ __PMC_EV_BLOCK(P6, 0x11100) \ - __PMC_EV_P6() + __PMC_EV_P6() \ + __PMC_EV_BLOCK(XSCALE, 0x11200) \ + __PMC_EV_XSCALE() #define PMC_EVENT_FIRST PMC_EV_TSC_TSC -#define PMC_EVENT_LAST PMC_EV_P6_LAST +#define PMC_EVENT_LAST PMC_EV_XSCALE_LAST #endif /* _DEV_HWPMC_PMC_EVENTS_H_ */ diff --git a/sys/dev/if_ndis/if_ndis.c b/sys/dev/if_ndis/if_ndis.c index cd2397203999..b153e651472b 100644 --- a/sys/dev/if_ndis/if_ndis.c +++ b/sys/dev/if_ndis/if_ndis.c @@ -1012,7 +1012,12 @@ static void ndis_vap_delete(struct ieee80211vap *vap) { struct ndis_vap *nvp = NDIS_VAP(vap); + struct ieee80211com *ic = vap->iv_ic; + struct ifnet *ifp = ic->ic_ifp; + struct ndis_softc *sc = ifp->if_softc; + ndis_stop(sc); + callout_drain(&sc->ndis_scan_callout); ieee80211_vap_detach(vap); free(nvp, M_80211_VAP); } diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index 50c124953211..d13e208b1825 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -63,7 +63,6 @@ __FBSDID("$FreeBSD$"); /* * General defines */ - #define MBOX_DELAY_COUNT 1000000 / 100 #define ISP_MARK_PORTDB(a, b, c) \ isp_prt(isp, ISP_LOGSANCFG, \ @@ -1547,24 +1546,18 @@ isp_fibre_init(ispsoftc_t *isp) } icbp->icb_maxfrmlen = DEFAULT_FRAMESIZE(isp); - if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN || - icbp->icb_maxfrmlen > ICB_MAX_FRMLEN) { - isp_prt(isp, ISP_LOGERR, - "bad frame length (%d) from NVRAM- using %d", - DEFAULT_FRAMESIZE(isp), ICB_DFLT_FRMLEN); + if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN || icbp->icb_maxfrmlen > ICB_MAX_FRMLEN) { + isp_prt(isp, ISP_LOGERR, "bad frame length (%d) from NVRAM- using %d", DEFAULT_FRAMESIZE(isp), ICB_DFLT_FRMLEN); icbp->icb_maxfrmlen = ICB_DFLT_FRMLEN; } icbp->icb_maxalloc = fcp->isp_maxalloc; if (icbp->icb_maxalloc < 1) { - isp_prt(isp, ISP_LOGERR, - "bad maximum allocation (%d)- using 16", fcp->isp_maxalloc); + isp_prt(isp, ISP_LOGERR, "bad maximum allocation (%d)- using 16", fcp->isp_maxalloc); icbp->icb_maxalloc = 16; } icbp->icb_execthrottle = DEFAULT_EXEC_THROTTLE(isp); if (icbp->icb_execthrottle < 1) { - isp_prt(isp, ISP_LOGERR, - "bad execution throttle of %d- using %d", - DEFAULT_EXEC_THROTTLE(isp), ICB_DFLT_THROTTLE); + isp_prt(isp, ISP_LOGERR, "bad execution throttle of %d- using %d", DEFAULT_EXEC_THROTTLE(isp), ICB_DFLT_THROTTLE); icbp->icb_execthrottle = ICB_DFLT_THROTTLE; } icbp->icb_retry_delay = fcp->isp_retry_delay; @@ -1658,18 +1651,18 @@ isp_fibre_init(ispsoftc_t *isp) /* * For 22XX > 2.1.26 && 23XX, set some options. - * XXX: Probably okay for newer 2100 f/w too. */ if (ISP_FW_NEWER_THAN(isp, 2, 26, 0)) { - /* - * Turn on LIP F8 async event (1) - * Turn on generate AE 8013 on all LIP Resets (2) - * Disable LIP F7 switching (8) - */ MBSINIT(&mbs, MBOX_SET_FIRMWARE_OPTIONS, MBLOGALL, 0); - mbs.param[1] = 0xb; + mbs.param[1] = IFCOPT1_DISF7SWTCH|IFCOPT1_LIPASYNC|IFCOPT1_LIPF8; mbs.param[2] = 0; mbs.param[3] = 0; + if (ISP_FW_NEWER_THAN(isp, 3, 16, 0)) { + mbs.param[1] |= IFCOPT1_EQFQASYNC|IFCOPT1_CTIO_RETRY; + if (fcp->role & ISP_ROLE_TARGET) { + mbs.param[3] = IFCOPT3_NOPRLI; + } + } isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { return; @@ -2093,8 +2086,7 @@ isp_mark_portdb(ispsoftc_t *isp, int chan, int disposition) * or via FABRIC LOGIN/FABRIC LOGOUT for other cards. */ static int -isp_plogx(ispsoftc_t *isp, int chan, uint16_t handle, uint32_t portid, - int flags, int gs) +isp_plogx(ispsoftc_t *isp, int chan, uint16_t handle, uint32_t portid, int flags, int gs) { mbreg_t mbs; uint8_t q[QENTRY_LEN]; @@ -2771,15 +2763,21 @@ isp_pdb_sync(ispsoftc_t *isp, int chan) /* * Make sure we're okay for doing this right now. */ - if (fcp->isp_loopstate != LOOP_PDB_RCVD && fcp->isp_loopstate != LOOP_FSCAN_DONE && fcp->isp_loopstate != LOOP_LSCAN_DONE) { - isp_prt(isp, ISP_LOGWARN, "isp_pdb_sync: bad loopstate %d", fcp->isp_loopstate); + if (fcp->isp_loopstate != LOOP_PDB_RCVD && + fcp->isp_loopstate != LOOP_FSCAN_DONE && + fcp->isp_loopstate != LOOP_LSCAN_DONE) { + isp_prt(isp, ISP_LOGWARN, "isp_pdb_sync: bad loopstate %d", + fcp->isp_loopstate); return (-1); } - if (fcp->isp_topo == TOPO_FL_PORT || fcp->isp_topo == TOPO_NL_PORT || fcp->isp_topo == TOPO_N_PORT) { + if (fcp->isp_topo == TOPO_FL_PORT || + fcp->isp_topo == TOPO_NL_PORT || + fcp->isp_topo == TOPO_N_PORT) { if (fcp->isp_loopstate < LOOP_LSCAN_DONE) { if (isp_scan_loop(isp, chan) != 0) { - isp_prt(isp, ISP_LOGWARN, "isp_pdb_sync: isp_scan_loop failed"); + isp_prt(isp, ISP_LOGWARN, + "isp_pdb_sync: isp_scan_loop failed"); return (-1); } } @@ -2788,13 +2786,15 @@ isp_pdb_sync(ispsoftc_t *isp, int chan) if (fcp->isp_topo == TOPO_F_PORT || fcp->isp_topo == TOPO_FL_PORT) { if (fcp->isp_loopstate < LOOP_FSCAN_DONE) { if (isp_scan_fabric(isp, chan) != 0) { - isp_prt(isp, ISP_LOGWARN, "isp_pdb_sync: isp_scan_fabric failed"); + isp_prt(isp, ISP_LOGWARN, + "isp_pdb_sync: isp_scan_fabric failed"); return (-1); } } } - isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Chan %d Synchronizing PDBs", chan); + isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, + "Chan %d Synchronizing PDBs", chan); fcp->isp_loopstate = LOOP_SYNCING_PDB; @@ -2823,7 +2823,11 @@ isp_pdb_sync(ispsoftc_t *isp, int chan) lp->state = FC_PORTDB_STATE_NIL; isp_async(isp, ISPASYNC_DEV_GONE, chan, lp); if (lp->autologin == 0) { - (void) isp_plogx(isp, chan, lp->handle, lp->portid, PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT | PLOGX_FLG_FREE_NPHDL, 0); + (void) isp_plogx(isp, chan, lp->handle, + lp->portid, + PLOGX_FLG_CMD_LOGO | + PLOGX_FLG_IMPLICIT | + PLOGX_FLG_FREE_NPHDL, 0); } else { lp->autologin = 0; } @@ -3069,7 +3073,8 @@ isp_scan_loop(ispsoftc_t *isp, int chan) for (i = 0; i < MAX_FC_TARG; i++) { lp = &fcp->portdb[i]; - if (lp->state == FC_PORTDB_STATE_NIL || lp->target_mode) { + if (lp->state == FC_PORTDB_STATE_NIL || + lp->target_mode) { continue; } if (lp->node_wwn != tmp.node_wwn) { @@ -3587,7 +3592,8 @@ isp_scan_fabric(ispsoftc_t *isp, int chan) for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) { lp = &fcp->portdb[dbidx]; - if (lp->state != FC_PORTDB_STATE_PROBATIONAL || lp->target_mode) { + if (lp->state != FC_PORTDB_STATE_PROBATIONAL || + lp->target_mode) { continue; } if (lp->portid == portid) { @@ -3824,7 +3830,8 @@ isp_scan_fabric(ispsoftc_t *isp, int chan) if (fcp->portdb[dbidx].target_mode) { continue; } - if (fcp->portdb[dbidx].node_wwn == wwnn && fcp->portdb[dbidx].port_wwn == wwpn) { + if (fcp->portdb[dbidx].node_wwn == wwnn && + fcp->portdb[dbidx].port_wwn == wwpn) { break; } } diff --git a/sys/dev/isp/isp_stds.h b/sys/dev/isp/isp_stds.h index d0a98121a377..2ed66cb5f37d 100644 --- a/sys/dev/isp/isp_stds.h +++ b/sys/dev/isp/isp_stds.h @@ -31,7 +31,6 @@ */ #ifndef _ISP_STDS_H #define _ISP_STDS_H - /* * FC Frame Header * @@ -147,6 +146,7 @@ typedef struct { #define FCP_SNSLEN_VALID 0x02 #define FCP_RSPLEN_VALID 0x01 +#define FCP_MAX_RSPLEN 0x08 /* * FCP Response Code Definitions * Source: NCITS T10, Project 1144D, Revision 08 (aka FCP2r08) @@ -159,6 +159,8 @@ typedef struct { #define FCP_RSPNS_EROFS 3 #define FCP_RSPNS_TMF_REJECT 4 #define FCP_RSPNS_TMF_FAILED 5 +#define FCP_RSPNS_TMF_SUCCEEDED 8 +#define FCP_RSPNS_TMF_INCORRECT_LUN 9 /* unconverted miscellany */ diff --git a/sys/dev/isp/isp_tpublic.h b/sys/dev/isp/isp_tpublic.h deleted file mode 100644 index b16440b0748e..000000000000 --- a/sys/dev/isp/isp_tpublic.h +++ /dev/null @@ -1,428 +0,0 @@ -/* $FreeBSD$ */ -/*- - * Copyright (c) 1997-2007 by Matthew Jacob - * 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. - */ -/* - * Host Adapter Public Target Interface Structures && Routines - */ - -#ifndef _ISP_TPUBLIC_H -#define _ISP_TPUBLIC_H 1 - -/* - * Action codes set by the MD target driver for - * the external layer to figure out what to do with. - */ -typedef enum { - QOUT_HBA_REG=0, /* the argument is a pointer to a hba_register_t */ - QOUT_ENABLE, /* the argument is a pointer to a enadis_t */ - QOUT_DISABLE, /* the argument is a pointer to a enadis_t */ - QOUT_TMD_START, /* the argument is a pointer to a tmd_cmd_t */ - QOUT_TMD_DONE, /* the argument is a pointer to a tmd_cmd_t */ - QOUT_NOTIFY, /* the argument is a pointer to a tmd_notify_t */ - QOUT_HBA_UNREG /* the argument is a pointer to a hba_register_t */ -} tact_e; - -/* - * Action codes set by the external layer for the - * MD driver to figure out what to do with. - */ -typedef enum { - QIN_HBA_REG=99, /* the argument is a pointer to a hba_register_t */ - QIN_GETINFO, /* the argument is a pointer to a info_t */ - QIN_SETINFO, /* the argument is a pointer to a info_t */ - QIN_GETDLIST, /* the argument is a pointer to a fc_dlist_t */ - QIN_ENABLE, /* the argument is a pointer to a enadis_t */ - QIN_DISABLE, /* the argument is a pointer to a enadis_t */ - QIN_TMD_CONT, /* the argument is a pointer to a tmd_cmd_t */ - QIN_TMD_FIN, /* the argument is a pointer to a tmd_cmd_t */ - QIN_NOTIFY_ACK, /* the argument is a pointer to a tmd_notify_t */ - QIN_HBA_UNREG, /* the argument is a pointer to a hba_register_t */ -} qact_e; - -/* - * This structure is used to register to other software modules the - * binding of an HBA identifier, driver name and instance and the - * lun width capapbilities of this target driver. It's up to each - * platform to figure out how it wants to do this, but a typical - * sequence would be for the MD layer to find some external module's - * entry point and start by sending a QOUT_HBA_REG with info filled - * in, and the external module to call back with a QIN_HBA_REG that - * passes back the corresponding information. - */ -#define QR_VERSION 16 -typedef struct { - /* NB: tags from here to r_version must never change */ - void * r_identity; - void (*r_action)(qact_e, void *); - char r_name[8]; - int r_inst; - int r_version; - uint32_t r_locator; - uint32_t r_nchannels; - enum { R_FC, R_SPI } r_type; - void * r_private; -} hba_register_t; - -/* - * An information structure that is used to get or set per-channel transport layer parameters. - */ -typedef struct { - void * i_identity; - enum { I_FC, I_SPI } i_type; - int i_channel; - int i_error; - union { - struct { - uint64_t wwnn_nvram; - uint64_t wwpn_nvram; - uint64_t wwnn; - uint64_t wwpn; - } fc; - struct { - int iid; - } spi; - } i_id; -} info_t; - -/* - * An information structure to return a list of logged in WWPNs. FC specific. - */ -typedef struct { - void * d_identity; - int d_channel; - int d_error; - int d_count; - uint64_t * d_wwpns; -} fc_dlist_t; -/* - * Notify structure - */ -typedef enum { - NT_ABORT_TASK=0x1000, - NT_ABORT_TASK_SET, - NT_CLEAR_ACA, - NT_CLEAR_TASK_SET, - NT_LUN_RESET, - NT_TARGET_RESET, - NT_BUS_RESET, - NT_LIP_RESET, - NT_LINK_UP, - NT_LINK_DOWN, - NT_LOGOUT, - NT_HBA_RESET -} tmd_ncode_t; - -typedef struct tmd_notify { - void * nt_hba; /* HBA tag */ - uint64_t nt_iid; /* inititator id */ - uint64_t nt_tgt; /* target id */ - uint16_t nt_lun; /* logical unit */ - uint16_t : 15, - nt_need_ack : 1; /* this notify needs an ACK */ - uint64_t nt_tagval; /* tag value */ - uint32_t nt_channel; /* channel id */ - tmd_ncode_t nt_ncode; /* action */ - void * nt_lreserved; - void * nt_hreserved; -} tmd_notify_t; -#define LUN_ANY 0xffff -#define TGT_ANY ((uint64_t) -1) -#define INI_ANY ((uint64_t) -1) -#define TAG_ANY ((uint64_t) 0) -#define MATCH_TMD(tmd, iid, lun, tag) \ - ( \ - (tmd) && \ - (iid == INI_ANY || iid == tmd->cd_iid) && \ - (lun == LUN_ANY || lun == tmd->cd_lun) && \ - (tag == TAG_ANY || tag == tmd->cd_tagval) \ - ) - -/* - * A word about ENABLE/DISABLE: the argument is a pointer to a enadis_t - * with en_hba, en_iid, en_chan, en_tgt and en_lun filled out. - * - * If an error occurs in either enabling or disabling the described lun - * cd_error is set with an appropriate non-zero value. - */ -typedef struct { - void * en_private; /* for outer layer usage */ - void * en_hba; /* HBA tag */ - uint64_t en_iid; /* initiator ID */ - uint64_t en_tgt; /* target id */ - uint16_t en_lun; /* logical unit */ - uint16_t en_chan; /* channel on card */ - int en_error; -} enadis_t; - -/* - * Suggested Software Target Mode Command Handling structure. - * - * A note about terminology: - * - * MD stands for "Machine Dependent". - * - * This driver is structured in three layers: Outer MD, core, and inner MD. - * The latter also is bus dependent (i.e., is cognizant of PCI bus issues - * as well as platform issues). - * - * - * "Outer Layer" means "Other Module" - * - * Some additional module that actually implements SCSI target command - * policy is the recipient of incoming commands and the source of the - * disposition for them. - * - * The command structure below is one suggested possible MD command structure, - * but since the handling of thbis is entirely in the MD layer, there is - * no explicit or implicit requirement that it be used. - * - * The cd_private tag should be used by the MD layer to keep a free list - * of these structures. Code outside of this driver can then use this - * to identify it's own unit structures. That is, when not on the MD - * layer's freelist, the MD layer should shove into it the identifier - * that the outer layer has for it- passed in on an initial QIN_HBA_REG - * call (see below). - * - * The cd_hba tag is a tag that uniquely identifies the HBA this target - * mode command is coming from. The outer layer has to pass this back - * unchanged to avoid chaos. - * - * The cd_iid, cd_tgt, cd_lun and cd_port tags are used to identify the - * id of the initiator who sent us a command, the target claim to be, the - * lun on the target we claim to be, and the port instance (for multiple - * port host adapters) that this applies to (consider it an extra port - * parameter). The iid, tgt and lun values are deliberately chosen to be - * fat so that, for example, World Wide Names can be used instead of - * the units that the firmware uses (in the case where the MD - * layer maintains a port database, for example). - * - * The cd_tagtype field specifies what kind of command tag type, if - * any, has been sent with the command. Note that the Outer Layer - * still needs to pass the tag handle through unchanged even - * if the tag type is CD_UNTAGGED. - * - * The cd_cdb contains storage for the passed in command descriptor block. - * There is no need to define length as the callee should be able to - * figure this out. - * - * The tag cd_lflags are the flags set by the MD driver when it gets - * command incoming or when it needs to inform any outside entities - * that the last requested action failed. - * - * The tag cd_hflags should be set by any outside software to indicate - * the validity of sense and status fields (defined below) and to indicate - * the direction data is expected to move. It is an error to have both - * CDFH_DATA_IN and CDFH_DATA_OUT set. - * - * If the CDFH_STSVALID flag is set, the command should be completed (after - * sending any data and/or status). If CDFH_SNSVALID is set and the MD layer - * can also handle sending the associated sense data (either back with an - * FCP RESPONSE IU for Fibre Channel or otherwise automatically handling a - * REQUEST SENSE from the initator for this target/lun), the MD layer will - * set the CDFL_SENTSENSE flag on successful transmission of the sense data. - * It is an error for the CDFH_SNSVALID bit to be set and CDFH_STSVALID not - * to be set. It is an error for the CDFH_SNSVALID be set and the associated - * SCSI status (cd_scsi_status) not be set to CHECK CONDITON. - * - * The tag cd_data points to a data segment to either be filled or - * read from depending on the direction of data movement. The tag - * is undefined if no data direction is set. The MD layer and outer - * layers must agree on the meaning of cd_data and it is specifically - * not defined here. - * - * The tag cd_totlen is the total data amount expected to be moved - * over the life of the command. It may be set by the MD layer, possibly - * from the datalen field of an FCP CMND IU unit. If it shows up in the outer - * layers set to zero and the CDB indicates data should be moved, the outer - * layer should set it to the amount expected to be moved. - * - * The tag cd_resid should be the total residual of data not transferred. - * The outer layers need to set this at the begining of command processing - * to equal cd_totlen. As data is successfully moved, this value is decreased. - * At the end of a command, any nonzero residual indicates the number of bytes - * requested by the command but not moved. - * - * The tag cd_xfrlen is the length of the currently active data transfer. - * This allows several interations between any outside software and the - * MD layer to move data. - * - * The reason that total length and total residual have to be tracked - * is to keep track of relative offset. - * - * The tags cd_sense and cd_scsi_status are pretty obvious. - * - * The tag cd_error is to communicate between the MD layer and outer software - * the current error conditions. - * - * The tag cd_lreserved, cd_hreserved are scratch areas for use for the MD - * and outer layers respectively. - * - */ - -#ifndef TMD_CDBLEN -#define TMD_CDBLEN 16 -#endif -#ifndef TMD_SENSELEN -#define TMD_SENSELEN 18 -#endif -#ifndef QCDS -#define QCDS (sizeof (void *)) -#endif - -typedef struct tmd_cmd { - void * cd_private; /* private data pointer */ - void * cd_hba; /* HBA tag */ - void * cd_data; /* 'pointer' to data */ - uint64_t cd_iid; /* initiator ID */ - uint64_t cd_tgt; /* target id */ - uint8_t cd_lun[8]; /* logical unit */ - uint64_t cd_tagval; /* tag value */ - uint32_t cd_channel; /* channel index */ - uint32_t cd_lflags; /* flags lower level sets */ - uint32_t cd_hflags; /* flags higher level sets */ - uint32_t cd_totlen; /* total data load */ - uint32_t cd_resid; /* total data residual */ - uint32_t cd_xfrlen; /* current data load */ - int32_t cd_error; /* current error */ - uint8_t cd_tagtype; /* tag type */ - uint8_t cd_scsi_status; - uint8_t cd_sense[TMD_SENSELEN]; - uint8_t cd_cdb[TMD_CDBLEN]; - union { - void * ptrs[QCDS / sizeof (void *)]; - uint64_t llongs[QCDS / sizeof (uint64_t)]; - uint32_t longs[QCDS / sizeof (uint32_t)]; - uint16_t shorts[QCDS / sizeof (uint16_t)]; - uint8_t bytes[QCDS]; - } cd_lreserved[4], cd_hreserved[4]; -} tmd_cmd_t; - -/* defined tags */ -#define CD_UNTAGGED 0 -#define CD_SIMPLE_TAG 1 -#define CD_ORDERED_TAG 2 -#define CD_HEAD_TAG 3 -#define CD_ACA_TAG 4 - -#ifndef TMD_SIZE -#define TMD_SIZE (sizeof (tmd_cmd_t)) -#endif - -#define L0LUN_TO_FLATLUN(lptr) ((((lptr)[0] & 0x3f) << 8) | ((lptr)[1])) -#define FLATLUN_TO_L0LUN(lptr, lun) \ - (lptr)[1] = lun & 0xff; \ - if (sizeof (lun) == 1) { \ - (lptr)[0] = 0; \ - } else { \ - uint16_t nl = lun; \ - if (nl == LUN_ANY) { \ - (lptr)[0] = (nl >> 8) & 0xff; \ - } else if (nl < 256) { \ - (lptr)[0] = 0; \ - } else { \ - (lptr)[0] = 0x40 | ((nl >> 8) & 0x3f); \ - } \ - } \ - memset(&(lptr)[2], 0, 6) - -/* - * Note that NODISC (obviously) doesn't apply to non-SPI transport. - * - * Note that knowing the data direction and lengh at the time of receipt of - * a command from the initiator is a feature only of Fibre Channel. - * - * The CDFL_BIDIR is in anticipation of the adoption of some newer - * features required by OSD. - * - * The principle selector for MD layer to know whether data is to - * be transferred in any QOUT_TMD_CONT call is cd_xfrlen- the - * flags CDFH_DATA_IN and CDFH_DATA_OUT define which direction. - */ -#define CDFL_SNSVALID 0x01 /* sense data (from f/w) good */ -#define CDFL_SENTSTATUS 0x02 /* last action sent status */ -#define CDFL_DATA_IN 0x04 /* target (us) -> initiator (them) */ -#define CDFL_DATA_OUT 0x08 /* initiator (them) -> target (us) */ -#define CDFL_BIDIR 0x0C /* bidirectional data */ -#define CDFL_ERROR 0x10 /* last action ended in error */ -#define CDFL_NODISC 0x20 /* disconnects disabled */ -#define CDFL_SENTSENSE 0x40 /* last action sent sense data */ -#define CDFL_BUSY 0x80 /* this command is not on a free list */ -#define CDFL_PRIVATE 0xFF000000 /* private layer flags */ - -#define CDFH_SNSVALID 0x01 /* sense data (from outer layer) good */ -#define CDFH_STSVALID 0x02 /* status valid */ -#define CDFH_DATA_IN 0x04 /* target (us) -> initiator (them) */ -#define CDFH_DATA_OUT 0x08 /* initiator (them) -> target (us) */ -#define CDFH_DATA_MASK 0x0C /* mask to cover data direction */ -#define CDFH_PRIVATE 0xFF000000 /* private layer flags */ - - -/* - * A word about the START/CONT/DONE/FIN dance: - * - * When the HBA is enabled for receiving commands, one may show up - * without notice. When that happens, the MD target mode driver - * gets a tmd_cmd_t, fills it with the info that just arrived, and - * calls the outer layer with a QOUT_TMD_START code and pointer to - * the tmd_cmd_t. - * - * The outer layer decodes the command, fetches data, prepares stuff, - * whatever, and starts by passing back the pointer with a QIN_TMD_CONT - * code which causes the MD target mode driver to generate CTIOs to - * satisfy whatever action needs to be taken. When those CTIOs complete, - * the MD target driver sends the pointer to the cmd_tmd_t back with - * a QOUT_TMD_DONE code. This repeats for as long as necessary. These - * may not be done in parallel- they are sequential operations. - * - * The outer layer signals it wants to end the command by settings within - * the tmd_cmd_t itself. When the final QIN_TMD_CONT is reported completed, - * the outer layer frees the tmd_cmd_t by sending the pointer to it - * back with a QIN_TMD_FIN code. - * - * The graph looks like: - * - * QOUT_TMD_START -> [ QIN_TMD_CONT -> QOUT_TMD_DONE ] * -> QIN_TMD_FIN. - * - */ - -/* - * Target handler functions. - * - * The MD target handler function (the outer layer calls this) - * should be be prototyped like: - * - * void target_action(qact_e, void *arg) - * - * The outer layer target handler function (the MD layer calls this) - * should be be prototyped like: - * - * void scsi_target_handler(tact_e, void *arg) - */ -#endif /* _ISP_TPUBLIC_H */ -/* - * vim:ts=4:sw=4:expandtab - */ diff --git a/sys/dev/isp/ispmbox.h b/sys/dev/isp/ispmbox.h index 8f689379afae..2f9d152039f7 100644 --- a/sys/dev/isp/ispmbox.h +++ b/sys/dev/isp/ispmbox.h @@ -26,6 +26,7 @@ * SUCH DAMAGE. * */ + /* * Mailbox and Queue Entry Definitions for for Qlogic ISP SCSI adapters. */ @@ -245,12 +246,38 @@ #define ASYNC_RCV_ERR 0x8048 /* + * Firmware Options. There are a lot of them. + * + * IFCOPTN - ISP Fibre Channel Option Word N + */ +#define IFCOPT1_EQFQASYNC (1 << 13) /* enable QFULL notification */ +#define IFCOPT1_EAABSRCVD (1 << 12) +#define IFCOPT1_RJTASYNC (1 << 11) /* enable 8018 notification */ +#define IFCOPT1_ENAPURE (1 << 10) +#define IFCOPT1_ENA8017 (1 << 7) +#define IFCOPT1_DISGPIO67 (1 << 6) +#define IFCOPT1_LIPLOSSIMM (1 << 5) +#define IFCOPT1_DISF7SWTCH (1 << 4) +#define IFCOPT1_CTIO_RETRY (1 << 3) +#define IFCOPT1_LIPASYNC (1 << 1) +#define IFCOPT1_LIPF8 (1 << 0) + +#define IFCOPT2_LOOPBACK (1 << 1) +#define IFCOPT2_ATIO3_ONLY (1 << 0) + +#define IFCOPT3_NOPRLI (1 << 4) /* disable automatic sending of PRLI on local loops */ +#define IFCOPT3_RNDASYNC (1 << 1) +/* * 2.01.31 2200 Only. Need Bit 13 in Mailbox 1 for Set Firmware Options * mailbox command to enable this. */ #define ASYNC_QFULL_SENT 0x8049 /* + * Needs to be enabled + */ +#define ASYNC_AUTO_PLOGI_RJT 0x8018 +/* * 24XX only */ #define ASYNC_RJT_SENT 0x8049 diff --git a/sys/dev/kbd/kbd.c b/sys/dev/kbd/kbd.c index 851f6771f8b4..0813676d01df 100644 --- a/sys/dev/kbd/kbd.c +++ b/sys/dev/kbd/kbd.c @@ -728,7 +728,7 @@ genkbd_event(keyboard_t *kbd, int event, void *arg) size_t len; u_char *cp; int mode; - int c; + u_int c; /* assert(KBD_IS_VALID(kbd)) */ sc = (genkbd_softc_t *)arg; @@ -837,13 +837,14 @@ static int fkey_change_ok(fkeytab_t *, fkeyarg_t *, struct thread *); int genkbd_commonioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) { +#ifndef KBD_DISABLE_KEYMAP_LOAD + keymap_t *mapp; +#endif keyarg_t *keyp; fkeyarg_t *fkeyp; int s; int i; -#ifndef KBD_DISABLE_KEYMAP_LOAD int error; -#endif s = spltty(); switch (cmd) { @@ -869,18 +870,29 @@ genkbd_commonioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) break; case GIO_KEYMAP: /* get keyboard translation table */ - bcopy(kbd->kb_keymap, arg, sizeof(*kbd->kb_keymap)); - break; + error = copyout(kbd->kb_keymap, *(void **)arg, + sizeof(keymap_t)); + splx(s); + return (error); case PIO_KEYMAP: /* set keyboard translation table */ #ifndef KBD_DISABLE_KEYMAP_LOAD - error = keymap_change_ok(kbd->kb_keymap, (keymap_t *)arg, - curthread); + mapp = malloc(sizeof *mapp, M_TEMP, M_NOWAIT); + error = copyin(*(void **)arg, mapp, sizeof *mapp); + if (error != 0) { + splx(s); + free(mapp, M_TEMP); + return (error); + } + + error = keymap_change_ok(kbd->kb_keymap, mapp, curthread); if (error != 0) { splx(s); + free(mapp, M_TEMP); return (error); } bzero(kbd->kb_accentmap, sizeof(*kbd->kb_accentmap)); - bcopy(arg, kbd->kb_keymap, sizeof(*kbd->kb_keymap)); + bcopy(mapp, kbd->kb_keymap, sizeof(*kbd->kb_keymap)); + free(mapp, M_TEMP); break; #else splx(s); diff --git a/sys/dev/mwl/if_mwl.c b/sys/dev/mwl/if_mwl.c index 991bc792e1a3..4a1dc8ab5782 100644 --- a/sys/dev/mwl/if_mwl.c +++ b/sys/dev/mwl/if_mwl.c @@ -304,7 +304,7 @@ mwl_attach(uint16_t devid, struct mwl_softc *sc) ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); if (ifp == NULL) { - device_printf(sc->sc_dev, "can not if_alloc()\n"); + device_printf(sc->sc_dev, "cannot if_alloc()\n"); return ENOSPC; } ic = ifp->if_l2com; @@ -2303,8 +2303,10 @@ mwl_dma_setup(struct mwl_softc *sc) int error, i; error = mwl_rxdma_setup(sc); - if (error != 0) + if (error != 0) { + mwl_rxdma_cleanup(sc); return error; + } for (i = 0; i < MWL_NUM_TX_QUEUES; i++) { error = mwl_txdma_setup(sc, &sc->sc_txq[i]); diff --git a/sys/dev/mxge/if_mxge.c b/sys/dev/mxge/if_mxge.c index 88c3489ee3a7..6e8ca67eb98a 100644 --- a/sys/dev/mxge/if_mxge.c +++ b/sys/dev/mxge/if_mxge.c @@ -106,6 +106,7 @@ static int mxge_max_slices = 1; static int mxge_rss_hash_type = MXGEFW_RSS_HASH_TYPE_SRC_PORT; static int mxge_always_promisc = 0; static int mxge_initial_mtu = ETHERMTU_JUMBO; +static int mxge_throttle = 0; static char *mxge_fw_unaligned = "mxge_ethp_z8e"; static char *mxge_fw_aligned = "mxge_eth_z8e"; static char *mxge_fw_rss_aligned = "mxge_rss_eth_z8e"; @@ -143,7 +144,7 @@ MODULE_DEPEND(mxge, zlib, 1, 1, 1); static int mxge_load_firmware(mxge_softc_t *sc, int adopt); static int mxge_send_cmd(mxge_softc_t *sc, uint32_t cmd, mxge_cmd_t *data); -static int mxge_close(mxge_softc_t *sc); +static int mxge_close(mxge_softc_t *sc, int down); static int mxge_open(mxge_softc_t *sc); static void mxge_tick(void *arg); @@ -596,10 +597,13 @@ static int mxge_select_firmware(mxge_softc_t *sc) { int aligned = 0; + int force_firmware = mxge_force_firmware; + if (sc->throttle) + force_firmware = sc->throttle; - if (mxge_force_firmware != 0) { - if (mxge_force_firmware == 1) + if (force_firmware != 0) { + if (force_firmware == 1) aligned = 1; else aligned = 0; @@ -1305,8 +1309,7 @@ mxge_reset(mxge_softc_t *sc, int interrupts_setup) ss->lro_queued = 0; ss->lro_flushed = 0; if (ss->fw_stats != NULL) { - ss->fw_stats->valid = 0; - ss->fw_stats->send_done_count = 0; + bzero(ss->fw_stats, sizeof *ss->fw_stats); } } sc->rdma_tags_available = 15; @@ -1314,10 +1317,48 @@ mxge_reset(mxge_softc_t *sc, int interrupts_setup) mxge_change_promisc(sc, sc->ifp->if_flags & IFF_PROMISC); mxge_change_pause(sc, sc->pause); mxge_set_multicast_list(sc); + if (sc->throttle) { + cmd.data0 = sc->throttle; + if (mxge_send_cmd(sc, MXGEFW_CMD_SET_THROTTLE_FACTOR, + &cmd)) { + device_printf(sc->dev, + "can't enable throttle\n"); + } + } return status; } static int +mxge_change_throttle(SYSCTL_HANDLER_ARGS) +{ + mxge_cmd_t cmd; + mxge_softc_t *sc; + int err; + unsigned int throttle; + + sc = arg1; + throttle = sc->throttle; + err = sysctl_handle_int(oidp, &throttle, arg2, req); + if (err != 0) { + return err; + } + + if (throttle == sc->throttle) + return 0; + + if (throttle < MXGE_MIN_THROTTLE || throttle > MXGE_MAX_THROTTLE) + return EINVAL; + + mtx_lock(&sc->driver_mtx); + cmd.data0 = throttle; + err = mxge_send_cmd(sc, MXGEFW_CMD_SET_THROTTLE_FACTOR, &cmd); + if (err == 0) + sc->throttle = throttle; + mtx_unlock(&sc->driver_mtx); + return err; +} + +static int mxge_change_intr_coal(SYSCTL_HANDLER_ARGS) { mxge_softc_t *sc; @@ -1379,7 +1420,7 @@ mxge_change_lro_locked(mxge_softc_t *sc, int lro_cnt) ifp->if_capenable |= IFCAP_LRO; sc->lro_cnt = lro_cnt; if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - mxge_close(sc); + mxge_close(sc, 0); err = mxge_open(sc); } return err; @@ -1495,6 +1536,10 @@ mxge_add_sysctls(mxge_softc_t *sc) "read_write_dma_MBs", CTLFLAG_RD, &sc->read_write_dma, 0, "DMA concurrent Read/Write speed in MB/s"); + SYSCTL_ADD_INT(ctx, children, OID_AUTO, + "watchdog_resets", + CTLFLAG_RD, &sc->watchdog_resets, + 0, "Number of times NIC was reset"); /* performance related tunables */ @@ -1505,6 +1550,12 @@ mxge_add_sysctls(mxge_softc_t *sc) "I", "interrupt coalescing delay in usecs"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, + "throttle", + CTLTYPE_INT|CTLFLAG_RW, sc, + 0, mxge_change_throttle, + "I", "transmit throttling"); + + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "flow_control_enabled", CTLTYPE_INT|CTLFLAG_RW, sc, 0, mxge_change_flow_control, @@ -3600,7 +3651,7 @@ abort: } static int -mxge_close(mxge_softc_t *sc) +mxge_close(mxge_softc_t *sc, int down) { mxge_cmd_t cmd; int err, old_down_cnt; @@ -3617,21 +3668,23 @@ mxge_close(mxge_softc_t *sc) } #endif sc->ifp->if_drv_flags &= ~IFF_DRV_RUNNING; - old_down_cnt = sc->down_cnt; - wmb(); - err = mxge_send_cmd(sc, MXGEFW_CMD_ETHERNET_DOWN, &cmd); - if (err) { - device_printf(sc->dev, "Couldn't bring down link\n"); - } - if (old_down_cnt == sc->down_cnt) { - /* wait for down irq */ - DELAY(10 * sc->intr_coal_delay); - } - wmb(); - if (old_down_cnt == sc->down_cnt) { - device_printf(sc->dev, "never got down irq\n"); + if (!down) { + old_down_cnt = sc->down_cnt; + wmb(); + err = mxge_send_cmd(sc, MXGEFW_CMD_ETHERNET_DOWN, &cmd); + if (err) { + device_printf(sc->dev, + "Couldn't bring down link\n"); + } + if (old_down_cnt == sc->down_cnt) { + /* wait for down irq */ + DELAY(10 * sc->intr_coal_delay); + } + wmb(); + if (old_down_cnt == sc->down_cnt) { + device_printf(sc->dev, "never got down irq\n"); + } } - mxge_free_mbufs(sc); return 0; @@ -3684,8 +3737,9 @@ static int mxge_watchdog_reset(mxge_softc_t *sc, int slice) { struct pci_devinfo *dinfo; + struct mxge_slice_state *ss; mxge_tx_ring_t *tx; - int err; + int err, running, s, num_tx_slices = 1; uint32_t reboot; uint16_t cmd; @@ -3719,6 +3773,30 @@ mxge_watchdog_reset(mxge_softc_t *sc, int slice) reboot = mxge_read_reboot(sc); device_printf(sc->dev, "NIC rebooted, status = 0x%x\n", reboot); + running = sc->ifp->if_drv_flags & IFF_DRV_RUNNING; + if (running) { + + /* + * quiesce NIC so that TX routines will not try to + * xmit after restoration of BAR + */ + + /* Mark the link as down */ + if (sc->link_state) { + sc->link_state = 0; + if_link_state_change(sc->ifp, + LINK_STATE_DOWN); + } +#ifdef IFNET_BUF_RING + num_tx_slices = sc->num_slices; +#endif + /* grab all TX locks to ensure no tx */ + for (s = 0; s < num_tx_slices; s++) { + ss = &sc->ss[s]; + mtx_lock(&ss->tx.mtx); + } + mxge_close(sc, 1); + } /* restore PCI configuration space */ dinfo = device_get_ivars(sc->dev); pci_cfg_restore(sc->dev, dinfo); @@ -3726,10 +3804,22 @@ mxge_watchdog_reset(mxge_softc_t *sc, int slice) /* and redo any changes we made to our config space */ mxge_setup_cfg_space(sc); - if (sc->ifp->if_drv_flags & IFF_DRV_RUNNING) { - mxge_close(sc); - err = mxge_open(sc); + /* reload f/w */ + err = mxge_load_firmware(sc, 0); + if (err) { + device_printf(sc->dev, + "Unable to re-load f/w\n"); } + if (running) { + if (!err) + err = mxge_open(sc); + /* release all TX locks */ + for (s = 0; s < num_tx_slices; s++) { + ss = &sc->ss[s]; + mtx_unlock(&ss->tx.mtx); + } + } + sc->watchdog_resets++; } else { tx = &sc->ss[slice].tx; device_printf(sc->dev, @@ -3745,6 +3835,9 @@ mxge_watchdog_reset(mxge_softc_t *sc, int slice) be32toh(sc->ss->fw_stats->send_done_count)); device_printf(sc->dev, "not resetting\n"); } + if (err) + device_printf(sc->dev, "watchdog reset failed\n"); + return (err); } @@ -3860,11 +3953,11 @@ mxge_change_mtu(mxge_softc_t *sc, int mtu) old_mtu = ifp->if_mtu; ifp->if_mtu = mtu; if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - mxge_close(sc); + mxge_close(sc, 0); err = mxge_open(sc); if (err != 0) { ifp->if_mtu = old_mtu; - mxge_close(sc); + mxge_close(sc, 0); (void) mxge_open(sc); } } @@ -3922,7 +4015,7 @@ mxge_ioctl(struct ifnet *ifp, u_long command, caddr_t data) } } else { if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - mxge_close(sc); + mxge_close(sc, 0); } } mtx_unlock(&sc->driver_mtx); @@ -4016,6 +4109,7 @@ mxge_fetch_tunables(mxge_softc_t *sc) TUNABLE_INT_FETCH("hw.mxge.rss_hash_type", &mxge_rss_hash_type); TUNABLE_INT_FETCH("hw.mxge.rss_hashtype", &mxge_rss_hash_type); TUNABLE_INT_FETCH("hw.mxge.initial_mtu", &mxge_initial_mtu); + TUNABLE_INT_FETCH("hw.mxge.throttle", &mxge_throttle); if (sc->lro_cnt != 0) mxge_lro_cnt = sc->lro_cnt; @@ -4033,6 +4127,12 @@ mxge_fetch_tunables(mxge_softc_t *sc) if (mxge_initial_mtu > ETHERMTU_JUMBO || mxge_initial_mtu < ETHER_MIN_LEN) mxge_initial_mtu = ETHERMTU_JUMBO; + + if (mxge_throttle && mxge_throttle > MXGE_MAX_THROTTLE) + mxge_throttle = MXGE_MAX_THROTTLE; + if (mxge_throttle && mxge_throttle < MXGE_MIN_THROTTLE) + mxge_throttle = MXGE_MIN_THROTTLE; + sc->throttle = mxge_throttle; } @@ -4645,7 +4745,7 @@ mxge_detach(device_t dev) mtx_lock(&sc->driver_mtx); sc->dying = 1; if (sc->ifp->if_drv_flags & IFF_DRV_RUNNING) - mxge_close(sc); + mxge_close(sc, 0); mtx_unlock(&sc->driver_mtx); ether_ifdetach(sc->ifp); callout_drain(&sc->co_hdl); diff --git a/sys/dev/mxge/if_mxge_var.h b/sys/dev/mxge/if_mxge_var.h index 47c39b5f0193..b25adb4363cb 100644 --- a/sys/dev/mxge/if_mxge_var.h +++ b/sys/dev/mxge/if_mxge_var.h @@ -261,6 +261,7 @@ struct mxge_softc { int fw_multicast_support; int link_width; int max_mtu; + int throttle; int tx_defrag; int media_flags; int need_media_probe; @@ -286,6 +287,8 @@ struct mxge_softc { #define MXGE_PCI_REV_Z8ES 1 #define MXGE_XFP_COMPLIANCE_BYTE 131 #define MXGE_SFP_COMPLIANCE_BYTE 3 +#define MXGE_MIN_THROTTLE 416 +#define MXGE_MAX_THROTTLE 4096 #define MXGE_HIGHPART_TO_U32(X) \ (sizeof (X) == 8) ? ((uint32_t)((uint64_t)(X) >> 32)) : (0) diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index 0b7b26700c59..47aedbde0dd5 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -2149,62 +2149,38 @@ pci_disable_busmaster_method(device_t dev, device_t child) int pci_enable_io_method(device_t dev, device_t child, int space) { - uint16_t command; uint16_t bit; - char *error; - - bit = 0; - error = NULL; switch(space) { case SYS_RES_IOPORT: bit = PCIM_CMD_PORTEN; - error = "port"; break; case SYS_RES_MEMORY: bit = PCIM_CMD_MEMEN; - error = "memory"; break; default: return (EINVAL); } pci_set_command_bit(dev, child, bit); - /* Some devices seem to need a brief stall here, what do to? */ - command = PCI_READ_CONFIG(dev, child, PCIR_COMMAND, 2); - if (command & bit) - return (0); - device_printf(child, "failed to enable %s mapping!\n", error); - return (ENXIO); + return (0); } int pci_disable_io_method(device_t dev, device_t child, int space) { - uint16_t command; uint16_t bit; - char *error; - - bit = 0; - error = NULL; switch(space) { case SYS_RES_IOPORT: bit = PCIM_CMD_PORTEN; - error = "port"; break; case SYS_RES_MEMORY: bit = PCIM_CMD_MEMEN; - error = "memory"; break; default: return (EINVAL); } pci_clear_command_bit(dev, child, bit); - command = PCI_READ_CONFIG(dev, child, PCIR_COMMAND, 2); - if (command & bit) { - device_printf(child, "failed to disable %s mapping!\n", error); - return (ENXIO); - } return (0); } diff --git a/sys/dev/pci/pcireg.h b/sys/dev/pci/pcireg.h index c7a7245bf1d3..981d1e0cde4e 100644 --- a/sys/dev/pci/pcireg.h +++ b/sys/dev/pci/pcireg.h @@ -44,6 +44,7 @@ #define PCI_SLOTMAX 31 /* highest supported slot number */ #define PCI_FUNCMAX 7 /* highest supported function number */ #define PCI_REGMAX 255 /* highest supported config register addr. */ +#define PCIE_REGMAX 4095 /* highest supported config register addr. */ #define PCI_MAXHDRTYPE 2 /* PCI config header registers for all devices */ diff --git a/sys/dev/ppbus/vpo.c b/sys/dev/ppbus/vpo.c index 40091787a4f0..673a7858d4da 100644 --- a/sys/dev/ppbus/vpo.c +++ b/sys/dev/ppbus/vpo.c @@ -176,9 +176,6 @@ vpo_attach(device_t dev) return (ENXIO); } ppb_unlock(ppbus); - - /* all went ok */ - vpo_cam_rescan(vpo); /* have CAM rescan the bus */ return (0); @@ -194,12 +191,15 @@ vpo_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb) static void vpo_cam_rescan(struct vpo_data *vpo) { + device_t ppbus = device_get_parent(vpo->vpo_dev); struct cam_path *path; union ccb *ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK | M_ZERO); + ppb_lock(ppbus); if (xpt_create_path(&path, xpt_periph, cam_sim_path(vpo->sim), 0, 0) != CAM_REQ_CMP) { /* A failure is benign as the user can do a manual rescan */ + ppb_unlock(ppbus); free(ccb, M_TEMP); return; } @@ -209,6 +209,7 @@ vpo_cam_rescan(struct vpo_data *vpo) ccb->ccb_h.cbfcnp = vpo_cam_rescan_callback; ccb->crcn.flags = CAM_FLAG_NONE; xpt_action(ccb); + ppb_unlock(ppbus); /* The scan is in progress now. */ } diff --git a/sys/dev/sound/pci/es137x.c b/sys/dev/sound/pci/es137x.c index 3a62724305b1..8d04f7085d0e 100644 --- a/sys/dev/sound/pci/es137x.c +++ b/sys/dev/sound/pci/es137x.c @@ -1,10 +1,33 @@ /*- - * Support the ENSONIQ AudioPCI board and Creative Labs SoundBlaster PCI - * boards based on the ES1370, ES1371 and ES1373 chips. - * * Copyright (c) 1999 Russell Cattelan <cattelan@thebarn.com> + * Copyright (c) 1998 Joachim Kuebart <joachim.kuebart@gmx.net> + * 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. + */ + +/*- * Copyright (c) 1999 Cameron Grant <cg@freebsd.org> - * Copyright (c) 1998 by Joachim Kuebart. All rights reserved. + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -40,12 +63,14 @@ */ /* + * Support the ENSONIQ AudioPCI board and Creative Labs SoundBlaster PCI + * boards based on the ES1370, ES1371 and ES1373 chips. + * * Part of this code was heavily inspired by the linux driver from * Thomas Sailer (sailer@ife.ee.ethz.ch) * Just about everything has been touched and reworked in some way but * the all the underlying sequences/timing/register values are from * Thomas' code. - * */ #ifdef HAVE_KERNEL_OPTION_HEADERS diff --git a/sys/dev/sound/pci/es137x.h b/sys/dev/sound/pci/es137x.h index 7e0225fe8cae..fb86a94df827 100644 --- a/sys/dev/sound/pci/es137x.h +++ b/sys/dev/sound/pci/es137x.h @@ -1,26 +1,21 @@ /*- - * This supports the ENSONIQ AudioPCI board based on the ES1370. - * - * Copyright (c) 1998 Joachim Kuebart <joki@kuebart.stuttgart.netsurf.de> + * Copyright (c) 1998 Joachim Kuebart <joachim.kuebart@gmx.net> * 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 immediately at the beginning of the file, without modification, - * this list of conditions, and the following disclaimer. + * 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. Absolutely no warranty of function or purpose is made by the author - * Joachim Kuebart. - * 4. Modifications may be freely made to this file if the above conditions - * are met. * * $FreeBSD$ */ +/* This supports the ENSONIQ AudioPCI board based on the ES1370. */ + #ifndef _ES1370_REG_H #define _ES1370_REG_H diff --git a/sys/dev/sound/pci/t4dwave.c b/sys/dev/sound/pci/t4dwave.c index 086c4fe9227a..8d9c4c64e9a7 100644 --- a/sys/dev/sound/pci/t4dwave.c +++ b/sys/dev/sound/pci/t4dwave.c @@ -45,18 +45,22 @@ SND_DECLARE_FILE("$FreeBSD$"); #define SPA_PCI_ID 0x70181039 #define TR_DEFAULT_BUFSZ 0x1000 +/* For ALi M5451 the DMA transfer size appears to be fixed to 64k. */ +#define ALI_BUFSZ 0x10000 +#define TR_BUFALGN 0x8 #define TR_TIMEOUT_CDC 0xffff +#define TR_MAXHWCH 64 +#define ALI_MAXHWCH 32 #define TR_MAXPLAYCH 4 +#define ALI_MAXPLAYCH 1 /* - * Though, it's not clearly documented in trident datasheet, trident - * audio cards can't handle DMA addresses located above 1GB. The LBA - * (loop begin address) register which holds DMA base address is 32bits - * register. - * But the MSB 2bits are used for other purposes(I guess it is really - * bad idea). This effectivly limits the DMA address space up to 1GB. + * Though, it's not clearly documented in the 4DWAVE datasheet, the + * DX and NX chips can't handle DMA addresses located above 1GB as the + * LBA (loop begin address) register which holds the DMA base address + * is 32-bit, but the two MSBs are used for other purposes. */ -#define TR_MAXADDR ((1 << 30) - 1) - +#define TR_MAXADDR ((1U << 30) - 1) +#define ALI_MAXADDR ((1U << 31) - 1) struct tr_info; @@ -97,6 +101,7 @@ struct tr_info { struct mtx *lock; + u_int32_t hwchns; u_int32_t playchns; unsigned int bufsz; @@ -398,7 +403,10 @@ tr_wrch(struct tr_chinfo *ch) ch->ec &= 0x00000fff; ch->alpha &= 0x00000fff; ch->delta &= 0x0000ffff; - ch->lba &= 0x3fffffff; + if (tr->type == ALI_PCI_ID) + ch->lba &= ALI_MAXADDR; + else + ch->lba &= TR_MAXADDR; cr[1]=ch->lba; cr[3]=(ch->fmc<<14) | (ch->rvol<<7) | (ch->cvol); @@ -441,7 +449,10 @@ tr_rdch(struct tr_chinfo *ch) snd_mtxunlock(tr->lock); - ch->lba= (cr[1] & 0x3fffffff); + if (tr->type == ALI_PCI_ID) + ch->lba=(cr[1] & ALI_MAXADDR); + else + ch->lba=(cr[1] & TR_MAXADDR); ch->fmc= (cr[3] & 0x0000c000) >> 14; ch->rvol= (cr[3] & 0x00003f80) >> 7; ch->cvol= (cr[3] & 0x0000007f); @@ -628,7 +639,6 @@ trrchan_setformat(kobj_t obj, void *data, u_int32_t format) tr_wr(tr, TR_REG_SBCTRL, i, 1); return 0; - } static u_int32_t @@ -729,7 +739,7 @@ tr_intr(void *p) intsrc = tr_rd(tr, TR_REG_MISCINT, 4); if (intsrc & TR_INT_ADDR) { chnum = 0; - while (chnum < 64) { + while (chnum < tr->hwchns) { mask = 0x00000001; active = tr_rd(tr, (chnum < 32)? TR_REG_ADDRINTA : TR_REG_ADDRINTB, 4); bufhalf = tr_rd(tr, (chnum < 32)? TR_REG_CSPF_A : TR_REG_CSPF_B, 4); @@ -815,8 +825,13 @@ tr_pci_attach(device_t dev) u_int32_t data; struct tr_info *tr; struct ac97_info *codec = 0; + bus_addr_t lowaddr; int i, dacn; char status[SND_STATUSLEN]; +#ifdef __sparc64__ + device_t *children; + int nchildren; +#endif tr = malloc(sizeof(*tr), M_DEVBUF, M_WAITOK | M_ZERO); tr->type = pci_get_devid(dev); @@ -834,7 +849,7 @@ tr_pci_attach(device_t dev) } else { switch (tr->type) { case ALI_PCI_ID: - dacn = 1; + dacn = ALI_MAXPLAYCH; break; default: dacn = TR_MAXPLAYCH; @@ -859,8 +874,6 @@ tr_pci_attach(device_t dev) goto bad; } - tr->bufsz = pcm_getbuffersize(dev, 4096, TR_DEFAULT_BUFSZ, 65536); - if (tr_init(tr) == -1) { device_printf(dev, "unable to initialize the card\n"); goto bad; @@ -879,12 +892,59 @@ tr_pci_attach(device_t dev) goto bad; } - if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2, + if (tr->type == ALI_PCI_ID) { + /* + * The M5451 generates 31 bit of DMA and in order to do + * 32-bit DMA, the 31st bit can be set via its accompanying + * ISA bridge. Note that we can't predict whether bus_dma(9) + * will actually supply us with a 32-bit buffer and even when + * using a low address of BUS_SPACE_MAXADDR_32BIT for both + * we might end up with the play buffer being in the 32-bit + * range while the record buffer isn't or vice versa. So we + * limit enabling the 31st bit to sparc64, where the IOMMU + * guarantees that we're using a 32-bit address (and in turn + * requires it). + */ + lowaddr = ALI_MAXADDR; +#ifdef __sparc64__ + if (device_get_children(device_get_parent(dev), &children, + &nchildren) == 0) { + for (i = 0; i < nchildren; i++) { + if (pci_get_devid(children[i]) == 0x153310b9) { + lowaddr = BUS_SPACE_MAXADDR_32BIT; + data = pci_read_config(children[i], + 0x7e, 1); + if (bootverbose) + device_printf(dev, + "M1533 0x7e: 0x%x -> ", + data); + data |= 0x1; + if (bootverbose) + printf("0x%x\n", data); + pci_write_config(children[i], 0x7e, + data, 1); + break; + } + } + } + free(children, M_TEMP); +#endif + tr->hwchns = ALI_MAXHWCH; + tr->bufsz = ALI_BUFSZ; + } else { + lowaddr = TR_MAXADDR; + tr->hwchns = TR_MAXHWCH; + tr->bufsz = pcm_getbuffersize(dev, 4096, TR_DEFAULT_BUFSZ, + 65536); + } + + if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), + /*alignment*/TR_BUFALGN, /*boundary*/0, - /*lowaddr*/TR_MAXADDR, + /*lowaddr*/lowaddr, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, - /*maxsize*/tr->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff, + /*maxsize*/tr->bufsz, /*nsegments*/1, /*maxsegz*/tr->bufsz, /*flags*/0, /*lockfunc*/busdma_lock_mutex, /*lockarg*/&Giant, &tr->parent_dmat) != 0) { device_printf(dev, "unable to create dma tag\n"); diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c index e75db9df799b..c9809583d923 100644 --- a/sys/dev/syscons/syscons.c +++ b/sys/dev/syscons/syscons.c @@ -634,14 +634,8 @@ sckbdevent(keyboard_t *thiskbd, int event, void *arg) break; case FKEY: /* function key, return string */ cp = kbdd_get_fkeystr(thiskbd, KEYCHAR(c), &len); - if (cp != NULL) { - if (ttydisc_can_bypass(cur_tty)) { - ttydisc_rint_bypass(cur_tty, cp, len); - } else { - while (len-- > 0) - ttydisc_rint(cur_tty, *cp++, 0); - } - } + if (cp != NULL) + ttydisc_rint_simple(cur_tty, cp, len); break; case MKEY: /* meta is active, prepend ESC */ ttydisc_rint(cur_tty, 0x1b, 0); diff --git a/sys/dev/twa/tw_cl_io.c b/sys/dev/twa/tw_cl_io.c index 162b1ea326f3..6fea17522360 100644 --- a/sys/dev/twa/tw_cl_io.c +++ b/sys/dev/twa/tw_cl_io.c @@ -396,7 +396,7 @@ tw_cl_fw_passthru(struct tw_cl_ctlr_handle *ctlr_handle, * non-zero-- failure */ TW_INT32 -tw_cl_ioctl(struct tw_cl_ctlr_handle *ctlr_handle, TW_INT32 cmd, TW_VOID *buf) +tw_cl_ioctl(struct tw_cl_ctlr_handle *ctlr_handle, u_long cmd, TW_VOID *buf) { struct tw_cli_ctlr_context *ctlr = (struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt); diff --git a/sys/dev/twa/tw_cl_share.h b/sys/dev/twa/tw_cl_share.h index 265ff77afefa..e58381831789 100644 --- a/sys/dev/twa/tw_cl_share.h +++ b/sys/dev/twa/tw_cl_share.h @@ -565,7 +565,7 @@ extern TW_INT32 tw_cl_interrupt(struct tw_cl_ctlr_handle *ctlr_handle); /* CL's ioctl handler. */ extern TW_INT32 tw_cl_ioctl(struct tw_cl_ctlr_handle *ctlr_handle, - TW_INT32 cmd, TW_VOID *buf); + u_long cmd, TW_VOID *buf); #ifdef TW_OSL_DEBUG diff --git a/sys/dev/twe/twe.c b/sys/dev/twe/twe.c index 59b5027adac9..90dfa2e505e4 100644 --- a/sys/dev/twe/twe.c +++ b/sys/dev/twe/twe.c @@ -487,7 +487,7 @@ twe_dump_blocks(struct twe_softc *sc, int unit, u_int32_t lba, void *data, int n * Handle controller-specific control operations. */ int -twe_ioctl(struct twe_softc *sc, int ioctlcmd, void *addr) +twe_ioctl(struct twe_softc *sc, u_long ioctlcmd, void *addr) { struct twe_usercommand *tu = (struct twe_usercommand *)addr; struct twe_paramcommand *tp = (struct twe_paramcommand *)addr; diff --git a/sys/dev/twe/twevar.h b/sys/dev/twe/twevar.h index 90391ad95dfc..2711ccc94932 100644 --- a/sys/dev/twe/twevar.h +++ b/sys/dev/twe/twevar.h @@ -150,7 +150,7 @@ extern void twe_startio(struct twe_softc *sc); extern int twe_start(struct twe_request *tr); extern int twe_dump_blocks(struct twe_softc *sc, int unit, /* crashdump block write */ u_int32_t lba, void *data, int nblks); -extern int twe_ioctl(struct twe_softc *sc, int cmd, +extern int twe_ioctl(struct twe_softc *sc, u_long cmd, void *addr); /* handle user request */ extern void twe_describe_controller(struct twe_softc *sc); /* print controller info */ extern void twe_print_controller(struct twe_softc *sc); diff --git a/sys/fs/procfs/procfs.c b/sys/fs/procfs/procfs.c index 77d1dc62ca4a..8b69eb1a0b3c 100644 --- a/sys/fs/procfs/procfs.c +++ b/sys/fs/procfs/procfs.c @@ -108,7 +108,8 @@ procfs_attr(PFS_ATTR_ARGS) else if (strcmp(pn->pn_name, "mem") == 0 || strcmp(pn->pn_name, "regs") == 0 || strcmp(pn->pn_name, "dbregs") == 0 || - strcmp(pn->pn_name, "fpregs") == 0) + strcmp(pn->pn_name, "fpregs") == 0 || + strcmp(pn->pn_name, "osrel") == 0) vap->va_mode = 0600; if (p != NULL) { @@ -186,6 +187,8 @@ procfs_init(PFS_INIT_ARGS) NULL, NULL, NULL, PFS_RD); pfs_create_file(dir, "status", procfs_doprocstatus, NULL, NULL, NULL, PFS_RD); + pfs_create_file(dir, "osrel", procfs_doosrel, + procfs_attr, procfs_candebug, NULL, PFS_RDWR); pfs_create_link(dir, "file", procfs_doprocfile, NULL, procfs_notsystem, NULL, 0); diff --git a/sys/fs/procfs/procfs.h b/sys/fs/procfs/procfs.h index 48d4bca84b48..259822451b0d 100644 --- a/sys/fs/procfs/procfs.h +++ b/sys/fs/procfs/procfs.h @@ -39,6 +39,7 @@ #ifdef _KERNEL int procfs_docurproc(PFS_FILL_ARGS); +int procfs_doosrel(PFS_FILL_ARGS); int procfs_doproccmdline(PFS_FILL_ARGS); int procfs_doprocctl(PFS_FILL_ARGS); int procfs_doprocdbregs(PFS_FILL_ARGS); diff --git a/sys/fs/procfs/procfs_osrel.c b/sys/fs/procfs/procfs_osrel.c new file mode 100644 index 000000000000..d32bd6d537d2 --- /dev/null +++ b/sys/fs/procfs/procfs_osrel.c @@ -0,0 +1,68 @@ +/*- + * Copyright (c) 2009 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. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/sbuf.h> +#include <sys/uio.h> + +#include <fs/pseudofs/pseudofs.h> +#include <fs/procfs/procfs.h> + +int +procfs_doosrel(PFS_FILL_ARGS) +{ + const char *pp; + int ov, osrel, i; + + if (uio == NULL) + return (EOPNOTSUPP); + if (uio->uio_rw == UIO_READ) { + sbuf_printf(sb, "%d\n", p->p_osrel); + } else { + sbuf_trim(sb); + sbuf_finish(sb); + pp = sbuf_data(sb); + osrel = 0; + i = sbuf_len(sb); + while (i--) { + if (*pp < '0' || *pp > '9') + return (EINVAL); + ov = osrel * 10 + *pp++ - '0'; + if (ov < osrel) + return (EINVAL); + osrel = ov; + } + p->p_osrel = osrel; + } + return (0); +} diff --git a/sys/geom/part/g_part.c b/sys/geom/part/g_part.c index 78c36501326b..6e81a9c70b68 100644 --- a/sys/geom/part/g_part.c +++ b/sys/geom/part/g_part.c @@ -480,6 +480,10 @@ g_part_ctl_add(struct gctl_req *req, struct g_part_parms *gpp) gctl_error(req, "%d index '%d'", EEXIST, gpp->gpp_index); return (EEXIST); } + if (index > table->gpt_entries) { + gctl_error(req, "%d index '%d'", ENOSPC, index); + return (ENOSPC); + } entry = (delent == NULL) ? g_malloc(table->gpt_scheme->gps_entrysz, M_WAITOK | M_ZERO) : delent; diff --git a/sys/i386/acpica/acpi_machdep.c b/sys/i386/acpica/acpi_machdep.c index a0ef60ffa4d8..ae23178d3e25 100644 --- a/sys/i386/acpica/acpi_machdep.c +++ b/sys/i386/acpica/acpi_machdep.c @@ -42,6 +42,8 @@ __FBSDID("$FreeBSD$"); #include <vm/pmap.h> #include <contrib/dev/acpica/include/acpi.h> +#include <contrib/dev/acpica/include/accommon.h> +#include <contrib/dev/acpica/include/actables.h> #include <dev/acpica/acpivar.h> #include <dev/acpica/acpiio.h> @@ -558,6 +560,244 @@ acpi_cpu_c1() } /* + * 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 = roundup(length + off, PAGE_SIZE); + 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 = roundup(length + off, PAGE_SIZE); + 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); + table_unmap(table, length); + return (NULL); + } + 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 diff --git a/sys/i386/acpica/madt.c b/sys/i386/acpica/madt.c index f9756ec0a77c..114fbc78a3e1 100644 --- a/sys/i386/acpica/madt.c +++ b/sys/i386/acpica/madt.c @@ -36,27 +36,19 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/smp.h> - #include <vm/vm.h> -#include <vm/vm_param.h> #include <vm/pmap.h> #include <machine/apicreg.h> -#include <machine/frame.h> #include <machine/intr_machdep.h> #include <machine/apicvar.h> -#include <machine/md_var.h> -#include <machine/specialreg.h> #include <contrib/dev/acpica/include/acpi.h> -#include <contrib/dev/acpica/include/accommon.h> #include <contrib/dev/acpica/include/actables.h> #include <dev/acpica/acpivar.h> #include <dev/pci/pcivar.h> -typedef void madt_entry_handler(ACPI_SUBTABLE_HEADER *entry, void *arg); - /* These two arrays are indexed by APIC IDs. */ struct ioapic_info { void *io_apic; @@ -79,8 +71,6 @@ static enum intr_polarity interrupt_polarity(UINT16 IntiFlags, UINT8 Source); static enum intr_trigger interrupt_trigger(UINT16 IntiFlags, UINT8 Source); static int madt_find_cpu(u_int acpi_id, u_int *apic_id); static int madt_find_interrupt(int intr, void **apic, u_int *pin); -static void *madt_map(vm_paddr_t pa, int offset, vm_offset_t length); -static void *madt_map_table(vm_paddr_t pa, int offset, const char *sig); static void madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg); static void madt_parse_interrupt_override( ACPI_MADT_INTERRUPT_OVERRIDE *intr); @@ -92,13 +82,10 @@ static int madt_probe(void); static int madt_probe_cpus(void); static void madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg __unused); -static int madt_probe_table(vm_paddr_t address); static void madt_register(void *dummy); static int madt_setup_local(void); static int madt_setup_io(void); -static void madt_unmap(void *data, vm_offset_t length); -static void madt_unmap_table(void *table); -static void madt_walk_table(madt_entry_handler *handler, void *arg); +static void madt_walk_table(acpi_subtable_handler *handler, void *arg); static struct apic_enumerator madt_enumerator = { "MADT", @@ -108,87 +95,6 @@ static struct apic_enumerator madt_enumerator = { madt_setup_io }; -/* - * Code to abuse the crashdump map to map in the tables for the early - * probe. We cheat and make 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. We have to use 2 pages for the table headers - * in case a header spans a page boundary. The offset is in pages; - * the length is in bytes. - */ -static void * -madt_map(vm_paddr_t pa, int offset, vm_offset_t length) -{ - vm_offset_t va, off; - void *data; - - off = pa & PAGE_MASK; - length = roundup(length + off, PAGE_SIZE); - 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); -} - -static void -madt_unmap(void *data, vm_offset_t length) -{ - vm_offset_t va, off; - - va = (vm_offset_t)data; - off = va & PAGE_MASK; - length = roundup(length + off, PAGE_SIZE); - va &= ~PAGE_MASK; - while (length > 0) { - pmap_kremove(va); - invlpg(va); - va += PAGE_SIZE; - length -= PAGE_SIZE; - } -} - -static void * -madt_map_table(vm_paddr_t pa, int offset, const char *sig) -{ - ACPI_TABLE_HEADER *header; - vm_offset_t length; - void *table; - - header = madt_map(pa, offset, sizeof(ACPI_TABLE_HEADER)); - if (strncmp(header->Signature, sig, ACPI_NAME_SIZE) != 0) { - madt_unmap(header, sizeof(ACPI_TABLE_HEADER)); - return (NULL); - } - length = header->Length; - madt_unmap(header, sizeof(ACPI_TABLE_HEADER)); - table = madt_map(pa, offset, length); - if (ACPI_FAILURE(AcpiTbChecksum(table, length))) { - if (bootverbose) - printf("MADT: Failed checksum for table %s\n", sig); - madt_unmap(table, length); - return (NULL); - } - return (table); -} - -static void -madt_unmap_table(void *table) -{ - ACPI_TABLE_HEADER *header; - - header = (ACPI_TABLE_HEADER *)table; - madt_unmap(table, header->Length); -} /* * Look for an ACPI Multiple APIC Description Table ("APIC") @@ -196,137 +102,25 @@ madt_unmap_table(void *table) static int madt_probe(void) { - ACPI_PHYSICAL_ADDRESS rsdp_ptr; - ACPI_TABLE_RSDP *rsdp; - ACPI_TABLE_RSDT *rsdt; - ACPI_TABLE_XSDT *xsdt; - int i, count; - - if (resource_disabled("acpi", 0)) - return (ENXIO); - - /* - * 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 (ENXIO); - rsdp = pmap_mapbios(rsdp_ptr, sizeof(ACPI_TABLE_RSDP)); - if (rsdp == NULL) { - if (bootverbose) - printf("MADT: Failed to map RSDP\n"); - return (ENXIO); - } - - /* - * For ACPI >= 2.0, use the XSDT if it is available. - * Otherwise, use the RSDT. We map the XSDT or RSDT at page 1 - * in the crashdump area. Page 0 is used to map in the - * headers of candidate ACPI tables. - */ - 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("MADT: RSDP failed extended checksum\n"); - return (ENXIO); - } - xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 2, - ACPI_SIG_XSDT); - if (xsdt == NULL) { - if (bootverbose) - printf("MADT: Failed to map XSDT\n"); - return (ENXIO); - } - count = (xsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) / - sizeof(UINT64); - for (i = 0; i < count; i++) - if (madt_probe_table(xsdt->TableOffsetEntry[i])) - break; - madt_unmap_table(xsdt); - } else { - rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 2, - ACPI_SIG_RSDT); - if (rsdt == NULL) { - if (bootverbose) - printf("MADT: Failed to map RSDT\n"); - return (ENXIO); - } - count = (rsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) / - sizeof(UINT32); - for (i = 0; i < count; i++) - if (madt_probe_table(rsdt->TableOffsetEntry[i])) - break; - madt_unmap_table(rsdt); - } - pmap_unmapbios((vm_offset_t)rsdp, sizeof(ACPI_TABLE_RSDP)); - if (madt_physaddr == 0) { - if (bootverbose) - printf("MADT: No MADT table found\n"); - return (ENXIO); - } - if (bootverbose) - printf("MADT: Found table at 0x%jx\n", - (uintmax_t)madt_physaddr); - /* - * Verify that we can map the full table and that its checksum is - * correct, etc. - */ - madt = madt_map_table(madt_physaddr, 0, ACPI_SIG_MADT); - if (madt == NULL) + madt_physaddr = acpi_find_table(ACPI_SIG_MADT); + if (madt_physaddr == 0) return (ENXIO); - madt_unmap_table(madt); - madt = NULL; - return (0); } /* - * See if a given ACPI table is the MADT. - */ -static int -madt_probe_table(vm_paddr_t address) -{ - ACPI_TABLE_HEADER *table; - - table = madt_map(address, 0, sizeof(ACPI_TABLE_HEADER)); - if (table == NULL) { - if (bootverbose) - printf("MADT: 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, ACPI_SIG_MADT, ACPI_NAME_SIZE) != 0) { - madt_unmap(table, sizeof(ACPI_TABLE_HEADER)); - return (0); - } - madt_physaddr = address; - madt_length = table->Length; - madt_unmap(table, sizeof(ACPI_TABLE_HEADER)); - return (1); -} - -/* * Run through the MP table enumerating CPUs. */ static int madt_probe_cpus(void) { - madt = madt_map_table(madt_physaddr, 0, ACPI_SIG_MADT); + madt = acpi_map_table(madt_physaddr, ACPI_SIG_MADT); + madt_length = madt->Header.Length; KASSERT(madt != NULL, ("Unable to re-map MADT")); madt_walk_table(madt_probe_cpus_handler, NULL); - madt_unmap_table(madt); + acpi_unmap_table(madt); madt = NULL; return (0); } @@ -416,17 +210,11 @@ SYSINIT(madt_register, SI_SUB_CPU - 1, SI_ORDER_SECOND, madt_register, NULL); * Call the handler routine for each entry in the MADT table. */ static void -madt_walk_table(madt_entry_handler *handler, void *arg) +madt_walk_table(acpi_subtable_handler *handler, void *arg) { - ACPI_SUBTABLE_HEADER *entry; - u_char *p, *end; - - end = (u_char *)(madt) + madt->Header.Length; - for (p = (u_char *)(madt + 1); p < end; ) { - entry = (ACPI_SUBTABLE_HEADER *)p; - handler(entry, arg); - p += entry->Length; - } + + acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length, + handler, arg); } static void diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES index 876224e7788c..594c43a5669c 100644 --- a/sys/i386/conf/NOTES +++ b/sys/i386/conf/NOTES @@ -353,7 +353,7 @@ options AGP_DEBUG ##################################################################### # HARDWARE DEVICE CONFIGURATION -# To include support for VGA VESA video modes (depends on X86EMU) +# To include support for VGA VESA video modes options VESA # Turn on extra debugging checks and output for VESA support. @@ -361,6 +361,9 @@ options VESA_DEBUG device dpms # DPMS suspend & resume via VESA BIOS +# x86 real mode BIOS emulator, required by atkbdc/dpms/vesa +options X86BIOS + # # The Numeric Processing eXtension driver. This is non-optional. device npx @@ -444,6 +447,9 @@ options VGA_WIDTH90 # support 90 column modes # Debugging. options VGA_DEBUG +# Linear framebuffer driver for S3 VESA 1.2 cards. Works on top of VESA. +device s3pci + # 3Dfx Voodoo Graphics, Voodoo II /dev/3dfx CDEV support. This will create # the /dev/3dfx0 device to work with glide implementations. This should get # linked to /dev/3dfx and /dev/voodoo. Note that this is not the same as diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index 1a6b3c6015ee..96c8f25704e2 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -1946,7 +1946,7 @@ sdtossd(sd, ssd) static int add_smap_entry(struct bios_smap *smap, vm_paddr_t *physmap, int *physmap_idxp) { - int i, physmap_idx; + int i, insert_idx, physmap_idx; physmap_idx = *physmap_idxp; @@ -1968,17 +1968,34 @@ add_smap_entry(struct bios_smap *smap, vm_paddr_t *physmap, int *physmap_idxp) } #endif + /* + * Find insertion point while checking for overlap. Start off by + * assuming the new entry will be added to the end. + */ + insert_idx = physmap_idx + 2; for (i = 0; i <= physmap_idx; i += 2) { if (smap->base < physmap[i + 1]) { + if (smap->base + smap->length <= physmap[i]) { + insert_idx = i; + break; + } if (boothowto & RB_VERBOSE) printf( - "Overlapping or non-monotonic memory region, ignoring second region\n"); + "Overlapping memory regions, ignoring second region\n"); return (1); } } - if (smap->base == physmap[physmap_idx + 1]) { - physmap[physmap_idx + 1] += smap->length; + /* See if we can prepend to the next entry. */ + if (insert_idx <= physmap_idx && + smap->base + smap->length == physmap[insert_idx]) { + physmap[insert_idx] = smap->base; + return (1); + } + + /* See if we can append to the previous entry. */ + if (insert_idx > 0 && smap->base == physmap[insert_idx - 1]) { + physmap[insert_idx - 1] += smap->length; return (1); } @@ -1989,8 +2006,19 @@ add_smap_entry(struct bios_smap *smap, vm_paddr_t *physmap, int *physmap_idxp) "Too many segments in the physical address map, giving up\n"); return (0); } - physmap[physmap_idx] = smap->base; - physmap[physmap_idx + 1] = smap->base + smap->length; + + /* + * Move the last 'N' entries down to make room for the new + * entry if needed. + */ + for (i = physmap_idx; i > insert_idx; i -= 2) { + physmap[i] = physmap[i - 2]; + physmap[i + 1] = physmap[i - 1]; + } + + /* Insert the new entry. */ + physmap[insert_idx] = smap->base; + physmap[insert_idx + 1] = smap->base + smap->length; return (1); } diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c index f3b4d99523b0..7e3bc3701ce4 100644 --- a/sys/i386/i386/pmap.c +++ b/sys/i386/i386/pmap.c @@ -702,6 +702,11 @@ pmap_init(void) * Are large page mappings enabled? */ TUNABLE_INT_FETCH("vm.pmap.pg_ps_enabled", &pg_ps_enabled); + if (pg_ps_enabled) { + KASSERT(MAXPAGESIZES > 1 && pagesizes[1] == 0, + ("pmap_init: can't assign to pagesizes[1]")); + pagesizes[1] = NBPDR; + } /* * Calculate the size of the pv head table for superpages. diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c index f7064f04a537..f4df66870217 100644 --- a/sys/i386/i386/trap.c +++ b/sys/i386/i386/trap.c @@ -225,6 +225,11 @@ trap(struct trapframe *frame) } #endif + if (type == T_RESERVED) { + trap_fatal(frame, 0); + goto out; + } + #ifdef HWPMC_HOOKS /* * CPU PMCs interrupt using an NMI so we check for that first. diff --git a/sys/i386/include/acpica_machdep.h b/sys/i386/include/acpica_machdep.h index f90b213eb54b..d5bfe65e48f8 100644 --- a/sys/i386/include/acpica_machdep.h +++ b/sys/i386/include/acpica_machdep.h @@ -97,5 +97,8 @@ extern int acpi_release_global_lock(uint32_t *lock); void acpi_SetDefaultIntrModel(int model); void acpi_cpu_c1(void); +void *acpi_map_table(vm_paddr_t pa, const char *sig); +void acpi_unmap_table(void *table); +vm_paddr_t acpi_find_table(const char *sig); #endif /* __ACPICA_MACHDEP_H__ */ diff --git a/sys/i386/include/param.h b/sys/i386/include/param.h index b6a527dba054..11ac12efac70 100644 --- a/sys/i386/include/param.h +++ b/sys/i386/include/param.h @@ -110,6 +110,8 @@ #define NBPDR (1<<PDRSHIFT) /* bytes/page dir */ #define PDRMASK (NBPDR-1) +#define MAXPAGESIZES 2 /* maximum number of supported page sizes */ + #define IOPAGES 2 /* pages of i/o permission bitmap */ #ifndef KSTACK_PAGES diff --git a/sys/i386/pci/pci_cfgreg.c b/sys/i386/pci/pci_cfgreg.c index 20050e6f0144..ae56990cd7ba 100644 --- a/sys/i386/pci/pci_cfgreg.c +++ b/sys/i386/pci/pci_cfgreg.c @@ -299,9 +299,9 @@ pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes) if (bus <= PCI_BUSMAX && slot < devmax && func <= PCI_FUNCMAX - && reg <= PCI_REGMAX + && (unsigned)reg <= PCI_REGMAX && bytes != 3 - && (unsigned) bytes <= 4 + && (unsigned)bytes <= 4 && (reg & (bytes - 1)) == 0) { switch (cfgmech) { case CFGMECH_PCIE: @@ -595,7 +595,7 @@ pcie_cfgregopen(uint64_t base, uint8_t minbus, uint8_t maxbus) * fall back to using type 1 config access instead. */ if (pci_cfgregopen() != 0) { - for (slot = 0; slot < 32; slot++) { + for (slot = 0; slot <= PCI_SLOTMAX; slot++) { val1 = pcireg_cfgread(0, slot, 0, 0, 4); if (val1 == 0xffffffff) continue; @@ -661,8 +661,8 @@ pciereg_cfgread(int bus, unsigned slot, unsigned func, unsigned reg, vm_paddr_t pa, papage; int data = -1; - if (bus < pcie_minbus || bus > pcie_maxbus || slot >= 32 || - func > PCI_FUNCMAX || reg >= 0x1000 || bytes > 4 || bytes == 3) + if (bus < pcie_minbus || bus > pcie_maxbus || slot > PCI_SLOTMAX || + func > PCI_FUNCMAX || reg > PCIE_REGMAX) return (-1); critical_enter(); @@ -695,8 +695,8 @@ pciereg_cfgwrite(int bus, unsigned slot, unsigned func, unsigned reg, int data, volatile vm_offset_t va; vm_paddr_t pa, papage; - if (bus < pcie_minbus || bus > pcie_maxbus || slot >= 32 || - func > PCI_FUNCMAX || reg >= 0x1000) + if (bus < pcie_minbus || bus > pcie_maxbus || slot > PCI_SLOTMAX || + func > PCI_FUNCMAX || reg > PCIE_REGMAX) return; critical_enter(); diff --git a/sys/ia64/include/param.h b/sys/ia64/include/param.h index 8518020a9240..331af7aacf40 100644 --- a/sys/ia64/include/param.h +++ b/sys/ia64/include/param.h @@ -89,6 +89,8 @@ #define PAGE_MASK (PAGE_SIZE-1) #define NPTEPG (PAGE_SIZE/(sizeof (pt_entry_t))) +#define MAXPAGESIZES 1 /* maximum number of supported page sizes */ + #ifndef KSTACK_PAGES #define KSTACK_PAGES 4 /* pages of kernel stack */ #endif diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index 8ce7621e9a7f..86a950f9bd89 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -145,7 +145,8 @@ static int filt_timer(struct knote *kn, long hint); static int filt_userattach(struct knote *kn); static void filt_userdetach(struct knote *kn); static int filt_user(struct knote *kn, long hint); -static void filt_usertouch(struct knote *kn, struct kevent *kev, long type); +static void filt_usertouch(struct knote *kn, struct kevent *kev, + u_long type); static struct filterops file_filtops = { .f_isfd = 1, @@ -616,9 +617,9 @@ filt_user(struct knote *kn, __unused long hint) } static void -filt_usertouch(struct knote *kn, struct kevent *kev, long type) +filt_usertouch(struct knote *kn, struct kevent *kev, u_long type) { - int ffctrl; + u_int ffctrl; switch (type) { case EVENT_REGISTER: diff --git a/sys/kern/kern_mib.c b/sys/kern/kern_mib.c index d42d31d651f5..04e4dc0437b7 100644 --- a/sys/kern/kern_mib.c +++ b/sys/kern/kern_mib.c @@ -204,6 +204,33 @@ SYSCTL_PROC(_hw, HW_USERMEM, usermem, CTLTYPE_ULONG | CTLFLAG_RD, SYSCTL_ULONG(_hw, OID_AUTO, availpages, CTLFLAG_RD, &physmem, 0, ""); +u_long pagesizes[MAXPAGESIZES] = { PAGE_SIZE }; + +static int +sysctl_hw_pagesizes(SYSCTL_HANDLER_ARGS) +{ + int error; +#ifdef SCTL_MASK32 + int i; + uint32_t pagesizes32[MAXPAGESIZES]; + + if (req->flags & SCTL_MASK32) { + /* + * Recreate the "pagesizes" array with 32-bit elements. Truncate + * any page size greater than UINT32_MAX to zero. + */ + for (i = 0; i < MAXPAGESIZES; i++) + pagesizes32[i] = (uint32_t)pagesizes[i]; + + error = SYSCTL_OUT(req, pagesizes32, sizeof(pagesizes32)); + } else +#endif + error = SYSCTL_OUT(req, pagesizes, sizeof(pagesizes)); + return (error); +} +SYSCTL_PROC(_hw, OID_AUTO, pagesizes, CTLTYPE_ULONG | CTLFLAG_RD, + NULL, 0, sysctl_hw_pagesizes, "LU", "Supported page sizes"); + static char machine_arch[] = MACHINE_ARCH; SYSCTL_STRING(_hw, HW_MACHINE_ARCH, machine_arch, CTLFLAG_RD, machine_arch, 0, "System architecture"); diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c index bcb60edd8d14..2ab099d758fc 100644 --- a/sys/kern/kern_umtx.c +++ b/sys/kern/kern_umtx.c @@ -2556,6 +2556,7 @@ do_rw_wrlock(struct thread *td, struct urwlock *rwlock, int timo) uint32_t flags; int32_t state, oldstate; int32_t blocked_writers; + int32_t blocked_readers; int error; uq = td->td_umtxq; @@ -2564,6 +2565,7 @@ do_rw_wrlock(struct thread *td, struct urwlock *rwlock, int timo) if (error != 0) return (error); + blocked_readers = 0; for (;;) { state = fuword32(__DEVOLATILE(int32_t *, &rwlock->rw_state)); while (!(state & URWLOCK_WRITE_OWNER) && URWLOCK_READER_COUNT(state) == 0) { @@ -2575,8 +2577,18 @@ do_rw_wrlock(struct thread *td, struct urwlock *rwlock, int timo) state = oldstate; } - if (error) + if (error) { + if (!(state & (URWLOCK_WRITE_OWNER|URWLOCK_WRITE_WAITERS)) && + blocked_readers != 0) { + umtxq_lock(&uq->uq_key); + umtxq_busy(&uq->uq_key); + umtxq_signal_queue(&uq->uq_key, INT_MAX, UMTX_SHARED_QUEUE); + umtxq_unbusy(&uq->uq_key); + umtxq_unlock(&uq->uq_key); + } + break; + } /* grab monitor lock */ umtxq_lock(&uq->uq_key); @@ -2627,7 +2639,9 @@ sleep: break; state = oldstate; } - } + blocked_readers = fuword32(&rwlock->rw_blocked_readers); + } else + blocked_readers = 0; umtxq_lock(&uq->uq_key); umtxq_unbusy(&uq->uq_key); diff --git a/sys/kern/subr_acl_nfs4.c b/sys/kern/subr_acl_nfs4.c index 85609b98bd95..c3f4b65cbd5f 100644 --- a/sys/kern/subr_acl_nfs4.c +++ b/sys/kern/subr_acl_nfs4.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2008 Edward Tomasz NapieraÅ‚a <trasz@FreeBSD.org> + * Copyright (c) 2008-2009 Edward Tomasz NapieraÅ‚a <trasz@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,7 +49,213 @@ __FBSDID("$FreeBSD$"); #include <sys/stat.h> #define KASSERT(a, b) assert(a) #define CTASSERT(a) -#endif +#endif /* _KERNEL */ + +#ifdef _KERNEL + +static struct { + accmode_t accmode; + int mask; +} accmode2mask[] = {{VREAD, ACL_READ_DATA}, + {VWRITE, ACL_WRITE_DATA}, + {VAPPEND, ACL_APPEND_DATA}, + {VEXEC, ACL_EXECUTE}, + {VREAD_NAMED_ATTRS, ACL_READ_NAMED_ATTRS}, + {VWRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS}, + {VDELETE_CHILD, ACL_DELETE_CHILD}, + {VREAD_ATTRIBUTES, ACL_READ_ATTRIBUTES}, + {VWRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, + {VDELETE, ACL_DELETE}, + {VREAD_ACL, ACL_READ_ACL}, + {VWRITE_ACL, ACL_WRITE_ACL}, + {VWRITE_OWNER, ACL_WRITE_OWNER}, + {VSYNCHRONIZE, ACL_SYNCHRONIZE}, + {0, 0}}; + +static int +_access_mask_from_accmode(accmode_t accmode) +{ + int access_mask = 0, i; + + for (i = 0; accmode2mask[i].accmode != 0; i++) { + if (accmode & accmode2mask[i].accmode) + access_mask |= accmode2mask[i].mask; + } + + return (access_mask); +} + +/* + * Return 0, iff access is allowed, 1 otherwise. + */ +static int +_acl_denies(const struct acl *aclp, int access_mask, struct ucred *cred, + int file_uid, int file_gid, int *denied_explicitly) +{ + int i; + const struct acl_entry *entry; + + if (denied_explicitly != NULL) + *denied_explicitly = 0; + + KASSERT(aclp->acl_cnt > 0, ("aclp->acl_cnt > 0")); + KASSERT(aclp->acl_cnt <= ACL_MAX_ENTRIES, + ("aclp->acl_cnt <= ACL_MAX_ENTRIES")); + + for (i = 0; i < aclp->acl_cnt; i++) { + entry = &(aclp->acl_entry[i]); + + if (entry->ae_entry_type != ACL_ENTRY_TYPE_ALLOW && + entry->ae_entry_type != ACL_ENTRY_TYPE_DENY) + continue; + if (entry->ae_flags & ACL_ENTRY_INHERIT_ONLY) + continue; + switch (entry->ae_tag) { + case ACL_USER_OBJ: + if (file_uid != cred->cr_uid) + continue; + break; + case ACL_USER: + if (entry->ae_id != cred->cr_uid) + continue; + break; + case ACL_GROUP_OBJ: + if (!groupmember(file_gid, cred)) + continue; + break; + case ACL_GROUP: + if (!groupmember(entry->ae_id, cred)) + continue; + break; + default: + KASSERT(entry->ae_tag == ACL_EVERYONE, + ("entry->ae_tag == ACL_EVERYONE")); + } + + if (entry->ae_entry_type == ACL_ENTRY_TYPE_DENY) { + if (entry->ae_perm & access_mask) { + if (denied_explicitly != NULL) + *denied_explicitly = 1; + return (1); + } + } + + access_mask &= ~(entry->ae_perm); + if (access_mask == 0) + return (0); + } + + return (1); +} + +int +vaccess_acl_nfs4(enum vtype type, uid_t file_uid, gid_t file_gid, + struct acl *aclp, accmode_t accmode, struct ucred *cred, int *privused) +{ + accmode_t priv_granted = 0; + int denied, explicitly_denied, access_mask, is_directory, + must_be_owner = 0; + + if (privused != NULL) + *privused = 0; + + if (accmode & VADMIN) + must_be_owner = 1; + + /* + * Ignore VSYNCHRONIZE permission. + */ + accmode &= ~VSYNCHRONIZE; + + access_mask = _access_mask_from_accmode(accmode); + + if (type == VDIR) + is_directory = 1; + else + is_directory = 0; + + /* + * File owner is always allowed to read and write the ACL + * and basic attributes. This is to prevent a situation + * where user would change ACL in a way that prevents him + * from undoing the change. + */ + if (file_uid == cred->cr_uid) + access_mask &= ~(ACL_READ_ACL | ACL_WRITE_ACL | + ACL_READ_ATTRIBUTES | ACL_WRITE_ATTRIBUTES); + + /* + * Ignore append permission for regular files; use write + * permission instead. + */ + if (!is_directory && (access_mask & ACL_APPEND_DATA)) { + access_mask &= ~ACL_APPEND_DATA; + access_mask |= ACL_WRITE_DATA; + } + + denied = _acl_denies(aclp, access_mask, cred, file_uid, file_gid, + &explicitly_denied); + + if (must_be_owner) { + if (file_uid != cred->cr_uid) + denied = EPERM; + } + + if (!denied) + return (0); + + /* + * Access failed. Iff it was not denied explicitly and + * VEXPLICIT_DENY flag was specified, allow access. + */ + if ((accmode & VEXPLICIT_DENY) && explicitly_denied == 0) + return (0); + + accmode &= ~VEXPLICIT_DENY; + + /* + * No match. Try to use privileges, if there are any. + */ + if (is_directory) { + if ((accmode & VEXEC) && !priv_check_cred(cred, + PRIV_VFS_LOOKUP, 0)) + priv_granted |= VEXEC; + } else { + if ((accmode & VEXEC) && !priv_check_cred(cred, + PRIV_VFS_EXEC, 0)) + priv_granted |= VEXEC; + } + + if ((accmode & VREAD) && !priv_check_cred(cred, PRIV_VFS_READ, 0)) + priv_granted |= VREAD; + + if ((accmode & (VWRITE | VAPPEND | VDELETE_CHILD)) && + !priv_check_cred(cred, PRIV_VFS_WRITE, 0)) + priv_granted |= (VWRITE | VAPPEND | VDELETE_CHILD); + + if ((accmode & VADMIN_PERMS) && + !priv_check_cred(cred, PRIV_VFS_ADMIN, 0)) + priv_granted |= VADMIN_PERMS; + + if ((accmode & VSTAT_PERMS) && + !priv_check_cred(cred, PRIV_VFS_STAT, 0)) + priv_granted |= VSTAT_PERMS; + + if ((accmode & priv_granted) == accmode) { + if (privused != NULL) + *privused = 1; + + return (0); + } + + if (accmode & (VADMIN_PERMS | VDELETE_CHILD | VDELETE)) + denied = EPERM; + else + denied = EACCES; + + return (denied); +} +#endif /* _KERNEL */ static int _acl_entry_matches(struct acl_entry *entry, acl_tag_t tag, acl_perm_t perm, @@ -577,3 +783,290 @@ acl_nfs4_sync_mode_from_acl(mode_t *_mode, const struct acl *aclp) *_mode = mode | (old_mode & ACL_PRESERVE_MASK); } + +void +acl_nfs4_compute_inherited_acl(const struct acl *parent_aclp, + struct acl *child_aclp, mode_t mode, int file_owner_id, + int is_directory) +{ + int i, flags; + const struct acl_entry *parent_entry; + struct acl_entry *entry, *copy; + + KASSERT(child_aclp->acl_cnt == 0, ("child_aclp->acl_cnt == 0")); + KASSERT(parent_aclp->acl_cnt > 0, ("parent_aclp->acl_cnt > 0")); + KASSERT(parent_aclp->acl_cnt <= ACL_MAX_ENTRIES, + ("parent_aclp->acl_cnt <= ACL_MAX_ENTRIES")); + + /* + * NFSv4 Minor Version 1, draft-ietf-nfsv4-minorversion1-03.txt + * + * 3.16.6.2. Applying the mode given to CREATE or OPEN + * to an inherited ACL + */ + + /* + * 1. Form an ACL that is the concatenation of all inheritable ACEs. + */ + for (i = 0; i < parent_aclp->acl_cnt; i++) { + parent_entry = &(parent_aclp->acl_entry[i]); + flags = parent_entry->ae_flags; + + /* + * Entry is not inheritable at all. + */ + if ((flags & (ACL_ENTRY_DIRECTORY_INHERIT | + ACL_ENTRY_FILE_INHERIT)) == 0) + continue; + + /* + * We're creating a file, but entry is not inheritable + * by files. + */ + if (!is_directory && (flags & ACL_ENTRY_FILE_INHERIT) == 0) + continue; + + /* + * Entry is inheritable only by files, but has NO_PROPAGATE + * flag set, and we're creating a directory, so it wouldn't + * propagate to any file in that directory anyway. + */ + if (is_directory && + (flags & ACL_ENTRY_DIRECTORY_INHERIT) == 0 && + (flags & ACL_ENTRY_NO_PROPAGATE_INHERIT)) + continue; + + KASSERT(child_aclp->acl_cnt + 1 <= ACL_MAX_ENTRIES, + ("child_aclp->acl_cnt + 1 <= ACL_MAX_ENTRIES")); + child_aclp->acl_entry[child_aclp->acl_cnt] = *parent_entry; + child_aclp->acl_cnt++; + } + + /* + * 2. For each entry in the new ACL, adjust its flags, possibly + * creating two entries in place of one. + */ + for (i = 0; i < child_aclp->acl_cnt; i++) { + entry = &(child_aclp->acl_entry[i]); + + /* + * This is not in the specification, but SunOS + * apparently does that. + */ + if (((entry->ae_flags & ACL_ENTRY_NO_PROPAGATE_INHERIT) || + !is_directory) && + entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) + entry->ae_perm &= ~(ACL_WRITE_ACL | ACL_WRITE_OWNER); + + /* + * 2.A. If the ACL_ENTRY_NO_PROPAGATE_INHERIT is set, or if the object + * being created is not a directory, then clear the + * following flags: ACL_ENTRY_NO_PROPAGATE_INHERIT, + * ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT, + * ACL_ENTRY_INHERIT_ONLY. + */ + if (entry->ae_flags & ACL_ENTRY_NO_PROPAGATE_INHERIT || + !is_directory) { + entry->ae_flags &= ~(ACL_ENTRY_NO_PROPAGATE_INHERIT | + ACL_ENTRY_FILE_INHERIT | ACL_ENTRY_DIRECTORY_INHERIT | + ACL_ENTRY_INHERIT_ONLY); + + /* + * Continue on to the next ACE. + */ + continue; + } + + /* + * 2.B. If the object is a directory and ACL_ENTRY_FILE_INHERIT + * is set, but ACL_ENTRY_NO_PROPAGATE_INHERIT is not set, ensure + * that ACL_ENTRY_INHERIT_ONLY is set. Continue to the + * next ACE. Otherwise... + */ + /* + * XXX: Read it again and make sure what does the "otherwise" + * apply to. + */ + if (is_directory && + (entry->ae_flags & ACL_ENTRY_FILE_INHERIT) && + ((entry->ae_flags & ACL_ENTRY_DIRECTORY_INHERIT) == 0)) { + entry->ae_flags |= ACL_ENTRY_INHERIT_ONLY; + continue; + } + + /* + * 2.C. If the type of the ACE is neither ALLOW nor deny, + * then continue. + */ + if (entry->ae_entry_type != ACL_ENTRY_TYPE_ALLOW && + entry->ae_entry_type != ACL_ENTRY_TYPE_DENY) + continue; + + /* + * 2.D. Copy the original ACE into a second, adjacent ACE. + */ + copy = _acl_duplicate_entry(child_aclp, i); + + /* + * 2.E. On the first ACE, ensure that ACL_ENTRY_INHERIT_ONLY + * is set. + */ + entry->ae_flags |= ACL_ENTRY_INHERIT_ONLY; + + /* + * 2.F. On the second ACE, clear the following flags: + * ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_FILE_INHERIT, + * ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_INHERIT_ONLY. + */ + copy->ae_flags &= ~(ACL_ENTRY_NO_PROPAGATE_INHERIT | + ACL_ENTRY_FILE_INHERIT | ACL_ENTRY_DIRECTORY_INHERIT | + ACL_ENTRY_INHERIT_ONLY); + + /* + * 2.G. On the second ACE, if the type is ALLOW, + * an implementation MAY clear the following + * mask bits: ACL_WRITE_ACL, ACL_WRITE_OWNER. + */ + if (copy->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) + copy->ae_perm &= ~(ACL_WRITE_ACL | ACL_WRITE_OWNER); + + /* + * Increment the counter to skip the copied entry. + */ + i++; + } + + /* + * 3. To ensure that the mode is honored, apply the algorithm describe + * in Section 2.16.6.3, using the mode that is to be used for file + * creation. + */ + acl_nfs4_sync_acl_from_mode(child_aclp, mode, file_owner_id); +} + +#ifdef _KERNEL +static int +_acls_are_equal(const struct acl *a, const struct acl *b) +{ + int i; + const struct acl_entry *entrya, *entryb; + + if (a->acl_cnt != b->acl_cnt) + return (0); + + for (i = 0; i < b->acl_cnt; i++) { + entrya = &(a->acl_entry[i]); + entryb = &(b->acl_entry[i]); + + if (entrya->ae_tag != entryb->ae_tag || + entrya->ae_id != entryb->ae_id || + entrya->ae_perm != entryb->ae_perm || + entrya->ae_entry_type != entryb->ae_entry_type || + entrya->ae_flags != entryb->ae_flags) + return (0); + } + + return (1); +} + +/* + * This routine is used to determine whether to remove entry_type attribute + * that stores ACL contents. + */ +int +acl_nfs4_is_trivial(const struct acl *aclp, int file_owner_id) +{ + int trivial; + mode_t tmpmode = 0; + struct acl *tmpaclp; + + if (aclp->acl_cnt != 6) + return (0); + + /* + * Compute the mode from the ACL, then compute new ACL from that mode. + * If the ACLs are identical, then the ACL is trivial. + * + * XXX: I guess there is a faster way to do this. However, even + * this slow implementation significantly speeds things up + * for files that don't have any entry_type ACL entries - it's + * critical for performance to not use EA when they are not + * needed. + */ + tmpaclp = acl_alloc(M_WAITOK | M_ZERO); + acl_nfs4_sync_mode_from_acl(&tmpmode, aclp); + acl_nfs4_sync_acl_from_mode(tmpaclp, tmpmode, file_owner_id); + trivial = _acls_are_equal(aclp, tmpaclp); + acl_free(tmpaclp); + + return (trivial); +} +#endif /* _KERNEL */ + +int +acl_nfs4_check(const struct acl *aclp, int is_directory) +{ + int i; + const struct acl_entry *entry; + + /* + * The spec doesn't seem to say anything about ACL validity. + * It seems there is not much to do here. There is even no need + * to count "owner@" or "everyone@" (ACL_USER_OBJ and ACL_EVERYONE) + * entries, as there can be several of them and that's perfectly + * valid. There can be none of them too. Really. + */ + + if (aclp->acl_cnt > ACL_MAX_ENTRIES || aclp->acl_cnt <= 0) + return (EINVAL); + + for (i = 0; i < aclp->acl_cnt; i++) { + entry = &(aclp->acl_entry[i]); + + switch (entry->ae_tag) { + case ACL_USER_OBJ: + case ACL_GROUP_OBJ: + case ACL_EVERYONE: + if (entry->ae_id != ACL_UNDEFINED_ID) + return (EINVAL); + break; + + case ACL_USER: + case ACL_GROUP: + if (entry->ae_id == ACL_UNDEFINED_ID) + return (EINVAL); + break; + + default: + return (EINVAL); + } + + if ((entry->ae_perm | ACL_NFS4_PERM_BITS) != ACL_NFS4_PERM_BITS) + return (EINVAL); + + /* + * Disallow ACL_ENTRY_TYPE_AUDIT and ACL_ENTRY_TYPE_ALARM for now. + */ + if (entry->ae_entry_type != ACL_ENTRY_TYPE_ALLOW && + entry->ae_entry_type != ACL_ENTRY_TYPE_DENY) + return (EINVAL); + + if ((entry->ae_flags | ACL_FLAGS_BITS) != ACL_FLAGS_BITS) + return (EINVAL); + + /* Disallow unimplemented flags. */ + if (entry->ae_flags & (ACL_ENTRY_SUCCESSFUL_ACCESS | + ACL_ENTRY_FAILED_ACCESS)) + return (EINVAL); + + /* Disallow flags not allowed for ordinary files. */ + if (!is_directory) { + if (entry->ae_flags & (ACL_ENTRY_FILE_INHERIT | + ACL_ENTRY_DIRECTORY_INHERIT | + ACL_ENTRY_NO_PROPAGATE_INHERIT | ACL_ENTRY_INHERIT_ONLY)) + return (EINVAL); + } + } + + return (0); +} diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c index f202631ce88b..3f51c5cada88 100644 --- a/sys/kern/subr_bus.c +++ b/sys/kern/subr_bus.c @@ -1017,7 +1017,7 @@ devclass_driver_added(devclass_t dc, driver_t *driver) * Call BUS_DRIVER_ADDED for any existing busses in this class. */ for (i = 0; i < dc->maxunit; i++) - if (dc->devices[i]) + if (dc->devices[i] && device_is_attached(dc->devices[i])) BUS_DRIVER_ADDED(dc->devices[i], driver); /* diff --git a/sys/kern/subr_devstat.c b/sys/kern/subr_devstat.c index bbfed445ed1e..e90df59a5a22 100644 --- a/sys/kern/subr_devstat.c +++ b/sys/kern/subr_devstat.c @@ -469,7 +469,7 @@ static struct devstat * devstat_alloc(void) { struct devstat *dsp; - struct statspage *spp; + struct statspage *spp, *spp2; u_int u; static int once; @@ -479,6 +479,7 @@ devstat_alloc(void) UID_ROOT, GID_WHEEL, 0400, DEVSTAT_DEVICE_NAME); once = 1; } + spp2 = NULL; mtx_lock(&devstat_mutex); for (;;) { TAILQ_FOREACH(spp, &pagelist, list) { @@ -487,24 +488,30 @@ devstat_alloc(void) } if (spp != NULL) break; - /* - * We had no free slot in any of our pages, drop the mutex - * and get another page. In theory we could have more than - * one process doing this at the same time and consequently - * we may allocate more pages than we will need. That is - * Just Too Bad[tm], we can live with that. - */ mtx_unlock(&devstat_mutex); - spp = malloc(sizeof *spp, M_DEVSTAT, M_ZERO | M_WAITOK); - spp->stat = malloc(PAGE_SIZE, M_DEVSTAT, M_ZERO | M_WAITOK); - spp->nfree = statsperpage; - mtx_lock(&devstat_mutex); + spp2 = malloc(sizeof *spp, M_DEVSTAT, M_ZERO | M_WAITOK); + spp2->stat = malloc(PAGE_SIZE, M_DEVSTAT, M_ZERO | M_WAITOK); + spp2->nfree = statsperpage; + /* - * It would make more sense to add the new page at the head - * but the order on the list determine the sequence of the - * mapping so we can't do that. + * If free statspages were added while the lock was released + * just reuse them. */ - TAILQ_INSERT_TAIL(&pagelist, spp, list); + mtx_lock(&devstat_mutex); + TAILQ_FOREACH(spp, &pagelist, list) + if (spp->nfree > 0) + break; + if (spp == NULL) { + spp = spp2; + + /* + * It would make more sense to add the new page at the + * head but the order on the list determine the + * sequence of the mapping so we can't do that. + */ + TAILQ_INSERT_TAIL(&pagelist, spp, list); + } else + break; } dsp = spp->stat; for (u = 0; u < statsperpage; u++) { @@ -515,6 +522,10 @@ devstat_alloc(void) spp->nfree--; dsp->allocated = 1; mtx_unlock(&devstat_mutex); + if (spp2 != NULL && spp2 != spp) { + free(spp2->stat, M_DEVSTAT); + free(spp2, M_DEVSTAT); + } return (dsp); } diff --git a/sys/kern/subr_smp.c b/sys/kern/subr_smp.c index d28001f7cc7b..f226e3a6e012 100644 --- a/sys/kern/subr_smp.c +++ b/sys/kern/subr_smp.c @@ -104,12 +104,6 @@ SYSCTL_INT(_kern_smp, OID_AUTO, forward_signal_enabled, CTLFLAG_RW, &forward_signal_enabled, 0, "Forwarding of a signal to a process on a different CPU"); -/* Enable forwarding of roundrobin to all other cpus */ -static int forward_roundrobin_enabled = 1; -SYSCTL_INT(_kern_smp, OID_AUTO, forward_roundrobin_enabled, CTLFLAG_RW, - &forward_roundrobin_enabled, 0, - "Forwarding of roundrobin to all other CPUs"); - /* Variables needed for SMP rendezvous. */ static volatile int smp_rv_ncpus; static void (*volatile smp_rv_setup_func)(void *arg); @@ -189,33 +183,6 @@ forward_signal(struct thread *td) ipi_selected(1 << id, IPI_AST); } -void -forward_roundrobin(void) -{ - struct pcpu *pc; - struct thread *td; - cpumask_t id, map, me; - - CTR0(KTR_SMP, "forward_roundrobin()"); - - if (!smp_started || cold || panicstr) - return; - if (!forward_roundrobin_enabled) - return; - map = 0; - me = PCPU_GET(cpumask); - SLIST_FOREACH(pc, &cpuhead, pc_allcpu) { - td = pc->pc_curthread; - id = pc->pc_cpumask; - if (id != me && (id & stopped_cpus) == 0 && - !TD_IS_IDLETHREAD(td)) { - td->td_flags |= TDF_NEEDRESCHED; - map |= id; - } - } - ipi_selected(map, IPI_AST); -} - /* * When called the executing CPU will send an IPI to all other CPUs * requesting that they halt execution. diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 9717679eb433..34eaf2059c38 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$"); #include <sys/fcntl.h> #include <sys/file.h> #include <sys/filio.h> +#include <sys/jail.h> #include <sys/mount.h> #include <sys/mbuf.h> #include <sys/protosw.h> @@ -2316,6 +2317,7 @@ sctp_peeloff(td, uap) goto done; td->td_retval[0] = fd; + CURVNET_SET(head->so_vnet); so = sonewconn(head, SS_ISCONNECTED); if (so == NULL) goto noconnection; @@ -2355,6 +2357,7 @@ noconnection: /* * Release explicitly held references before returning. */ + CURVNET_RESTORE(); done: if (nfp != NULL) fdrop(nfp, td); @@ -2433,9 +2436,11 @@ sctp_generic_sendmsg (td, uap) auio.uio_offset = 0; /* XXX */ auio.uio_resid = 0; len = auio.uio_resid = uap->mlen; + CURVNET_SET(so->so_vnet); error = sctp_lower_sosend(so, to, &auio, (struct mbuf *)NULL, (struct mbuf *)NULL, uap->flags, use_rcvinfo, u_sinfo, td); + CURVNET_RESTORE(); if (error) { if (auio.uio_resid != len && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) @@ -2543,9 +2548,11 @@ sctp_generic_sendmsg_iov(td, uap) } } len = auio.uio_resid; + CURVNET_SET(so->so_vnet); error = sctp_lower_sosend(so, to, &auio, (struct mbuf *)NULL, (struct mbuf *)NULL, uap->flags, use_rcvinfo, u_sinfo, td); + CURVNET_RESTORE(); if (error) { if (auio.uio_resid != len && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) @@ -2665,9 +2672,11 @@ sctp_generic_recvmsg(td, uap) if (KTRPOINT(td, KTR_GENIO)) ktruio = cloneuio(&auio); #endif /* KTRACE */ + CURVNET_SET(so->so_vnet); error = sctp_sorecvmsg(so, &auio, (struct mbuf **)NULL, fromsa, fromlen, &msg_flags, (struct sctp_sndrcvinfo *)&sinfo, 1); + CURVNET_RESTORE(); if (error) { if (auio.uio_resid != (int)len && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) diff --git a/sys/mips/include/param.h b/sys/mips/include/param.h index 10f348a7cf8f..b81864940467 100644 --- a/sys/mips/include/param.h +++ b/sys/mips/include/param.h @@ -115,6 +115,8 @@ #define SEGOFSET (NBSEG-1) /* byte offset into segment */ #define SEGSHIFT 22 /* LOG2(NBSEG) */ +#define MAXPAGESIZES 1 /* maximum number of supported page sizes */ + /* XXXimp: This has moved to vmparam.h */ /* Also, this differs from the mips2 definition, but likely is better */ /* since this means the kernel won't chew up TLBs when it is executing */ diff --git a/sys/modules/Makefile b/sys/modules/Makefile index 8f37b61954f4..49d88600d1a6 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -298,7 +298,7 @@ SUBDIR= ${_3dfx} \ wlan_xauth \ ${_wpi} \ ${_wpifw} \ - x86emu \ + ${_x86bios} \ ${_xe} \ xfs \ xl \ @@ -456,6 +456,7 @@ _padlock= padlock _s3= s3 _twa= twa _vesa= vesa +_x86bios= x86bios .elif ${MACHINE} == "pc98" _canbepm= canbepm _canbus= canbus @@ -528,6 +529,7 @@ _padlock= padlock .endif _pccard= pccard _rdma= rdma +_s3= s3 _safe= safe _scsi_low= scsi_low _smbfs= smbfs @@ -538,6 +540,7 @@ _sppp= sppp _tmpfs= tmpfs _twa= twa _vesa= vesa +_x86bios= x86bios _wi= wi _wpi= wpi _wpifw= wpifw diff --git a/sys/modules/procfs/Makefile b/sys/modules/procfs/Makefile index 6c840edcfc04..c3b36337f02e 100644 --- a/sys/modules/procfs/Makefile +++ b/sys/modules/procfs/Makefile @@ -13,6 +13,7 @@ SRCS+= procfs_ioctl.c SRCS+= procfs_map.c SRCS+= procfs_mem.c SRCS+= procfs_note.c +SRCS+= procfs_osrel.c SRCS+= procfs_regs.c SRCS+= procfs_rlimit.c SRCS+= procfs_status.c diff --git a/sys/modules/x86bios/Makefile b/sys/modules/x86bios/Makefile new file mode 100644 index 000000000000..8b5fa302a78f --- /dev/null +++ b/sys/modules/x86bios/Makefile @@ -0,0 +1,10 @@ +# $FreeBSD$ + +KMOD= x86bios +SRCS= opt_x86bios.h + +.PATH: ${.CURDIR}/../../contrib/x86emu +.PATH: ${.CURDIR}/../../compat/x86bios +SRCS+= x86bios.c x86bios_alloc.c x86emu.c x86emu_util.c + +.include <bsd.kmod.mk> diff --git a/sys/modules/x86emu/Makefile b/sys/modules/x86emu/Makefile deleted file mode 100644 index 3991d6c70d05..000000000000 --- a/sys/modules/x86emu/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $FreeBSD$ - -.PATH: ${.CURDIR}/../../contrib/x86emu - -KMOD= x86emu -SRCS= x86emu.c x86emu_util.c - -.include <bsd.kmod.mk> diff --git a/sys/net/if.c b/sys/net/if.c index c0ff443d6dc1..55de666a6360 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1432,9 +1432,9 @@ ifa_add_loopback_route(struct ifaddr *ifa, struct sockaddr *ia) if (error == 0 && rt != NULL) { RT_LOCK(rt); ((struct sockaddr_dl *)rt->rt_gateway)->sdl_type = - rt->rt_ifp->if_type; + ifa->ifa_ifp->if_type; ((struct sockaddr_dl *)rt->rt_gateway)->sdl_index = - rt->rt_ifp->if_index; + ifa->ifa_ifp->if_index; RT_REMREF(rt); RT_UNLOCK(rt); } else if (error != 0) diff --git a/sys/net/if_llatbl.c b/sys/net/if_llatbl.c index b66d6e154b27..4991c81d92c6 100644 --- a/sys/net/if_llatbl.c +++ b/sys/net/if_llatbl.c @@ -57,11 +57,14 @@ __FBSDID("$FreeBSD$"); MALLOC_DEFINE(M_LLTABLE, "lltable", "link level address tables"); -static SLIST_HEAD(, lltable) lltables = SLIST_HEAD_INITIALIZER(lltables); +static VNET_DEFINE(SLIST_HEAD(, lltable), lltables); +#define V_lltables VNET(lltables) extern void arprequest(struct ifnet *, struct in_addr *, struct in_addr *, u_char *); +static void vnet_lltable_init(void); + struct rwlock lltable_rwlock; RW_SYSINIT(lltable_rwlock, &lltable_rwlock, "lltable_rwlock"); @@ -75,7 +78,7 @@ lltable_sysctl_dumparp(int af, struct sysctl_req *wr) int error = 0; LLTABLE_RLOCK(); - SLIST_FOREACH(llt, &lltables, llt_link) { + SLIST_FOREACH(llt, &V_lltables, llt_link) { if (llt->llt_af == af) { error = llt->llt_dump(llt, wr); if (error != 0) @@ -157,7 +160,7 @@ lltable_free(struct lltable *llt) KASSERT(llt != NULL, ("%s: llt is NULL", __func__)); LLTABLE_WLOCK(); - SLIST_REMOVE(&lltables, llt, lltable, llt_link); + SLIST_REMOVE(&V_lltables, llt, lltable, llt_link); LLTABLE_WUNLOCK(); for (i=0; i < LLTBL_HASHTBL_SIZE; i++) { @@ -180,7 +183,7 @@ lltable_drain(int af) register int i; LLTABLE_RLOCK(); - SLIST_FOREACH(llt, &lltables, llt_link) { + SLIST_FOREACH(llt, &V_lltables, llt_link) { if (llt->llt_af != af) continue; @@ -202,7 +205,7 @@ lltable_prefix_free(int af, struct sockaddr *prefix, struct sockaddr *mask) struct lltable *llt; LLTABLE_RLOCK(); - SLIST_FOREACH(llt, &lltables, llt_link) { + SLIST_FOREACH(llt, &V_lltables, llt_link) { if (llt->llt_af != af) continue; @@ -232,7 +235,7 @@ lltable_init(struct ifnet *ifp, int af) LIST_INIT(&llt->lle_head[i]); LLTABLE_WLOCK(); - SLIST_INSERT_HEAD(&lltables, llt, llt_link); + SLIST_INSERT_HEAD(&V_lltables, llt, llt_link); LLTABLE_WUNLOCK(); return (llt); @@ -302,7 +305,7 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info) /* XXX linked list may be too expensive */ LLTABLE_RLOCK(); - SLIST_FOREACH(llt, &lltables, llt_link) { + SLIST_FOREACH(llt, &V_lltables, llt_link) { if (llt->llt_af == dst->sa_family && llt->llt_ifp == ifp) break; @@ -367,3 +370,13 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info) return (error); } + +static void +vnet_lltable_init() +{ + + SLIST_INIT(&V_lltables); +} +VNET_SYSINIT(vnet_lltable_init, SI_SUB_PSEUDO, SI_ORDER_FIRST, + vnet_lltable_init, NULL); + diff --git a/sys/net80211/ieee80211.h b/sys/net80211/ieee80211.h index 5ddca24e69f4..712c2a8dcb2d 100644 --- a/sys/net80211/ieee80211.h +++ b/sys/net80211/ieee80211.h @@ -708,7 +708,7 @@ enum { IEEE80211_ELEMID_VENDOR = 221, /* vendor private */ /* - * 802.11s IEs based on D3.0 spec and were not assigned by + * 802.11s IEs based on D3.03 spec and were not assigned by * ANA. Beware changing them because some of them are being * kept compatible with Linux. */ @@ -726,10 +726,9 @@ enum { IEEE80211_ELEMID_MESHPREQ = 68, IEEE80211_ELEMID_MESHPREP = 69, IEEE80211_ELEMID_MESHPERR = 70, - IEEE80211_ELEMID_MESHPU = 53, - IEEE80211_ELEMID_MESHPUC = 54, + IEEE80211_ELEMID_MESHPXU = 53, + IEEE80211_ELEMID_MESHPXUC = 54, IEEE80211_ELEMID_MESHAH = 60, /* Abbreviated Handshake */ - IEEE80211_ELEMID_MESHPEERVER = 80, /* Peering Protocol Version */ }; struct ieee80211_tim_ie { @@ -925,6 +924,9 @@ enum { IEEE80211_REASON_MESH_INVALID_GTK = 8, /* 11s */ IEEE80211_REASON_MESH_INCONS_PARAMS = 9, /* 11s */ IEEE80211_REASON_MESH_INVALID_SECURITY = 10, /* 11s */ + IEEE80211_REASON_MESH_PERR_UNSPEC = 11, /* 11s */ + IEEE80211_REASON_MESH_PERR_NO_FI = 12, /* 11s */ + IEEE80211_REASON_MESH_PERR_DEST_UNREACH = 13, /* 11s */ IEEE80211_STATUS_SUCCESS = 0, IEEE80211_STATUS_UNSPECIFIED = 1, diff --git a/sys/net80211/ieee80211_hwmp.c b/sys/net80211/ieee80211_hwmp.c index 040941e8425d..2468169122ab 100644 --- a/sys/net80211/ieee80211_hwmp.c +++ b/sys/net80211/ieee80211_hwmp.c @@ -188,10 +188,7 @@ SYSCTL_PROC(_net_wlan_hwmp, OID_AUTO, rannint, CTLTYPE_INT | CTLFLAG_RW, #define IEEE80211_HWMP_DEFAULT_MAXHOPS 31 -static ieee80211_recv_action_func hwmp_recv_action_meshpath_preq; -static ieee80211_recv_action_func hwmp_recv_action_meshpath_prep; -static ieee80211_recv_action_func hwmp_recv_action_meshpath_perr; -static ieee80211_recv_action_func hwmp_recv_action_meshpath_rann; +static ieee80211_recv_action_func hwmp_recv_action_meshpath; static struct ieee80211_mesh_proto_path mesh_proto_hwmp = { .mpp_descr = "HWMP", @@ -217,16 +214,10 @@ ieee80211_hwmp_init(void) ieee80211_hwmp_rannint = msecs_to_ticks(1*1000); /* - * Register action frame handlers. + * Register action frame handler. */ ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESHPATH, - IEEE80211_ACTION_MESHPATH_REQ, hwmp_recv_action_meshpath_preq); - ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESHPATH, - IEEE80211_ACTION_MESHPATH_REP, hwmp_recv_action_meshpath_prep); - ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESHPATH, - IEEE80211_ACTION_MESHPATH_ERR, hwmp_recv_action_meshpath_perr); - ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESHPATH, - IEEE80211_ACTION_MESHPATH_RANN, hwmp_recv_action_meshpath_rann); + IEEE80211_ACTION_MESHPATH_SEL, hwmp_recv_action_meshpath); /* NB: default is 5 secs per spec */ mesh_proto_hwmp.mpp_inact = msecs_to_ticks(5*1000); @@ -285,17 +276,23 @@ hwmp_newstate(struct ieee80211vap *vap, enum ieee80211_state ostate, int arg) } static int -hwmp_recv_action_meshpath_preq(struct ieee80211_node *ni, +hwmp_recv_action_meshpath(struct ieee80211_node *ni, const struct ieee80211_frame *wh, const uint8_t *frm, const uint8_t *efrm) { struct ieee80211vap *vap = ni->ni_vap; struct ieee80211_meshpreq_ie preq; + struct ieee80211_meshprep_ie prep; + struct ieee80211_meshperr_ie perr; + struct ieee80211_meshrann_ie rann; const uint8_t *iefrm = frm + 2; /* action + code */ + int found = 0; while (efrm - iefrm > 1) { IEEE80211_VERIFY_LENGTH(efrm - iefrm, iefrm[1] + 2, return 0); - if (*iefrm == IEEE80211_ELEMID_MESHPREQ) { + switch (*iefrm) { + case IEEE80211_ELEMID_MESHPREQ: + { const struct ieee80211_meshpreq_ie *mpreq = (const struct ieee80211_meshpreq_ie *) iefrm; /* XXX > 1 target */ @@ -305,7 +302,7 @@ hwmp_recv_action_meshpath_preq(struct ieee80211_node *ni, IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP, wh, NULL, "%s", "PREQ with wrong len"); vap->iv_stats.is_rx_mgtdiscard++; - return 1; + break; } memcpy(&preq, mpreq, sizeof(preq)); preq.preq_id = LE_READ_4(&mpreq->preq_id); @@ -315,28 +312,11 @@ hwmp_recv_action_meshpath_preq(struct ieee80211_node *ni, preq.preq_targets[0].target_seq = LE_READ_4(&mpreq->preq_targets[0].target_seq); hwmp_recv_preq(vap, ni, wh, &preq); - return 0; + found++; + break; } - iefrm += iefrm[1] + 2; - } - IEEE80211_DISCARD(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP, - wh, NULL, "%s", "PREQ without IE"); - vap->iv_stats.is_rx_mgtdiscard++; - return 0; -} - -static int -hwmp_recv_action_meshpath_prep(struct ieee80211_node *ni, - const struct ieee80211_frame *wh, - const uint8_t *frm, const uint8_t *efrm) -{ - struct ieee80211vap *vap = ni->ni_vap; - struct ieee80211_meshprep_ie prep; - const uint8_t *iefrm = frm + 2; /* action + code */ - - while (efrm - iefrm > 1) { - IEEE80211_VERIFY_LENGTH(efrm - iefrm, iefrm[1] + 2, return 0); - if (*iefrm == IEEE80211_ELEMID_MESHPREP) { + case IEEE80211_ELEMID_MESHPREP: + { const struct ieee80211_meshprep_ie *mprep = (const struct ieee80211_meshprep_ie *) iefrm; if (mprep->prep_len != @@ -345,7 +325,7 @@ hwmp_recv_action_meshpath_prep(struct ieee80211_node *ni, IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP, wh, NULL, "%s", "PREP with wrong len"); vap->iv_stats.is_rx_mgtdiscard++; - return 1; + break; } memcpy(&prep, mprep, sizeof(prep)); prep.prep_targetseq = LE_READ_4(&mprep->prep_targetseq); @@ -353,28 +333,11 @@ hwmp_recv_action_meshpath_prep(struct ieee80211_node *ni, prep.prep_metric = LE_READ_4(&mprep->prep_metric); prep.prep_origseq = LE_READ_4(&mprep->prep_origseq); hwmp_recv_prep(vap, ni, wh, &prep); - return 0; + found++; + break; } - iefrm += iefrm[1] + 2; - } - IEEE80211_DISCARD(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP, - wh, NULL, "%s", "PREP without IE"); - vap->iv_stats.is_rx_mgtdiscard++; - return 0; -} - -static int -hwmp_recv_action_meshpath_perr(struct ieee80211_node *ni, - const struct ieee80211_frame *wh, - const uint8_t *frm, const uint8_t *efrm) -{ - struct ieee80211_meshperr_ie perr; - struct ieee80211vap *vap = ni->ni_vap; - const uint8_t *iefrm = frm + 2; /* action + code */ - - while (efrm - iefrm > 1) { - IEEE80211_VERIFY_LENGTH(efrm - iefrm, iefrm[1] + 2, return 0); - if (*iefrm == IEEE80211_ELEMID_MESHPERR) { + case IEEE80211_ELEMID_MESHPERR: + { const struct ieee80211_meshperr_ie *mperr = (const struct ieee80211_meshperr_ie *) iefrm; /* XXX > 1 target */ @@ -384,34 +347,17 @@ hwmp_recv_action_meshpath_perr(struct ieee80211_node *ni, IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP, wh, NULL, "%s", "PERR with wrong len"); vap->iv_stats.is_rx_mgtdiscard++; - return 1; + break; } memcpy(&perr, mperr, sizeof(perr)); perr.perr_dests[0].dest_seq = LE_READ_4(&mperr->perr_dests[0].dest_seq); hwmp_recv_perr(vap, ni, wh, &perr); - return 0; + found++; + break; } - iefrm += iefrm[1] + 2; - } - IEEE80211_DISCARD(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP, - wh, NULL, "%s", "PERR without IE"); - vap->iv_stats.is_rx_mgtdiscard++; - return 0; -} - -static int -hwmp_recv_action_meshpath_rann(struct ieee80211_node *ni, - const struct ieee80211_frame *wh, - const uint8_t *frm, const uint8_t *efrm) -{ - struct ieee80211vap *vap = ni->ni_vap; - struct ieee80211_meshrann_ie rann; - const uint8_t *iefrm = frm + 2; /* action + code */ - - while (efrm - iefrm > 1) { - IEEE80211_VERIFY_LENGTH(efrm - iefrm, iefrm[1] + 2, return 0); - if (*iefrm == IEEE80211_ELEMID_MESHRANN) { + case IEEE80211_ELEMID_MESHRANN: + { const struct ieee80211_meshrann_ie *mrann = (const struct ieee80211_meshrann_ie *) iefrm; if (mrann->rann_len != @@ -426,13 +372,18 @@ hwmp_recv_action_meshpath_rann(struct ieee80211_node *ni, rann.rann_seq = LE_READ_4(&mrann->rann_seq); rann.rann_metric = LE_READ_4(&mrann->rann_metric); hwmp_recv_rann(vap, ni, wh, &rann); - return 0; + found++; + break; + } } iefrm += iefrm[1] + 2; } - IEEE80211_DISCARD(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP, - wh, NULL, "%s", "RANN without IE"); - vap->iv_stats.is_rx_mgtdiscard++; + if (!found) { + IEEE80211_DISCARD(vap, + IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP, + wh, NULL, "%s", "PATH SEL action without IE"); + vap->iv_stats.is_rx_mgtdiscard++; + } return 0; } @@ -480,24 +431,21 @@ hwmp_send_action(struct ieee80211_node *ni, return ENOMEM; } *frm++ = IEEE80211_ACTION_CAT_MESHPATH; + *frm++ = IEEE80211_ACTION_MESHPATH_SEL; switch (*ie) { case IEEE80211_ELEMID_MESHPREQ: - *frm++ = IEEE80211_ACTION_MESHPATH_REQ; frm = hwmp_add_meshpreq(frm, (struct ieee80211_meshpreq_ie *)ie); break; case IEEE80211_ELEMID_MESHPREP: - *frm++ = IEEE80211_ACTION_MESHPATH_REP; frm = hwmp_add_meshprep(frm, (struct ieee80211_meshprep_ie *)ie); break; case IEEE80211_ELEMID_MESHPERR: - *frm++ = IEEE80211_ACTION_MESHPATH_ERR; frm = hwmp_add_meshperr(frm, (struct ieee80211_meshperr_ie *)ie); break; case IEEE80211_ELEMID_MESHRANN: - *frm++ = IEEE80211_ACTION_MESHPATH_RANN; frm = hwmp_add_meshrann(frm, (struct ieee80211_meshrann_ie *)ie); break; @@ -528,6 +476,11 @@ hwmp_send_action(struct ieee80211_node *ni, return ic->ic_raw_xmit(ni, m, ¶ms); } +#define ADDSHORT(frm, v) do { \ + frm[0] = (v) & 0xff; \ + frm[1] = (v) >> 8; \ + frm += 2; \ +} while (0) #define ADDWORD(frm, v) do { \ LE_WRITE_4(frm, v); \ frm += 4; \ @@ -592,12 +545,14 @@ hwmp_add_meshperr(uint8_t *frm, const struct ieee80211_meshperr_ie *perr) *frm++ = IEEE80211_ELEMID_MESHPERR; *frm++ = sizeof(struct ieee80211_meshperr_ie) - 2 + (perr->perr_ndests - 1) * sizeof(*perr->perr_dests); - *frm++ = perr->perr_mode; + *frm++ = perr->perr_ttl; *frm++ = perr->perr_ndests; for (i = 0; i < perr->perr_ndests; i++) { + *frm += perr->perr_dests[i].dest_flags; IEEE80211_ADDR_COPY(frm, perr->perr_dests[i].dest_addr); frm += 6; ADDWORD(frm, perr->perr_dests[i].dest_seq); + ADDSHORT(frm, perr->perr_dests[i].dest_rcode); } return frm; } @@ -1138,12 +1093,15 @@ hwmp_send_prep(struct ieee80211_node *ni, sizeof(struct ieee80211_meshprep_ie)); } +#define PERR_DFLAGS(n) perr.perr_dests[n].dest_flags #define PERR_DADDR(n) perr.perr_dests[n].dest_addr #define PERR_DSEQ(n) perr.perr_dests[n].dest_seq +#define PERR_DRCODE(n) perr.perr_dests[n].dest_rcode static void hwmp_peerdown(struct ieee80211_node *ni) { struct ieee80211vap *vap = ni->ni_vap; + struct ieee80211_mesh_state *ms = vap->iv_mesh; struct ieee80211_meshperr_ie perr; struct ieee80211_mesh_route *rt; struct ieee80211_hwmp_route *hr; @@ -1154,19 +1112,27 @@ hwmp_peerdown(struct ieee80211_node *ni) hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route); IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, "%s", "delete route entry"); - perr.perr_mode = 0; + perr.perr_ttl = ms->ms_ttl; perr.perr_ndests = 1; + if (hr->hr_seq == 0) + PERR_DFLAGS(0) |= IEEE80211_MESHPERR_DFLAGS_USN; + PERR_DFLAGS(0) |= IEEE80211_MESHPERR_DFLAGS_RC; IEEE80211_ADDR_COPY(PERR_DADDR(0), rt->rt_dest); PERR_DSEQ(0) = hr->hr_seq; + PERR_DRCODE(0) = IEEE80211_REASON_MESH_PERR_DEST_UNREACH; /* NB: flush everything passing through peer */ ieee80211_mesh_rt_flush_peer(vap, ni->ni_macaddr); hwmp_send_perr(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &perr); } +#undef PERR_DFLAGS #undef PERR_DADDR #undef PERR_DSEQ +#undef PERR_DRCODE +#define PERR_DFLAGS(n) perr->perr_dests[n].dest_flags #define PERR_DADDR(n) perr->perr_dests[n].dest_addr #define PERR_DSEQ(n) perr->perr_dests[n].dest_seq +#define PERR_DRCODE(n) perr->perr_dests[n].dest_rcode static void hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni, const struct ieee80211_frame *wh, const struct ieee80211_meshperr_ie *perr) @@ -1192,9 +1158,9 @@ hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni, rt = ieee80211_mesh_rt_find(vap, PERR_DADDR(i)); if (rt == NULL) continue; - hr = IEEE80211_MESH_ROUTE_PRIV(rt, - struct ieee80211_hwmp_route); - if (HWMP_SEQ_GEQ(PERR_DSEQ(i), hr->hr_seq)) { + hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route); + if (!(PERR_DFLAGS(0) & IEEE80211_MESHPERR_DFLAGS_USN) && + HWMP_SEQ_GEQ(PERR_DSEQ(i), hr->hr_seq)) { ieee80211_mesh_rt_del(vap, rt->rt_dest); ieee80211_mesh_rt_flush_peer(vap, rt->rt_dest); rt = NULL; @@ -1205,10 +1171,11 @@ hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni, * Propagate the PERR if we previously found it on our routing table. * XXX handle ndest > 1 */ - if (forward) { + if (forward && perr->perr_ttl > 1) { IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, "propagate PERR from %s", ether_sprintf(wh->i_addr2)); memcpy(&pperr, perr, sizeof(*perr)); + pperr.perr_ttl--; hwmp_send_perr(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &pperr); } diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c index 722749576ba3..b0bfe8892d07 100644 --- a/sys/net80211/ieee80211_mesh.c +++ b/sys/net80211/ieee80211_mesh.c @@ -87,10 +87,10 @@ static void mesh_peer_timeout_backoff(struct ieee80211_node *); static void mesh_peer_timeout_cb(void *); static __inline void mesh_peer_timeout_stop(struct ieee80211_node *); -static int mesh_verify_meshpeerver(struct ieee80211vap *, const uint8_t *); static int mesh_verify_meshid(struct ieee80211vap *, const uint8_t *); static int mesh_verify_meshconf(struct ieee80211vap *, const uint8_t *); -static int mesh_verify_meshpeer(struct ieee80211vap *, const uint8_t *); +static int mesh_verify_meshpeer(struct ieee80211vap *, uint8_t, + const uint8_t *); uint32_t mesh_airtime_calc(struct ieee80211_node *); /* @@ -1544,19 +1544,16 @@ static const struct ieee80211_meshpeer_ie * mesh_parse_meshpeering_action(struct ieee80211_node *ni, const struct ieee80211_frame *wh, /* XXX for VERIFY_LENGTH */ const uint8_t *frm, const uint8_t *efrm, - struct ieee80211_meshpeer_ie *mp) + struct ieee80211_meshpeer_ie *mp, uint8_t subtype) { struct ieee80211vap *vap = ni->ni_vap; const struct ieee80211_meshpeer_ie *mpie; - const uint8_t *meshid, *meshconf, *meshpeerver, *meshpeer; + const uint8_t *meshid, *meshconf, *meshpeer; - meshid = meshconf = meshpeerver = meshpeer = NULL; + meshid = meshconf = meshpeer = NULL; while (efrm - frm > 1) { IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1] + 2, return NULL); switch (*frm) { - case IEEE80211_ELEMID_MESHPEERVER: - meshpeerver = frm; - break; case IEEE80211_ELEMID_MESHID: meshid = frm; break; @@ -1567,12 +1564,10 @@ mesh_parse_meshpeering_action(struct ieee80211_node *ni, meshpeer = frm; mpie = (const struct ieee80211_meshpeer_ie *) frm; memset(mp, 0, sizeof(*mp)); - mp->peer_subtype = mpie->peer_subtype; mp->peer_llinkid = LE_READ_2(&mpie->peer_llinkid); /* NB: peer link ID is optional on these frames */ - if (mpie->peer_subtype == - IEEE80211_MESH_PEER_LINK_CLOSE && - mpie->peer_len == 5) { + if (subtype == IEEE80211_MESH_PEER_LINK_CLOSE && + mpie->peer_len == 8) { mp->peer_linkid = 0; mp->peer_rcode = LE_READ_2(&mpie->peer_linkid); } else { @@ -1589,12 +1584,12 @@ mesh_parse_meshpeering_action(struct ieee80211_node *ni, * close subtype don't have a Mesh Configuration IE. * If if fails validation, close the peer link. */ - KASSERT(meshpeer != NULL && mp->peer_subtype != - IEEE80211_ACTION_MESHPEERING_CLOSE, ("parsing close action")); + KASSERT(meshpeer != NULL && + subtype != IEEE80211_ACTION_MESHPEERING_CLOSE, + ("parsing close action")); - if (mesh_verify_meshpeerver(vap, meshpeerver) || - mesh_verify_meshid(vap, meshid) || - mesh_verify_meshpeer(vap, meshpeer) || + if (mesh_verify_meshid(vap, meshid) || + mesh_verify_meshpeer(vap, subtype, meshpeer) || mesh_verify_meshconf(vap, meshconf)) { uint16_t args[3]; @@ -1638,7 +1633,8 @@ mesh_recv_action_meshpeering_open(struct ieee80211_node *ni, uint16_t args[3]; /* +2+2 for action + code + capabilites */ - meshpeer = mesh_parse_meshpeering_action(ni, wh, frm+2+2, efrm, &ie); + meshpeer = mesh_parse_meshpeering_action(ni, wh, frm+2+2, efrm, &ie, + IEEE80211_ACTION_MESHPEERING_OPEN); if (meshpeer == NULL) { return 0; } @@ -1770,7 +1766,8 @@ mesh_recv_action_meshpeering_confirm(struct ieee80211_node *ni, uint16_t args[3]; /* +2+2+2+2 for action + code + capabilites + status code + AID */ - meshpeer = mesh_parse_meshpeering_action(ni, wh, frm+2+2+2+2, efrm, &ie); + meshpeer = mesh_parse_meshpeering_action(ni, wh, frm+2+2+2+2, efrm, &ie, + IEEE80211_ACTION_MESHPEERING_CONFIRM); if (meshpeer == NULL) { return 0; } @@ -1933,7 +1930,6 @@ mesh_send_action_meshpeering_open(struct ieee80211_node *ni, ic->ic_headroom + sizeof(struct ieee80211_frame), sizeof(uint16_t) /* action+category */ + sizeof(uint16_t) /* capabilites */ - + sizeof(struct ieee80211_meshpeerver_ie) + 2 + IEEE80211_RATE_SIZE + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE) + 2 + IEEE80211_MESHID_LEN @@ -1946,7 +1942,6 @@ mesh_send_action_meshpeering_open(struct ieee80211_node *ni, * [1] category * [1] action * [2] capabilities - * [tlv] mesh peer protocol version * [tlv] rates * [tlv] xrates * [tlv] mesh id @@ -1956,7 +1951,6 @@ mesh_send_action_meshpeering_open(struct ieee80211_node *ni, *frm++ = category; *frm++ = action; ADDSHORT(frm, ieee80211_getcapinfo(vap, ni->ni_chan)); - frm = ieee80211_add_meshpeerver(frm, vap); rs = ieee80211_get_suprates(ic, ic->ic_curchan); frm = ieee80211_add_rates(frm, rs); frm = ieee80211_add_xrates(frm, rs); @@ -1999,7 +1993,6 @@ mesh_send_action_meshpeering_confirm(struct ieee80211_node *ni, + sizeof(uint16_t) /* capabilites */ + sizeof(uint16_t) /* status code */ + sizeof(uint16_t) /* AID */ - + sizeof(struct ieee80211_meshpeerver_ie) + 2 + IEEE80211_RATE_SIZE + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE) + 2 + IEEE80211_MESHID_LEN @@ -2014,7 +2007,6 @@ mesh_send_action_meshpeering_confirm(struct ieee80211_node *ni, * [2] capabilities * [2] status code * [2] association id (peer ID) - * [tlv] mesh peer protocol version * [tlv] rates * [tlv] xrates * [tlv] mesh id @@ -2026,7 +2018,6 @@ mesh_send_action_meshpeering_confirm(struct ieee80211_node *ni, ADDSHORT(frm, ieee80211_getcapinfo(vap, ni->ni_chan)); ADDSHORT(frm, 0); /* status code */ ADDSHORT(frm, args[1]); /* AID */ - frm = ieee80211_add_meshpeerver(frm, vap); rs = ieee80211_get_suprates(ic, ic->ic_curchan); frm = ieee80211_add_rates(frm, rs); frm = ieee80211_add_xrates(frm, rs); @@ -2067,7 +2058,6 @@ mesh_send_action_meshpeering_close(struct ieee80211_node *ni, ic->ic_headroom + sizeof(struct ieee80211_frame), sizeof(uint16_t) /* action+category */ + sizeof(uint16_t) /* reason code */ - + sizeof(struct ieee80211_meshpeerver_ie) + 2 + IEEE80211_MESHID_LEN + sizeof(struct ieee80211_meshpeer_ie) ); @@ -2077,14 +2067,12 @@ mesh_send_action_meshpeering_close(struct ieee80211_node *ni, * [1] category * [1] action * [2] reason code - * [tlv] mesh peer protocol version * [tlv] mesh id * [tlv] mesh peer link mgmt */ *frm++ = category; *frm++ = action; ADDSHORT(frm, args[2]); /* reason code */ - frm = ieee80211_add_meshpeerver(frm, vap); frm = ieee80211_add_meshid(frm, vap); frm = ieee80211_add_meshpeer(frm, IEEE80211_MESH_PEER_LINK_CLOSE, @@ -2279,19 +2267,6 @@ mesh_peer_timeout_cb(void *arg) } static int -mesh_verify_meshpeerver(struct ieee80211vap *vap, const uint8_t *ie) -{ - static const uint8_t peer[4] = IEEE80211_MESHPEERVER_PEER; - const struct ieee80211_meshpeerver_ie *meshpeerver = - (const struct ieee80211_meshpeerver_ie *) ie; - - if (meshpeerver->peerver_len != - sizeof(struct ieee80211_meshpeerver_ie) - 2) - return 1; - return memcmp(meshpeerver->peerver_proto, peer, 4); -} - -static int mesh_verify_meshid(struct ieee80211vap *vap, const uint8_t *ie) { struct ieee80211_mesh_state *ms = vap->iv_mesh; @@ -2364,26 +2339,28 @@ mesh_verify_meshconf(struct ieee80211vap *vap, const uint8_t *ie) } static int -mesh_verify_meshpeer(struct ieee80211vap *vap, const uint8_t *ie) +mesh_verify_meshpeer(struct ieee80211vap *vap, uint8_t subtype, + const uint8_t *ie) { const struct ieee80211_meshpeer_ie *meshpeer = (const struct ieee80211_meshpeer_ie *) ie; - if (meshpeer == NULL) + if (meshpeer == NULL || meshpeer->peer_len < 6 || + meshpeer->peer_len > 10) return 1; - switch (meshpeer->peer_subtype) { + switch (subtype) { case IEEE80211_MESH_PEER_LINK_OPEN: - if (meshpeer->peer_len != 3) + if (meshpeer->peer_len != 6) return 1; break; case IEEE80211_MESH_PEER_LINK_CONFIRM: - if (meshpeer->peer_len != 5) + if (meshpeer->peer_len != 8) return 1; break; case IEEE80211_MESH_PEER_LINK_CLOSE: - if (meshpeer->peer_len < 5) + if (meshpeer->peer_len < 8) return 1; - if (meshpeer->peer_len == 5 && meshpeer->peer_linkid != 0) + if (meshpeer->peer_len == 8 && meshpeer->peer_linkid != 0) return 1; if (meshpeer->peer_rcode == 0) return 1; @@ -2449,53 +2426,40 @@ ieee80211_add_meshconf(uint8_t *frm, struct ieee80211vap *vap) } /* - * Add a Mesh Peer Protocol IE to a frame. - * XXX: needs to grow support for Abbreviated Handshake - */ -uint8_t * -ieee80211_add_meshpeerver(uint8_t *frm, struct ieee80211vap *vap) -{ - static struct ieee80211_meshpeerver_ie ie = { - .peerver_ie = IEEE80211_ELEMID_MESHPEERVER, - .peerver_len = 4, - .peerver_proto = IEEE80211_MESHPEERVER_PEER, - }; - - KASSERT(vap->iv_opmode == IEEE80211_M_MBSS, ("not a MBSS vap")); - - memcpy(frm, &ie, sizeof(ie)); - return frm + sizeof(ie); -} - -/* * Add a Mesh Peer Management IE to a frame. */ uint8_t * ieee80211_add_meshpeer(uint8_t *frm, uint8_t subtype, uint16_t localid, uint16_t peerid, uint16_t reason) { + /* XXX change for AH */ + static const uint8_t meshpeerproto[4] = IEEE80211_MESH_PEER_PROTO; + KASSERT(localid != 0, ("localid == 0")); *frm++ = IEEE80211_ELEMID_MESHPEER; switch (subtype) { case IEEE80211_MESH_PEER_LINK_OPEN: - *frm++ = 3; /* length */ - *frm++ = subtype; + *frm++ = 6; /* length */ + memcpy(frm, meshpeerproto, 4); + frm += 4; ADDSHORT(frm, localid); /* local ID */ break; case IEEE80211_MESH_PEER_LINK_CONFIRM: KASSERT(peerid != 0, ("sending peer confirm without peer id")); - *frm++ = 5; /* length */ - *frm++ = subtype; + *frm++ = 8; /* length */ + memcpy(frm, meshpeerproto, 4); + frm += 4; ADDSHORT(frm, localid); /* local ID */ ADDSHORT(frm, peerid); /* peer ID */ break; case IEEE80211_MESH_PEER_LINK_CLOSE: if (peerid) - *frm++ = 7; /* length */ + *frm++ = 10; /* length */ else - *frm++ = 5; /* length */ - *frm++ = subtype; + *frm++ = 8; /* length */ + memcpy(frm, meshpeerproto, 4); + frm += 4; ADDSHORT(frm, localid); /* local ID */ if (peerid) ADDSHORT(frm, peerid); /* peer ID */ diff --git a/sys/net80211/ieee80211_mesh.h b/sys/net80211/ieee80211_mesh.h index b02c257a5e52..e3ce79a4945e 100644 --- a/sys/net80211/ieee80211_mesh.h +++ b/sys/net80211/ieee80211_mesh.h @@ -34,7 +34,7 @@ #define IEEE80211_MESH_DEFAULT_TTL 31 /* - * NB: all structures are__packed so sizeof works on arm, et. al. + * NB: all structures are __packed so sizeof works on arm, et. al. */ /* * 802.11s Information Elements. @@ -116,28 +116,11 @@ struct ieee80211_meshcngst_ie { AC_BE, AC_VI, AC_VO */ } __packed; -/* Peer Version */ -struct ieee80211_meshpeerver_ie { - uint8_t peerver_ie; /* IEEE80211_ELEMID_MESHPEERVER */ - uint8_t peerver_len; - uint8_t peerver_proto[4]; -} __packed; -/* Mesh Peering Management Protocol */ -#define IEEE80211_MESHPEERVER_PEER_OUI 0x00, 0x0f, 0xac -#define IEEE80211_MESHPEERVER_PEER_VALUE 0x2a -#define IEEE80211_MESHPEERVER_PEER { IEEE80211_MESHPEERVER_PEER_OUI, \ - IEEE80211_MESHPEERVER_PEER_VALUE } -/* Abbreviated Handshake Protocol */ -#define IEEE80211_MESHPEERVER_AH_OUI 0x00, 0x0f, 0xac -#define IEEE80211_MESHPEERVER_AH_VALUE 0x2b -#define IEEE80211_MESHPEERVER_AH { IEEE80211_MESHPEERVER_AH_OUI, \ - IEEE80211_MESHPEERVER_AH_VALUE } - /* Peer Link Management */ struct ieee80211_meshpeer_ie { uint8_t peer_ie; /* IEEE80211_ELEMID_MESHPEER */ uint8_t peer_len; - uint8_t peer_subtype; + uint8_t peer_proto[4]; /* Peer Management Protocol */ uint16_t peer_llinkid; /* Local Link ID */ uint16_t peer_linkid; /* Peer Link ID */ uint16_t peer_rcode; @@ -150,6 +133,16 @@ enum { /* values 3-255 are reserved */ }; +/* Mesh Peering Management Protocol */ +#define IEEE80211_MESH_PEER_PROTO_OUI 0x00, 0x0f, 0xac +#define IEEE80211_MESH_PEER_PROTO_VALUE 0x2a +#define IEEE80211_MESH_PEER_PROTO { IEEE80211_MESH_PEER_PROTO_OUI, \ + IEEE80211_MESH_PEER_PROTO_VALUE } +/* Abbreviated Handshake Protocol */ +#define IEEE80211_MESH_PEER_PROTO_AH_OUI 0x00, 0x0f, 0xac +#define IEEE80211_MESH_PEER_PROTO_AH_VALUE 0x2b +#define IEEE80211_MESH_PEER_PROTO_AH { IEEE80211_MESH_PEER_PROTO_AH_OUI, \ + IEEE80211_MESH_PEER_PROTO_AH_VALUE } #ifdef notyet /* Mesh Channel Switch Annoucement */ struct ieee80211_meshcsa_ie { @@ -256,11 +249,15 @@ struct ieee80211_meshprep_ie { struct ieee80211_meshperr_ie { uint8_t perr_ie; /* IEEE80211_ELEMID_MESHPERR */ uint8_t perr_len; - uint8_t perr_mode; /* NB: reserved */ + uint8_t perr_ttl; uint8_t perr_ndests; /* Number of Destinations */ struct { + uint8_t dest_flags; +#define IEEE80211_MESHPERR_DFLAGS_USN 0x01 +#define IEEE80211_MESHPERR_DFLAGS_RC 0x02 uint8_t dest_addr[IEEE80211_ADDR_LEN]; uint32_t dest_seq; /* HWMP Sequence Number */ + uint16_t dest_rcode; } __packed perr_dests[1]; /* NB: variable size */ } __packed; @@ -310,14 +307,11 @@ enum { }; /* - * Mesh Path Selection Action codes. + * Mesh Path Selection Action code. */ enum { - IEEE80211_ACTION_MESHPATH_REQ = 0, - IEEE80211_ACTION_MESHPATH_REP = 1, - IEEE80211_ACTION_MESHPATH_ERR = 2, - IEEE80211_ACTION_MESHPATH_RANN = 3, - /* 4-255 reserved */ + IEEE80211_ACTION_MESHPATH_SEL = 0, + /* 1-255 reserved */ }; /* @@ -479,7 +473,6 @@ int ieee80211_mesh_register_proto_path(const int ieee80211_mesh_register_proto_metric(const struct ieee80211_mesh_proto_metric *); -uint8_t * ieee80211_add_meshpeerver(uint8_t *, struct ieee80211vap *); uint8_t * ieee80211_add_meshid(uint8_t *, struct ieee80211vap *); uint8_t * ieee80211_add_meshconf(uint8_t *, struct ieee80211vap *); uint8_t * ieee80211_add_meshpeer(uint8_t *, uint8_t, uint16_t, uint16_t, diff --git a/sys/netinet/in_mcast.c b/sys/netinet/in_mcast.c index e855093a1c3e..2ef6d3a4e571 100644 --- a/sys/netinet/in_mcast.c +++ b/sys/netinet/in_mcast.c @@ -2427,8 +2427,10 @@ inp_set_source_filters(struct inpcb *inp, struct sockopt *sopt) if (error) return (error); - if (msfr.msfr_nsrcs > in_mcast_maxsocksrc || - (msfr.msfr_fmode != MCAST_EXCLUDE && + if (msfr.msfr_nsrcs > in_mcast_maxsocksrc) + return (ENOBUFS); + + if ((msfr.msfr_fmode != MCAST_EXCLUDE && msfr.msfr_fmode != MCAST_INCLUDE)) return (EINVAL); diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c index f1f5adef3abf..2bc6ca9632e8 100644 --- a/sys/netinet/in_proto.c +++ b/sys/netinet/in_proto.c @@ -150,39 +150,42 @@ struct protosw inetsw[] = { }, #ifdef SCTP { - .pr_type = SOCK_DGRAM, - .pr_domain = &inetdomain, - .pr_protocol = IPPROTO_SCTP, - .pr_flags = PR_WANTRCVD, - .pr_input = sctp_input, - .pr_ctlinput = sctp_ctlinput, - .pr_ctloutput = sctp_ctloutput, - .pr_init = sctp_init, - .pr_drain = sctp_drain, - .pr_usrreqs = &sctp_usrreqs + .pr_type = SOCK_DGRAM, + .pr_domain = &inetdomain, + .pr_protocol = IPPROTO_SCTP, + .pr_flags = PR_WANTRCVD, + .pr_input = sctp_input, + .pr_ctlinput = sctp_ctlinput, + .pr_ctloutput = sctp_ctloutput, + .pr_init = sctp_init, +#ifdef VIMAGE + .pr_destroy = sctp_finish, +#endif + .pr_drain = sctp_drain, + .pr_usrreqs = &sctp_usrreqs }, { - .pr_type = SOCK_SEQPACKET, - .pr_domain = &inetdomain, - .pr_protocol = IPPROTO_SCTP, - .pr_flags = PR_WANTRCVD, - .pr_input = sctp_input, - .pr_ctlinput = sctp_ctlinput, - .pr_ctloutput = sctp_ctloutput, - .pr_drain = sctp_drain, - .pr_usrreqs = &sctp_usrreqs + .pr_type = SOCK_SEQPACKET, + .pr_domain = &inetdomain, + .pr_protocol = IPPROTO_SCTP, + .pr_flags = PR_WANTRCVD, + .pr_input = sctp_input, + .pr_ctlinput = sctp_ctlinput, + .pr_ctloutput = sctp_ctloutput, + .pr_drain = sctp_drain, + .pr_usrreqs = &sctp_usrreqs }, { - .pr_type = SOCK_STREAM, - .pr_domain = &inetdomain, - .pr_protocol = IPPROTO_SCTP, - .pr_flags = PR_WANTRCVD, - .pr_input = sctp_input, - .pr_ctlinput = sctp_ctlinput, - .pr_ctloutput = sctp_ctloutput, - .pr_drain = sctp_drain, - .pr_usrreqs = &sctp_usrreqs + .pr_type = SOCK_STREAM, + .pr_domain = &inetdomain, + .pr_protocol = IPPROTO_SCTP, + .pr_flags = PR_WANTRCVD, + .pr_input = sctp_input, + .pr_ctlinput = sctp_ctlinput, + .pr_ctloutput = sctp_ctloutput, + .pr_drain = sctp_drain, + .pr_usrreqs = &sctp_usrreqs }, #endif /* SCTP */ { diff --git a/sys/netinet/sctp_asconf.c b/sys/netinet/sctp_asconf.c index c38c344fcf28..404b5ad0aa74 100644 --- a/sys/netinet/sctp_asconf.c +++ b/sys/netinet/sctp_asconf.c @@ -881,7 +881,7 @@ send_reply: /* we probably don't need these operations */ (void)sa6_recoverscope(from6); sa6_embedscope(from6, - MODULE_GLOBAL(MOD_INET6, ip6_use_defzone)); + MODULE_GLOBAL(ip6_use_defzone)); break; } diff --git a/sys/netinet/sctp_bsd_addr.c b/sys/netinet/sctp_bsd_addr.c index 792a720b6dfa..6a8dfc91163e 100644 --- a/sys/netinet/sctp_bsd_addr.c +++ b/sys/netinet/sctp_bsd_addr.c @@ -89,6 +89,7 @@ sctp_wakeup_iterator(void) static void sctp_iterator_thread(void *v) { + CURVNET_SET((struct vnet *)v); SCTP_IPI_ITERATOR_WQ_LOCK(); SCTP_BASE_INFO(iterator_running) = 0; while (1) { @@ -100,6 +101,7 @@ sctp_iterator_thread(void *v) } sctp_iterator_worker(); } + CURVNET_RESTORE(); } void @@ -108,7 +110,7 @@ sctp_startup_iterator(void) int ret; ret = kproc_create(sctp_iterator_thread, - (void *)NULL, + (void *)curvnet, &SCTP_BASE_INFO(thread_proc), RFPROC, SCTP_KTHREAD_PAGES, @@ -126,7 +128,7 @@ sctp_gather_internal_ifa_flags(struct sctp_ifa *ifa) ifa6 = (struct in6_ifaddr *)ifa->ifa; ifa->flags = ifa6->ia6_flags; - if (!MODULE_GLOBAL(MOD_INET6, ip6_use_deprecated)) { + if (!MODULE_GLOBAL(ip6_use_deprecated)) { if (ifa->flags & IN6_IFF_DEPRECATED) { ifa->localifa_flags |= SCTP_ADDR_IFA_UNUSEABLE; @@ -206,7 +208,8 @@ sctp_init_ifns_for_vrf(int vrfid) struct sctp_ifa *sctp_ifa; uint32_t ifa_flags; - TAILQ_FOREACH(ifn, &MODULE_GLOBAL(MOD_NET, ifnet), if_list) { + IFNET_RLOCK(); + TAILQ_FOREACH(ifn, &MODULE_GLOBAL(ifnet), if_list) { IF_ADDR_LOCK(ifn); TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) { if (ifa->ifa_addr == NULL) { @@ -251,6 +254,7 @@ sctp_init_ifns_for_vrf(int vrfid) } IF_ADDR_UNLOCK(ifn); } + IFNET_RUNLOCK(); } void @@ -336,7 +340,8 @@ void struct ifnet *ifn; struct ifaddr *ifa; - TAILQ_FOREACH(ifn, &MODULE_GLOBAL(MOD_NET, ifnet), if_list) { + IFNET_RLOCK(); + TAILQ_FOREACH(ifn, &MODULE_GLOBAL(ifnet), if_list) { if (!(*pred) (ifn)) { continue; } @@ -344,6 +349,7 @@ void sctp_addr_change(ifa, add ? RTM_ADD : RTM_DELETE); } } + IFNET_RUNLOCK(); } struct mbuf * diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index 4a916265b9e7..e59e78858fcf 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -5873,7 +5873,7 @@ sctp_skip_csum_4: * idea, so I will leave it in place. */ if (inp && ipsec4_in_reject(m, &inp->ip_inp.inp)) { - MODULE_GLOBAL(MOD_IPSEC, ipsec4stat).in_polvio++; + MODULE_GLOBAL(ipsec4stat).in_polvio++; SCTP_STAT_INCR(sctps_hdrops); goto bad; } diff --git a/sys/netinet/sctp_os_bsd.h b/sys/netinet/sctp_os_bsd.h index d01879081bd0..f0cca72c76d3 100644 --- a/sys/netinet/sctp_os_bsd.h +++ b/sys/netinet/sctp_os_bsd.h @@ -78,9 +78,7 @@ __FBSDID("$FreeBSD$"); #include <netinet/ip_icmp.h> #include <netinet/icmp_var.h> -#ifdef VIMAGE -#error "SCTP is not yet compatible with VIMAGE." -#endif +#include <net/vnet.h> #ifdef IPSEC #include <netipsec/ipsec.h> @@ -137,25 +135,21 @@ MALLOC_DECLARE(SCTP_M_SOCKOPT); #define SCTP_CTR6 CTR6 #endif -#define SCTP_BASE_INFO(__m) system_base_info.sctppcbinfo.__m -#define SCTP_BASE_STATS system_base_info.sctpstat -#define SCTP_BASE_STAT(__m) system_base_info.sctpstat.__m -#define SCTP_BASE_SYSCTL(__m) system_base_info.sctpsysctl.__m -#define SCTP_BASE_VAR(__m) system_base_info.__m - /* * Macros to expand out globals defined by various modules * to either a real global or a virtualized instance of one, * depending on whether VIMAGE is defined. */ -/* first define modules that supply us information */ -#define MOD_NET net -#define MOD_INET inet -#define MOD_INET6 inet6 -#define MOD_IPSEC ipsec - /* then define the macro(s) that hook into the vimage macros */ -#define MODULE_GLOBAL(__MODULE, __SYMBOL) V_ ## __SYMBOL +#define MODULE_GLOBAL(__SYMBOL) V_##__SYMBOL + +#define V_system_base_info VNET(system_base_info) +#define SCTP_BASE_INFO(__m) V_system_base_info.sctppcbinfo.__m +#define SCTP_BASE_STATS V_system_base_info.sctpstat +#define SCTP_BASE_STATS_SYSCTL VNET_NAME(system_base_info.sctpstat) +#define SCTP_BASE_STAT(__m) V_system_base_info.sctpstat.__m +#define SCTP_BASE_SYSCTL(__m) VNET_NAME(system_base_info.sctpsysctl.__m) +#define SCTP_BASE_VAR(__m) V_system_base_info.__m /* * diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 1e768fc5bbe1..b9750b9d50e0 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -3829,7 +3829,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, sin6 = &tmp; /* KAME hack: embed scopeid */ - if (sa6_embedscope(sin6, MODULE_GLOBAL(MOD_INET6, ip6_use_defzone)) != 0) { + if (sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)) != 0) { SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); return (EINVAL); } @@ -3883,7 +3883,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, if (net->src_addr_selected == 0) { sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; /* KAME hack: embed scopeid */ - if (sa6_embedscope(sin6, MODULE_GLOBAL(MOD_INET6, ip6_use_defzone)) != 0) { + if (sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)) != 0) { SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); return (EINVAL); } @@ -3906,7 +3906,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, } else { sin6 = (struct sockaddr_in6 *)&ro->ro_dst; /* KAME hack: embed scopeid */ - if (sa6_embedscope(sin6, MODULE_GLOBAL(MOD_INET6, ip6_use_defzone)) != 0) { + if (sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)) != 0) { SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); return (EINVAL); } @@ -5143,7 +5143,7 @@ do_a_abort: */ (void)sa6_recoverscope(sin6); stc.scope_id = sin6->sin6_scope_id; - sa6_embedscope(sin6, MODULE_GLOBAL(MOD_INET6, ip6_use_defzone)); + sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)); stc.loopback_scope = 1; stc.local_scope = 0; stc.site_scope = 1; @@ -5179,7 +5179,7 @@ do_a_abort: */ (void)sa6_recoverscope(sin6); stc.scope_id = sin6->sin6_scope_id; - sa6_embedscope(sin6, MODULE_GLOBAL(MOD_INET6, ip6_use_defzone)); + sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)); } else if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) { /* * If the new destination is @@ -10768,7 +10768,7 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh, /* Fill in the IPv6 header for the ABORT */ ip6_out->ip6_flow = ip6->ip6_flow; - ip6_out->ip6_hlim = MODULE_GLOBAL(MOD_INET6, ip6_defhlim); + ip6_out->ip6_hlim = MODULE_GLOBAL(ip6_defhlim); if (port) { ip6_out->ip6_nxt = IPPROTO_UDP; } else { @@ -11787,7 +11787,7 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag, /* Fill in the IP6 header for the ABORT */ ip6_out->ip6_flow = ip6->ip6_flow; - ip6_out->ip6_hlim = MODULE_GLOBAL(MOD_INET6, ip6_defhlim); + ip6_out->ip6_hlim = MODULE_GLOBAL(ip6_defhlim); if (port) { ip6_out->ip6_nxt = IPPROTO_UDP; } else { @@ -12014,7 +12014,7 @@ sctp_send_operr_to(struct mbuf *m, int iphlen, struct mbuf *scm, uint32_t vtag, /* Fill in the IP6 header for the ABORT */ ip6_out->ip6_flow = ip6->ip6_flow; - ip6_out->ip6_hlim = MODULE_GLOBAL(MOD_INET6, ip6_defhlim); + ip6_out->ip6_hlim = MODULE_GLOBAL(ip6_defhlim); if (port) { ip6_out->ip6_nxt = IPPROTO_UDP; } else { @@ -12384,8 +12384,8 @@ sctp_lower_sosend(struct socket *so, t_inp = inp = (struct sctp_inpcb *)so->so_pcb; if (inp == NULL) { - SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, EFAULT); - error = EFAULT; + SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, EINVAL); + error = EINVAL; if (i_pak) { SCTP_RELEASE_PKT(i_pak); } @@ -12432,8 +12432,8 @@ sctp_lower_sosend(struct socket *so, if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && (inp->sctp_socket->so_qlimit)) { /* The listener can NOT send */ - SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, EFAULT); - error = EFAULT; + SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, ENOTCONN); + error = ENOTCONN; goto out_unlocked; } if ((use_rcvinfo) && srcv) { @@ -12566,8 +12566,8 @@ sctp_lower_sosend(struct socket *so, if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) { /* Should I really unlock ? */ - SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, EFAULT); - error = EFAULT; + SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, EINVAL); + error = EINVAL; goto out_unlocked; } @@ -12596,6 +12596,12 @@ sctp_lower_sosend(struct socket *so, } } if (stcb == NULL) { + if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || + (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { + SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOTCONN); + error = ENOTCONN; + goto out_unlocked; + } if (addr == NULL) { SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOENT); error = ENOENT; @@ -13759,7 +13765,7 @@ sctp_v6src_match_nexthop(struct sockaddr_in6 *src6, sctp_route_t * ro) return (0); /* get prefix entry of address */ - LIST_FOREACH(pfx, &MODULE_GLOBAL(MOD_INET6, nd_prefix), ndpr_entry) { + LIST_FOREACH(pfx, &MODULE_GLOBAL(nd_prefix), ndpr_entry) { if (pfx->ndpr_stateflags & NDPRF_DETACHED) continue; if (IN6_ARE_MASKED_ADDR_EQUAL(&pfx->ndpr_prefix.sin6_addr, diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index 0d1f1e0f8477..21cd88998a8a 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -48,7 +48,7 @@ __FBSDID("$FreeBSD$"); #include <netinet/udp.h> -struct sctp_base_info system_base_info; +VNET_DEFINE(struct sctp_base_info, system_base_info); /* FIX: we don't handle multiple link local scopes */ /* "scopeless" replacement IN6_ARE_ADDR_EQUAL */ @@ -59,11 +59,11 @@ SCTP6_ARE_ADDR_EQUAL(struct sockaddr_in6 *a, struct sockaddr_in6 *b) struct sockaddr_in6 tmp_a, tmp_b; memcpy(&tmp_a, a, sizeof(struct sockaddr_in6)); - if (sa6_embedscope(&tmp_a, MODULE_GLOBAL(MOD_INET6, ip6_use_defzone)) != 0) { + if (sa6_embedscope(&tmp_a, MODULE_GLOBAL(ip6_use_defzone)) != 0) { return 0; } memcpy(&tmp_b, b, sizeof(struct sockaddr_in6)); - if (sa6_embedscope(&tmp_b, MODULE_GLOBAL(MOD_INET6, ip6_use_defzone)) != 0) { + if (sa6_embedscope(&tmp_b, MODULE_GLOBAL(ip6_use_defzone)) != 0) { return 0; } return (IN6_ARE_ADDR_EQUAL(&tmp_a.sin6_addr, &tmp_b.sin6_addr)); @@ -2008,7 +2008,7 @@ sctp_findassociation_addr(struct mbuf *m, int iphlen, int offset, /* Get the scopes in properly to the sin6 addr's */ /* we probably don't need these operations */ (void)sa6_recoverscope(from6); - sa6_embedscope(from6, MODULE_GLOBAL(MOD_INET6, ip6_use_defzone)); + sa6_embedscope(from6, MODULE_GLOBAL(ip6_use_defzone)); break; } #endif @@ -2049,7 +2049,7 @@ sctp_findassociation_addr(struct mbuf *m, int iphlen, int offset, /* Get the scopes in properly to the sin6 addr's */ /* we probably don't need these operations */ (void)sa6_recoverscope(to6); - sa6_embedscope(to6, MODULE_GLOBAL(MOD_INET6, ip6_use_defzone)); + sa6_embedscope(to6, MODULE_GLOBAL(ip6_use_defzone)); break; } #endif @@ -2316,7 +2316,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id) } #endif /* IPSEC */ SCTP_INCR_EP_COUNT(); - inp->ip_inp.inp.inp_ip_ttl = MODULE_GLOBAL(MOD_INET, ip_defttl); + inp->ip_inp.inp.inp_ip_ttl = MODULE_GLOBAL(ip_defttl); SCTP_INP_INFO_WUNLOCK(); so->so_pcb = (caddr_t)inp; @@ -2688,7 +2688,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { bindall = 0; /* KAME hack: embed scopeid */ - if (sa6_embedscope(sin6, MODULE_GLOBAL(MOD_INET6, ip6_use_defzone)) != 0) { + if (sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)) != 0) { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); return (EINVAL); } @@ -2814,8 +2814,8 @@ continue_anyway: int done; if (ip_inp->inp_flags & INP_HIGHPORT) { - first = MODULE_GLOBAL(MOD_INET, ipport_hifirstauto); - last = MODULE_GLOBAL(MOD_INET, ipport_hilastauto); + first = MODULE_GLOBAL(ipport_hifirstauto); + last = MODULE_GLOBAL(ipport_hilastauto); } else if (ip_inp->inp_flags & INP_LOWPORT) { if (p && (error = priv_check(p, PRIV_NETINET_RESERVEDPORT) @@ -2826,11 +2826,11 @@ continue_anyway: SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error); return (error); } - first = MODULE_GLOBAL(MOD_INET, ipport_lowfirstauto); - last = MODULE_GLOBAL(MOD_INET, ipport_lowlastauto); + first = MODULE_GLOBAL(ipport_lowfirstauto); + last = MODULE_GLOBAL(ipport_lowlastauto); } else { - first = MODULE_GLOBAL(MOD_INET, ipport_firstauto); - last = MODULE_GLOBAL(MOD_INET, ipport_lastauto); + first = MODULE_GLOBAL(ipport_firstauto); + last = MODULE_GLOBAL(ipport_lastauto); } if (first > last) { uint16_t temp; @@ -3756,7 +3756,7 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr, struct sockaddr_in6 *sin6; sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; - (void)sa6_embedscope(sin6, MODULE_GLOBAL(MOD_INET6, ip6_use_defzone)); + (void)sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)); sin6->sin6_scope_id = 0; } #endif @@ -6422,10 +6422,6 @@ sctp_drain_mbufs(struct sctp_inpcb *inp, struct sctp_tcb *stcb) /* We look for anything larger than the cum-ack + 1 */ - SCTP_STAT_INCR(sctps_protocol_drain_calls); - if (SCTP_BASE_SYSCTL(sctp_do_drain) == 0) { - return; - } asoc = &stcb->asoc; if (asoc->cumulative_tsn == asoc->highest_tsn_inside_map) { /* none we can reneg on. */ @@ -6588,22 +6584,37 @@ sctp_drain() * is LOW on MBUF's and needs help. This is where reneging will * occur. We really hope this does NOT happen! */ - struct sctp_inpcb *inp; - struct sctp_tcb *stcb; + VNET_ITERATOR_DECL(vnet_iter); + VNET_LIST_RLOCK_NOSLEEP(); + VNET_FOREACH(vnet_iter) { + CURVNET_SET(vnet_iter); + struct sctp_inpcb *inp; + struct sctp_tcb *stcb; - SCTP_INP_INFO_RLOCK(); - LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) { - /* For each endpoint */ - SCTP_INP_RLOCK(inp); - LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { - /* For each association */ - SCTP_TCB_LOCK(stcb); - sctp_drain_mbufs(inp, stcb); - SCTP_TCB_UNLOCK(stcb); + SCTP_STAT_INCR(sctps_protocol_drain_calls); + if (SCTP_BASE_SYSCTL(sctp_do_drain) == 0) { +#ifdef VIMAGE + continue; +#else + return; +#endif } - SCTP_INP_RUNLOCK(inp); + SCTP_INP_INFO_RLOCK(); + LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) { + /* For each endpoint */ + SCTP_INP_RLOCK(inp); + LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { + /* For each association */ + SCTP_TCB_LOCK(stcb); + sctp_drain_mbufs(inp, stcb); + SCTP_TCB_UNLOCK(stcb); + } + SCTP_INP_RUNLOCK(inp); + } + SCTP_INP_INFO_RUNLOCK(); + CURVNET_RESTORE(); } - SCTP_INP_INFO_RUNLOCK(); + VNET_LIST_RUNLOCK_NOSLEEP(); } /* diff --git a/sys/netinet/sctp_pcb.h b/sys/netinet/sctp_pcb.h index 684ed5ae17d5..d9e1db6dc05e 100644 --- a/sys/netinet/sctp_pcb.h +++ b/sys/netinet/sctp_pcb.h @@ -462,7 +462,7 @@ struct sctp_tcb { * goes with the base info. sctp_pcb.c has * the real definition. */ -extern struct sctp_base_info system_base_info; +VNET_DECLARE(struct sctp_base_info, system_base_info); #ifdef INET6 int SCTP6_ARE_ADDR_EQUAL(struct sockaddr_in6 *a, struct sockaddr_in6 *b); diff --git a/sys/netinet/sctp_structs.h b/sys/netinet/sctp_structs.h index 59725f5d992e..595c37c3e7a6 100644 --- a/sys/netinet/sctp_structs.h +++ b/sys/netinet/sctp_structs.h @@ -51,6 +51,7 @@ struct sctp_timer { void *ep; void *tcb; void *net; + void *vnet; /* for sanity checking */ void *self; diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c index b5c5f6c4795b..ceb4622ab8a2 100644 --- a/sys/netinet/sctp_sysctl.c +++ b/sys/netinet/sctp_sysctl.c @@ -930,7 +930,7 @@ SYSCTL_PROC(_net_inet_sctp, OID_AUTO, output_unlocked, CTLTYPE_INT | CTLFLAG_RW, #endif SYSCTL_STRUCT(_net_inet_sctp, OID_AUTO, stats, CTLFLAG_RW, - &SCTP_BASE_STATS, sctpstat, + &SCTP_BASE_STATS_SYSCTL, sctpstat, "SCTP statistics (struct sctp_stat)"); SYSCTL_PROC(_net_inet_sctp, OID_AUTO, assoclist, CTLFLAG_RD, diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c index b40ef503f61e..334401838e19 100644 --- a/sys/netinet/sctp_timer.c +++ b/sys/netinet/sctp_timer.c @@ -1773,7 +1773,7 @@ sctp_pathmtu_timer(struct sctp_inpcb *inp, struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; /* KAME hack: embed scopeid */ - (void)sa6_embedscope(sin6, MODULE_GLOBAL(MOD_INET6, ip6_use_defzone)); + (void)sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)); } #endif diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index 4442f11befba..a8ea998a3b3e 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -544,7 +544,7 @@ sctp_attach(struct socket *so, int proto, struct thread *p) inp->sctp_flags &= ~SCTP_PCB_FLAGS_BOUND_V6; /* I'm not v6! */ ip_inp = &inp->ip_inp.inp; ip_inp->inp_vflag |= INP_IPV4; - ip_inp->inp_ip_ttl = MODULE_GLOBAL(MOD_INET, ip_defttl); + ip_inp->inp_ip_ttl = MODULE_GLOBAL(ip_defttl); #ifdef IPSEC error = ipsec_init_policy(so, &ip_inp->inp_sp); #ifdef SCTP_LOG_CLOSING diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index c7bdfb54b5c8..94dea3fa73d4 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -1446,6 +1446,7 @@ sctp_timeout_handler(void *t) inp = (struct sctp_inpcb *)tmr->ep; stcb = (struct sctp_tcb *)tmr->tcb; net = (struct sctp_nets *)tmr->net; + CURVNET_SET((struct vnet *)tmr->vnet); did_output = 1; #ifdef SCTP_AUDITING_ENABLED @@ -1459,6 +1460,7 @@ sctp_timeout_handler(void *t) * SCTP_PRINTF("Stale SCTP timer fired (%p), ignoring...\n", * tmr); */ + CURVNET_RESTORE(); return; } tmr->stopped_from = 0xa001; @@ -1467,10 +1469,12 @@ sctp_timeout_handler(void *t) * SCTP_PRINTF("SCTP timer fired with invalid type: 0x%x\n", * tmr->type); */ + CURVNET_RESTORE(); return; } tmr->stopped_from = 0xa002; if ((tmr->type != SCTP_TIMER_TYPE_ADDR_WQ) && (inp == NULL)) { + CURVNET_RESTORE(); return; } /* if this is an iterator timeout, get the struct and clear inp */ @@ -1494,6 +1498,7 @@ sctp_timeout_handler(void *t) (tmr->type != SCTP_TIMER_TYPE_ASOCKILL)) ) { SCTP_INP_DECR_REF(inp); + CURVNET_RESTORE(); return; } } @@ -1505,6 +1510,7 @@ sctp_timeout_handler(void *t) if (inp) { SCTP_INP_DECR_REF(inp); } + CURVNET_RESTORE(); return; } } @@ -1517,6 +1523,7 @@ sctp_timeout_handler(void *t) if (stcb) { atomic_add_int(&stcb->asoc.refcnt, -1); } + CURVNET_RESTORE(); return; } tmr->stopped_from = 0xa006; @@ -1531,6 +1538,7 @@ sctp_timeout_handler(void *t) if (inp) { SCTP_INP_DECR_REF(inp); } + CURVNET_RESTORE(); return; } } @@ -1903,6 +1911,7 @@ out_decr: out_no_decr: SCTPDBG(SCTP_DEBUG_TIMER1, "Timer now complete (type %d)\n", type); + CURVNET_RESTORE(); } void @@ -2263,6 +2272,7 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb, tmr->tcb = (void *)stcb; tmr->net = (void *)net; tmr->self = (void *)tmr; + tmr->vnet = (void *)curvnet; tmr->ticks = sctp_get_tick_count(); (void)SCTP_OS_TIMER_START(&tmr->timer, to_ticks, sctp_timeout_handler, tmr); return; diff --git a/sys/netinet6/sctp6_usrreq.c b/sys/netinet6/sctp6_usrreq.c index 9597528b7d0d..50f5ef83746c 100644 --- a/sys/netinet6/sctp6_usrreq.c +++ b/sys/netinet6/sctp6_usrreq.c @@ -223,7 +223,7 @@ sctp_skip_csum: */ if (in6p_ip && (ipsec6_in_reject(m, in6p_ip))) { /* XXX */ - MODULE_GLOBAL(MOD_IPSEC, ipsec6stat).in_polvio++; + MODULE_GLOBAL(ipsec6stat).in_polvio++; goto bad; } #endif /* IPSEC */ @@ -695,7 +695,7 @@ sctp6_attach(struct socket *so, int proto, struct thread *p) * socket as well, because the socket may be bound to an IPv6 * wildcard address, which may match an IPv4-mapped IPv6 address. */ - inp6->inp_ip_ttl = MODULE_GLOBAL(MOD_INET, ip_defttl); + inp6->inp_ip_ttl = MODULE_GLOBAL(ip_defttl); #endif /* * Hmm what about the IPSEC stuff that is missing here but in @@ -859,7 +859,7 @@ sctp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr, } } if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { - if (!MODULE_GLOBAL(MOD_INET6, ip6_v6only)) { + if (!MODULE_GLOBAL(ip6_v6only)) { struct sockaddr_in sin; /* convert v4-mapped into v4 addr and send */ @@ -990,7 +990,7 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p) } } if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { - if (!MODULE_GLOBAL(MOD_INET6, ip6_v6only)) { + if (!MODULE_GLOBAL(ip6_v6only)) { /* convert v4-mapped into v4 addr */ in6_sin6_2_sin((struct sockaddr_in *)&ss, sin6); addr = (struct sockaddr *)&ss; diff --git a/sys/pci/intpm.c b/sys/pci/intpm.c index 13404c83f5f7..1cbe75df407e 100644 --- a/sys/pci/intpm.c +++ b/sys/pci/intpm.c @@ -167,6 +167,12 @@ intsmb_attach(device_t dev) sc->poll == 0 ? "enabled" : "disabled"); printf("revision %d\n", pci_read_config(dev, PCI_REVID_SMB, 1)); + if (!sc->poll && intr == PCI_INTR_SMB_SMI) { + device_printf(dev, + "using polling mode when configured interrupt is SMI\n"); + sc->poll = 1; + } + if (sc->poll) goto no_intr; diff --git a/sys/powerpc/include/param.h b/sys/powerpc/include/param.h index 160cd782a7d8..6c3edf9c92a0 100644 --- a/sys/powerpc/include/param.h +++ b/sys/powerpc/include/param.h @@ -86,6 +86,8 @@ #define PAGE_MASK (PAGE_SIZE - 1) #define NPTEPG (PAGE_SIZE/(sizeof (pt_entry_t))) +#define MAXPAGESIZES 1 /* maximum number of supported page sizes */ + #ifndef KSTACK_PAGES #define KSTACK_PAGES 4 /* includes pcb */ #endif diff --git a/sys/sparc64/conf/GENERIC b/sys/sparc64/conf/GENERIC index 95be09ad6234..ecf640cc4396 100644 --- a/sys/sparc64/conf/GENERIC +++ b/sys/sparc64/conf/GENERIC @@ -68,6 +68,7 @@ options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores options P1003_1B_SEMAPHORES # POSIX-style semaphores options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions +options PRINTF_BUFR_SIZE=128 # Prevent printf output being interspersed. options HWPMC_HOOKS # Necessary kernel hooks for hwpmc(4) options AUDIT # Security event auditing options MAC # TrustedBSD MAC Framework diff --git a/sys/sparc64/include/param.h b/sys/sparc64/include/param.h index 90864b0556f7..af026b293f29 100644 --- a/sys/sparc64/include/param.h +++ b/sys/sparc64/include/param.h @@ -109,6 +109,8 @@ #define PAGE_SIZE_MAX PAGE_SIZE_4M #define PAGE_MASK_MAX PAGE_MASK_4M +#define MAXPAGESIZES 1 /* maximum number of supported page sizes */ + #ifndef KSTACK_PAGES #define KSTACK_PAGES 4 /* pages of kernel stack (with pcb) */ #endif diff --git a/sys/sun4v/include/param.h b/sys/sun4v/include/param.h index 069ab548d57f..2ca699e838a3 100644 --- a/sys/sun4v/include/param.h +++ b/sys/sun4v/include/param.h @@ -104,6 +104,8 @@ #define PAGE_SIZE_MAX PAGE_SIZE_4M #define PAGE_MASK_MAX PAGE_MASK_4M +#define MAXPAGESIZES 1 /* maximum number of supported page sizes */ + #ifndef KSTACK_PAGES #define KSTACK_PAGES 4 /* pages of kernel stack (with pcb) */ #endif diff --git a/sys/sys/event.h b/sys/sys/event.h index ec76f3551e8d..4365e44e58d4 100644 --- a/sys/sys/event.h +++ b/sys/sys/event.h @@ -191,7 +191,7 @@ struct filterops { int (*f_attach)(struct knote *kn); void (*f_detach)(struct knote *kn); int (*f_event)(struct knote *kn, long hint); - void (*f_touch)(struct knote *kn, struct kevent *kev, long type); + void (*f_touch)(struct knote *kn, struct kevent *kev, u_long type); }; /* diff --git a/sys/sys/kbio.h b/sys/sys/kbio.h index 6f82c6d59017..22b028572fd6 100644 --- a/sys/sys/kbio.h +++ b/sys/sys/kbio.h @@ -106,7 +106,7 @@ typedef struct keyboard_repeat keyboard_repeat_t; #define _KEYMAP_DECLARED struct keyent_t { - u_char map[NUM_STATES]; + u_int map[NUM_STATES]; u_char spcl; u_char flgs; #define FLAG_LOCK_O 0 @@ -220,8 +220,9 @@ typedef struct fkeyarg fkeyarg_t; #define GIO_SCRNMAP _IOR('k', 2, scrmap_t) #define PIO_SCRNMAP _IOW('k', 3, scrmap_t) #endif -#define GIO_KEYMAP _IOR('k', 6, keymap_t) -#define PIO_KEYMAP _IOW('k', 7, keymap_t) +/* XXX: Should have keymap_t as an argument, but that's too big for ioctl()! */ +#define GIO_KEYMAP _IO('k', 6) +#define PIO_KEYMAP _IO('k', 7) #define GIO_DEADKEYMAP _IOR('k', 8, accentmap_t) #define PIO_DEADKEYMAP _IOW('k', 9, accentmap_t) #define GIO_KEYMAPENT _IOWR('k', 10, keyarg_t) diff --git a/sys/sys/mman.h b/sys/sys/mman.h index 6a963c9228cb..9b64e8981ccf 100644 --- a/sys/sys/mman.h +++ b/sys/sys/mman.h @@ -208,6 +208,7 @@ __BEGIN_DECLS * posix_typed_mem_open(). */ #if __BSD_VISIBLE +int getpagesizes(size_t *, int); int madvise(void *, size_t, int); int mincore(const void *, size_t, char *); int minherit(void *, size_t, int); diff --git a/sys/sys/param.h b/sys/sys/param.h index 0fb65b09c8d2..7bfab291c448 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -58,7 +58,7 @@ * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 900001 /* Master, propagated to newvers */ +#define __FreeBSD_version 900002 /* Master, propagated to newvers */ #ifndef LOCORE #include <sys/types.h> diff --git a/sys/sys/smp.h b/sys/sys/smp.h index d80b9e46ef93..782ef74974bf 100644 --- a/sys/sys/smp.h +++ b/sys/sys/smp.h @@ -120,7 +120,6 @@ void cpu_mp_setmaxid(void); void cpu_mp_start(void); void forward_signal(struct thread *); -void forward_roundrobin(void); int restart_cpus(cpumask_t); int stop_cpus(cpumask_t); int stop_cpus_hard(cpumask_t); diff --git a/sys/sys/systm.h b/sys/sys/systm.h index 96222da91522..397976fd564f 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -54,6 +54,7 @@ extern int kstack_pages; /* number of kernel stack pages */ extern int nswap; /* size of swap space */ +extern u_long pagesizes[]; /* supported page sizes */ extern long physmem; /* physical memory */ extern long realmem; /* 'real' memory */ diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 2f2d90a80d46..dffbf9a293f3 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -614,6 +614,9 @@ int vn_commname(struct vnode *vn, char *buf, u_int buflen); int vaccess(enum vtype type, mode_t file_mode, uid_t file_uid, gid_t file_gid, accmode_t accmode, struct ucred *cred, int *privused); +int vaccess_acl_nfs4(enum vtype type, uid_t file_uid, gid_t file_gid, + struct acl *aclp, accmode_t accmode, struct ucred *cred, + int *privused); int vaccess_acl_posix1e(enum vtype type, uid_t file_uid, gid_t file_gid, struct acl *acl, accmode_t accmode, struct ucred *cred, int *privused); diff --git a/sys/teken/sequences b/sys/teken/sequences index 8f7bfb443881..957665a02f53 100644 --- a/sys/teken/sequences +++ b/sys/teken/sequences @@ -104,6 +104,7 @@ C25ADBG Cons25 set adapter background ^[ [ = G r C25ADFG Cons25 set adapter foreground ^[ [ = F r C25BLPD Cons25 set bell pitch duration ^[ [ = B r r C25CURS Cons25 set cursor type ^[ [ = S r +C25MODE Cons25 set terminal mode ^[ [ = T r C25VTSW Cons25 switch virtual terminal ^[ [ z r # VT52 compatibility diff --git a/sys/teken/teken.c b/sys/teken/teken.c index da5c056c2c94..c928510b86d9 100644 --- a/sys/teken/teken.c +++ b/sys/teken/teken.c @@ -48,10 +48,6 @@ static FILE *df; #endif /* __FreeBSD__ && _KERNEL */ -#include "teken.h" -#include "teken_wcwidth.h" -#include "teken_scs.h" - /* Private flags for t_stateflags. */ #define TS_FIRSTDIGIT 0x01 /* First numeric digit in escape sequence. */ #define TS_INSERT 0x02 /* Insert mode. */ @@ -64,6 +60,10 @@ static FILE *df; /* Character that blanks a cell. */ #define BLANK ' ' +#include "teken.h" +#include "teken_wcwidth.h" +#include "teken_scs.h" + static teken_state_t teken_state_init; /* diff --git a/sys/teken/teken.h b/sys/teken/teken.h index 65ee05e23be7..4e73f7b1c8c3 100644 --- a/sys/teken/teken.h +++ b/sys/teken/teken.h @@ -109,7 +109,7 @@ typedef struct { tf_respond_t *tf_respond; } teken_funcs_t; -typedef teken_char_t teken_scs_t(teken_char_t); +typedef teken_char_t teken_scs_t(teken_t *, teken_char_t); /* * Terminal state. diff --git a/sys/teken/teken_scs.h b/sys/teken/teken_scs.h index baeb296539d4..5f42aa41c052 100644 --- a/sys/teken/teken_scs.h +++ b/sys/teken/teken_scs.h @@ -58,39 +58,49 @@ static teken_char_t teken_scs_process(teken_t *t, teken_char_t c) { - return (t->t_scs[t->t_curscs](c)); + return (t->t_scs[t->t_curscs](t, c)); } /* Unicode points for VT100 box drawing. */ -static const uint16_t teken_boxdrawing[31] = { +static const uint16_t teken_boxdrawing_unicode[31] = { 0x25c6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1, 0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x23ba, 0x23bb, 0x2500, 0x23bc, 0x23bd, 0x251c, 0x2524, 0x2534, 0x252c, 0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7 }; +/* CP437 points for VT100 box drawing. */ +static const uint8_t teken_boxdrawing_8bit[31] = { + 0x04, 0xb1, 0x48, 0x46, 0x43, 0x4c, 0xf8, 0xf1, + 0x4e, 0x56, 0xd9, 0xbf, 0xda, 0xc0, 0xc5, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc3, 0xb4, 0xc1, 0xc2, + 0xb3, 0xf3, 0xf2, 0xe3, 0xd8, 0x9c, 0xfa, +}; + static teken_char_t -teken_scs_special_graphics(teken_char_t c) +teken_scs_special_graphics(teken_t *t, teken_char_t c) { /* Box drawing. */ if (c >= '`' && c <= '~') - return (teken_boxdrawing[c - '`']); + return (t->t_stateflags & TS_8BIT ? + teken_boxdrawing_8bit[c - '`'] : + teken_boxdrawing_unicode[c - '`']); return (c); } static teken_char_t -teken_scs_uk_national(teken_char_t c) +teken_scs_uk_national(teken_t *t, teken_char_t c) { /* Pound sign. */ if (c == '#') - return (0xa3); + return (t->t_stateflags & TS_8BIT ? 0x9c : 0xa3); return (c); } static teken_char_t -teken_scs_us_ascii(teken_char_t c) +teken_scs_us_ascii(teken_t *t __unused, teken_char_t c) { /* No processing. */ diff --git a/sys/teken/teken_subr.h b/sys/teken/teken_subr.h index ab3e759d2c09..7d8cd0cbe935 100644 --- a/sys/teken/teken_subr.h +++ b/sys/teken/teken_subr.h @@ -397,6 +397,11 @@ teken_subr_delete_line(teken_t *t, unsigned int nrows) { teken_rect_t tr; + /* Ignore if outside scrolling region. */ + if (t->t_cursor.tp_row < t->t_scrollreg.ts_begin || + t->t_cursor.tp_row >= t->t_scrollreg.ts_end) + return; + tr.tr_begin.tp_col = 0; tr.tr_end.tp_row = t->t_scrollreg.ts_end; tr.tr_end.tp_col = t->t_winsize.tp_col; @@ -656,6 +661,11 @@ teken_subr_insert_line(teken_t *t, unsigned int nrows) { teken_rect_t tr; + /* Ignore if outside scrolling region. */ + if (t->t_cursor.tp_row < t->t_scrollreg.ts_begin || + t->t_cursor.tp_row >= t->t_scrollreg.ts_end) + return; + tr.tr_begin.tp_row = t->t_cursor.tp_row; tr.tr_begin.tp_col = 0; tr.tr_end.tp_col = t->t_winsize.tp_col; @@ -802,8 +812,9 @@ teken_subr_regular_character(teken_t *t, teken_char_t c) int width; if (t->t_stateflags & TS_8BIT) { - if (!(t->t_stateflags & TS_CONS25) && c <= 0x1B) + if (!(t->t_stateflags & TS_CONS25) && (c <= 0x1b || c == 0x7f)) return; + c = teken_scs_process(t, c); width = 1; } else { c = teken_scs_process(t, c); diff --git a/sys/teken/teken_subr_compat.h b/sys/teken/teken_subr_compat.h index c642af71770b..088f378af588 100644 --- a/sys/teken/teken_subr_compat.h +++ b/sys/teken/teken_subr_compat.h @@ -87,6 +87,20 @@ teken_subr_cons25_set_bell_pitch_duration(teken_t *t, unsigned int pitch, (duration & 0xffff)); } +static void +teken_subr_cons25_set_terminal_mode(teken_t *t, unsigned int mode) +{ + + switch (mode) { + case 0: /* Switch terminal to xterm. */ + t->t_stateflags &= ~TS_CONS25; + break; + case 1: /* Switch terminal to cons25. */ + t->t_stateflags |= TS_CONS25; + break; + } +} + #if 0 static void teken_subr_vt52_decid(teken_t *t) diff --git a/sys/ufs/ufs/ufs_gjournal.c b/sys/ufs/ufs/ufs_gjournal.c index da0de65a28f6..8e35c082e082 100644 --- a/sys/ufs/ufs/ufs_gjournal.c +++ b/sys/ufs/ufs/ufs_gjournal.c @@ -29,8 +29,6 @@ __FBSDID("$FreeBSD$"); #include "opt_ufs.h" -#ifdef UFS_GJOURNAL - #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> @@ -137,5 +135,3 @@ ufs_gjournal_close(struct vnode *vp) return; ufs_gjournal_modref(vp, -1); } - -#endif /* UFS_GJOURNAL */ diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index 2b99e3653df3..c8d25ee3a305 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -64,6 +64,7 @@ __FBSDID("$FreeBSD$"); #include <sys/mount.h> #include <sys/conf.h> #include <sys/stat.h> +#include <sys/sysent.h> #include <sys/vmmeter.h> #include <sys/sysctl.h> @@ -229,7 +230,8 @@ mmap(td, uap) fp = NULL; /* make sure mapping fits into numeric range etc */ - if (uap->len == 0 || + if ((uap->len == 0 && !SV_CURPROC_FLAG(SV_AOUT) && + curproc->p_osrel >= 800104) || ((flags & MAP_ANON) && uap->fd != -1)) return (EINVAL); |