[Midnightbsd-cvs] src: sys/amd64:
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Sun Sep 21 11:21:13 EDT 2008
Log Message:
-----------
Modified Files:
--------------
src/sys/amd64:
Makefile (r1.1.1.1 -> r1.2)
src/sys/amd64/acpica:
OsdEnvironment.c (r1.1.1.1 -> r1.2)
acpi_machdep.c (r1.1.1.1 -> r1.2)
acpi_wakeup.c (r1.1.1.1 -> r1.2)
madt.c (r1.1.1.1 -> r1.2)
src/sys/amd64/amd64:
apic_vector.S (r1.1.1.1 -> r1.2)
bios.c (r1.1.1.1 -> r1.2)
busdma_machdep.c (r1.2 -> r1.3)
cpu_switch.S (r1.1.1.1 -> r1.2)
db_disasm.c (r1.1.1.1 -> r1.2)
db_trace.c (r1.2 -> r1.3)
dump_machdep.c (r1.1.1.1 -> r1.2)
elf_machdep.c (r1.1.1.2 -> r1.2)
fpu.c (r1.2 -> r1.3)
gdb_machdep.c (r1.1.1.1 -> r1.2)
genassym.c (r1.1.1.1 -> r1.2)
identcpu.c (r1.3 -> r1.4)
initcpu.c (r1.2 -> r1.3)
intr_machdep.c (r1.2 -> r1.3)
io.c (r1.1.1.1 -> r1.2)
io_apic.c (r1.2 -> r1.3)
legacy.c (r1.1.1.1 -> r1.2)
local_apic.c (r1.2 -> r1.3)
machdep.c (r1.2 -> r1.3)
mp_machdep.c (r1.2 -> r1.3)
mp_watchdog.c (r1.1.1.1 -> r1.2)
mptable.c (r1.1.1.1 -> r1.2)
mptable_pci.c (r1.1.1.1 -> r1.2)
nexus.c (r1.1.1.1 -> r1.2)
pmap.c (r1.1.1.1 -> r1.2)
prof_machdep.c (r1.1.1.1 -> r1.2)
support.S (r1.1.1.1 -> r1.2)
trap.c (r1.1.1.1 -> r1.2)
tsc.c (r1.1.1.1 -> r1.2)
uma_machdep.c (r1.1.1.1 -> r1.2)
vm_machdep.c (r1.1.1.1 -> r1.2)
src/sys/amd64/ia32:
ia32_exception.S (r1.1.1.1 -> r1.2)
ia32_reg.c (r1.1.1.2 -> r1.2)
ia32_signal.c (r1.1.1.1 -> r1.2)
ia32_sigtramp.S (r1.1.1.1 -> r1.2)
ia32_syscall.c (r1.1.1.1 -> r1.2)
src/sys/amd64/include:
_limits.h (r1.1.1.1 -> r1.2)
_types.h (r1.1.1.1 -> r1.2)
acpica_machdep.h (r1.1.1.2 -> r1.2)
apicvar.h (r1.2 -> r1.3)
asm.h (r1.1.1.1 -> r1.2)
asmacros.h (r1.1.1.1 -> r1.2)
atomic.h (r1.1.1.1 -> r1.2)
bus.h (r1.1.1.1 -> r1.2)
bus_dma.h (r1.1.1.1 -> r1.2)
clock.h (r1.1.1.1 -> r1.2)
cpu.h (r1.1.1.1 -> r1.2)
elf.h (r1.1.1.1 -> r1.2)
frame.h (r1.1.1.1 -> r1.2)
gdb_machdep.h (r1.1.1.1 -> r1.2)
intr_machdep.h (r1.2 -> r1.3)
kdb.h (r1.1.1.1 -> r1.2)
legacyvar.h (r1.1.1.1 -> r1.2)
md_var.h (r1.2 -> r1.3)
mptable.h (r1.2 -> r1.3)
mutex.h (r1.1.1.2 -> r1.2)
param.h (r1.1.1.1 -> r1.2)
pcb.h (r1.1.1.1 -> r1.2)
pci_cfgreg.h (r1.1.1.1 -> r1.2)
pcpu.h (r1.1.1.1 -> r1.2)
pmap.h (r1.1.1.1 -> r1.2)
profile.h (r1.1.1.1 -> r1.2)
reg.h (r1.1.1.1 -> r1.2)
segments.h (r1.1.1.1 -> r1.2)
setjmp.h (r1.1.1.1 -> r1.2)
signal.h (r1.1.1.1 -> r1.2)
smp.h (r1.1.1.1 -> r1.2)
specialreg.h (r1.2 -> r1.3)
stdarg.h (r1.2 -> r1.3)
trap.h (r1.1.1.1 -> r1.2)
vmparam.h (r1.1.1.1 -> r1.2)
src/sys/amd64/include/pc:
bios.h (r1.1.1.1 -> r1.2)
src/sys/amd64/isa:
atpic.c (r1.2 -> r1.3)
atpic_vector.S (r1.1.1.1 -> r1.2)
clock.c (r1.1.1.1 -> r1.2)
icu.h (r1.1.1.1 -> r1.2)
isa.c (r1.1.1.1 -> r1.2)
src/sys/amd64/linux32:
linux.h (r1.1.1.1 -> r1.2)
linux32_dummy.c (r1.1.1.1 -> r1.2)
linux32_locore.s (r1.1.1.1 -> r1.2)
linux32_machdep.c (r1.1.1.1 -> r1.2)
linux32_proto.h (r1.1.1.1 -> r1.2)
linux32_syscall.h (r1.1.1.1 -> r1.2)
linux32_sysent.c (r1.1.1.1 -> r1.2)
linux32_sysvec.c (r1.1.1.2 -> r1.2)
syscalls.conf (r1.1.1.1 -> r1.2)
syscalls.master (r1.1.1.1 -> r1.2)
src/sys/amd64/pci:
pci_bus.c (r1.1.1.1 -> r1.2)
pci_cfgreg.c (r1.1.1.1 -> r1.2)
Added Files:
-----------
src/sys/amd64/amd64:
bpf_jit_machdep.c (r1.1)
bpf_jit_machdep.h (r1.1)
minidump_machdep.c (r1.1)
msi.c (r1.1)
src/sys/amd64/include:
minidump.h (r1.1)
src/sys/amd64/linux32:
linux32_support.s (r1.1)
-------------- next part --------------
Index: madt.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/acpica/madt.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/acpica/madt.c -L sys/amd64/acpica/madt.c -u -r1.1.1.1 -r1.2
--- sys/amd64/acpica/madt.c
+++ sys/amd64/acpica/madt.c
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/acpica/madt.c,v 1.16.2.1 2005/11/07 09:53:24 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/acpica/madt.c,v 1.24 2007/05/08 22:01:02 jhb Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -53,43 +53,43 @@
#include <dev/acpica/acpivar.h>
#include <dev/pci/pcivar.h>
-#define NIOAPICS 32 /* Max number of I/O APICs */
-#define NLAPICS 32 /* Max number of local APICs */
-
-typedef void madt_entry_handler(APIC_HEADER *entry, void *arg);
+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;
UINT32 io_vector;
-} ioapics[NIOAPICS];
+} ioapics[MAX_APIC_ID + 1];
struct lapic_info {
u_int la_enabled:1;
u_int la_acpi_id:8;
-} lapics[NLAPICS];
+} lapics[MAX_APIC_ID + 1];
static int madt_found_sci_override;
-static MULTIPLE_APIC_TABLE *madt;
+static ACPI_TABLE_MADT *madt;
static vm_paddr_t madt_physaddr;
static vm_offset_t madt_length;
-MALLOC_DEFINE(M_MADT, "MADT Table", "ACPI MADT Table Items");
+MALLOC_DEFINE(M_MADT, "madt_table", "ACPI MADT Table Items");
-static enum intr_polarity interrupt_polarity(UINT16 Polarity, UINT8 Source);
-static enum intr_trigger interrupt_trigger(UINT16 TriggerMode, UINT8 Source);
+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(APIC_HEADER *entry, void *arg);
-static void madt_parse_interrupt_override(MADT_INTERRUPT_OVERRIDE *intr);
-static void madt_parse_ints(APIC_HEADER *entry, void *arg __unused);
-static void madt_parse_local_nmi(MADT_LOCAL_APIC_NMI *nmi);
-static void madt_parse_nmi(MADT_NMI_SOURCE *nmi);
+static void madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg);
+static void madt_parse_interrupt_override(
+ ACPI_MADT_INTERRUPT_OVERRIDE *intr);
+static void madt_parse_ints(ACPI_SUBTABLE_HEADER *entry,
+ void *arg __unused);
+static void madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi);
+static void madt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi);
static int madt_probe(void);
static int madt_probe_cpus(void);
-static void madt_probe_cpus_handler(APIC_HEADER *entry, void *arg __unused);
+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);
@@ -161,14 +161,14 @@
void *table;
header = madt_map(pa, offset, sizeof(ACPI_TABLE_HEADER));
- if (strncmp(header->Signature, sig, 4) != 0) {
+ 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(AcpiTbVerifyTableChecksum(table))) {
+ if (ACPI_FAILURE(AcpiTbChecksum(table, length))) {
if (bootverbose)
printf("MADT: Failed checksum for table %s\n", sig);
madt_unmap(table, length);
@@ -192,10 +192,10 @@
static int
madt_probe(void)
{
- ACPI_POINTER rsdp_ptr;
- RSDP_DESCRIPTOR *rsdp;
- RSDT_DESCRIPTOR *rsdt;
- XSDT_DESCRIPTOR *xsdt;
+ 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))
@@ -203,15 +203,12 @@
/*
* Map in the RSDP. Since ACPI uses AcpiOsMapMemory() which in turn
- * calls pmap_mapdev() to find the RSDP, we assume that we can use
- * pmap_mapdev() to map the RSDP.
+ * calls pmap_mapbios() to find the RSDP, we assume that we can use
+ * pmap_mapbios() to map the RSDP.
*/
- if (AcpiOsGetRootPointer(ACPI_LOGICAL_ADDRESSING, &rsdp_ptr) != AE_OK)
+ if ((rsdp_ptr = AcpiOsGetRootPointer()) == 0)
return (ENXIO);
-#ifdef __i386__
- KASSERT(rsdp_ptr.Pointer.Physical < KERNLOAD, ("RSDP too high"));
-#endif
- rsdp = pmap_mapdev(rsdp_ptr.Pointer.Physical, sizeof(RSDP_DESCRIPTOR));
+ rsdp = pmap_mapbios(rsdp_ptr, sizeof(ACPI_TABLE_RSDP));
if (rsdp == NULL) {
if (bootverbose)
printf("MADT: Failed to map RSDP\n");
@@ -219,48 +216,51 @@
}
/*
- * For ACPI < 2.0, use the RSDT. For ACPI >= 2.0, use the XSDT.
- * We map the XSDT and RSDT at page 1 in the crashdump area.
- * Page 0 is used to map in the headers of candidate ACPI tables.
+ * 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) {
+ 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(rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0) {
+ 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, 1, XSDT_SIG);
+ xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 1,
+ ACPI_SIG_XSDT);
if (xsdt == NULL) {
if (bootverbose)
printf("MADT: Failed to map XSDT\n");
return (ENXIO);
}
- count = (xsdt->Length - sizeof(ACPI_TABLE_HEADER)) /
+ 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, 1, RSDT_SIG);
+ rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 1,
+ ACPI_SIG_RSDT);
if (rsdt == NULL) {
if (bootverbose)
printf("MADT: Failed to map RSDT\n");
return (ENXIO);
}
- count = (rsdt->Length - sizeof(ACPI_TABLE_HEADER)) /
+ 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_unmapdev((vm_offset_t)rsdp, sizeof(RSDP_DESCRIPTOR));
+ pmap_unmapbios((vm_offset_t)rsdp, sizeof(ACPI_TABLE_RSDP));
if (madt_physaddr == 0) {
if (bootverbose)
printf("MADT: No MADT table found\n");
@@ -274,7 +274,7 @@
* Verify that we can map the full table and that its checksum is
* correct, etc.
*/
- madt = madt_map_table(madt_physaddr, 0, APIC_SIG);
+ madt = madt_map_table(madt_physaddr, 0, ACPI_SIG_MADT);
if (madt == NULL)
return (ENXIO);
madt_unmap_table(madt);
@@ -302,7 +302,7 @@
printf("Table '%.4s' at 0x%jx\n", table->Signature,
(uintmax_t)address);
- if (strncmp(table->Signature, APIC_SIG, 4) != 0) {
+ if (strncmp(table->Signature, ACPI_SIG_MADT, ACPI_NAME_SIZE) != 0) {
madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
return (0);
}
@@ -319,7 +319,7 @@
madt_probe_cpus(void)
{
- madt = madt_map_table(madt_physaddr, 0, APIC_SIG);
+ madt = madt_map_table(madt_physaddr, 0, ACPI_SIG_MADT);
KASSERT(madt != NULL, ("Unable to re-map MADT"));
madt_walk_table(madt_probe_cpus_handler, NULL);
madt_unmap_table(madt);
@@ -334,11 +334,11 @@
madt_setup_local(void)
{
- madt = pmap_mapdev(madt_physaddr, madt_length);
- lapic_init((uintptr_t)madt->LocalApicAddress);
+ madt = pmap_mapbios(madt_physaddr, madt_length);
+ lapic_init(madt->Address);
printf("ACPI APIC Table: <%.*s %.*s>\n",
- (int)sizeof(madt->OemId), madt->OemId,
- (int)sizeof(madt->OemTableId), madt->OemTableId);
+ (int)sizeof(madt->Header.OemId), madt->Header.OemId,
+ (int)sizeof(madt->Header.OemTableId), madt->Header.OemTableId);
/*
* We ignore 64-bit local APIC override entries. Should we
@@ -377,10 +377,10 @@
* force it to use level trigger and active-low polarity.
*/
if (!madt_found_sci_override) {
- if (madt_find_interrupt(AcpiGbl_FADT->SciInt, &ioapic, &pin)
- != 0)
- printf("MADT: Could not find APIC for SCI IRQ %d\n",
- AcpiGbl_FADT->SciInt);
+ if (madt_find_interrupt(AcpiGbl_FADT.SciInterrupt, &ioapic,
+ &pin) != 0)
+ printf("MADT: Could not find APIC for SCI IRQ %u\n",
+ AcpiGbl_FADT.SciInterrupt);
else {
printf(
"MADT: Forcing active-low polarity and level trigger for SCI\n");
@@ -390,7 +390,7 @@
}
/* Third, we register all the I/O APIC's. */
- for (i = 0; i < NIOAPICS; i++)
+ for (i = 0; i <= MAX_APIC_ID; i++)
if (ioapics[i].io_apic != NULL)
ioapic_register(ioapics[i].io_apic);
@@ -415,46 +415,46 @@
static void
madt_walk_table(madt_entry_handler *handler, void *arg)
{
- APIC_HEADER *entry;
+ ACPI_SUBTABLE_HEADER *entry;
u_char *p, *end;
- end = (u_char *)(madt) + madt->Length;
+ end = (u_char *)(madt) + madt->Header.Length;
for (p = (u_char *)(madt + 1); p < end; ) {
- entry = (APIC_HEADER *)p;
+ entry = (ACPI_SUBTABLE_HEADER *)p;
handler(entry, arg);
p += entry->Length;
}
}
static void
-madt_probe_cpus_handler(APIC_HEADER *entry, void *arg)
+madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg)
{
- MADT_PROCESSOR_APIC *proc;
+ ACPI_MADT_LOCAL_APIC *proc;
struct lapic_info *la;
switch (entry->Type) {
- case APIC_PROCESSOR:
+ case ACPI_MADT_TYPE_LOCAL_APIC:
/*
* The MADT does not include a BSP flag, so we have to
* let the MP code figure out which CPU is the BSP on
* its own.
*/
- proc = (MADT_PROCESSOR_APIC *)entry;
+ proc = (ACPI_MADT_LOCAL_APIC *)entry;
if (bootverbose)
- printf("MADT: Found CPU APIC ID %d ACPI ID %d: %s\n",
- proc->LocalApicId, proc->ProcessorId,
- proc->ProcessorEnabled ? "enabled" : "disabled");
- if (!proc->ProcessorEnabled)
+ printf("MADT: Found CPU APIC ID %u ACPI ID %u: %s\n",
+ proc->Id, proc->ProcessorId,
+ (proc->LapicFlags & ACPI_MADT_ENABLED) ?
+ "enabled" : "disabled");
+ if (!(proc->LapicFlags & ACPI_MADT_ENABLED))
break;
- if (proc->LocalApicId >= NLAPICS)
- panic("%s: CPU ID %d too high", __func__,
- proc->LocalApicId);
- la = &lapics[proc->LocalApicId];
+ if (proc->Id > MAX_APIC_ID)
+ panic("%s: CPU ID %u too high", __func__, proc->Id);
+ la = &lapics[proc->Id];
KASSERT(la->la_enabled == 0,
- ("Duplicate local APIC ID %d", proc->LocalApicId));
+ ("Duplicate local APIC ID %u", proc->Id));
la->la_enabled = 1;
la->la_acpi_id = proc->ProcessorId;
- lapic_create(proc->LocalApicId, 0);
+ lapic_create(proc->Id, 0);
break;
}
}
@@ -464,27 +464,26 @@
* Add an I/O APIC from an entry in the table.
*/
static void
-madt_parse_apics(APIC_HEADER *entry, void *arg __unused)
+madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg __unused)
{
- MADT_IO_APIC *apic;
+ ACPI_MADT_IO_APIC *apic;
switch (entry->Type) {
- case APIC_IO:
- apic = (MADT_IO_APIC *)entry;
+ case ACPI_MADT_TYPE_IO_APIC:
+ apic = (ACPI_MADT_IO_APIC *)entry;
if (bootverbose)
- printf("MADT: Found IO APIC ID %d, Interrupt %d at %p\n",
- apic->IoApicId, apic->Interrupt,
+ printf(
+ "MADT: Found IO APIC ID %u, Interrupt %u at %p\n",
+ apic->Id, apic->GlobalIrqBase,
(void *)(uintptr_t)apic->Address);
- if (apic->IoApicId >= NIOAPICS)
- panic("%s: I/O APIC ID %d too high", __func__,
- apic->IoApicId);
- if (ioapics[apic->IoApicId].io_apic != NULL)
- panic("%s: Double APIC ID %d", __func__,
- apic->IoApicId);
- ioapics[apic->IoApicId].io_apic = ioapic_create(
- (uintptr_t)apic->Address, apic->IoApicId,
- apic->Interrupt);
- ioapics[apic->IoApicId].io_vector = apic->Interrupt;
+ if (apic->Id > MAX_APIC_ID)
+ panic("%s: I/O APIC ID %u too high", __func__,
+ apic->Id);
+ if (ioapics[apic->Id].io_apic != NULL)
+ panic("%s: Double APIC ID %u", __func__, apic->Id);
+ ioapics[apic->Id].io_apic = ioapic_create(apic->Address,
+ apic->Id, apic->GlobalIrqBase);
+ ioapics[apic->Id].io_vector = apic->GlobalIrqBase;
break;
default:
break;
@@ -498,18 +497,18 @@
* SCI for which we use Active Lo, Level Triggered.
*/
static enum intr_polarity
-interrupt_polarity(UINT16 Polarity, UINT8 Source)
+interrupt_polarity(UINT16 IntiFlags, UINT8 Source)
{
- switch (Polarity) {
- case POLARITY_CONFORMS:
- if (Source == AcpiGbl_FADT->SciInt)
+ switch (IntiFlags & ACPI_MADT_POLARITY_MASK) {
+ case ACPI_MADT_POLARITY_CONFORMS:
+ if (Source == AcpiGbl_FADT.SciInterrupt)
return (INTR_POLARITY_LOW);
else
return (INTR_POLARITY_HIGH);
- case POLARITY_ACTIVE_HIGH:
+ case ACPI_MADT_POLARITY_ACTIVE_HIGH:
return (INTR_POLARITY_HIGH);
- case POLARITY_ACTIVE_LOW:
+ case ACPI_MADT_POLARITY_ACTIVE_LOW:
return (INTR_POLARITY_LOW);
default:
panic("Bogus Interrupt Polarity");
@@ -517,18 +516,18 @@
}
static enum intr_trigger
-interrupt_trigger(UINT16 TriggerMode, UINT8 Source)
+interrupt_trigger(UINT16 IntiFlags, UINT8 Source)
{
- switch (TriggerMode) {
- case TRIGGER_CONFORMS:
- if (Source == AcpiGbl_FADT->SciInt)
+ switch (IntiFlags & ACPI_MADT_TRIGGER_MASK) {
+ case ACPI_MADT_TRIGGER_CONFORMS:
+ if (Source == AcpiGbl_FADT.SciInterrupt)
return (INTR_TRIGGER_LEVEL);
else
return (INTR_TRIGGER_EDGE);
- case TRIGGER_EDGE:
+ case ACPI_MADT_TRIGGER_EDGE:
return (INTR_TRIGGER_EDGE);
- case TRIGGER_LEVEL:
+ case ACPI_MADT_TRIGGER_LEVEL:
return (INTR_TRIGGER_LEVEL);
default:
panic("Bogus Interrupt Trigger Mode");
@@ -543,7 +542,7 @@
{
int i;
- for (i = 0; i < NLAPICS; i++) {
+ for (i = 0; i <= MAX_APIC_ID; i++) {
if (!lapics[i].la_enabled)
continue;
if (lapics[i].la_acpi_id != acpi_id)
@@ -564,7 +563,7 @@
int i, best;
best = -1;
- for (i = 0; i < NIOAPICS; i++) {
+ for (i = 0; i <= MAX_APIC_ID; i++) {
if (ioapics[i].io_apic == NULL ||
ioapics[i].io_vector > intr)
continue;
@@ -586,7 +585,7 @@
* Parse an interrupt source override for an ISA interrupt.
*/
static void
-madt_parse_interrupt_override(MADT_INTERRUPT_OVERRIDE *intr)
+madt_parse_interrupt_override(ACPI_MADT_INTERRUPT_OVERRIDE *intr)
{
void *new_ioapic, *old_ioapic;
u_int new_pin, old_pin;
@@ -594,20 +593,19 @@
enum intr_polarity pol;
char buf[64];
- if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->Source == 0 &&
- intr->Interrupt == 2) {
+ if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->SourceIrq == 0 &&
+ intr->GlobalIrq == 2) {
if (bootverbose)
printf("MADT: Skipping timer override\n");
return;
}
if (bootverbose)
printf("MADT: Interrupt override: source %u, irq %u\n",
- intr->Source, intr->Interrupt);
+ intr->SourceIrq, intr->GlobalIrq);
KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero"));
- if (madt_find_interrupt(intr->Interrupt, &new_ioapic,
- &new_pin) != 0) {
- printf("MADT: Could not find APIC for vector %d (IRQ %d)\n",
- intr->Interrupt, intr->Source);
+ if (madt_find_interrupt(intr->GlobalIrq, &new_ioapic, &new_pin) != 0) {
+ printf("MADT: Could not find APIC for vector %u (IRQ %u)\n",
+ intr->GlobalIrq, intr->SourceIrq);
return;
}
@@ -615,15 +613,15 @@
* Lookup the appropriate trigger and polarity modes for this
* entry.
*/
- trig = interrupt_trigger(intr->TriggerMode, intr->Source);
- pol = interrupt_polarity(intr->Polarity, intr->Source);
+ trig = interrupt_trigger(intr->IntiFlags, intr->SourceIrq);
+ pol = interrupt_polarity(intr->IntiFlags, intr->SourceIrq);
/*
* If the SCI is identity mapped but has edge trigger and
* active-hi polarity or the force_sci_lo tunable is set,
* force it to use level/lo.
*/
- if (intr->Source == AcpiGbl_FADT->SciInt) {
+ if (intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) {
madt_found_sci_override = 1;
if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) {
if (tolower(buf[0]) == 'e')
@@ -652,23 +650,24 @@
}
/* Remap the IRQ if it is mapped to a different interrupt vector. */
- if (intr->Source != intr->Interrupt) {
+ if (intr->SourceIrq != intr->GlobalIrq) {
/*
* If the SCI is remapped to a non-ISA global interrupt,
* then override the vector we use to setup and allocate
* the interrupt.
*/
- if (intr->Interrupt > 15 &&
- intr->Source == AcpiGbl_FADT->SciInt)
- acpi_OverrideInterruptLevel(intr->Interrupt);
+ if (intr->GlobalIrq > 15 &&
+ intr->SourceIrq == AcpiGbl_FADT.SciInterrupt)
+ acpi_OverrideInterruptLevel(intr->GlobalIrq);
else
- ioapic_remap_vector(new_ioapic, new_pin, intr->Source);
- if (madt_find_interrupt(intr->Source, &old_ioapic,
+ ioapic_remap_vector(new_ioapic, new_pin,
+ intr->SourceIrq);
+ if (madt_find_interrupt(intr->SourceIrq, &old_ioapic,
&old_pin) != 0)
- printf("MADT: Could not find APIC for source IRQ %d\n",
- intr->Source);
+ printf("MADT: Could not find APIC for source IRQ %u\n",
+ intr->SourceIrq);
else if (ioapic_get_vector(old_ioapic, old_pin) ==
- intr->Source)
+ intr->SourceIrq)
ioapic_disable_pin(old_ioapic, old_pin);
}
@@ -681,31 +680,31 @@
* Parse an entry for an NMI routed to an IO APIC.
*/
static void
-madt_parse_nmi(MADT_NMI_SOURCE *nmi)
+madt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi)
{
void *ioapic;
u_int pin;
- if (madt_find_interrupt(nmi->Interrupt, &ioapic, &pin) != 0) {
- printf("MADT: Could not find APIC for vector %d\n",
- nmi->Interrupt);
+ if (madt_find_interrupt(nmi->GlobalIrq, &ioapic, &pin) != 0) {
+ printf("MADT: Could not find APIC for vector %u\n",
+ nmi->GlobalIrq);
return;
}
ioapic_set_nmi(ioapic, pin);
- if (nmi->TriggerMode != TRIGGER_CONFORMS)
+ if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
ioapic_set_triggermode(ioapic, pin,
- interrupt_trigger(nmi->TriggerMode, 0));
- if (nmi->Polarity != TRIGGER_CONFORMS)
+ interrupt_trigger(nmi->IntiFlags, 0));
+ if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
ioapic_set_polarity(ioapic, pin,
- interrupt_polarity(nmi->Polarity, 0));
+ interrupt_polarity(nmi->IntiFlags, 0));
}
/*
* Parse an entry for an NMI routed to a local APIC LVT pin.
*/
static void
-madt_parse_local_nmi(MADT_LOCAL_APIC_NMI *nmi)
+madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi)
{
u_int apic_id, pin;
@@ -713,8 +712,8 @@
apic_id = APIC_ID_ALL;
else if (madt_find_cpu(nmi->ProcessorId, &apic_id) != 0) {
if (bootverbose)
- printf("MADT: Ignoring local NMI routed to ACPI CPU %u\n",
- nmi->ProcessorId);
+ printf("MADT: Ignoring local NMI routed to "
+ "ACPI CPU %u\n", nmi->ProcessorId);
return;
}
if (nmi->Lint == 0)
@@ -722,31 +721,31 @@
else
pin = LVT_LINT1;
lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
- if (nmi->TriggerMode != TRIGGER_CONFORMS)
+ if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
lapic_set_lvt_triggermode(apic_id, pin,
- interrupt_trigger(nmi->TriggerMode, 0));
- if (nmi->Polarity != POLARITY_CONFORMS)
+ interrupt_trigger(nmi->IntiFlags, 0));
+ if (!(nmi->IntiFlags & ACPI_MADT_POLARITY_CONFORMS))
lapic_set_lvt_polarity(apic_id, pin,
- interrupt_polarity(nmi->Polarity, 0));
+ interrupt_polarity(nmi->IntiFlags, 0));
}
/*
* Parse interrupt entries.
*/
static void
-madt_parse_ints(APIC_HEADER *entry, void *arg __unused)
+madt_parse_ints(ACPI_SUBTABLE_HEADER *entry, void *arg __unused)
{
switch (entry->Type) {
- case APIC_XRUPT_OVERRIDE:
+ case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
madt_parse_interrupt_override(
- (MADT_INTERRUPT_OVERRIDE *)entry);
+ (ACPI_MADT_INTERRUPT_OVERRIDE *)entry);
break;
- case APIC_NMI:
- madt_parse_nmi((MADT_NMI_SOURCE *)entry);
+ case ACPI_MADT_TYPE_NMI_SOURCE:
+ madt_parse_nmi((ACPI_MADT_NMI_SOURCE *)entry);
break;
- case APIC_LOCAL_NMI:
- madt_parse_local_nmi((MADT_LOCAL_APIC_NMI *)entry);
+ case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
+ madt_parse_local_nmi((ACPI_MADT_LOCAL_APIC_NMI *)entry);
break;
}
}
@@ -767,7 +766,7 @@
if (CPU_ABSENT(i))
continue;
pc = pcpu_find(i);
- KASSERT(pc != NULL, ("no pcpu data for CPU %d", i));
+ KASSERT(pc != NULL, ("no pcpu data for CPU %u", i));
la = &lapics[pc->pc_apic_id];
if (!la->la_enabled)
panic("APIC: CPU with APIC ID %u is not enabled",
Index: acpi_wakeup.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/acpica/acpi_wakeup.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/acpica/acpi_wakeup.c -L sys/amd64/acpica/acpi_wakeup.c -u -r1.1.1.1 -r1.2
--- sys/amd64/acpica/acpi_wakeup.c
+++ sys/amd64/acpica/acpi_wakeup.c
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/acpica/acpi_wakeup.c,v 1.21.10.1 2005/11/07 09:53:24 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/acpica/acpi_wakeup.c,v 1.22 2005/09/11 18:39:00 obrien Exp $");
#include <sys/param.h>
#include <sys/bus.h>
Index: OsdEnvironment.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/acpica/OsdEnvironment.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/acpica/OsdEnvironment.c -L sys/amd64/acpica/OsdEnvironment.c -u -r1.1.1.1 -r1.2
--- sys/amd64/acpica/OsdEnvironment.c
+++ sys/amd64/acpica/OsdEnvironment.c
@@ -26,16 +26,18 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/acpica/OsdEnvironment.c,v 1.12.8.1 2005/11/07 09:53:24 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/acpica/OsdEnvironment.c,v 1.14 2007/03/22 18:16:38 jkim Exp $");
/*
* 6.1 : Environmental support
*/
#include <sys/types.h>
+#include <sys/bus.h>
#include <sys/linker_set.h>
#include <sys/sysctl.h>
#include <contrib/dev/acpica/acpi.h>
+#include <contrib/dev/acpica/actables.h>
static u_long amd64_acpi_root;
@@ -54,25 +56,16 @@
return(0);
}
-ACPI_STATUS
-AcpiOsGetRootPointer(UINT32 Flags, ACPI_POINTER *RsdpPhysicalAddress)
+ACPI_PHYSICAL_ADDRESS
+AcpiOsGetRootPointer(void)
{
- ACPI_POINTER ptr;
- ACPI_STATUS status;
+ u_long ptr;
+
+ if (amd64_acpi_root == 0 &&
+ (resource_long_value("acpi", 0, "rsdp", (long *)&ptr) == 0 ||
+ AcpiFindRootPointer((ACPI_NATIVE_UINT *)&ptr) == AE_OK) &&
+ ptr != 0)
+ amd64_acpi_root = ptr;
- if (amd64_acpi_root == 0) {
- /*
- * The loader passes the physical address at which it found the
- * RSDP in a hint. We could recover this rather than searching
- * manually here.
- */
- status = AcpiFindRootPointer(Flags, &ptr);
- if (status == AE_OK)
- amd64_acpi_root = ptr.Pointer.Physical;
- } else
- status = AE_OK;
-
- RsdpPhysicalAddress->PointerType = ACPI_PHYSICAL_POINTER;
- RsdpPhysicalAddress->Pointer.Physical = amd64_acpi_root;
- return (status);
+ return (amd64_acpi_root);
}
Index: acpi_machdep.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/acpica/acpi_machdep.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/acpica/acpi_machdep.c -L sys/amd64/acpica/acpi_machdep.c -u -r1.1.1.1 -r1.2
--- sys/amd64/acpica/acpi_machdep.c
+++ sys/amd64/acpica/acpi_machdep.c
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/acpica/acpi_machdep.c,v 1.16.2.1 2005/11/07 09:53:24 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/acpica/acpi_machdep.c,v 1.17 2005/09/11 18:39:00 obrien Exp $");
#include <sys/param.h>
#include <sys/bus.h>
Index: intr_machdep.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/intr_machdep.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/amd64/amd64/intr_machdep.c -L sys/amd64/amd64/intr_machdep.c -u -r1.2 -r1.3
--- sys/amd64/amd64/intr_machdep.c
+++ sys/amd64/amd64/intr_machdep.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/amd64/amd64/intr_machdep.c,v 1.15.2.2 2006/03/10 19:37:30 jhb Exp $
+ * $FreeBSD: src/sys/amd64/amd64/intr_machdep.c,v 1.34.2.1 2007/11/26 15:06:49 scottl Exp $
*/
/*
@@ -37,31 +37,50 @@
* that source.
*/
+#include "opt_atpic.h"
#include "opt_ddb.h"
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/interrupt.h>
-#include <sys/lock.h>
#include <sys/ktr.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/syslog.h>
#include <sys/systm.h>
+#include <sys/sx.h>
#include <machine/clock.h>
#include <machine/intr_machdep.h>
+#include <machine/smp.h>
#ifdef DDB
#include <ddb/ddb.h>
#endif
+#ifndef DEV_ATPIC
+#include <machine/segments.h>
+#include <machine/frame.h>
+#include <dev/ic/i8259.h>
+#include <amd64/isa/icu.h>
+#include <amd64/isa/isa.h>
+#endif
+
#define MAX_STRAY_LOG 5
typedef void (*mask_fn)(void *);
static int intrcnt_index;
static struct intsrc *interrupt_sources[NUM_IO_INTS];
-static struct mtx intr_table_lock;
+static struct sx intr_table_lock;
+static struct mtx intrcnt_lock;
+static STAILQ_HEAD(, pic) pics;
+
+#ifdef INTR_FILTER
+static void intr_eoi_src(void *arg);
+static void intr_disab_eoi_src(void *arg);
+static void intr_event_stray(void *cookie);
+#endif
#ifdef SMP
static int assign_cpu;
@@ -70,10 +89,45 @@
#endif
static void intr_init(void *__dummy);
+static int intr_pic_registered(struct pic *pic);
static void intrcnt_setname(const char *name, int index);
static void intrcnt_updatename(struct intsrc *is);
static void intrcnt_register(struct intsrc *is);
+static int
+intr_pic_registered(struct pic *pic)
+{
+ struct pic *p;
+
+ STAILQ_FOREACH(p, &pics, pics) {
+ if (p == pic)
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * Register a new interrupt controller (PIC). This is to support suspend
+ * and resume where we suspend/resume controllers rather than individual
+ * sources. This also allows controllers with no active sources (such as
+ * 8259As in a system using the APICs) to participate in suspend and resume.
+ */
+int
+intr_register_pic(struct pic *pic)
+{
+ int error;
+
+ sx_xlock(&intr_table_lock);
+ if (intr_pic_registered(pic))
+ error = EBUSY;
+ else {
+ STAILQ_INSERT_TAIL(&pics, pic, pics);
+ error = 0;
+ }
+ sx_xunlock(&intr_table_lock);
+ return (error);
+}
+
/*
* Register a new interrupt source with the global interrupt system.
* The global interrupts need to be disabled when this function is
@@ -84,23 +138,30 @@
{
int error, vector;
+ KASSERT(intr_pic_registered(isrc->is_pic), ("unregistered PIC"));
vector = isrc->is_pic->pic_vector(isrc);
if (interrupt_sources[vector] != NULL)
return (EEXIST);
+#ifdef INTR_FILTER
+ error = intr_event_create(&isrc->is_event, isrc, 0,
+ (mask_fn)isrc->is_pic->pic_enable_source,
+ intr_eoi_src, intr_disab_eoi_src, "irq%d:", vector);
+#else
error = intr_event_create(&isrc->is_event, isrc, 0,
(mask_fn)isrc->is_pic->pic_enable_source, "irq%d:", vector);
+#endif
if (error)
return (error);
- mtx_lock_spin(&intr_table_lock);
+ sx_xlock(&intr_table_lock);
if (interrupt_sources[vector] != NULL) {
- mtx_unlock_spin(&intr_table_lock);
+ sx_xunlock(&intr_table_lock);
intr_event_destroy(isrc->is_event);
return (EEXIST);
}
intrcnt_register(isrc);
interrupt_sources[vector] = isrc;
- isrc->is_enabled = 0;
- mtx_unlock_spin(&intr_table_lock);
+ isrc->is_handlers = 0;
+ sx_xunlock(&intr_table_lock);
return (0);
}
@@ -112,8 +173,8 @@
}
int
-intr_add_handler(const char *name, int vector, driver_intr_t handler,
- void *arg, enum intr_type flags, void **cookiep)
+intr_add_handler(const char *name, int vector, driver_filter_t filter,
+ driver_intr_t handler, void *arg, enum intr_type flags, void **cookiep)
{
struct intsrc *isrc;
int error;
@@ -121,22 +182,21 @@
isrc = intr_lookup_source(vector);
if (isrc == NULL)
return (EINVAL);
- error = intr_event_add_handler(isrc->is_event, name, handler, arg,
- intr_priority(flags), flags, cookiep);
+ error = intr_event_add_handler(isrc->is_event, name, filter, handler,
+ arg, intr_priority(flags), flags, cookiep);
if (error == 0) {
+ sx_xlock(&intr_table_lock);
intrcnt_updatename(isrc);
- mtx_lock_spin(&intr_table_lock);
- if (!isrc->is_enabled) {
- isrc->is_enabled = 1;
+ isrc->is_handlers++;
+ if (isrc->is_handlers == 1) {
#ifdef SMP
if (assign_cpu)
intr_assign_next_cpu(isrc);
#endif
- mtx_unlock_spin(&intr_table_lock);
isrc->is_pic->pic_enable_intr(isrc);
- } else
- mtx_unlock_spin(&intr_table_lock);
- isrc->is_pic->pic_enable_source(isrc);
+ isrc->is_pic->pic_enable_source(isrc);
+ }
+ sx_xunlock(&intr_table_lock);
}
return (error);
}
@@ -144,13 +204,21 @@
int
intr_remove_handler(void *cookie)
{
+ struct intsrc *isrc;
int error;
+ isrc = intr_handler_source(cookie);
error = intr_event_remove_handler(cookie);
-#ifdef XXX
- if (error == 0)
- intrcnt_updatename(/* XXX */);
-#endif
+ if (error == 0) {
+ sx_xlock(&intr_table_lock);
+ isrc->is_handlers--;
+ if (isrc->is_handlers == 0) {
+ isrc->is_pic->pic_disable_source(isrc, PIC_NO_EOI);
+ isrc->is_pic->pic_disable_intr(isrc);
+ }
+ intrcnt_updatename(isrc);
+ sx_xunlock(&intr_table_lock);
+ }
return (error);
}
@@ -165,13 +233,84 @@
return (isrc->is_pic->pic_config_intr(isrc, trig, pol));
}
+#ifdef INTR_FILTER
void
-intr_execute_handlers(struct intsrc *isrc, struct intrframe *iframe)
+intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame)
+{
+ struct thread *td;
+ struct intr_event *ie;
+ int vector;
+
+ td = curthread;
+
+ /*
+ * We count software interrupts when we process them. The
+ * code here follows previous practice, but there's an
+ * argument for counting hardware interrupts when they're
+ * processed too.
+ */
+ (*isrc->is_count)++;
+ PCPU_INC(cnt.v_intr);
+
+ ie = isrc->is_event;
+
+ /*
+ * XXX: We assume that IRQ 0 is only used for the ISA timer
+ * device (clk).
+ */
+ vector = isrc->is_pic->pic_vector(isrc);
+ if (vector == 0)
+ clkintr_pending = 1;
+
+ if (intr_event_handle(ie, frame) != 0)
+ intr_event_stray(isrc);
+}
+
+static void
+intr_event_stray(void *cookie)
+{
+ struct intsrc *isrc;
+
+ isrc = cookie;
+ /*
+ * For stray interrupts, mask and EOI the source, bump the
+ * stray count, and log the condition.
+ */
+ isrc->is_pic->pic_disable_source(isrc, PIC_EOI);
+ (*isrc->is_straycount)++;
+ if (*isrc->is_straycount < MAX_STRAY_LOG)
+ log(LOG_ERR, "stray irq%d\n", isrc->is_pic->pic_vector(isrc));
+ else if (*isrc->is_straycount == MAX_STRAY_LOG)
+ log(LOG_CRIT,
+ "too many stray irq %d's: not logging anymore\n",
+ isrc->is_pic->pic_vector(isrc));
+}
+
+static void
+intr_eoi_src(void *arg)
+{
+ struct intsrc *isrc;
+
+ isrc = arg;
+ isrc->is_pic->pic_eoi_source(isrc);
+}
+
+static void
+intr_disab_eoi_src(void *arg)
+{
+ struct intsrc *isrc;
+
+ isrc = arg;
+ isrc->is_pic->pic_disable_source(isrc, PIC_EOI);
+}
+#else
+void
+intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame)
{
struct thread *td;
struct intr_event *ie;
struct intr_handler *ih;
- int error, vector, thread;
+ int error, vector, thread, ret;
td = curthread;
@@ -182,7 +321,7 @@
* processed too.
*/
(*isrc->is_count)++;
- PCPU_LAZY_INC(cnt.v_intr);
+ PCPU_INC(cnt.v_intr);
ie = isrc->is_event;
@@ -214,23 +353,32 @@
* Execute fast interrupt handlers directly.
* To support clock handlers, if a handler registers
* with a NULL argument, then we pass it a pointer to
- * an intrframe as its argument.
+ * a trapframe as its argument.
*/
td->td_intr_nesting_level++;
+ ret = 0;
thread = 0;
critical_enter();
TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
- if (!(ih->ih_flags & IH_FAST)) {
+ if (ih->ih_filter == NULL) {
thread = 1;
continue;
}
CTR4(KTR_INTR, "%s: exec %p(%p) for %s", __func__,
- ih->ih_handler, ih->ih_argument == NULL ? iframe :
+ ih->ih_filter, ih->ih_argument == NULL ? frame :
ih->ih_argument, ih->ih_name);
if (ih->ih_argument == NULL)
- ih->ih_handler(iframe);
+ ret = ih->ih_filter(frame);
else
- ih->ih_handler(ih->ih_argument);
+ ret = ih->ih_filter(ih->ih_argument);
+ /*
+ * Wrapper handler special case: see
+ * i386/intr_machdep.c::intr_execute_handlers()
+ */
+ if (!thread) {
+ if (ret == FILTER_SCHEDULE_THREAD)
+ thread = 1;
+ }
}
/*
@@ -242,40 +390,44 @@
isrc->is_pic->pic_disable_source(isrc, PIC_EOI);
else
isrc->is_pic->pic_eoi_source(isrc);
- critical_exit();
/* Schedule the ithread if needed. */
if (thread) {
error = intr_event_schedule_thread(ie);
KASSERT(error == 0, ("bad stray interrupt"));
}
+ critical_exit();
td->td_intr_nesting_level--;
}
+#endif
void
intr_resume(void)
{
- struct intsrc **isrc;
- int i;
+ struct pic *pic;
- mtx_lock_spin(&intr_table_lock);
- for (i = 0, isrc = interrupt_sources; i < NUM_IO_INTS; i++, isrc++)
- if (*isrc != NULL && (*isrc)->is_pic->pic_resume != NULL)
- (*isrc)->is_pic->pic_resume(*isrc);
- mtx_unlock_spin(&intr_table_lock);
+#ifndef DEV_ATPIC
+ atpic_reset();
+#endif
+ sx_xlock(&intr_table_lock);
+ STAILQ_FOREACH(pic, &pics, pics) {
+ if (pic->pic_resume != NULL)
+ pic->pic_resume(pic);
+ }
+ sx_xunlock(&intr_table_lock);
}
void
intr_suspend(void)
{
- struct intsrc **isrc;
- int i;
+ struct pic *pic;
- mtx_lock_spin(&intr_table_lock);
- for (i = 0, isrc = interrupt_sources; i < NUM_IO_INTS; i++, isrc++)
- if (*isrc != NULL && (*isrc)->is_pic->pic_suspend != NULL)
- (*isrc)->is_pic->pic_suspend(*isrc);
- mtx_unlock_spin(&intr_table_lock);
+ sx_xlock(&intr_table_lock);
+ STAILQ_FOREACH(pic, &pics, pics) {
+ if (pic->pic_suspend != NULL)
+ pic->pic_suspend(pic);
+ }
+ sx_xunlock(&intr_table_lock);
}
static void
@@ -298,8 +450,8 @@
{
char straystr[MAXCOMLEN + 1];
- /* mtx_assert(&intr_table_lock, MA_OWNED); */
KASSERT(is->is_event != NULL, ("%s: isrc with no event", __func__));
+ mtx_lock_spin(&intrcnt_lock);
is->is_index = intrcnt_index;
intrcnt_index += 2;
snprintf(straystr, MAXCOMLEN + 1, "stray irq%d",
@@ -308,17 +460,18 @@
is->is_count = &intrcnt[is->is_index];
intrcnt_setname(straystr, is->is_index + 1);
is->is_straycount = &intrcnt[is->is_index + 1];
+ mtx_unlock_spin(&intrcnt_lock);
}
void
intrcnt_add(const char *name, u_long **countp)
{
- mtx_lock_spin(&intr_table_lock);
+ mtx_lock_spin(&intrcnt_lock);
*countp = &intrcnt[intrcnt_index];
intrcnt_setname(name, intrcnt_index);
intrcnt_index++;
- mtx_unlock_spin(&intr_table_lock);
+ mtx_unlock_spin(&intrcnt_lock);
}
static void
@@ -327,10 +480,34 @@
intrcnt_setname("???", 0);
intrcnt_index = 1;
- mtx_init(&intr_table_lock, "intr table", NULL, MTX_SPIN);
+ STAILQ_INIT(&pics);
+ sx_init(&intr_table_lock, "intr sources");
+ mtx_init(&intrcnt_lock, "intrcnt", NULL, MTX_SPIN);
}
SYSINIT(intr_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_init, NULL)
+#ifndef DEV_ATPIC
+/* Initialize the two 8259A's to a known-good shutdown state. */
+void
+atpic_reset(void)
+{
+
+ outb(IO_ICU1, ICW1_RESET | ICW1_IC4);
+ outb(IO_ICU1 + ICU_IMR_OFFSET, IDT_IO_INTS);
+ outb(IO_ICU1 + ICU_IMR_OFFSET, 1 << 2);
+ outb(IO_ICU1 + ICU_IMR_OFFSET, ICW4_8086);
+ outb(IO_ICU1 + ICU_IMR_OFFSET, 0xff);
+ outb(IO_ICU1, OCW3_SEL | OCW3_RR);
+
+ outb(IO_ICU2, ICW1_RESET | ICW1_IC4);
+ outb(IO_ICU2 + ICU_IMR_OFFSET, IDT_IO_INTS + 8);
+ outb(IO_ICU2 + ICU_IMR_OFFSET, 2);
+ outb(IO_ICU2 + ICU_IMR_OFFSET, ICW4_8086);
+ outb(IO_ICU2 + ICU_IMR_OFFSET, 0xff);
+ outb(IO_ICU2, OCW3_SEL | OCW3_RR);
+}
+#endif
+
#ifdef DDB
/*
* Dump data about interrupt handlers
@@ -338,16 +515,14 @@
DB_SHOW_COMMAND(irqs, db_show_irqs)
{
struct intsrc **isrc;
- int i, quit, verbose;
+ int i, verbose;
- quit = 0;
if (strcmp(modif, "v") == 0)
verbose = 1;
else
verbose = 0;
isrc = interrupt_sources;
- db_setup_paging(db_simple_pager, &quit, db_lines_per_page);
- for (i = 0; i < NUM_IO_INTS && !quit; i++, isrc++)
+ for (i = 0; i < NUM_IO_INTS && !db_pager_quit; i++, isrc++)
if (*isrc != NULL)
db_dump_intr_event((*isrc)->is_event, verbose);
}
@@ -359,8 +534,9 @@
* allocate CPUs round-robin.
*/
-static u_int cpu_apic_ids[MAXCPU];
-static int current_cpu, num_cpus;
+/* The BSP is always a valid target. */
+static cpumask_t intr_cpus = (1 << 0);
+static int current_cpu, num_cpus = 1;
static void
intr_assign_next_cpu(struct intsrc *isrc)
@@ -373,29 +549,29 @@
*/
pic = isrc->is_pic;
apic_id = cpu_apic_ids[current_cpu];
- current_cpu++;
- if (current_cpu >= num_cpus)
- current_cpu = 0;
- if (bootverbose) {
- printf("INTR: Assigning IRQ %d", pic->pic_vector(isrc));
- printf(" to local APIC %u\n", apic_id);
- }
pic->pic_assign_cpu(isrc, apic_id);
+ do {
+ current_cpu++;
+ if (current_cpu >= num_cpus)
+ current_cpu = 0;
+ } while (!(intr_cpus & (1 << current_cpu)));
}
/*
- * Add a local APIC ID to our list of valid local APIC IDs that can
- * be destinations of interrupts.
+ * Add a CPU to our mask of valid CPUs that can be destinations of
+ * interrupts.
*/
void
-intr_add_cpu(u_int apic_id)
+intr_add_cpu(u_int cpu)
{
+ if (cpu >= MAXCPU)
+ panic("%s: Invalid CPU ID", __func__);
if (bootverbose)
- printf("INTR: Adding local APIC %d as a target\n", apic_id);
- if (num_cpus >= MAXCPU)
- panic("WARNING: Local APIC IDs exhausted!");
- cpu_apic_ids[num_cpus] = apic_id;
+ printf("INTR: Adding local APIC %d as a target\n",
+ cpu_apic_ids[cpu]);
+
+ intr_cpus |= (1 << cpu);
num_cpus++;
}
@@ -413,15 +589,15 @@
if (num_cpus <= 1)
return;
- /* Round-robin assign each enabled source a CPU. */
- mtx_lock_spin(&intr_table_lock);
+ /* Round-robin assign a CPU to each enabled source. */
+ sx_xlock(&intr_table_lock);
assign_cpu = 1;
for (i = 0; i < NUM_IO_INTS; i++) {
isrc = interrupt_sources[i];
- if (isrc != NULL && isrc->is_enabled)
+ if (isrc != NULL && isrc->is_handlers > 0)
intr_assign_next_cpu(isrc);
}
- mtx_unlock_spin(&intr_table_lock);
+ sx_xunlock(&intr_table_lock);
}
SYSINIT(intr_shuffle_irqs, SI_SUB_SMP, SI_ORDER_SECOND, intr_shuffle_irqs, NULL)
#endif
Index: db_disasm.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/db_disasm.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/amd64/db_disasm.c -L sys/amd64/amd64/db_disasm.c -u -r1.1.1.1 -r1.2
--- sys/amd64/amd64/db_disasm.c
+++ sys/amd64/amd64/db_disasm.c
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/db_disasm.c,v 1.30 2005/03/30 22:57:41 peter Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/db_disasm.c,v 1.31 2006/11/13 21:14:54 jhb Exp $");
/*
* Instruction disassembler.
@@ -84,6 +84,7 @@
#define Ib 21 /* byte immediate, unsigned */
#define Ibs 22 /* byte immediate, signed */
#define Iw 23 /* word immediate, unsigned */
+#define Ilq 24 /* long/quad immediate, unsigned */
#define O 25 /* direct address */
#define Db 26 /* byte displacement from EIP */
#define Dl 27 /* long displacement from EIP */
@@ -351,7 +352,6 @@
0,
0,
0,
- 0,
db_inst_0f8x,
db_inst_0f9x,
db_inst_0fax,
@@ -752,14 +752,14 @@
/*b6*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 },
/*b7*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 },
-/*b8*/ { "mov", FALSE, LONG, op2(I, Ri), 0 },
-/*b9*/ { "mov", FALSE, LONG, op2(I, Ri), 0 },
-/*ba*/ { "mov", FALSE, LONG, op2(I, Ri), 0 },
-/*bb*/ { "mov", FALSE, LONG, op2(I, Ri), 0 },
-/*bc*/ { "mov", FALSE, LONG, op2(I, Ri), 0 },
-/*bd*/ { "mov", FALSE, LONG, op2(I, Ri), 0 },
-/*be*/ { "mov", FALSE, LONG, op2(I, Ri), 0 },
-/*bf*/ { "mov", FALSE, LONG, op2(I, Ri), 0 },
+/*b8*/ { "mov", FALSE, LONG, op2(Ilq, Ri), 0 },
+/*b9*/ { "mov", FALSE, LONG, op2(Ilq, Ri), 0 },
+/*ba*/ { "mov", FALSE, LONG, op2(Ilq, Ri), 0 },
+/*bb*/ { "mov", FALSE, LONG, op2(Ilq, Ri), 0 },
+/*bc*/ { "mov", FALSE, LONG, op2(Ilq, Ri), 0 },
+/*bd*/ { "mov", FALSE, LONG, op2(Ilq, Ri), 0 },
+/*be*/ { "mov", FALSE, LONG, op2(Ilq, Ri), 0 },
+/*bf*/ { "mov", FALSE, LONG, op2(Ilq, Ri), 0 },
/*c0*/ { "", TRUE, BYTE, op2(Ib, E), db_Grp2 },
/*c1*/ { "", TRUE, LONG, op2(Ib, E), db_Grp2 },
@@ -854,17 +854,6 @@
int ss;
};
-static const char * const db_index_reg_16[8] = {
- "%bx,%si",
- "%bx,%di",
- "%bp,%si",
- "%bp,%di",
- "%si",
- "%di",
- "%bp",
- "%bx"
-};
-
static const char * const db_reg[2][4][16] = {
{{"%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh",
@@ -927,7 +916,7 @@
int regmodrm;
struct i_addr * addrp; /* out */
{
- int mod, rm, sib, index, disp;
+ int mod, rm, sib, index, disp, size, have_sib;
mod = f_mod(rex, regmodrm);
rm = f_rm(rex, regmodrm);
@@ -940,68 +929,49 @@
addrp->is_reg = FALSE;
addrp->index = 0;
- if (short_addr) {
- addrp->index = 0;
- addrp->ss = 0;
- switch (mod) {
- case 0:
- if (rm == 6) {
- get_value_inc(disp, loc, 2, FALSE);
- addrp->disp = disp;
- addrp->base = 0;
- }
- else {
- addrp->disp = 0;
- addrp->base = db_index_reg_16[rm];
- }
- break;
- case 1:
- get_value_inc(disp, loc, 1, TRUE);
- disp &= 0xFFFF;
- addrp->disp = disp;
- addrp->base = db_index_reg_16[rm];
- break;
- case 2:
- get_value_inc(disp, loc, 2, FALSE);
- addrp->disp = disp;
- addrp->base = db_index_reg_16[rm];
- break;
- }
- }
- else {
- if (mod != 3 && rm == 4) {
- get_value_inc(sib, loc, 1, FALSE);
- rm = sib_base(rex, sib);
- index = sib_index(rex, sib);
- if (index != 4)
- addrp->index = db_reg[1][QUAD][index];
- addrp->ss = sib_ss(rex, sib);
- }
+ if (short_addr)
+ size = LONG;
+ else
+ size = QUAD;
- switch (mod) {
- case 0:
- if (rm == 5) {
- get_value_inc(addrp->disp, loc, 4, FALSE);
+ if ((rm & 0x7) == 4) {
+ get_value_inc(sib, loc, 1, FALSE);
+ rm = sib_base(rex, sib);
+ index = sib_index(rex, sib);
+ if (index != 4)
+ addrp->index = db_reg[1][size][index];
+ addrp->ss = sib_ss(rex, sib);
+ have_sib = 1;
+ } else
+ have_sib = 0;
+
+ switch (mod) {
+ case 0:
+ if (rm == 5) {
+ get_value_inc(addrp->disp, loc, 4, FALSE);
+ if (have_sib)
addrp->base = 0;
- }
- else {
- addrp->disp = 0;
- addrp->base = db_reg[1][QUAD][rm];
- }
- break;
-
- case 1:
- get_value_inc(disp, loc, 1, TRUE);
- addrp->disp = disp;
- addrp->base = db_reg[1][QUAD][rm];
- break;
-
- case 2:
- get_value_inc(disp, loc, 4, FALSE);
- addrp->disp = disp;
- addrp->base = db_reg[1][QUAD][rm];
- break;
- }
+ else if (short_addr)
+ addrp->base = "%eip";
+ else
+ addrp->base = "%rip";
+ } else {
+ addrp->disp = 0;
+ addrp->base = db_reg[1][size][rm];
+ }
+ break;
+
+ case 1:
+ get_value_inc(disp, loc, 1, TRUE);
+ addrp->disp = disp;
+ addrp->base = db_reg[1][size][rm];
+ break;
+
+ case 2:
+ get_value_inc(disp, loc, 4, FALSE);
+ addrp->disp = disp;
+ addrp->base = db_reg[1][size][rm];
+ break;
}
return (loc);
}
@@ -1022,7 +992,8 @@
db_printf("%s:", seg);
}
- db_printsym((db_addr_t)addrp->disp, DB_STGY_ANY);
+ if (addrp->disp != 0 || (addrp->base == 0 && addrp->index == 0))
+ db_printsym((db_addr_t)addrp->disp, DB_STGY_ANY);
if (addrp->base != 0 || addrp->index != 0) {
db_printf("(");
if (addrp->base)
@@ -1154,6 +1125,7 @@
int prefix;
int imm;
int imm2;
+ long imm64;
int len;
struct i_addr address;
@@ -1426,6 +1398,12 @@
db_printf("$%#r", imm);
break;
+ case Ilq:
+ len = db_lengths[rex & REX_W ? QUAD : LONG];
+ get_value_inc(imm64, loc, len, FALSE);
+ db_printf("$%#lr", imm64);
+ break;
+
case O:
len = (short_addr ? 2 : 4);
get_value_inc(displ, loc, len, FALSE);
Index: db_trace.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/db_trace.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/amd64/amd64/db_trace.c -L sys/amd64/amd64/db_trace.c -u -r1.2 -r1.3
--- sys/amd64/amd64/db_trace.c
+++ sys/amd64/amd64/db_trace.c
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/db_trace.c,v 1.66.2.2 2006/03/13 03:03:51 jeff Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/db_trace.c,v 1.80.2.1 2007/11/21 16:38:54 jhb Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -91,6 +91,7 @@
{ "r15", DB_OFFSET(tf_r15), db_frame },
{ "rip", DB_OFFSET(tf_rip), db_frame },
{ "rflags", DB_OFFSET(tf_rflags), db_frame },
+#define DB_N_SHOW_REGS 20 /* Don't show registers after here. */
{ "dr0", NULL, db_dr0 },
{ "dr1", NULL, db_dr1 },
{ "dr2", NULL, db_dr2 },
@@ -100,7 +101,7 @@
{ "dr6", NULL, db_dr6 },
{ "dr7", NULL, db_dr7 },
};
-struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
+struct db_variable *db_eregs = db_regs + DB_N_SHOW_REGS;
#define DB_DRX_FUNC(reg) \
static int \
@@ -192,19 +193,17 @@
#define TRAP 1
#define INTERRUPT 2
#define SYSCALL 3
+#define TRAP_INTERRUPT 5
static void db_nextframe(struct amd64_frame **, db_addr_t *, struct thread *);
static int db_numargs(struct amd64_frame *);
static void db_print_stack_entry(const char *, int, char **, long *, db_addr_t);
static void decode_syscall(int, struct thread *);
-static char * watchtype_str(int type);
-int amd64_set_watch(int watchnum, unsigned int watchaddr, int size, int access,
- struct dbreg * d);
-int amd64_clr_watch(int watchnum, struct dbreg * d);
-int db_md_set_watchpoint(db_expr_t addr, db_expr_t size);
-int db_md_clr_watchpoint(db_expr_t addr, db_expr_t size);
-void db_md_list_watchpoints(void);
+static const char * watchtype_str(int type);
+int amd64_set_watch(int watchnum, unsigned long watchaddr, int size,
+ int access, struct dbreg *d);
+int amd64_clr_watch(int watchnum, struct dbreg *d);
/*
* Figure out how many arguments were passed into the frame at "fp".
@@ -318,14 +317,24 @@
if (name != NULL) {
if (strcmp(name, "calltrap") == 0 ||
strcmp(name, "fork_trampoline") == 0 ||
- strcmp(name, "nmi_calltrap") == 0)
+ strcmp(name, "nmi_calltrap") == 0 ||
+ strcmp(name, "Xdblfault") == 0)
frame_type = TRAP;
else if (strncmp(name, "Xatpic_intr", 11) == 0 ||
- strncmp(name, "Xatpic_fastintr", 15) == 0 ||
- strncmp(name, "Xapic_isr", 9) == 0)
+ strncmp(name, "Xapic_isr", 9) == 0 ||
+ strcmp(name, "Xtimerint") == 0 ||
+ strcmp(name, "Xipi_intr_bitmap_handler") == 0 ||
+ strcmp(name, "Xcpustop") == 0 ||
+ strcmp(name, "Xrendezvous") == 0)
frame_type = INTERRUPT;
else if (strcmp(name, "Xfast_syscall") == 0)
frame_type = SYSCALL;
+ /* XXX: These are interrupts with trap frames. */
+ else if (strcmp(name, "Xtimerint") == 0 ||
+ strcmp(name, "Xcpustop") == 0 ||
+ strcmp(name, "Xrendezvous") == 0 ||
+ strcmp(name, "Xipi_intr_bitmap_handler") == 0)
+ frame_type = TRAP_INTERRUPT;
}
/*
@@ -357,6 +366,7 @@
db_printf("--- syscall");
decode_syscall(tf->tf_rax, td);
break;
+ case TRAP_INTERRUPT:
case INTERRUPT:
db_printf("--- interrupt");
break;
@@ -382,16 +392,14 @@
long *argp;
db_expr_t offset;
c_db_sym_t sym;
- int narg, quit;
+ int narg;
boolean_t first;
if (count == -1)
count = 1024;
first = TRUE;
- quit = 0;
- db_setup_paging(db_simple_pager, &quit, db_lines_per_page);
- while (count-- && !quit) {
+ while (count-- && !db_pager_quit) {
sym = db_search_symbol(pc, DB_STGY_ANY, &offset);
db_symbol_values(sym, &name, NULL);
@@ -526,24 +534,23 @@
int
amd64_set_watch(watchnum, watchaddr, size, access, d)
int watchnum;
- unsigned int watchaddr;
+ unsigned long watchaddr;
int size;
int access;
- struct dbreg * d;
+ struct dbreg *d;
{
- int i;
- unsigned int mask;
-
+ int i, len;
+
if (watchnum == -1) {
- for (i = 0, mask = 0x3; i < 4; i++, mask <<= 2)
- if ((d->dr[7] & mask) == 0)
+ for (i = 0; i < 4; i++)
+ if (!DBREG_DR7_ENABLED(d->dr[7], i))
break;
if (i < 4)
watchnum = i;
else
return (-1);
}
-
+
switch (access) {
case DBREG_DR7_EXEC:
size = 1; /* size must be 1 for an execution breakpoint */
@@ -551,29 +558,39 @@
case DBREG_DR7_WRONLY:
case DBREG_DR7_RDWR:
break;
- default : return (-1);
+ default:
+ return (-1);
}
-
+
/*
- * we can watch a 1, 2, or 4 byte sized location
+ * we can watch a 1, 2, 4, or 8 byte sized location
*/
switch (size) {
- case 1 : mask = 0x00; break;
- case 2 : mask = 0x01 << 2; break;
- case 4 : mask = 0x03 << 2; break;
- default : return (-1);
+ case 1:
+ len = DBREG_DR7_LEN_1;
+ break;
+ case 2:
+ len = DBREG_DR7_LEN_2;
+ break;
+ case 4:
+ len = DBREG_DR7_LEN_4;
+ break;
+ case 8:
+ len = DBREG_DR7_LEN_8;
+ break;
+ default:
+ return (-1);
}
- mask |= access;
-
/* clear the bits we are about to affect */
- d->dr[7] &= ~((0x3 << (watchnum*2)) | (0x0f << (watchnum*4+16)));
+ d->dr[7] &= ~DBREG_DR7_MASK(watchnum);
/* set drN register to the address, N=watchnum */
- DBREG_DRX(d,watchnum) = watchaddr;
+ DBREG_DRX(d, watchnum) = watchaddr;
/* enable the watchpoint */
- d->dr[7] |= (0x2 << (watchnum*2)) | (mask << (watchnum*4+16));
+ d->dr[7] |= DBREG_DR7_SET(watchnum, len, access,
+ DBREG_DR7_GLOBAL_ENABLE);
return (watchnum);
}
@@ -582,15 +599,15 @@
int
amd64_clr_watch(watchnum, d)
int watchnum;
- struct dbreg * d;
+ struct dbreg *d;
{
if (watchnum < 0 || watchnum >= 4)
return (-1);
-
- d->dr[7] = d->dr[7] & ~((0x3 << (watchnum*2)) | (0x0f << (watchnum*4+16)));
- DBREG_DRX(d,watchnum) = 0;
-
+
+ d->dr[7] &= ~DBREG_DR7_MASK(watchnum);
+ DBREG_DRX(d, watchnum) = 0;
+
return (0);
}
@@ -600,38 +617,38 @@
db_expr_t addr;
db_expr_t size;
{
- int avail, wsize;
- int i;
struct dbreg d;
-
+ int avail, i, wsize;
+
fill_dbregs(NULL, &d);
-
+
avail = 0;
- for(i=0; i<4; i++) {
- if ((d.dr[7] & (3 << (i*2))) == 0)
+ for(i = 0; i < 4; i++) {
+ if (!DBREG_DR7_ENABLED(d.dr[7], i))
avail++;
}
-
- if (avail*4 < size)
+
+ if (avail * 8 < size)
return (-1);
-
- for (i=0; i<4 && (size != 0); i++) {
- if ((d.dr[7] & (3<<(i*2))) == 0) {
- if (size > 4)
+
+ for (i = 0; i < 4 && (size > 0); i++) {
+ if (!DBREG_DR7_ENABLED(d.dr[7], i)) {
+ if (size >= 8 || (avail == 1 && size > 4))
+ wsize = 8;
+ else if (size > 2)
wsize = 4;
else
wsize = size;
- if (wsize == 3)
- wsize++;
- amd64_set_watch(i, addr, wsize,
+ amd64_set_watch(i, addr, wsize,
DBREG_DR7_WRONLY, &d);
addr += wsize;
size -= wsize;
+ avail--;
}
}
-
+
set_dbregs(NULL, &d);
-
+
return(0);
}
@@ -641,28 +658,27 @@
db_expr_t addr;
db_expr_t size;
{
- int i;
struct dbreg d;
+ int i;
fill_dbregs(NULL, &d);
- for(i=0; i<4; i++) {
- if (d.dr[7] & (3 << (i*2))) {
- if ((DBREG_DRX((&d), i) >= addr) &&
+ for(i = 0; i < 4; i++) {
+ if (DBREG_DR7_ENABLED(d.dr[7], i)) {
+ if ((DBREG_DRX((&d), i) >= addr) &&
(DBREG_DRX((&d), i) < addr+size))
amd64_clr_watch(i, &d);
-
+
}
}
-
+
set_dbregs(NULL, &d);
-
+
return(0);
}
-static
-char *
+static const char *
watchtype_str(type)
int type;
{
@@ -678,30 +694,33 @@
void
db_md_list_watchpoints()
{
- int i;
struct dbreg d;
+ int i, len, type;
fill_dbregs(NULL, &d);
db_printf("\nhardware watchpoints:\n");
- db_printf(" watch status type len address\n");
- db_printf(" ----- -------- ---------- --- ----------\n");
- for (i=0; i<4; i++) {
- if (d.dr[7] & (0x03 << (i*2))) {
- unsigned type, len;
- type = (d.dr[7] >> (16+(i*4))) & 3;
- len = (d.dr[7] >> (16+(i*4)+2)) & 3;
- db_printf(" %-5d %-8s %10s %3d 0x%016lx\n",
- i, "enabled", watchtype_str(type),
- len + 1, DBREG_DRX((&d), i));
- }
- else {
+ db_printf(" watch status type len address\n");
+ db_printf(" ----- -------- ---------- --- ------------------\n");
+ for (i = 0; i < 4; i++) {
+ if (DBREG_DR7_ENABLED(d.dr[7], i)) {
+ type = DBREG_DR7_ACCESS(d.dr[7], i);
+ len = DBREG_DR7_LEN(d.dr[7], i);
+ if (len == DBREG_DR7_LEN_8)
+ len = 8;
+ else
+ len++;
+ db_printf(" %-5d %-8s %10s %3d ",
+ i, "enabled", watchtype_str(type), len);
+ db_printsym((db_addr_t)DBREG_DRX((&d), i), DB_STGY_ANY);
+ db_printf("\n");
+ } else {
db_printf(" %-5d disabled\n", i);
}
}
-
+
db_printf("\ndebug register values:\n");
- for (i=0; i<8; i++) {
+ for (i = 0; i < 8; i++) {
db_printf(" dr%d 0x%016lx\n", i, DBREG_DRX((&d), i));
}
db_printf("\n");
Index: mp_watchdog.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/mp_watchdog.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/amd64/mp_watchdog.c -L sys/amd64/amd64/mp_watchdog.c -u -r1.1.1.1 -r1.2
--- sys/amd64/amd64/mp_watchdog.c
+++ sys/amd64/amd64/mp_watchdog.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/amd64/amd64/mp_watchdog.c,v 1.4 2005/02/28 08:55:53 pjd Exp $
+ * $FreeBSD: src/sys/amd64/amd64/mp_watchdog.c,v 1.5 2007/06/04 23:56:33 jeff Exp $
*/
#include "opt_mp_watchdog.h"
@@ -105,9 +105,7 @@
* locks to make sure. Then reset the timer.
*/
mtx_lock(&Giant);
- mtx_lock_spin(&sched_lock);
watchdog_timer = WATCHDOG_THRESHOLD;
- mtx_unlock_spin(&sched_lock);
mtx_unlock(&Giant);
callout_reset(&watchdog_callout, 1 * hz, watchdog_function, NULL);
}
@@ -156,34 +154,6 @@
sysctl_watchdog, "I", "");
/*
- * A badly behaved sysctl that leaks the sched lock when written to. Then
- * spin holding it just to make matters worse. This can be used to test the
- * effectiveness of the watchdog by generating a fairly hard and nast hang.
- * Note that Giant is also held in the current world order when we get here.
- */
-static int
-sysctl_leak_schedlock(SYSCTL_HANDLER_ARGS)
-{
- int error, temp;
-
- temp = 0;
- error = sysctl_handle_int(oidp, &temp, 0, req);
- if (error)
- return (error);
-
- if (req->newptr != NULL) {
- if (temp) {
- printf("Leaking the sched lock...\n");
- mtx_lock_spin(&sched_lock);
- while (1);
- }
- }
- return (0);
-}
-SYSCTL_PROC(_debug, OID_AUTO, leak_schedlock, CTLTYPE_INT|CTLFLAG_RW, 0, 0,
- sysctl_leak_schedlock, "IU", "");
-
-/*
* Drop into the debugger by sending an IPI NMI to the boot processor.
*/
static void
Index: mp_machdep.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/mp_machdep.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/amd64/amd64/mp_machdep.c -L sys/amd64/amd64/mp_machdep.c -u -r1.2 -r1.3
--- sys/amd64/amd64/mp_machdep.c
+++ sys/amd64/amd64/mp_machdep.c
@@ -25,10 +25,9 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/mp_machdep.c,v 1.260.2.5.2.1 2006/04/28 06:54:33 cperciva Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/mp_machdep.c,v 1.287.2.2 2007/11/28 23:24:06 cperciva Exp $");
#include "opt_cpu.h"
-#include "opt_kdb.h"
#include "opt_kstack_pages.h"
#include "opt_mp_watchdog.h"
#include "opt_sched.h"
@@ -47,6 +46,7 @@
#include <sys/mutex.h>
#include <sys/pcpu.h>
#include <sys/proc.h>
+#include <sys/sched.h>
#include <sys/smp.h>
#include <sys/sysctl.h>
@@ -57,7 +57,6 @@
#include <vm/vm_extern.h>
#include <machine/apicreg.h>
-#include <machine/clock.h>
#include <machine/md_var.h>
#include <machine/mp_watchdog.h>
#include <machine/pcb.h>
@@ -82,6 +81,8 @@
int boot_cpu_id = -1; /* designated BSP */
extern int nkpt;
+extern struct pcpu __pcpu[];
+
/*
* CPU topology map datastructures for HTT.
*/
@@ -95,6 +96,9 @@
/* Free these after use */
void *bootstacks[MAXCPU];
+/* Temporary holder for double fault stack */
+char *doublefault_stack;
+
/* Hotwire a 0->4MB V==P mapping */
extern pt_entry_t *KPTphys;
@@ -110,10 +114,30 @@
extern inthand_t IDTVEC(fast_syscall), IDTVEC(fast_syscall32);
+#ifdef STOP_NMI
+volatile cpumask_t ipi_nmi_pending;
+
+static void ipi_nmi_selected(u_int32_t cpus);
+#endif
+
/*
* Local data and functions.
*/
+#ifdef STOP_NMI
+/*
+ * Provide an alternate method of stopping other CPUs. If another CPU has
+ * disabled interrupts the conventional STOP IPI will be blocked. This
+ * NMI-based stop should get through in that case.
+ */
+static int stop_cpus_with_nmi = 1;
+SYSCTL_INT(_debug, OID_AUTO, stop_cpus_with_nmi, CTLTYPE_INT | CTLFLAG_RW,
+ &stop_cpus_with_nmi, 0, "");
+TUNABLE_INT("debug.stop_cpus_with_nmi", &stop_cpus_with_nmi);
+#else
+#define stop_cpus_with_nmi 0
+#endif
+
static u_int logical_cpus;
/* used to hold the AP's until we are ready to release them */
@@ -130,14 +154,15 @@
int cpu_present:1;
int cpu_bsp:1;
int cpu_disabled:1;
-} static cpu_info[MAXCPU];
-static int cpu_apic_ids[MAXCPU];
+} static cpu_info[MAX_APIC_ID + 1];
+int cpu_apic_ids[MAXCPU];
/* Holds pending bitmap based IPIs per CPU */
static volatile u_int cpu_ipi_pending[MAXCPU];
static u_int boot_address;
+static void assign_cpu_ids(void);
static void set_interrupt_apic_ids(void);
static int start_all_aps(void);
static int start_ap(int apic_id);
@@ -146,7 +171,7 @@
static int hlt_logical_cpus;
static u_int hyperthreading_cpus;
static cpumask_t hyperthreading_cpus_mask;
-static int hyperthreading_allowed;
+static int hyperthreading_allowed = 1;
static struct sysctl_ctx_list logical_cpu_clist;
static u_int bootMP_size;
@@ -161,28 +186,25 @@
mp_topology(void)
{
struct cpu_group *group;
- int logical_cpus;
int apic_id;
int groups;
int cpu;
/* Build the smp_topology map. */
/* Nothing to do if there is no HTT support. */
- if ((cpu_feature & CPUID_HTT) == 0)
- return;
- logical_cpus = (cpu_procinfo & CPUID_HTT_CORES) >> 16;
- if (logical_cpus <= 1)
+ if (hyperthreading_cpus <= 1)
return;
group = &mp_groups[0];
groups = 1;
- for (cpu = 0, apic_id = 0; apic_id < MAXCPU; apic_id++) {
+ for (cpu = 0, apic_id = 0; apic_id <= MAX_APIC_ID; apic_id++) {
if (!cpu_info[apic_id].cpu_present)
continue;
/*
* If the current group has members and we're not a logical
* cpu, create a new group.
*/
- if (group->cg_count != 0 && (apic_id % logical_cpus) == 0) {
+ if (group->cg_count != 0 &&
+ (apic_id % hyperthreading_cpus) == 0) {
group++;
groups++;
}
@@ -196,11 +218,6 @@
smp_topology = &mp_top;
}
-
-#ifdef KDB_STOP_NMI
-volatile cpumask_t ipi_nmi_pending;
-#endif
-
/*
* Calculate usable address in base memory for AP trampoline code.
*/
@@ -222,9 +239,8 @@
cpu_add(u_int apic_id, char boot_cpu)
{
- if (apic_id >= MAXCPU) {
- printf("SMP: CPU %d exceeds maximum CPU %d, ignoring\n",
- apic_id, MAXCPU - 1);
+ if (apic_id > MAX_APIC_ID) {
+ panic("SMP: APIC ID %d too high", apic_id);
return;
}
KASSERT(cpu_info[apic_id].cpu_present == 0, ("CPU %d added twice",
@@ -237,13 +253,13 @@
boot_cpu_id = apic_id;
cpu_info[apic_id].cpu_bsp = 1;
}
- mp_ncpus++;
- if (apic_id > mp_maxid)
- mp_maxid = apic_id;
+ if (mp_ncpus < MAXCPU) {
+ mp_ncpus++;
+ mp_maxid = mp_ncpus -1;
+ }
if (bootverbose)
printf("SMP: Added CPU %d (%s)\n", apic_id, boot_cpu ? "BSP" :
"AP");
-
}
void
@@ -262,8 +278,7 @@
else
KASSERT(mp_maxid >= mp_ncpus - 1,
("%s: counters out of sync: max %d, count %d", __func__,
- mp_maxid, mp_ncpus));
-
+ mp_maxid, mp_ncpus));
}
int
@@ -318,7 +333,10 @@
setidt(IPI_INVLTLB, IDTVEC(invltlb), SDT_SYSIGT, SEL_KPL, 0);
setidt(IPI_INVLPG, IDTVEC(invlpg), SDT_SYSIGT, SEL_KPL, 0);
setidt(IPI_INVLRNG, IDTVEC(invlrng), SDT_SYSIGT, SEL_KPL, 0);
-
+
+ /* Install an inter-CPU IPI for cache invalidation. */
+ setidt(IPI_INVLCACHE, IDTVEC(invlcache), SDT_SYSIGT, SEL_KPL, 0);
+
/* Install an inter-CPU IPI for all-CPU rendezvous */
setidt(IPI_RENDEZVOUS, IDTVEC(rendezvous), SDT_SYSIGT, SEL_KPL, 0);
@@ -338,6 +356,8 @@
("BSP's APIC ID doesn't match boot_cpu_id"));
cpu_apic_ids[0] = boot_cpu_id;
+ assign_cpu_ids();
+
/* Start each Application Processor */
start_all_aps();
@@ -389,6 +409,9 @@
}
set_interrupt_apic_ids();
+
+ /* Last, setup the cpu topology now that we have probed CPUs */
+ mp_topology();
}
@@ -402,7 +425,7 @@
/* List CPUs */
printf(" cpu0 (BSP): APIC ID: %2d\n", boot_cpu_id);
- for (i = 1, x = 0; x < MAXCPU; x++) {
+ for (i = 1, x = 0; x <= MAX_APIC_ID; x++) {
if (!cpu_info[x].cpu_present || cpu_info[x].cpu_bsp)
continue;
if (cpu_info[x].cpu_disabled)
@@ -432,6 +455,7 @@
common_tss[cpu] = common_tss[0];
common_tss[cpu].tss_rsp0 = 0; /* not used until after switch */
common_tss[cpu].tss_iobase = sizeof(struct amd64tss);
+ common_tss[cpu].tss_ist1 = (long)&doublefault_stack[PAGE_SIZE];
gdt_segs[GPROC0_SEL].ssd_base = (long) &common_tss[cpu];
ssdtosyssd(&gdt_segs[GPROC0_SEL],
@@ -488,6 +512,9 @@
while (!aps_ready)
ia32_pause();
+ /* Initialize the PAT MSR. */
+ pmap_init_pat();
+
/* set up CPU registers and state */
cpu_setregs();
@@ -512,7 +539,7 @@
mtx_lock_spin(&ap_boot_mtx);
/* Init local apic for irq's */
- lapic_setup();
+ lapic_setup(1);
/* Set memory range attributes for this CPU to match the BSP */
mem_range_AP_init();
@@ -556,25 +583,7 @@
while (smp_started == 0)
ia32_pause();
- /* ok, now grab sched_lock and enter the scheduler */
- mtx_lock_spin(&sched_lock);
-
- /*
- * Correct spinlock nesting. The idle thread context that we are
- * borrowing was created so that it would start out with a single
- * spin lock (sched_lock) held in fork_trampoline(). Since we've
- * explicitly acquired locks in this function, the nesting count
- * is now 2 rather than 1. Since we are nested, calling
- * spinlock_exit() will simply adjust the counts without allowing
- * spin lock using code to interrupt us.
- */
- spinlock_exit();
- KASSERT(curthread->td_md.md_spinlock_count == 1, ("invalid count"));
-
- binuptime(PCPU_PTR(switchtime));
- PCPU_SET(switchticks, ticks);
-
- cpu_throw(NULL, choosethread()); /* doesn't return */
+ sched_throw(NULL);
panic("scheduler returned us to %s", __func__);
/* NOTREACHED */
@@ -594,24 +603,69 @@
static void
set_interrupt_apic_ids(void)
{
- u_int apic_id;
+ u_int i, apic_id;
- for (apic_id = 0; apic_id < MAXCPU; apic_id++) {
- if (!cpu_info[apic_id].cpu_present)
+ for (i = 0; i < MAXCPU; i++) {
+ apic_id = cpu_apic_ids[i];
+ if (apic_id == -1)
continue;
if (cpu_info[apic_id].cpu_bsp)
continue;
+ if (cpu_info[apic_id].cpu_disabled)
+ continue;
/* Don't let hyperthreads service interrupts. */
if (hyperthreading_cpus > 1 &&
apic_id % hyperthreading_cpus != 0)
continue;
- intr_add_cpu(apic_id);
+ intr_add_cpu(i);
}
}
/*
+ * Assign logical CPU IDs to local APICs.
+ */
+static void
+assign_cpu_ids(void)
+{
+ u_int i;
+
+ /* Check for explicitly disabled CPUs. */
+ for (i = 0; i <= MAX_APIC_ID; i++) {
+ if (!cpu_info[i].cpu_present || cpu_info[i].cpu_bsp)
+ continue;
+
+ /* Don't use this CPU if it has been disabled by a tunable. */
+ if (resource_disabled("lapic", i)) {
+ cpu_info[i].cpu_disabled = 1;
+ continue;
+ }
+ }
+
+ /*
+ * Assign CPU IDs to local APIC IDs and disable any CPUs
+ * beyond MAXCPU. CPU 0 has already been assigned to the BSP,
+ * so we only have to assign IDs for APs.
+ */
+ mp_ncpus = 1;
+ for (i = 0; i <= MAX_APIC_ID; i++) {
+ if (!cpu_info[i].cpu_present || cpu_info[i].cpu_bsp ||
+ cpu_info[i].cpu_disabled)
+ continue;
+
+ if (mp_ncpus < MAXCPU) {
+ cpu_apic_ids[mp_ncpus] = i;
+ mp_ncpus++;
+ } else
+ cpu_info[i].cpu_disabled = 1;
+ }
+ KASSERT(mp_maxid >= mp_ncpus - 1,
+ ("%s: counters out of sync: max %d, count %d", __func__, mp_maxid,
+ mp_ncpus));
+}
+
+/*
* start each AP in our list
*/
static int
@@ -662,27 +716,12 @@
outb(CMOS_DATA, BIOS_WARM); /* 'warm-start' */
/* start each AP */
- for (cpu = 0, apic_id = 0; apic_id < MAXCPU; apic_id++) {
-
- /* Ignore non-existent CPUs and the BSP. */
- if (!cpu_info[apic_id].cpu_present ||
- cpu_info[apic_id].cpu_bsp)
- continue;
-
- /* Don't use this CPU if it has been disabled by a tunable. */
- if (resource_disabled("lapic", apic_id)) {
- cpu_info[apic_id].cpu_disabled = 1;
- mp_ncpus--;
- continue;
- }
-
- cpu++;
-
- /* save APIC ID for this logical ID */
- cpu_apic_ids[cpu] = apic_id;
+ for (cpu = 1; cpu < mp_ncpus; cpu++) {
+ apic_id = cpu_apic_ids[cpu];
/* allocate and set up an idle stack data page */
- bootstacks[cpu] = (char *)kmem_alloc(kernel_map, KSTACK_PAGES * PAGE_SIZE);
+ bootstacks[cpu] = (void *)kmem_alloc(kernel_map, KSTACK_PAGES * PAGE_SIZE);
+ doublefault_stack = (char *)kmem_alloc(kernel_map, PAGE_SIZE);
bootSTK = (char *)bootstacks[cpu] + KSTACK_PAGES * PAGE_SIZE - 8;
bootAP = cpu;
@@ -801,13 +840,16 @@
ncpu = mp_ncpus - 1; /* does not shootdown self */
if (ncpu < 1)
return; /* no other cpus */
- mtx_assert(&smp_ipi_mtx, MA_OWNED);
+ if (!(read_rflags() & PSL_I))
+ panic("%s: interrupts disabled", __func__);
+ mtx_lock_spin(&smp_ipi_mtx);
smp_tlb_addr1 = addr1;
smp_tlb_addr2 = addr2;
atomic_store_rel_int(&smp_tlb_wait, 0);
ipi_all_but_self(vector);
while (smp_tlb_wait < ncpu)
ia32_pause();
+ mtx_unlock_spin(&smp_ipi_mtx);
}
static void
@@ -835,7 +877,9 @@
if (ncpu < 1)
return;
}
- mtx_assert(&smp_ipi_mtx, MA_OWNED);
+ if (!(read_rflags() & PSL_I))
+ panic("%s: interrupts disabled", __func__);
+ mtx_lock_spin(&smp_ipi_mtx);
smp_tlb_addr1 = addr1;
smp_tlb_addr2 = addr2;
atomic_store_rel_int(&smp_tlb_wait, 0);
@@ -845,6 +889,15 @@
ipi_selected(mask, vector);
while (smp_tlb_wait < ncpu)
ia32_pause();
+ mtx_unlock_spin(&smp_ipi_mtx);
+}
+
+void
+smp_cache_flush(void)
+{
+
+ if (smp_started)
+ smp_tlb_shootdown(IPI_INVLCACHE, 0, 0);
}
void
@@ -900,29 +953,23 @@
}
}
-
void
-ipi_bitmap_handler(struct clockframe frame)
+ipi_bitmap_handler(struct trapframe frame)
{
int cpu = PCPU_GET(cpuid);
u_int ipi_bitmap;
ipi_bitmap = atomic_readandclear_int(&cpu_ipi_pending[cpu]);
-#ifdef IPI_PREEMPTION
- if (ipi_bitmap & IPI_PREEMPT) {
- mtx_lock_spin(&sched_lock);
- /* Don't preempt the idle thread */
- if (curthread->td_priority < PRI_MIN_IDLE) {
- struct thread *running_thread = curthread;
- if (running_thread->td_critnest > 1)
- running_thread->td_owepreempt = 1;
- else
- mi_switch(SW_INVOL | SW_PREEMPT, NULL);
- }
- mtx_unlock_spin(&sched_lock);
+ if (ipi_bitmap & (1 << IPI_PREEMPT)) {
+ struct thread *running_thread = curthread;
+ thread_lock(running_thread);
+ if (running_thread->td_critnest > 1)
+ running_thread->td_owepreempt = 1;
+ else
+ mi_switch(SW_INVOL | SW_PREEMPT, NULL);
+ thread_unlock(running_thread);
}
-#endif
/* Nothing to do for AST */
}
@@ -943,6 +990,12 @@
ipi = IPI_BITMAP_VECTOR;
}
+#ifdef STOP_NMI
+ if (ipi == IPI_STOP && stop_cpus_with_nmi) {
+ ipi_nmi_selected(cpus);
+ return;
+ }
+#endif
CTR3(KTR_SMP, "%s: cpus: %x ipi: %x", __func__, cpus, ipi);
while ((cpu = ffs(cpus)) != 0) {
cpu--;
@@ -973,6 +1026,10 @@
ipi_all(u_int ipi)
{
+ if (IPI_IS_BITMAPED(ipi) || (ipi == IPI_STOP && stop_cpus_with_nmi)) {
+ ipi_selected(all_cpus, ipi);
+ return;
+ }
CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
lapic_ipi_vectored(ipi, APIC_IPI_DEST_ALL);
}
@@ -984,6 +1041,10 @@
ipi_all_but_self(u_int ipi)
{
+ if (IPI_IS_BITMAPED(ipi) || (ipi == IPI_STOP && stop_cpus_with_nmi)) {
+ ipi_selected(PCPU_GET(other_cpus), ipi);
+ return;
+ }
CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
lapic_ipi_vectored(ipi, APIC_IPI_DEST_OTHERS);
}
@@ -995,11 +1056,15 @@
ipi_self(u_int ipi)
{
+ if (IPI_IS_BITMAPED(ipi) || (ipi == IPI_STOP && stop_cpus_with_nmi)) {
+ ipi_selected(PCPU_GET(cpumask), ipi);
+ return;
+ }
CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
lapic_ipi_vectored(ipi, APIC_IPI_DEST_SELF);
}
-#ifdef KDB_STOP_NMI
+#ifdef STOP_NMI
/*
* send NMI IPI to selected CPUs
*/
@@ -1009,7 +1074,6 @@
void
ipi_nmi_selected(u_int32_t cpus)
{
-
int cpu;
register_t icrlo;
@@ -1018,10 +1082,8 @@
CTR2(KTR_SMP, "%s: cpus: %x nmi", __func__, cpus);
-
atomic_set_int(&ipi_nmi_pending, cpus);
-
while ((cpu = ffs(cpus)) != 0) {
cpu--;
cpus &= ~(1 << cpu);
@@ -1033,41 +1095,52 @@
if (!lapic_ipi_wait(BEFORE_SPIN))
panic("ipi_nmi_selected: previous IPI has not cleared");
- lapic_ipi_raw(icrlo,cpu_apic_ids[cpu]);
+ lapic_ipi_raw(icrlo, cpu_apic_ids[cpu]);
}
}
-
int
-ipi_nmi_handler()
+ipi_nmi_handler(void)
{
- int cpu = PCPU_GET(cpuid);
+ int cpumask = PCPU_GET(cpumask);
- if(!(atomic_load_acq_int(&ipi_nmi_pending) & (1 << cpu)))
+ if (!(ipi_nmi_pending & cpumask))
return 1;
- atomic_clear_int(&ipi_nmi_pending,1 << cpu);
+ atomic_clear_int(&ipi_nmi_pending, cpumask);
+ cpustop_handler();
+ return 0;
+}
+
+#endif /* STOP_NMI */
+
+/*
+ * Handle an IPI_STOP by saving our current context and spinning until we
+ * are resumed.
+ */
+void
+cpustop_handler(void)
+{
+ int cpu = PCPU_GET(cpuid);
+ int cpumask = PCPU_GET(cpumask);
savectx(&stoppcbs[cpu]);
/* Indicate that we are stopped */
- atomic_set_int(&stopped_cpus,1 << cpu);
-
+ atomic_set_int(&stopped_cpus, cpumask);
/* Wait for restart */
- while(!(atomic_load_acq_int(&started_cpus) & (1 << cpu)))
+ while (!(started_cpus & cpumask))
ia32_pause();
- atomic_clear_int(&started_cpus,1 << cpu);
- atomic_clear_int(&stopped_cpus,1 << cpu);
+ atomic_clear_int(&started_cpus, cpumask);
+ atomic_clear_int(&stopped_cpus, cpumask);
- if(cpu == 0 && cpustop_restartfunc != NULL)
+ if (cpu == 0 && cpustop_restartfunc != NULL) {
cpustop_restartfunc();
-
- return 0;
+ cpustop_restartfunc = NULL;
+ }
}
-
-#endif /* KDB_STOP_NMI */
/*
* This is called once the rest of the system is up and running and we're
@@ -1079,11 +1152,9 @@
if (mp_ncpus == 1)
return;
- mtx_lock_spin(&sched_lock);
atomic_store_rel_int(&aps_ready, 1);
while (smp_started == 0)
ia32_pause();
- mtx_unlock_spin(&sched_lock);
}
SYSINIT(start_aps, SI_SUB_SMP, SI_ORDER_FIRST, release_aps, NULL);
Index: io_apic.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/io_apic.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/amd64/amd64/io_apic.c -L sys/amd64/amd64/io_apic.c -u -r1.2 -r1.3
--- sys/amd64/amd64/io_apic.c
+++ sys/amd64/amd64/io_apic.c
@@ -28,20 +28,23 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/io_apic.c,v 1.15.2.4 2006/03/07 18:33:20 jhb Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/io_apic.c,v 1.31 2007/06/05 18:57:48 jhb Exp $");
-#include "opt_atpic.h"
#include "opt_isa.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
-#include <sys/malloc.h>
#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/sysctl.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
#include <vm/vm.h>
#include <vm/pmap.h>
@@ -49,6 +52,7 @@
#include <machine/frame.h>
#include <machine/intr_machdep.h>
#include <machine/apicvar.h>
+#include <machine/resource.h>
#include <machine/segments.h>
#define IOAPIC_ISA_INTS 16
@@ -61,9 +65,7 @@
#define IRQ_SMI (NUM_IO_INTS + 3)
#define IRQ_DISABLED (NUM_IO_INTS + 4)
-#define TODO printf("%s: not implemented!\n", __func__)
-
-static MALLOC_DEFINE(M_IOAPIC, "I/O APIC", "I/O APIC structures");
+static MALLOC_DEFINE(M_IOAPIC, "io_apic", "I/O APIC structures");
/*
* I/O APIC interrupt source driver. Each pin is assigned an IRQ cookie
@@ -73,6 +75,10 @@
* IRQs behave as PCI IRQs by default. We also assume that the pin for
* IRQ 0 is actually an ExtINT pin. The apic enumerators override the
* configuration of individual pins as indicated by their tables.
+ *
+ * Documentation for the I/O APIC: "82093AA I/O Advanced Programmable
+ * Interrupt Controller (IOAPIC)", May 1996, Intel Corp.
+ * ftp://download.intel.com/design/chipsets/datashts/29056601.pdf
*/
struct ioapic_intsrc {
@@ -85,6 +91,7 @@
u_int io_edgetrigger:1;
u_int io_masked:1;
int io_bus:4;
+ uint32_t io_lowreg;
};
struct ioapic {
@@ -94,6 +101,7 @@
u_int io_intbase:8; /* System Interrupt base */
u_int io_numintr:8;
volatile ioapic_t *io_addr; /* XXX: should use bus_space */
+ vm_paddr_t io_paddr;
STAILQ_ENTRY(ioapic) io_next;
struct ioapic_intsrc io_pins[0];
};
@@ -106,20 +114,20 @@
static void ioapic_disable_source(struct intsrc *isrc, int eoi);
static void ioapic_eoi_source(struct intsrc *isrc);
static void ioapic_enable_intr(struct intsrc *isrc);
+static void ioapic_disable_intr(struct intsrc *isrc);
static int ioapic_vector(struct intsrc *isrc);
static int ioapic_source_pending(struct intsrc *isrc);
static int ioapic_config_intr(struct intsrc *isrc, enum intr_trigger trig,
enum intr_polarity pol);
-static void ioapic_suspend(struct intsrc *isrc);
-static void ioapic_resume(struct intsrc *isrc);
+static void ioapic_resume(struct pic *pic);
static void ioapic_assign_cpu(struct intsrc *isrc, u_int apic_id);
static void ioapic_program_intpin(struct ioapic_intsrc *intpin);
static STAILQ_HEAD(,ioapic) ioapic_list = STAILQ_HEAD_INITIALIZER(ioapic_list);
struct pic ioapic_template = { ioapic_enable_source, ioapic_disable_source,
ioapic_eoi_source, ioapic_enable_intr,
- ioapic_vector, ioapic_source_pending,
- ioapic_suspend, ioapic_resume,
+ ioapic_disable_intr, ioapic_vector,
+ ioapic_source_pending, NULL, ioapic_resume,
ioapic_config_intr, ioapic_assign_cpu };
static int next_ioapic_base;
@@ -203,9 +211,7 @@
mtx_lock_spin(&icu_lock);
if (intpin->io_masked) {
- flags = ioapic_read(io->io_addr,
- IOAPIC_REDTBL_LO(intpin->io_intpin));
- flags &= ~(IOART_INTMASK);
+ flags = intpin->io_lowreg & ~IOART_INTMASK;
ioapic_write(io->io_addr, IOAPIC_REDTBL_LO(intpin->io_intpin),
flags);
intpin->io_masked = 0;
@@ -222,9 +228,7 @@
mtx_lock_spin(&icu_lock);
if (!intpin->io_masked && !intpin->io_edgetrigger) {
- flags = ioapic_read(io->io_addr,
- IOAPIC_REDTBL_LO(intpin->io_intpin));
- flags |= IOART_INTMSET;
+ flags = intpin->io_lowreg | IOART_INTMSET;
ioapic_write(io->io_addr, IOAPIC_REDTBL_LO(intpin->io_intpin),
flags);
intpin->io_masked = 1;
@@ -309,6 +313,7 @@
/* Write the values to the APIC. */
mtx_lock_spin(&icu_lock);
+ intpin->io_lowreg = low;
ioapic_write(io->io_addr, IOAPIC_REDTBL_LO(intpin->io_intpin), low);
value = ioapic_read(io->io_addr, IOAPIC_REDTBL_HI(intpin->io_intpin));
value &= ~IOART_DEST;
@@ -355,6 +360,23 @@
}
}
+static void
+ioapic_disable_intr(struct intsrc *isrc)
+{
+ struct ioapic_intsrc *intpin = (struct ioapic_intsrc *)isrc;
+ u_int vector;
+
+ if (intpin->io_vector != 0) {
+ /* Mask this interrupt pin and free its APIC vector. */
+ vector = intpin->io_vector;
+ apic_disable_vector(vector);
+ intpin->io_masked = 1;
+ intpin->io_vector = 0;
+ ioapic_program_intpin(intpin);
+ apic_free_vector(vector, intpin->io_irq);
+ }
+}
+
static int
ioapic_vector(struct intsrc *isrc)
{
@@ -417,24 +439,20 @@
}
static void
-ioapic_suspend(struct intsrc *isrc)
-{
-
- TODO;
-}
-
-static void
-ioapic_resume(struct intsrc *isrc)
+ioapic_resume(struct pic *pic)
{
+ struct ioapic *io = (struct ioapic *)pic;
+ int i;
- ioapic_program_intpin((struct ioapic_intsrc *)isrc);
+ for (i = 0; i < io->io_numintr; i++)
+ ioapic_program_intpin(&io->io_pins[i]);
}
/*
* Create a plain I/O APIC object.
*/
void *
-ioapic_create(uintptr_t addr, int32_t apic_id, int intbase)
+ioapic_create(vm_paddr_t addr, int32_t apic_id, int intbase)
{
struct ioapic *io;
struct ioapic_intsrc *intpin;
@@ -443,7 +461,7 @@
uint32_t value;
/* Map the register window so we can access the device. */
- apic = (ioapic_t *)pmap_mapdev(addr, IOAPIC_MEM_REGION);
+ apic = pmap_mapdev(addr, IOAPIC_MEM_REGION);
mtx_lock_spin(&icu_lock);
value = ioapic_read(apic, IOAPIC_VER);
mtx_unlock_spin(&icu_lock);
@@ -474,13 +492,14 @@
intbase = next_ioapic_base;
printf("ioapic%u: Assuming intbase of %d\n", io->io_id,
intbase);
- } else if (intbase != next_ioapic_base)
+ } else if (intbase != next_ioapic_base && bootverbose)
printf("ioapic%u: WARNING: intbase %d != expected base %d\n",
io->io_id, intbase, next_ioapic_base);
io->io_intbase = intbase;
next_ioapic_base = intbase + numintr;
io->io_numintr = numintr;
io->io_addr = apic;
+ io->io_paddr = addr;
/*
* Initialize pins. Start off with interrupts disabled. Default
@@ -518,13 +537,6 @@
* be routed to other CPUs later after they are enabled.
*/
intpin->io_cpu = PCPU_GET(apic_id);
- if (bootverbose && intpin->io_irq != IRQ_DISABLED) {
- printf("ioapic%u: intpin %d -> ", io->io_id, i);
- ioapic_print_irq(intpin);
- printf(" (%s, %s)\n", intpin->io_edgetrigger ?
- "edge" : "level", intpin->io_activehi ? "high" :
- "low");
- }
value = ioapic_read(apic, IOAPIC_REDTBL_LO(i));
ioapic_write(apic, IOAPIC_REDTBL_LO(i), value | IOART_INTMSET);
}
@@ -589,6 +601,8 @@
return (EINVAL);
if (io->io_pins[pin].io_irq >= NUM_IO_INTS)
return (EINVAL);
+ if (io->io_pins[pin].io_bus == bus_type)
+ return (0);
io->io_pins[pin].io_bus = bus_type;
if (bootverbose)
printf("ioapic%u: intpin %d bus %s\n", io->io_id, pin,
@@ -672,13 +686,17 @@
ioapic_set_polarity(void *cookie, u_int pin, enum intr_polarity pol)
{
struct ioapic *io;
+ int activehi;
io = (struct ioapic *)cookie;
if (pin >= io->io_numintr || pol == INTR_POLARITY_CONFORM)
return (EINVAL);
if (io->io_pins[pin].io_irq >= NUM_IO_INTS)
return (EINVAL);
- io->io_pins[pin].io_activehi = (pol == INTR_POLARITY_HIGH);
+ activehi = (pol == INTR_POLARITY_HIGH);
+ if (io->io_pins[pin].io_activehi == activehi)
+ return (0);
+ io->io_pins[pin].io_activehi = activehi;
if (bootverbose)
printf("ioapic%u: intpin %d polarity: %s\n", io->io_id, pin,
pol == INTR_POLARITY_HIGH ? "high" : "low");
@@ -689,13 +707,17 @@
ioapic_set_triggermode(void *cookie, u_int pin, enum intr_trigger trigger)
{
struct ioapic *io;
+ int edgetrigger;
io = (struct ioapic *)cookie;
if (pin >= io->io_numintr || trigger == INTR_TRIGGER_CONFORM)
return (EINVAL);
if (io->io_pins[pin].io_irq >= NUM_IO_INTS)
- return (EINVAL);
- io->io_pins[pin].io_edgetrigger = (trigger == INTR_TRIGGER_EDGE);
+ return (EINVAL);
+ edgetrigger = (trigger == INTR_TRIGGER_EDGE);
+ if (io->io_pins[pin].io_edgetrigger == edgetrigger)
+ return (0);
+ io->io_pins[pin].io_edgetrigger = edgetrigger;
if (bootverbose)
printf("ioapic%u: intpin %d trigger: %s\n", io->io_id, pin,
trigger == INTR_TRIGGER_EDGE ? "edge" : "level");
@@ -725,7 +747,121 @@
io->io_intbase + io->io_numintr - 1);
/* Register valid pins as interrupt sources. */
+ intr_register_pic(&io->io_pic);
for (i = 0, pin = io->io_pins; i < io->io_numintr; i++, pin++)
if (pin->io_irq < NUM_IO_INTS)
intr_register_source(&pin->io_intsrc);
}
+
+/* A simple new-bus driver to consume PCI I/O APIC devices. */
+static int
+ioapic_pci_probe(device_t dev)
+{
+
+ if (pci_get_class(dev) == PCIC_BASEPERIPH &&
+ pci_get_subclass(dev) == PCIS_BASEPERIPH_PIC) {
+ switch (pci_get_progif(dev)) {
+ case PCIP_BASEPERIPH_PIC_IO_APIC:
+ device_set_desc(dev, "IO APIC");
+ break;
+ case PCIP_BASEPERIPH_PIC_IOX_APIC:
+ device_set_desc(dev, "IO(x) APIC");
+ break;
+ default:
+ return (ENXIO);
+ }
+ device_quiet(dev);
+ return (-10000);
+ }
+ return (ENXIO);
+}
+
+static int
+ioapic_pci_attach(device_t dev)
+{
+
+ return (0);
+}
+
+static device_method_t ioapic_pci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ioapic_pci_probe),
+ DEVMETHOD(device_attach, ioapic_pci_attach),
+
+ { 0, 0 }
+};
+
+DEFINE_CLASS_0(ioapic, ioapic_pci_driver, ioapic_pci_methods, 0);
+
+static devclass_t ioapic_devclass;
+DRIVER_MODULE(ioapic, pci, ioapic_pci_driver, ioapic_devclass, 0, 0);
+
+/*
+ * A new-bus driver to consume the memory resources associated with
+ * the APICs in the system. On some systems ACPI or PnPBIOS system
+ * resource devices may already claim these resources. To keep from
+ * breaking those devices, we attach ourself to the nexus device after
+ * legacy0 and acpi0 and ignore any allocation failures.
+ */
+static void
+apic_identify(driver_t *driver, device_t parent)
+{
+
+ /*
+ * Add at order 12. acpi0 is probed at order 10 and legacy0
+ * is probed at order 11.
+ */
+ if (lapic_paddr != 0)
+ BUS_ADD_CHILD(parent, 12, "apic", 0);
+}
+
+static int
+apic_probe(device_t dev)
+{
+
+ device_set_desc(dev, "APIC resources");
+ device_quiet(dev);
+ return (0);
+}
+
+static void
+apic_add_resource(device_t dev, int rid, vm_paddr_t base, size_t length)
+{
+ int error;
+
+ error = bus_set_resource(dev, SYS_RES_MEMORY, rid, base, length);
+ if (error)
+ panic("apic_add_resource: resource %d failed set with %d", rid,
+ error);
+ bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 0);
+}
+
+static int
+apic_attach(device_t dev)
+{
+ struct ioapic *io;
+ int i;
+
+ /* Reserve the local APIC. */
+ apic_add_resource(dev, 0, lapic_paddr, sizeof(lapic_t));
+ i = 1;
+ STAILQ_FOREACH(io, &ioapic_list, io_next) {
+ apic_add_resource(dev, i, io->io_paddr, IOAPIC_MEM_REGION);
+ i++;
+ }
+ return (0);
+}
+
+static device_method_t apic_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_identify, apic_identify),
+ DEVMETHOD(device_probe, apic_probe),
+ DEVMETHOD(device_attach, apic_attach),
+
+ { 0, 0 }
+};
+
+DEFINE_CLASS_0(apic, apic_driver, apic_methods, 0);
+
+static devclass_t apic_devclass;
+DRIVER_MODULE(apic, nexus, apic_driver, apic_devclass, 0, 0);
Index: cpu_switch.S
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/cpu_switch.S,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/amd64/cpu_switch.S -L sys/amd64/amd64/cpu_switch.S -u -r1.1.1.1 -r1.2
--- sys/amd64/amd64/cpu_switch.S
+++ sys/amd64/amd64/cpu_switch.S
@@ -30,13 +30,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/amd64/amd64/cpu_switch.S,v 1.151.8.2 2005/11/15 00:25:59 peter Exp $
+ * $FreeBSD: src/sys/amd64/amd64/cpu_switch.S,v 1.160 2007/08/22 05:06:14 jkoshy Exp $
*/
#include <machine/asmacros.h>
#include <machine/specialreg.h>
#include "assym.s"
+#include "opt_sched.h"
/*****************************************************************************/
/* Scheduling */
@@ -50,6 +51,12 @@
#define LK
#endif
+#if defined(SCHED_ULE) && defined(SMP)
+#define SETLK xchgq
+#else
+#define SETLK movq
+#endif
+
/*
* cpu_throw()
*
@@ -73,19 +80,17 @@
movq TD_PCB(%rsi),%rdx /* newtd->td_proc */
movq PCB_CR3(%rdx),%rdx
movq %rdx,%cr3 /* new address space */
- /* set bit in new pm_active */
- movq TD_PROC(%rsi),%rdx
- movq P_VMSPACE(%rdx), %rdx
- LK btsl %eax, VM_PMAP+PM_ACTIVE(%rdx) /* set new */
- jmp sw1
+ jmp swact
+END(cpu_throw)
/*
- * cpu_switch(old, new)
+ * cpu_switch(old, new, mtx)
*
* Save the current thread state, then select the next thread to run
* and load its state.
* %rdi = oldtd
* %rsi = newtd
+ * %rdx = mtx
*/
ENTRY(cpu_switch)
/* Switch to new thread. First, save context. */
@@ -104,11 +109,12 @@
testl $PCB_32BIT,PCB_FLAGS(%r8)
jz 1f /* no, skip over */
- /* Save segment selector numbers */
- movl %ds,PCB_DS(%r8)
- movl %es,PCB_ES(%r8)
- movl %fs,PCB_FS(%r8)
+ /* Save userland %gs */
movl %gs,PCB_GS(%r8)
+ movq PCB_GS32P(%r8),%rax
+ movq (%rax),%rax
+ movq %rax,PCB_GS32SD(%r8)
+
1:
/* Test if debug registers should be saved. */
testl $PCB_DBREGS,PCB_FLAGS(%r8)
@@ -138,7 +144,7 @@
smsw %ax
orb $CR0_TS,%al
lmsw %ax
- xorq %rax,%rax
+ xorl %eax,%eax
movq %rax,PCPU(FPCURTHREAD)
1:
@@ -146,46 +152,43 @@
movq TD_PCB(%rsi),%r8
/* switch address space */
- movq PCB_CR3(%r8),%rdx
+ movq PCB_CR3(%r8),%rcx
movq %cr3,%rax
- cmpq %rdx,%rax /* Same address space? */
- je sw1
- movq %rdx,%cr3 /* new address space */
-
+ cmpq %rcx,%rax /* Same address space? */
+ jne swinact
+ SETLK %rdx, TD_LOCK(%rdi) /* Release the old thread */
+ jmp sw1
+swinact:
+ movq %rcx,%cr3 /* new address space */
movl PCPU(CPUID), %eax
/* Release bit from old pmap->pm_active */
- movq TD_PROC(%rdi), %rdx /* oldproc */
- movq P_VMSPACE(%rdx), %rdx
- LK btrl %eax, VM_PMAP+PM_ACTIVE(%rdx) /* clear old */
-
+ movq TD_PROC(%rdi), %rcx /* oldproc */
+ movq P_VMSPACE(%rcx), %rcx
+ LK btrl %eax, VM_PMAP+PM_ACTIVE(%rcx) /* clear old */
+ SETLK %rdx, TD_LOCK(%rdi) /* Release the old thread */
+swact:
/* Set bit in new pmap->pm_active */
movq TD_PROC(%rsi),%rdx /* newproc */
movq P_VMSPACE(%rdx), %rdx
LK btsl %eax, VM_PMAP+PM_ACTIVE(%rdx) /* set new */
sw1:
+#if defined(SCHED_ULE) && defined(SMP)
+ /* Wait for the new thread to become unblocked */
+ movq $blocked_lock, %rdx
+1:
+ movq TD_LOCK(%rsi),%rcx
+ cmpq %rcx, %rdx
+ pause
+ je 1b
+ lfence
+#endif
/*
* At this point, we've switched address spaces and are ready
* to load up the rest of the next context.
*/
movq TD_PCB(%rsi),%r8
- testl $PCB_32BIT,PCB_FLAGS(%r8)
- jz 1f /* no, skip over */
-
- /* Restore segment selector numbers */
- movl PCB_DS(%r8),%ds
- movl PCB_ES(%r8),%es
- movl PCB_FS(%r8),%fs
-
- /* Restore userland %gs while preserving kernel gsbase */
- movl $MSR_GSBASE,%ecx
- rdmsr
- movl PCB_GS(%r8),%gs
- wrmsr
- jmp 2f
-1:
-
/* Restore userland %fs */
movl $MSR_FSBASE,%ecx
movl PCB_FSBASE(%r8),%eax
@@ -197,7 +200,6 @@
movl PCB_GSBASE(%r8),%eax
movl PCB_GSBASE+4(%r8),%edx
wrmsr
-2:
/* Update the TSS_RSP0 pointer for the next interrupt */
movq PCPU(TSSP), %rax
@@ -206,6 +208,22 @@
movq %rbx, (%rax)
movq %rbx, PCPU(RSP0)
+ movq %r8, PCPU(CURPCB)
+ movq %rsi, PCPU(CURTHREAD) /* into next thread */
+
+ testl $PCB_32BIT,PCB_FLAGS(%r8)
+ jz 1f /* no, skip over */
+
+ /* Restore userland %gs while preserving kernel gsbase */
+ movq PCB_GS32P(%r8),%rax
+ movq PCB_GS32SD(%r8),%rbx
+ movq %rbx,(%rax)
+ movl $MSR_GSBASE,%ecx
+ rdmsr
+ movl PCB_GS(%r8),%gs
+ wrmsr
+
+1:
/* Restore context. */
movq PCB_RBX(%r8),%rbx
movq PCB_RSP(%r8),%rsp
@@ -217,9 +235,6 @@
movq PCB_RIP(%r8),%rax
movq %rax,(%rsp)
- movq %r8, PCPU(CURPCB)
- movq %rsi, PCPU(CURTHREAD) /* into next thread */
-
/* Test if debug registers should be restored. */
testl $PCB_DBREGS,PCB_FLAGS(%r8)
jz 1f
@@ -242,7 +257,8 @@
movq %rax,%dr7
1:
ret
-
+END(cpu_switch)
+
/*
* savectx(pcb)
* Update pcb, saving current processor state.
@@ -300,3 +316,4 @@
popfq
ret
+END(savectx)
Index: trap.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/trap.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/amd64/trap.c -L sys/amd64/amd64/trap.c -u -r1.1.1.1 -r1.2
--- sys/amd64/amd64/trap.c
+++ sys/amd64/amd64/trap.c
@@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/trap.c,v 1.289.2.3 2005/11/28 20:03:03 jhb Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/trap.c,v 1.319.2.2 2007/12/06 14:20:25 kib Exp $");
/*
* AMD64 Trap and System call handling
@@ -75,6 +75,7 @@
#ifdef HWPMC_HOOKS
#include <sys/pmckern.h>
#endif
+#include <security/audit/audit.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
@@ -93,12 +94,12 @@
#endif
#include <machine/tss.h>
-extern void trap(struct trapframe frame);
-extern void syscall(struct trapframe frame);
+extern void trap(struct trapframe *frame);
+extern void syscall(struct trapframe *frame);
+void dblfault_handler(struct trapframe *frame);
static int trap_pfault(struct trapframe *, int);
static void trap_fatal(struct trapframe *, vm_offset_t);
-void dblfault_handler(void);
#define MAX_TRAP_MSG 30
static char *trap_msg[] = {
@@ -143,10 +144,11 @@
static int panic_on_nmi = 1;
SYSCTL_INT(_machdep, OID_AUTO, panic_on_nmi, CTLFLAG_RW,
&panic_on_nmi, 0, "Panic on NMI");
+static int prot_fault_translation = 0;
+SYSCTL_INT(_machdep, OID_AUTO, prot_fault_translation, CTLFLAG_RW,
+ &prot_fault_translation, 0, "Select signal to deliver on protection fault");
-#ifdef WITNESS
extern char *syscallnames[];
-#endif
/*
* Exception, fault, and trap interface to the FreeBSD kernel.
@@ -156,24 +158,27 @@
*/
void
-trap(frame)
- struct trapframe frame;
+trap(struct trapframe *frame)
{
struct thread *td = curthread;
struct proc *p = td->td_proc;
- u_int sticks = 0;
- int i = 0, ucode = 0, type, code;
+ int i = 0, ucode = 0, code;
+ u_int type;
+ register_t addr = 0;
+ ksiginfo_t ksi;
- PCPU_LAZY_INC(cnt.v_trap);
- type = frame.tf_trapno;
+ PCPU_INC(cnt.v_trap);
+ type = frame->tf_trapno;
-#ifdef KDB_STOP_NMI
- /* Handler for NMI IPIs used for debugging */
+#ifdef SMP
+#ifdef STOP_NMI
+ /* Handler for NMI IPIs used for stopping CPUs. */
if (type == T_NMI) {
if (ipi_nmi_handler() == 0)
goto out;
}
-#endif /* KDB_STOP_NMI */
+#endif /* STOP_NMI */
+#endif /* SMP */
#ifdef KDB
if (kdb_active) {
@@ -190,12 +195,12 @@
* the NMI was handled by it and we can return immediately.
*/
if (type == T_NMI && pmc_intr &&
- (*pmc_intr)(PCPU_GET(cpuid), (uintptr_t) frame.tf_rip,
- TRAPF_USERMODE(&frame)))
+ (*pmc_intr)(PCPU_GET(cpuid), (uintptr_t) frame->tf_rip,
+ TRAPF_USERMODE(frame)))
goto out;
#endif
- if ((frame.tf_rflags & PSL_I) == 0) {
+ if ((frame->tf_rflags & PSL_I) == 0) {
/*
* Buggy application or kernel code has disabled
* interrupts and then trapped. Enabling interrupts
@@ -203,7 +208,7 @@
* interrupts disabled until they are accidentally
* enabled later.
*/
- if (ISPL(frame.tf_cs) == SEL_UPL)
+ if (ISPL(frame->tf_cs) == SEL_UPL)
printf(
"pid %ld (%s): trap %d with interrupts disabled\n",
(long)curproc->p_pid, curproc->p_comm, type);
@@ -216,15 +221,15 @@
printf("kernel trap %d with interrupts disabled\n",
type);
/*
- * We shouldn't enable interrupts while in a critical
- * section.
+ * We shouldn't enable interrupts while holding a
+ * spin lock or servicing an NMI.
*/
- if (td->td_critnest == 0)
+ if (type != T_NMI && td->td_md.md_spinlock_count == 0)
enable_intr();
}
}
- code = frame.tf_err;
+ code = frame->tf_err;
if (type == T_PAGEFLT) {
/*
* If we get a page fault while in a critical section, then
@@ -233,30 +238,40 @@
* do the VM lookup, so just consider it a fatal trap so the
* kernel can print out a useful trap message and even get
* to the debugger.
+ *
+ * If we get a page fault while holding a non-sleepable
+ * lock, then it is most likely a fatal kernel page fault.
+ * If WITNESS is enabled, then it's going to whine about
+ * bogus LORs with various VM locks, so just skip to the
+ * fatal trap handling directly.
*/
- if (td->td_critnest != 0)
- trap_fatal(&frame, frame.tf_addr);
+ if (td->td_critnest != 0 ||
+ WITNESS_CHECK(WARN_SLEEPOK | WARN_GIANTOK, NULL,
+ "Kernel page fault") != 0)
+ trap_fatal(frame, frame->tf_addr);
}
- if (ISPL(frame.tf_cs) == SEL_UPL) {
+ if (ISPL(frame->tf_cs) == SEL_UPL) {
/* user trap */
- sticks = td->td_sticks;
- td->td_frame = &frame;
+ td->td_pticks = 0;
+ td->td_frame = frame;
+ addr = frame->tf_rip;
if (td->td_ucred != p->p_ucred)
cred_update_thread(td);
switch (type) {
case T_PRIVINFLT: /* privileged instruction fault */
- ucode = type;
i = SIGILL;
+ ucode = ILL_PRVOPC;
break;
case T_BPTFLT: /* bpt instruction fault */
case T_TRCTRAP: /* trace trap */
enable_intr();
- frame.tf_rflags &= ~PSL_T;
+ frame->tf_rflags &= ~PSL_T;
i = SIGTRAP;
+ ucode = (type == T_TRCTRAP ? TRAP_TRACE : TRAP_BRKPT);
break;
case T_ARITHTRAP: /* arithmetic trap */
@@ -267,25 +282,66 @@
break;
case T_PROTFLT: /* general protection fault */
+ i = SIGBUS;
+ ucode = BUS_OBJERR;
+ break;
case T_STKFLT: /* stack fault */
case T_SEGNPFLT: /* segment not present fault */
+ i = SIGBUS;
+ ucode = BUS_ADRERR;
+ break;
case T_TSSFLT: /* invalid TSS fault */
+ i = SIGBUS;
+ ucode = BUS_OBJERR;
+ break;
case T_DOUBLEFLT: /* double fault */
default:
- ucode = code + BUS_SEGM_FAULT ;
i = SIGBUS;
+ ucode = BUS_OBJERR;
break;
case T_PAGEFLT: /* page fault */
+ addr = frame->tf_addr;
+#ifdef KSE
if (td->td_pflags & TDP_SA)
thread_user_enter(td);
- i = trap_pfault(&frame, TRUE);
+#endif
+ i = trap_pfault(frame, TRUE);
if (i == -1)
goto userout;
if (i == 0)
goto user;
- ucode = T_PAGEFLT;
+ if (i == SIGSEGV)
+ ucode = SEGV_MAPERR;
+ else {
+ if (prot_fault_translation == 0) {
+ /*
+ * Autodetect.
+ * This check also covers the images
+ * without the ABI-tag ELF note.
+ */
+ if (p->p_osrel >= 700004) {
+ i = SIGSEGV;
+ ucode = SEGV_ACCERR;
+ } else {
+ i = SIGBUS;
+ ucode = BUS_PAGE_FAULT;
+ }
+ } else if (prot_fault_translation == 1) {
+ /*
+ * Always compat mode.
+ */
+ i = SIGBUS;
+ ucode = BUS_PAGE_FAULT;
+ } else {
+ /*
+ * Always SIGSEGV mode.
+ */
+ i = SIGSEGV;
+ ucode = SEGV_ACCERR;
+ }
+ }
break;
case T_DIVIDE: /* integer divide fault */
@@ -305,7 +361,7 @@
*/
if (kdb_on_nmi) {
printf ("NMI ... going to debugger\n");
- kdb_trap(type, 0, &frame);
+ kdb_trap(type, 0, frame);
}
#endif /* KDB */
goto userout;
@@ -328,12 +384,14 @@
/* transparent fault (due to context switch "late") */
if (fpudna())
goto userout;
- i = SIGFPE;
- ucode = FPE_FPU_NP_TRAP;
+ printf("pid %d killed due to lack of floating point\n",
+ p->p_pid);
+ i = SIGKILL;
+ ucode = 0;
break;
case T_FPOPFLT: /* FPU operand fetch fault */
- ucode = T_FPOPFLT;
+ ucode = ILL_COPROC;
i = SIGILL;
break;
@@ -349,7 +407,7 @@
("kernel trap doesn't have ucred"));
switch (type) {
case T_PAGEFLT: /* page fault */
- (void) trap_pfault(&frame, FALSE);
+ (void) trap_pfault(frame, FALSE);
goto out;
case T_DNA:
@@ -382,12 +440,12 @@
* selectors and pointers when the user changes
* them.
*/
- if (frame.tf_rip == (long)doreti_iret) {
- frame.tf_rip = (long)doreti_iret_fault;
+ if (frame->tf_rip == (long)doreti_iret) {
+ frame->tf_rip = (long)doreti_iret_fault;
goto out;
}
if (PCPU_GET(curpcb)->pcb_onfault != NULL) {
- frame.tf_rip =
+ frame->tf_rip =
(long)PCPU_GET(curpcb)->pcb_onfault;
goto out;
}
@@ -403,8 +461,8 @@
* problem here and not every time the kernel is
* entered.
*/
- if (frame.tf_rflags & PSL_NT) {
- frame.tf_rflags &= ~PSL_NT;
+ if (frame->tf_rflags & PSL_NT) {
+ frame->tf_rflags &= ~PSL_NT;
goto out;
}
break;
@@ -438,8 +496,7 @@
* Otherwise, debugger traps "can't happen".
*/
#ifdef KDB
- /* XXX Giant */
- if (kdb_trap(type, 0, &frame))
+ if (kdb_trap(type, 0, frame))
goto out;
#endif
break;
@@ -456,7 +513,7 @@
*/
if (kdb_on_nmi) {
printf ("NMI ... going to debugger\n");
- kdb_trap(type, 0, &frame);
+ kdb_trap(type, 0, frame);
}
#endif /* KDB */
goto out;
@@ -466,7 +523,7 @@
#endif /* DEV_ISA */
}
- trap_fatal(&frame, 0);
+ trap_fatal(frame, 0);
goto out;
}
@@ -474,20 +531,25 @@
if (*p->p_sysent->sv_transtrap)
i = (*p->p_sysent->sv_transtrap)(i, type);
- trapsignal(td, i, ucode);
+ ksiginfo_init_trap(&ksi);
+ ksi.ksi_signo = i;
+ ksi.ksi_code = ucode;
+ ksi.ksi_trapno = type;
+ ksi.ksi_addr = (void *)addr;
+ trapsignal(td, &ksi);
#ifdef DEBUG
if (type <= MAX_TRAP_MSG) {
uprintf("fatal process exception: %s",
trap_msg[type]);
if ((type == T_PAGEFLT) || (type == T_PROTFLT))
- uprintf(", fault VA = 0x%lx", frame.tf_addr);
+ uprintf(", fault VA = 0x%lx", frame->tf_addr);
uprintf("\n");
}
#endif
user:
- userret(td, &frame, sticks);
+ userret(td, frame);
mtx_assert(&Giant, MA_NOTOWNED);
userout:
out:
@@ -501,7 +563,7 @@
{
vm_offset_t va;
struct vmspace *vm = NULL;
- vm_map_t map = 0;
+ vm_map_t map;
int rv = 0;
vm_prot_t ftype;
struct thread *td = curthread;
@@ -532,8 +594,14 @@
map = &vm->vm_map;
}
+ /*
+ * PGEX_I is defined only if the execute disable bit capability is
+ * supported and enabled.
+ */
if (frame->tf_err & PGEX_W)
ftype = VM_PROT_WRITE;
+ else if ((frame->tf_err & PGEX_I) && pg_nx != 0)
+ ftype = VM_PROT_EXECUTE;
else
ftype = VM_PROT_READ;
@@ -582,7 +650,8 @@
struct trapframe *frame;
vm_offset_t eva;
{
- int code, type, ss;
+ int code, ss;
+ u_int type;
long esp;
struct soft_segment_descriptor softseg;
char *msg;
@@ -604,9 +673,10 @@
#endif
if (type == T_PAGEFLT) {
printf("fault virtual address = 0x%lx\n", eva);
- printf("fault code = %s %s, %s\n",
+ printf("fault code = %s %s %s, %s\n",
code & PGEX_U ? "user" : "supervisor",
code & PGEX_W ? "write" : "read",
+ code & PGEX_I ? "instruction" : "data",
code & PGEX_P ? "protection violation" : "page not present");
}
printf("instruction pointer = 0x%lx:0x%lx\n",
@@ -645,15 +715,9 @@
}
#ifdef KDB
- if (debugger_on_panic || kdb_active) {
- register_t rflags;
- rflags = intr_disable();
- if (kdb_trap(type, 0, frame)) {
- intr_restore(rflags);
+ if (debugger_on_panic || kdb_active)
+ if (kdb_trap(type, 0, frame))
return;
- }
- intr_restore(rflags);
- }
#endif
printf("trap number = %d\n", type);
if (type <= MAX_TRAP_MSG)
@@ -669,9 +733,12 @@
* for example).
*/
void
-dblfault_handler()
+dblfault_handler(struct trapframe *frame)
{
printf("\nFatal double fault\n");
+ printf("rip = 0x%lx\n", frame->tf_rip);
+ printf("rsp = 0x%lx\n", frame->tf_rsp);
+ printf("rbp = 0x%lx\n", frame->tf_rbp);
#ifdef SMP
/* two separate prints in case of a trap on an unmapped page */
printf("cpuid = %d; ", PCPU_GET(cpuid));
@@ -686,57 +753,52 @@
* A system call is essentially treated as a trap.
*/
void
-syscall(frame)
- struct trapframe frame;
+syscall(struct trapframe *frame)
{
caddr_t params;
struct sysent *callp;
struct thread *td = curthread;
struct proc *p = td->td_proc;
register_t orig_tf_rflags;
- u_int sticks;
int error;
int narg;
register_t args[8];
register_t *argp;
u_int code;
int reg, regcnt;
+ ksiginfo_t ksi;
- /*
- * note: PCPU_LAZY_INC() can only be used if we can afford
- * occassional inaccuracy in the count.
- */
- PCPU_LAZY_INC(cnt.v_syscall);
+ PCPU_INC(cnt.v_syscall);
#ifdef DIAGNOSTIC
- if (ISPL(frame.tf_cs) != SEL_UPL) {
- mtx_lock(&Giant); /* try to stabilize the system XXX */
+ if (ISPL(frame->tf_cs) != SEL_UPL) {
panic("syscall");
/* NOT REACHED */
- mtx_unlock(&Giant);
}
#endif
reg = 0;
regcnt = 6;
- sticks = td->td_sticks;
- td->td_frame = &frame;
+ td->td_pticks = 0;
+ td->td_frame = frame;
if (td->td_ucred != p->p_ucred)
cred_update_thread(td);
+#ifdef KSE
if (p->p_flag & P_SA)
thread_user_enter(td);
- params = (caddr_t)frame.tf_rsp + sizeof(register_t);
- code = frame.tf_rax;
- orig_tf_rflags = frame.tf_rflags;
+#endif
+ params = (caddr_t)frame->tf_rsp + sizeof(register_t);
+ code = frame->tf_rax;
+ orig_tf_rflags = frame->tf_rflags;
if (p->p_sysent->sv_prepsyscall) {
/*
* The prep code is MP aware.
*/
- (*p->p_sysent->sv_prepsyscall)(&frame, (int *)args, &code, ¶ms);
+ (*p->p_sysent->sv_prepsyscall)(frame, (int *)args, &code, ¶ms);
} else {
if (code == SYS_syscall || code == SYS___syscall) {
- code = frame.tf_rdi;
+ code = frame->tf_rdi;
reg++;
regcnt--;
}
@@ -750,7 +812,7 @@
else
callp = &p->p_sysent->sv_table[code];
- narg = callp->sy_narg & SYF_ARGMASK;
+ narg = callp->sy_narg;
/*
* copyin and the ktrsyscall()/ktrsysret() code is MP-aware
@@ -758,7 +820,7 @@
KASSERT(narg <= sizeof(args) / sizeof(args[0]),
("Too many syscall arguments!"));
error = 0;
- argp = &frame.tf_rdi;
+ argp = &frame->tf_rdi;
argp += reg;
bcopy(argp, args, sizeof(args[0]) * regcnt);
if (narg > regcnt) {
@@ -776,27 +838,26 @@
CTR4(KTR_SYSC, "syscall enter thread %p pid %d proc %s code %d", td,
td->td_proc->p_pid, td->td_proc->p_comm, code);
+ td->td_syscalls++;
+
if (error == 0) {
td->td_retval[0] = 0;
- td->td_retval[1] = frame.tf_rdx;
+ td->td_retval[1] = frame->tf_rdx;
STOPEVENT(p, S_SCE, narg);
PTRACESTOP_SC(p, td, S_PT_SCE);
- if ((callp->sy_narg & SYF_MPSAFE) == 0) {
- mtx_lock(&Giant);
- error = (*callp->sy_call)(td, argp);
- mtx_unlock(&Giant);
- } else
- error = (*callp->sy_call)(td, argp);
+ AUDIT_SYSCALL_ENTER(code, td);
+ error = (*callp->sy_call)(td, argp);
+ AUDIT_SYSCALL_EXIT(error, td);
}
switch (error) {
case 0:
- frame.tf_rax = td->td_retval[0];
- frame.tf_rdx = td->td_retval[1];
- frame.tf_rflags &= ~PSL_C;
+ frame->tf_rax = td->td_retval[0];
+ frame->tf_rdx = td->td_retval[1];
+ frame->tf_rflags &= ~PSL_C;
break;
case ERESTART:
@@ -806,8 +867,8 @@
* (which was holding the value of %rcx) is restored for
* the next iteration.
*/
- frame.tf_rip -= frame.tf_err;
- frame.tf_r10 = frame.tf_rcx;
+ frame->tf_rip -= frame->tf_err;
+ frame->tf_r10 = frame->tf_rcx;
td->td_pcb->pcb_flags |= PCB_FULLCTX;
break;
@@ -821,8 +882,8 @@
else
error = p->p_sysent->sv_errtbl[error];
}
- frame.tf_rax = error;
- frame.tf_rflags |= PSL_C;
+ frame->tf_rax = error;
+ frame->tf_rflags |= PSL_C;
break;
}
@@ -830,14 +891,31 @@
* Traced syscall.
*/
if (orig_tf_rflags & PSL_T) {
- frame.tf_rflags &= ~PSL_T;
- trapsignal(td, SIGTRAP, 0);
+ frame->tf_rflags &= ~PSL_T;
+ ksiginfo_init_trap(&ksi);
+ ksi.ksi_signo = SIGTRAP;
+ ksi.ksi_code = TRAP_TRACE;
+ ksi.ksi_addr = (void *)frame->tf_rip;
+ trapsignal(td, &ksi);
}
/*
+ * Check for misbehavior.
+ */
+ WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
+ (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???");
+ KASSERT(td->td_critnest == 0,
+ ("System call %s returning in a critical section",
+ (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"));
+ KASSERT(td->td_locks == 0,
+ ("System call %s returning with %d locks held",
+ (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???",
+ td->td_locks));
+
+ /*
* Handle reschedule and other end-of-syscall issues
*/
- userret(td, &frame, sticks);
+ userret(td, frame);
CTR4(KTR_SYSC, "syscall exit thread %p pid %d proc %s code %d", td,
td->td_proc->p_pid, td->td_proc->p_comm, code);
@@ -855,9 +933,4 @@
STOPEVENT(p, S_SCX, code);
PTRACESTOP_SC(p, td, S_PT_SCX);
-
- WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
- (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???");
- mtx_assert(&sched_lock, MA_NOTOWNED);
- mtx_assert(&Giant, MA_NOTOWNED);
}
Index: apic_vector.S
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/apic_vector.S,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/amd64/apic_vector.S -L sys/amd64/amd64/apic_vector.S -u -r1.1.1.1 -r1.2
--- sys/amd64/amd64/apic_vector.S
+++ sys/amd64/amd64/apic_vector.S
@@ -28,7 +28,7 @@
* SUCH DAMAGE.
*
* from: vector.s, 386BSD 0.1 unknown origin
- * $FreeBSD: src/sys/amd64/amd64/apic_vector.S,v 1.103 2005/06/30 05:33:26 peter Exp $
+ * $FreeBSD: src/sys/amd64/amd64/apic_vector.S,v 1.110 2006/12/17 06:48:39 kmacy Exp $
*/
/*
@@ -42,53 +42,6 @@
#include "assym.s"
/*
- * Macros to create and destroy a trap frame.
- */
-#define PUSH_FRAME \
- subq $TF_RIP,%rsp ; /* skip dummy tf_err and tf_trapno */ \
- testb $SEL_RPL_MASK,TF_CS(%rsp) ; /* come from kernel? */ \
- jz 1f ; /* Yes, dont swapgs again */ \
- swapgs ; \
-1: movq %rdi,TF_RDI(%rsp) ; \
- movq %rsi,TF_RSI(%rsp) ; \
- movq %rdx,TF_RDX(%rsp) ; \
- movq %rcx,TF_RCX(%rsp) ; \
- movq %r8,TF_R8(%rsp) ; \
- movq %r9,TF_R9(%rsp) ; \
- movq %rax,TF_RAX(%rsp) ; \
- movq %rbx,TF_RBX(%rsp) ; \
- movq %rbp,TF_RBP(%rsp) ; \
- movq %r10,TF_R10(%rsp) ; \
- movq %r11,TF_R11(%rsp) ; \
- movq %r12,TF_R12(%rsp) ; \
- movq %r13,TF_R13(%rsp) ; \
- movq %r14,TF_R14(%rsp) ; \
- movq %r15,TF_R15(%rsp)
-
-#define POP_FRAME \
- movq TF_RDI(%rsp),%rdi ; \
- movq TF_RSI(%rsp),%rsi ; \
- movq TF_RDX(%rsp),%rdx ; \
- movq TF_RCX(%rsp),%rcx ; \
- movq TF_R8(%rsp),%r8 ; \
- movq TF_R9(%rsp),%r9 ; \
- movq TF_RAX(%rsp),%rax ; \
- movq TF_RBX(%rsp),%rbx ; \
- movq TF_RBP(%rsp),%rbp ; \
- movq TF_R10(%rsp),%r10 ; \
- movq TF_R11(%rsp),%r11 ; \
- movq TF_R12(%rsp),%r12 ; \
- movq TF_R13(%rsp),%r13 ; \
- movq TF_R14(%rsp),%r14 ; \
- movq TF_R15(%rsp),%r15 ; \
- testb $SEL_RPL_MASK,TF_CS(%rsp) ; /* come from kernel? */ \
- jz 1f ; /* keep kernel GS.base */ \
- cli ; \
- swapgs ; \
-1: addq $TF_RIP,%rsp /* skip over tf_err, tf_trapno */
-
-
-/*
* I/O Interrupt Entry Point. Rather than having one entry point for
* each interrupt source, we use one entry point for each 32-bit word
* in the ISR. The handler determines the highest bit set in the ISR,
@@ -107,7 +60,8 @@
jz 2f ; \
addl $(32 * index),%eax ; \
1: ; \
- movq %rax, %rdi ; /* pass the IRQ */ \
+ movq %rsp, %rsi ; \
+ movl %eax, %edi ; /* pass the IRQ */ \
call lapic_handle_intr ; \
MEXITCOUNT ; \
jmp doreti ; \
@@ -144,12 +98,8 @@
SUPERALIGN_TEXT
IDTVEC(timerint)
PUSH_FRAME
-
- movq lapic, %rdx
- movl $0, LA_EOI(%rdx) /* End Of Interrupt to APIC */
-
FAKE_MCOUNT(TF_RIP(%rsp))
-
+ movq %rsp, %rdi
call lapic_handle_timer
MEXITCOUNT
jmp doreti
@@ -222,51 +172,43 @@
iretq
/*
- * Forward hardclock to another CPU. Pushes a clockframe and calls
- * forwarded_hardclock().
+ * Invalidate cache.
*/
.text
SUPERALIGN_TEXT
-IDTVEC(ipi_intr_bitmap_handler)
-
- PUSH_FRAME
+IDTVEC(invlcache)
+ pushq %rax
- movq lapic, %rdx
- movl $0, LA_EOI(%rdx) /* End Of Interrupt to APIC */
-
- FAKE_MCOUNT(TF_RIP(%rsp))
+ wbinvd
- call ipi_bitmap_handler
- MEXITCOUNT
- jmp doreti
+ movq lapic, %rax
+ movl $0, LA_EOI(%rax) /* End Of Interrupt to APIC */
+
+ lock
+ incl smp_tlb_wait
+
+ popq %rax
+ iretq
/*
- * Executed by a CPU when it receives an Xcpuast IPI from another CPU,
- *
- * The other CPU has already executed aston() or need_resched() on our
- * current process, so we simply need to ack the interrupt and return
- * via doreti to run ast().
+ * Handler for IPIs sent via the per-cpu IPI bitmap.
*/
-
.text
SUPERALIGN_TEXT
-IDTVEC(cpuast)
+IDTVEC(ipi_intr_bitmap_handler)
PUSH_FRAME
movq lapic, %rdx
movl $0, LA_EOI(%rdx) /* End Of Interrupt to APIC */
-
+
FAKE_MCOUNT(TF_RIP(%rsp))
+ call ipi_bitmap_handler
MEXITCOUNT
jmp doreti
/*
- * Executed by a CPU when it receives an Xcpustop IPI from another CPU,
- *
- * - Signals its receipt.
- * - Waits for permission to restart.
- * - Signals its restart.
+ * Executed by a CPU when it receives an IPI_STOP from another CPU.
*/
.text
SUPERALIGN_TEXT
@@ -276,34 +218,8 @@
movq lapic, %rax
movl $0, LA_EOI(%rax) /* End Of Interrupt to APIC */
- movl PCPU(CPUID), %eax
- imull $PCB_SIZE, %eax
- leaq stoppcbs(%rax), %rdi
- call savectx /* Save process context */
-
- movl PCPU(CPUID), %eax
-
- lock
- btsl %eax, stopped_cpus /* stopped_cpus |= (1<<id) */
-1:
- btl %eax, started_cpus /* while (!(started_cpus & (1<<id))) */
- jnc 1b
-
- lock
- btrl %eax, started_cpus /* started_cpus &= ~(1<<id) */
- lock
- btrl %eax, stopped_cpus /* stopped_cpus &= ~(1<<id) */
-
- test %eax, %eax
- jnz 2f
-
- movq cpustop_restartfunc, %rax
- testq %rax, %rax
- jz 2f
- movq $0, cpustop_restartfunc /* One-shot */
+ call cpustop_handler
- call *%rax
-2:
POP_FRAME
iretq
Index: elf_machdep.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/elf_machdep.c,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -L sys/amd64/amd64/elf_machdep.c -L sys/amd64/amd64/elf_machdep.c -u -r1.1.1.2 -r1.2
--- sys/amd64/amd64/elf_machdep.c
+++ sys/amd64/amd64/elf_machdep.c
@@ -24,7 +24,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/elf_machdep.c,v 1.22.8.1 2005/12/30 22:13:57 marcel Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/elf_machdep.c,v 1.26 2007/05/22 02:22:57 kan Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@@ -82,6 +82,7 @@
"/libexec/ld-elf.so.1",
&elf64_freebsd_sysvec,
NULL,
+ BI_CAN_EXEC_DYN,
};
SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_ANY,
@@ -96,6 +97,7 @@
"/usr/libexec/ld-elf.so.1",
&elf64_freebsd_sysvec,
NULL,
+ BI_CAN_EXEC_DYN,
};
SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
@@ -195,6 +197,7 @@
break;
case R_X86_64_GLOB_DAT: /* S */
+ case R_X86_64_JMP_SLOT: /* XXX need addend + offset */
addr = lookup(lf, symidx, 1);
if (addr == 0)
return -1;
Index: gdb_machdep.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/gdb_machdep.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/amd64/gdb_machdep.c -L sys/amd64/amd64/gdb_machdep.c -u -r1.1.1.1 -r1.2
--- sys/amd64/amd64/gdb_machdep.c
+++ sys/amd64/amd64/gdb_machdep.c
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/gdb_machdep.c,v 1.4.2.1 2005/11/15 00:25:59 peter Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/gdb_machdep.c,v 1.6 2006/04/04 03:00:20 marcel Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -91,3 +91,27 @@
kdb_frame->tf_rip = *(register_t *)val;
}
}
+
+int
+gdb_cpu_signal(int type, int code)
+{
+
+ switch (type & ~T_USER) {
+ case 0: return (SIGFPE); /* Divide by zero. */
+ case 1: return (SIGTRAP); /* Debug exception. */
+ case 3: return (SIGTRAP); /* Breakpoint. */
+ case 4: return (SIGSEGV); /* into instr. (overflow). */
+ case 5: return (SIGURG); /* bound instruction. */
+ case 6: return (SIGILL); /* Invalid opcode. */
+ case 7: return (SIGFPE); /* Coprocessor not present. */
+ case 8: return (SIGEMT); /* Double fault. */
+ case 9: return (SIGSEGV); /* Coprocessor segment overrun. */
+ case 10: return (SIGTRAP); /* Invalid TSS (also single-step). */
+ case 11: return (SIGSEGV); /* Segment not present. */
+ case 12: return (SIGSEGV); /* Stack exception. */
+ case 13: return (SIGSEGV); /* General protection. */
+ case 14: return (SIGSEGV); /* Page fault. */
+ case 16: return (SIGEMT); /* Coprocessor error. */
+ }
+ return (SIGEMT);
+}
Index: busdma_machdep.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/busdma_machdep.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/amd64/amd64/busdma_machdep.c -L sys/amd64/amd64/busdma_machdep.c -u -r1.2 -r1.3
--- sys/amd64/amd64/busdma_machdep.c
+++ sys/amd64/amd64/busdma_machdep.c
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/busdma_machdep.c,v 1.70.2.3 2006/03/28 06:28:37 delphij Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/busdma_machdep.c,v 1.83 2007/06/17 04:21:58 mjacob Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -48,6 +48,7 @@
#include <machine/atomic.h>
#include <machine/bus.h>
#include <machine/md_var.h>
+#include <machine/specialreg.h>
#define MAX_BPAGES 8192
@@ -219,6 +220,10 @@
if (boundary != 0 && boundary < maxsegsz)
maxsegsz = boundary;
+ if (maxsegsz == 0) {
+ return (EINVAL);
+ }
+
/* Return a NULL tag on failure */
*dmat = NULL;
@@ -492,7 +497,16 @@
}
}
+ /*
+ * XXX:
+ * (dmat->alignment < dmat->maxsize) is just a quick hack; the exact
+ * alignment guarantees of malloc need to be nailed down, and the
+ * code below should be rewritten to take that into account.
+ *
+ * In the meantime, we'll warn the user if malloc gets it wrong.
+ */
if ((dmat->maxsize <= PAGE_SIZE) &&
+ (dmat->alignment < dmat->maxsize) &&
dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem)) {
*vaddr = malloc(dmat->maxsize, M_DEVBUF, mflags);
} else {
@@ -510,7 +524,12 @@
CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
__func__, dmat, dmat->flags, ENOMEM);
return (ENOMEM);
+ } else if ((uintptr_t)*vaddr & (dmat->alignment - 1)) {
+ printf("bus_dmamem_alloc failed to align memory properly.\n");
}
+ if (flags & BUS_DMA_NOCACHE)
+ pmap_change_attr((vm_offset_t)*vaddr, dmat->maxsize,
+ PAT_UNCACHEABLE);
CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
__func__, dmat, dmat->flags, ENOMEM);
return (0);
@@ -529,8 +548,10 @@
*/
if (map != NULL)
panic("bus_dmamem_free: Invalid map freed\n");
- if ((dmat->maxsize <= PAGE_SIZE)
- && dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem))
+ pmap_change_attr((vm_offset_t)vaddr, dmat->maxsize, PAT_WRITE_BACK);
+ if ((dmat->maxsize <= PAGE_SIZE) &&
+ (dmat->alignment < dmat->maxsize) &&
+ dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem))
free(vaddr, M_DEVBUF);
else {
contigfree(vaddr, dmat->maxsize, M_DEVBUF);
@@ -632,6 +653,8 @@
* Compute the segment size, and adjust counts.
*/
sgsize = PAGE_SIZE - ((u_long)curaddr & PAGE_MASK);
+ if (sgsize > dmat->maxsegsz)
+ sgsize = dmat->maxsegsz;
if (buflen < sgsize)
sgsize = buflen;
@@ -703,9 +726,10 @@
error = _bus_dmamap_load_buffer(dmat, map, buf, buflen, NULL, flags,
&lastaddr, dmat->segments, &nsegs, 1);
+ CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
+ __func__, dmat, dmat->flags, error, nsegs + 1);
+
if (error == EINPROGRESS) {
- CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
- __func__, dmat, dmat->flags, error);
return (error);
}
@@ -714,8 +738,13 @@
else
(*callback)(callback_arg, dmat->segments, nsegs + 1, 0);
- CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error 0 nsegs %d",
- __func__, dmat, dmat->flags, nsegs + 1);
+ /*
+ * Return ENOMEM to the caller so that it can pass it up the stack.
+ * This error only happens when NOWAIT is set, so deferal is disabled.
+ */
+ if (error == ENOMEM)
+ return (error);
+
return (0);
}
@@ -812,7 +841,7 @@
bus_dmamap_callback2_t *callback, void *callback_arg,
int flags)
{
- bus_addr_t lastaddr;
+ bus_addr_t lastaddr = 0;
int nsegs, error, first, i;
bus_size_t resid;
struct iovec *iov;
@@ -888,7 +917,6 @@
* want to add support for invalidating
* the caches on broken hardware
*/
- dmat->bounce_zone->total_bounced++;
CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x op 0x%x "
"performing bounce", __func__, op, dmat, dmat->flags);
@@ -899,6 +927,7 @@
bpage->datacount);
bpage = STAILQ_NEXT(bpage, links);
}
+ dmat->bounce_zone->total_bounced++;
}
if (op & BUS_DMASYNC_POSTREAD) {
@@ -908,6 +937,7 @@
bpage->datacount);
bpage = STAILQ_NEXT(bpage, links);
}
+ dmat->bounce_zone->total_bounced++;
}
}
}
Index: vm_machdep.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/vm_machdep.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/amd64/vm_machdep.c -L sys/amd64/amd64/vm_machdep.c -u -r1.1.1.1 -r1.2
--- sys/amd64/amd64/vm_machdep.c
+++ sys/amd64/amd64/vm_machdep.c
@@ -41,10 +41,11 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/vm_machdep.c,v 1.248.2.1 2005/11/15 00:25:59 peter Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/vm_machdep.c,v 1.255 2007/06/04 23:57:29 jeff Exp $");
#include "opt_isa.h"
#include "opt_cpu.h"
+#include "opt_compat.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -69,6 +70,7 @@
#include <machine/cpu.h>
#include <machine/md_var.h>
#include <machine/pcb.h>
+#include <machine/specialreg.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>
@@ -79,6 +81,12 @@
#include <amd64/isa/isa.h>
+#ifdef COMPAT_IA32
+
+extern struct sysentvec ia32_freebsd_sysvec;
+
+#endif
+
static void cpu_reset_real(void);
#ifdef SMP
static void cpu_reset_proxy(void);
@@ -162,7 +170,7 @@
* pcb2->pcb_[fg]sbase: cloned above
*/
- /* Setup to release sched_lock in fork_exit(). */
+ /* Setup to release spin count in fork_exit(). */
td2->td_md.md_spinlock_count = 1;
td2->td_md.md_saved_flags = PSL_KERNEL | PSL_I;
@@ -296,7 +304,7 @@
* pcb2->pcb_[fg]sbase: cloned above
*/
- /* Setup to release sched_lock in fork_exit(). */
+ /* Setup to release spin count in fork_exit(). */
td->td_md.md_spinlock_count = 1;
td->td_md.md_saved_flags = PSL_KERNEL | PSL_I;
}
@@ -320,6 +328,28 @@
*/
cpu_thread_clean(td);
+#ifdef COMPAT_IA32
+ if (td->td_proc->p_sysent == &ia32_freebsd_sysvec) {
+ /*
+ * Set the trap frame to point at the beginning of the uts
+ * function.
+ */
+ td->td_frame->tf_rbp = 0;
+ td->td_frame->tf_rsp =
+ (((uintptr_t)stack->ss_sp + stack->ss_size - 4) & ~0x0f) - 4;
+ td->td_frame->tf_rip = (uintptr_t)entry;
+
+ /*
+ * Pass the address of the mailbox for this kse to the uts
+ * function as a parameter on the stack.
+ */
+ suword32((void *)(td->td_frame->tf_rsp + sizeof(int32_t)),
+ (uint32_t)(uintptr_t)arg);
+
+ return;
+ }
+#endif
+
/*
* Set the trap frame to point at the beginning of the uts
* function.
@@ -328,7 +358,6 @@
td->td_frame->tf_rsp =
((register_t)stack->ss_sp + stack->ss_size) & ~0x0f;
td->td_frame->tf_rsp -= 8;
- td->td_frame->tf_rbp = 0;
td->td_frame->tf_rip = (register_t)entry;
/*
@@ -345,6 +374,19 @@
if ((u_int64_t)tls_base >= VM_MAXUSER_ADDRESS)
return (EINVAL);
+#ifdef COMPAT_IA32
+ if (td->td_proc->p_sysent == &ia32_freebsd_sysvec) {
+ if (td == curthread) {
+ critical_enter();
+ td->td_pcb->pcb_gsbase = (register_t)tls_base;
+ wrmsr(MSR_KGSBASE, td->td_pcb->pcb_gsbase);
+ critical_exit();
+ } else {
+ td->td_pcb->pcb_gsbase = (register_t)tls_base;
+ }
+ return (0);
+ }
+#endif
if (td == curthread) {
critical_enter();
td->td_pcb->pcb_fsbase = (register_t)tls_base;
@@ -389,7 +431,9 @@
cpustop_restartfunc = cpu_reset_proxy;
cpu_reset_proxy_active = 0;
printf("cpu_reset: Restarting BSP\n");
- started_cpus = (1<<0); /* Restart CPU #0 */
+
+ /* Restart CPU #0. */
+ atomic_store_rel_int(&started_cpus, 1 << 0);
cnt = 0;
while (cpu_reset_proxy_active == 0 && cnt < 10000000)
@@ -413,6 +457,10 @@
static void
cpu_reset_real()
{
+ struct region_descriptor null_idt;
+ int b;
+
+ disable_intr();
/*
* Attempt to do a CPU reset via the keyboard controller,
@@ -421,14 +469,44 @@
*/
outb(IO_KBD + 4, 0xFE);
DELAY(500000); /* wait 0.5 sec to see if that did it */
- printf("Keyboard reset did not work, attempting CPU shutdown\n");
+
+ /*
+ * Attempt to force a reset via the Reset Control register at
+ * I/O port 0xcf9. Bit 2 forces a system reset when it is
+ * written as 1. Bit 1 selects the type of reset to attempt:
+ * 0 selects a "soft" reset, and 1 selects a "hard" reset. We
+ * try to do a "soft" reset first, and then a "hard" reset.
+ */
+ outb(0xcf9, 0x2);
+ outb(0xcf9, 0x6);
+ DELAY(500000); /* wait 0.5 sec to see if that did it */
+
+ /*
+ * Attempt to force a reset via the Fast A20 and Init register
+ * at I/O port 0x92. Bit 1 serves as an alternate A20 gate.
+ * Bit 0 asserts INIT# when set to 1. We are careful to only
+ * preserve bit 1 while setting bit 0. We also must clear bit
+ * 0 before setting it if it isn't already clear.
+ */
+ b = inb(0x92);
+ if (b != 0xff) {
+ if ((b & 0x1) != 0)
+ outb(0x92, b & 0xfe);
+ outb(0x92, b | 0x1);
+ DELAY(500000); /* wait 0.5 sec to see if that did it */
+ }
+
+ printf("No known reset method worked, attempting CPU shutdown\n");
DELAY(1000000); /* wait 1 sec for printf to complete */
- /* Force a shutdown by unmapping entire address space. */
- bzero((caddr_t)PML4map, PAGE_SIZE);
+ /* Wipe the IDT. */
+ null_idt.rd_limit = 0;
+ null_idt.rd_base = 0;
+ lidt(&null_idt);
/* "good night, sweet prince .... <THUNK!>" */
- invltlb();
+ breakpoint();
+
/* NOTREACHED */
while(1);
}
Index: mptable.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/mptable.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/amd64/mptable.c -L sys/amd64/amd64/mptable.c -u -r1.1.1.1 -r1.2
--- sys/amd64/amd64/mptable.c
+++ sys/amd64/amd64/mptable.c
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/mptable.c,v 1.236 2005/04/15 18:44:53 peter Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/mptable.c,v 1.240 2007/05/08 22:01:02 jhb Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -50,7 +50,7 @@
/* string defined by the Intel MP Spec as identifying the MP table */
#define MP_SIG 0x5f504d5f /* _MP_ */
-#define NAPICID 32 /* Max number of APIC's */
+#define MAX_LAPIC_ID 63 /* Max local APIC ID for HTT fixup */
#define BIOS_BASE (0xf0000)
#define BIOS_SIZE (0x10000)
@@ -136,12 +136,12 @@
static mpfps_t mpfps;
static mpcth_t mpct;
-static void *ioapics[NAPICID];
+static void *ioapics[MAX_APIC_ID + 1];
static bus_datum *busses;
static int mptable_nioapics, mptable_nbusses, mptable_maxbusid;
static int pci0 = -1;
-static MALLOC_DEFINE(M_MPTABLE, "MP Table", "MP Table Items");
+static MALLOC_DEFINE(M_MPTABLE, "mptable", "MP Table Items");
static enum intr_polarity conforming_polarity(u_char src_bus,
u_char src_bus_irq);
@@ -152,7 +152,7 @@
static void mptable_count_items(void);
static void mptable_count_items_handler(u_char *entry, void *arg);
#ifdef MPTABLE_FORCE_HTT
-static void mptable_hyperthread_fixup(u_int id_mask);
+static void mptable_hyperthread_fixup(u_long id_mask);
#endif
static void mptable_parse_apics_and_busses(void);
static void mptable_parse_apics_and_busses_handler(u_char *entry,
@@ -294,7 +294,7 @@
static int
mptable_probe_cpus(void)
{
- u_int cpu_mask;
+ u_long cpu_mask;
/* Is this a pre-defined config? */
if (mpfps->config_type != 0) {
@@ -316,18 +316,20 @@
static int
mptable_setup_local(void)
{
+ vm_paddr_t addr;
/* Is this a pre-defined config? */
printf("MPTable: <");
if (mpfps->config_type != 0) {
- lapic_init(DEFAULT_APIC_BASE);
+ addr = DEFAULT_APIC_BASE;
printf("Default Configuration %d", mpfps->config_type);
} else {
- lapic_init((uintptr_t)mpct->apic_address);
+ addr = mpct->apic_address;
printf("%.*s %.*s", (int)sizeof(mpct->oem_id), mpct->oem_id,
(int)sizeof(mpct->product_id), mpct->product_id);
}
printf(">\n");
+ lapic_init(addr);
return (0);
}
@@ -354,7 +356,7 @@
mptable_parse_ints();
/* Fourth, we register all the I/O APIC's. */
- for (i = 0; i < NAPICID; i++)
+ for (i = 0; i <= MAX_APIC_ID; i++)
if (ioapics[i] != NULL)
ioapic_register(ioapics[i]);
@@ -412,7 +414,7 @@
mptable_probe_cpus_handler(u_char *entry, void *arg)
{
proc_entry_ptr proc;
- u_int *cpu_mask;
+ u_long *cpu_mask;
switch (*entry) {
case MPCT_ENTRY_PROCESSOR:
@@ -420,8 +422,10 @@
if (proc->cpu_flags & PROCENTRY_FLAG_EN) {
lapic_create(proc->apic_id, proc->cpu_flags &
PROCENTRY_FLAG_BP);
- cpu_mask = (u_int *)arg;
- *cpu_mask |= (1 << proc->apic_id);
+ if (proc->apic_id < MAX_LAPIC_ID) {
+ cpu_mask = (u_long *)arg;
+ *cpu_mask |= (1ul << proc->apic_id);
+ }
}
break;
}
@@ -508,14 +512,14 @@
apic = (io_apic_entry_ptr)entry;
if (!(apic->apic_flags & IOAPICENTRY_FLAG_EN))
break;
- if (apic->apic_id >= NAPICID)
+ if (apic->apic_id > MAX_APIC_ID)
panic("%s: I/O APIC ID %d too high", __func__,
apic->apic_id);
if (ioapics[apic->apic_id] != NULL)
panic("%s: Double APIC ID %d", __func__,
apic->apic_id);
- ioapics[apic->apic_id] = ioapic_create(
- (uintptr_t)apic->apic_address, apic->apic_id, -1);
+ ioapics[apic->apic_id] = ioapic_create(apic->apic_address,
+ apic->apic_id, -1);
break;
default:
break;
@@ -653,7 +657,7 @@
return;
}
}
- if (apic_id >= NAPICID) {
+ if (apic_id > MAX_APIC_ID) {
printf("MPTable: Ignoring interrupt entry for ioapic%d\n",
intr->dst_apic_id);
return;
@@ -866,7 +870,7 @@
* with the number of logical CPU's in the processor.
*/
static void
-mptable_hyperthread_fixup(u_int id_mask)
+mptable_hyperthread_fixup(u_long id_mask)
{
u_int i, id, logical_cpus;
@@ -883,7 +887,7 @@
* physical processor. If any of those ID's are
* already in the table, then kill the fixup.
*/
- for (id = 0; id < NAPICID; id++) {
+ for (id = 0; id <= MAX_LAPIC_ID; id++) {
if ((id_mask & 1 << id) == 0)
continue;
/* First, make sure we are on a logical_cpus boundary. */
@@ -898,7 +902,7 @@
* Ok, the ID's checked out, so perform the fixup by
* adding the logical CPUs.
*/
- while ((id = ffs(id_mask)) != 0) {
+ while ((id = ffsl(id_mask)) != 0) {
id--;
for (i = id + 1; i < id + logical_cpus; i++) {
if (bootverbose)
Index: support.S
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/support.S,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/amd64/support.S -L sys/amd64/amd64/support.S -u -r1.1.1.1 -r1.2
--- sys/amd64/amd64/support.S
+++ sys/amd64/amd64/support.S
@@ -27,7 +27,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/amd64/amd64/support.S,v 1.115 2005/06/24 00:45:01 peter Exp $
+ * $FreeBSD: src/sys/amd64/amd64/support.S,v 1.128 2007/08/22 05:06:14 jkoshy Exp $
*/
#include "opt_ddb.h"
@@ -59,7 +59,7 @@
/* done */
ENTRY(bzero)
movq %rsi,%rcx
- xorq %rax,%rax
+ xorl %eax,%eax
shrq $3,%rcx
cld
rep
@@ -69,12 +69,13 @@
rep
stosb
ret
-
+END(bzero)
+
/* Address: %rdi */
ENTRY(pagezero)
movq $-PAGE_SIZE,%rdx
subq %rdx,%rdi
- xorq %rax,%rax
+ xorl %eax,%eax
1:
movnti %rax,(%rdi,%rdx)
movnti %rax,8(%rdi,%rdx)
@@ -84,6 +85,7 @@
jne 1b
sfence
ret
+END(pagezero)
ENTRY(bcmp)
movq %rdx,%rcx
@@ -101,6 +103,7 @@
setne %al
movsbl %al,%eax
ret
+END(bcmp)
/*
* bcopy(src, dst, cnt)
@@ -144,7 +147,8 @@
movsq
cld
ret
-
+END(bcopy)
+
/*
* Note: memcpy does not support overlapping copies
*/
@@ -159,6 +163,7 @@
rep
movsb
ret
+END(memcpy)
/*
* pagecopy(%rdi=from, %rsi=to)
@@ -185,6 +190,7 @@
jne 2b
sfence
ret
+END(pagecopy)
/* fillw(pat, base, cnt) */
/* %rdi,%rsi, %rdx */
@@ -196,6 +202,7 @@
rep
stosw
ret
+END(fillw)
/*****************************************************************************/
/* copyout and fubyte family */
@@ -242,7 +249,7 @@
cmpq %rcx,%rax
ja copyout_fault
- xchgq %rdi, %rsi
+ xchgq %rdi,%rsi
/* bcopy(%rsi, %rdi, %rdx) */
movq %rdx,%rcx
@@ -256,7 +263,7 @@
movsb
done_copyout:
- xorq %rax,%rax
+ xorl %eax,%eax
movq PCPU(CURPCB),%rdx
movq %rax,PCB_ONFAULT(%rdx)
ret
@@ -267,6 +274,7 @@
movq $0,PCB_ONFAULT(%rdx)
movq $EFAULT,%rax
ret
+END(copyout)
/*
* copyin(from_user, to_kernel, len) - MP SAFE
@@ -288,8 +296,8 @@
cmpq %rcx,%rax
ja copyin_fault
- xchgq %rdi, %rsi
- movq %rdx, %rcx
+ xchgq %rdi,%rsi
+ movq %rdx,%rcx
movb %cl,%al
shrq $3,%rcx /* copy longword-wise */
cld
@@ -301,7 +309,7 @@
movsb
done_copyin:
- xorq %rax,%rax
+ xorl %eax,%eax
movq PCPU(CURPCB),%rdx
movq %rax,PCB_ONFAULT(%rdx)
ret
@@ -312,12 +320,13 @@
movq $0,PCB_ONFAULT(%rdx)
movq $EFAULT,%rax
ret
+END(copyin)
/*
- * casuptr. Compare and set user pointer. Returns -1 or the current value.
+ * casuword32. Compare and set user integer. Returns -1 or the current value.
* dst = %rdi, old = %rsi, new = %rdx
*/
-ENTRY(casuptr)
+ENTRY(casuword32)
movq PCPU(CURPCB),%rcx
movq $fusufault,PCB_ONFAULT(%rcx)
@@ -325,11 +334,40 @@
cmpq %rax,%rdi /* verify address is valid */
ja fusufault
- movq %rsi, %rax /* old */
+ movl %esi,%eax /* old */
#ifdef SMP
lock
#endif
- cmpxchgq %rdx, (%rdi) /* new = %rdx */
+ cmpxchgl %edx,(%rdi) /* new = %edx */
+
+ /*
+ * The old value is in %eax. If the store succeeded it will be the
+ * value we expected (old) from before the store, otherwise it will
+ * be the current value.
+ */
+
+ movq PCPU(CURPCB),%rcx
+ movq $0,PCB_ONFAULT(%rcx)
+ ret
+END(casuword32)
+
+/*
+ * casuword. Compare and set user word. Returns -1 or the current value.
+ * dst = %rdi, old = %rsi, new = %rdx
+ */
+ENTRY(casuword)
+ movq PCPU(CURPCB),%rcx
+ movq $fusufault,PCB_ONFAULT(%rcx)
+
+ movq $VM_MAXUSER_ADDRESS-4,%rax
+ cmpq %rax,%rdi /* verify address is valid */
+ ja fusufault
+
+ movq %rsi,%rax /* old */
+#ifdef SMP
+ lock
+#endif
+ cmpxchgq %rdx,(%rdi) /* new = %rdx */
/*
* The old value is in %eax. If the store succeeded it will be the
@@ -341,6 +379,7 @@
movq $fusufault,PCB_ONFAULT(%rcx)
movq $0,PCB_ONFAULT(%rcx)
ret
+END(casuword)
/*
* Fetch (load) a 64-bit word, a 32-bit word, a 16-bit word, or an 8-bit
@@ -360,6 +399,8 @@
movq (%rdi),%rax
movq $0,PCB_ONFAULT(%rcx)
ret
+END(fuword64)
+END(fuword)
ENTRY(fuword32)
movq PCPU(CURPCB),%rcx
@@ -372,6 +413,7 @@
movl (%rdi),%eax
movq $0,PCB_ONFAULT(%rcx)
ret
+END(fuword32)
/*
* fuswintr() and suswintr() are specialized variants of fuword16() and
@@ -384,6 +426,8 @@
ENTRY(fuswintr)
movq $-1,%rax
ret
+END(suswintr)
+END(fuswintr)
ENTRY(fuword16)
movq PCPU(CURPCB),%rcx
@@ -396,6 +440,7 @@
movzwl (%rdi),%eax
movq $0,PCB_ONFAULT(%rcx)
ret
+END(fuword16)
ENTRY(fubyte)
movq PCPU(CURPCB),%rcx
@@ -408,11 +453,12 @@
movzbl (%rdi),%eax
movq $0,PCB_ONFAULT(%rcx)
ret
+END(fubyte)
ALIGN_TEXT
fusufault:
movq PCPU(CURPCB),%rcx
- xorq %rax,%rax
+ xorl %eax,%eax
movq %rax,PCB_ONFAULT(%rcx)
decq %rax
ret
@@ -432,10 +478,12 @@
ja fusufault
movq %rsi,(%rdi)
- xorq %rax,%rax
+ xorl %eax,%eax
movq PCPU(CURPCB),%rcx
movq %rax,PCB_ONFAULT(%rcx)
ret
+END(suword64)
+END(suword)
ENTRY(suword32)
movq PCPU(CURPCB),%rcx
@@ -446,10 +494,11 @@
ja fusufault
movl %esi,(%rdi)
- xorq %rax,%rax
+ xorl %eax,%eax
movq PCPU(CURPCB),%rcx
movq %rax,PCB_ONFAULT(%rcx)
ret
+END(suword32)
ENTRY(suword16)
movq PCPU(CURPCB),%rcx
@@ -460,10 +509,11 @@
ja fusufault
movw %si,(%rdi)
- xorq %rax,%rax
+ xorl %eax,%eax
movq PCPU(CURPCB),%rcx /* restore trashed register */
movq %rax,PCB_ONFAULT(%rcx)
ret
+END(suword16)
ENTRY(subyte)
movq PCPU(CURPCB),%rcx
@@ -473,12 +523,13 @@
cmpq %rax,%rdi /* verify address validity */
ja fusufault
- movl %esi, %eax
+ movl %esi,%eax
movb %al,(%rdi)
- xorq %rax,%rax
+ xorl %eax,%eax
movq PCPU(CURPCB),%rcx /* restore trashed register */
movq %rax,PCB_ONFAULT(%rcx)
ret
+END(subyte)
/*
* copyinstr(from, to, maxlen, int *lencopied) - MP SAFE
@@ -490,9 +541,9 @@
* return the actual length in *lencopied.
*/
ENTRY(copyinstr)
- movq %rdx, %r8 /* %r8 = maxlen */
- movq %rcx, %r9 /* %r9 = *len */
- xchgq %rdi, %rsi /* %rdi = from, %rsi = to */
+ movq %rdx,%r8 /* %r8 = maxlen */
+ movq %rcx,%r9 /* %r9 = *len */
+ xchgq %rdi,%rsi /* %rdi = from, %rsi = to */
movq PCPU(CURPCB),%rcx
movq $cpystrflt,PCB_ONFAULT(%rcx)
@@ -522,7 +573,7 @@
/* Success -- 0 byte reached */
decq %rdx
- xorq %rax,%rax
+ xorl %eax,%eax
jmp cpystrflt_x
3:
/* rdx is zero - return ENAMETOOLONG or EFAULT */
@@ -547,16 +598,16 @@
movq %r8,(%r9)
1:
ret
-
+END(copyinstr)
/*
* copystr(from, to, maxlen, int *lencopied) - MP SAFE
* %rdi, %rsi, %rdx, %rcx
*/
ENTRY(copystr)
- movq %rdx, %r8 /* %r8 = maxlen */
+ movq %rdx,%r8 /* %r8 = maxlen */
- xchgq %rdi, %rsi
+ xchgq %rdi,%rsi
incq %rdx
cld
1:
@@ -569,7 +620,7 @@
/* Success -- 0 byte reached */
decq %rdx
- xorq %rax,%rax
+ xorl %eax,%eax
jmp 6f
4:
/* rdx is zero -- return ENAMETOOLONG */
@@ -577,13 +628,14 @@
6:
- testq %rcx, %rcx
+ testq %rcx,%rcx
jz 7f
/* set *lencopied and return %rax */
- subq %rdx, %r8
- movq %r8, (%rcx)
+ subq %rdx,%r8
+ movq %r8,(%rcx)
7:
ret
+END(copystr)
/*
* Handling of special amd64 registers and descriptor tables etc
@@ -598,7 +650,7 @@
jmp 1f
nop
1:
- movl $KDSEL, %eax
+ movl $KDSEL,%eax
movl %eax,%ds
movl %eax,%es
movl %eax,%fs /* Beware, use wrmsr to set 64 bit base */
@@ -611,6 +663,7 @@
pushq %rax
MEXITCOUNT
lretq
+END(lgdt)
/*****************************************************************************/
/* setjump, longjump */
@@ -628,6 +681,7 @@
movq %rdx,56(%rdi) /* save rip */
xorl %eax,%eax /* return(0); */
ret
+END(setjmp)
ENTRY(longjmp)
movq 0(%rdi),%rbx /* restore rbx */
@@ -642,6 +696,7 @@
xorl %eax,%eax /* return(1); */
incl %eax
ret
+END(longjmp)
/*
* Support for BB-profiling (gcc -a). The kernbb program will extract
Index: local_apic.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/local_apic.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/amd64/amd64/local_apic.c -L sys/amd64/amd64/local_apic.c -u -r1.2 -r1.3
--- sys/amd64/amd64/local_apic.c
+++ sys/amd64/amd64/local_apic.c
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/local_apic.c,v 1.17.2.6 2006/03/10 19:37:30 jhb Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/local_apic.c,v 1.42.2.1 2007/11/08 20:09:15 jhb Exp $");
#include "opt_hwpmc_hooks.h"
@@ -46,12 +46,12 @@
#include <sys/mutex.h>
#include <sys/pcpu.h>
#include <sys/smp.h>
-#include <sys/proc.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <machine/apicreg.h>
+#include <machine/cpu.h>
#include <machine/cputypes.h>
#include <machine/frame.h>
#include <machine/intr_machdep.h>
@@ -65,13 +65,6 @@
#include <ddb/ddb.h>
#endif
-/*
- * We can handle up to 60 APICs via our logical cluster IDs, but currently
- * the physical IDs on Intel processors up to the Pentium 4 are limited to
- * 16.
- */
-#define MAX_APICID 16
-
/* Sanity checks on IDT vectors. */
CTASSERT(APIC_IO_INTS + APIC_NUM_IOINTS == APIC_TIMER_INT);
CTASSERT(APIC_TIMER_INT < APIC_LOCAL_INTS);
@@ -114,7 +107,7 @@
u_long la_hard_ticks;
u_long la_stat_ticks;
u_long la_prof_ticks;
-} static lapics[MAX_APICID];
+} static lapics[MAX_APIC_ID + 1];
/* XXX: should thermal be an NMI? */
@@ -147,16 +140,22 @@
APIC_TDCR_32, APIC_TDCR_64, APIC_TDCR_128
};
+extern inthand_t IDTVEC(rsvd);
+
volatile lapic_t *lapic;
+vm_paddr_t lapic_paddr;
static u_long lapic_timer_divisor, lapic_timer_period, lapic_timer_hz;
static void lapic_enable(void);
+static void lapic_resume(struct pic *pic);
static void lapic_timer_enable_intr(void);
static void lapic_timer_oneshot(u_int count);
static void lapic_timer_periodic(u_int count);
static void lapic_timer_set_divisor(u_int divisor);
static uint32_t lvt_mode(struct lapic *la, u_int pin, uint32_t value);
+struct pic lapic_pic = { .pic_resume = lapic_resume };
+
static uint32_t
lvt_mode(struct lapic *la, u_int pin, uint32_t value)
{
@@ -202,13 +201,14 @@
* Map the local APIC and setup necessary interrupt vectors.
*/
void
-lapic_init(uintptr_t addr)
+lapic_init(vm_paddr_t addr)
{
/* Map the local APIC and setup the spurious interrupt handler. */
KASSERT(trunc_page(addr) == addr,
("local APIC not aligned on a page boundary"));
- lapic = (lapic_t *)pmap_mapdev(addr, sizeof(lapic_t));
+ lapic = pmap_mapdev(addr, sizeof(lapic_t));
+ lapic_paddr = addr;
setidt(APIC_SPURIOUS_INT, IDTVEC(spuriousint), SDT_SYSIGT, SEL_KPL, 0);
/* Perform basic initialization of the BSP's local APIC. */
@@ -217,7 +217,6 @@
/* Set BSP's per-CPU local APIC ID. */
PCPU_SET(apic_id, lapic_id());
- intr_add_cpu(PCPU_GET(apic_id));
/* Local APIC timer interrupt. */
setidt(APIC_TIMER_INT, IDTVEC(timerint), SDT_SYSIGT, SEL_KPL, 0);
@@ -234,7 +233,7 @@
{
int i;
- if (apic_id >= MAX_APICID) {
+ if (apic_id > MAX_APIC_ID) {
printf("APIC: Ignoring local APIC with ID %d\n", apic_id);
if (boot_cpu)
panic("Can't ignore BSP");
@@ -277,7 +276,7 @@
}
void
-lapic_setup(void)
+lapic_setup(int boot)
{
struct lapic *la;
u_int32_t maxlvt;
@@ -306,9 +305,13 @@
/* Program timer LVT and setup handler. */
lapic->lvt_timer = lvt_mode(la, LVT_TIMER, lapic->lvt_timer);
- snprintf(buf, sizeof(buf), "cpu%d: timer", PCPU_GET(cpuid));
- intrcnt_add(buf, &la->la_timer_count);
- if (PCPU_GET(cpuid) != 0) {
+ if (boot) {
+ snprintf(buf, sizeof(buf), "cpu%d: timer", PCPU_GET(cpuid));
+ intrcnt_add(buf, &la->la_timer_count);
+ }
+
+ /* We don't setup the timer during boot on the BSP until later. */
+ if (!(boot && PCPU_GET(cpuid) == 0)) {
KASSERT(lapic_timer_period != 0, ("lapic%u: zero divisor",
lapic_id()));
lapic_timer_set_divisor(lapic_timer_divisor);
@@ -318,6 +321,29 @@
/* XXX: Error and thermal LVTs */
+ if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
+ /*
+ * Detect the presence of C1E capability mostly on latest
+ * dual-cores (or future) k8 family. This feature renders
+ * the local APIC timer dead, so we disable it by reading
+ * the Interrupt Pending Message register and clearing both
+ * C1eOnCmpHalt (bit 28) and SmiOnCmpHalt (bit 27).
+ *
+ * Reference:
+ * "BIOS and Kernel Developer's Guide for AMD NPT
+ * Family 0Fh Processors"
+ * #32559 revision 3.00
+ */
+ if ((cpu_id & 0x00000f00) == 0x00000f00 &&
+ (cpu_id & 0x0fff0000) >= 0x00040000) {
+ uint64_t msr;
+
+ msr = rdmsr(0xc0010055);
+ if (msr & 0x18000000)
+ wrmsr(0xc0010055, msr & ~0x18000000ULL);
+ }
+ }
+
intr_restore(eflags);
}
@@ -398,6 +424,14 @@
lapic->svr = value;
}
+/* Reset the local APIC on the BSP during resume. */
+static void
+lapic_resume(struct pic *pic)
+{
+
+ lapic_setup(0);
+}
+
int
lapic_id(void)
{
@@ -595,22 +629,41 @@
}
void
-lapic_handle_intr(void *cookie, struct intrframe frame)
+lapic_handle_intr(int vector, struct trapframe *frame)
{
struct intsrc *isrc;
- int vec = (uintptr_t)cookie;
- if (vec == -1)
+ if (vector == -1)
panic("Couldn't get vector from ISR!");
- isrc = intr_lookup_source(apic_idt_to_irq(vec));
- intr_execute_handlers(isrc, &frame);
+ isrc = intr_lookup_source(apic_idt_to_irq(vector));
+ intr_execute_handlers(isrc, frame);
}
void
-lapic_handle_timer(struct clockframe frame)
+lapic_handle_timer(struct trapframe *frame)
{
struct lapic *la;
+ /* Send EOI first thing. */
+ lapic_eoi();
+
+#if defined(SMP) && !defined(SCHED_ULE)
+ /*
+ * Don't do any accounting for the disabled HTT cores, since it
+ * will provide misleading numbers for the userland.
+ *
+ * No locking is necessary here, since even if we loose the race
+ * when hlt_cpus_mask changes it is not a big deal, really.
+ *
+ * Don't do that for ULE, since ULE doesn't consider hlt_cpus_mask
+ * and unlike other schedulers it actually schedules threads to
+ * those CPUs.
+ */
+ if ((hlt_cpus_mask & (1 << PCPU_GET(cpuid))) != 0)
+ return;
+#endif
+
+ /* Look up our local APIC structure for the tick counters. */
la = &lapics[PCPU_GET(apic_id)];
(*la->la_timer_count)++;
critical_enter();
@@ -620,16 +673,16 @@
if (la->la_hard_ticks >= lapic_timer_hz) {
la->la_hard_ticks -= lapic_timer_hz;
if (PCPU_GET(cpuid) == 0)
- hardclock(&frame);
+ hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
else
- hardclock_process(&frame);
+ hardclock_cpu(TRAPF_USERMODE(frame));
}
/* Fire statclock at stathz. */
la->la_stat_ticks += stathz;
if (la->la_stat_ticks >= lapic_timer_hz) {
la->la_stat_ticks -= lapic_timer_hz;
- statclock(&frame);
+ statclock(TRAPF_USERMODE(frame));
}
/* Fire profclock at profhz, but only when needed. */
@@ -637,7 +690,7 @@
if (la->la_prof_ticks >= lapic_timer_hz) {
la->la_prof_ticks -= lapic_timer_hz;
if (profprocs != 0)
- profclock(&frame);
+ profclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
}
critical_exit();
}
@@ -710,6 +763,65 @@
panic("Couldn't find an APIC vector for IRQ %u", irq);
}
+/*
+ * Request 'count' free contiguous IDT vectors to be used by 'count'
+ * IRQs. 'count' must be a power of two and the vectors will be
+ * aligned on a boundary of 'align'. If the request cannot be
+ * satisfied, 0 is returned.
+ */
+u_int
+apic_alloc_vectors(u_int *irqs, u_int count, u_int align)
+{
+ u_int first, run, vector;
+
+ KASSERT(powerof2(count), ("bad count"));
+ KASSERT(powerof2(align), ("bad align"));
+ KASSERT(align >= count, ("align < count"));
+#ifdef INVARIANTS
+ for (run = 0; run < count; run++)
+ KASSERT(irqs[run] < NUM_IO_INTS, ("Invalid IRQ %u at index %u",
+ irqs[run], run));
+#endif
+
+ /*
+ * Search for 'count' free vectors. As with apic_alloc_vector(),
+ * this just uses a simple first fit algorithm.
+ */
+ run = 0;
+ first = 0;
+ mtx_lock_spin(&icu_lock);
+ for (vector = 0; vector < APIC_NUM_IOINTS; vector++) {
+
+ /* Vector is in use, end run. */
+ if (ioint_irqs[vector] != 0) {
+ run = 0;
+ first = 0;
+ continue;
+ }
+
+ /* Start a new run if run == 0 and vector is aligned. */
+ if (run == 0) {
+ if ((vector & (align - 1)) != 0)
+ continue;
+ first = vector;
+ }
+ run++;
+
+ /* Keep looping if the run isn't long enough yet. */
+ if (run < count)
+ continue;
+
+ /* Found a run, assign IRQs and return the first vector. */
+ for (vector = 0; vector < count; vector++)
+ ioint_irqs[first + vector] = irqs[vector];
+ mtx_unlock_spin(&icu_lock);
+ return (first + APIC_IO_INTS);
+ }
+ mtx_unlock_spin(&icu_lock);
+ printf("APIC: Couldn't find APIC vectors for %u IRQs\n", count);
+ return (0);
+}
+
void
apic_enable_vector(u_int vector)
{
@@ -720,6 +832,16 @@
setidt(vector, ioint_handlers[vector / 32], SDT_SYSIGT, SEL_KPL, 0);
}
+void
+apic_disable_vector(u_int vector)
+{
+
+ KASSERT(vector != IDT_SYSCALL, ("Attempt to overwrite syscall entry"));
+ KASSERT(ioint_handlers[vector / 32] != NULL,
+ ("No ISR handler for vector %u", vector));
+ setidt(vector, &IDTVEC(rsvd), SDT_SYSIGT, SEL_KPL, 0);
+}
+
/* Release an APIC vector when it's no longer in use. */
void
apic_free_vector(u_int vector, u_int irq)
@@ -752,18 +874,16 @@
DB_SHOW_COMMAND(apic, db_show_apic)
{
struct intsrc *isrc;
- int quit, i, verbose;
+ int i, verbose;
u_int irq;
- quit = 0;
if (strcmp(modif, "vv") == 0)
verbose = 2;
else if (strcmp(modif, "v") == 0)
verbose = 1;
else
verbose = 0;
- db_setup_paging(db_simple_pager, &quit, db_lines_per_page);
- for (i = 0; i < APIC_NUM_IOINTS + 1 && !quit; i++) {
+ for (i = 0; i < APIC_NUM_IOINTS + 1 && !db_pager_quit; i++) {
irq = ioint_irqs[i];
if (irq != 0 && irq != IRQ_SYSCALL) {
db_printf("vec 0x%2x -> ", i + APIC_IO_INTS);
@@ -781,6 +901,76 @@
}
}
}
+
+static void
+dump_mask(const char *prefix, uint32_t v, int base)
+{
+ int i, first;
+
+ first = 1;
+ for (i = 0; i < 32; i++)
+ if (v & (1 << i)) {
+ if (first) {
+ db_printf("%s:", prefix);
+ first = 0;
+ }
+ db_printf(" %02x", base + i);
+ }
+ if (!first)
+ db_printf("\n");
+}
+
+/* Show info from the lapic regs for this CPU. */
+DB_SHOW_COMMAND(lapic, db_show_lapic)
+{
+ uint32_t v;
+
+ db_printf("lapic ID = %d\n", lapic_id());
+ v = lapic->version;
+ db_printf("version = %d.%d\n", (v & APIC_VER_VERSION) >> 4,
+ v & 0xf);
+ db_printf("max LVT = %d\n", (v & APIC_VER_MAXLVT) >> MAXLVTSHIFT);
+ v = lapic->svr;
+ db_printf("SVR = %02x (%s)\n", v & APIC_SVR_VECTOR,
+ v & APIC_SVR_ENABLE ? "enabled" : "disabled");
+ db_printf("TPR = %02x\n", lapic->tpr);
+
+#define dump_field(prefix, index) \
+ dump_mask(__XSTRING(prefix ## index), lapic->prefix ## index, \
+ index * 32)
+
+ db_printf("In-service Interrupts:\n");
+ dump_field(isr, 0);
+ dump_field(isr, 1);
+ dump_field(isr, 2);
+ dump_field(isr, 3);
+ dump_field(isr, 4);
+ dump_field(isr, 5);
+ dump_field(isr, 6);
+ dump_field(isr, 7);
+
+ db_printf("TMR Interrupts:\n");
+ dump_field(tmr, 0);
+ dump_field(tmr, 1);
+ dump_field(tmr, 2);
+ dump_field(tmr, 3);
+ dump_field(tmr, 4);
+ dump_field(tmr, 5);
+ dump_field(tmr, 6);
+ dump_field(tmr, 7);
+
+ db_printf("IRR Interrupts:\n");
+ dump_field(irr, 0);
+ dump_field(irr, 1);
+ dump_field(irr, 2);
+ dump_field(irr, 3);
+ dump_field(irr, 4);
+ dump_field(irr, 5);
+ dump_field(irr, 6);
+ dump_field(irr, 7);
+
+#undef dump_field
+}
#endif
/*
@@ -817,10 +1007,6 @@
struct apic_enumerator *enumerator;
int retval, best;
- /* We only support built in local APICs. */
- if (!(cpu_feature & CPUID_APIC))
- return;
-
/* Don't probe if APIC mode is disabled. */
if (resource_disabled("apic", 0))
return;
@@ -870,12 +1056,8 @@
if (retval != 0)
printf("%s: Failed to setup the local APIC: returned %d\n",
best_enum->apic_name, retval);
-#ifdef SMP
- /* Last, setup the cpu topology now that we have probed CPUs */
- mp_topology();
-#endif
}
-SYSINIT(apic_setup_local, SI_SUB_CPU, SI_ORDER_FIRST, apic_setup_local, NULL)
+SYSINIT(apic_setup_local, SI_SUB_CPU, SI_ORDER_SECOND, apic_setup_local, NULL)
/*
* Setup the I/O APICs.
@@ -896,9 +1078,13 @@
* Finish setting up the local APIC on the BSP once we know how to
* properly program the LINT pins.
*/
- lapic_setup();
+ lapic_setup(1);
+ intr_register_pic(&lapic_pic);
if (bootverbose)
lapic_dump("BSP");
+
+ /* Enable the MSI "pic". */
+ msi_init();
}
SYSINIT(apic_setup_io, SI_SUB_INTR, SI_ORDER_SECOND, apic_setup_io, NULL)
--- /dev/null
+++ sys/amd64/amd64/bpf_jit_machdep.c
@@ -0,0 +1,494 @@
+/*-
+ * Copyright (c) 2002 - 2003 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 Jung-uk Kim <jkim at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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: src/sys/amd64/amd64/bpf_jit_machdep.c,v 1.4 2006/01/03 20:26:02 jkim Exp $");
+
+#include "opt_bpf.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/malloc.h>
+
+#include <net/if.h>
+#include <net/bpf.h>
+#include <net/bpf_jitter.h>
+
+#include <amd64/amd64/bpf_jit_machdep.h>
+
+bpf_filter_func bpf_jit_compile(struct bpf_insn *, u_int, int *);
+
+/*
+ * emit routine to update the jump table
+ */
+static void
+emit_length(bpf_bin_stream *stream, u_int value, u_int len)
+{
+
+ (stream->refs)[stream->bpf_pc] += len;
+ stream->cur_ip += len;
+}
+
+/*
+ * emit routine to output the actual binary code
+ */
+static void
+emit_code(bpf_bin_stream *stream, u_int value, u_int len)
+{
+
+ switch (len) {
+ case 1:
+ stream->ibuf[stream->cur_ip] = (u_char)value;
+ stream->cur_ip++;
+ break;
+
+ case 2:
+ *((u_short *)(stream->ibuf + stream->cur_ip)) = (u_short)value;
+ stream->cur_ip += 2;
+ break;
+
+ case 4:
+ *((u_int *)(stream->ibuf + stream->cur_ip)) = value;
+ stream->cur_ip += 4;
+ break;
+ }
+
+ return;
+}
+
+/*
+ * Function that does the real stuff
+ */
+bpf_filter_func
+bpf_jit_compile(struct bpf_insn *prog, u_int nins, int *mem)
+{
+ struct bpf_insn *ins;
+ u_int i, pass;
+ bpf_bin_stream stream;
+
+ /*
+ * NOTE: do not modify the name of this variable, as it's used by
+ * the macros to emit code.
+ */
+ emit_func emitm;
+
+ /* Do not compile an empty filter. */
+ if (nins == 0)
+ return NULL;
+
+ /* Allocate the reference table for the jumps */
+ stream.refs = (u_int *)malloc((nins + 1) * sizeof(u_int),
+ M_BPFJIT, M_NOWAIT);
+ if (stream.refs == NULL)
+ return NULL;
+
+ /* Reset the reference table */
+ for (i = 0; i < nins + 1; i++)
+ stream.refs[i] = 0;
+
+ stream.cur_ip = 0;
+ stream.bpf_pc = 0;
+
+ /*
+ * the first pass will emit the lengths of the instructions
+ * to create the reference table
+ */
+ emitm = emit_length;
+
+ pass = 0;
+ for (;;) {
+ ins = prog;
+
+ /* create the procedure header */
+ PUSH(RBP);
+ MOVrq(RBP, RSP);
+ MOVoqd(RBP, -8, ESI);
+ MOVoqd(RBP, -12, EDX);
+ PUSH(RBX);
+ MOVrq(RBX, RDI);
+
+ for (i = 0; i < nins; i++) {
+ stream.bpf_pc++;
+
+ switch (ins->code) {
+ default:
+ return NULL;
+
+ case BPF_RET|BPF_K:
+ MOVid(EAX, ins->k);
+ POP(RBX);
+ LEAVE_RET();
+ break;
+
+ case BPF_RET|BPF_A:
+ POP(RBX);
+ LEAVE_RET();
+ break;
+
+ case BPF_LD|BPF_W|BPF_ABS:
+ MOVid(ECX, ins->k);
+ MOVrd(ESI, ECX);
+ ADDib(ECX, sizeof(int));
+ CMPodd(ECX, RBP, -12);
+ JLEb(5);
+ ZERO_EAX();
+ POP(RBX);
+ LEAVE_RET();
+ MOVobd(EAX, RBX, RSI);
+ BSWAP(EAX);
+ break;
+
+ case BPF_LD|BPF_H|BPF_ABS:
+ ZERO_EAX();
+ MOVid(ECX, ins->k);
+ MOVrd(ESI, ECX);
+ ADDib(ECX, sizeof(short));
+ CMPodd(ECX, RBP, -12);
+ JLEb(3);
+ POP(RBX);
+ LEAVE_RET();
+ MOVobw(AX, RBX, RSI);
+ SWAP_AX();
+ break;
+
+ case BPF_LD|BPF_B|BPF_ABS:
+ ZERO_EAX();
+ MOVid(ECX, ins->k);
+ CMPodd(ECX, RBP, -12);
+ JLEb(3);
+ POP(RBX);
+ LEAVE_RET();
+ MOVobb(AL, RBX, RCX);
+ break;
+
+ case BPF_LD|BPF_W|BPF_LEN:
+ MOVodd(EAX, RBP, -8);
+ break;
+
+ case BPF_LDX|BPF_W|BPF_LEN:
+ MOVodd(EDX, RBP, -8);
+ break;
+
+ case BPF_LD|BPF_W|BPF_IND:
+ MOVid(ECX, ins->k);
+ ADDrd(ECX, EDX);
+ MOVrd(ESI, ECX);
+ ADDib(ECX, sizeof(int));
+ CMPodd(ECX, RBP, -12);
+ JLEb(5);
+ ZERO_EAX();
+ POP(RBX);
+ LEAVE_RET();
+ MOVobd(EAX, RBX, RSI);
+ BSWAP(EAX);
+ break;
+
+ case BPF_LD|BPF_H|BPF_IND:
+ ZERO_EAX();
+ MOVid(ECX, ins->k);
+ ADDrd(ECX, EDX);
+ MOVrd(ESI, ECX);
+ ADDib(ECX, sizeof(short));
+ CMPodd(ECX, RBP, -12);
+ JLEb(3);
+ POP(RBX);
+ LEAVE_RET();
+ MOVobw(AX, RBX, RSI);
+ SWAP_AX();
+ break;
+
+ case BPF_LD|BPF_B|BPF_IND:
+ ZERO_EAX();
+ MOVid(ECX, ins->k);
+ ADDrd(ECX, EDX);
+ CMPodd(ECX, RBP, -12);
+ JLEb(3);
+ POP(RBX);
+ LEAVE_RET();
+ MOVobb(AL, RBX, RCX);
+ break;
+
+ case BPF_LDX|BPF_MSH|BPF_B:
+ MOVid(ECX, ins->k);
+ CMPodd(ECX, RBP, -12);
+ JLEb(5);
+ ZERO_EAX();
+ POP(RBX);
+ LEAVE_RET();
+ ZERO_EDX();
+ MOVobb(DL, RBX, RCX);
+ ANDib(DL, 0xf);
+ SHLib(EDX, 2);
+ break;
+
+ case BPF_LD|BPF_IMM:
+ MOVid(EAX, ins->k);
+ break;
+
+ case BPF_LDX|BPF_IMM:
+ MOVid(EDX, ins->k);
+ break;
+
+ case BPF_LD|BPF_MEM:
+ MOViq(RCX, (uintptr_t)mem);
+ MOVid(ESI, ins->k * 4);
+ MOVobd(EAX, RCX, RSI);
+ break;
+
+ case BPF_LDX|BPF_MEM:
+ MOViq(RCX, (uintptr_t)mem);
+ MOVid(ESI, ins->k * 4);
+ MOVobd(EDX, RCX, RSI);
+ break;
+
+ case BPF_ST:
+ /*
+ * XXX this command and the following could
+ * be optimized if the previous instruction
+ * was already of this type
+ */
+ MOViq(RCX, (uintptr_t)mem);
+ MOVid(ESI, ins->k * 4);
+ MOVomd(RCX, RSI, EAX);
+ break;
+
+ case BPF_STX:
+ MOViq(RCX, (uintptr_t)mem);
+ MOVid(ESI, ins->k * 4);
+ MOVomd(RCX, RSI, EDX);
+ break;
+
+ case BPF_JMP|BPF_JA:
+ JMP(stream.refs[stream.bpf_pc + ins->k] -
+ stream.refs[stream.bpf_pc]);
+ break;
+
+ case BPF_JMP|BPF_JGT|BPF_K:
+ CMPid(EAX, ins->k);
+ /* 5 is the size of the following JMP */
+ JG(stream.refs[stream.bpf_pc + ins->jt] -
+ stream.refs[stream.bpf_pc] + 5 );
+ JMP(stream.refs[stream.bpf_pc + ins->jf] -
+ stream.refs[stream.bpf_pc]);
+ break;
+
+ case BPF_JMP|BPF_JGE|BPF_K:
+ CMPid(EAX, ins->k);
+ JGE(stream.refs[stream.bpf_pc + ins->jt] -
+ stream.refs[stream.bpf_pc] + 5);
+ JMP(stream.refs[stream.bpf_pc + ins->jf] -
+ stream.refs[stream.bpf_pc]);
+ break;
+
+ case BPF_JMP|BPF_JEQ|BPF_K:
+ CMPid(EAX, ins->k);
+ JE(stream.refs[stream.bpf_pc + ins->jt] -
+ stream.refs[stream.bpf_pc] + 5);
+ JMP(stream.refs[stream.bpf_pc + ins->jf] -
+ stream.refs[stream.bpf_pc]);
+ break;
+
+ case BPF_JMP|BPF_JSET|BPF_K:
+ MOVrd(ECX, EAX);
+ ANDid(ECX, ins->k);
+ JE(stream.refs[stream.bpf_pc + ins->jf] -
+ stream.refs[stream.bpf_pc] + 5);
+ JMP(stream.refs[stream.bpf_pc + ins->jt] -
+ stream.refs[stream.bpf_pc]);
+ break;
+
+ case BPF_JMP|BPF_JGT|BPF_X:
+ CMPrd(EAX, EDX);
+ JA(stream.refs[stream.bpf_pc + ins->jt] -
+ stream.refs[stream.bpf_pc] + 5);
+ JMP(stream.refs[stream.bpf_pc + ins->jf] -
+ stream.refs[stream.bpf_pc]);
+ break;
+
+ case BPF_JMP|BPF_JGE|BPF_X:
+ CMPrd(EAX, EDX);
+ JAE(stream.refs[stream.bpf_pc + ins->jt] -
+ stream.refs[stream.bpf_pc] + 5);
+ JMP(stream.refs[stream.bpf_pc + ins->jf] -
+ stream.refs[stream.bpf_pc]);
+ break;
+
+ case BPF_JMP|BPF_JEQ|BPF_X:
+ CMPrd(EAX, EDX);
+ JE(stream.refs[stream.bpf_pc + ins->jt] -
+ stream.refs[stream.bpf_pc] + 5);
+ JMP(stream.refs[stream.bpf_pc + ins->jf] -
+ stream.refs[stream.bpf_pc]);
+ break;
+
+ case BPF_JMP|BPF_JSET|BPF_X:
+ MOVrd(ECX, EAX);
+ ANDrd(ECX, EDX);
+ JE(stream.refs[stream.bpf_pc + ins->jf] -
+ stream.refs[stream.bpf_pc] + 5);
+ JMP(stream.refs[stream.bpf_pc + ins->jt] -
+ stream.refs[stream.bpf_pc]);
+ break;
+
+ case BPF_ALU|BPF_ADD|BPF_X:
+ ADDrd(EAX, EDX);
+ break;
+
+ case BPF_ALU|BPF_SUB|BPF_X:
+ SUBrd(EAX, EDX);
+ break;
+
+ case BPF_ALU|BPF_MUL|BPF_X:
+ MOVrd(ECX, EDX);
+ MULrd(EDX);
+ MOVrd(EDX, ECX);
+ break;
+
+ case BPF_ALU|BPF_DIV|BPF_X:
+ CMPid(EDX, 0);
+ JNEb(5);
+ ZERO_EAX();
+ POP(RBX);
+ LEAVE_RET();
+ MOVrd(ECX, EDX);
+ ZERO_EDX();
+ DIVrd(ECX);
+ MOVrd(EDX, ECX);
+ break;
+
+ case BPF_ALU|BPF_AND|BPF_X:
+ ANDrd(EAX, EDX);
+ break;
+
+ case BPF_ALU|BPF_OR|BPF_X:
+ ORrd(EAX, EDX);
+ break;
+
+ case BPF_ALU|BPF_LSH|BPF_X:
+ MOVrd(ECX, EDX);
+ SHL_CLrb(EAX);
+ break;
+
+ case BPF_ALU|BPF_RSH|BPF_X:
+ MOVrd(ECX, EDX);
+ SHR_CLrb(EAX);
+ break;
+
+ case BPF_ALU|BPF_ADD|BPF_K:
+ ADD_EAXi(ins->k);
+ break;
+
+ case BPF_ALU|BPF_SUB|BPF_K:
+ SUB_EAXi(ins->k);
+ break;
+
+ case BPF_ALU|BPF_MUL|BPF_K:
+ MOVrd(ECX, EDX);
+ MOVid(EDX, ins->k);
+ MULrd(EDX);
+ MOVrd(EDX, ECX);
+ break;
+
+ case BPF_ALU|BPF_DIV|BPF_K:
+ MOVrd(ECX, EDX);
+ ZERO_EDX();
+ MOVid(ESI, ins->k);
+ DIVrd(ESI);
+ MOVrd(EDX, ECX);
+ break;
+
+ case BPF_ALU|BPF_AND|BPF_K:
+ ANDid(EAX, ins->k);
+ break;
+
+ case BPF_ALU|BPF_OR|BPF_K:
+ ORid(EAX, ins->k);
+ break;
+
+ case BPF_ALU|BPF_LSH|BPF_K:
+ SHLib(EAX, (ins->k) & 255);
+ break;
+
+ case BPF_ALU|BPF_RSH|BPF_K:
+ SHRib(EAX, (ins->k) & 255);
+ break;
+
+ case BPF_ALU|BPF_NEG:
+ NEGd(EAX);
+ break;
+
+ case BPF_MISC|BPF_TAX:
+ MOVrd(EDX, EAX);
+ break;
+
+ case BPF_MISC|BPF_TXA:
+ MOVrd(EAX, EDX);
+ break;
+ }
+ ins++;
+ }
+
+ pass++;
+ if (pass == 2)
+ break;
+
+ stream.ibuf = (char *)malloc(stream.cur_ip, M_BPFJIT, M_NOWAIT);
+ if (stream.ibuf == NULL) {
+ free(stream.refs, M_BPFJIT);
+ return NULL;
+ }
+
+ /*
+ * modify the reference table to contain the offsets and
+ * not the lengths of the instructions
+ */
+ for (i = 1; i < nins + 1; i++)
+ stream.refs[i] += stream.refs[i - 1];
+
+ /* Reset the counters */
+ stream.cur_ip = 0;
+ stream.bpf_pc = 0;
+
+ /* the second pass creates the actual code */
+ emitm = emit_code;
+ }
+
+ /*
+ * the reference table is needed only during compilation,
+ * now we can free it
+ */
+ free(stream.refs, M_BPFJIT);
+
+ return (bpf_filter_func)stream.ibuf;
+}
Index: identcpu.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/identcpu.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -L sys/amd64/amd64/identcpu.c -L sys/amd64/amd64/identcpu.c -u -r1.3 -r1.4
--- sys/amd64/amd64/identcpu.c
+++ sys/amd64/amd64/identcpu.c
@@ -39,12 +39,14 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/identcpu.c,v 1.136.2.3 2006/04/24 18:21:54 jkim Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/identcpu.c,v 1.154 2007/05/30 14:23:26 des Exp $");
#include "opt_cpu.h"
#include <sys/param.h>
#include <sys/bus.h>
+#include <sys/cpu.h>
+#include <sys/eventhandler.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/sysctl.h>
@@ -69,6 +71,8 @@
static void print_AMD_info(void);
static void print_AMD_assoc(int i);
+void setPQL2(int *const size, int *const ways);
+static void setPQL2_AMD(int *const size, int *const ways);
int cpu_class;
char machine[] = "amd64";
@@ -93,6 +97,9 @@
{ "Sledgehammer", CPUCLASS_K8 }, /* CPU_SLEDGEHAMMER */
};
+extern int pq_l2size;
+extern int pq_l2nways;
+
void
printcpuinfo(void)
{
@@ -350,7 +357,8 @@
else if (strcmp(cpu_vendor, "GenuineIntel") == 0 &&
(cpu_high >= 4)) {
cpuid_count(4, 0, regs);
- cmp = ((regs[0] & 0xfc000000) >> 26) + 1;
+ if ((regs[0] & 0x1f) != 0)
+ cmp = ((regs[0] >> 26) & 0x3f) + 1;
}
if (cmp > 1)
printf("\n Cores per package: %d", cmp);
@@ -393,6 +401,21 @@
}
+/* Update TSC freq with the value indicated by the caller. */
+static void
+tsc_freq_changed(void *arg, const struct cf_level *level, int status)
+{
+ /* If there was an error during the transition, don't do anything. */
+ if (status != 0)
+ return;
+
+ /* Total setting for this level gives the new frequency in MHz. */
+ hw_clockrate = level->total_set.freq;
+}
+
+EVENTHANDLER_DEFINE(cpufreq_post_change, tsc_freq_changed, NULL,
+ EVENTHANDLER_PRI_ANY);
+
/*
* Final stage of CPU identification. -- Should I check TI?
*/
@@ -521,3 +544,30 @@
print_AMD_l2_assoc((regs[2] >> 12) & 0x0f);
}
}
+
+static void
+setPQL2_AMD(int *const size, int *const ways)
+{
+ if (cpu_exthigh >= 0x80000006) {
+ u_int regs[4];
+
+ do_cpuid(0x80000006, regs);
+ *size = regs[2] >> 16;
+ *ways = (regs[2] >> 12) & 0x0f;
+ switch (*ways) {
+ case 0: /* disabled/not present */
+ case 15: /* fully associative */
+ default: *ways = 1; break; /* reserved configuration */
+ case 4: *ways = 4; break;
+ case 6: *ways = 8; break;
+ case 8: *ways = 16; break;
+ }
+ }
+}
+
+void
+setPQL2(int *const size, int *const ways)
+{
+ if (strcmp(cpu_vendor, "AuthenticAMD") == 0)
+ setPQL2_AMD(size, ways);
+}
Index: tsc.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/tsc.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/amd64/tsc.c -L sys/amd64/amd64/tsc.c -u -r1.1.1.1 -r1.2
--- sys/amd64/amd64/tsc.c
+++ sys/amd64/amd64/tsc.c
@@ -25,11 +25,14 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/tsc.c,v 1.205 2003/11/17 08:58:13 peter Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/tsc.c,v 1.208 2007/06/04 18:25:01 dwmalone Exp $");
#include "opt_clock.h"
#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/cpu.h>
+#include <sys/malloc.h>
#include <sys/systm.h>
#include <sys/sysctl.h>
#include <sys/time.h>
@@ -41,8 +44,11 @@
#include <machine/md_var.h>
#include <machine/specialreg.h>
+#include "cpufreq_if.h"
+
uint64_t tsc_freq;
int tsc_is_broken;
+static eventhandler_tag tsc_levels_tag, tsc_pre_tag, tsc_post_tag;
#ifdef SMP
static int smp_tsc;
@@ -51,14 +57,19 @@
TUNABLE_INT("kern.timecounter.smp_tsc", &smp_tsc);
#endif
+static void tsc_freq_changed(void *arg, const struct cf_level *level,
+ int status);
+static void tsc_freq_changing(void *arg, const struct cf_level *level,
+ int *status);
static unsigned tsc_get_timecount(struct timecounter *tc);
+static void tsc_levels_changed(void *arg, int unit);
static struct timecounter tsc_timecounter = {
tsc_get_timecount, /* get_timecount */
0, /* no poll_pps */
- ~0u, /* counter_mask */
+ ~0u, /* counter_mask */
0, /* frequency */
- "TSC", /* name */
+ "TSC", /* name */
800, /* quality (adjusted in code) */
};
@@ -77,8 +88,23 @@
tsc_freq = tscval[1] - tscval[0];
if (bootverbose)
printf("TSC clock: %lu Hz\n", tsc_freq);
-}
+ /*
+ * Inform CPU accounting about our boot-time clock rate. Once the
+ * system is finished booting, we will get the real max clock rate
+ * via tsc_freq_max(). This also will be updated if someone loads
+ * a cpufreq driver after boot that discovers a new max frequency.
+ */
+ set_cputicker(rdtsc, tsc_freq, 1);
+
+ /* Register to find out about changes in CPU frequency. */
+ tsc_pre_tag = EVENTHANDLER_REGISTER(cpufreq_pre_change,
+ tsc_freq_changing, NULL, EVENTHANDLER_PRI_FIRST);
+ tsc_post_tag = EVENTHANDLER_REGISTER(cpufreq_post_change,
+ tsc_freq_changed, NULL, EVENTHANDLER_PRI_FIRST);
+ tsc_levels_tag = EVENTHANDLER_REGISTER(cpufreq_levels_changed,
+ tsc_levels_changed, NULL, EVENTHANDLER_PRI_ANY);
+}
void
init_TSC_tc(void)
@@ -103,6 +129,72 @@
}
}
+/*
+ * When cpufreq levels change, find out about the (new) max frequency. We
+ * use this to update CPU accounting in case it got a lower estimate at boot.
+ */
+static void
+tsc_levels_changed(void *arg, int unit)
+{
+ device_t cf_dev;
+ struct cf_level *levels;
+ int count, error;
+ uint64_t max_freq;
+
+ /* Only use values from the first CPU, assuming all are equal. */
+ if (unit != 0)
+ return;
+
+ /* Find the appropriate cpufreq device instance. */
+ cf_dev = devclass_get_device(devclass_find("cpufreq"), unit);
+ if (cf_dev == NULL) {
+ printf("tsc_levels_changed() called but no cpufreq device?\n");
+ return;
+ }
+
+ /* Get settings from the device and find the max frequency. */
+ count = 64;
+ levels = malloc(count * sizeof(*levels), M_TEMP, M_NOWAIT);
+ if (levels == NULL)
+ return;
+ error = CPUFREQ_LEVELS(cf_dev, levels, &count);
+ if (error == 0 && count != 0) {
+ max_freq = (uint64_t)levels[0].total_set.freq * 1000000;
+ set_cputicker(rdtsc, max_freq, 1);
+ } else
+ printf("tsc_levels_changed: no max freq found\n");
+ free(levels, M_TEMP);
+}
+
+/*
+ * If the TSC timecounter is in use, veto the pending change. It may be
+ * possible in the future to handle a dynamically-changing timecounter rate.
+ */
+static void
+tsc_freq_changing(void *arg, const struct cf_level *level, int *status)
+{
+
+ if (*status != 0 || timecounter != &tsc_timecounter)
+ return;
+
+ printf("timecounter TSC must not be in use when "
+ "changing frequencies; change denied\n");
+ *status = EBUSY;
+}
+
+/* Update TSC freq with the value indicated by the caller. */
+static void
+tsc_freq_changed(void *arg, const struct cf_level *level, int status)
+{
+ /* If there was an error during the transition, don't do anything. */
+ if (status != 0)
+ return;
+
+ /* Total setting for this level gives the new frequency in MHz. */
+ tsc_freq = (uint64_t)level->total_set.freq * 1000000;
+ tsc_timecounter.tc_frequency = tsc_freq;
+}
+
static int
sysctl_machdep_tsc_freq(SYSCTL_HANDLER_ARGS)
{
@@ -112,7 +204,7 @@
if (tsc_timecounter.tc_frequency == 0)
return (EOPNOTSUPP);
freq = tsc_freq;
- error = sysctl_handle_int(oidp, &freq, sizeof(freq), req);
+ error = sysctl_handle_quad(oidp, &freq, 0, req);
if (error == 0 && req->newptr != NULL) {
tsc_freq = freq;
tsc_timecounter.tc_frequency = tsc_freq;
@@ -120,8 +212,8 @@
return (error);
}
-SYSCTL_PROC(_machdep, OID_AUTO, tsc_freq, CTLTYPE_LONG | CTLFLAG_RW,
- 0, sizeof(u_int), sysctl_machdep_tsc_freq, "IU", "");
+SYSCTL_PROC(_machdep, OID_AUTO, tsc_freq, CTLTYPE_QUAD | CTLFLAG_RW,
+ 0, sizeof(u_int), sysctl_machdep_tsc_freq, "QU", "");
static unsigned
tsc_get_timecount(struct timecounter *tc)
Index: initcpu.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/initcpu.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/amd64/amd64/initcpu.c -L sys/amd64/amd64/initcpu.c -u -r1.2 -r1.3
--- sys/amd64/amd64/initcpu.c
+++ sys/amd64/amd64/initcpu.c
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/initcpu.c,v 1.48.8.2 2006/07/01 09:06:40 davidxu Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/initcpu.c,v 1.50 2006/06/19 22:59:28 davidxu Exp $");
#include "opt_cpu.h"
Index: bios.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/bios.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/amd64/bios.c -L sys/amd64/amd64/bios.c -u -r1.1.1.1 -r1.2
--- sys/amd64/amd64/bios.c
+++ sys/amd64/amd64/bios.c
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/bios.c,v 1.72 2004/09/24 01:08:34 peter Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/bios.c,v 1.73 2005/07/21 09:48:36 phk Exp $");
/*
* Subset of the i386 bios support code. We cannot make bios16 nor bios32
@@ -93,18 +93,3 @@
}
return(0);
}
-
-const u_char *
-bios_string(u_int from, u_int to, const u_char *string, int len)
-{
- const char *t, *te;
-
- if (len == 0)
- len = strlen(string);
- t = (const char *)(KERNBASE + from);
- te = (const char *)(KERNBASE + to);
- for (; t <= te; t++)
- if (!memcmp(string, t, len))
- return (t);
- return (NULL);
-}
Index: legacy.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/legacy.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/amd64/legacy.c -L sys/amd64/amd64/legacy.c -u -r1.1.1.1 -r1.2
--- sys/amd64/amd64/legacy.c
+++ sys/amd64/amd64/legacy.c
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/legacy.c,v 1.59 2005/02/15 07:26:28 njl Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/legacy.c,v 1.61 2007/09/30 11:05:13 marius Exp $");
/*
* This code implements a system driver for legacy systems that do not
@@ -105,10 +105,10 @@
{
/*
- * Add child device with order of 1 so it gets probed
- * after ACPI (which is at order 0.
+ * Add child device with order of 11 so it gets probed
+ * after ACPI (which is at order 10).
*/
- if (BUS_ADD_CHILD(parent, 1, "legacy", 0) == NULL)
+ if (BUS_ADD_CHILD(parent, 11, "legacy", 0) == NULL)
panic("legacy: could not attach");
}
@@ -207,6 +207,9 @@
struct legacy_device *atdev = DEVTOAT(child);
switch (which) {
+ case LEGACY_IVAR_PCIDOMAIN:
+ *result = 0;
+ break;
case LEGACY_IVAR_PCIBUS:
*result = atdev->lg_pcibus;
break;
@@ -223,6 +226,8 @@
struct legacy_device *atdev = DEVTOAT(child);
switch (which) {
+ case LEGACY_IVAR_PCIDOMAIN:
+ return EINVAL;
case LEGACY_IVAR_PCIBUS:
atdev->lg_pcibus = value;
break;
Index: machdep.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/machdep.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/amd64/amd64/machdep.c -L sys/amd64/amd64/machdep.c -u -r1.2 -r1.3
--- sys/amd64/amd64/machdep.c
+++ sys/amd64/amd64/machdep.c
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/machdep.c,v 1.638.2.6 2006/03/20 19:56:43 jhb Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/machdep.c,v 1.675.2.2.2.1 2008/01/19 18:15:01 kib Exp $");
#include "opt_atalk.h"
#include "opt_atpic.h"
@@ -61,6 +61,7 @@
#include <sys/buf.h>
#include <sys/bus.h>
#include <sys/callout.h>
+#include <sys/clock.h>
#include <sys/cons.h>
#include <sys/cpu.h>
#include <sys/eventhandler.h>
@@ -124,9 +125,11 @@
#include <machine/smp.h>
#endif
-#include <dev/ic/i8259.h>
+#ifdef DEV_ATPIC
#include <amd64/isa/icu.h>
+#else
#include <machine/apicvar.h>
+#endif
#include <isa/isareg.h>
#include <isa/rtc.h>
@@ -135,7 +138,6 @@
CTASSERT(offsetof(struct pcpu, pc_curthread) == 0);
extern u_int64_t hammer_time(u_int64_t, u_int64_t);
-extern void dblfault_handler(void);
extern void printcpuinfo(void); /* XXX header file */
extern void identify_cpu(void);
@@ -153,6 +155,10 @@
extern vm_offset_t ksym_start, ksym_end;
#endif
+/* Intel ICH registers */
+#define ICH_PMBASE 0x400
+#define ICH_SMI_EN ICH_PMBASE + 0x30
+
int _udatasel, _ucodesel, _ucode32sel;
int cold = 1;
@@ -160,8 +166,16 @@
long Maxmem = 0;
long realmem = 0;
-vm_paddr_t phys_avail[20];
-vm_paddr_t dump_avail[20];
+/*
+ * The number of PHYSMAP entries must be one less than the number of
+ * PHYSSEG entries because the PHYSMAP entry that spans the largest
+ * physical address that is accessible by ISA DMA is split into two
+ * PHYSSEG entries.
+ */
+#define PHYSMAP_SIZE (2 * (VM_PHYSSEG_MAX - 1))
+
+vm_paddr_t phys_avail[PHYSMAP_SIZE + 2];
+vm_paddr_t dump_avail[PHYSMAP_SIZE + 2];
/* must be 2 less so 0 0 can signal end of chunks */
#define PHYS_AVAIL_ARRAY_END ((sizeof(phys_avail) / sizeof(phys_avail[0])) - 2)
@@ -182,6 +196,27 @@
cpu_startup(dummy)
void *dummy;
{
+ char *sysenv;
+
+ /*
+ * On MacBooks, we need to disallow the legacy USB circuit to
+ * generate an SMI# because this can cause several problems,
+ * namely: incorrect CPU frequency detection and failure to
+ * start the APs.
+ * We do this by disabling a bit in the SMI_EN (SMI Control and
+ * Enable register) of the Intel ICH LPC Interface Bridge.
+ */
+ sysenv = getenv("smbios.system.product");
+ if (sysenv != NULL) {
+ if (strncmp(sysenv, "MacBook", 7) == 0) {
+ if (bootverbose)
+ printf("Disabling LEGACY_USB_EN bit on "
+ "Intel ICH.\n");
+ outl(ICH_SMI_EN, inl(ICH_SMI_EN) & ~0x8);
+ }
+ freeenv(sysenv);
+ }
+
/*
* Good {morning,afternoon,evening,night}.
*/
@@ -191,8 +226,8 @@
#ifdef PERFMON
perfmon_init();
#endif
- printf("real memory = %ju (%ju MB)\n", ptoa((uintmax_t)Maxmem),
- ptoa((uintmax_t)Maxmem) / 1048576);
+ printf("usable memory = %ju (%ju MB)\n", ptoa((uintmax_t)physmem),
+ ptoa((uintmax_t)physmem) / 1048576);
realmem = Maxmem;
/*
* Display any holes after the first chunk of extended memory.
@@ -215,7 +250,7 @@
vm_ksubmap_init(&kmi);
- printf("avail memory = %ju (%ju MB)\n",
+ printf("avail memory = %ju (%ju MB)\n",
ptoa((uintmax_t)cnt.v_free_count),
ptoa((uintmax_t)cnt.v_free_count) / 1048576);
@@ -239,11 +274,7 @@
* specified pc, psl.
*/
void
-sendsig(catcher, sig, mask, code)
- sig_t catcher;
- int sig;
- sigset_t *mask;
- u_long code;
+sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
{
struct sigframe sf, *sfp;
struct proc *p;
@@ -251,11 +282,13 @@
struct sigacts *psp;
char *sp;
struct trapframe *regs;
+ int sig;
int oonstack;
td = curthread;
p = td->td_proc;
PROC_LOCK_ASSERT(p, MA_OWNED);
+ sig = ksi->ksi_signo;
psp = p->p_sigacts;
mtx_assert(&psp->ps_mtx, MA_OWNED);
regs = td->td_frame;
@@ -299,13 +332,13 @@
sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher;
/* Fill in POSIX parts */
- sf.sf_si.si_signo = sig;
- sf.sf_si.si_code = code;
- regs->tf_rcx = regs->tf_addr; /* arg 4 in %rcx */
+ sf.sf_si = ksi->ksi_info;
+ sf.sf_si.si_signo = sig; /* maybe a translated signal */
+ regs->tf_rcx = (register_t)ksi->ksi_addr; /* arg 4 in %rcx */
} else {
/* Old FreeBSD-style arguments. */
- regs->tf_rsi = code; /* arg 2 in %rsi */
- regs->tf_rcx = regs->tf_addr; /* arg 4 in %rcx */
+ regs->tf_rsi = ksi->ksi_code; /* arg 2 in %rsi */
+ regs->tf_rcx = (register_t)ksi->ksi_addr; /* arg 4 in %rcx */
sf.sf_ahu.sf_handler = catcher;
}
mtx_unlock(&psp->ps_mtx);
@@ -331,28 +364,6 @@
}
/*
- * Build siginfo_t for SA thread
- */
-void
-cpu_thread_siginfo(int sig, u_long code, siginfo_t *si)
-{
- struct proc *p;
- struct thread *td;
- struct trapframe *regs;
-
- td = curthread;
- p = td->td_proc;
- regs = td->td_frame;
- PROC_LOCK_ASSERT(p, MA_OWNED);
-
- bzero(si, sizeof(*si));
- si->si_signo = sig;
- si->si_code = code;
- si->si_addr = (void *)regs->tf_addr;
- /* XXXKSE fill other fields */
-}
-
-/*
* System call to cleanup state after a signal
* has been taken. Reset signal mask and
* stack state from context left by sendsig (above).
@@ -367,7 +378,7 @@
sigreturn(td, uap)
struct thread *td;
struct sigreturn_args /* {
- const __ucontext *sigcntxp;
+ const struct __ucontext *sigcntxp;
} */ *uap;
{
ucontext_t uc;
@@ -376,6 +387,7 @@
const ucontext_t *ucp;
long rflags;
int cs, error, ret;
+ ksiginfo_t ksi;
error = copyin(uap->sigcntxp, &uc, sizeof(uc));
if (error != 0)
@@ -409,7 +421,12 @@
cs = ucp->uc_mcontext.mc_cs;
if (!CS_SECURE(cs)) {
printf("sigreturn: cs = 0x%x\n", cs);
- trapsignal(td, SIGBUS, T_PROTFLT);
+ ksiginfo_init_trap(&ksi);
+ ksi.ksi_signo = SIGBUS;
+ ksi.ksi_code = BUS_OBJERR;
+ ksi.ksi_trapno = T_PROTFLT;
+ ksi.ksi_addr = (void *)regs->tf_rip;
+ trapsignal(td, &ksi);
return (EINVAL);
}
@@ -473,9 +490,9 @@
#ifdef SMP
/* Schedule ourselves on the indicated cpu. */
- mtx_lock_spin(&sched_lock);
+ thread_lock(curthread);
sched_bind(curthread, cpu_id);
- mtx_unlock_spin(&sched_lock);
+ thread_unlock(curthread);
#endif
/* Calibrate by measuring a short delay. */
@@ -486,9 +503,9 @@
intr_restore(reg);
#ifdef SMP
- mtx_lock_spin(&sched_lock);
+ thread_lock(curthread);
sched_unbind(curthread);
- mtx_unlock_spin(&sched_lock);
+ thread_unlock(curthread);
#endif
/*
@@ -527,6 +544,7 @@
* help lock contention somewhat, and this is critical for HTT. -Peter
*/
static int cpu_idle_hlt = 1;
+TUNABLE_INT("machdep.cpu_idle_hlt", &cpu_idle_hlt);
SYSCTL_INT(_machdep, OID_AUTO, cpu_idle_hlt, CTLFLAG_RW,
&cpu_idle_hlt, 0, "Idle loop HLT enable");
@@ -646,26 +664,6 @@
load_cr0(cr0);
}
-static int
-sysctl_machdep_adjkerntz(SYSCTL_HANDLER_ARGS)
-{
- int error;
- error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2,
- req);
- if (!error && req->newptr)
- resettodr();
- return (error);
-}
-
-SYSCTL_PROC(_machdep, CPU_ADJKERNTZ, adjkerntz, CTLTYPE_INT|CTLFLAG_RW,
- &adjkerntz, 0, sysctl_machdep_adjkerntz, "I", "");
-
-SYSCTL_INT(_machdep, CPU_DISRTCSET, disable_rtc_set,
- CTLFLAG_RW, &disable_rtc_set, 0, "");
-
-SYSCTL_INT(_machdep, CPU_WALLCLOCK, wall_cmos_clock,
- CTLFLAG_RW, &wall_cmos_clock, 0, "");
-
/*
* Initialize amd64 and configure to run kernel
*/
@@ -757,6 +755,15 @@
0, /* long */
0, /* default 32 vs 16 bit size */
0 /* limit granularity (byte/page units)*/ },
+/* GUGS32_SEL 8 32 bit GS Descriptor for user */
+{ 0x0, /* segment base address */
+ 0xfffff, /* length - all address space */
+ SDT_MEMRWA, /* segment type */
+ SEL_UPL, /* segment descriptor priority level */
+ 1, /* segment descriptor present */
+ 0, /* long */
+ 1, /* default 32 vs 16 bit size */
+ 1 /* limit granularity (byte/page units)*/ },
};
void
@@ -780,8 +787,6 @@
ip->gd_hioffset = ((uintptr_t)func)>>16 ;
}
-#define IDTVEC(name) __CONCAT(X,name)
-
extern inthand_t
IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl),
IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(fpusegm),
@@ -850,8 +855,6 @@
}
#endif
-#define PHYSMAP_SIZE (2 * 20)
-
u_int basemem;
/*
@@ -870,7 +873,7 @@
static void
getmemsize(caddr_t kmdp, u_int64_t first)
{
- int i, physmap_idx, pa_indx, da_indx;
+ int i, off, physmap_idx, pa_indx, da_indx;
vm_paddr_t pa, physmap[PHYSMAP_SIZE];
u_long physmem_tunable;
pt_entry_t *pte;
@@ -912,7 +915,7 @@
if (smap->base < physmap[i + 1]) {
if (boothowto & RB_VERBOSE)
printf(
- "Overlapping or non-montonic memory region, ignoring second region\n");
+ "Overlapping or non-monotonic memory region, ignoring second region\n");
continue;
}
}
@@ -965,17 +968,17 @@
if (TUNABLE_ULONG_FETCH("hw.physmem", &physmem_tunable))
Maxmem = atop(physmem_tunable);
+ /*
+ * Don't allow MAXMEM or hw.physmem to extend the amount of memory
+ * in the system.
+ */
+ if (Maxmem > atop(physmap[physmap_idx + 1]))
+ Maxmem = atop(physmap[physmap_idx + 1]);
+
if (atop(physmap[physmap_idx + 1]) != Maxmem &&
(boothowto & RB_VERBOSE))
printf("Physical memory use set to %ldK\n", Maxmem * 4);
- /*
- * If Maxmem has been increased beyond what the system has detected,
- * extend the last memory segment to the new limit.
- */
- if (atop(physmap[physmap_idx + 1]) < Maxmem)
- physmap[physmap_idx + 1] = ptoa((vm_paddr_t)Maxmem);
-
/* call pmap initialization to make new kernel address space */
pmap_bootstrap(&first);
@@ -1133,14 +1136,17 @@
/* Trim off space for the message buffer. */
phys_avail[pa_indx] -= round_page(MSGBUF_SIZE);
- avail_end = phys_avail[pa_indx];
+ /* Map the message buffer. */
+ for (off = 0; off < round_page(MSGBUF_SIZE); off += PAGE_SIZE)
+ pmap_kenter((vm_offset_t)msgbufp + off, phys_avail[pa_indx] +
+ off);
}
u_int64_t
hammer_time(u_int64_t modulep, u_int64_t physfree)
{
caddr_t kmdp;
- int gsel_tss, off, x;
+ int gsel_tss, x;
struct pcpu *pc;
u_int64_t msr;
char *env;
@@ -1155,7 +1161,7 @@
* This may be done better later if it gets more high level
* components in it. If so just link td->td_proc here.
*/
- proc_linkup(&proc0, &ksegrp0, &thread0);
+ proc_linkup0(&proc0, &thread0);
preload_metadata = (caddr_t)(uintptr_t)(modulep + KERNBASE);
preload_bootstrap_relocate(KERNBASE);
@@ -1208,7 +1214,6 @@
* under witness.
*/
mutex_init();
- mtx_init(&clock_lock, "clk", NULL, MTX_SPIN);
mtx_init(&icu_lock, "icu", NULL, MTX_SPIN | MTX_NOWITNESS);
/* exceptions */
@@ -1216,7 +1221,7 @@
setidt(x, &IDTVEC(rsvd), SDT_SYSIGT, SEL_KPL, 0);
setidt(IDT_DE, &IDTVEC(div), SDT_SYSIGT, SEL_KPL, 0);
setidt(IDT_DB, &IDTVEC(dbg), SDT_SYSIGT, SEL_KPL, 0);
- setidt(IDT_NMI, &IDTVEC(nmi), SDT_SYSIGT, SEL_KPL, 0);
+ setidt(IDT_NMI, &IDTVEC(nmi), SDT_SYSIGT, SEL_KPL, 1);
setidt(IDT_BP, &IDTVEC(bpt), SDT_SYSIGT, SEL_UPL, 0);
setidt(IDT_OF, &IDTVEC(ofl), SDT_SYSIGT, SEL_KPL, 0);
setidt(IDT_BR, &IDTVEC(bnd), SDT_SYSIGT, SEL_KPL, 0);
@@ -1239,6 +1244,12 @@
lidt(&r_idt);
/*
+ * Initialize the i8254 before the console so that console
+ * initialization can use DELAY().
+ */
+ i8254_init();
+
+ /*
* Initialize the console before we print anything out.
*/
cninit();
@@ -1249,19 +1260,7 @@
atpic_startup();
#else
/* Reset and mask the atpics and leave them shut down. */
- outb(IO_ICU1, ICW1_RESET | ICW1_IC4);
- outb(IO_ICU1 + ICU_IMR_OFFSET, IDT_IO_INTS);
- outb(IO_ICU1 + ICU_IMR_OFFSET, 1 << 2);
- outb(IO_ICU1 + ICU_IMR_OFFSET, ICW4_8086);
- outb(IO_ICU1 + ICU_IMR_OFFSET, 0xff);
- outb(IO_ICU1, OCW3_SEL | OCW3_RR);
-
- outb(IO_ICU2, ICW1_RESET | ICW1_IC4);
- outb(IO_ICU2 + ICU_IMR_OFFSET, IDT_IO_INTS + 8);
- outb(IO_ICU2 + ICU_IMR_OFFSET, 2);
- outb(IO_ICU2 + ICU_IMR_OFFSET, ICW4_8086);
- outb(IO_ICU2 + ICU_IMR_OFFSET, 0xff);
- outb(IO_ICU2, OCW3_SEL | OCW3_RR);
+ atpic_reset();
/*
* Point the ICU spurious interrupt vectors at the APIC spurious
@@ -1315,10 +1314,6 @@
/* now running on new page tables, configured,and u/iom is accessible */
- /* Map the message buffer. */
- for (off = 0; off < round_page(MSGBUF_SIZE); off += PAGE_SIZE)
- pmap_kenter((vm_offset_t)msgbufp + off, avail_end + off);
-
msgbufinit(msgbufp, MSGBUF_SIZE);
fpuinit();
@@ -1525,7 +1520,7 @@
penv_xmm->en_rip = penv_fpreg->en_rip;
penv_xmm->en_rdp = penv_fpreg->en_rdp;
penv_xmm->en_mxcsr = penv_fpreg->en_mxcsr;
- penv_xmm->en_mxcsr_mask = penv_fpreg->en_mxcsr_mask;
+ penv_xmm->en_mxcsr_mask = penv_fpreg->en_mxcsr_mask & cpu_mxcsr_mask;
/* FPU registers */
for (i = 0; i < 8; ++i)
@@ -1652,6 +1647,7 @@
static int
set_fpcontext(struct thread *td, const mcontext_t *mcp)
{
+ struct savefpu *fpstate;
if (mcp->mc_fpformat == _MC_FPFMT_NODEV)
return (0);
@@ -1667,7 +1663,9 @@
* be called with interrupts disabled.
* XXX obsolete on trap-16 systems?
*/
- fpusetregs(td, (struct savefpu *)&mcp->mc_fpstate);
+ fpstate = (struct savefpu *)&mcp->mc_fpstate;
+ fpstate->sv_env.en_mxcsr &= cpu_mxcsr_mask;
+ fpusetregs(td, fpstate);
} else
return (EINVAL);
return (0);
@@ -1734,7 +1732,6 @@
{
struct pcb *pcb;
int i;
- u_int64_t mask1, mask2;
if (td == NULL) {
load_dr0(dbregs->dr[0]);
@@ -1751,10 +1748,13 @@
* TRCTRAP or a general protection fault right here.
* Upper bits of dr6 and dr7 must not be set
*/
- for (i = 0, mask1 = 0x3<<16, mask2 = 0x2<<16; i < 8;
- i++, mask1 <<= 2, mask2 <<= 2)
- if ((dbregs->dr[7] & mask1) == mask2)
+ for (i = 0; i < 4; i++) {
+ if (DBREG_DR7_ACCESS(dbregs->dr[7], i) == 0x02)
+ return (EINVAL);
+ if (td->td_frame->tf_cs == _ucode32sel &&
+ DBREG_DR7_LEN(dbregs->dr[7], i) == DBREG_DR7_LEN_8)
return (EINVAL);
+ }
if ((dbregs->dr[6] & 0xffffffff00000000ul) != 0 ||
(dbregs->dr[7] & 0xffffffff00000000ul) != 0)
return (EINVAL);
@@ -1775,22 +1775,22 @@
* from within kernel mode?
*/
- if (dbregs->dr[7] & 0x3) {
+ if (DBREG_DR7_ENABLED(dbregs->dr[7], 0)) {
/* dr0 is enabled */
if (dbregs->dr[0] >= VM_MAXUSER_ADDRESS)
return (EINVAL);
}
- if (dbregs->dr[7] & 0x3<<2) {
+ if (DBREG_DR7_ENABLED(dbregs->dr[7], 1)) {
/* dr1 is enabled */
if (dbregs->dr[1] >= VM_MAXUSER_ADDRESS)
return (EINVAL);
}
- if (dbregs->dr[7] & 0x3<<4) {
+ if (DBREG_DR7_ENABLED(dbregs->dr[7], 2)) {
/* dr2 is enabled */
if (dbregs->dr[2] >= VM_MAXUSER_ADDRESS)
return (EINVAL);
}
- if (dbregs->dr[7] & 0x3<<6) {
+ if (DBREG_DR7_ENABLED(dbregs->dr[7], 3)) {
/* dr3 is enabled */
if (dbregs->dr[3] >= VM_MAXUSER_ADDRESS)
return (EINVAL);
@@ -1874,9 +1874,8 @@
addr[nbp++] = (caddr_t)rdr3();
}
- for (i=0; i<nbp; i++) {
- if (addr[i] <
- (caddr_t)VM_MAXUSER_ADDRESS) {
+ for (i = 0; i < nbp; i++) {
+ if (addr[i] < (caddr_t)VM_MAXUSER_ADDRESS) {
/*
* addr[i] is in user space
*/
Index: pmap.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/pmap.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/amd64/pmap.c -L sys/amd64/amd64/pmap.c -u -r1.1.1.1 -r1.2
--- sys/amd64/amd64/pmap.c
+++ sys/amd64/amd64/pmap.c
@@ -77,7 +77,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/pmap.c,v 1.516.2.4 2005/11/19 20:31:30 alc Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/pmap.c,v 1.590.2.3.2.1 2008/01/19 18:15:01 kib Exp $");
/*
* Manages physical address maps.
@@ -106,6 +106,7 @@
*/
#include "opt_msgbuf.h"
+#include "opt_pmap.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -153,15 +154,20 @@
#endif
#if !defined(PMAP_DIAGNOSTIC)
-#define PMAP_INLINE __inline
+#define PMAP_INLINE __gnu89_inline
#else
#define PMAP_INLINE
#endif
+#define PV_STATS
+#ifdef PV_STATS
+#define PV_STAT(x) do { x ; } while (0)
+#else
+#define PV_STAT(x) do { } while (0)
+#endif
+
struct pmap kernel_pmap_store;
-vm_paddr_t avail_start; /* PA of first available physical page */
-vm_paddr_t avail_end; /* PA of last available physical page */
vm_offset_t virtual_avail; /* VA of first avail page (after kernel bss) */
vm_offset_t virtual_end; /* VA of last avail page (end of kernel AS) */
@@ -173,7 +179,7 @@
static u_int64_t KPTphys; /* phys addr of kernel level 1 */
static u_int64_t KPDphys; /* phys addr of kernel level 2 */
-static u_int64_t KPDPphys; /* phys addr of kernel level 3 */
+u_int64_t KPDPphys; /* phys addr of kernel level 3 */
u_int64_t KPML4phys; /* phys addr of kernel level 4 */
static u_int64_t DMPDphys; /* phys addr of direct mapped level 2 */
@@ -182,10 +188,8 @@
/*
* Data for the pv entry allocation mechanism
*/
-static uma_zone_t pvzone;
-static struct vm_object pvzone_obj;
static int pv_entry_count = 0, pv_entry_max = 0, pv_entry_high_water = 0;
-int pmap_pagedaemon_waken;
+static int shpgperproc = PMAP_SHPGPERPROC;
/*
* All those kernel PT submaps that BSD is so fond of
@@ -199,23 +203,28 @@
*/
static caddr_t crashdumpmap;
-static PMAP_INLINE void free_pv_entry(pv_entry_t pv);
-static pv_entry_t get_pv_entry(void);
-static void pmap_clear_ptes(vm_page_t m, long bit);
+static void free_pv_entry(pmap_t pmap, pv_entry_t pv);
+static pv_entry_t get_pv_entry(pmap_t locked_pmap, int try);
+static vm_page_t pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va,
+ vm_page_t m, vm_prot_t prot, vm_page_t mpte);
static int pmap_remove_pte(pmap_t pmap, pt_entry_t *ptq,
- vm_offset_t sva, pd_entry_t ptepde);
-static void pmap_remove_page(pmap_t pmap, vm_offset_t va, pd_entry_t *pde);
+ vm_offset_t sva, pd_entry_t ptepde, vm_page_t *free);
+static void pmap_remove_page(pmap_t pmap, vm_offset_t va, pd_entry_t *pde,
+ vm_page_t *free);
static void pmap_remove_entry(struct pmap *pmap, vm_page_t m,
vm_offset_t va);
static void pmap_insert_entry(pmap_t pmap, vm_offset_t va, vm_page_t m);
+static boolean_t pmap_try_insert_pv_entry(pmap_t pmap, vm_offset_t va,
+ vm_page_t m);
static vm_page_t pmap_allocpde(pmap_t pmap, vm_offset_t va, int flags);
static vm_page_t pmap_allocpte(pmap_t pmap, vm_offset_t va, int flags);
static vm_page_t _pmap_allocpte(pmap_t pmap, vm_pindex_t ptepindex, int flags);
-static int _pmap_unwire_pte_hold(pmap_t pmap, vm_offset_t va, vm_page_t m);
-static int pmap_unuse_pt(pmap_t, vm_offset_t, pd_entry_t);
+static int _pmap_unwire_pte_hold(pmap_t pmap, vm_offset_t va, vm_page_t m,
+ vm_page_t* free);
+static int pmap_unuse_pt(pmap_t, vm_offset_t, pd_entry_t, vm_page_t *);
static vm_offset_t pmap_kmem_choose(vm_offset_t addr);
CTASSERT(1 << PDESHIFT == sizeof(pd_entry_t));
@@ -388,38 +397,38 @@
}
static u_int64_t
-allocpages(int n)
+allocpages(vm_paddr_t *firstaddr, int n)
{
u_int64_t ret;
- ret = avail_start;
+ ret = *firstaddr;
bzero((void *)ret, n * PAGE_SIZE);
- avail_start += n * PAGE_SIZE;
+ *firstaddr += n * PAGE_SIZE;
return (ret);
}
static void
-create_pagetables(void)
+create_pagetables(vm_paddr_t *firstaddr)
{
int i;
/* Allocate pages */
- KPTphys = allocpages(NKPT);
- KPML4phys = allocpages(1);
- KPDPphys = allocpages(NKPML4E);
- KPDphys = allocpages(NKPDPE);
+ KPTphys = allocpages(firstaddr, NKPT);
+ KPML4phys = allocpages(firstaddr, 1);
+ KPDPphys = allocpages(firstaddr, NKPML4E);
+ KPDphys = allocpages(firstaddr, NKPDPE);
ndmpdp = (ptoa(Maxmem) + NBPDP - 1) >> PDPSHIFT;
if (ndmpdp < 4) /* Minimum 4GB of dirmap */
ndmpdp = 4;
- DMPDPphys = allocpages(NDMPML4E);
- DMPDphys = allocpages(ndmpdp);
+ DMPDPphys = allocpages(firstaddr, NDMPML4E);
+ DMPDphys = allocpages(firstaddr, ndmpdp);
dmaplimit = (vm_paddr_t)ndmpdp << PDPSHIFT;
/* Fill in the underlying page table pages */
/* Read-only from zero to physfree */
/* XXX not fully used, underneath 2M pages */
- for (i = 0; (i << PAGE_SHIFT) < avail_start; i++) {
+ for (i = 0; (i << PAGE_SHIFT) < *firstaddr; i++) {
((pt_entry_t *)KPTphys)[i] = i << PAGE_SHIFT;
((pt_entry_t *)KPTphys)[i] |= PG_RW | PG_V | PG_G;
}
@@ -432,7 +441,7 @@
/* Map from zero to end of allocations under 2M pages */
/* This replaces some of the KPTphys entries above */
- for (i = 0; (i << PDRSHIFT) < avail_start; i++) {
+ for (i = 0; (i << PDRSHIFT) < *firstaddr; i++) {
((pd_entry_t *)KPDphys)[i] = i << PDRSHIFT;
((pd_entry_t *)KPDphys)[i] |= PG_RW | PG_V | PG_PS | PG_G;
}
@@ -480,21 +489,17 @@
* (physical) address starting relative to 0]
*/
void
-pmap_bootstrap(firstaddr)
- vm_paddr_t *firstaddr;
+pmap_bootstrap(vm_paddr_t *firstaddr)
{
vm_offset_t va;
pt_entry_t *pte, *unused;
- avail_start = *firstaddr;
-
/*
* Create an initial set of page tables to run the kernel in.
*/
- create_pagetables();
- *firstaddr = avail_start;
+ create_pagetables(firstaddr);
- virtual_avail = (vm_offset_t) KERNBASE + avail_start;
+ virtual_avail = (vm_offset_t) KERNBASE + *firstaddr;
virtual_avail = pmap_kmem_choose(virtual_avail);
virtual_end = VM_MAX_KERNEL_ADDRESS;
@@ -510,7 +515,7 @@
PMAP_LOCK_INIT(kernel_pmap);
kernel_pmap->pm_pml4 = (pdp_entry_t *) (KERNBASE + KPML4phys);
kernel_pmap->pm_active = -1; /* don't allow deactivation */
- TAILQ_INIT(&kernel_pmap->pm_pvlist);
+ TAILQ_INIT(&kernel_pmap->pm_pvchunk);
nkpt = NKPT;
/*
@@ -543,6 +548,51 @@
*CMAP1 = 0;
invltlb();
+
+ /* Initialize the PAT MSR. */
+ pmap_init_pat();
+}
+
+/*
+ * Setup the PAT MSR.
+ */
+void
+pmap_init_pat(void)
+{
+ uint64_t pat_msr;
+
+ /* Bail if this CPU doesn't implement PAT. */
+ if (!(cpu_feature & CPUID_PAT))
+ panic("no PAT??");
+
+#ifdef PAT_WORKS
+ /*
+ * Leave the indices 0-3 at the default of WB, WT, UC, and UC-.
+ * Program 4 and 5 as WP and WC.
+ * Leave 6 and 7 as UC and UC-.
+ */
+ pat_msr = rdmsr(MSR_PAT);
+ pat_msr &= ~(PAT_MASK(4) | PAT_MASK(5));
+ pat_msr |= PAT_VALUE(4, PAT_WRITE_PROTECTED) |
+ PAT_VALUE(5, PAT_WRITE_COMBINING);
+#else
+ /*
+ * Due to some Intel errata, we can only safely use the lower 4
+ * PAT entries. Thus, just replace PAT Index 2 with WC instead
+ * of UC-.
+ *
+ * Intel Pentium III Processor Specification Update
+ * Errata E.27 (Upper Four PAT Entries Not Usable With Mode B
+ * or Mode C Paging)
+ *
+ * Intel Pentium IV Processor Specification Update
+ * Errata N46 (PAT Index MSB May Be Calculated Incorrectly)
+ */
+ pat_msr = rdmsr(MSR_PAT);
+ pat_msr &= ~PAT_MASK(2);
+ pat_msr |= PAT_VALUE(2, PAT_WRITE_COMBINING);
+#endif
+ wrmsr(MSR_PAT, pat_msr);
}
/*
@@ -564,69 +614,151 @@
void
pmap_init(void)
{
- int shpgperproc = PMAP_SHPGPERPROC;
/*
* Initialize the address space (zone) for the pv entries. Set a
* high water mark so that the system can recover from excessive
* numbers of pv entries.
*/
- pvzone = uma_zcreate("PV ENTRY", sizeof(struct pv_entry), NULL, NULL,
- NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM | UMA_ZONE_NOFREE);
TUNABLE_INT_FETCH("vm.pmap.shpgperproc", &shpgperproc);
pv_entry_max = shpgperproc * maxproc + cnt.v_page_count;
TUNABLE_INT_FETCH("vm.pmap.pv_entries", &pv_entry_max);
pv_entry_high_water = 9 * (pv_entry_max / 10);
- uma_zone_set_obj(pvzone, &pvzone_obj, pv_entry_max);
}
-void
-pmap_init2()
+SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters");
+static int
+pmap_pventry_proc(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+
+ error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
+ if (error == 0 && req->newptr) {
+ shpgperproc = (pv_entry_max - cnt.v_page_count) / maxproc;
+ pv_entry_high_water = 9 * (pv_entry_max / 10);
+ }
+ return (error);
+}
+SYSCTL_PROC(_vm_pmap, OID_AUTO, pv_entry_max, CTLTYPE_INT|CTLFLAG_RW,
+ &pv_entry_max, 0, pmap_pventry_proc, "IU", "Max number of PV entries");
+
+static int
+pmap_shpgperproc_proc(SYSCTL_HANDLER_ARGS)
{
+ int error;
+
+ error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
+ if (error == 0 && req->newptr) {
+ pv_entry_max = shpgperproc * maxproc + cnt.v_page_count;
+ pv_entry_high_water = 9 * (pv_entry_max / 10);
+ }
+ return (error);
}
+SYSCTL_PROC(_vm_pmap, OID_AUTO, shpgperproc, CTLTYPE_INT|CTLFLAG_RW,
+ &shpgperproc, 0, pmap_shpgperproc_proc, "IU", "Page share factor per proc");
/***************************************************
* Low level helper routines.....
***************************************************/
-#if defined(PMAP_DIAGNOSTIC)
-
/*
- * This code checks for non-writeable/modified pages.
- * This should be an invalid condition.
+ * Determine the appropriate bits to set in a PTE or PDE for a specified
+ * caching mode.
*/
static int
-pmap_nw_modified(pt_entry_t ptea)
+pmap_cache_bits(int mode, boolean_t is_pde)
{
- int pte;
+ int pat_flag, pat_index, cache_bits;
- pte = (int) ptea;
+ /* The PAT bit is different for PTE's and PDE's. */
+ pat_flag = is_pde ? PG_PDE_PAT : PG_PTE_PAT;
- if ((pte & (PG_M|PG_RW)) == PG_M)
- return 1;
- else
- return 0;
-}
+ /* If we don't support PAT, map extended modes to older ones. */
+ if (!(cpu_feature & CPUID_PAT)) {
+ switch (mode) {
+ case PAT_UNCACHEABLE:
+ case PAT_WRITE_THROUGH:
+ case PAT_WRITE_BACK:
+ break;
+ case PAT_UNCACHED:
+ case PAT_WRITE_COMBINING:
+ case PAT_WRITE_PROTECTED:
+ mode = PAT_UNCACHEABLE;
+ break;
+ }
+ }
+
+ /* Map the caching mode to a PAT index. */
+ switch (mode) {
+#ifdef PAT_WORKS
+ case PAT_UNCACHEABLE:
+ pat_index = 3;
+ break;
+ case PAT_WRITE_THROUGH:
+ pat_index = 1;
+ break;
+ case PAT_WRITE_BACK:
+ pat_index = 0;
+ break;
+ case PAT_UNCACHED:
+ pat_index = 2;
+ break;
+ case PAT_WRITE_COMBINING:
+ pat_index = 5;
+ break;
+ case PAT_WRITE_PROTECTED:
+ pat_index = 4;
+ break;
+#else
+ case PAT_UNCACHED:
+ case PAT_UNCACHEABLE:
+ case PAT_WRITE_PROTECTED:
+ pat_index = 3;
+ break;
+ case PAT_WRITE_THROUGH:
+ pat_index = 1;
+ break;
+ case PAT_WRITE_BACK:
+ pat_index = 0;
+ break;
+ case PAT_WRITE_COMBINING:
+ pat_index = 2;
+ break;
#endif
-
-
-/*
- * this routine defines the region(s) of memory that should
- * not be tested for the modified bit.
- */
-static PMAP_INLINE int
-pmap_track_modified(vm_offset_t va)
-{
- if ((va < kmi.clean_sva) || (va >= kmi.clean_eva))
- return 1;
- else
- return 0;
+ default:
+ panic("Unknown caching mode %d\n", mode);
+ }
+
+ /* Map the 3-bit index value into the PAT, PCD, and PWT bits. */
+ cache_bits = 0;
+ if (pat_index & 0x4)
+ cache_bits |= pat_flag;
+ if (pat_index & 0x2)
+ cache_bits |= PG_NC_PCD;
+ if (pat_index & 0x1)
+ cache_bits |= PG_NC_PWT;
+ return (cache_bits);
}
-
#ifdef SMP
/*
* For SMP, these functions have to use the IPI mechanism for coherence.
+ *
+ * N.B.: Before calling any of the following TLB invalidation functions,
+ * the calling processor must ensure that all stores updating a non-
+ * kernel page table are globally performed. Otherwise, another
+ * processor could cache an old, pre-update entry without being
+ * invalidated. This can happen one of two ways: (1) The pmap becomes
+ * active on another processor after its pm_active field is checked by
+ * one of the following functions but before a store updating the page
+ * table is globally performed. (2) The pmap becomes active on another
+ * processor before its pm_active field is checked but due to
+ * speculative loads one of the following functions stills reads the
+ * pmap as inactive on the other processor.
+ *
+ * The kernel page table is exempt because its pm_active field is
+ * immutable. The kernel page table is always active on every
+ * processor.
*/
void
pmap_invalidate_page(pmap_t pmap, vm_offset_t va)
@@ -634,18 +766,7 @@
u_int cpumask;
u_int other_cpus;
- if (smp_started) {
- if (!(read_rflags() & PSL_I))
- panic("%s: interrupts disabled", __func__);
- mtx_lock_spin(&smp_ipi_mtx);
- } else
- critical_enter();
- /*
- * We need to disable interrupt preemption but MUST NOT have
- * interrupts disabled here.
- * XXX we may need to hold schedlock to get a coherent pm_active
- * XXX critical sections disable interrupts again
- */
+ sched_pin();
if (pmap == kernel_pmap || pmap->pm_active == all_cpus) {
invlpg(va);
smp_invlpg(va);
@@ -657,10 +778,7 @@
if (pmap->pm_active & other_cpus)
smp_masked_invlpg(pmap->pm_active & other_cpus, va);
}
- if (smp_started)
- mtx_unlock_spin(&smp_ipi_mtx);
- else
- critical_exit();
+ sched_unpin();
}
void
@@ -670,18 +788,7 @@
u_int other_cpus;
vm_offset_t addr;
- if (smp_started) {
- if (!(read_rflags() & PSL_I))
- panic("%s: interrupts disabled", __func__);
- mtx_lock_spin(&smp_ipi_mtx);
- } else
- critical_enter();
- /*
- * We need to disable interrupt preemption but MUST NOT have
- * interrupts disabled here.
- * XXX we may need to hold schedlock to get a coherent pm_active
- * XXX critical sections disable interrupts again
- */
+ sched_pin();
if (pmap == kernel_pmap || pmap->pm_active == all_cpus) {
for (addr = sva; addr < eva; addr += PAGE_SIZE)
invlpg(addr);
@@ -696,10 +803,7 @@
smp_masked_invlpg_range(pmap->pm_active & other_cpus,
sva, eva);
}
- if (smp_started)
- mtx_unlock_spin(&smp_ipi_mtx);
- else
- critical_exit();
+ sched_unpin();
}
void
@@ -708,18 +812,7 @@
u_int cpumask;
u_int other_cpus;
- if (smp_started) {
- if (!(read_rflags() & PSL_I))
- panic("%s: interrupts disabled", __func__);
- mtx_lock_spin(&smp_ipi_mtx);
- } else
- critical_enter();
- /*
- * We need to disable interrupt preemption but MUST NOT have
- * interrupts disabled here.
- * XXX we may need to hold schedlock to get a coherent pm_active
- * XXX critical sections disable interrupts again
- */
+ sched_pin();
if (pmap == kernel_pmap || pmap->pm_active == all_cpus) {
invltlb();
smp_invltlb();
@@ -731,10 +824,17 @@
if (pmap->pm_active & other_cpus)
smp_masked_invltlb(pmap->pm_active & other_cpus);
}
- if (smp_started)
- mtx_unlock_spin(&smp_ipi_mtx);
- else
- critical_exit();
+ sched_unpin();
+}
+
+void
+pmap_invalidate_cache(void)
+{
+
+ sched_pin();
+ wbinvd();
+ smp_cache_flush();
+ sched_unpin();
}
#else /* !SMP */
/*
@@ -766,6 +866,13 @@
if (pmap == kernel_pmap || pmap->pm_active)
invltlb();
}
+
+PMAP_INLINE void
+pmap_invalidate_cache(void)
+{
+
+ wbinvd();
+}
#endif /* !SMP */
/*
@@ -798,9 +905,7 @@
pde = *pdep;
if (pde) {
if ((pde & PG_PS) != 0) {
- KASSERT((pde & PG_FRAME & PDRMASK) == 0,
- ("pmap_extract: bad pde"));
- rtval = (pde & PG_FRAME) | (va & PDRMASK);
+ rtval = (pde & PG_PS_FRAME) | (va & PDRMASK);
PMAP_UNLOCK(pmap);
return rtval;
}
@@ -833,9 +938,7 @@
if (pdep != NULL && (pde = *pdep)) {
if (pde & PG_PS) {
if ((pde & PG_RW) || (prot & VM_PROT_WRITE) == 0) {
- KASSERT((pde & PG_FRAME & PDRMASK) == 0,
- ("pmap_extract_and_hold: bad pde"));
- m = PHYS_TO_VM_PAGE((pde & PG_FRAME) |
+ m = PHYS_TO_VM_PAGE((pde & PG_PS_FRAME) |
(va & PDRMASK));
vm_page_hold(m);
}
@@ -864,7 +967,7 @@
} else {
pde = vtopde(va);
if (*pde & PG_PS) {
- pa = (*pde & ~(NBPDR - 1)) | (va & (NBPDR - 1));
+ pa = (*pde & PG_PS_FRAME) | (va & PDRMASK);
} else {
pa = *vtopte(va);
pa = (pa & PG_FRAME) | (va & PAGE_MASK);
@@ -890,6 +993,15 @@
pte_store(pte, pa | PG_RW | PG_V | PG_G);
}
+PMAP_INLINE void
+pmap_kenter_attr(vm_offset_t va, vm_paddr_t pa, int mode)
+{
+ pt_entry_t *pte;
+
+ pte = vtopte(va);
+ pte_store(pte, pa | PG_RW | PG_V | PG_G | pmap_cache_bits(mode, 0));
+}
+
/*
* Remove a page from the kernel pagetables.
* Note: not SMP coherent.
@@ -932,17 +1044,22 @@
* Note: SMP coherent. Uses a ranged shootdown IPI.
*/
void
-pmap_qenter(vm_offset_t sva, vm_page_t *m, int count)
+pmap_qenter(vm_offset_t sva, vm_page_t *ma, int count)
{
- vm_offset_t va;
+ pt_entry_t *endpte, oldpte, *pte;
- va = sva;
- while (count-- > 0) {
- pmap_kenter(va, VM_PAGE_TO_PHYS(*m));
- va += PAGE_SIZE;
- m++;
- }
- pmap_invalidate_range(kernel_pmap, sva, va);
+ oldpte = 0;
+ pte = vtopte(sva);
+ endpte = pte + count;
+ while (pte < endpte) {
+ oldpte |= *pte;
+ pte_store(pte, VM_PAGE_TO_PHYS(*ma) | PG_G | PG_RW | PG_V);
+ pte++;
+ ma++;
+ }
+ if ((oldpte & PG_V) != 0)
+ pmap_invalidate_range(kernel_pmap, sva, sva + count *
+ PAGE_SIZE);
}
/*
@@ -966,24 +1083,36 @@
/***************************************************
* Page table page management routines.....
***************************************************/
+static __inline void
+pmap_free_zero_pages(vm_page_t free)
+{
+ vm_page_t m;
+
+ while (free != NULL) {
+ m = free;
+ free = m->right;
+ vm_page_free_zero(m);
+ }
+}
/*
* This routine unholds page table pages, and if the hold count
* drops to zero, then it decrements the wire count.
*/
-static PMAP_INLINE int
-pmap_unwire_pte_hold(pmap_t pmap, vm_offset_t va, vm_page_t m)
+static __inline int
+pmap_unwire_pte_hold(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_page_t *free)
{
--m->wire_count;
if (m->wire_count == 0)
- return _pmap_unwire_pte_hold(pmap, va, m);
+ return _pmap_unwire_pte_hold(pmap, va, m, free);
else
return 0;
}
static int
-_pmap_unwire_pte_hold(pmap_t pmap, vm_offset_t va, vm_page_t m)
+_pmap_unwire_pte_hold(pmap_t pmap, vm_offset_t va, vm_page_t m,
+ vm_page_t *free)
{
vm_offset_t pteva;
@@ -1015,24 +1144,36 @@
vm_page_t pdpg;
pdpg = PHYS_TO_VM_PAGE(*pmap_pdpe(pmap, va) & PG_FRAME);
- pmap_unwire_pte_hold(pmap, va, pdpg);
+ pmap_unwire_pte_hold(pmap, va, pdpg, free);
}
if (m->pindex >= NUPDE && m->pindex < (NUPDE + NUPDPE)) {
/* We just released a PD, unhold the matching PDP */
vm_page_t pdppg;
pdppg = PHYS_TO_VM_PAGE(*pmap_pml4e(pmap, va) & PG_FRAME);
- pmap_unwire_pte_hold(pmap, va, pdppg);
+ pmap_unwire_pte_hold(pmap, va, pdppg, free);
}
/*
+ * This is a release store so that the ordinary store unmapping
+ * the page table page is globally performed before TLB shoot-
+ * down is begun.
+ */
+ atomic_subtract_rel_int(&cnt.v_wire_count, 1);
+
+ /*
* Do an invltlb to make the invalidated mapping
* take effect immediately.
*/
pmap_invalidate_page(pmap, pteva);
- vm_page_free_zero(m);
- atomic_subtract_int(&cnt.v_wire_count, 1);
+ /*
+ * Put page on a list so that it is released after
+ * *ALL* TLB shootdown is done
+ */
+ m->right = *free;
+ *free = m;
+
return 1;
}
@@ -1041,7 +1182,7 @@
* conditionally free the page, and manage the hold/wire counts.
*/
static int
-pmap_unuse_pt(pmap_t pmap, vm_offset_t va, pd_entry_t ptepde)
+pmap_unuse_pt(pmap_t pmap, vm_offset_t va, pd_entry_t ptepde, vm_page_t *free)
{
vm_page_t mpte;
@@ -1049,18 +1190,17 @@
return 0;
KASSERT(ptepde != 0, ("pmap_unuse_pt: ptepde != 0"));
mpte = PHYS_TO_VM_PAGE(ptepde & PG_FRAME);
- return pmap_unwire_pte_hold(pmap, va, mpte);
+ return pmap_unwire_pte_hold(pmap, va, mpte, free);
}
void
-pmap_pinit0(pmap)
- struct pmap *pmap;
+pmap_pinit0(pmap_t pmap)
{
PMAP_LOCK_INIT(pmap);
pmap->pm_pml4 = (pml4_entry_t *)(KERNBASE + KPML4phys);
pmap->pm_active = 0;
- TAILQ_INIT(&pmap->pm_pvlist);
+ TAILQ_INIT(&pmap->pm_pvchunk);
bzero(&pmap->pm_stats, sizeof pmap->pm_stats);
}
@@ -1068,9 +1208,8 @@
* Initialize a preallocated and zeroed pmap structure,
* such as one in a vmspace structure.
*/
-void
-pmap_pinit(pmap)
- register struct pmap *pmap;
+int
+pmap_pinit(pmap_t pmap)
{
vm_page_t pml4pg;
static vm_pindex_t color;
@@ -1097,8 +1236,10 @@
pmap->pm_pml4[PML4PML4I] = VM_PAGE_TO_PHYS(pml4pg) | PG_V | PG_RW | PG_A | PG_M;
pmap->pm_active = 0;
- TAILQ_INIT(&pmap->pm_pvlist);
+ TAILQ_INIT(&pmap->pm_pvchunk);
bzero(&pmap->pm_stats, sizeof pmap->pm_stats);
+
+ return (1);
}
/*
@@ -1269,7 +1410,7 @@
{
vm_pindex_t ptepindex;
pd_entry_t *pd;
- vm_page_t m;
+ vm_page_t m, free;
KASSERT((flags & (M_NOWAIT | M_WAITOK)) == M_NOWAIT ||
(flags & (M_NOWAIT | M_WAITOK)) == M_WAITOK,
@@ -1293,8 +1434,10 @@
*pd = 0;
pd = 0;
pmap->pm_stats.resident_count -= NBPDR / PAGE_SIZE;
- pmap_unuse_pt(pmap, va, *pmap_pdpe(pmap, va));
+ free = NULL;
+ pmap_unuse_pt(pmap, va, *pmap_pdpe(pmap, va), &free);
pmap_invalidate_all(kernel_pmap);
+ pmap_free_zero_pages(free);
}
/*
@@ -1341,11 +1484,9 @@
pmap->pm_pml4[DMPML4I] = 0; /* Direct Map */
pmap->pm_pml4[PML4PML4I] = 0; /* Recursive Mapping */
- vm_page_lock_queues();
m->wire_count--;
atomic_subtract_int(&cnt.v_wire_count, 1);
vm_page_free_zero(m);
- vm_page_unlock_queues();
PMAP_LOCK_DESTROY(pmap);
}
@@ -1357,7 +1498,7 @@
return sysctl_handle_long(oidp, &ksize, 0, req);
}
SYSCTL_PROC(_vm, OID_AUTO, kvm_size, CTLTYPE_LONG|CTLFLAG_RD,
- 0, 0, kvm_size, "IU", "Size of KVM");
+ 0, 0, kvm_size, "LU", "Size of KVM");
static int
kvm_free(SYSCTL_HANDLER_ARGS)
@@ -1367,7 +1508,7 @@
return sysctl_handle_long(oidp, &kfree, 0, req);
}
SYSCTL_PROC(_vm, OID_AUTO, kvm_free, CTLTYPE_LONG|CTLFLAG_RD,
- 0, 0, kvm_free, "IU", "Amount of KVM free");
+ 0, 0, kvm_free, "LU", "Amount of KVM free");
/*
* grow the number of kernel page table entries, if needed
@@ -1387,9 +1528,15 @@
while ((*pmap_pde(kernel_pmap, kernel_vm_end) & PG_V) != 0) {
kernel_vm_end = (kernel_vm_end + PAGE_SIZE * NPTEPG) & ~(PAGE_SIZE * NPTEPG - 1);
nkpt++;
+ if (kernel_vm_end - 1 >= kernel_map->max_offset) {
+ kernel_vm_end = kernel_map->max_offset;
+ break;
+ }
}
}
addr = roundup2(addr, PAGE_SIZE * NPTEPG);
+ if (addr - 1 >= kernel_map->max_offset)
+ addr = kernel_map->max_offset;
while (kernel_vm_end < addr) {
pde = pmap_pde(kernel_pmap, kernel_vm_end);
if (pde == NULL) {
@@ -1407,6 +1554,10 @@
}
if ((*pde & PG_V) != 0) {
kernel_vm_end = (kernel_vm_end + PAGE_SIZE * NPTEPG) & ~(PAGE_SIZE * NPTEPG - 1);
+ if (kernel_vm_end - 1 >= kernel_map->max_offset) {
+ kernel_vm_end = kernel_map->max_offset;
+ break;
+ }
continue;
}
@@ -1426,6 +1577,10 @@
*pmap_pde(kernel_pmap, kernel_vm_end) = newpdir;
kernel_vm_end = (kernel_vm_end + PAGE_SIZE * NPTEPG) & ~(PAGE_SIZE * NPTEPG - 1);
+ if (kernel_vm_end - 1 >= kernel_map->max_offset) {
+ kernel_vm_end = kernel_map->max_offset;
+ break;
+ }
}
}
@@ -1434,35 +1589,239 @@
* page management routines.
***************************************************/
+CTASSERT(sizeof(struct pv_chunk) == PAGE_SIZE);
+CTASSERT(_NPCM == 3);
+CTASSERT(_NPCPV == 168);
+
+static __inline struct pv_chunk *
+pv_to_chunk(pv_entry_t pv)
+{
+
+ return (struct pv_chunk *)((uintptr_t)pv & ~(uintptr_t)PAGE_MASK);
+}
+
+#define PV_PMAP(pv) (pv_to_chunk(pv)->pc_pmap)
+
+#define PC_FREE0 0xfffffffffffffffful
+#define PC_FREE1 0xfffffffffffffffful
+#define PC_FREE2 0x000000fffffffffful
+
+static uint64_t pc_freemask[_NPCM] = { PC_FREE0, PC_FREE1, PC_FREE2 };
+
+SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_count, CTLFLAG_RD, &pv_entry_count, 0,
+ "Current number of pv entries");
+
+#ifdef PV_STATS
+static int pc_chunk_count, pc_chunk_allocs, pc_chunk_frees, pc_chunk_tryfail;
+
+SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_count, CTLFLAG_RD, &pc_chunk_count, 0,
+ "Current number of pv entry chunks");
+SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_allocs, CTLFLAG_RD, &pc_chunk_allocs, 0,
+ "Current number of pv entry chunks allocated");
+SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_frees, CTLFLAG_RD, &pc_chunk_frees, 0,
+ "Current number of pv entry chunks frees");
+SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_tryfail, CTLFLAG_RD, &pc_chunk_tryfail, 0,
+ "Number of times tried to get a chunk page but failed.");
+
+static long pv_entry_frees, pv_entry_allocs;
+static int pv_entry_spare;
+
+SYSCTL_LONG(_vm_pmap, OID_AUTO, pv_entry_frees, CTLFLAG_RD, &pv_entry_frees, 0,
+ "Current number of pv entry frees");
+SYSCTL_LONG(_vm_pmap, OID_AUTO, pv_entry_allocs, CTLFLAG_RD, &pv_entry_allocs, 0,
+ "Current number of pv entry allocs");
+SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_spare, CTLFLAG_RD, &pv_entry_spare, 0,
+ "Current number of spare pv entries");
+
+static int pmap_collect_inactive, pmap_collect_active;
+
+SYSCTL_INT(_vm_pmap, OID_AUTO, pmap_collect_inactive, CTLFLAG_RD, &pmap_collect_inactive, 0,
+ "Current number times pmap_collect called on inactive queue");
+SYSCTL_INT(_vm_pmap, OID_AUTO, pmap_collect_active, CTLFLAG_RD, &pmap_collect_active, 0,
+ "Current number times pmap_collect called on active queue");
+#endif
+
+/*
+ * We are in a serious low memory condition. Resort to
+ * drastic measures to free some pages so we can allocate
+ * another pv entry chunk. This is normally called to
+ * unmap inactive pages, and if necessary, active pages.
+ */
+static void
+pmap_collect(pmap_t locked_pmap, struct vpgqueues *vpq)
+{
+ pd_entry_t ptepde;
+ pmap_t pmap;
+ pt_entry_t *pte, tpte;
+ pv_entry_t next_pv, pv;
+ vm_offset_t va;
+ vm_page_t m, free;
+
+ TAILQ_FOREACH(m, &vpq->pl, pageq) {
+ if (m->hold_count || m->busy)
+ continue;
+ TAILQ_FOREACH_SAFE(pv, &m->md.pv_list, pv_list, next_pv) {
+ va = pv->pv_va;
+ pmap = PV_PMAP(pv);
+ /* Avoid deadlock and lock recursion. */
+ if (pmap > locked_pmap)
+ PMAP_LOCK(pmap);
+ else if (pmap != locked_pmap && !PMAP_TRYLOCK(pmap))
+ continue;
+ pmap->pm_stats.resident_count--;
+ pte = pmap_pte_pde(pmap, va, &ptepde);
+ if (pte == NULL) {
+ panic("null pte in pmap_collect");
+ }
+ tpte = pte_load_clear(pte);
+ KASSERT((tpte & PG_W) == 0,
+ ("pmap_collect: wired pte %#lx", tpte));
+ if (tpte & PG_A)
+ vm_page_flag_set(m, PG_REFERENCED);
+ if (tpte & PG_M) {
+ KASSERT((tpte & PG_RW),
+ ("pmap_collect: modified page not writable: va: %#lx, pte: %#lx",
+ va, tpte));
+ vm_page_dirty(m);
+ }
+ free = NULL;
+ pmap_unuse_pt(pmap, va, ptepde, &free);
+ pmap_invalidate_page(pmap, va);
+ pmap_free_zero_pages(free);
+ TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
+ if (TAILQ_EMPTY(&m->md.pv_list))
+ vm_page_flag_clear(m, PG_WRITEABLE);
+ m->md.pv_list_count--;
+ free_pv_entry(pmap, pv);
+ if (pmap != locked_pmap)
+ PMAP_UNLOCK(pmap);
+ }
+ }
+}
+
+
/*
* free the pv_entry back to the free list
*/
-static PMAP_INLINE void
-free_pv_entry(pv_entry_t pv)
+static void
+free_pv_entry(pmap_t pmap, pv_entry_t pv)
{
+ vm_page_t m;
+ struct pv_chunk *pc;
+ int idx, field, bit;
+
+ mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+ PV_STAT(pv_entry_frees++);
+ PV_STAT(pv_entry_spare++);
pv_entry_count--;
- uma_zfree(pvzone, pv);
+ pc = pv_to_chunk(pv);
+ idx = pv - &pc->pc_pventry[0];
+ field = idx / 64;
+ bit = idx % 64;
+ pc->pc_map[field] |= 1ul << bit;
+ /* move to head of list */
+ TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
+ TAILQ_INSERT_HEAD(&pmap->pm_pvchunk, pc, pc_list);
+ if (pc->pc_map[0] != PC_FREE0 || pc->pc_map[1] != PC_FREE1 ||
+ pc->pc_map[2] != PC_FREE2)
+ return;
+ PV_STAT(pv_entry_spare -= _NPCPV);
+ PV_STAT(pc_chunk_count--);
+ PV_STAT(pc_chunk_frees++);
+ /* entire chunk is free, return it */
+ TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
+ m = PHYS_TO_VM_PAGE(DMAP_TO_PHYS((vm_offset_t)pc));
+ dump_drop_page(m->phys_addr);
+ vm_page_free(m);
}
/*
* get a new pv_entry, allocating a block from the system
* when needed.
- * the memory allocation is performed bypassing the malloc code
- * because of the possibility of allocations at interrupt time.
*/
static pv_entry_t
-get_pv_entry(void)
+get_pv_entry(pmap_t pmap, int try)
{
+ static const struct timeval printinterval = { 60, 0 };
+ static struct timeval lastprint;
+ static vm_pindex_t colour;
+ int bit, field;
+ pv_entry_t pv;
+ struct pv_chunk *pc;
+ vm_page_t m;
+
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+ mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ PV_STAT(pv_entry_allocs++);
pv_entry_count++;
- if ((pv_entry_count > pv_entry_high_water) &&
- (pmap_pagedaemon_waken == 0)) {
- pmap_pagedaemon_waken = 1;
- wakeup (&vm_pages_needed);
+ if (pv_entry_count > pv_entry_high_water)
+ if (ratecheck(&lastprint, &printinterval))
+ printf("Approaching the limit on PV entries, consider "
+ "increasing either the vm.pmap.shpgperproc or the "
+ "vm.pmap.pv_entry_max sysctl.\n");
+ pc = TAILQ_FIRST(&pmap->pm_pvchunk);
+ if (pc != NULL) {
+ for (field = 0; field < _NPCM; field++) {
+ if (pc->pc_map[field]) {
+ bit = bsfq(pc->pc_map[field]);
+ break;
+ }
+ }
+ if (field < _NPCM) {
+ pv = &pc->pc_pventry[field * 64 + bit];
+ pc->pc_map[field] &= ~(1ul << bit);
+ /* If this was the last item, move it to tail */
+ if (pc->pc_map[0] == 0 && pc->pc_map[1] == 0 &&
+ pc->pc_map[2] == 0) {
+ TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
+ TAILQ_INSERT_TAIL(&pmap->pm_pvchunk, pc, pc_list);
+ }
+ PV_STAT(pv_entry_spare--);
+ return (pv);
+ }
}
- return uma_zalloc(pvzone, M_NOWAIT);
+ /* No free items, allocate another chunk */
+ m = vm_page_alloc(NULL, colour, VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ);
+ if (m == NULL) {
+ if (try) {
+ pv_entry_count--;
+ PV_STAT(pc_chunk_tryfail++);
+ return (NULL);
+ }
+ /*
+ * Reclaim pv entries: At first, destroy mappings to inactive
+ * pages. After that, if a pv chunk entry is still needed,
+ * destroy mappings to active pages.
+ */
+ PV_STAT(pmap_collect_inactive++);
+ pmap_collect(pmap, &vm_page_queues[PQ_INACTIVE]);
+ m = vm_page_alloc(NULL, colour,
+ VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ);
+ if (m == NULL) {
+ PV_STAT(pmap_collect_active++);
+ pmap_collect(pmap, &vm_page_queues[PQ_ACTIVE]);
+ m = vm_page_alloc(NULL, colour,
+ VM_ALLOC_SYSTEM | VM_ALLOC_NOOBJ);
+ if (m == NULL)
+ panic("get_pv_entry: increase vm.pmap.shpgperproc");
+ }
+ }
+ PV_STAT(pc_chunk_count++);
+ PV_STAT(pc_chunk_allocs++);
+ colour++;
+ dump_add_page(m->phys_addr);
+ pc = (void *)PHYS_TO_DMAP(m->phys_addr);
+ pc->pc_pmap = pmap;
+ pc->pc_map[0] = PC_FREE0 & ~1ul; /* preallocated bit 0 */
+ pc->pc_map[1] = PC_FREE1;
+ pc->pc_map[2] = PC_FREE2;
+ pv = &pc->pc_pventry[0];
+ TAILQ_INSERT_HEAD(&pmap->pm_pvchunk, pc, pc_list);
+ PV_STAT(pv_entry_spare += _NPCPV - 1);
+ return (pv);
}
-
static void
pmap_remove_entry(pmap_t pmap, vm_page_t m, vm_offset_t va)
{
@@ -1470,24 +1829,16 @@
PMAP_LOCK_ASSERT(pmap, MA_OWNED);
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
- if (m->md.pv_list_count < pmap->pm_stats.resident_count) {
- TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
- if (pmap == pv->pv_pmap && va == pv->pv_va)
- break;
- }
- } else {
- TAILQ_FOREACH(pv, &pmap->pm_pvlist, pv_plist) {
- if (va == pv->pv_va)
- break;
- }
+ TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
+ if (pmap == PV_PMAP(pv) && va == pv->pv_va)
+ break;
}
KASSERT(pv != NULL, ("pmap_remove_entry: pv not found"));
TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
m->md.pv_list_count--;
if (TAILQ_EMPTY(&m->md.pv_list))
vm_page_flag_clear(m, PG_WRITEABLE);
- TAILQ_REMOVE(&pmap->pm_pvlist, pv, pv_plist);
- free_pv_entry(pv);
+ free_pv_entry(pmap, pv);
}
/*
@@ -1499,24 +1850,40 @@
{
pv_entry_t pv;
- pv = get_pv_entry();
- if (pv == NULL)
- panic("no pv entries: increase vm.pmap.shpgperproc");
- pv->pv_va = va;
- pv->pv_pmap = pmap;
-
PMAP_LOCK_ASSERT(pmap, MA_OWNED);
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
- TAILQ_INSERT_TAIL(&pmap->pm_pvlist, pv, pv_plist);
+ pv = get_pv_entry(pmap, FALSE);
+ pv->pv_va = va;
TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_list);
m->md.pv_list_count++;
}
/*
+ * Conditionally create a pv entry.
+ */
+static boolean_t
+pmap_try_insert_pv_entry(pmap_t pmap, vm_offset_t va, vm_page_t m)
+{
+ pv_entry_t pv;
+
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+ mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ if (pv_entry_count < pv_entry_high_water &&
+ (pv = get_pv_entry(pmap, TRUE)) != NULL) {
+ pv->pv_va = va;
+ TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_list);
+ m->md.pv_list_count++;
+ return (TRUE);
+ } else
+ return (FALSE);
+}
+
+/*
* pmap_remove_pte: do the things to unmap a page in a process
*/
static int
-pmap_remove_pte(pmap_t pmap, pt_entry_t *ptq, vm_offset_t va, pd_entry_t ptepde)
+pmap_remove_pte(pmap_t pmap, pt_entry_t *ptq, vm_offset_t va,
+ pd_entry_t ptepde, vm_page_t *free)
{
pt_entry_t oldpte;
vm_page_t m;
@@ -1535,28 +1902,23 @@
if (oldpte & PG_MANAGED) {
m = PHYS_TO_VM_PAGE(oldpte & PG_FRAME);
if (oldpte & PG_M) {
-#if defined(PMAP_DIAGNOSTIC)
- if (pmap_nw_modified((pt_entry_t) oldpte)) {
- printf(
- "pmap_remove: modified page not writable: va: 0x%lx, pte: 0x%lx\n",
- va, oldpte);
- }
-#endif
- if (pmap_track_modified(va))
- vm_page_dirty(m);
+ KASSERT((oldpte & PG_RW),
+ ("pmap_remove_pte: modified page not writable: va: %#lx, pte: %#lx",
+ va, oldpte));
+ vm_page_dirty(m);
}
if (oldpte & PG_A)
vm_page_flag_set(m, PG_REFERENCED);
pmap_remove_entry(pmap, m, va);
}
- return (pmap_unuse_pt(pmap, va, ptepde));
+ return (pmap_unuse_pt(pmap, va, ptepde, free));
}
/*
* Remove a single page from a process address space
*/
static void
-pmap_remove_page(pmap_t pmap, vm_offset_t va, pd_entry_t *pde)
+pmap_remove_page(pmap_t pmap, vm_offset_t va, pd_entry_t *pde, vm_page_t *free)
{
pt_entry_t *pte;
@@ -1566,7 +1928,7 @@
pte = pmap_pde_to_pte(pde, va);
if ((*pte & PG_V) == 0)
return;
- pmap_remove_pte(pmap, pte, va, *pde);
+ pmap_remove_pte(pmap, pte, va, *pde, free);
pmap_invalidate_page(pmap, va);
}
@@ -1584,6 +1946,7 @@
pdp_entry_t *pdpe;
pd_entry_t ptpaddr, *pde;
pt_entry_t *pte;
+ vm_page_t free = NULL;
int anyvalid;
/*
@@ -1605,7 +1968,7 @@
if (sva + PAGE_SIZE == eva) {
pde = pmap_pde(pmap, sva);
if (pde && (*pde & PG_PS) == 0) {
- pmap_remove_page(pmap, sva, pde);
+ pmap_remove_page(pmap, sva, pde, &free);
goto out;
}
}
@@ -1647,7 +2010,7 @@
if ((ptpaddr & PG_PS) != 0) {
*pde = 0;
pmap->pm_stats.resident_count -= NBPDR / PAGE_SIZE;
- pmap_unuse_pt(pmap, sva, *pdpe);
+ pmap_unuse_pt(pmap, sva, *pdpe, &free);
anyvalid = 1;
continue;
}
@@ -1664,16 +2027,23 @@
sva += PAGE_SIZE) {
if (*pte == 0)
continue;
- anyvalid = 1;
- if (pmap_remove_pte(pmap, pte, sva, ptpaddr))
+
+ /*
+ * The TLB entry for a PG_G mapping is invalidated
+ * by pmap_remove_pte().
+ */
+ if ((*pte & PG_G) == 0)
+ anyvalid = 1;
+ if (pmap_remove_pte(pmap, pte, sva, ptpaddr, &free))
break;
}
}
out:
- vm_page_unlock_queues();
if (anyvalid)
pmap_invalidate_all(pmap);
+ vm_page_unlock_queues();
PMAP_UNLOCK(pmap);
+ pmap_free_zero_pages(free);
}
/*
@@ -1692,9 +2062,11 @@
void
pmap_remove_all(vm_page_t m)
{
- register pv_entry_t pv;
+ pv_entry_t pv;
+ pmap_t pmap;
pt_entry_t *pte, tpte;
pd_entry_t ptepde;
+ vm_page_t free;
#if defined(PMAP_DIAGNOSTIC)
/*
@@ -1707,12 +2079,16 @@
#endif
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) {
- PMAP_LOCK(pv->pv_pmap);
- pv->pv_pmap->pm_stats.resident_count--;
- pte = pmap_pte_pde(pv->pv_pmap, pv->pv_va, &ptepde);
+ pmap = PV_PMAP(pv);
+ PMAP_LOCK(pmap);
+ pmap->pm_stats.resident_count--;
+ pte = pmap_pte_pde(pmap, pv->pv_va, &ptepde);
+ if (pte == NULL) {
+ panic("null pte in pmap_remove_all");
+ }
tpte = pte_load_clear(pte);
if (tpte & PG_W)
- pv->pv_pmap->pm_stats.wired_count--;
+ pmap->pm_stats.wired_count--;
if (tpte & PG_A)
vm_page_flag_set(m, PG_REFERENCED);
@@ -1720,23 +2096,19 @@
* Update the vm_page_t clean and reference bits.
*/
if (tpte & PG_M) {
-#if defined(PMAP_DIAGNOSTIC)
- if (pmap_nw_modified((pt_entry_t) tpte)) {
- printf(
- "pmap_remove_all: modified page not writable: va: 0x%lx, pte: 0x%lx\n",
- pv->pv_va, tpte);
- }
-#endif
- if (pmap_track_modified(pv->pv_va))
- vm_page_dirty(m);
+ KASSERT((tpte & PG_RW),
+ ("pmap_remove_all: modified page not writable: va: %#lx, pte: %#lx",
+ pv->pv_va, tpte));
+ vm_page_dirty(m);
}
- pmap_invalidate_page(pv->pv_pmap, pv->pv_va);
- TAILQ_REMOVE(&pv->pv_pmap->pm_pvlist, pv, pv_plist);
+ free = NULL;
+ pmap_unuse_pt(pmap, pv->pv_va, ptepde, &free);
+ pmap_invalidate_page(pmap, pv->pv_va);
+ pmap_free_zero_pages(free);
TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
m->md.pv_list_count--;
- pmap_unuse_pt(pv->pv_pmap, pv->pv_va, ptepde);
- PMAP_UNLOCK(pv->pv_pmap);
- free_pv_entry(pv);
+ free_pv_entry(pmap, pv);
+ PMAP_UNLOCK(pmap);
}
vm_page_flag_clear(m, PG_WRITEABLE);
}
@@ -1760,7 +2132,8 @@
return;
}
- if (prot & VM_PROT_WRITE)
+ if ((prot & (VM_PROT_WRITE|VM_PROT_EXECUTE)) ==
+ (VM_PROT_WRITE|VM_PROT_EXECUTE))
return;
anychanged = 0;
@@ -1796,7 +2169,10 @@
* Check for large page.
*/
if ((ptpaddr & PG_PS) != 0) {
- *pde &= ~(PG_M|PG_RW);
+ if ((prot & VM_PROT_WRITE) == 0)
+ *pde &= ~(PG_M|PG_RW);
+ if ((prot & VM_PROT_EXECUTE) == 0)
+ *pde |= pg_nx;
anychanged = 1;
continue;
}
@@ -1811,6 +2187,8 @@
retry:
obits = pbits = *pte;
+ if ((pbits & PG_V) == 0)
+ continue;
if (pbits & PG_MANAGED) {
m = NULL;
if (pbits & PG_A) {
@@ -1818,8 +2196,7 @@
vm_page_flag_set(m, PG_REFERENCED);
pbits &= ~PG_A;
}
- if ((pbits & PG_M) != 0 &&
- pmap_track_modified(sva)) {
+ if ((pbits & PG_M) != 0) {
if (m == NULL)
m = PHYS_TO_VM_PAGE(pbits &
PG_FRAME);
@@ -1827,7 +2204,10 @@
}
}
- pbits &= ~(PG_RW | PG_M);
+ if ((prot & VM_PROT_WRITE) == 0)
+ pbits &= ~(PG_RW | PG_M);
+ if ((prot & VM_PROT_EXECUTE) == 0)
+ pbits |= pg_nx;
if (pbits != obits) {
if (!atomic_cmpset_long(pte, obits, pbits))
@@ -1839,9 +2219,9 @@
}
}
}
- vm_page_unlock_queues();
if (anychanged)
pmap_invalidate_all(pmap);
+ vm_page_unlock_queues();
PMAP_UNLOCK(pmap);
}
@@ -1862,7 +2242,8 @@
boolean_t wired)
{
vm_paddr_t pa;
- register pt_entry_t *pte;
+ pd_entry_t *pde;
+ pt_entry_t *pte;
vm_paddr_t opa;
pt_entry_t origpte, newpte;
vm_page_t mpte, om;
@@ -1899,7 +2280,13 @@
}
#endif
- pte = pmap_pte(pmap, va);
+ pde = pmap_pde(pmap, va);
+ if (pde != NULL) {
+ if ((*pde & PG_PS) != 0)
+ panic("pmap_enter: attempted pmap_enter on 2MB page");
+ pte = pmap_pde_to_pte(pde, va);
+ } else
+ pte = NULL;
/*
* Page Directory table entry not valid, we need a new PT page
@@ -1912,9 +2299,6 @@
origpte = *pte;
opa = origpte & PG_FRAME;
- if (origpte & PG_PS)
- panic("pmap_enter: attempted pmap_enter on 2MB page");
-
/*
* Mapping has not changed, must be protection or wiring change.
*/
@@ -1970,6 +2354,8 @@
* Enter on the PV list if part of our managed memory.
*/
if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0) {
+ KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva,
+ ("pmap_enter: managed mapping within the clean submap"));
pmap_insert_entry(pmap, va, m);
pa |= PG_MANAGED;
}
@@ -1985,8 +2371,10 @@
* Now validate mapping with desired protection/wiring.
*/
newpte = (pt_entry_t)(pa | PG_V);
- if ((prot & VM_PROT_WRITE) != 0)
+ if ((prot & VM_PROT_WRITE) != 0) {
newpte |= PG_RW;
+ vm_page_flag_set(m, PG_WRITEABLE);
+ }
if ((prot & VM_PROT_EXECUTE) == 0)
newpte |= pg_nx;
if (wired)
@@ -2013,10 +2401,9 @@
}
if (origpte & PG_M) {
KASSERT((origpte & PG_RW),
- ("pmap_enter: modified page not writable:"
- " va: 0x%lx, pte: 0x%lx", va, origpte));
- if ((origpte & PG_MANAGED) &&
- pmap_track_modified(va))
+ ("pmap_enter: modified page not writable: va: %#lx, pte: %#lx",
+ va, origpte));
+ if ((origpte & PG_MANAGED) != 0)
vm_page_dirty(om);
if ((newpte & PG_RW) == 0)
invlva = TRUE;
@@ -2031,6 +2418,38 @@
}
/*
+ * Maps a sequence of resident pages belonging to the same object.
+ * The sequence begins with the given page m_start. This page is
+ * mapped at the given virtual address start. Each subsequent page is
+ * mapped at a virtual address that is offset from start by the same
+ * amount as the page is offset from m_start within the object. The
+ * last page in the sequence is the page with the largest offset from
+ * m_start that can be mapped at a virtual address less than the given
+ * virtual address end. Not every virtual page between start and end
+ * is mapped; only those for which a resident page exists with the
+ * corresponding offset from m_start are mapped.
+ */
+void
+pmap_enter_object(pmap_t pmap, vm_offset_t start, vm_offset_t end,
+ vm_page_t m_start, vm_prot_t prot)
+{
+ vm_page_t m, mpte;
+ vm_pindex_t diff, psize;
+
+ VM_OBJECT_LOCK_ASSERT(m_start->object, MA_OWNED);
+ psize = atop(end - start);
+ mpte = NULL;
+ m = m_start;
+ PMAP_LOCK(pmap);
+ while (m != NULL && (diff = m->pindex - m_start->pindex) < psize) {
+ mpte = pmap_enter_quick_locked(pmap, start + ptoa(diff), m,
+ prot, mpte);
+ m = TAILQ_NEXT(m, listq);
+ }
+ PMAP_UNLOCK(pmap);
+}
+
+/*
* this code makes some *MAJOR* assumptions:
* 1. Current pmap & pmap exists.
* 2. Not wired.
@@ -2039,16 +2458,28 @@
* but is *MUCH* faster than pmap_enter...
*/
-vm_page_t
-pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
- vm_page_t mpte)
+void
+pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot)
{
+
+ PMAP_LOCK(pmap);
+ (void) pmap_enter_quick_locked(pmap, va, m, prot, NULL);
+ PMAP_UNLOCK(pmap);
+}
+
+static vm_page_t
+pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m,
+ vm_prot_t prot, vm_page_t mpte)
+{
+ vm_page_t free;
pt_entry_t *pte;
vm_paddr_t pa;
+ KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva ||
+ (m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0,
+ ("pmap_enter_quick_locked: managed mapping within the clean submap"));
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
- VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
- PMAP_LOCK(pmap);
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
/*
* In the case that a page table page is not
@@ -2065,7 +2496,6 @@
if (mpte && (mpte->pindex == ptepindex)) {
mpte->wire_count++;
} else {
- retry:
/*
* Get the page directory entry
*/
@@ -2083,18 +2513,8 @@
} else {
mpte = _pmap_allocpte(pmap, ptepindex,
M_NOWAIT);
- if (mpte == NULL) {
- PMAP_UNLOCK(pmap);
- vm_page_busy(m);
- vm_page_unlock_queues();
- VM_OBJECT_UNLOCK(m->object);
- VM_WAIT;
- VM_OBJECT_LOCK(m->object);
- vm_page_lock_queues();
- vm_page_wakeup(m);
- PMAP_LOCK(pmap);
- goto retry;
- }
+ if (mpte == NULL)
+ return (mpte);
}
}
} else {
@@ -2110,19 +2530,27 @@
pte = vtopte(va);
if (*pte) {
if (mpte != NULL) {
- pmap_unwire_pte_hold(pmap, va, mpte);
+ mpte->wire_count--;
mpte = NULL;
}
- goto out;
+ return (mpte);
}
/*
- * Enter on the PV list if part of our managed memory. Note that we
- * raise IPL while manipulating pv_table since pmap_enter can be
- * called at interrupt time.
+ * Enter on the PV list if part of our managed memory.
*/
- if ((m->flags & (PG_FICTITIOUS|PG_UNMANAGED)) == 0)
- pmap_insert_entry(pmap, va, m);
+ if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0 &&
+ !pmap_try_insert_pv_entry(pmap, va, m)) {
+ if (mpte != NULL) {
+ free = NULL;
+ if (pmap_unwire_pte_hold(pmap, va, mpte, &free)) {
+ pmap_invalidate_page(pmap, va);
+ pmap_free_zero_pages(free);
+ }
+ mpte = NULL;
+ }
+ return (mpte);
+ }
/*
* Increment counters
@@ -2140,8 +2568,6 @@
pte_store(pte, pa | PG_V | PG_U);
else
pte_store(pte, pa | PG_V | PG_U | PG_MANAGED);
-out:
- PMAP_UNLOCK(pmap);
return mpte;
}
@@ -2188,7 +2614,6 @@
retry:
p = vm_page_lookup(object, pindex);
if (p != NULL) {
- vm_page_lock_queues();
if (vm_page_sleep_if_busy(p, FALSE, "init4p"))
goto retry;
} else {
@@ -2207,8 +2632,8 @@
p = vm_page_lookup(object, pindex);
vm_page_lock_queues();
vm_page_wakeup(p);
+ vm_page_unlock_queues();
}
- vm_page_unlock_queues();
ptepa = VM_PAGE_TO_PHYS(p);
if (ptepa & (NBPDR - 1))
@@ -2261,12 +2686,9 @@
* The mapping must already exist in the pmap.
*/
void
-pmap_change_wiring(pmap, va, wired)
- register pmap_t pmap;
- vm_offset_t va;
- boolean_t wired;
+pmap_change_wiring(pmap_t pmap, vm_offset_t va, boolean_t wired)
{
- register pt_entry_t *pte;
+ pt_entry_t *pte;
/*
* Wiring is not a hardware characteristic so there is no need to
@@ -2298,10 +2720,10 @@
pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len,
vm_offset_t src_addr)
{
+ vm_page_t free;
vm_offset_t addr;
vm_offset_t end_addr = src_addr + len;
vm_offset_t va_next;
- vm_page_t m;
if (dst_addr != src_addr)
return;
@@ -2327,15 +2749,6 @@
if (addr >= UPT_MIN_ADDRESS)
panic("pmap_copy: invalid to pmap_copy page tables");
- /*
- * Don't let optional prefaulting of pages make us go
- * way below the low water mark of free pages or way
- * above high water mark of used pv entries.
- */
- if (cnt.v_free_count < cnt.v_free_reserved ||
- pv_entry_count > pv_entry_high_water)
- break;
-
pml4e = pmap_pml4e(src_pmap, addr);
if ((*pml4e & PG_V) == 0) {
va_next = (addr + NBPML4) & ~PML4MASK;
@@ -2363,11 +2776,11 @@
PHYS_TO_DMAP(VM_PAGE_TO_PHYS(dstmpde));
pde = &pde[pmap_pde_index(addr)];
if (*pde == 0) {
- *pde = srcptepaddr;
+ *pde = srcptepaddr & ~PG_W;
dst_pmap->pm_stats.resident_count +=
NBPDR / PAGE_SIZE;
} else
- pmap_unwire_pte_hold(dst_pmap, addr, dstmpde);
+ dstmpde->wire_count--;
continue;
}
@@ -2386,11 +2799,6 @@
* we only virtual copy managed pages
*/
if ((ptetemp & PG_MANAGED) != 0) {
- /*
- * We have to check after allocpte for the
- * pte still being around... allocpte can
- * block.
- */
dstmpte = pmap_allocpte(dst_pmap, addr,
M_NOWAIT);
if (dstmpte == NULL)
@@ -2398,18 +2806,26 @@
dst_pte = (pt_entry_t *)
PHYS_TO_DMAP(VM_PAGE_TO_PHYS(dstmpte));
dst_pte = &dst_pte[pmap_pte_index(addr)];
- if (*dst_pte == 0) {
+ if (*dst_pte == 0 &&
+ pmap_try_insert_pv_entry(dst_pmap, addr,
+ PHYS_TO_VM_PAGE(ptetemp & PG_FRAME))) {
/*
- * Clear the modified and
+ * Clear the wired, modified, and
* accessed (referenced) bits
* during the copy.
*/
- m = PHYS_TO_VM_PAGE(ptetemp & PG_FRAME);
- *dst_pte = ptetemp & ~(PG_M | PG_A);
+ *dst_pte = ptetemp & ~(PG_W | PG_M |
+ PG_A);
dst_pmap->pm_stats.resident_count++;
- pmap_insert_entry(dst_pmap, addr, m);
- } else
- pmap_unwire_pte_hold(dst_pmap, addr, dstmpte);
+ } else {
+ free = NULL;
+ if (pmap_unwire_pte_hold(dst_pmap,
+ addr, dstmpte, &free)) {
+ pmap_invalidate_page(dst_pmap,
+ addr);
+ pmap_free_zero_pages(free);
+ }
+ }
if (dstmpte->wire_count >= srcmpte->wire_count)
break;
}
@@ -2488,9 +2904,7 @@
* subset of pmaps for proper page aging.
*/
boolean_t
-pmap_page_exists_quick(pmap, m)
- pmap_t pmap;
- vm_page_t m;
+pmap_page_exists_quick(pmap_t pmap, vm_page_t m)
{
pv_entry_t pv;
int loops = 0;
@@ -2500,7 +2914,7 @@
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
- if (pv->pv_pmap == pmap) {
+ if (PV_PMAP(pv) == pmap) {
return TRUE;
}
loops++;
@@ -2510,7 +2924,6 @@
return (FALSE);
}
-#define PMAP_REMOVE_PAGES_CURPROC_ONLY
/*
* Remove all pages from specified address space
* this aids process exit speeds. Also, this code
@@ -2520,83 +2933,99 @@
* in the case of running down an entire address space.
*/
void
-pmap_remove_pages(pmap, sva, eva)
- pmap_t pmap;
- vm_offset_t sva, eva;
+pmap_remove_pages(pmap_t pmap)
{
pt_entry_t *pte, tpte;
- vm_page_t m;
- pv_entry_t pv, npv;
+ vm_page_t m, free = NULL;
+ pv_entry_t pv;
+ struct pv_chunk *pc, *npc;
+ int field, idx;
+ int64_t bit;
+ uint64_t inuse, bitmask;
+ int allfree;
-#ifdef PMAP_REMOVE_PAGES_CURPROC_ONLY
if (pmap != vmspace_pmap(curthread->td_proc->p_vmspace)) {
printf("warning: pmap_remove_pages called with non-current pmap\n");
return;
}
-#endif
vm_page_lock_queues();
PMAP_LOCK(pmap);
- for (pv = TAILQ_FIRST(&pmap->pm_pvlist); pv; pv = npv) {
-
- if (pv->pv_va >= eva || pv->pv_va < sva) {
- npv = TAILQ_NEXT(pv, pv_plist);
- continue;
- }
-
-#ifdef PMAP_REMOVE_PAGES_CURPROC_ONLY
- pte = vtopte(pv->pv_va);
-#else
- pte = pmap_pte(pmap, pv->pv_va);
-#endif
- tpte = *pte;
-
- if (tpte == 0) {
- printf("TPTE at %p IS ZERO @ VA %08lx\n",
- pte, pv->pv_va);
- panic("bad pte");
- }
+ TAILQ_FOREACH_SAFE(pc, &pmap->pm_pvchunk, pc_list, npc) {
+ allfree = 1;
+ for (field = 0; field < _NPCM; field++) {
+ inuse = (~(pc->pc_map[field])) & pc_freemask[field];
+ while (inuse != 0) {
+ bit = bsfq(inuse);
+ bitmask = 1UL << bit;
+ idx = field * 64 + bit;
+ pv = &pc->pc_pventry[idx];
+ inuse &= ~bitmask;
+
+ pte = vtopte(pv->pv_va);
+ tpte = *pte;
+
+ if (tpte == 0) {
+ printf(
+ "TPTE at %p IS ZERO @ VA %08lx\n",
+ pte, pv->pv_va);
+ panic("bad pte");
+ }
/*
* We cannot remove wired pages from a process' mapping at this time
*/
- if (tpte & PG_W) {
- npv = TAILQ_NEXT(pv, pv_plist);
- continue;
- }
+ if (tpte & PG_W) {
+ allfree = 0;
+ continue;
+ }
- m = PHYS_TO_VM_PAGE(tpte & PG_FRAME);
- KASSERT(m->phys_addr == (tpte & PG_FRAME),
- ("vm_page_t %p phys_addr mismatch %016jx %016jx",
- m, (uintmax_t)m->phys_addr, (uintmax_t)tpte));
+ m = PHYS_TO_VM_PAGE(tpte & PG_FRAME);
+ KASSERT(m->phys_addr == (tpte & PG_FRAME),
+ ("vm_page_t %p phys_addr mismatch %016jx %016jx",
+ m, (uintmax_t)m->phys_addr,
+ (uintmax_t)tpte));
+
+ KASSERT(m < &vm_page_array[vm_page_array_size],
+ ("pmap_remove_pages: bad tpte %#jx",
+ (uintmax_t)tpte));
- KASSERT(m < &vm_page_array[vm_page_array_size],
- ("pmap_remove_pages: bad tpte %#jx", (uintmax_t)tpte));
+ pmap->pm_stats.resident_count--;
- pmap->pm_stats.resident_count--;
+ pte_clear(pte);
- pte_clear(pte);
+ /*
+ * Update the vm_page_t clean/reference bits.
+ */
+ if (tpte & PG_M)
+ vm_page_dirty(m);
- /*
- * Update the vm_page_t clean and reference bits.
- */
- if (tpte & PG_M) {
- vm_page_dirty(m);
+ /* Mark free */
+ PV_STAT(pv_entry_frees++);
+ PV_STAT(pv_entry_spare++);
+ pv_entry_count--;
+ pc->pc_map[field] |= bitmask;
+ m->md.pv_list_count--;
+ TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
+ if (TAILQ_EMPTY(&m->md.pv_list))
+ vm_page_flag_clear(m, PG_WRITEABLE);
+ pmap_unuse_pt(pmap, pv->pv_va,
+ *vtopde(pv->pv_va), &free);
+ }
+ }
+ if (allfree) {
+ PV_STAT(pv_entry_spare -= _NPCPV);
+ PV_STAT(pc_chunk_count--);
+ PV_STAT(pc_chunk_frees++);
+ TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
+ m = PHYS_TO_VM_PAGE(DMAP_TO_PHYS((vm_offset_t)pc));
+ dump_drop_page(m->phys_addr);
+ vm_page_free(m);
}
-
- npv = TAILQ_NEXT(pv, pv_plist);
- TAILQ_REMOVE(&pmap->pm_pvlist, pv, pv_plist);
-
- m->md.pv_list_count--;
- TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
- if (TAILQ_EMPTY(&m->md.pv_list))
- vm_page_flag_clear(m, PG_WRITEABLE);
-
- pmap_unuse_pt(pmap, pv->pv_va, *vtopde(pv->pv_va));
- free_pv_entry(pv);
}
pmap_invalidate_all(pmap);
- PMAP_UNLOCK(pmap);
vm_page_unlock_queues();
+ PMAP_UNLOCK(pmap);
+ pmap_free_zero_pages(free);
}
/*
@@ -2610,6 +3039,7 @@
{
pv_entry_t pv;
pt_entry_t *pte;
+ pmap_t pmap;
boolean_t rv;
rv = FALSE;
@@ -2618,17 +3048,11 @@
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
- /*
- * if the bit being tested is the modified bit, then
- * mark clean_map and ptes as never
- * modified.
- */
- if (!pmap_track_modified(pv->pv_va))
- continue;
- PMAP_LOCK(pv->pv_pmap);
- pte = pmap_pte(pv->pv_pmap, pv->pv_va);
+ pmap = PV_PMAP(pv);
+ PMAP_LOCK(pmap);
+ pte = pmap_pte(pmap, pv->pv_va);
rv = (*pte & PG_M) != 0;
- PMAP_UNLOCK(pv->pv_pmap);
+ PMAP_UNLOCK(pmap);
if (rv)
break;
}
@@ -2660,70 +3084,36 @@
}
/*
- * Clear the given bit in each of the given page's ptes.
+ * Clear the write and modified bits in each of the given page's mappings.
*/
-static __inline void
-pmap_clear_ptes(vm_page_t m, long bit)
+void
+pmap_remove_write(vm_page_t m)
{
- register pv_entry_t pv;
- pt_entry_t pbits, *pte;
+ pv_entry_t pv;
+ pmap_t pmap;
+ pt_entry_t oldpte, *pte;
- if ((m->flags & PG_FICTITIOUS) ||
- (bit == PG_RW && (m->flags & PG_WRITEABLE) == 0))
+ if ((m->flags & PG_FICTITIOUS) != 0 ||
+ (m->flags & PG_WRITEABLE) == 0)
return;
-
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
- /*
- * Loop over all current mappings setting/clearing as appropos If
- * setting RO do we need to clear the VAC?
- */
TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
- /*
- * don't write protect pager mappings
- */
- if (bit == PG_RW) {
- if (!pmap_track_modified(pv->pv_va))
- continue;
- }
-
- PMAP_LOCK(pv->pv_pmap);
- pte = pmap_pte(pv->pv_pmap, pv->pv_va);
+ pmap = PV_PMAP(pv);
+ PMAP_LOCK(pmap);
+ pte = pmap_pte(pmap, pv->pv_va);
retry:
- pbits = *pte;
- if (pbits & bit) {
- if (bit == PG_RW) {
- if (!atomic_cmpset_long(pte, pbits,
- pbits & ~(PG_RW | PG_M)))
- goto retry;
- if (pbits & PG_M) {
- vm_page_dirty(m);
- }
- } else {
- atomic_clear_long(pte, bit);
- }
- pmap_invalidate_page(pv->pv_pmap, pv->pv_va);
- }
- PMAP_UNLOCK(pv->pv_pmap);
- }
- if (bit == PG_RW)
- vm_page_flag_clear(m, PG_WRITEABLE);
-}
-
-/*
- * pmap_page_protect:
- *
- * Lower the permission for all mappings to a given page.
- */
-void
-pmap_page_protect(vm_page_t m, vm_prot_t prot)
-{
- if ((prot & VM_PROT_WRITE) == 0) {
- if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
- pmap_clear_ptes(m, PG_RW);
- } else {
- pmap_remove_all(m);
+ oldpte = *pte;
+ if (oldpte & PG_RW) {
+ if (!atomic_cmpset_long(pte, oldpte, oldpte &
+ ~(PG_RW | PG_M)))
+ goto retry;
+ if ((oldpte & PG_M) != 0)
+ vm_page_dirty(m);
+ pmap_invalidate_page(pmap, pv->pv_va);
}
+ PMAP_UNLOCK(pmap);
}
+ vm_page_flag_clear(m, PG_WRITEABLE);
}
/*
@@ -2741,46 +3131,33 @@
int
pmap_ts_referenced(vm_page_t m)
{
- register pv_entry_t pv, pvf, pvn;
+ pv_entry_t pv, pvf, pvn;
+ pmap_t pmap;
pt_entry_t *pte;
- pt_entry_t v;
int rtval = 0;
if (m->flags & PG_FICTITIOUS)
return (rtval);
-
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
if ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) {
-
pvf = pv;
-
do {
pvn = TAILQ_NEXT(pv, pv_list);
-
TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
-
TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_list);
-
- if (!pmap_track_modified(pv->pv_va))
- continue;
-
- PMAP_LOCK(pv->pv_pmap);
- pte = pmap_pte(pv->pv_pmap, pv->pv_va);
-
- if (pte && ((v = pte_load(pte)) & PG_A) != 0) {
+ pmap = PV_PMAP(pv);
+ PMAP_LOCK(pmap);
+ pte = pmap_pte(pmap, pv->pv_va);
+ if ((*pte & PG_A) != 0) {
atomic_clear_long(pte, PG_A);
- pmap_invalidate_page(pv->pv_pmap, pv->pv_va);
-
+ pmap_invalidate_page(pmap, pv->pv_va);
rtval++;
- if (rtval > 4) {
- PMAP_UNLOCK(pv->pv_pmap);
- break;
- }
+ if (rtval > 4)
+ pvn = NULL;
}
- PMAP_UNLOCK(pv->pv_pmap);
+ PMAP_UNLOCK(pmap);
} while ((pv = pvn) != NULL && pv != pvf);
}
-
return (rtval);
}
@@ -2790,7 +3167,23 @@
void
pmap_clear_modify(vm_page_t m)
{
- pmap_clear_ptes(m, PG_M);
+ pv_entry_t pv;
+ pmap_t pmap;
+ pt_entry_t *pte;
+
+ if ((m->flags & PG_FICTITIOUS) != 0)
+ return;
+ mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
+ pmap = PV_PMAP(pv);
+ PMAP_LOCK(pmap);
+ pte = pmap_pte(pmap, pv->pv_va);
+ if (*pte & PG_M) {
+ atomic_clear_long(pte, PG_M);
+ pmap_invalidate_page(pmap, pv->pv_va);
+ }
+ PMAP_UNLOCK(pmap);
+ }
}
/*
@@ -2801,13 +3194,69 @@
void
pmap_clear_reference(vm_page_t m)
{
- pmap_clear_ptes(m, PG_A);
+ pv_entry_t pv;
+ pmap_t pmap;
+ pt_entry_t *pte;
+
+ if ((m->flags & PG_FICTITIOUS) != 0)
+ return;
+ mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
+ pmap = PV_PMAP(pv);
+ PMAP_LOCK(pmap);
+ pte = pmap_pte(pmap, pv->pv_va);
+ if (*pte & PG_A) {
+ atomic_clear_long(pte, PG_A);
+ pmap_invalidate_page(pmap, pv->pv_va);
+ }
+ PMAP_UNLOCK(pmap);
+ }
}
/*
* Miscellaneous support routines follow
*/
+/* Adjust the cache mode for a 4KB page mapped via a PTE. */
+static __inline void
+pmap_pte_attr(vm_offset_t va, int mode)
+{
+ pt_entry_t *pte;
+ u_int opte, npte;
+
+ pte = vtopte(va);
+
+ /*
+ * The cache mode bits are all in the low 32-bits of the
+ * PTE, so we can just spin on updating the low 32-bits.
+ */
+ do {
+ opte = *(u_int *)pte;
+ npte = opte & ~(PG_PTE_PAT | PG_NC_PCD | PG_NC_PWT);
+ npte |= pmap_cache_bits(mode, 0);
+ } while (npte != opte && !atomic_cmpset_int((u_int *)pte, opte, npte));
+}
+
+/* Adjust the cache mode for a 2MB page mapped via a PDE. */
+static __inline void
+pmap_pde_attr(vm_offset_t va, int mode)
+{
+ pd_entry_t *pde;
+ u_int opde, npde;
+
+ pde = pmap_pde(kernel_pmap, va);
+
+ /*
+ * The cache mode bits are all in the low 32-bits of the
+ * PDE, so we can just spin on updating the low 32-bits.
+ */
+ do {
+ opde = *(u_int *)pde;
+ npde = opde & ~(PG_PDE_PAT | PG_NC_PCD | PG_NC_PWT);
+ npde |= pmap_cache_bits(mode, 1);
+ } while (npde != opde && !atomic_cmpset_int((u_int *)pde, opde, npde));
+}
+
/*
* Map a set of physical memory pages into the kernel virtual
* address space. Return a pointer to where it is mapped. This
@@ -2815,14 +3264,15 @@
* NOT real memory.
*/
void *
-pmap_mapdev(pa, size)
- vm_paddr_t pa;
- vm_size_t size;
+pmap_mapdev_attr(vm_paddr_t pa, vm_size_t size, int mode)
{
vm_offset_t va, tmpva, offset;
- /* If this fits within the direct map window, use it */
- if (pa < dmaplimit && (pa + size) < dmaplimit)
+ /*
+ * If this fits within the direct map window and use WB caching
+ * mode, use the direct map.
+ */
+ if (pa < dmaplimit && (pa + size) < dmaplimit && mode == PAT_WRITE_BACK)
return ((void *)PHYS_TO_DMAP(pa));
offset = pa & PAGE_MASK;
size = roundup(offset + size, PAGE_SIZE);
@@ -2831,19 +3281,32 @@
panic("pmap_mapdev: Couldn't alloc kernel virtual memory");
pa = trunc_page(pa);
for (tmpva = va; size > 0; ) {
- pmap_kenter(tmpva, pa);
+ pmap_kenter_attr(tmpva, pa, mode);
size -= PAGE_SIZE;
tmpva += PAGE_SIZE;
pa += PAGE_SIZE;
}
pmap_invalidate_range(kernel_pmap, va, tmpva);
+ pmap_invalidate_cache();
return ((void *)(va + offset));
}
+void *
+pmap_mapdev(vm_paddr_t pa, vm_size_t size)
+{
+
+ return (pmap_mapdev_attr(pa, size, PAT_UNCACHEABLE));
+}
+
+void *
+pmap_mapbios(vm_paddr_t pa, vm_size_t size)
+{
+
+ return (pmap_mapdev_attr(pa, size, PAT_WRITE_BACK));
+}
+
void
-pmap_unmapdev(va, size)
- vm_offset_t va;
- vm_size_t size;
+pmap_unmapdev(vm_offset_t va, vm_size_t size)
{
vm_offset_t base, offset, tmpva;
@@ -2859,13 +3322,78 @@
kmem_free(kernel_map, base, size);
}
+int
+pmap_change_attr(va, size, mode)
+ vm_offset_t va;
+ vm_size_t size;
+ int mode;
+{
+ vm_offset_t base, offset, tmpva;
+ pd_entry_t *pde;
+ pt_entry_t *pte;
+
+ base = trunc_page(va);
+ offset = va & PAGE_MASK;
+ size = roundup(offset + size, PAGE_SIZE);
+
+ /* Only supported on kernel virtual addresses. */
+ if (base <= VM_MAXUSER_ADDRESS)
+ return (EINVAL);
+
+ /*
+ * XXX: We have to support tearing 2MB pages down into 4k pages if
+ * needed here.
+ */
+ /* Pages that aren't mapped aren't supported. */
+ for (tmpva = base; tmpva < (base + size); ) {
+ pde = pmap_pde(kernel_pmap, tmpva);
+ if (*pde == 0)
+ return (EINVAL);
+ if (*pde & PG_PS) {
+ /* Handle 2MB pages that are completely contained. */
+ if (size >= NBPDR) {
+ tmpva += NBPDR;
+ continue;
+ }
+ return (EINVAL);
+ }
+ pte = vtopte(va);
+ if (*pte == 0)
+ return (EINVAL);
+ tmpva += PAGE_SIZE;
+ }
+
+ /*
+ * Ok, all the pages exist, so run through them updating their
+ * cache mode.
+ */
+ for (tmpva = base; size > 0; ) {
+ pde = pmap_pde(kernel_pmap, tmpva);
+ if (*pde & PG_PS) {
+ pmap_pde_attr(tmpva, mode);
+ tmpva += NBPDR;
+ size -= NBPDR;
+ } else {
+ pmap_pte_attr(tmpva, mode);
+ tmpva += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+ }
+
+ /*
+ * Flush CPU caches to make sure any data isn't cached that shouldn't
+ * be, etc.
+ */
+ pmap_invalidate_range(kernel_pmap, base, tmpva);
+ pmap_invalidate_cache();
+ return (0);
+}
+
/*
* perform the pmap work for mincore
*/
int
-pmap_mincore(pmap, addr)
- pmap_t pmap;
- vm_offset_t addr;
+pmap_mincore(pmap_t pmap, vm_offset_t addr)
{
pt_entry_t *ptep, pte;
vm_page_t m;
@@ -2925,7 +3453,6 @@
void
pmap_activate(struct thread *td)
{
- struct proc *p = td->td_proc;
pmap_t pmap, oldpmap;
u_int64_t cr3;
@@ -2942,18 +3469,7 @@
pmap->pm_active |= PCPU_GET(cpumask);
#endif
cr3 = vtophys(pmap->pm_pml4);
- /* XXXKSE this is wrong.
- * pmap_activate is for the current thread on the current cpu
- */
- if (p->p_flag & P_SA) {
- /* Make sure all other cr3 entries are updated. */
- /* what if they are running? XXXKSE (maybe abort them) */
- FOREACH_THREAD_IN_PROC(p, td) {
- td->td_pcb->pcb_cr3 = cr3;
- }
- } else {
- td->td_pcb->pcb_cr3 = cr3;
- }
+ td->td_pcb->pcb_cr3 = cr3;
load_cr3(cr3);
critical_exit();
}
Index: io.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/io.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/amd64/io.c -L sys/amd64/amd64/io.c -u -r1.1.1.1 -r1.2
--- sys/amd64/amd64/io.c
+++ sys/amd64/amd64/io.c
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/io.c,v 1.1 2004/08/01 11:40:50 markm Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/io.c,v 1.2 2006/11/06 13:41:49 rwatson Exp $");
#include <sys/param.h>
#include <sys/conf.h>
@@ -33,6 +33,7 @@
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/signalvar.h>
#include <sys/systm.h>
@@ -54,7 +55,7 @@
{
int error;
- error = suser(td);
+ error = priv_check(td, PRIV_IO);
if (error != 0)
return (error);
error = securelevel_gt(td->td_ucred, 0);
Index: nexus.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/nexus.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/amd64/nexus.c -L sys/amd64/amd64/nexus.c -u -r1.1.1.1 -r1.2
--- sys/amd64/amd64/nexus.c
+++ sys/amd64/amd64/nexus.c
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/nexus.c,v 1.66 2005/03/18 11:57:43 phk Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/nexus.c,v 1.77 2007/05/08 21:29:13 jhb Exp $");
/*
* This code implements a `root nexus' for Intel Architecture
@@ -41,13 +41,13 @@
* and I/O memory address space.
*/
-#define __RMAN_RESOURCE_VISIBLE
#include "opt_isa.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
+#include <sys/linker.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <machine/bus.h>
@@ -60,7 +60,11 @@
#include <vm/pmap.h>
#include <machine/pmap.h>
+#include <machine/metadata.h>
#include <machine/resource.h>
+#include <machine/pc/bios.h>
+
+#include "pcib_if.h"
#ifdef DEV_ISA
#include <isa/isavar.h>
@@ -94,13 +98,19 @@
static int nexus_release_resource(device_t, device_t, int, int,
struct resource *);
static int nexus_setup_intr(device_t, device_t, struct resource *, int flags,
- void (*)(void *), void *, void **);
+ driver_filter_t filter, void (*)(void *), void *,
+ void **);
static int nexus_teardown_intr(device_t, device_t, struct resource *,
void *);
static struct resource_list *nexus_get_reslist(device_t dev, device_t child);
static int nexus_set_resource(device_t, device_t, int, int, u_long, u_long);
static int nexus_get_resource(device_t, device_t, int, int, u_long *, u_long *);
static void nexus_delete_resource(device_t, device_t, int, int);
+static int nexus_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs);
+static int nexus_release_msi(device_t pcib, device_t dev, int count, int *irqs);
+static int nexus_alloc_msix(device_t pcib, device_t dev, int *irq);
+static int nexus_release_msix(device_t pcib, device_t dev, int irq);
+static int nexus_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr, uint32_t *data);
static device_method_t nexus_methods[] = {
/* Device interface */
@@ -126,6 +136,13 @@
DEVMETHOD(bus_get_resource, nexus_get_resource),
DEVMETHOD(bus_delete_resource, nexus_delete_resource),
+ /* pcib interface */
+ DEVMETHOD(pcib_alloc_msi, nexus_alloc_msi),
+ DEVMETHOD(pcib_release_msi, nexus_release_msi),
+ DEVMETHOD(pcib_alloc_msix, nexus_alloc_msix),
+ DEVMETHOD(pcib_release_msix, nexus_release_msix),
+ DEVMETHOD(pcib_map_msi, nexus_map_msi),
+
{ 0, 0 }
};
@@ -141,7 +158,7 @@
static int
nexus_probe(device_t dev)
{
- int irq, last;
+ int irq;
device_quiet(dev); /* suppress attach message for neatness */
@@ -174,18 +191,10 @@
* We search for regions of existing IRQs and add those to the IRQ
* resource manager.
*/
- last = -1;
for (irq = 0; irq < NUM_IO_INTS; irq++)
- if (intr_lookup_source(irq) != NULL) {
- if (last == -1)
- last = irq;
- } else if (last != -1) {
- if (rman_manage_region(&irq_rman, last, irq - 1) != 0)
+ if (intr_lookup_source(irq) != NULL)
+ if (rman_manage_region(&irq_rman, irq, irq) != 0)
panic("nexus_probe irq_rman add");
- last = -1;
- }
- if (last != -1 && rman_manage_region(&irq_rman, last, irq - 1) != 0)
- panic("nexus_probe irq_rman add");
/*
* ISA DMA on PCI systems is implemented in the ISA part of each
@@ -341,13 +350,7 @@
rv = rman_reserve_resource(rm, start, end, count, flags, child);
if (rv == 0)
return 0;
-
- if (type == SYS_RES_MEMORY) {
- rman_set_bustag(rv, AMD64_BUS_SPACE_MEM);
- } else if (type == SYS_RES_IOPORT) {
- rman_set_bustag(rv, AMD64_BUS_SPACE_IO);
- rman_set_bushandle(rv, rman_get_start(rv));
- }
+ rman_set_rid(rv, *rid);
if (needactivate) {
if (bus_activate_resource(child, type, *rid, rv)) {
@@ -367,27 +370,16 @@
/*
* If this is a memory resource, map it into the kernel.
*/
- if (rman_get_bustag(r) == AMD64_BUS_SPACE_MEM) {
- caddr_t vaddr = 0;
-
- if (rman_get_end(r) < 1024 * 1024) {
- /*
- * The first 1Mb is mapped at KERNBASE.
- */
- vaddr = (caddr_t)(uintptr_t)(KERNBASE + rman_get_start(r));
- } else {
- u_int64_t paddr;
- u_int64_t psize;
- u_int32_t poffs;
-
- paddr = rman_get_start(r);
- psize = rman_get_size(r);
+ if (type == SYS_RES_MEMORY) {
+ void *vaddr;
- poffs = paddr - trunc_page(paddr);
- vaddr = (caddr_t) pmap_mapdev(paddr-poffs, psize+poffs) + poffs;
- }
+ vaddr = pmap_mapdev(rman_get_start(r), rman_get_size(r));
rman_set_virtual(r, vaddr);
+ rman_set_bustag(r, AMD64_BUS_SPACE_MEM);
rman_set_bushandle(r, (bus_space_handle_t) vaddr);
+ } else if (type == SYS_RES_IOPORT) {
+ rman_set_bustag(r, AMD64_BUS_SPACE_IO);
+ rman_set_bushandle(r, rman_get_start(r));
}
return (rman_activate_resource(r));
}
@@ -399,12 +391,9 @@
/*
* If this is a memory resource, unmap it.
*/
- if ((rman_get_bustag(r) == AMD64_BUS_SPACE_MEM) &&
- (rman_get_end(r) >= 1024 * 1024)) {
- u_int32_t psize;
-
- psize = rman_get_size(r);
- pmap_unmapdev((vm_offset_t)rman_get_virtual(r), psize);
+ if (type == SYS_RES_MEMORY) {
+ pmap_unmapdev((vm_offset_t)rman_get_virtual(r),
+ rman_get_size(r));
}
return (rman_deactivate_resource(r));
@@ -430,7 +419,8 @@
*/
static int
nexus_setup_intr(device_t bus, device_t child, struct resource *irq,
- int flags, void (*ihand)(void *), void *arg, void **cookiep)
+ int flags, driver_filter_t filter, void (*ihand)(void *),
+ void *arg, void **cookiep)
{
int error;
@@ -450,7 +440,7 @@
return (error);
error = intr_add_handler(device_get_nameunit(child),
- rman_get_start(irq), ihand, arg, flags, cookiep);
+ rman_get_start(irq), filter, ihand, arg, flags, cookiep);
return (error);
}
@@ -513,6 +503,123 @@
resource_list_delete(rl, type, rid);
}
+/* Called from the MSI code to add new IRQs to the IRQ rman. */
+void
+nexus_add_irq(u_long irq)
+{
+
+ if (rman_manage_region(&irq_rman, irq, irq) != 0)
+ panic("%s: failed", __func__);
+}
+
+static int
+nexus_alloc_msix(device_t pcib, device_t dev, int *irq)
+{
+
+ return (msix_alloc(dev, irq));
+}
+
+static int
+nexus_release_msix(device_t pcib, device_t dev, int irq)
+{
+
+ return (msix_release(irq));
+}
+
+static int
+nexus_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs)
+{
+
+ return (msi_alloc(dev, count, maxcount, irqs));
+}
+
+static int
+nexus_release_msi(device_t pcib, device_t dev, int count, int *irqs)
+{
+
+ return (msi_release(irqs, count));
+}
+
+static int
+nexus_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr, uint32_t *data)
+{
+
+ return (msi_map(irq, addr, data));
+}
+
+/* Placeholder for system RAM. */
+static void
+ram_identify(driver_t *driver, device_t parent)
+{
+
+ if (resource_disabled("ram", 0))
+ return;
+ if (BUS_ADD_CHILD(parent, 0, "ram", 0) == NULL)
+ panic("ram_identify");
+}
+
+static int
+ram_probe(device_t dev)
+{
+
+ device_quiet(dev);
+ device_set_desc(dev, "System RAM");
+ return (0);
+}
+
+static int
+ram_attach(device_t dev)
+{
+ struct bios_smap *smapbase, *smap, *smapend;
+ struct resource *res;
+ caddr_t kmdp;
+ uint32_t smapsize;
+ int error, rid;
+
+ /* Retrieve the system memory map from the loader. */
+ kmdp = preload_search_by_type("elf kernel");
+ if (kmdp == NULL)
+ kmdp = preload_search_by_type("elf64 kernel");
+ smapbase = (struct bios_smap *)preload_search_info(kmdp,
+ MODINFO_METADATA | MODINFOMD_SMAP);
+ smapsize = *((u_int32_t *)smapbase - 1);
+ smapend = (struct bios_smap *)((uintptr_t)smapbase + smapsize);
+
+ rid = 0;
+ for (smap = smapbase; smap < smapend; smap++) {
+ if (smap->type != 0x01 || smap->length == 0)
+ continue;
+ error = bus_set_resource(dev, SYS_RES_MEMORY, rid, smap->base,
+ smap->length);
+ if (error)
+ panic("ram_attach: resource %d failed set with %d", rid,
+ error);
+ res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 0);
+ if (res == NULL)
+ panic("ram_attach: resource %d failed to attach", rid);
+ rid++;
+ }
+ return (0);
+}
+
+static device_method_t ram_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_identify, ram_identify),
+ DEVMETHOD(device_probe, ram_probe),
+ DEVMETHOD(device_attach, ram_attach),
+ { 0, 0 }
+};
+
+static driver_t ram_driver = {
+ "ram",
+ ram_methods,
+ 1, /* no softc */
+};
+
+static devclass_t ram_devclass;
+
+DRIVER_MODULE(ram, nexus, ram_driver, ram_devclass, 0, 0);
+
#ifdef DEV_ISA
/*
* Placeholder which claims PnP 'devices' which describe system
Index: fpu.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/fpu.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/amd64/amd64/fpu.c -L sys/amd64/amd64/fpu.c -u -r1.2 -r1.3
--- sys/amd64/amd64/fpu.c
+++ sys/amd64/amd64/fpu.c
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/fpu.c,v 1.157 2005/03/11 22:16:09 peter Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/fpu.c,v 1.159 2006/06/19 22:36:01 davidxu Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -125,6 +125,10 @@
mxcsr = __INITIAL_MXCSR__;
ldmxcsr(mxcsr);
fxsave(&fpu_cleanstate);
+ if (fpu_cleanstate.sv_env.en_mxcsr_mask)
+ cpu_mxcsr_mask = fpu_cleanstate.sv_env.en_mxcsr_mask;
+ else
+ cpu_mxcsr_mask = 0xFFBF;
start_emulating();
bzero(fpu_cleanstate.sv_fp, sizeof(fpu_cleanstate.sv_fp));
bzero(fpu_cleanstate.sv_xmm, sizeof(fpu_cleanstate.sv_xmm));
Index: genassym.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/genassym.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/amd64/genassym.c -L sys/amd64/amd64/genassym.c -u -r1.1.1.1 -r1.2
--- sys/amd64/amd64/genassym.c
+++ sys/amd64/amd64/genassym.c
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/genassym.c,v 1.155.2.2 2005/11/15 00:25:59 peter Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/genassym.c,v 1.165 2007/09/17 21:55:28 peter Exp $");
#include "opt_compat.h"
#include "opt_kstack_pages.h"
@@ -74,11 +74,12 @@
ASSYM(P_VMSPACE, offsetof(struct proc, p_vmspace));
ASSYM(VM_PMAP, offsetof(struct vmspace, vm_pmap));
ASSYM(PM_ACTIVE, offsetof(struct pmap, pm_active));
-ASSYM(P_SFLAG, offsetof(struct proc, p_sflag));
+ASSYM(TD_LOCK, offsetof(struct thread, td_lock));
ASSYM(TD_FLAGS, offsetof(struct thread, td_flags));
ASSYM(TD_PCB, offsetof(struct thread, td_pcb));
ASSYM(TD_PROC, offsetof(struct thread, td_proc));
+ASSYM(TD_TID, offsetof(struct thread, td_tid));
ASSYM(TDF_ASTPENDING, TDF_ASTPENDING);
ASSYM(TDF_NEEDRESCHED, TDF_NEEDRESCHED);
@@ -135,12 +136,14 @@
ASSYM(PCB_DR7, offsetof(struct pcb, pcb_dr7));
ASSYM(PCB_DBREGS, PCB_DBREGS);
ASSYM(PCB_32BIT, PCB_32BIT);
+ASSYM(PCB_FULLCTX, PCB_FULLCTX);
ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags));
-ASSYM(PCB_FULLCTX, PCB_FULLCTX);
ASSYM(PCB_SAVEFPU, offsetof(struct pcb, pcb_save));
ASSYM(PCB_SAVEFPU_SIZE, sizeof(struct savefpu));
ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault));
+ASSYM(PCB_GS32P, offsetof(struct pcb, pcb_gs32p));
+ASSYM(PCB_GS32SD, offsetof(struct pcb, pcb_gs32sd));
ASSYM(PCB_SIZE, sizeof(struct pcb));
@@ -177,6 +180,7 @@
ASSYM(ENOENT, ENOENT);
ASSYM(EFAULT, EFAULT);
ASSYM(ENAMETOOLONG, ENAMETOOLONG);
+ASSYM(MAXCPU, MAXCPU);
ASSYM(MAXCOMLEN, MAXCOMLEN);
ASSYM(MAXPATHLEN, MAXPATHLEN);
ASSYM(PC_SIZEOF, sizeof(struct pcpu));
--- /dev/null
+++ sys/amd64/amd64/minidump_machdep.c
@@ -0,0 +1,420 @@
+/*-
+ * Copyright (c) 2006 Peter Wemm
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/minidump_machdep.c,v 1.2.4.1 2008/01/30 21:21:50 ru Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/cons.h>
+#include <sys/kernel.h>
+#include <sys/kerneldump.h>
+#include <sys/msgbuf.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <machine/atomic.h>
+#include <machine/elf.h>
+#include <machine/md_var.h>
+#include <machine/vmparam.h>
+#include <machine/minidump.h>
+
+CTASSERT(sizeof(struct kerneldumpheader) == 512);
+
+/*
+ * Don't touch the first SIZEOF_METADATA bytes on the dump device. This
+ * is to protect us from metadata and to protect metadata from us.
+ */
+#define SIZEOF_METADATA (64*1024)
+
+#define MD_ALIGN(x) (((off_t)(x) + PAGE_MASK) & ~PAGE_MASK)
+#define DEV_ALIGN(x) (((off_t)(x) + (DEV_BSIZE-1)) & ~(DEV_BSIZE-1))
+
+extern uint64_t KPDPphys;
+
+uint64_t *vm_page_dump;
+int vm_page_dump_size;
+
+static struct kerneldumpheader kdh;
+static off_t dumplo;
+
+/* Handle chunked writes. */
+static size_t fragsz;
+static void *dump_va;
+static size_t counter, progress;
+
+CTASSERT(sizeof(*vm_page_dump) == 8);
+
+static int
+is_dumpable(vm_paddr_t pa)
+{
+ int i;
+
+ for (i = 0; dump_avail[i] != 0 || dump_avail[i + 1] != 0; i += 2) {
+ if (pa >= dump_avail[i] && pa < dump_avail[i + 1])
+ return (1);
+ }
+ return (0);
+}
+
+/* XXX should be MI */
+static void
+mkdumpheader(struct kerneldumpheader *kdh, uint32_t archver, uint64_t dumplen,
+ uint32_t blksz)
+{
+
+ bzero(kdh, sizeof(*kdh));
+ strncpy(kdh->magic, KERNELDUMPMAGIC, sizeof(kdh->magic));
+ strncpy(kdh->architecture, MACHINE_ARCH, sizeof(kdh->architecture));
+ kdh->version = htod32(KERNELDUMPVERSION);
+ kdh->architectureversion = htod32(archver);
+ kdh->dumplength = htod64(dumplen);
+ kdh->dumptime = htod64(time_second);
+ kdh->blocksize = htod32(blksz);
+ strncpy(kdh->hostname, hostname, sizeof(kdh->hostname));
+ strncpy(kdh->versionstring, version, sizeof(kdh->versionstring));
+ if (panicstr != NULL)
+ strncpy(kdh->panicstring, panicstr, sizeof(kdh->panicstring));
+ kdh->parity = kerneldump_parity(kdh);
+}
+
+#define PG2MB(pgs) (((pgs) + (1 << 8) - 1) >> 8)
+
+static int
+blk_flush(struct dumperinfo *di)
+{
+ int error;
+
+ if (fragsz == 0)
+ return (0);
+
+ error = dump_write(di, dump_va, 0, dumplo, fragsz);
+ dumplo += fragsz;
+ fragsz = 0;
+ return (error);
+}
+
+static int
+blk_write(struct dumperinfo *di, char *ptr, vm_paddr_t pa, size_t sz)
+{
+ size_t len;
+ int error, i, c;
+
+ error = 0;
+ if ((sz % PAGE_SIZE) != 0) {
+ printf("size not page aligned\n");
+ return (EINVAL);
+ }
+ if (ptr != NULL && pa != 0) {
+ printf("cant have both va and pa!\n");
+ return (EINVAL);
+ }
+ if (pa != 0 && (((uintptr_t)ptr) % PAGE_SIZE) != 0) {
+ printf("address not page aligned\n");
+ return (EINVAL);
+ }
+ if (ptr != NULL) {
+ /* If we're doing a virtual dump, flush any pre-existing pa pages */
+ error = blk_flush(di);
+ if (error)
+ return (error);
+ }
+ while (sz) {
+ len = (MAXDUMPPGS * PAGE_SIZE) - fragsz;
+ if (len > sz)
+ len = sz;
+ counter += len;
+ progress -= len;
+ if (counter >> 24) {
+ printf(" %ld", PG2MB(progress >> PAGE_SHIFT));
+ counter &= (1<<24) - 1;
+ }
+ if (ptr) {
+ error = dump_write(di, ptr, 0, dumplo, len);
+ if (error)
+ return (error);
+ dumplo += len;
+ ptr += len;
+ sz -= len;
+ } else {
+ for (i = 0; i < len; i += PAGE_SIZE)
+ dump_va = pmap_kenter_temporary(pa + i, (i + fragsz) >> PAGE_SHIFT);
+ fragsz += len;
+ pa += len;
+ sz -= len;
+ if (fragsz == (MAXDUMPPGS * PAGE_SIZE)) {
+ error = blk_flush(di);
+ if (error)
+ return (error);
+ }
+ }
+
+ /* Check for user abort. */
+ c = cncheckc();
+ if (c == 0x03)
+ return (ECANCELED);
+ if (c != -1)
+ printf(" (CTRL-C to abort) ");
+ }
+
+ return (0);
+}
+
+/* A fake page table page, to avoid having to handle both 4K and 2M pages */
+static pt_entry_t fakept[NPTEPG];
+
+void
+minidumpsys(struct dumperinfo *di)
+{
+ uint64_t dumpsize;
+ uint32_t ptesize;
+ vm_offset_t va;
+ int error;
+ uint64_t bits;
+ uint64_t *pdp, *pd, *pt, pa;
+ int i, j, k, bit;
+ struct minidumphdr mdhdr;
+
+ counter = 0;
+ /* Walk page table pages, set bits in vm_page_dump */
+ ptesize = 0;
+ pdp = (uint64_t *)PHYS_TO_DMAP(KPDPphys);
+ for (va = KERNBASE; va < kernel_vm_end; va += NBPDR) {
+ i = (va >> PDPSHIFT) & ((1ul << NPDPEPGSHIFT) - 1);
+ /*
+ * We always write a page, even if it is zero. Each
+ * page written corresponds to 2MB of space
+ */
+ ptesize += PAGE_SIZE;
+ if ((pdp[i] & PG_V) == 0)
+ continue;
+ pd = (uint64_t *)PHYS_TO_DMAP(pdp[i] & PG_FRAME);
+ j = ((va >> PDRSHIFT) & ((1ul << NPDEPGSHIFT) - 1));
+ if ((pd[j] & (PG_PS | PG_V)) == (PG_PS | PG_V)) {
+ /* This is an entire 2M page. */
+ pa = pd[j] & PG_PS_FRAME;
+ for (k = 0; k < NPTEPG; k++) {
+ if (is_dumpable(pa))
+ dump_add_page(pa);
+ pa += PAGE_SIZE;
+ }
+ continue;
+ }
+ if ((pd[j] & PG_V) == PG_V) {
+ /* set bit for each valid page in this 2MB block */
+ pt = (uint64_t *)PHYS_TO_DMAP(pd[j] & PG_FRAME);
+ for (k = 0; k < NPTEPG; k++) {
+ if ((pt[k] & PG_V) == PG_V) {
+ pa = pt[k] & PG_FRAME;
+ if (is_dumpable(pa))
+ dump_add_page(pa);
+ }
+ }
+ } else {
+ /* nothing, we're going to dump a null page */
+ }
+ }
+
+ /* Calculate dump size. */
+ dumpsize = ptesize;
+ dumpsize += round_page(msgbufp->msg_size);
+ dumpsize += round_page(vm_page_dump_size);
+ for (i = 0; i < vm_page_dump_size / sizeof(*vm_page_dump); i++) {
+ bits = vm_page_dump[i];
+ while (bits) {
+ bit = bsfq(bits);
+ pa = (((uint64_t)i * sizeof(*vm_page_dump) * NBBY) + bit) * PAGE_SIZE;
+ /* Clear out undumpable pages now if needed */
+ if (is_dumpable(pa)) {
+ dumpsize += PAGE_SIZE;
+ } else {
+ dump_drop_page(pa);
+ }
+ bits &= ~(1ul << bit);
+ }
+ }
+ dumpsize += PAGE_SIZE;
+
+ /* Determine dump offset on device. */
+ if (di->mediasize < SIZEOF_METADATA + dumpsize + sizeof(kdh) * 2) {
+ error = ENOSPC;
+ goto fail;
+ }
+ dumplo = di->mediaoffset + di->mediasize - dumpsize;
+ dumplo -= sizeof(kdh) * 2;
+ progress = dumpsize;
+
+ /* Initialize mdhdr */
+ bzero(&mdhdr, sizeof(mdhdr));
+ strcpy(mdhdr.magic, MINIDUMP_MAGIC);
+ mdhdr.version = MINIDUMP_VERSION;
+ mdhdr.msgbufsize = msgbufp->msg_size;
+ mdhdr.bitmapsize = vm_page_dump_size;
+ mdhdr.ptesize = ptesize;
+ mdhdr.kernbase = KERNBASE;
+ mdhdr.dmapbase = DMAP_MIN_ADDRESS;
+ mdhdr.dmapend = DMAP_MAX_ADDRESS;
+
+ mkdumpheader(&kdh, KERNELDUMP_AMD64_VERSION, dumpsize, di->blocksize);
+
+ printf("Physical memory: %ju MB\n", ptoa((uintmax_t)physmem) / 1048576);
+ printf("Dumping %llu MB:", (long long)dumpsize >> 20);
+
+ /* Dump leader */
+ error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
+ if (error)
+ goto fail;
+ dumplo += sizeof(kdh);
+
+ /* Dump my header */
+ bzero(&fakept, sizeof(fakept));
+ bcopy(&mdhdr, &fakept, sizeof(mdhdr));
+ error = blk_write(di, (char *)&fakept, 0, PAGE_SIZE);
+ if (error)
+ goto fail;
+
+ /* Dump msgbuf up front */
+ error = blk_write(di, (char *)msgbufp->msg_ptr, 0, round_page(msgbufp->msg_size));
+ if (error)
+ goto fail;
+
+ /* Dump bitmap */
+ error = blk_write(di, (char *)vm_page_dump, 0, round_page(vm_page_dump_size));
+ if (error)
+ goto fail;
+
+ /* Dump kernel page table pages */
+ pdp = (uint64_t *)PHYS_TO_DMAP(KPDPphys);
+ for (va = KERNBASE; va < kernel_vm_end; va += NBPDR) {
+ i = (va >> PDPSHIFT) & ((1ul << NPDPEPGSHIFT) - 1);
+ /* We always write a page, even if it is zero */
+ if ((pdp[i] & PG_V) == 0) {
+ bzero(fakept, sizeof(fakept));
+ error = blk_write(di, (char *)&fakept, 0, PAGE_SIZE);
+ if (error)
+ goto fail;
+ /* flush, in case we reuse fakept in the same block */
+ error = blk_flush(di);
+ if (error)
+ goto fail;
+ continue;
+ }
+ pd = (uint64_t *)PHYS_TO_DMAP(pdp[i] & PG_FRAME);
+ j = ((va >> PDRSHIFT) & ((1ul << NPDEPGSHIFT) - 1));
+ if ((pd[j] & (PG_PS | PG_V)) == (PG_PS | PG_V)) {
+ /* This is a single 2M block. Generate a fake PTP */
+ pa = pd[j] & PG_PS_FRAME;
+ for (k = 0; k < NPTEPG; k++) {
+ fakept[k] = (pa + (k * PAGE_SIZE)) | PG_V | PG_RW | PG_A | PG_M;
+ }
+ error = blk_write(di, (char *)&fakept, 0, PAGE_SIZE);
+ if (error)
+ goto fail;
+ /* flush, in case we reuse fakept in the same block */
+ error = blk_flush(di);
+ if (error)
+ goto fail;
+ continue;
+ }
+ if ((pd[j] & PG_V) == PG_V) {
+ pt = (uint64_t *)PHYS_TO_DMAP(pd[j] & PG_FRAME);
+ error = blk_write(di, (char *)pt, 0, PAGE_SIZE);
+ if (error)
+ goto fail;
+ } else {
+ bzero(fakept, sizeof(fakept));
+ error = blk_write(di, (char *)&fakept, 0, PAGE_SIZE);
+ if (error)
+ goto fail;
+ /* flush, in case we reuse fakept in the same block */
+ error = blk_flush(di);
+ if (error)
+ goto fail;
+ }
+ }
+
+ /* Dump memory chunks */
+ /* XXX cluster it up and use blk_dump() */
+ for (i = 0; i < vm_page_dump_size / sizeof(*vm_page_dump); i++) {
+ bits = vm_page_dump[i];
+ while (bits) {
+ bit = bsfq(bits);
+ pa = (((uint64_t)i * sizeof(*vm_page_dump) * NBBY) + bit) * PAGE_SIZE;
+ error = blk_write(di, 0, pa, PAGE_SIZE);
+ if (error)
+ goto fail;
+ bits &= ~(1ul << bit);
+ }
+ }
+
+ error = blk_flush(di);
+ if (error)
+ goto fail;
+
+ /* Dump trailer */
+ error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
+ if (error)
+ goto fail;
+ dumplo += sizeof(kdh);
+
+ /* Signal completion, signoff and exit stage left. */
+ dump_write(di, NULL, 0, 0, 0);
+ printf("\nDump complete\n");
+ return;
+
+ fail:
+ if (error < 0)
+ error = -error;
+
+ if (error == ECANCELED)
+ printf("\nDump aborted\n");
+ else if (error == ENOSPC)
+ printf("\nDump failed. Partition too small.\n");
+ else
+ printf("\n** DUMP FAILED (ERROR %d) **\n", error);
+}
+
+void
+dump_add_page(vm_paddr_t pa)
+{
+ int idx, bit;
+
+ pa >>= PAGE_SHIFT;
+ idx = pa >> 6; /* 2^6 = 64 */
+ bit = pa & 63;
+ atomic_set_long(&vm_page_dump[idx], 1ul << bit);
+}
+
+void
+dump_drop_page(vm_paddr_t pa)
+{
+ int idx, bit;
+
+ pa >>= PAGE_SHIFT;
+ idx = pa >> 6; /* 2^6 = 64 */
+ bit = pa & 63;
+ atomic_clear_long(&vm_page_dump[idx], 1ul << bit);
+}
Index: prof_machdep.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/prof_machdep.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/amd64/prof_machdep.c -L sys/amd64/amd64/prof_machdep.c -u -r1.1.1.1 -r1.2
--- sys/amd64/amd64/prof_machdep.c
+++ sys/amd64/amd64/prof_machdep.c
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/prof_machdep.c,v 1.24 2005/05/14 09:10:00 nyan Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/prof_machdep.c,v 1.29 2007/03/26 18:03:29 njl Exp $");
#ifdef GUPROF
#if 0
@@ -35,22 +35,20 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/cpu.h>
+#include <sys/eventhandler.h>
#include <sys/gmon.h>
#include <sys/kernel.h>
+#include <sys/smp.h>
#include <sys/sysctl.h>
#include <machine/clock.h>
#if 0
#include <machine/perfmon.h>
#endif
-#include <machine/profile.h>
-#undef MCOUNT
-#endif
-
-#include <machine/asmacros.h>
#include <machine/timerreg.h>
-#ifdef GUPROF
#define CPUTIME_CLOCK_UNINITIALIZED 0
#define CPUTIME_CLOCK_I8254 1
#define CPUTIME_CLOCK_TSC 2
@@ -60,11 +58,14 @@
int cputime_bias = 1; /* initialize for locality of reference */
static int cputime_clock = CPUTIME_CLOCK_UNINITIALIZED;
-#ifdef I586_PMC_GUPROF
+#if defined(PERFMON) && defined(I586_PMC_GUPROF)
static u_int cputime_clock_pmc_conf = I586_PMC_GUPROF;
static int cputime_clock_pmc_init;
static struct gmonparam saved_gmp;
#endif
+#if defined(I586_CPU) || defined(I686_CPU)
+static int cputime_prof_active;
+#endif
#endif /* GUPROF */
#ifdef __GNUCLIKE_ASM
@@ -80,7 +81,7 @@
# \n\
# Check that we are profiling. Do it early for speed. \n\
# \n\
- cmpl $GMON_PROF_OFF," __XSTRING(CNAME(_gmonparam)) "+GM_STATE \n\
+ cmpl $GMON_PROF_OFF,_gmonparam+GM_STATE \n\
je .mcount_exit \n\
# \n\
# __mcount is the same as [.]mcount except the caller \n\
@@ -98,11 +99,11 @@
jmp .got_frompc \n\
\n\
.p2align 4,0x90 \n\
- .globl " __XSTRING(HIDENAME(mcount)) " \n\
-" __XSTRING(HIDENAME(mcount)) ": \n\
+ .globl .mcount \n\
+.mcount: \n\
.globl __cyg_profile_func_enter \n\
__cyg_profile_func_enter: \n\
- cmpl $GMON_PROF_OFF," __XSTRING(CNAME(_gmonparam)) "+GM_STATE \n\
+ cmpl $GMON_PROF_OFF,_gmonparam+GM_STATE \n\
je .mcount_exit \n\
# \n\
# The caller's stack frame has already been built, so \n\
@@ -126,7 +127,7 @@
\n\
pushfq \n\
cli \n\
- call " __XSTRING(CNAME(mcount)) " \n\
+ call mcount \n\
popfq \n\
popq %r9 \n\
popq %r8 \n\
@@ -139,7 +140,7 @@
ret \n\
");
#else /* !__GNUCLIKE_ASM */
-#error this file needs to be ported to your compiler
+#error "this file needs to be ported to your compiler"
#endif /* __GNUCLIKE_ASM */
#ifdef GUPROF
@@ -164,11 +165,11 @@
GMON_PROF_HIRES = 4 \n\
\n\
.p2align 4,0x90 \n\
- .globl " __XSTRING(HIDENAME(mexitcount)) " \n\
-" __XSTRING(HIDENAME(mexitcount)) ": \n\
+ .globl .mexitcount \n\
+.mexitcount: \n\
.globl __cyg_profile_func_exit \n\
__cyg_profile_func_exit: \n\
- cmpl $GMON_PROF_HIRES," __XSTRING(CNAME(_gmonparam)) "+GM_STATE \n\
+ cmpl $GMON_PROF_HIRES,_gmonparam+GM_STATE \n\
jne .mexitcount_exit \n\
pushq %rax \n\
pushq %rdx \n\
@@ -180,7 +181,7 @@
movq 7*8(%rsp),%rdi \n\
pushfq \n\
cli \n\
- call " __XSTRING(CNAME(mexitcount)) " \n\
+ call mexitcount \n\
popfq \n\
popq %r9 \n\
popq %r8 \n\
@@ -192,8 +193,6 @@
.mexitcount_exit: \n\
ret \n\
");
-#else /* !__GNUCLIKE_ASM */
-#error this file needs to be ported to your compiler
#endif /* __GNUCLIKE_ASM */
/*
@@ -212,7 +211,7 @@
u_char high, low;
static u_int prev_count;
-#ifndef SMP
+#if defined(I586_CPU) || defined(I686_CPU)
if (cputime_clock == CPUTIME_CLOCK_TSC) {
/*
* Scale the TSC a little to make cputime()'s frequency
@@ -226,7 +225,7 @@
prev_count = count;
return (delta);
}
-#if defined(PERFMON) && defined(I586_PMC_GUPROF)
+#if defined(PERFMON) && defined(I586_PMC_GUPROF) && !defined(SMP)
if (cputime_clock == CPUTIME_CLOCK_I586_PMC) {
/*
* XXX permon_read() should be inlined so that the
@@ -240,8 +239,8 @@
prev_count = count;
return (delta);
}
-#endif /* PERFMON && I586_PMC_GUPROF */
-#endif /* !SMP */
+#endif /* PERFMON && I586_PMC_GUPROF && !SMP */
+#endif /* I586_CPU || I686_CPU */
/*
* Read the current value of the 8254 timer counter 0.
@@ -323,15 +322,17 @@
{
if (cputime_clock == CPUTIME_CLOCK_UNINITIALIZED) {
cputime_clock = CPUTIME_CLOCK_I8254;
-#ifndef SMP
- if (tsc_freq != 0)
+#if defined(I586_CPU) || defined(I686_CPU)
+ if (tsc_freq != 0 && !tsc_is_broken && mp_ncpus == 1)
cputime_clock = CPUTIME_CLOCK_TSC;
#endif
}
gp->profrate = timer_freq << CPUTIME_CLOCK_I8254_SHIFT;
-#ifndef SMP
- if (cputime_clock == CPUTIME_CLOCK_TSC)
+#if defined(I586_CPU) || defined(I686_CPU)
+ if (cputime_clock == CPUTIME_CLOCK_TSC) {
gp->profrate = tsc_freq >> 1;
+ cputime_prof_active = 1;
+ }
#if defined(PERFMON) && defined(I586_PMC_GUPROF)
else if (cputime_clock == CPUTIME_CLOCK_I586_PMC) {
if (perfmon_avail() &&
@@ -358,7 +359,7 @@
}
}
#endif /* PERFMON && I586_PMC_GUPROF */
-#endif /* !SMP */
+#endif /* I586_CPU || I686_CPU */
cputime_bias = 0;
cputime();
}
@@ -374,18 +375,27 @@
cputime_clock_pmc_init = FALSE;
}
#endif
+#if defined(I586_CPU) || defined(I686_CPU)
+ if (cputime_clock == CPUTIME_CLOCK_TSC)
+ cputime_prof_active = 0;
+#endif
}
-#else /* !GUPROF */
-#ifdef __GNUCLIKE_ASM
-__asm(" \n\
- .text \n\
- .p2align 4,0x90 \n\
- .globl " __XSTRING(HIDENAME(mexitcount)) " \n\
-" __XSTRING(HIDENAME(mexitcount)) ": \n\
- ret \n\
-");
-#else /* !__GNUCLIKE_ASM */
-#error this file needs to be ported to your compiler
-#endif /* __GNUCLIKE_ASM */
+#if defined(I586_CPU) || defined(I686_CPU)
+/* If the cpu frequency changed while profiling, report a warning. */
+static void
+tsc_freq_changed(void *arg, const struct cf_level *level, int status)
+{
+
+ /* If there was an error during the transition, don't do anything. */
+ if (status != 0)
+ return;
+ if (cputime_prof_active && cputime_clock == CPUTIME_CLOCK_TSC)
+ printf("warning: cpu freq changed while profiling active\n");
+}
+
+EVENTHANDLER_DEFINE(cpufreq_post_change, tsc_freq_changed, NULL,
+ EVENTHANDLER_PRI_ANY);
+#endif /* I586_CPU || I686_CPU */
+
#endif /* GUPROF */
--- /dev/null
+++ sys/amd64/amd64/bpf_jit_machdep.h
@@ -0,0 +1,437 @@
+/*-
+ * Copyright (c) 2002 - 2003 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 Jung-uk Kim <jkim at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS intERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/amd64/amd64/bpf_jit_machdep.h,v 1.3 2005/12/06 20:11:07 jkim Exp $
+ */
+
+#ifndef _BPF_JIT_MACHDEP_H_
+#define _BPF_JIT_MACHDEP_H_
+
+/*
+ * Registers
+ */
+#define RAX 0
+#define RCX 1
+#define RDX 2
+#define RBX 3
+#define RSP 4
+#define RBP 5
+#define RSI 6
+#define RDI 7
+
+#define EAX 0
+#define ECX 1
+#define EDX 2
+#define EBX 3
+#define ESP 4
+#define EBP 5
+#define ESI 6
+#define EDI 7
+
+#define AX 0
+#define CX 1
+#define DX 2
+#define BX 3
+#define SP 4
+#define BP 5
+#define SI 6
+#define DI 7
+
+#define AL 0
+#define CL 1
+#define DL 2
+#define BL 3
+
+/* A stream of native binary code.*/
+typedef struct bpf_bin_stream {
+ /* Current native instruction pointer. */
+ int cur_ip;
+
+ /*
+ * Current BPF instruction pointer, i.e. position in
+ * the BPF program reached by the jitter.
+ */
+ int bpf_pc;
+
+ /* Instruction buffer, contains the generated native code. */
+ char *ibuf;
+
+ /* Jumps reference table. */
+ u_int *refs;
+} bpf_bin_stream;
+
+/*
+ * Prototype of the emit functions.
+ *
+ * Different emit functions are used to create the reference table and
+ * to generate the actual filtering code. This allows to have simpler
+ * instruction macros.
+ * The first parameter is the stream that will receive the data.
+ * The second one is a variable containing the data.
+ * The third one is the length, that can be 1, 2, or 4 since it is possible
+ * to emit a byte, a short, or a word at a time.
+ */
+typedef void (*emit_func)(bpf_bin_stream *stream, u_int value, u_int n);
+
+/*
+ * native Instruction Macros
+ */
+
+/* mov r32,i32 */
+#define MOVid(r32, i32) do { \
+ emitm(&stream, (11 << 4) | (1 << 3) | (r32 & 0x7), 1); \
+ emitm(&stream, i32, 4); \
+} while (0)
+
+/* mov r64,i64 */
+#define MOViq(r64, i64) do { \
+ emitm(&stream, 0x48, 1); \
+ emitm(&stream, (11 << 4) | (1 << 3) | (r64 & 0x7), 1); \
+ emitm(&stream, i64, 4); \
+ emitm(&stream, (i64 >> 32), 4); \
+} while (0)
+
+/* mov dr32,sr32 */
+#define MOVrd(dr32, sr32) do { \
+ emitm(&stream, (8 << 4) | 3 | (1 << 3), 1); \
+ emitm(&stream, \
+ (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \
+} while (0)
+
+/* mov dr64,sr64 */
+#define MOVrq(dr64, sr64) do { \
+ emitm(&stream, 0x48, 1); \
+ emitm(&stream, (8 << 4) | 3 | (1 << 3), 1); \
+ emitm(&stream, \
+ (3 << 6) | ((dr64 & 0x7) << 3) | (sr64 & 0x7), 1); \
+} while (0)
+
+/* mov dr32,sr64[off] */
+#define MOVodd(dr32, sr64, off) do { \
+ emitm(&stream, (8 << 4) | 3 | (1 << 3), 1); \
+ emitm(&stream, \
+ (1 << 6) | ((dr32 & 0x7) << 3) | (sr64 & 0x7), 1); \
+ emitm(&stream, off, 1); \
+} while (0)
+
+/* mov dr64[off],sr32 */
+#define MOVoqd(dr64, off, sr32) do { \
+ emitm(&stream, (8 << 4) | 1 | (1 << 3), 1); \
+ emitm(&stream, \
+ (1 << 6) | ((sr32 & 0x7) << 3) | (dr64 & 0x7), 1); \
+ emitm(&stream, off, 1); \
+} while (0)
+
+/* mov dr32,sr64[or64] */
+#define MOVobd(dr32, sr64, or64) do { \
+ emitm(&stream, (8 << 4) | 3 | (1 << 3), 1); \
+ emitm(&stream, ((dr32 & 0x7) << 3) | 4, 1); \
+ emitm(&stream, ((or64 & 0x7) << 3) | (sr64 & 0x7), 1); \
+} while (0)
+
+/* mov dr16,sr64[or64] */
+#define MOVobw(dr32, sr64, or64) do { \
+ emitm(&stream, 0x66, 1); \
+ emitm(&stream, (8 << 4) | 3 | (1 << 3), 1); \
+ emitm(&stream, ((dr32 & 0x7) << 3) | 4, 1); \
+ emitm(&stream, ((or64 & 0x7) << 3) | (sr64 & 0x7), 1); \
+} while (0)
+
+/* mov dr8,sr64[or64] */
+#define MOVobb(dr8, sr64, or64) do { \
+ emitm(&stream, 0x8a, 1); \
+ emitm(&stream, ((dr8 & 0x7) << 3) | 4, 1); \
+ emitm(&stream, ((or64 & 0x7) << 3) | (sr64 & 0x7), 1); \
+} while (0)
+
+/* mov [dr64][or64],sr32 */
+#define MOVomd(dr64, or64, sr32) do { \
+ emitm(&stream, 0x89, 1); \
+ emitm(&stream, ((sr32 & 0x7) << 3) | 4, 1); \
+ emitm(&stream, ((or64 & 0x7) << 3) | (dr64 & 0x7), 1); \
+} while (0)
+
+/* bswap dr32 */
+#define BSWAP(dr32) do { \
+ emitm(&stream, 0xf, 1); \
+ emitm(&stream, (0x19 << 3) | dr32, 1); \
+} while (0)
+
+/* xchg al,ah */
+#define SWAP_AX() do { \
+ emitm(&stream, 0x86, 1); \
+ emitm(&stream, 0xc4, 1); \
+} while (0)
+
+/* push r64 */
+#define PUSH(r64) do { \
+ emitm(&stream, (5 << 4) | (0 << 3) | (r64 & 0x7), 1); \
+} while (0)
+
+/* pop r64 */
+#define POP(r64) do { \
+ emitm(&stream, (5 << 4) | (1 << 3) | (r64 & 0x7), 1); \
+} while (0)
+
+/* leave/ret */
+#define LEAVE_RET() do { \
+ emitm(&stream, 0xc9, 1); \
+ emitm(&stream, 0xc3, 1); \
+} while (0)
+
+/* add dr32,sr32 */
+#define ADDrd(dr32, sr32) do { \
+ emitm(&stream, 0x03, 1); \
+ emitm(&stream, \
+ (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \
+} while (0)
+
+/* add eax,i32 */
+#define ADD_EAXi(i32) do { \
+ emitm(&stream, 0x05, 1); \
+ emitm(&stream, i32, 4); \
+} while (0)
+
+/* add r32,i32 */
+#define ADDid(r32, i32) do { \
+ emitm(&stream, 0x81, 1); \
+ emitm(&stream, (24 << 3) | r32, 1); \
+ emitm(&stream, i32, 4); \
+} while (0)
+
+/* add r32,i8 */
+#define ADDib(r32, i8) do { \
+ emitm(&stream, 0x83, 1); \
+ emitm(&stream, (24 << 3) | r32, 1); \
+ emitm(&stream, i8, 1); \
+} while (0)
+
+/* sub dr32,sr32 */
+#define SUBrd(dr32, sr32) do { \
+ emitm(&stream, 0x2b, 1); \
+ emitm(&stream, \
+ (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \
+} while (0)
+
+/* sub eax,i32 */
+#define SUB_EAXi(i32) do { \
+ emitm(&stream, 0x2d, 1); \
+ emitm(&stream, i32, 4); \
+} while (0)
+
+/* mul r32 */
+#define MULrd(r32) do { \
+ emitm(&stream, 0xf7, 1); \
+ emitm(&stream, (7 << 5) | (r32 & 0x7), 1); \
+} while (0)
+
+/* div r32 */
+#define DIVrd(r32) do { \
+ emitm(&stream, 0xf7, 1); \
+ emitm(&stream, (15 << 4) | (r32 & 0x7), 1); \
+} while (0)
+
+/* and r8,i8 */
+#define ANDib(r8, i8) do { \
+ emitm(&stream, 0x80, 1); \
+ emitm(&stream, (7 << 5) | r8, 1); \
+ emitm(&stream, i8, 1); \
+} while (0)
+
+/* and r32,i32 */
+#define ANDid(r32, i32) do { \
+ if (r32 == EAX) { \
+ emitm(&stream, 0x25, 1); \
+ emitm(&stream, i32, 4); \
+ } else { \
+ emitm(&stream, 0x81, 1); \
+ emitm(&stream, (7 << 5) | r32, 1); \
+ emitm(&stream, i32, 4); \
+ } \
+} while (0)
+
+/* and dr32,sr32 */
+#define ANDrd(dr32, sr32) do { \
+ emitm(&stream, 0x23, 1); \
+ emitm(&stream, \
+ (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \
+} while (0)
+
+/* or dr32,sr32 */
+#define ORrd(dr32, sr32) do { \
+ emitm(&stream, 0x0b, 1); \
+ emitm(&stream, \
+ (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \
+} while (0)
+
+/* or r32,i32 */
+#define ORid(r32, i32) do { \
+ if (r32 == EAX) { \
+ emitm(&stream, 0x0d, 1); \
+ emitm(&stream, i32, 4); \
+ } else { \
+ emitm(&stream, 0x81, 1); \
+ emitm(&stream, (25 << 3) | r32, 1); \
+ emitm(&stream, i32, 4); \
+ } \
+} while (0)
+
+/* shl r32,i8 */
+#define SHLib(r32, i8) do { \
+ emitm(&stream, 0xc1, 1); \
+ emitm(&stream, (7 << 5) | (r32 & 0x7), 1); \
+ emitm(&stream, i8, 1); \
+} while (0)
+
+/* shl dr32,cl */
+#define SHL_CLrb(dr32) do { \
+ emitm(&stream, 0xd3, 1); \
+ emitm(&stream, (7 << 5) | (dr32 & 0x7), 1); \
+} while (0)
+
+/* shr r32,i8 */
+#define SHRib(r32, i8) do { \
+ emitm(&stream, 0xc1, 1); \
+ emitm(&stream, (29 << 3) | (r32 & 0x7), 1); \
+ emitm(&stream, i8, 1); \
+} while (0)
+
+/* shr dr32,cl */
+#define SHR_CLrb(dr32) do { \
+ emitm(&stream, 0xd3, 1); \
+ emitm(&stream, (29 << 3) | (dr32 & 0x7), 1); \
+} while (0)
+
+/* neg r32 */
+#define NEGd(r32) do { \
+ emitm(&stream, 0xf7, 1); \
+ emitm(&stream, (27 << 3) | (r32 & 0x7), 1); \
+} while (0)
+
+/* cmp dr32,sr64[off] */
+#define CMPodd(dr32, sr64, off) do { \
+ emitm(&stream, (3 << 4) | 3 | (1 << 3), 1); \
+ emitm(&stream, \
+ (1 << 6) | ((dr32 & 0x7) << 3) | (sr64 & 0x7), 1); \
+ emitm(&stream, off, 1); \
+} while (0)
+
+/* cmp dr32,sr32 */
+#define CMPrd(dr32, sr32) do { \
+ emitm(&stream, 0x3b, 1); \
+ emitm(&stream, \
+ (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \
+} while (0)
+
+/* cmp dr32,i32 */
+#define CMPid(dr32, i32) do { \
+ if (dr32 == EAX){ \
+ emitm(&stream, 0x3d, 1); \
+ emitm(&stream, i32, 4); \
+ } else { \
+ emitm(&stream, 0x81, 1); \
+ emitm(&stream, (0x1f << 3) | (dr32 & 0x7), 1); \
+ emitm(&stream, i32, 4); \
+ } \
+} while (0)
+
+/* jne off32 */
+#define JNEb(off8) do { \
+ emitm(&stream, 0x75, 1); \
+ emitm(&stream, off8, 1); \
+} while (0)
+
+/* je off32 */
+#define JE(off32) do { \
+ emitm(&stream, 0x0f, 1); \
+ emitm(&stream, 0x84, 1); \
+ emitm(&stream, off32, 4); \
+} while (0)
+
+/* jle off32 */
+#define JLE(off32) do { \
+ emitm(&stream, 0x0f, 1); \
+ emitm(&stream, 0x8e, 1); \
+ emitm(&stream, off32, 4); \
+} while (0)
+
+/* jle off8 */
+#define JLEb(off8) do { \
+ emitm(&stream, 0x7e, 1); \
+ emitm(&stream, off8, 1); \
+} while (0)
+
+/* ja off32 */
+#define JA(off32) do { \
+ emitm(&stream, 0x0f, 1); \
+ emitm(&stream, 0x87, 1); \
+ emitm(&stream, off32, 4); \
+} while (0)
+
+/* jae off32 */
+#define JAE(off32) do { \
+ emitm(&stream, 0x0f, 1); \
+ emitm(&stream, 0x83, 1); \
+ emitm(&stream, off32, 4); \
+} while (0)
+
+/* jg off32 */
+#define JG(off32) do { \
+ emitm(&stream, 0x0f, 1); \
+ emitm(&stream, 0x8f, 1); \
+ emitm(&stream, off32, 4); \
+} while (0)
+
+/* jge off32 */
+#define JGE(off32) do { \
+ emitm(&stream, 0x0f, 1); \
+ emitm(&stream, 0x8d, 1); \
+ emitm(&stream, off32, 4); \
+} while (0)
+
+/* jmp off32 */
+#define JMP(off32) do { \
+ emitm(&stream, 0xe9, 1); \
+ emitm(&stream, off32, 4); \
+} while (0)
+
+/* xor eax,eax */
+#define ZERO_EAX() do { \
+ emitm(&stream, 0x31, 1); \
+ emitm(&stream, 0xc0, 1); \
+} while (0)
+
+/* xor edx,edx */
+#define ZERO_EDX() do { \
+ emitm(&stream, 0x31, 1); \
+ emitm(&stream, 0xd2, 1); \
+} while (0)
+
+#endif /* _BPF_JIT_MACHDEP_H_ */
--- /dev/null
+++ sys/amd64/amd64/msi.c
@@ -0,0 +1,506 @@
+/*-
+ * Copyright (c) 2006 Yahoo!, Inc.
+ * All rights reserved.
+ * Written by: John Baldwin <jhb at FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Support for PCI Message Signalled Interrupts (MSI). MSI interrupts on
+ * x86 are basically APIC messages that the northbridge delivers directly
+ * to the local APICs as if they had come from an I/O APIC.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/msi.c,v 1.6.2.1 2007/10/30 18:00:55 jhb Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/sx.h>
+#include <sys/systm.h>
+#include <machine/apicreg.h>
+#include <machine/md_var.h>
+#include <machine/frame.h>
+#include <machine/intr_machdep.h>
+#include <machine/apicvar.h>
+#include <dev/pci/pcivar.h>
+
+/* Fields in address for Intel MSI messages. */
+#define MSI_INTEL_ADDR_DEST 0x000ff000
+#define MSI_INTEL_ADDR_RH 0x00000008
+# define MSI_INTEL_ADDR_RH_ON 0x00000008
+# define MSI_INTEL_ADDR_RH_OFF 0x00000000
+#define MSI_INTEL_ADDR_DM 0x00000004
+# define MSI_INTEL_ADDR_DM_PHYSICAL 0x00000000
+# define MSI_INTEL_ADDR_DM_LOGICAL 0x00000004
+
+/* Fields in data for Intel MSI messages. */
+#define MSI_INTEL_DATA_TRGRMOD IOART_TRGRMOD /* Trigger mode. */
+# define MSI_INTEL_DATA_TRGREDG IOART_TRGREDG
+# define MSI_INTEL_DATA_TRGRLVL IOART_TRGRLVL
+#define MSI_INTEL_DATA_LEVEL 0x00004000 /* Polarity. */
+# define MSI_INTEL_DATA_DEASSERT 0x00000000
+# define MSI_INTEL_DATA_ASSERT 0x00004000
+#define MSI_INTEL_DATA_DELMOD IOART_DELMOD /* Delivery mode. */
+# define MSI_INTEL_DATA_DELFIXED IOART_DELFIXED
+# define MSI_INTEL_DATA_DELLOPRI IOART_DELLOPRI
+# define MSI_INTEL_DATA_DELSMI IOART_DELSMI
+# define MSI_INTEL_DATA_DELNMI IOART_DELNMI
+# define MSI_INTEL_DATA_DELINIT IOART_DELINIT
+# define MSI_INTEL_DATA_DELEXINT IOART_DELEXINT
+#define MSI_INTEL_DATA_INTVEC IOART_INTVEC /* Interrupt vector. */
+
+/*
+ * Build Intel MSI message and data values from a source. AMD64 systems
+ * seem to be compatible, so we use the same function for both.
+ */
+#define INTEL_ADDR(msi) \
+ (MSI_INTEL_ADDR_BASE | (msi)->msi_cpu << 12 | \
+ MSI_INTEL_ADDR_RH_OFF | MSI_INTEL_ADDR_DM_PHYSICAL)
+#define INTEL_DATA(msi) \
+ (MSI_INTEL_DATA_TRGREDG | MSI_INTEL_DATA_DELFIXED | (msi)->msi_vector)
+
+static MALLOC_DEFINE(M_MSI, "msi", "PCI MSI");
+
+/*
+ * MSI sources are bunched into groups. This is because MSI forces
+ * all of the messages to share the address and data registers and
+ * thus certain properties (such as the local APIC ID target on x86).
+ * Each group has a 'first' source that contains information global to
+ * the group. These fields are marked with (g) below.
+ *
+ * Note that local APIC ID is kind of special. Each message will be
+ * assigned an ID by the system; however, a group will use the ID from
+ * the first message.
+ *
+ * For MSI-X, each message is isolated.
+ */
+struct msi_intsrc {
+ struct intsrc msi_intsrc;
+ device_t msi_dev; /* Owning device. (g) */
+ struct msi_intsrc *msi_first; /* First source in group. */
+ u_int msi_irq; /* IRQ cookie. */
+ u_int msi_msix; /* MSI-X message. */
+ u_int msi_vector:8; /* IDT vector. */
+ u_int msi_cpu:8; /* Local APIC ID. (g) */
+ u_int msi_count:8; /* Messages in this group. (g) */
+};
+
+static void msi_create_source(void);
+static void msi_enable_source(struct intsrc *isrc);
+static void msi_disable_source(struct intsrc *isrc, int eoi);
+static void msi_eoi_source(struct intsrc *isrc);
+static void msi_enable_intr(struct intsrc *isrc);
+static void msi_disable_intr(struct intsrc *isrc);
+static int msi_vector(struct intsrc *isrc);
+static int msi_source_pending(struct intsrc *isrc);
+static int msi_config_intr(struct intsrc *isrc, enum intr_trigger trig,
+ enum intr_polarity pol);
+static void msi_assign_cpu(struct intsrc *isrc, u_int apic_id);
+
+struct pic msi_pic = { msi_enable_source, msi_disable_source, msi_eoi_source,
+ msi_enable_intr, msi_disable_intr, msi_vector,
+ msi_source_pending, NULL, NULL, msi_config_intr,
+ msi_assign_cpu };
+
+static int msi_enabled;
+static int msi_last_irq;
+static struct mtx msi_lock;
+
+static void
+msi_enable_source(struct intsrc *isrc)
+{
+}
+
+static void
+msi_disable_source(struct intsrc *isrc, int eoi)
+{
+
+ if (eoi == PIC_EOI)
+ lapic_eoi();
+}
+
+static void
+msi_eoi_source(struct intsrc *isrc)
+{
+
+ lapic_eoi();
+}
+
+static void
+msi_enable_intr(struct intsrc *isrc)
+{
+ struct msi_intsrc *msi = (struct msi_intsrc *)isrc;
+
+ apic_enable_vector(msi->msi_vector);
+}
+
+static void
+msi_disable_intr(struct intsrc *isrc)
+{
+ struct msi_intsrc *msi = (struct msi_intsrc *)isrc;
+
+ apic_disable_vector(msi->msi_vector);
+}
+
+static int
+msi_vector(struct intsrc *isrc)
+{
+ struct msi_intsrc *msi = (struct msi_intsrc *)isrc;
+
+ return (msi->msi_irq);
+}
+
+static int
+msi_source_pending(struct intsrc *isrc)
+{
+
+ return (0);
+}
+
+static int
+msi_config_intr(struct intsrc *isrc, enum intr_trigger trig,
+ enum intr_polarity pol)
+{
+
+ return (ENODEV);
+}
+
+static void
+msi_assign_cpu(struct intsrc *isrc, u_int apic_id)
+{
+ struct msi_intsrc *msi = (struct msi_intsrc *)isrc;
+
+ msi->msi_cpu = apic_id;
+ if (bootverbose)
+ printf("msi: Assigning %s IRQ %d to local APIC %u\n",
+ msi->msi_msix ? "MSI-X" : "MSI", msi->msi_irq,
+ msi->msi_cpu);
+ pci_remap_msi_irq(msi->msi_dev, msi->msi_irq);
+}
+
+void
+msi_init(void)
+{
+
+ /* Check if we have a supported CPU. */
+ if (!(strcmp(cpu_vendor, "GenuineIntel") == 0 ||
+ strcmp(cpu_vendor, "AuthenticAMD") == 0))
+ return;
+
+ msi_enabled = 1;
+ intr_register_pic(&msi_pic);
+ mtx_init(&msi_lock, "msi", NULL, MTX_DEF);
+}
+
+void
+msi_create_source(void)
+{
+ struct msi_intsrc *msi;
+ u_int irq;
+
+ mtx_lock(&msi_lock);
+ if (msi_last_irq >= NUM_MSI_INTS) {
+ mtx_unlock(&msi_lock);
+ return;
+ }
+ irq = msi_last_irq + FIRST_MSI_INT;
+ msi_last_irq++;
+ mtx_unlock(&msi_lock);
+
+ msi = malloc(sizeof(struct msi_intsrc), M_MSI, M_WAITOK | M_ZERO);
+ msi->msi_intsrc.is_pic = &msi_pic;
+ msi->msi_irq = irq;
+ intr_register_source(&msi->msi_intsrc);
+ nexus_add_irq(irq);
+}
+
+/*
+ * Try to allocate 'count' interrupt sources with contiguous IDT values. If
+ * we allocate any new sources, then their IRQ values will be at the end of
+ * the irqs[] array, with *newirq being the index of the first new IRQ value
+ * and *newcount being the number of new IRQ values added.
+ */
+int
+msi_alloc(device_t dev, int count, int maxcount, int *irqs)
+{
+ struct msi_intsrc *msi, *fsrc;
+ int cnt, i, vector;
+
+ if (!msi_enabled)
+ return (ENXIO);
+
+again:
+ mtx_lock(&msi_lock);
+
+ /* Try to find 'count' free IRQs. */
+ cnt = 0;
+ for (i = FIRST_MSI_INT; i < FIRST_MSI_INT + NUM_MSI_INTS; i++) {
+ msi = (struct msi_intsrc *)intr_lookup_source(i);
+
+ /* End of allocated sources, so break. */
+ if (msi == NULL)
+ break;
+
+ /* If this is a free one, save its IRQ in the array. */
+ if (msi->msi_dev == NULL) {
+ irqs[cnt] = i;
+ cnt++;
+ if (cnt == count)
+ break;
+ }
+ }
+
+ /* Do we need to create some new sources? */
+ if (cnt < count) {
+ /* If we would exceed the max, give up. */
+ if (i + (count - cnt) > FIRST_MSI_INT + NUM_MSI_INTS) {
+ mtx_unlock(&msi_lock);
+ return (ENXIO);
+ }
+ mtx_unlock(&msi_lock);
+
+ /* We need count - cnt more sources. */
+ while (cnt < count) {
+ msi_create_source();
+ cnt++;
+ }
+ goto again;
+ }
+
+ /* Ok, we now have the IRQs allocated. */
+ KASSERT(cnt == count, ("count mismatch"));
+
+ /* Allocate 'count' IDT vectors. */
+ vector = apic_alloc_vectors(irqs, count, maxcount);
+ if (vector == 0) {
+ mtx_unlock(&msi_lock);
+ return (ENOSPC);
+ }
+
+ /* Assign IDT vectors and make these messages owned by 'dev'. */
+ fsrc = (struct msi_intsrc *)intr_lookup_source(irqs[0]);
+ for (i = 0; i < count; i++) {
+ msi = (struct msi_intsrc *)intr_lookup_source(irqs[i]);
+ msi->msi_dev = dev;
+ msi->msi_vector = vector + i;
+ if (bootverbose)
+ printf("msi: routing MSI IRQ %d to vector %u\n",
+ msi->msi_irq, msi->msi_vector);
+ msi->msi_first = fsrc;
+ KASSERT(msi->msi_intsrc.is_handlers == 0,
+ ("dead MSI has handlers"));
+ }
+ fsrc->msi_count = count;
+ mtx_unlock(&msi_lock);
+
+ return (0);
+}
+
+int
+msi_release(int *irqs, int count)
+{
+ struct msi_intsrc *msi, *first;
+ int i;
+
+ mtx_lock(&msi_lock);
+ first = (struct msi_intsrc *)intr_lookup_source(irqs[0]);
+ if (first == NULL) {
+ mtx_unlock(&msi_lock);
+ return (ENOENT);
+ }
+
+ /* Make sure this isn't an MSI-X message. */
+ if (first->msi_msix) {
+ mtx_unlock(&msi_lock);
+ return (EINVAL);
+ }
+
+ /* Make sure this message is allocated to a group. */
+ if (first->msi_first == NULL) {
+ mtx_unlock(&msi_lock);
+ return (ENXIO);
+ }
+
+ /*
+ * Make sure this is the start of a group and that we are releasing
+ * the entire group.
+ */
+ if (first->msi_first != first || first->msi_count != count) {
+ mtx_unlock(&msi_lock);
+ return (EINVAL);
+ }
+ KASSERT(first->msi_dev != NULL, ("unowned group"));
+
+ /* Clear all the extra messages in the group. */
+ for (i = 1; i < count; i++) {
+ msi = (struct msi_intsrc *)intr_lookup_source(irqs[i]);
+ KASSERT(msi->msi_first == first, ("message not in group"));
+ KASSERT(msi->msi_dev == first->msi_dev, ("owner mismatch"));
+ msi->msi_first = NULL;
+ msi->msi_dev = NULL;
+ apic_free_vector(msi->msi_vector, msi->msi_irq);
+ msi->msi_vector = 0;
+ }
+
+ /* Clear out the first message. */
+ first->msi_first = NULL;
+ first->msi_dev = NULL;
+ apic_free_vector(first->msi_vector, first->msi_irq);
+ first->msi_vector = 0;
+ first->msi_count = 0;
+
+ mtx_unlock(&msi_lock);
+ return (0);
+}
+
+int
+msi_map(int irq, uint64_t *addr, uint32_t *data)
+{
+ struct msi_intsrc *msi;
+
+ mtx_lock(&msi_lock);
+ msi = (struct msi_intsrc *)intr_lookup_source(irq);
+ if (msi == NULL) {
+ mtx_unlock(&msi_lock);
+ return (ENOENT);
+ }
+
+ /* Make sure this message is allocated to a device. */
+ if (msi->msi_dev == NULL) {
+ mtx_unlock(&msi_lock);
+ return (ENXIO);
+ }
+
+ /*
+ * If this message isn't an MSI-X message, make sure it's part
+ * of a group, and switch to the first message in the
+ * group.
+ */
+ if (!msi->msi_msix) {
+ if (msi->msi_first == NULL) {
+ mtx_unlock(&msi_lock);
+ return (ENXIO);
+ }
+ msi = msi->msi_first;
+ }
+
+ *addr = INTEL_ADDR(msi);
+ *data = INTEL_DATA(msi);
+ mtx_unlock(&msi_lock);
+ return (0);
+}
+
+int
+msix_alloc(device_t dev, int *irq)
+{
+ struct msi_intsrc *msi;
+ int i, vector;
+
+ if (!msi_enabled)
+ return (ENXIO);
+
+again:
+ mtx_lock(&msi_lock);
+
+ /* Find a free IRQ. */
+ for (i = FIRST_MSI_INT; i < FIRST_MSI_INT + NUM_MSI_INTS; i++) {
+ msi = (struct msi_intsrc *)intr_lookup_source(i);
+
+ /* End of allocated sources, so break. */
+ if (msi == NULL)
+ break;
+
+ /* Stop at the first free source. */
+ if (msi->msi_dev == NULL)
+ break;
+ }
+
+ /* Do we need to create a new source? */
+ if (msi == NULL) {
+ /* If we would exceed the max, give up. */
+ if (i + 1 > FIRST_MSI_INT + NUM_MSI_INTS) {
+ mtx_unlock(&msi_lock);
+ return (ENXIO);
+ }
+ mtx_unlock(&msi_lock);
+
+ /* Create a new source. */
+ msi_create_source();
+ goto again;
+ }
+
+ /* Allocate an IDT vector. */
+ vector = apic_alloc_vector(i);
+ if (bootverbose)
+ printf("msi: routing MSI-X IRQ %d to vector %u\n", msi->msi_irq,
+ vector);
+
+ /* Setup source. */
+ msi->msi_dev = dev;
+ msi->msi_vector = vector;
+ msi->msi_msix = 1;
+
+ KASSERT(msi->msi_intsrc.is_handlers == 0, ("dead MSI-X has handlers"));
+ mtx_unlock(&msi_lock);
+
+ *irq = i;
+ return (0);
+}
+
+int
+msix_release(int irq)
+{
+ struct msi_intsrc *msi;
+
+ mtx_lock(&msi_lock);
+ msi = (struct msi_intsrc *)intr_lookup_source(irq);
+ if (msi == NULL) {
+ mtx_unlock(&msi_lock);
+ return (ENOENT);
+ }
+
+ /* Make sure this is an MSI-X message. */
+ if (!msi->msi_msix) {
+ mtx_unlock(&msi_lock);
+ return (EINVAL);
+ }
+
+ KASSERT(msi->msi_dev != NULL, ("unowned message"));
+
+ /* Clear out the message. */
+ msi->msi_dev = NULL;
+ apic_free_vector(msi->msi_vector, msi->msi_irq);
+ msi->msi_vector = 0;
+ msi->msi_msix = 0;
+
+ mtx_unlock(&msi_lock);
+ return (0);
+}
Index: uma_machdep.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/uma_machdep.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/amd64/uma_machdep.c -L sys/amd64/amd64/uma_machdep.c -u -r1.1.1.1 -r1.2
--- sys/amd64/amd64/uma_machdep.c
+++ sys/amd64/amd64/uma_machdep.c
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/uma_machdep.c,v 1.1 2003/10/14 05:51:31 alc Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/uma_machdep.c,v 1.4 2007/09/15 18:47:01 alc Exp $");
#include <sys/param.h>
#include <sys/lock.h>
@@ -44,14 +44,15 @@
{
static vm_pindex_t colour;
vm_page_t m;
+ vm_paddr_t pa;
void *va;
int pflags;
*flags = UMA_SLAB_PRIV;
if ((wait & (M_NOWAIT|M_USE_RESERVE)) == M_NOWAIT)
- pflags = VM_ALLOC_INTERRUPT;
+ pflags = VM_ALLOC_INTERRUPT | VM_ALLOC_WIRED;
else
- pflags = VM_ALLOC_SYSTEM;
+ pflags = VM_ALLOC_SYSTEM | VM_ALLOC_WIRED;
if (wait & M_ZERO)
pflags |= VM_ALLOC_ZERO;
for (;;) {
@@ -64,7 +65,9 @@
} else
break;
}
- va = (void *)PHYS_TO_DMAP(m->phys_addr);
+ pa = m->phys_addr;
+ dump_add_page(pa);
+ va = (void *)PHYS_TO_DMAP(pa);
if ((wait & M_ZERO) && (m->flags & PG_ZERO) == 0)
pagezero(va);
return (va);
@@ -74,9 +77,12 @@
uma_small_free(void *mem, int size, u_int8_t flags)
{
vm_page_t m;
+ vm_paddr_t pa;
- m = PHYS_TO_VM_PAGE(DMAP_TO_PHYS((vm_offset_t)mem));
- vm_page_lock_queues();
+ pa = DMAP_TO_PHYS((vm_offset_t)mem);
+ dump_drop_page(pa);
+ m = PHYS_TO_VM_PAGE(pa);
+ m->wire_count--;
vm_page_free(m);
- vm_page_unlock_queues();
+ atomic_subtract_int(&cnt.v_wire_count, 1);
}
Index: dump_machdep.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/dump_machdep.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/amd64/dump_machdep.c -L sys/amd64/amd64/dump_machdep.c -u -r1.1.1.1 -r1.2
--- sys/amd64/amd64/dump_machdep.c
+++ sys/amd64/amd64/dump_machdep.c
@@ -25,12 +25,13 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/dump_machdep.c,v 1.11 2005/07/02 19:57:30 marcel Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/dump_machdep.c,v 1.12.4.1 2008/01/30 21:21:50 ru Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/cons.h>
+#include <sys/sysctl.h>
#include <sys/kernel.h>
#include <sys/kerneldump.h>
#include <vm/vm.h>
@@ -40,6 +41,11 @@
CTASSERT(sizeof(struct kerneldumpheader) == 512);
+int do_minidump = 1;
+TUNABLE_INT("debug.minidump", &do_minidump);
+SYSCTL_INT(_debug, OID_AUTO, minidump, CTLFLAG_RW, &do_minidump, 0,
+ "Enable mini crash dumps");
+
/*
* Don't touch the first SIZEOF_METADATA bytes on the dump device. This
* is to protect us from metadata and to protect metadata from us.
@@ -134,7 +140,7 @@
ptr += len;
sz -= len;
if (fragsz == DEV_BSIZE) {
- error = di->dumper(di->priv, buffer, 0, dumplo,
+ error = dump_write(di, buffer, 0, dumplo,
DEV_BSIZE);
if (error)
return error;
@@ -154,7 +160,7 @@
if (fragsz == 0)
return (0);
- error = di->dumper(di->priv, buffer, 0, dumplo, DEV_BSIZE);
+ error = dump_write(di, buffer, 0, dumplo, DEV_BSIZE);
dumplo += DEV_BSIZE;
fragsz = 0;
return (error);
@@ -195,7 +201,7 @@
a = pa + i * PAGE_SIZE;
va = pmap_kenter_temporary(trunc_page(a), i);
}
- error = di->dumper(di->priv, va, 0, dumplo, sz);
+ error = dump_write(di, va, 0, dumplo, sz);
if (error)
break;
dumplo += sz;
@@ -272,6 +278,10 @@
size_t hdrsz;
int error;
+ if (do_minidump) {
+ minidumpsys(di);
+ return;
+ }
bzero(&ehdr, sizeof(ehdr));
ehdr.e_ident[EI_MAG0] = ELFMAG0;
ehdr.e_ident[EI_MAG1] = ELFMAG1;
@@ -317,7 +327,7 @@
ehdr.e_phnum);
/* Dump leader */
- error = di->dumper(di->priv, &kdh, 0, dumplo, sizeof(kdh));
+ error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
if (error)
goto fail;
dumplo += sizeof(kdh);
@@ -348,12 +358,12 @@
goto fail;
/* Dump trailer */
- error = di->dumper(di->priv, &kdh, 0, dumplo, sizeof(kdh));
+ error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
if (error)
goto fail;
/* Signal completion, signoff and exit stage left. */
- di->dumper(di->priv, NULL, 0, 0, 0);
+ dump_write(di, NULL, 0, 0, 0);
printf("\nDump complete\n");
return;
Index: mptable_pci.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/amd64/mptable_pci.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/amd64/mptable_pci.c -L sys/amd64/amd64/mptable_pci.c -u -r1.1.1.1 -r1.2
--- sys/amd64/amd64/mptable_pci.c
+++ sys/amd64/amd64/mptable_pci.c
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/mptable_pci.c,v 1.2.8.1 2005/09/18 02:55:09 imp Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/mptable_pci.c,v 1.8 2007/05/02 17:50:34 jhb Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -72,6 +72,37 @@
return (bus_generic_attach(dev));
}
+/* Pass MSI requests up to the nexus. */
+static int
+mptable_hostb_alloc_msi(device_t pcib, device_t dev, int count, int maxcount,
+ int *irqs)
+{
+ device_t bus;
+
+ bus = device_get_parent(pcib);
+ return (PCIB_ALLOC_MSI(device_get_parent(bus), dev, count, maxcount,
+ irqs));
+}
+
+static int
+mptable_hostb_alloc_msix(device_t pcib, device_t dev, int *irq)
+{
+ device_t bus;
+
+ bus = device_get_parent(pcib);
+ return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq));
+}
+
+static int
+mptable_hostb_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
+ uint32_t *data)
+{
+ device_t bus;
+
+ bus = device_get_parent(pcib);
+ return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data));
+}
+
static device_method_t mptable_hostb_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, mptable_hostb_probe),
@@ -96,17 +127,19 @@
DEVMETHOD(pcib_read_config, legacy_pcib_read_config),
DEVMETHOD(pcib_write_config, legacy_pcib_write_config),
DEVMETHOD(pcib_route_interrupt, mptable_pci_route_interrupt),
+ DEVMETHOD(pcib_alloc_msi, mptable_hostb_alloc_msi),
+ DEVMETHOD(pcib_release_msi, pcib_release_msi),
+ DEVMETHOD(pcib_alloc_msix, mptable_hostb_alloc_msix),
+ DEVMETHOD(pcib_release_msix, pcib_release_msix),
+ DEVMETHOD(pcib_map_msi, mptable_hostb_map_msi),
{ 0, 0 }
};
-static driver_t mptable_hostb_driver = {
- "pcib",
- mptable_hostb_methods,
- 1,
-};
+static devclass_t hostb_devclass;
-DRIVER_MODULE(mptable_pcib, legacy, mptable_hostb_driver, pcib_devclass, 0, 0);
+DEFINE_CLASS_0(pcib, mptable_hostb_driver, mptable_hostb_methods, 1);
+DRIVER_MODULE(mptable_pcib, legacy, mptable_hostb_driver, hostb_devclass, 0, 0);
/* PCI to PCI bridge driver. */
@@ -151,15 +184,17 @@
DEVMETHOD(pcib_read_config, pcib_read_config),
DEVMETHOD(pcib_write_config, pcib_write_config),
DEVMETHOD(pcib_route_interrupt, mptable_pci_route_interrupt),
+ DEVMETHOD(pcib_alloc_msi, pcib_alloc_msi),
+ DEVMETHOD(pcib_release_msi, pcib_release_msi),
+ DEVMETHOD(pcib_alloc_msix, pcib_alloc_msix),
+ DEVMETHOD(pcib_release_msix, pcib_release_msix),
+ DEVMETHOD(pcib_map_msi, pcib_map_msi),
{0, 0}
};
-static driver_t mptable_pcib_driver = {
- "pcib",
- mptable_pcib_pci_methods,
- sizeof(struct pcib_softc),
-};
+static devclass_t pcib_devclass;
+DEFINE_CLASS_0(pcib, mptable_pcib_driver, mptable_pcib_pci_methods,
+ sizeof(struct pcib_softc));
DRIVER_MODULE(mptable_pcib, pci, mptable_pcib_driver, pcib_devclass, 0, 0);
-
Index: syscalls.master
===================================================================
RCS file: /home/cvs/src/sys/amd64/linux32/syscalls.master,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/linux32/syscalls.master -L sys/amd64/linux32/syscalls.master -u -r1.1.1.1 -r1.2
--- sys/amd64/linux32/syscalls.master
+++ sys/amd64/linux32/syscalls.master
@@ -1,17 +1,17 @@
- $FreeBSD: src/sys/amd64/linux32/syscalls.master,v 1.4.2.1 2005/07/20 17:42:14 jhb Exp $
+ $FreeBSD: src/sys/amd64/linux32/syscalls.master,v 1.30 2007/09/18 19:50:32 dwmalone Exp $
; @(#)syscalls.master 8.1 (Berkeley) 7/19/93
; System call name/number master file (or rather, slave, from LINUX).
; Processed to create linux_sysent.c, linux_proto.h and linux_syscall.h.
-; Columns: number type nargs name alt{name,tag,rtyp}/comments
+; Columns: number audit type nargs name alt{name,tag,rtyp}/comments
; number system call number, must be in order
; audit the audit event associated with the system call
; A value of AUE_NULL means no auditing, but it also means that
; there is no audit event for the call at this time. For the
; case where the event exists, but we don't want auditing, the
; event should be #defined to AUE_NULL in audit_kevents.h.
-; type one of STD, OBSOL, UNIMPL, COMPAT
+; type one of STD, OBSOL, UNIMPL
; name psuedo-prototype of syscall routine
; If one of the following alts is different, then all appear:
; altname name of system call if different
@@ -21,8 +21,6 @@
; types:
; STD always included
-; COMPAT included on COMPAT #ifdef
-; LIBCOMPAT included on COMPAT #ifdef, and placed in syscall.h
; OBSOL obsolete, not included in system, only specifies name
; UNIMPL not implemented, placeholder only
@@ -40,395 +38,446 @@
; #ifdef's, etc. may be included, and are copied to the output files.
0 AUE_NULL UNIMPL setup
-1 AUE_NULL MNOPROTO { void sys_exit(int rval); } exit \
+1 AUE_EXIT NOPROTO { void sys_exit(int rval); } exit \
sys_exit_args void
-2 AUE_NULL MSTD { int linux_fork(void); }
-3 AUE_NULL MNOPROTO { int read(int fd, char *buf, \
+2 AUE_FORK STD { int linux_fork(void); }
+3 AUE_NULL NOPROTO { int read(int fd, char *buf, \
u_int nbyte); }
-4 AUE_NULL MNOPROTO { int write(int fd, char *buf, \
+4 AUE_NULL NOPROTO { int write(int fd, char *buf, \
u_int nbyte); }
-5 AUE_NULL MSTD { int linux_open(char *path, l_int flags, \
+5 AUE_OPEN_RWTC STD { int linux_open(char *path, l_int flags, \
l_int mode); }
-6 AUE_NULL MNOPROTO { int close(int fd); }
-7 AUE_NULL MSTD { int linux_waitpid(l_pid_t pid, \
+6 AUE_CLOSE NOPROTO { int close(int fd); }
+7 AUE_WAIT4 STD { int linux_waitpid(l_pid_t pid, \
l_int *status, l_int options); }
-8 AUE_NULL MSTD { int linux_creat(char *path, l_int mode); }
-9 AUE_NULL MSTD { int linux_link(char *path, char *to); }
-10 AUE_NULL MSTD { int linux_unlink(char *path); }
-11 AUE_NULL MSTD { int linux_execve(char *path, char **argp, \
+8 AUE_CREAT STD { int linux_creat(char *path, \
+ l_int mode); }
+9 AUE_LINK STD { int linux_link(char *path, char *to); }
+10 AUE_UNLINK STD { int linux_unlink(char *path); }
+11 AUE_EXECVE STD { int linux_execve(char *path, char **argp, \
char **envp); }
-12 AUE_NULL MSTD { int linux_chdir(char *path); }
-13 AUE_NULL MSTD { int linux_time(l_time_t *tm); }
-14 AUE_NULL MSTD { int linux_mknod(char *path, l_int mode, \
+12 AUE_CHDIR STD { int linux_chdir(char *path); }
+13 AUE_NULL STD { int linux_time(l_time_t *tm); }
+14 AUE_MKNOD STD { int linux_mknod(char *path, l_int mode, \
l_dev_t dev); }
-15 AUE_NULL MSTD { int linux_chmod(char *path, \
+15 AUE_CHMOD STD { int linux_chmod(char *path, \
l_mode_t mode); }
-16 AUE_NULL MSTD { int linux_lchown16(char *path, \
+16 AUE_LCHOWN STD { int linux_lchown16(char *path, \
l_uid16_t uid, l_gid16_t gid); }
17 AUE_NULL UNIMPL break
-18 AUE_NULL UNIMPL stat
-19 AUE_NULL MSTD { int linux_lseek(l_uint fdes, l_off_t off, \
+18 AUE_STAT STD { int linux_stat(char *path, \
+ struct linux_stat *up); }
+19 AUE_LSEEK STD { int linux_lseek(l_uint fdes, l_off_t off, \
l_int whence); }
-20 AUE_NULL MSTD { int linux_getpid(void); }
-21 AUE_NULL STD { int linux_mount(char *specialfile, \
+20 AUE_GETPID STD { int linux_getpid(void); }
+21 AUE_MOUNT STD { int linux_mount(char *specialfile, \
char *dir, char *filesystemtype, \
l_ulong rwflag, void *data); }
-22 AUE_NULL STD { int linux_oldumount(char *path); }
-23 AUE_NULL MSTD { int linux_setuid16(l_uid16_t uid); }
-24 AUE_NULL MSTD { int linux_getuid16(void); }
-25 AUE_NULL MSTD { int linux_stime(void); }
-26 AUE_NULL MSTD { int linux_ptrace(l_long req, l_long pid, \
+22 AUE_UMOUNT STD { int linux_oldumount(char *path); }
+23 AUE_SETUID STD { int linux_setuid16(l_uid16_t uid); }
+24 AUE_GETUID STD { int linux_getuid16(void); }
+25 AUE_SETTIMEOFDAY STD { int linux_stime(void); }
+26 AUE_PTRACE STD { int linux_ptrace(l_long req, l_long pid, \
l_long addr, l_long data); }
-27 AUE_NULL MSTD { int linux_alarm(l_uint secs); }
-28 AUE_NULL UNIMPL fstat
-29 AUE_NULL MSTD { int linux_pause(void); }
-30 AUE_NULL MSTD { int linux_utime(char *fname, \
+27 AUE_NULL STD { int linux_alarm(l_uint secs); }
+28 AUE_FSTAT UNIMPL fstat
+29 AUE_NULL STD { int linux_pause(void); }
+30 AUE_UTIME STD { int linux_utime(char *fname, \
struct l_utimbuf *times); }
31 AUE_NULL UNIMPL stty
32 AUE_NULL UNIMPL gtty
-33 AUE_NULL MSTD { int linux_access(char *path, l_int flags); }
-34 AUE_NULL MSTD { int linux_nice(l_int inc); }
+33 AUE_ACCESS STD { int linux_access(char *path, l_int flags); }
+34 AUE_NICE STD { int linux_nice(l_int inc); }
35 AUE_NULL UNIMPL ftime
-36 AUE_NULL MNOPROTO { int sync(void); }
-37 AUE_NULL MSTD { int linux_kill(l_int pid, l_int signum); }
-38 AUE_NULL MSTD { int linux_rename(char *from, char *to); }
-39 AUE_NULL MSTD { int linux_mkdir(char *path, l_int mode); }
-40 AUE_NULL MSTD { int linux_rmdir(char *path); }
-41 AUE_NULL MNOPROTO { int dup(u_int fd); }
-42 AUE_NULL MSTD { int linux_pipe(l_ulong *pipefds); }
-43 AUE_NULL MSTD { int linux_times(struct l_times_argv *buf); }
+36 AUE_SYNC NOPROTO { int sync(void); }
+37 AUE_KILL STD { int linux_kill(l_int pid, l_int signum); }
+38 AUE_RENAME STD { int linux_rename(char *from, char *to); }
+39 AUE_MKDIR STD { int linux_mkdir(char *path, l_int mode); }
+40 AUE_RMDIR STD { int linux_rmdir(char *path); }
+41 AUE_DUP NOPROTO { int dup(u_int fd); }
+42 AUE_PIPE STD { int linux_pipe(l_ulong *pipefds); }
+43 AUE_NULL STD { int linux_times(struct l_times_argv *buf); }
44 AUE_NULL UNIMPL prof
45 AUE_NULL STD { int linux_brk(l_ulong dsend); }
-46 AUE_NULL MSTD { int linux_setgid16(l_gid16_t gid); }
-47 AUE_NULL MSTD { int linux_getgid16(void); }
-48 AUE_NULL MSTD { int linux_signal(l_int sig, \
+46 AUE_SETGID STD { int linux_setgid16(l_gid16_t gid); }
+47 AUE_GETGID STD { int linux_getgid16(void); }
+48 AUE_NULL STD { int linux_signal(l_int sig, \
l_handler_t handler); }
-49 AUE_NULL MSTD { int linux_geteuid16(void); }
-50 AUE_NULL MSTD { int linux_getegid16(void); }
-51 AUE_NULL MNOPROTO { int acct(char *path); }
-52 AUE_NULL STD { int linux_umount(char *path, l_int flags); }
+49 AUE_GETEUID STD { int linux_geteuid16(void); }
+50 AUE_GETEGID STD { int linux_getegid16(void); }
+51 AUE_ACCT NOPROTO { int acct(char *path); }
+52 AUE_UMOUNT STD { int linux_umount(char *path, l_int flags); }
53 AUE_NULL UNIMPL lock
-54 AUE_NULL STD { int linux_ioctl(l_uint fd, l_uint cmd, \
+54 AUE_IOCTL STD { int linux_ioctl(l_uint fd, l_uint cmd, \
uintptr_t arg); }
-55 AUE_NULL MSTD { int linux_fcntl(l_uint fd, l_uint cmd, \
+55 AUE_FCNTL STD { int linux_fcntl(l_uint fd, l_uint cmd, \
uintptr_t arg); }
56 AUE_NULL UNIMPL mpx
-57 AUE_NULL MNOPROTO { int setpgid(int pid, int pgid); }
+57 AUE_SETPGRP NOPROTO { int setpgid(int pid, int pgid); }
58 AUE_NULL UNIMPL ulimit
-59 AUE_NULL MSTD { int linux_olduname(void); }
-60 AUE_NULL MNOPROTO { int umask(int newmask); }
-61 AUE_NULL MNOPROTO { int chroot(char *path); }
-62 AUE_NULL MSTD { int linux_ustat(l_dev_t dev, \
+59 AUE_NULL STD { int linux_olduname(void); }
+60 AUE_UMASK NOPROTO { int umask(int newmask); }
+61 AUE_CHROOT NOPROTO { int chroot(char *path); }
+62 AUE_NULL STD { int linux_ustat(l_dev_t dev, \
struct l_ustat *ubuf); }
-63 AUE_NULL MNOPROTO { int dup2(u_int from, u_int to); }
-64 AUE_NULL MNOPROTO { int getppid(void); }
-65 AUE_NULL MNOPROTO { int getpgrp(void); }
-66 AUE_NULL MNOPROTO { int setsid(void); }
-67 AUE_NULL MSTD { int linux_sigaction(l_int sig, \
+63 AUE_DUP2 NOPROTO { int dup2(u_int from, u_int to); }
+64 AUE_GETPPID STD { int linux_getppid(void); }
+65 AUE_GETPGRP NOPROTO { int getpgrp(void); }
+66 AUE_SETSID NOPROTO { int setsid(void); }
+67 AUE_NULL STD { int linux_sigaction(l_int sig, \
l_osigaction_t *nsa, \
l_osigaction_t *osa); }
-68 AUE_NULL MSTD { int linux_sgetmask(void); }
-69 AUE_NULL MSTD { int linux_ssetmask(l_osigset_t mask); }
-70 AUE_NULL MSTD { int linux_setreuid16(l_uid16_t ruid, \
+68 AUE_NULL STD { int linux_sgetmask(void); }
+69 AUE_NULL STD { int linux_ssetmask(l_osigset_t mask); }
+70 AUE_SETREUID STD { int linux_setreuid16(l_uid16_t ruid, \
l_uid16_t euid); }
-71 AUE_NULL MSTD { int linux_setregid16(l_gid16_t rgid, \
+71 AUE_SETREGID STD { int linux_setregid16(l_gid16_t rgid, \
l_gid16_t egid); }
-72 AUE_NULL MSTD { int linux_sigsuspend(l_int hist0, \
+72 AUE_NULL STD { int linux_sigsuspend(l_int hist0, \
l_int hist1, l_osigset_t mask); }
-73 AUE_NULL MSTD { int linux_sigpending(l_osigset_t *mask); }
-74 AUE_NULL MNOPROTO { int osethostname(char *hostname, \
- u_int len); } osethostname \
- sethostname_args int
-75 AUE_NULL MSTD { int linux_setrlimit(l_uint resource, \
+73 AUE_NULL STD { int linux_sigpending(l_osigset_t *mask); }
+74 AUE_SYSCTL STD { int linux_sethostname(char *hostname, \
+ u_int len); }
+75 AUE_SETRLIMIT STD { int linux_setrlimit(l_uint resource, \
struct l_rlimit *rlim); }
-76 AUE_NULL MSTD { int linux_old_getrlimit(l_uint resource, \
+76 AUE_GETRLIMIT STD { int linux_old_getrlimit(l_uint resource, \
struct l_rlimit *rlim); }
-77 AUE_NULL MSTD { int linux_getrusage(int who, \
+77 AUE_GETRUSAGE STD { int linux_getrusage(int who, \
struct l_rusage *rusage); }
-78 AUE_NULL MSTD { int linux_gettimeofday( \
+78 AUE_NULL STD { int linux_gettimeofday( \
struct l_timeval *tp, \
struct timezone *tzp); }
-79 AUE_NULL MSTD { int linux_settimeofday( \
+79 AUE_SETTIMEOFDAY STD { int linux_settimeofday( \
struct l_timeval *tp, \
struct timezone *tzp); }
-80 AUE_NULL MSTD { int linux_getgroups16(l_uint gidsetsize, \
+80 AUE_GETGROUPS STD { int linux_getgroups16(l_uint gidsetsize, \
l_gid16_t *gidset); }
-81 AUE_NULL MSTD { int linux_setgroups16(l_uint gidsetsize, \
+81 AUE_SETGROUPS STD { int linux_setgroups16(l_uint gidsetsize, \
l_gid16_t *gidset); }
-82 AUE_NULL MSTD { int linux_old_select( \
+82 AUE_SELECT STD { int linux_old_select( \
struct l_old_select_argv *ptr); }
-83 AUE_NULL MSTD { int linux_symlink(char *path, \
- char *to); }
-84 AUE_NULL UNIMPL ostat
-85 AUE_NULL MSTD { int linux_readlink(char *name, \
- char *buf, l_int count); }
-86 AUE_NULL UNIMPL linux_uselib
-87 AUE_NULL MNOPROTO { int swapon(char *name); }
-88 AUE_NULL MSTD { int linux_reboot(l_int magic1, \
- l_int magic2, l_uint cmd, \
- void *arg); }
-89 AUE_NULL STD { int linux_readdir(l_uint fd, \
+83 AUE_SYMLINK STD { int linux_symlink(char *path, char *to); }
+84 AUE_LSTAT STD { int linux_lstat(char *path, struct linux_lstat *up); }
+85 AUE_READLINK STD { int linux_readlink(char *name, char *buf, \
+ l_int count); }
+86 AUE_USELIB UNIMPL linux_uselib
+87 AUE_SWAPON NOPROTO { int swapon(char *name); }
+88 AUE_REBOOT STD { int linux_reboot(l_int magic1, \
+ l_int magic2, l_uint cmd, void *arg); }
+89 AUE_GETDIRENTRIES STD { int linux_readdir(l_uint fd, \
struct l_dirent *dent, l_uint count); }
-90 AUE_NULL MSTD { int linux_mmap(struct l_mmap_argv *ptr); }
-91 AUE_NULL MNOPROTO { int munmap(caddr_t addr, int len); }
-92 AUE_NULL MSTD { int linux_truncate(char *path, \
+90 AUE_MMAP STD { int linux_mmap(struct l_mmap_argv *ptr); }
+91 AUE_MUNMAP NOPROTO { int munmap(caddr_t addr, int len); }
+92 AUE_TRUNCATE STD { int linux_truncate(char *path, \
l_ulong length); }
-93 AUE_NULL MNOPROTO { int oftruncate(int fd, long length); }
-94 AUE_NULL MNOPROTO { int fchmod(int fd, int mode); }
-95 AUE_NULL MNOPROTO { int fchown(int fd, int uid, int gid); }
-96 AUE_NULL MSTD { int linux_getpriority(int which, int who); }
-97 AUE_NULL MNOPROTO { int setpriority(int which, int who, \
+93 AUE_FTRUNCATE STD { int linux_ftruncate(int fd, long length); }
+94 AUE_FCHMOD NOPROTO { int fchmod(int fd, int mode); }
+95 AUE_FCHOWN NOPROTO { int fchown(int fd, int uid, int gid); }
+96 AUE_GETPRIORITY STD { int linux_getpriority(int which, int who); }
+97 AUE_SETPRIORITY NOPROTO { int setpriority(int which, int who, \
int prio); }
-98 AUE_NULL UNIMPL profil
-99 AUE_NULL MSTD { int linux_statfs(char *path, \
+98 AUE_PROFILE UNIMPL profil
+99 AUE_STATFS STD { int linux_statfs(char *path, \
struct l_statfs_buf *buf); }
-100 AUE_NULL MSTD { int linux_fstatfs(l_uint fd, \
+100 AUE_FSTATFS STD { int linux_fstatfs(l_uint fd, \
struct l_statfs_buf *buf); }
101 AUE_NULL UNIMPL ioperm
-102 AUE_NULL MSTD { int linux_socketcall(l_int what, \
+102 AUE_NULL STD { int linux_socketcall(l_int what, \
l_ulong args); }
-103 AUE_NULL MSTD { int linux_syslog(l_int type, char *buf, \
+103 AUE_NULL STD { int linux_syslog(l_int type, char *buf, \
l_int len); }
-104 AUE_NULL MSTD { int linux_setitimer(l_int which, \
+104 AUE_SETITIMER STD { int linux_setitimer(l_int which, \
struct l_itimerval *itv, \
struct l_itimerval *oitv); }
-105 AUE_NULL MSTD { int linux_getitimer(l_int which, \
+105 AUE_GETITIMER STD { int linux_getitimer(l_int which, \
struct l_itimerval *itv); }
-106 AUE_NULL MSTD { int linux_newstat(char *path, \
+106 AUE_STAT STD { int linux_newstat(char *path, \
struct l_newstat *buf); }
-107 AUE_NULL MSTD { int linux_newlstat(char *path, \
+107 AUE_LSTAT STD { int linux_newlstat(char *path, \
struct l_newstat *buf); }
-108 AUE_NULL MSTD { int linux_newfstat(l_uint fd, \
+108 AUE_FSTAT STD { int linux_newfstat(l_uint fd, \
struct l_newstat *buf); }
-109 AUE_NULL MSTD { int linux_uname(void); }
-110 AUE_NULL UNIMPL iopl
-111 AUE_NULL MSTD { int linux_vhangup(void); }
+109 AUE_NULL STD { int linux_uname(void); }
+110 AUE_NULL STD { int linux_iopl(l_ulong level); }
+111 AUE_NULL STD { int linux_vhangup(void); }
112 AUE_NULL UNIMPL idle
113 AUE_NULL UNIMPL vm86old
-114 AUE_NULL MSTD { int linux_wait4(l_pid_t pid, \
+114 AUE_WAIT4 STD { int linux_wait4(l_pid_t pid, \
l_uint *status, l_int options, \
struct l_rusage *rusage); }
-115 AUE_NULL MSTD { int linux_swapoff(void); }
-116 AUE_NULL MSTD { int linux_sysinfo(struct l_sysinfo *info); }
+115 AUE_SWAPOFF STD { int linux_swapoff(void); }
+116 AUE_NULL STD { int linux_sysinfo(struct l_sysinfo *info); }
117 AUE_NULL STD { int linux_ipc(l_uint what, l_int arg1, \
l_int arg2, l_int arg3, void *ptr, \
l_long arg5); }
-118 AUE_NULL MNOPROTO { int fsync(int fd); }
-119 AUE_NULL MSTD { int linux_sigreturn( \
+118 AUE_FSYNC NOPROTO { int fsync(int fd); }
+119 AUE_SIGRETURN STD { int linux_sigreturn( \
struct l_sigframe *sfp); }
-120 AUE_NULL MSTD { int linux_clone(l_int flags, \
- void *stack); }
-121 AUE_NULL MNOPROTO { int setdomainname(char *name, int len); }
-122 AUE_NULL MSTD { int linux_newuname( \
+; linux uses some strange calling convention here so we have to use the dummy arg
+120 AUE_RFORK STD { int linux_clone(l_int flags, void *stack, \
+ void *parent_tidptr, int dummy, void * child_tidptr); }
+121 AUE_SYSCTL NOPROTO { int setdomainname(char *name, \
+ int len); }
+122 AUE_NULL STD { int linux_newuname( \
struct l_new_utsname *buf); }
123 AUE_NULL UNIMPL modify_ldt
-124 AUE_NULL MSTD { int linux_adjtimex(void); }
-125 AUE_NULL MSTD { int linux_mprotect(caddr_t addr, int len, \
+124 AUE_ADJTIME STD { int linux_adjtimex(void); }
+125 AUE_MPROTECT STD { int linux_mprotect(caddr_t addr, int len, \
int prot); }
-126 AUE_NULL MSTD { int linux_sigprocmask(l_int how, \
+126 AUE_SIGPROCMASK STD { int linux_sigprocmask(l_int how, \
l_osigset_t *mask, l_osigset_t *omask); }
-127 AUE_NULL MSTD { int linux_create_module(void); }
-128 AUE_NULL MSTD { int linux_init_module(void); }
-129 AUE_NULL MSTD { int linux_delete_module(void); }
-130 AUE_NULL MSTD { int linux_get_kernel_syms(void); }
-131 AUE_NULL MSTD { int linux_quotactl(void); }
-132 AUE_NULL MNOPROTO { int getpgid(int pid); }
-133 AUE_NULL MNOPROTO { int fchdir(int fd); }
-134 AUE_NULL MSTD { int linux_bdflush(void); }
-135 AUE_NULL MSTD { int linux_sysfs(l_int option, \
+127 AUE_NULL STD { int linux_create_module(void); }
+128 AUE_NULL STD { int linux_init_module(void); }
+129 AUE_NULL STD { int linux_delete_module(void); }
+130 AUE_NULL STD { int linux_get_kernel_syms(void); }
+131 AUE_QUOTACTL STD { int linux_quotactl(void); }
+132 AUE_GETPGID NOPROTO { int getpgid(int pid); }
+133 AUE_FCHDIR NOPROTO { int fchdir(int fd); }
+134 AUE_BDFLUSH STD { int linux_bdflush(void); }
+135 AUE_NULL STD { int linux_sysfs(l_int option, \
l_ulong arg1, l_ulong arg2); }
-136 AUE_NULL MSTD { int linux_personality(l_ulong per); }
+136 AUE_PERSONALITY STD { int linux_personality(l_ulong per); }
137 AUE_NULL UNIMPL afs_syscall
-138 AUE_NULL MSTD { int linux_setfsuid16(l_uid16_t uid); }
-139 AUE_NULL MSTD { int linux_setfsgid16(l_gid16_t gid); }
-140 AUE_NULL MSTD { int linux_llseek(l_int fd, l_ulong ohigh, \
+138 AUE_SETFSUID STD { int linux_setfsuid16(l_uid16_t uid); }
+139 AUE_SETFSGID STD { int linux_setfsgid16(l_gid16_t gid); }
+140 AUE_LSEEK STD { int linux_llseek(l_int fd, l_ulong ohigh, \
l_ulong olow, l_loff_t *res, \
l_uint whence); }
-141 AUE_NULL STD { int linux_getdents(l_uint fd, void *dent, \
+141 AUE_GETDIRENTRIES STD { int linux_getdents(l_uint fd, void *dent, \
l_uint count); }
-142 AUE_NULL MSTD { int linux_select(l_int nfds, \
+142 AUE_SELECT STD { int linux_select(l_int nfds, \
l_fd_set *readfds, l_fd_set *writefds, \
l_fd_set *exceptfds, \
struct l_timeval *timeout); }
-143 AUE_NULL MNOPROTO { int flock(int fd, int how); }
-144 AUE_NULL MSTD { int linux_msync(l_ulong addr, \
+143 AUE_FLOCK NOPROTO { int flock(int fd, int how); }
+144 AUE_MSYNC STD { int linux_msync(l_ulong addr, \
l_size_t len, l_int fl); }
-145 AUE_NULL MSTD { int linux_readv(int fd, \
- struct iovec32 *iovp, u_int iovcnt); }
-146 AUE_NULL MSTD { int linux_writev(int fd, \
- struct iovec32 *iovp, u_int iovcnt); }
-147 AUE_NULL MSTD { int linux_getsid(l_pid_t pid); }
-148 AUE_NULL MSTD { int linux_fdatasync(l_uint fd); }
-149 AUE_NULL MSTD { int linux_sysctl( \
+145 AUE_READV STD { int linux_readv(int fd, struct iovec32 *iovp, \
+ u_int iovcnt); }
+146 AUE_WRITEV STD { int linux_writev(int fd, struct iovec32 *iovp, \
+ u_int iovcnt); }
+147 AUE_GETSID STD { int linux_getsid(l_pid_t pid); }
+148 AUE_NULL STD { int linux_fdatasync(l_uint fd); }
+149 AUE_SYSCTL STD { int linux_sysctl( \
struct l___sysctl_args *args); }
-150 AUE_NULL MNOPROTO { int mlock(const void *addr, size_t len); }
-151 AUE_NULL MNOPROTO { int munlock(const void *addr, \
- size_t len); }
-152 AUE_NULL MNOPROTO { int mlockall(int how); }
-153 AUE_NULL MNOPROTO { int munlockall(void); }
-154 AUE_NULL MNOPROTO { int sched_setparam(pid_t pid, \
+150 AUE_MLOCK NOPROTO { int mlock(const void *addr, size_t len); }
+151 AUE_MUNLOCK NOPROTO { int munlock(const void *addr, size_t len); }
+152 AUE_MLOCKALL NOPROTO { int mlockall(int how); }
+153 AUE_MUNLOCKALL NOPROTO { int munlockall(void); }
+154 AUE_SCHED_SETPARAM NOPROTO { int sched_setparam(pid_t pid, \
const struct sched_param *param); }
-155 AUE_NULL MNOPROTO { int sched_getparam(pid_t pid, \
+155 AUE_SCHED_GETPARAM NOPROTO { int sched_getparam(pid_t pid, \
struct sched_param *param); }
-156 AUE_NULL MSTD { int linux_sched_setscheduler(l_pid_t pid, \
- l_int policy, \
+156 AUE_SCHED_SETSCHEDULER STD { int linux_sched_setscheduler( \
+ l_pid_t pid, l_int policy, \
struct l_sched_param *param); }
-157 AUE_NULL MSTD { int linux_sched_getscheduler(l_pid_t pid); }
-158 AUE_NULL MNOPROTO { int sched_yield(void); }
-159 AUE_NULL MSTD { int linux_sched_get_priority_max( \
+157 AUE_SCHED_GETSCHEDULER STD { int linux_sched_getscheduler( \
+ l_pid_t pid); }
+158 AUE_NULL NOPROTO { int sched_yield(void); }
+159 AUE_SCHED_GET_PRIORITY_MAX STD { int linux_sched_get_priority_max( \
l_int policy); }
-160 AUE_NULL MSTD { int linux_sched_get_priority_min( \
+160 AUE_SCHED_GET_PRIORITY_MIN STD { int linux_sched_get_priority_min( \
l_int policy); }
-161 AUE_NULL MSTD { int linux_sched_rr_get_interval( \
- l_pid_t pid, \
+161 AUE_SCHED_RR_GET_INTERVAL STD { int linux_sched_rr_get_interval(l_pid_t pid, \
struct l_timespec *interval); }
-162 AUE_NULL MSTD { int linux_nanosleep( \
+162 AUE_NULL STD { int linux_nanosleep( \
const struct l_timespec *rqtp, \
struct l_timespec *rmtp); }
-163 AUE_NULL MSTD { int linux_mremap(l_ulong addr, \
+163 AUE_NULL STD { int linux_mremap(l_ulong addr, \
l_ulong old_len, l_ulong new_len, \
l_ulong flags, l_ulong new_addr); }
-164 AUE_NULL MSTD { int linux_setresuid16(l_uid16_t ruid, \
+164 AUE_SETRESUID STD { int linux_setresuid16(l_uid16_t ruid, \
l_uid16_t euid, l_uid16_t suid); }
-165 AUE_NULL MSTD { int linux_getresuid16(l_uid16_t *ruid, \
+165 AUE_GETRESUID STD { int linux_getresuid16(l_uid16_t *ruid, \
l_uid16_t *euid, l_uid16_t *suid); }
166 AUE_NULL UNIMPL vm86
-167 AUE_NULL MSTD { int linux_query_module(void); }
-168 AUE_NULL MNOPROTO { int poll(struct pollfd*, \
+167 AUE_NULL STD { int linux_query_module(void); }
+168 AUE_POLL NOPROTO { int poll(struct pollfd*, \
unsigned int nfds, int timeout); }
-169 AUE_NULL MSTD { int linux_nfsservctl(void); }
-170 AUE_NULL MSTD { int linux_setresgid16(l_gid16_t rgid, \
+169 AUE_NULL STD { int linux_nfsservctl(void); }
+170 AUE_SETRESGID STD { int linux_setresgid16(l_gid16_t rgid, \
l_gid16_t egid, l_gid16_t sgid); }
-171 AUE_NULL MSTD { int linux_getresgid16(l_gid16_t *rgid, \
+171 AUE_GETRESGID STD { int linux_getresgid16(l_gid16_t *rgid, \
l_gid16_t *egid, l_gid16_t *sgid); }
-172 AUE_NULL MSTD { int linux_prctl(void); }
-173 AUE_NULL MSTD { int linux_rt_sigreturn( \
+172 AUE_PRCTL STD { int linux_prctl(l_int option, l_int arg2, l_int arg3, \
+ l_int arg4, l_int arg5); }
+173 AUE_NULL STD { int linux_rt_sigreturn( \
struct l_ucontext *ucp); }
-174 AUE_NULL MSTD { int linux_rt_sigaction(l_int sig, \
+174 AUE_NULL STD { int linux_rt_sigaction(l_int sig, \
l_sigaction_t *act, l_sigaction_t *oact, \
l_size_t sigsetsize); }
-175 AUE_NULL MSTD { int linux_rt_sigprocmask(l_int how, \
+175 AUE_NULL STD { int linux_rt_sigprocmask(l_int how, \
l_sigset_t *mask, l_sigset_t *omask, \
l_size_t sigsetsize); }
-176 AUE_NULL MSTD { int linux_rt_sigpending(void); }
-177 AUE_NULL MSTD { int linux_rt_sigtimedwait(void); }
-178 AUE_NULL MSTD { int linux_rt_sigqueueinfo(void); }
-179 AUE_NULL MSTD { int linux_rt_sigsuspend( \
+176 AUE_NULL STD { int linux_rt_sigpending(l_sigset_t *set, \
+ l_size_t sigsetsize); }
+177 AUE_NULL STD { int linux_rt_sigtimedwait(l_sigset_t *mask, \
+ l_siginfo_t *ptr, \
+ struct l_timeval *timeout, \
+ l_size_t sigsetsize); }
+178 AUE_NULL STD { int linux_rt_sigqueueinfo(void); }
+179 AUE_NULL STD { int linux_rt_sigsuspend( \
l_sigset_t *newset, \
l_size_t sigsetsize); }
-180 AUE_NULL MSTD { int linux_pread(l_uint fd, char *buf, \
+180 AUE_PREAD STD { int linux_pread(l_uint fd, char *buf, \
l_size_t nbyte, l_loff_t offset); }
-181 AUE_NULL MSTD { int linux_pwrite(l_uint fd, char *buf, \
+181 AUE_PWRITE STD { int linux_pwrite(l_uint fd, char *buf, \
l_size_t nbyte, l_loff_t offset); }
-182 AUE_NULL MSTD { int linux_chown16(char *path, \
+182 AUE_CHOWN STD { int linux_chown16(char *path, \
l_uid16_t uid, l_gid16_t gid); }
-183 AUE_NULL MSTD { int linux_getcwd(char *buf, \
+183 AUE_GETCWD STD { int linux_getcwd(char *buf, \
l_ulong bufsize); }
-184 AUE_NULL MSTD { int linux_capget(void); }
-185 AUE_NULL MSTD { int linux_capset(void); }
-186 AUE_NULL MSTD { int linux_sigaltstack(l_stack_t *uss, \
+184 AUE_CAPGET STD { int linux_capget(void); }
+185 AUE_CAPSET STD { int linux_capset(void); }
+186 AUE_NULL STD { int linux_sigaltstack(l_stack_t *uss, \
l_stack_t *uoss); }
-187 AUE_NULL MSTD { int linux_sendfile(void); }
-188 AUE_NULL UNIMPL getpmsg
-189 AUE_NULL UNIMPL putpmsg
-190 AUE_NULL MSTD { int linux_vfork(void); }
-191 AUE_NULL MSTD { int linux_getrlimit(l_uint resource, \
+187 AUE_SENDFILE STD { int linux_sendfile(void); }
+188 AUE_GETPMSG UNIMPL getpmsg
+189 AUE_PUTPMSG UNIMPL putpmsg
+190 AUE_VFORK STD { int linux_vfork(void); }
+191 AUE_GETRLIMIT STD { int linux_getrlimit(l_uint resource, \
struct l_rlimit *rlim); }
-192 AUE_NULL MSTD { int linux_mmap2(l_ulong addr, l_ulong len, \
+192 AUE_MMAP STD { int linux_mmap2(l_ulong addr, l_ulong len, \
l_ulong prot, l_ulong flags, l_ulong fd, \
l_ulong pgoff); }
-193 AUE_NULL MSTD { int linux_truncate64(char *path, \
+193 AUE_TRUNCATE STD { int linux_truncate64(char *path, \
l_loff_t length); }
-194 AUE_NULL MSTD { int linux_ftruncate64(l_uint fd, \
+194 AUE_FTRUNCATE STD { int linux_ftruncate64(l_uint fd, \
l_loff_t length); }
-195 AUE_NULL MSTD { int linux_stat64(char *filename, \
+195 AUE_STAT STD { int linux_stat64(char *filename, \
struct l_stat64 *statbuf, l_long flags); }
-196 AUE_NULL MSTD { int linux_lstat64(char *filename, \
+196 AUE_LSTAT STD { int linux_lstat64(char *filename, \
struct l_stat64 *statbuf, l_long flags); }
-197 AUE_NULL MSTD { int linux_fstat64(l_ulong fd, \
+197 AUE_FSTAT STD { int linux_fstat64(l_ulong fd, \
struct l_stat64 *statbuf, l_long flags); }
-198 AUE_NULL MSTD { int linux_lchown(char *path, l_uid_t uid, \
+198 AUE_LCHOWN STD { int linux_lchown(char *path, l_uid_t uid, \
l_gid_t gid); }
-199 AUE_NULL MSTD { int linux_getuid(void); }
-200 AUE_NULL MSTD { int linux_getgid(void); }
-201 AUE_NULL MNOPROTO { int geteuid(void); }
-202 AUE_NULL MNOPROTO { int getegid(void); }
-203 AUE_NULL MNOPROTO { int setreuid(uid_t ruid, uid_t euid); }
-204 AUE_NULL MNOPROTO { int setregid(gid_t rgid, gid_t egid); }
-205 AUE_NULL MSTD { int linux_getgroups(l_int gidsetsize, \
+199 AUE_GETUID STD { int linux_getuid(void); }
+200 AUE_GETGID STD { int linux_getgid(void); }
+201 AUE_GETEUID NOPROTO { int geteuid(void); }
+202 AUE_GETEGID NOPROTO { int getegid(void); }
+203 AUE_SETREUID NOPROTO { int setreuid(uid_t ruid, uid_t euid); }
+204 AUE_SETREGID NOPROTO { int setregid(gid_t rgid, gid_t egid); }
+205 AUE_GETGROUPS STD { int linux_getgroups(l_int gidsetsize, \
l_gid_t *grouplist); }
-206 AUE_NULL MSTD { int linux_setgroups(l_int gidsetsize, \
+206 AUE_SETGROUPS STD { int linux_setgroups(l_int gidsetsize, \
l_gid_t *grouplist); }
-207 AUE_NULL NODEF fchown fchown fchown_args int
-208 AUE_NULL MNOPROTO { int setresuid(uid_t ruid, uid_t euid, \
+207 AUE_FCHOWN NODEF fchown fchown fchown_args int
+208 AUE_SETRESUID NOPROTO { int setresuid(uid_t ruid, uid_t euid, \
uid_t suid); }
-209 AUE_NULL MNOPROTO { int getresuid(uid_t *ruid, uid_t *euid, \
+209 AUE_GETRESUID NOPROTO { int getresuid(uid_t *ruid, uid_t *euid, \
uid_t *suid); }
-210 AUE_NULL MNOPROTO { int setresgid(gid_t rgid, gid_t egid, \
+210 AUE_SETRESGID NOPROTO { int setresgid(gid_t rgid, gid_t egid, \
gid_t sgid); }
-211 AUE_NULL MNOPROTO { int getresgid(gid_t *rgid, gid_t *egid, \
+211 AUE_GETRESGID NOPROTO { int getresgid(gid_t *rgid, gid_t *egid, \
gid_t *sgid); }
-212 AUE_NULL MSTD { int linux_chown(char *path, l_uid_t uid, \
+212 AUE_CHOWN STD { int linux_chown(char *path, l_uid_t uid, \
l_gid_t gid); }
-213 AUE_NULL MNOPROTO { int setuid(uid_t uid); }
-214 AUE_NULL MNOPROTO { int setgid(gid_t gid); }
-215 AUE_NULL MSTD { int linux_setfsuid(l_uid_t uid); }
-216 AUE_NULL MSTD { int linux_setfsgid(l_gid_t gid); }
-217 AUE_NULL MSTD { int linux_pivot_root(char *new_root, \
+213 AUE_SETUID NOPROTO { int setuid(uid_t uid); }
+214 AUE_SETGID NOPROTO { int setgid(gid_t gid); }
+215 AUE_SETFSUID STD { int linux_setfsuid(l_uid_t uid); }
+216 AUE_SETFSGID STD { int linux_setfsgid(l_gid_t gid); }
+217 AUE_PIVOT_ROOT STD { int linux_pivot_root(char *new_root, \
char *put_old); }
-218 AUE_NULL MSTD { int linux_mincore(l_ulong start, \
+218 AUE_MINCORE STD { int linux_mincore(l_ulong start, \
l_size_t len, u_char *vec); }
-219 AUE_NULL MNOPROTO { int madvise(void *addr, size_t len, \
+219 AUE_MADVISE NOPROTO { int madvise(void *addr, size_t len, \
int behav); }
-220 AUE_NULL STD { int linux_getdents64(l_uint fd, \
+220 AUE_GETDIRENTRIES STD { int linux_getdents64(l_uint fd, \
void *dirent, l_uint count); }
-221 AUE_NULL MSTD { int linux_fcntl64(l_uint fd, l_uint cmd, \
+221 AUE_FCNTL STD { int linux_fcntl64(l_uint fd, l_uint cmd, \
uintptr_t arg); }
222 AUE_NULL UNIMPL
223 AUE_NULL UNIMPL
-224 AUE_NULL MNOPROTO { int linux_getpid(void); } gettid \
- linux_getpid_args void
+224 AUE_NULL STD { long linux_gettid(void); }
225 AUE_NULL UNIMPL linux_readahead
-226 AUE_NULL MSTD { int linux_setxattr(void); }
-227 AUE_NULL MSTD { int linux_lsetxattr(void); }
-228 AUE_NULL MSTD { int linux_fsetxattr(void); }
-229 AUE_NULL MSTD { int linux_getxattr(void); }
-230 AUE_NULL MSTD { int linux_lgetxattr(void); }
-231 AUE_NULL MSTD { int linux_fgetxattr(void); }
-232 AUE_NULL MSTD { int linux_listxattr(void); }
-233 AUE_NULL MSTD { int linux_llistxattr(void); }
-234 AUE_NULL MSTD { int linux_flistxattr(void); }
-235 AUE_NULL MSTD { int linux_removexattr(void); }
-236 AUE_NULL MSTD { int linux_lremovexattr(void); }
-237 AUE_NULL MSTD { int linux_fremovexattr(void); }
-238 AUE_NULL UNIMPL linux_tkill
-239 AUE_NULL UNIMPL linux_sendfile64
-240 AUE_NULL UNIMPL linux_futex
+226 AUE_NULL STD { int linux_setxattr(void); }
+227 AUE_NULL STD { int linux_lsetxattr(void); }
+228 AUE_NULL STD { int linux_fsetxattr(void); }
+229 AUE_NULL STD { int linux_getxattr(void); }
+230 AUE_NULL STD { int linux_lgetxattr(void); }
+231 AUE_NULL STD { int linux_fgetxattr(void); }
+232 AUE_NULL STD { int linux_listxattr(void); }
+233 AUE_NULL STD { int linux_llistxattr(void); }
+234 AUE_NULL STD { int linux_flistxattr(void); }
+235 AUE_NULL STD { int linux_removexattr(void); }
+236 AUE_NULL STD { int linux_lremovexattr(void); }
+237 AUE_NULL STD { int linux_fremovexattr(void); }
+238 AUE_NULL STD { int linux_tkill(int tid, int sig); }
+239 AUE_SENDFILE UNIMPL linux_sendfile64
+240 AUE_NULL STD { int linux_sys_futex(void *uaddr, int op, int val, \
+ struct l_timespec *timeout, void *uaddr2, int val3); }
241 AUE_NULL UNIMPL linux_sched_setaffinity
-242 AUE_NULL UNIMPL linux_sched_getaffinity
-243 AUE_NULL UNIMPL linux_set_thread_area
+242 AUE_NULL STD { int linux_sched_getaffinity(l_pid_t pid, l_uint len, \
+ l_ulong *user_mask_ptr); }
+243 AUE_NULL STD { int linux_set_thread_area(struct l_user_desc *desc); }
244 AUE_NULL UNIMPL linux_get_thread_area
245 AUE_NULL UNIMPL linux_io_setup
246 AUE_NULL UNIMPL linux_io_destroy
247 AUE_NULL UNIMPL linux_io_getevents
-248 AUE_NULL UNIMPL linux_io_submit
+248 AUE_NULL UNIMPL inux_io_submit
249 AUE_NULL UNIMPL linux_io_cancel
-250 AUE_NULL MSTD { int linux_fadvise64(void); }
+250 AUE_NULL STD { int linux_fadvise64(void); }
251 AUE_NULL UNIMPL
-252 AUE_NULL MNOPROTO { void sys_exit(int rval); } exit_group \
- sys_exit_args void
-253 AUE_NULL UNIMPL linux_lookup_dcookie
-254 AUE_NULL UNIMPL linux_epoll_create
-255 AUE_NULL UNIMPL linux_epoll_ctl
-256 AUE_NULL UNIMPL linux_epoll_wait
-257 AUE_NULL UNIMPL linux_remap_file_pages
-258 AUE_NULL UNIMPL linux_set_tid_address
-259 AUE_NULL UNIMPL linux_timer_create
-260 AUE_NULL UNIMPL linux_timer_settime
-261 AUE_NULL UNIMPL linux_timer_gettime
-262 AUE_NULL UNIMPL linux_timer_getoverrun
-263 AUE_NULL UNIMPL linux_timer_delete
-264 AUE_NULL UNIMPL linux_clock_settime
-265 AUE_NULL UNIMPL linux_clock_gettime
-266 AUE_NULL UNIMPL linux_clock_getres
-267 AUE_NULL UNIMPL linux_clock_nanosleep
+252 AUE_EXIT STD { int linux_exit_group(int error_code); }
+253 AUE_NULL STD { int linux_lookup_dcookie(void); }
+254 AUE_NULL STD { int linux_epoll_create(void); }
+255 AUE_NULL STD { int linux_epoll_ctl(void); }
+256 AUE_NULL STD { int linux_epoll_wait(void); }
+257 AUE_NULL STD { int linux_remap_file_pages(void); }
+258 AUE_NULL STD { int linux_set_tid_address(int *tidptr); }
+259 AUE_NULL STD { int linux_timer_create(void); }
+260 AUE_NULL STD { int linux_timer_settime(void); }
+261 AUE_NULL STD { int linux_timer_gettime(void); }
+262 AUE_NULL STD { int linux_timer_getoverrun(void); }
+263 AUE_NULL STD { int linux_timer_delete(void); }
+264 AUE_CLOCK_SETTIME STD { int linux_clock_settime(clockid_t which, struct l_timespec *tp); }
+265 AUE_NULL STD { int linux_clock_gettime(clockid_t which, struct l_timespec *tp); }
+266 AUE_NULL STD { int linux_clock_getres(clockid_t which, struct l_timespec *tp); }
+267 AUE_NULL STD { int linux_clock_nanosleep(clockid_t which, int flags, \
+ struct l_timespec *rqtp, struct l_timespec *rmtp); }
+268 AUE_STATFS STD { int linux_statfs64(char *path, size_t bufsize, struct l_statfs64_buf *buf); }
+269 AUE_FSTATFS STD { int linux_fstatfs64(void); }
+270 AUE_NULL STD { int linux_tgkill(int tgid, int pid, int sig); }
+271 AUE_UTIMES STD { int linux_utimes(char *fname, \
+ struct l_timeval *tptr); }
+272 AUE_NULL STD { int linux_fadvise64_64(void); }
+273 AUE_NULL UNIMPL
+274 AUE_NULL STD { int linux_mbind(void); }
+275 AUE_NULL STD { int linux_get_mempolicy(void); }
+276 AUE_NULL STD { int linux_set_mempolicy(void); }
+277 AUE_NULL STD { int linux_mq_open(void); }
+278 AUE_NULL STD { int linux_mq_unlink(void); }
+279 AUE_NULL STD { int linux_mq_timedsend(void); }
+280 AUE_NULL STD { int linux_mq_timedreceive(void); }
+281 AUE_NULL STD { int linux_mq_notify(void); }
+282 AUE_NULL STD { int linux_mq_getsetattr(void); }
+283 AUE_NULL STD { int linux_kexec_load(void); }
+284 AUE_NULL STD { int linux_waitid(void); }
+285 AUE_NULL UNIMPL
+286 AUE_NULL STD { int linux_add_key(void); }
+287 AUE_NULL STD { int linux_request_key(void); }
+288 AUE_NULL STD { int linux_keyctl(void); }
+289 AUE_NULL STD { int linux_ioprio_set(void); }
+290 AUE_NULL STD { int linux_ioprio_get(void); }
+291 AUE_NULL STD { int linux_inotify_init(void); }
+292 AUE_NULL STD { int linux_inotify_add_watch(void); }
+293 AUE_NULL STD { int linux_inotify_rm_watch(void); }
+294 AUE_NULL STD { int linux_migrate_pages(void); }
+295 AUE_OPEN_RWTC STD { int linux_openat(l_int dfd, char *filename, \
+ l_int flags, l_int mode); }
+296 AUE_NULL STD { int linux_mkdirat(void); }
+297 AUE_NULL STD { int linux_mknodat(void); }
+298 AUE_NULL STD { int linux_fchownat(void); }
+299 AUE_NULL STD { int linux_futimesat(void); }
+300 AUE_NULL STD { int linux_fstatat64(void); }
+301 AUE_NULL STD { int linux_unlinkat(void); }
+302 AUE_NULL STD { int linux_renameat(void); }
+303 AUE_NULL STD { int linux_linkat(void); }
+304 AUE_NULL STD { int linux_symlinkat(void); }
+305 AUE_NULL STD { int linux_readlinkat(void); }
+306 AUE_NULL STD { int linux_fchmodat(void); }
+307 AUE_NULL STD { int linux_faccessat(void); }
+308 AUE_NULL STD { int linux_pselect6(void); }
+309 AUE_NULL STD { int linux_ppoll(void); }
+310 AUE_NULL STD { int linux_unshare(void); }
Index: syscalls.conf
===================================================================
RCS file: /home/cvs/src/sys/amd64/linux32/syscalls.conf,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/linux32/syscalls.conf -L sys/amd64/linux32/syscalls.conf -u -r1.1.1.1 -r1.2
--- sys/amd64/linux32/syscalls.conf
+++ sys/amd64/linux32/syscalls.conf
@@ -1,4 +1,4 @@
-# $FreeBSD: src/sys/amd64/linux32/syscalls.conf,v 1.1 2004/08/16 07:55:06 tjr Exp $
+# $FreeBSD: src/sys/amd64/linux32/syscalls.conf,v 1.2 2006/08/15 17:25:54 jhb Exp $
sysnames="/dev/null"
sysproto="linux32_proto.h"
sysproto_h=_LINUX_SYSPROTO_H_
@@ -8,4 +8,4 @@
syscallprefix="LINUX_SYS_"
switchname="linux_sysent"
namesname="linux_syscallnames"
-sysvec="\n"
+systrace="/dev/null"
Index: linux32_sysent.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/linux32/linux32_sysent.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/linux32/linux32_sysent.c -L sys/amd64/linux32/linux32_sysent.c -u -r1.1.1.1 -r1.2
--- sys/amd64/linux32/linux32_sysent.c
+++ sys/amd64/linux32/linux32_sysent.c
@@ -2,8 +2,8 @@
* System call switch table.
*
* DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/amd64/linux32/linux32_sysent.c,v 1.5.2.1 2005/07/20 17:43:52 jhb Exp $
- * created from FreeBSD: src/sys/amd64/linux32/syscalls.master,v 1.4.2.1 2005/07/20 17:42:14 jhb Exp
+ * $FreeBSD: src/sys/amd64/linux32/linux32_sysent.c,v 1.33 2007/09/18 19:50:32 dwmalone Exp $
+ * created from FreeBSD: src/sys/amd64/linux32/syscalls.master,v 1.29 2007/08/28 12:26:34 kib Exp
*/
#include <bsm/audit_kevents.h>
@@ -20,272 +20,315 @@
/* The casts are bogus but will do for now. */
struct sysent linux_sysent[] = {
#define nosys linux_nosys
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 0 = setup */
- { SYF_MPSAFE | AS(sys_exit_args), (sy_call_t *)sys_exit, AUE_NULL }, /* 1 = exit */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_fork, AUE_NULL }, /* 2 = linux_fork */
- { SYF_MPSAFE | AS(read_args), (sy_call_t *)read, AUE_NULL }, /* 3 = read */
- { SYF_MPSAFE | AS(write_args), (sy_call_t *)write, AUE_NULL }, /* 4 = write */
- { SYF_MPSAFE | AS(linux_open_args), (sy_call_t *)linux_open, AUE_NULL }, /* 5 = linux_open */
- { SYF_MPSAFE | AS(close_args), (sy_call_t *)close, AUE_NULL }, /* 6 = close */
- { SYF_MPSAFE | AS(linux_waitpid_args), (sy_call_t *)linux_waitpid, AUE_NULL }, /* 7 = linux_waitpid */
- { SYF_MPSAFE | AS(linux_creat_args), (sy_call_t *)linux_creat, AUE_NULL }, /* 8 = linux_creat */
- { SYF_MPSAFE | AS(linux_link_args), (sy_call_t *)linux_link, AUE_NULL }, /* 9 = linux_link */
- { SYF_MPSAFE | AS(linux_unlink_args), (sy_call_t *)linux_unlink, AUE_NULL }, /* 10 = linux_unlink */
- { SYF_MPSAFE | AS(linux_execve_args), (sy_call_t *)linux_execve, AUE_NULL }, /* 11 = linux_execve */
- { SYF_MPSAFE | AS(linux_chdir_args), (sy_call_t *)linux_chdir, AUE_NULL }, /* 12 = linux_chdir */
- { SYF_MPSAFE | AS(linux_time_args), (sy_call_t *)linux_time, AUE_NULL }, /* 13 = linux_time */
- { SYF_MPSAFE | AS(linux_mknod_args), (sy_call_t *)linux_mknod, AUE_NULL }, /* 14 = linux_mknod */
- { SYF_MPSAFE | AS(linux_chmod_args), (sy_call_t *)linux_chmod, AUE_NULL }, /* 15 = linux_chmod */
- { SYF_MPSAFE | AS(linux_lchown16_args), (sy_call_t *)linux_lchown16, AUE_NULL }, /* 16 = linux_lchown16 */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 17 = break */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 18 = stat */
- { SYF_MPSAFE | AS(linux_lseek_args), (sy_call_t *)linux_lseek, AUE_NULL }, /* 19 = linux_lseek */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_getpid, AUE_NULL }, /* 20 = linux_getpid */
- { AS(linux_mount_args), (sy_call_t *)linux_mount, AUE_NULL }, /* 21 = linux_mount */
- { AS(linux_oldumount_args), (sy_call_t *)linux_oldumount, AUE_NULL }, /* 22 = linux_oldumount */
- { SYF_MPSAFE | AS(linux_setuid16_args), (sy_call_t *)linux_setuid16, AUE_NULL }, /* 23 = linux_setuid16 */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_getuid16, AUE_NULL }, /* 24 = linux_getuid16 */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_stime, AUE_NULL }, /* 25 = linux_stime */
- { SYF_MPSAFE | AS(linux_ptrace_args), (sy_call_t *)linux_ptrace, AUE_NULL }, /* 26 = linux_ptrace */
- { SYF_MPSAFE | AS(linux_alarm_args), (sy_call_t *)linux_alarm, AUE_NULL }, /* 27 = linux_alarm */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 28 = fstat */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_pause, AUE_NULL }, /* 29 = linux_pause */
- { SYF_MPSAFE | AS(linux_utime_args), (sy_call_t *)linux_utime, AUE_NULL }, /* 30 = linux_utime */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 31 = stty */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 32 = gtty */
- { SYF_MPSAFE | AS(linux_access_args), (sy_call_t *)linux_access, AUE_NULL }, /* 33 = linux_access */
- { SYF_MPSAFE | AS(linux_nice_args), (sy_call_t *)linux_nice, AUE_NULL }, /* 34 = linux_nice */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 35 = ftime */
- { SYF_MPSAFE | 0, (sy_call_t *)sync, AUE_NULL }, /* 36 = sync */
- { SYF_MPSAFE | AS(linux_kill_args), (sy_call_t *)linux_kill, AUE_NULL }, /* 37 = linux_kill */
- { SYF_MPSAFE | AS(linux_rename_args), (sy_call_t *)linux_rename, AUE_NULL }, /* 38 = linux_rename */
- { SYF_MPSAFE | AS(linux_mkdir_args), (sy_call_t *)linux_mkdir, AUE_NULL }, /* 39 = linux_mkdir */
- { SYF_MPSAFE | AS(linux_rmdir_args), (sy_call_t *)linux_rmdir, AUE_NULL }, /* 40 = linux_rmdir */
- { SYF_MPSAFE | AS(dup_args), (sy_call_t *)dup, AUE_NULL }, /* 41 = dup */
- { SYF_MPSAFE | AS(linux_pipe_args), (sy_call_t *)linux_pipe, AUE_NULL }, /* 42 = linux_pipe */
- { SYF_MPSAFE | AS(linux_times_args), (sy_call_t *)linux_times, AUE_NULL }, /* 43 = linux_times */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 44 = prof */
- { AS(linux_brk_args), (sy_call_t *)linux_brk, AUE_NULL }, /* 45 = linux_brk */
- { SYF_MPSAFE | AS(linux_setgid16_args), (sy_call_t *)linux_setgid16, AUE_NULL }, /* 46 = linux_setgid16 */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_getgid16, AUE_NULL }, /* 47 = linux_getgid16 */
- { SYF_MPSAFE | AS(linux_signal_args), (sy_call_t *)linux_signal, AUE_NULL }, /* 48 = linux_signal */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_geteuid16, AUE_NULL }, /* 49 = linux_geteuid16 */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_getegid16, AUE_NULL }, /* 50 = linux_getegid16 */
- { SYF_MPSAFE | AS(acct_args), (sy_call_t *)acct, AUE_NULL }, /* 51 = acct */
- { AS(linux_umount_args), (sy_call_t *)linux_umount, AUE_NULL }, /* 52 = linux_umount */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 53 = lock */
- { AS(linux_ioctl_args), (sy_call_t *)linux_ioctl, AUE_NULL }, /* 54 = linux_ioctl */
- { SYF_MPSAFE | AS(linux_fcntl_args), (sy_call_t *)linux_fcntl, AUE_NULL }, /* 55 = linux_fcntl */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 56 = mpx */
- { SYF_MPSAFE | AS(setpgid_args), (sy_call_t *)setpgid, AUE_NULL }, /* 57 = setpgid */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 58 = ulimit */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_olduname, AUE_NULL }, /* 59 = linux_olduname */
- { SYF_MPSAFE | AS(umask_args), (sy_call_t *)umask, AUE_NULL }, /* 60 = umask */
- { SYF_MPSAFE | AS(chroot_args), (sy_call_t *)chroot, AUE_NULL }, /* 61 = chroot */
- { SYF_MPSAFE | AS(linux_ustat_args), (sy_call_t *)linux_ustat, AUE_NULL }, /* 62 = linux_ustat */
- { SYF_MPSAFE | AS(dup2_args), (sy_call_t *)dup2, AUE_NULL }, /* 63 = dup2 */
- { SYF_MPSAFE | 0, (sy_call_t *)getppid, AUE_NULL }, /* 64 = getppid */
- { SYF_MPSAFE | 0, (sy_call_t *)getpgrp, AUE_NULL }, /* 65 = getpgrp */
- { SYF_MPSAFE | 0, (sy_call_t *)setsid, AUE_NULL }, /* 66 = setsid */
- { SYF_MPSAFE | AS(linux_sigaction_args), (sy_call_t *)linux_sigaction, AUE_NULL }, /* 67 = linux_sigaction */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_sgetmask, AUE_NULL }, /* 68 = linux_sgetmask */
- { SYF_MPSAFE | AS(linux_ssetmask_args), (sy_call_t *)linux_ssetmask, AUE_NULL }, /* 69 = linux_ssetmask */
- { SYF_MPSAFE | AS(linux_setreuid16_args), (sy_call_t *)linux_setreuid16, AUE_NULL }, /* 70 = linux_setreuid16 */
- { SYF_MPSAFE | AS(linux_setregid16_args), (sy_call_t *)linux_setregid16, AUE_NULL }, /* 71 = linux_setregid16 */
- { SYF_MPSAFE | AS(linux_sigsuspend_args), (sy_call_t *)linux_sigsuspend, AUE_NULL }, /* 72 = linux_sigsuspend */
- { SYF_MPSAFE | AS(linux_sigpending_args), (sy_call_t *)linux_sigpending, AUE_NULL }, /* 73 = linux_sigpending */
- { SYF_MPSAFE | AS(sethostname_args), (sy_call_t *)osethostname, AUE_NULL }, /* 74 = osethostname */
- { SYF_MPSAFE | AS(linux_setrlimit_args), (sy_call_t *)linux_setrlimit, AUE_NULL }, /* 75 = linux_setrlimit */
- { SYF_MPSAFE | AS(linux_old_getrlimit_args), (sy_call_t *)linux_old_getrlimit, AUE_NULL }, /* 76 = linux_old_getrlimit */
- { SYF_MPSAFE | AS(linux_getrusage_args), (sy_call_t *)linux_getrusage, AUE_NULL }, /* 77 = linux_getrusage */
- { SYF_MPSAFE | AS(linux_gettimeofday_args), (sy_call_t *)linux_gettimeofday, AUE_NULL }, /* 78 = linux_gettimeofday */
- { SYF_MPSAFE | AS(linux_settimeofday_args), (sy_call_t *)linux_settimeofday, AUE_NULL }, /* 79 = linux_settimeofday */
- { SYF_MPSAFE | AS(linux_getgroups16_args), (sy_call_t *)linux_getgroups16, AUE_NULL }, /* 80 = linux_getgroups16 */
- { SYF_MPSAFE | AS(linux_setgroups16_args), (sy_call_t *)linux_setgroups16, AUE_NULL }, /* 81 = linux_setgroups16 */
- { SYF_MPSAFE | AS(linux_old_select_args), (sy_call_t *)linux_old_select, AUE_NULL }, /* 82 = linux_old_select */
- { SYF_MPSAFE | AS(linux_symlink_args), (sy_call_t *)linux_symlink, AUE_NULL }, /* 83 = linux_symlink */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 84 = ostat */
- { SYF_MPSAFE | AS(linux_readlink_args), (sy_call_t *)linux_readlink, AUE_NULL }, /* 85 = linux_readlink */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 86 = linux_uselib */
- { SYF_MPSAFE | AS(swapon_args), (sy_call_t *)swapon, AUE_NULL }, /* 87 = swapon */
- { SYF_MPSAFE | AS(linux_reboot_args), (sy_call_t *)linux_reboot, AUE_NULL }, /* 88 = linux_reboot */
- { AS(linux_readdir_args), (sy_call_t *)linux_readdir, AUE_NULL }, /* 89 = linux_readdir */
- { SYF_MPSAFE | AS(linux_mmap_args), (sy_call_t *)linux_mmap, AUE_NULL }, /* 90 = linux_mmap */
- { SYF_MPSAFE | AS(munmap_args), (sy_call_t *)munmap, AUE_NULL }, /* 91 = munmap */
- { SYF_MPSAFE | AS(linux_truncate_args), (sy_call_t *)linux_truncate, AUE_NULL }, /* 92 = linux_truncate */
- { SYF_MPSAFE | AS(oftruncate_args), (sy_call_t *)oftruncate, AUE_NULL }, /* 93 = oftruncate */
- { SYF_MPSAFE | AS(fchmod_args), (sy_call_t *)fchmod, AUE_NULL }, /* 94 = fchmod */
- { SYF_MPSAFE | AS(fchown_args), (sy_call_t *)fchown, AUE_NULL }, /* 95 = fchown */
- { SYF_MPSAFE | AS(linux_getpriority_args), (sy_call_t *)linux_getpriority, AUE_NULL }, /* 96 = linux_getpriority */
- { SYF_MPSAFE | AS(setpriority_args), (sy_call_t *)setpriority, AUE_NULL }, /* 97 = setpriority */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 98 = profil */
- { SYF_MPSAFE | AS(linux_statfs_args), (sy_call_t *)linux_statfs, AUE_NULL }, /* 99 = linux_statfs */
- { SYF_MPSAFE | AS(linux_fstatfs_args), (sy_call_t *)linux_fstatfs, AUE_NULL }, /* 100 = linux_fstatfs */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 101 = ioperm */
- { SYF_MPSAFE | AS(linux_socketcall_args), (sy_call_t *)linux_socketcall, AUE_NULL }, /* 102 = linux_socketcall */
- { SYF_MPSAFE | AS(linux_syslog_args), (sy_call_t *)linux_syslog, AUE_NULL }, /* 103 = linux_syslog */
- { SYF_MPSAFE | AS(linux_setitimer_args), (sy_call_t *)linux_setitimer, AUE_NULL }, /* 104 = linux_setitimer */
- { SYF_MPSAFE | AS(linux_getitimer_args), (sy_call_t *)linux_getitimer, AUE_NULL }, /* 105 = linux_getitimer */
- { SYF_MPSAFE | AS(linux_newstat_args), (sy_call_t *)linux_newstat, AUE_NULL }, /* 106 = linux_newstat */
- { SYF_MPSAFE | AS(linux_newlstat_args), (sy_call_t *)linux_newlstat, AUE_NULL }, /* 107 = linux_newlstat */
- { SYF_MPSAFE | AS(linux_newfstat_args), (sy_call_t *)linux_newfstat, AUE_NULL }, /* 108 = linux_newfstat */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_uname, AUE_NULL }, /* 109 = linux_uname */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 110 = iopl */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_vhangup, AUE_NULL }, /* 111 = linux_vhangup */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 112 = idle */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 113 = vm86old */
- { SYF_MPSAFE | AS(linux_wait4_args), (sy_call_t *)linux_wait4, AUE_NULL }, /* 114 = linux_wait4 */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_swapoff, AUE_NULL }, /* 115 = linux_swapoff */
- { SYF_MPSAFE | AS(linux_sysinfo_args), (sy_call_t *)linux_sysinfo, AUE_NULL }, /* 116 = linux_sysinfo */
- { AS(linux_ipc_args), (sy_call_t *)linux_ipc, AUE_NULL }, /* 117 = linux_ipc */
- { SYF_MPSAFE | AS(fsync_args), (sy_call_t *)fsync, AUE_NULL }, /* 118 = fsync */
- { SYF_MPSAFE | AS(linux_sigreturn_args), (sy_call_t *)linux_sigreturn, AUE_NULL }, /* 119 = linux_sigreturn */
- { SYF_MPSAFE | AS(linux_clone_args), (sy_call_t *)linux_clone, AUE_NULL }, /* 120 = linux_clone */
- { SYF_MPSAFE | AS(setdomainname_args), (sy_call_t *)setdomainname, AUE_NULL }, /* 121 = setdomainname */
- { SYF_MPSAFE | AS(linux_newuname_args), (sy_call_t *)linux_newuname, AUE_NULL }, /* 122 = linux_newuname */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 123 = modify_ldt */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_adjtimex, AUE_NULL }, /* 124 = linux_adjtimex */
- { SYF_MPSAFE | AS(linux_mprotect_args), (sy_call_t *)linux_mprotect, AUE_NULL }, /* 125 = linux_mprotect */
- { SYF_MPSAFE | AS(linux_sigprocmask_args), (sy_call_t *)linux_sigprocmask, AUE_NULL }, /* 126 = linux_sigprocmask */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_create_module, AUE_NULL }, /* 127 = linux_create_module */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_init_module, AUE_NULL }, /* 128 = linux_init_module */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_delete_module, AUE_NULL }, /* 129 = linux_delete_module */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_get_kernel_syms, AUE_NULL }, /* 130 = linux_get_kernel_syms */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_quotactl, AUE_NULL }, /* 131 = linux_quotactl */
- { SYF_MPSAFE | AS(getpgid_args), (sy_call_t *)getpgid, AUE_NULL }, /* 132 = getpgid */
- { SYF_MPSAFE | AS(fchdir_args), (sy_call_t *)fchdir, AUE_NULL }, /* 133 = fchdir */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_bdflush, AUE_NULL }, /* 134 = linux_bdflush */
- { SYF_MPSAFE | AS(linux_sysfs_args), (sy_call_t *)linux_sysfs, AUE_NULL }, /* 135 = linux_sysfs */
- { SYF_MPSAFE | AS(linux_personality_args), (sy_call_t *)linux_personality, AUE_NULL }, /* 136 = linux_personality */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 137 = afs_syscall */
- { SYF_MPSAFE | AS(linux_setfsuid16_args), (sy_call_t *)linux_setfsuid16, AUE_NULL }, /* 138 = linux_setfsuid16 */
- { SYF_MPSAFE | AS(linux_setfsgid16_args), (sy_call_t *)linux_setfsgid16, AUE_NULL }, /* 139 = linux_setfsgid16 */
- { SYF_MPSAFE | AS(linux_llseek_args), (sy_call_t *)linux_llseek, AUE_NULL }, /* 140 = linux_llseek */
- { AS(linux_getdents_args), (sy_call_t *)linux_getdents, AUE_NULL }, /* 141 = linux_getdents */
- { SYF_MPSAFE | AS(linux_select_args), (sy_call_t *)linux_select, AUE_NULL }, /* 142 = linux_select */
- { SYF_MPSAFE | AS(flock_args), (sy_call_t *)flock, AUE_NULL }, /* 143 = flock */
- { SYF_MPSAFE | AS(linux_msync_args), (sy_call_t *)linux_msync, AUE_NULL }, /* 144 = linux_msync */
- { SYF_MPSAFE | AS(linux_readv_args), (sy_call_t *)linux_readv, AUE_NULL }, /* 145 = linux_readv */
- { SYF_MPSAFE | AS(linux_writev_args), (sy_call_t *)linux_writev, AUE_NULL }, /* 146 = linux_writev */
- { SYF_MPSAFE | AS(linux_getsid_args), (sy_call_t *)linux_getsid, AUE_NULL }, /* 147 = linux_getsid */
- { SYF_MPSAFE | AS(linux_fdatasync_args), (sy_call_t *)linux_fdatasync, AUE_NULL }, /* 148 = linux_fdatasync */
- { SYF_MPSAFE | AS(linux_sysctl_args), (sy_call_t *)linux_sysctl, AUE_NULL }, /* 149 = linux_sysctl */
- { SYF_MPSAFE | AS(mlock_args), (sy_call_t *)mlock, AUE_NULL }, /* 150 = mlock */
- { SYF_MPSAFE | AS(munlock_args), (sy_call_t *)munlock, AUE_NULL }, /* 151 = munlock */
- { SYF_MPSAFE | AS(mlockall_args), (sy_call_t *)mlockall, AUE_NULL }, /* 152 = mlockall */
- { SYF_MPSAFE | 0, (sy_call_t *)munlockall, AUE_NULL }, /* 153 = munlockall */
- { SYF_MPSAFE | AS(sched_setparam_args), (sy_call_t *)sched_setparam, AUE_NULL }, /* 154 = sched_setparam */
- { SYF_MPSAFE | AS(sched_getparam_args), (sy_call_t *)sched_getparam, AUE_NULL }, /* 155 = sched_getparam */
- { SYF_MPSAFE | AS(linux_sched_setscheduler_args), (sy_call_t *)linux_sched_setscheduler, AUE_NULL }, /* 156 = linux_sched_setscheduler */
- { SYF_MPSAFE | AS(linux_sched_getscheduler_args), (sy_call_t *)linux_sched_getscheduler, AUE_NULL }, /* 157 = linux_sched_getscheduler */
- { SYF_MPSAFE | 0, (sy_call_t *)sched_yield, AUE_NULL }, /* 158 = sched_yield */
- { SYF_MPSAFE | AS(linux_sched_get_priority_max_args), (sy_call_t *)linux_sched_get_priority_max, AUE_NULL }, /* 159 = linux_sched_get_priority_max */
- { SYF_MPSAFE | AS(linux_sched_get_priority_min_args), (sy_call_t *)linux_sched_get_priority_min, AUE_NULL }, /* 160 = linux_sched_get_priority_min */
- { SYF_MPSAFE | AS(linux_sched_rr_get_interval_args), (sy_call_t *)linux_sched_rr_get_interval, AUE_NULL }, /* 161 = linux_sched_rr_get_interval */
- { SYF_MPSAFE | AS(linux_nanosleep_args), (sy_call_t *)linux_nanosleep, AUE_NULL }, /* 162 = linux_nanosleep */
- { SYF_MPSAFE | AS(linux_mremap_args), (sy_call_t *)linux_mremap, AUE_NULL }, /* 163 = linux_mremap */
- { SYF_MPSAFE | AS(linux_setresuid16_args), (sy_call_t *)linux_setresuid16, AUE_NULL }, /* 164 = linux_setresuid16 */
- { SYF_MPSAFE | AS(linux_getresuid16_args), (sy_call_t *)linux_getresuid16, AUE_NULL }, /* 165 = linux_getresuid16 */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 166 = vm86 */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_query_module, AUE_NULL }, /* 167 = linux_query_module */
- { SYF_MPSAFE | AS(poll_args), (sy_call_t *)poll, AUE_NULL }, /* 168 = poll */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_nfsservctl, AUE_NULL }, /* 169 = linux_nfsservctl */
- { SYF_MPSAFE | AS(linux_setresgid16_args), (sy_call_t *)linux_setresgid16, AUE_NULL }, /* 170 = linux_setresgid16 */
- { SYF_MPSAFE | AS(linux_getresgid16_args), (sy_call_t *)linux_getresgid16, AUE_NULL }, /* 171 = linux_getresgid16 */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_prctl, AUE_NULL }, /* 172 = linux_prctl */
- { SYF_MPSAFE | AS(linux_rt_sigreturn_args), (sy_call_t *)linux_rt_sigreturn, AUE_NULL }, /* 173 = linux_rt_sigreturn */
- { SYF_MPSAFE | AS(linux_rt_sigaction_args), (sy_call_t *)linux_rt_sigaction, AUE_NULL }, /* 174 = linux_rt_sigaction */
- { SYF_MPSAFE | AS(linux_rt_sigprocmask_args), (sy_call_t *)linux_rt_sigprocmask, AUE_NULL }, /* 175 = linux_rt_sigprocmask */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_rt_sigpending, AUE_NULL }, /* 176 = linux_rt_sigpending */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_rt_sigtimedwait, AUE_NULL }, /* 177 = linux_rt_sigtimedwait */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_rt_sigqueueinfo, AUE_NULL }, /* 178 = linux_rt_sigqueueinfo */
- { SYF_MPSAFE | AS(linux_rt_sigsuspend_args), (sy_call_t *)linux_rt_sigsuspend, AUE_NULL }, /* 179 = linux_rt_sigsuspend */
- { SYF_MPSAFE | AS(linux_pread_args), (sy_call_t *)linux_pread, AUE_NULL }, /* 180 = linux_pread */
- { SYF_MPSAFE | AS(linux_pwrite_args), (sy_call_t *)linux_pwrite, AUE_NULL }, /* 181 = linux_pwrite */
- { SYF_MPSAFE | AS(linux_chown16_args), (sy_call_t *)linux_chown16, AUE_NULL }, /* 182 = linux_chown16 */
- { SYF_MPSAFE | AS(linux_getcwd_args), (sy_call_t *)linux_getcwd, AUE_NULL }, /* 183 = linux_getcwd */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_capget, AUE_NULL }, /* 184 = linux_capget */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_capset, AUE_NULL }, /* 185 = linux_capset */
- { SYF_MPSAFE | AS(linux_sigaltstack_args), (sy_call_t *)linux_sigaltstack, AUE_NULL }, /* 186 = linux_sigaltstack */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_sendfile, AUE_NULL }, /* 187 = linux_sendfile */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 188 = getpmsg */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 189 = putpmsg */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_vfork, AUE_NULL }, /* 190 = linux_vfork */
- { SYF_MPSAFE | AS(linux_getrlimit_args), (sy_call_t *)linux_getrlimit, AUE_NULL }, /* 191 = linux_getrlimit */
- { SYF_MPSAFE | AS(linux_mmap2_args), (sy_call_t *)linux_mmap2, AUE_NULL }, /* 192 = linux_mmap2 */
- { SYF_MPSAFE | AS(linux_truncate64_args), (sy_call_t *)linux_truncate64, AUE_NULL }, /* 193 = linux_truncate64 */
- { SYF_MPSAFE | AS(linux_ftruncate64_args), (sy_call_t *)linux_ftruncate64, AUE_NULL }, /* 194 = linux_ftruncate64 */
- { SYF_MPSAFE | AS(linux_stat64_args), (sy_call_t *)linux_stat64, AUE_NULL }, /* 195 = linux_stat64 */
- { SYF_MPSAFE | AS(linux_lstat64_args), (sy_call_t *)linux_lstat64, AUE_NULL }, /* 196 = linux_lstat64 */
- { SYF_MPSAFE | AS(linux_fstat64_args), (sy_call_t *)linux_fstat64, AUE_NULL }, /* 197 = linux_fstat64 */
- { SYF_MPSAFE | AS(linux_lchown_args), (sy_call_t *)linux_lchown, AUE_NULL }, /* 198 = linux_lchown */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_getuid, AUE_NULL }, /* 199 = linux_getuid */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_getgid, AUE_NULL }, /* 200 = linux_getgid */
- { SYF_MPSAFE | 0, (sy_call_t *)geteuid, AUE_NULL }, /* 201 = geteuid */
- { SYF_MPSAFE | 0, (sy_call_t *)getegid, AUE_NULL }, /* 202 = getegid */
- { SYF_MPSAFE | AS(setreuid_args), (sy_call_t *)setreuid, AUE_NULL }, /* 203 = setreuid */
- { SYF_MPSAFE | AS(setregid_args), (sy_call_t *)setregid, AUE_NULL }, /* 204 = setregid */
- { SYF_MPSAFE | AS(linux_getgroups_args), (sy_call_t *)linux_getgroups, AUE_NULL }, /* 205 = linux_getgroups */
- { SYF_MPSAFE | AS(linux_setgroups_args), (sy_call_t *)linux_setgroups, AUE_NULL }, /* 206 = linux_setgroups */
- { AS(fchown_args), (sy_call_t *)fchown, AUE_NULL }, /* 207 = fchown */
- { SYF_MPSAFE | AS(setresuid_args), (sy_call_t *)setresuid, AUE_NULL }, /* 208 = setresuid */
- { SYF_MPSAFE | AS(getresuid_args), (sy_call_t *)getresuid, AUE_NULL }, /* 209 = getresuid */
- { SYF_MPSAFE | AS(setresgid_args), (sy_call_t *)setresgid, AUE_NULL }, /* 210 = setresgid */
- { SYF_MPSAFE | AS(getresgid_args), (sy_call_t *)getresgid, AUE_NULL }, /* 211 = getresgid */
- { SYF_MPSAFE | AS(linux_chown_args), (sy_call_t *)linux_chown, AUE_NULL }, /* 212 = linux_chown */
- { SYF_MPSAFE | AS(setuid_args), (sy_call_t *)setuid, AUE_NULL }, /* 213 = setuid */
- { SYF_MPSAFE | AS(setgid_args), (sy_call_t *)setgid, AUE_NULL }, /* 214 = setgid */
- { SYF_MPSAFE | AS(linux_setfsuid_args), (sy_call_t *)linux_setfsuid, AUE_NULL }, /* 215 = linux_setfsuid */
- { SYF_MPSAFE | AS(linux_setfsgid_args), (sy_call_t *)linux_setfsgid, AUE_NULL }, /* 216 = linux_setfsgid */
- { SYF_MPSAFE | AS(linux_pivot_root_args), (sy_call_t *)linux_pivot_root, AUE_NULL }, /* 217 = linux_pivot_root */
- { SYF_MPSAFE | AS(linux_mincore_args), (sy_call_t *)linux_mincore, AUE_NULL }, /* 218 = linux_mincore */
- { SYF_MPSAFE | AS(madvise_args), (sy_call_t *)madvise, AUE_NULL }, /* 219 = madvise */
- { AS(linux_getdents64_args), (sy_call_t *)linux_getdents64, AUE_NULL }, /* 220 = linux_getdents64 */
- { SYF_MPSAFE | AS(linux_fcntl64_args), (sy_call_t *)linux_fcntl64, AUE_NULL }, /* 221 = linux_fcntl64 */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 222 = */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 223 = */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_getpid, AUE_NULL }, /* 224 = gettid */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 225 = linux_readahead */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_setxattr, AUE_NULL }, /* 226 = linux_setxattr */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_lsetxattr, AUE_NULL }, /* 227 = linux_lsetxattr */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_fsetxattr, AUE_NULL }, /* 228 = linux_fsetxattr */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_getxattr, AUE_NULL }, /* 229 = linux_getxattr */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_lgetxattr, AUE_NULL }, /* 230 = linux_lgetxattr */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_fgetxattr, AUE_NULL }, /* 231 = linux_fgetxattr */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_listxattr, AUE_NULL }, /* 232 = linux_listxattr */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_llistxattr, AUE_NULL }, /* 233 = linux_llistxattr */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_flistxattr, AUE_NULL }, /* 234 = linux_flistxattr */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_removexattr, AUE_NULL }, /* 235 = linux_removexattr */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_lremovexattr, AUE_NULL }, /* 236 = linux_lremovexattr */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_fremovexattr, AUE_NULL }, /* 237 = linux_fremovexattr */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 238 = linux_tkill */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 239 = linux_sendfile64 */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 240 = linux_futex */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 241 = linux_sched_setaffinity */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 242 = linux_sched_getaffinity */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 243 = linux_set_thread_area */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 244 = linux_get_thread_area */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 245 = linux_io_setup */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 246 = linux_io_destroy */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 247 = linux_io_getevents */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 248 = linux_io_submit */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 249 = linux_io_cancel */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_fadvise64, AUE_NULL }, /* 250 = linux_fadvise64 */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 251 = */
- { SYF_MPSAFE | AS(sys_exit_args), (sy_call_t *)sys_exit, AUE_NULL }, /* 252 = exit_group */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 253 = linux_lookup_dcookie */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 254 = linux_epoll_create */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 255 = linux_epoll_ctl */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 256 = linux_epoll_wait */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 257 = linux_remap_file_pages */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 258 = linux_set_tid_address */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 259 = linux_timer_create */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 260 = linux_timer_settime */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 261 = linux_timer_gettime */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 262 = linux_timer_getoverrun */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 263 = linux_timer_delete */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 264 = linux_clock_settime */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 265 = linux_clock_gettime */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 266 = linux_clock_getres */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 267 = linux_clock_nanosleep */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 0 = setup */
+ { AS(sys_exit_args), (sy_call_t *)sys_exit, AUE_EXIT, NULL, 0, 0 }, /* 1 = exit */
+ { 0, (sy_call_t *)linux_fork, AUE_FORK, NULL, 0, 0 }, /* 2 = linux_fork */
+ { AS(read_args), (sy_call_t *)read, AUE_NULL, NULL, 0, 0 }, /* 3 = read */
+ { AS(write_args), (sy_call_t *)write, AUE_NULL, NULL, 0, 0 }, /* 4 = write */
+ { AS(linux_open_args), (sy_call_t *)linux_open, AUE_OPEN_RWTC, NULL, 0, 0 }, /* 5 = linux_open */
+ { AS(close_args), (sy_call_t *)close, AUE_CLOSE, NULL, 0, 0 }, /* 6 = close */
+ { AS(linux_waitpid_args), (sy_call_t *)linux_waitpid, AUE_WAIT4, NULL, 0, 0 }, /* 7 = linux_waitpid */
+ { AS(linux_creat_args), (sy_call_t *)linux_creat, AUE_CREAT, NULL, 0, 0 }, /* 8 = linux_creat */
+ { AS(linux_link_args), (sy_call_t *)linux_link, AUE_LINK, NULL, 0, 0 }, /* 9 = linux_link */
+ { AS(linux_unlink_args), (sy_call_t *)linux_unlink, AUE_UNLINK, NULL, 0, 0 }, /* 10 = linux_unlink */
+ { AS(linux_execve_args), (sy_call_t *)linux_execve, AUE_EXECVE, NULL, 0, 0 }, /* 11 = linux_execve */
+ { AS(linux_chdir_args), (sy_call_t *)linux_chdir, AUE_CHDIR, NULL, 0, 0 }, /* 12 = linux_chdir */
+ { AS(linux_time_args), (sy_call_t *)linux_time, AUE_NULL, NULL, 0, 0 }, /* 13 = linux_time */
+ { AS(linux_mknod_args), (sy_call_t *)linux_mknod, AUE_MKNOD, NULL, 0, 0 }, /* 14 = linux_mknod */
+ { AS(linux_chmod_args), (sy_call_t *)linux_chmod, AUE_CHMOD, NULL, 0, 0 }, /* 15 = linux_chmod */
+ { AS(linux_lchown16_args), (sy_call_t *)linux_lchown16, AUE_LCHOWN, NULL, 0, 0 }, /* 16 = linux_lchown16 */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 17 = break */
+ { AS(linux_stat_args), (sy_call_t *)linux_stat, AUE_STAT, NULL, 0, 0 }, /* 18 = linux_stat */
+ { AS(linux_lseek_args), (sy_call_t *)linux_lseek, AUE_LSEEK, NULL, 0, 0 }, /* 19 = linux_lseek */
+ { 0, (sy_call_t *)linux_getpid, AUE_GETPID, NULL, 0, 0 }, /* 20 = linux_getpid */
+ { AS(linux_mount_args), (sy_call_t *)linux_mount, AUE_MOUNT, NULL, 0, 0 }, /* 21 = linux_mount */
+ { AS(linux_oldumount_args), (sy_call_t *)linux_oldumount, AUE_UMOUNT, NULL, 0, 0 }, /* 22 = linux_oldumount */
+ { AS(linux_setuid16_args), (sy_call_t *)linux_setuid16, AUE_SETUID, NULL, 0, 0 }, /* 23 = linux_setuid16 */
+ { 0, (sy_call_t *)linux_getuid16, AUE_GETUID, NULL, 0, 0 }, /* 24 = linux_getuid16 */
+ { 0, (sy_call_t *)linux_stime, AUE_SETTIMEOFDAY, NULL, 0, 0 }, /* 25 = linux_stime */
+ { AS(linux_ptrace_args), (sy_call_t *)linux_ptrace, AUE_PTRACE, NULL, 0, 0 }, /* 26 = linux_ptrace */
+ { AS(linux_alarm_args), (sy_call_t *)linux_alarm, AUE_NULL, NULL, 0, 0 }, /* 27 = linux_alarm */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 28 = fstat */
+ { 0, (sy_call_t *)linux_pause, AUE_NULL, NULL, 0, 0 }, /* 29 = linux_pause */
+ { AS(linux_utime_args), (sy_call_t *)linux_utime, AUE_UTIME, NULL, 0, 0 }, /* 30 = linux_utime */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 31 = stty */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 32 = gtty */
+ { AS(linux_access_args), (sy_call_t *)linux_access, AUE_ACCESS, NULL, 0, 0 }, /* 33 = linux_access */
+ { AS(linux_nice_args), (sy_call_t *)linux_nice, AUE_NICE, NULL, 0, 0 }, /* 34 = linux_nice */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 35 = ftime */
+ { 0, (sy_call_t *)sync, AUE_SYNC, NULL, 0, 0 }, /* 36 = sync */
+ { AS(linux_kill_args), (sy_call_t *)linux_kill, AUE_KILL, NULL, 0, 0 }, /* 37 = linux_kill */
+ { AS(linux_rename_args), (sy_call_t *)linux_rename, AUE_RENAME, NULL, 0, 0 }, /* 38 = linux_rename */
+ { AS(linux_mkdir_args), (sy_call_t *)linux_mkdir, AUE_MKDIR, NULL, 0, 0 }, /* 39 = linux_mkdir */
+ { AS(linux_rmdir_args), (sy_call_t *)linux_rmdir, AUE_RMDIR, NULL, 0, 0 }, /* 40 = linux_rmdir */
+ { AS(dup_args), (sy_call_t *)dup, AUE_DUP, NULL, 0, 0 }, /* 41 = dup */
+ { AS(linux_pipe_args), (sy_call_t *)linux_pipe, AUE_PIPE, NULL, 0, 0 }, /* 42 = linux_pipe */
+ { AS(linux_times_args), (sy_call_t *)linux_times, AUE_NULL, NULL, 0, 0 }, /* 43 = linux_times */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 44 = prof */
+ { AS(linux_brk_args), (sy_call_t *)linux_brk, AUE_NULL, NULL, 0, 0 }, /* 45 = linux_brk */
+ { AS(linux_setgid16_args), (sy_call_t *)linux_setgid16, AUE_SETGID, NULL, 0, 0 }, /* 46 = linux_setgid16 */
+ { 0, (sy_call_t *)linux_getgid16, AUE_GETGID, NULL, 0, 0 }, /* 47 = linux_getgid16 */
+ { AS(linux_signal_args), (sy_call_t *)linux_signal, AUE_NULL, NULL, 0, 0 }, /* 48 = linux_signal */
+ { 0, (sy_call_t *)linux_geteuid16, AUE_GETEUID, NULL, 0, 0 }, /* 49 = linux_geteuid16 */
+ { 0, (sy_call_t *)linux_getegid16, AUE_GETEGID, NULL, 0, 0 }, /* 50 = linux_getegid16 */
+ { AS(acct_args), (sy_call_t *)acct, AUE_ACCT, NULL, 0, 0 }, /* 51 = acct */
+ { AS(linux_umount_args), (sy_call_t *)linux_umount, AUE_UMOUNT, NULL, 0, 0 }, /* 52 = linux_umount */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 53 = lock */
+ { AS(linux_ioctl_args), (sy_call_t *)linux_ioctl, AUE_IOCTL, NULL, 0, 0 }, /* 54 = linux_ioctl */
+ { AS(linux_fcntl_args), (sy_call_t *)linux_fcntl, AUE_FCNTL, NULL, 0, 0 }, /* 55 = linux_fcntl */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 56 = mpx */
+ { AS(setpgid_args), (sy_call_t *)setpgid, AUE_SETPGRP, NULL, 0, 0 }, /* 57 = setpgid */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 58 = ulimit */
+ { 0, (sy_call_t *)linux_olduname, AUE_NULL, NULL, 0, 0 }, /* 59 = linux_olduname */
+ { AS(umask_args), (sy_call_t *)umask, AUE_UMASK, NULL, 0, 0 }, /* 60 = umask */
+ { AS(chroot_args), (sy_call_t *)chroot, AUE_CHROOT, NULL, 0, 0 }, /* 61 = chroot */
+ { AS(linux_ustat_args), (sy_call_t *)linux_ustat, AUE_NULL, NULL, 0, 0 }, /* 62 = linux_ustat */
+ { AS(dup2_args), (sy_call_t *)dup2, AUE_DUP2, NULL, 0, 0 }, /* 63 = dup2 */
+ { 0, (sy_call_t *)linux_getppid, AUE_GETPPID, NULL, 0, 0 }, /* 64 = linux_getppid */
+ { 0, (sy_call_t *)getpgrp, AUE_GETPGRP, NULL, 0, 0 }, /* 65 = getpgrp */
+ { 0, (sy_call_t *)setsid, AUE_SETSID, NULL, 0, 0 }, /* 66 = setsid */
+ { AS(linux_sigaction_args), (sy_call_t *)linux_sigaction, AUE_NULL, NULL, 0, 0 }, /* 67 = linux_sigaction */
+ { 0, (sy_call_t *)linux_sgetmask, AUE_NULL, NULL, 0, 0 }, /* 68 = linux_sgetmask */
+ { AS(linux_ssetmask_args), (sy_call_t *)linux_ssetmask, AUE_NULL, NULL, 0, 0 }, /* 69 = linux_ssetmask */
+ { AS(linux_setreuid16_args), (sy_call_t *)linux_setreuid16, AUE_SETREUID, NULL, 0, 0 }, /* 70 = linux_setreuid16 */
+ { AS(linux_setregid16_args), (sy_call_t *)linux_setregid16, AUE_SETREGID, NULL, 0, 0 }, /* 71 = linux_setregid16 */
+ { AS(linux_sigsuspend_args), (sy_call_t *)linux_sigsuspend, AUE_NULL, NULL, 0, 0 }, /* 72 = linux_sigsuspend */
+ { AS(linux_sigpending_args), (sy_call_t *)linux_sigpending, AUE_NULL, NULL, 0, 0 }, /* 73 = linux_sigpending */
+ { AS(linux_sethostname_args), (sy_call_t *)linux_sethostname, AUE_SYSCTL, NULL, 0, 0 }, /* 74 = linux_sethostname */
+ { AS(linux_setrlimit_args), (sy_call_t *)linux_setrlimit, AUE_SETRLIMIT, NULL, 0, 0 }, /* 75 = linux_setrlimit */
+ { AS(linux_old_getrlimit_args), (sy_call_t *)linux_old_getrlimit, AUE_GETRLIMIT, NULL, 0, 0 }, /* 76 = linux_old_getrlimit */
+ { AS(linux_getrusage_args), (sy_call_t *)linux_getrusage, AUE_GETRUSAGE, NULL, 0, 0 }, /* 77 = linux_getrusage */
+ { AS(linux_gettimeofday_args), (sy_call_t *)linux_gettimeofday, AUE_NULL, NULL, 0, 0 }, /* 78 = linux_gettimeofday */
+ { AS(linux_settimeofday_args), (sy_call_t *)linux_settimeofday, AUE_SETTIMEOFDAY, NULL, 0, 0 }, /* 79 = linux_settimeofday */
+ { AS(linux_getgroups16_args), (sy_call_t *)linux_getgroups16, AUE_GETGROUPS, NULL, 0, 0 }, /* 80 = linux_getgroups16 */
+ { AS(linux_setgroups16_args), (sy_call_t *)linux_setgroups16, AUE_SETGROUPS, NULL, 0, 0 }, /* 81 = linux_setgroups16 */
+ { AS(linux_old_select_args), (sy_call_t *)linux_old_select, AUE_SELECT, NULL, 0, 0 }, /* 82 = linux_old_select */
+ { AS(linux_symlink_args), (sy_call_t *)linux_symlink, AUE_SYMLINK, NULL, 0, 0 }, /* 83 = linux_symlink */
+ { AS(linux_lstat_args), (sy_call_t *)linux_lstat, AUE_LSTAT, NULL, 0, 0 }, /* 84 = linux_lstat */
+ { AS(linux_readlink_args), (sy_call_t *)linux_readlink, AUE_READLINK, NULL, 0, 0 }, /* 85 = linux_readlink */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 86 = linux_uselib */
+ { AS(swapon_args), (sy_call_t *)swapon, AUE_SWAPON, NULL, 0, 0 }, /* 87 = swapon */
+ { AS(linux_reboot_args), (sy_call_t *)linux_reboot, AUE_REBOOT, NULL, 0, 0 }, /* 88 = linux_reboot */
+ { AS(linux_readdir_args), (sy_call_t *)linux_readdir, AUE_GETDIRENTRIES, NULL, 0, 0 }, /* 89 = linux_readdir */
+ { AS(linux_mmap_args), (sy_call_t *)linux_mmap, AUE_MMAP, NULL, 0, 0 }, /* 90 = linux_mmap */
+ { AS(munmap_args), (sy_call_t *)munmap, AUE_MUNMAP, NULL, 0, 0 }, /* 91 = munmap */
+ { AS(linux_truncate_args), (sy_call_t *)linux_truncate, AUE_TRUNCATE, NULL, 0, 0 }, /* 92 = linux_truncate */
+ { AS(linux_ftruncate_args), (sy_call_t *)linux_ftruncate, AUE_FTRUNCATE, NULL, 0, 0 }, /* 93 = linux_ftruncate */
+ { AS(fchmod_args), (sy_call_t *)fchmod, AUE_FCHMOD, NULL, 0, 0 }, /* 94 = fchmod */
+ { AS(fchown_args), (sy_call_t *)fchown, AUE_FCHOWN, NULL, 0, 0 }, /* 95 = fchown */
+ { AS(linux_getpriority_args), (sy_call_t *)linux_getpriority, AUE_GETPRIORITY, NULL, 0, 0 }, /* 96 = linux_getpriority */
+ { AS(setpriority_args), (sy_call_t *)setpriority, AUE_SETPRIORITY, NULL, 0, 0 }, /* 97 = setpriority */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 98 = profil */
+ { AS(linux_statfs_args), (sy_call_t *)linux_statfs, AUE_STATFS, NULL, 0, 0 }, /* 99 = linux_statfs */
+ { AS(linux_fstatfs_args), (sy_call_t *)linux_fstatfs, AUE_FSTATFS, NULL, 0, 0 }, /* 100 = linux_fstatfs */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 101 = ioperm */
+ { AS(linux_socketcall_args), (sy_call_t *)linux_socketcall, AUE_NULL, NULL, 0, 0 }, /* 102 = linux_socketcall */
+ { AS(linux_syslog_args), (sy_call_t *)linux_syslog, AUE_NULL, NULL, 0, 0 }, /* 103 = linux_syslog */
+ { AS(linux_setitimer_args), (sy_call_t *)linux_setitimer, AUE_SETITIMER, NULL, 0, 0 }, /* 104 = linux_setitimer */
+ { AS(linux_getitimer_args), (sy_call_t *)linux_getitimer, AUE_GETITIMER, NULL, 0, 0 }, /* 105 = linux_getitimer */
+ { AS(linux_newstat_args), (sy_call_t *)linux_newstat, AUE_STAT, NULL, 0, 0 }, /* 106 = linux_newstat */
+ { AS(linux_newlstat_args), (sy_call_t *)linux_newlstat, AUE_LSTAT, NULL, 0, 0 }, /* 107 = linux_newlstat */
+ { AS(linux_newfstat_args), (sy_call_t *)linux_newfstat, AUE_FSTAT, NULL, 0, 0 }, /* 108 = linux_newfstat */
+ { 0, (sy_call_t *)linux_uname, AUE_NULL, NULL, 0, 0 }, /* 109 = linux_uname */
+ { AS(linux_iopl_args), (sy_call_t *)linux_iopl, AUE_NULL, NULL, 0, 0 }, /* 110 = linux_iopl */
+ { 0, (sy_call_t *)linux_vhangup, AUE_NULL, NULL, 0, 0 }, /* 111 = linux_vhangup */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 112 = idle */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 113 = vm86old */
+ { AS(linux_wait4_args), (sy_call_t *)linux_wait4, AUE_WAIT4, NULL, 0, 0 }, /* 114 = linux_wait4 */
+ { 0, (sy_call_t *)linux_swapoff, AUE_SWAPOFF, NULL, 0, 0 }, /* 115 = linux_swapoff */
+ { AS(linux_sysinfo_args), (sy_call_t *)linux_sysinfo, AUE_NULL, NULL, 0, 0 }, /* 116 = linux_sysinfo */
+ { AS(linux_ipc_args), (sy_call_t *)linux_ipc, AUE_NULL, NULL, 0, 0 }, /* 117 = linux_ipc */
+ { AS(fsync_args), (sy_call_t *)fsync, AUE_FSYNC, NULL, 0, 0 }, /* 118 = fsync */
+ { AS(linux_sigreturn_args), (sy_call_t *)linux_sigreturn, AUE_SIGRETURN, NULL, 0, 0 }, /* 119 = linux_sigreturn */
+ { AS(linux_clone_args), (sy_call_t *)linux_clone, AUE_RFORK, NULL, 0, 0 }, /* 120 = linux_clone */
+ { AS(setdomainname_args), (sy_call_t *)setdomainname, AUE_SYSCTL, NULL, 0, 0 }, /* 121 = setdomainname */
+ { AS(linux_newuname_args), (sy_call_t *)linux_newuname, AUE_NULL, NULL, 0, 0 }, /* 122 = linux_newuname */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 123 = modify_ldt */
+ { 0, (sy_call_t *)linux_adjtimex, AUE_ADJTIME, NULL, 0, 0 }, /* 124 = linux_adjtimex */
+ { AS(linux_mprotect_args), (sy_call_t *)linux_mprotect, AUE_MPROTECT, NULL, 0, 0 }, /* 125 = linux_mprotect */
+ { AS(linux_sigprocmask_args), (sy_call_t *)linux_sigprocmask, AUE_SIGPROCMASK, NULL, 0, 0 }, /* 126 = linux_sigprocmask */
+ { 0, (sy_call_t *)linux_create_module, AUE_NULL, NULL, 0, 0 }, /* 127 = linux_create_module */
+ { 0, (sy_call_t *)linux_init_module, AUE_NULL, NULL, 0, 0 }, /* 128 = linux_init_module */
+ { 0, (sy_call_t *)linux_delete_module, AUE_NULL, NULL, 0, 0 }, /* 129 = linux_delete_module */
+ { 0, (sy_call_t *)linux_get_kernel_syms, AUE_NULL, NULL, 0, 0 }, /* 130 = linux_get_kernel_syms */
+ { 0, (sy_call_t *)linux_quotactl, AUE_QUOTACTL, NULL, 0, 0 }, /* 131 = linux_quotactl */
+ { AS(getpgid_args), (sy_call_t *)getpgid, AUE_GETPGID, NULL, 0, 0 }, /* 132 = getpgid */
+ { AS(fchdir_args), (sy_call_t *)fchdir, AUE_FCHDIR, NULL, 0, 0 }, /* 133 = fchdir */
+ { 0, (sy_call_t *)linux_bdflush, AUE_BDFLUSH, NULL, 0, 0 }, /* 134 = linux_bdflush */
+ { AS(linux_sysfs_args), (sy_call_t *)linux_sysfs, AUE_NULL, NULL, 0, 0 }, /* 135 = linux_sysfs */
+ { AS(linux_personality_args), (sy_call_t *)linux_personality, AUE_PERSONALITY, NULL, 0, 0 }, /* 136 = linux_personality */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 137 = afs_syscall */
+ { AS(linux_setfsuid16_args), (sy_call_t *)linux_setfsuid16, AUE_SETFSUID, NULL, 0, 0 }, /* 138 = linux_setfsuid16 */
+ { AS(linux_setfsgid16_args), (sy_call_t *)linux_setfsgid16, AUE_SETFSGID, NULL, 0, 0 }, /* 139 = linux_setfsgid16 */
+ { AS(linux_llseek_args), (sy_call_t *)linux_llseek, AUE_LSEEK, NULL, 0, 0 }, /* 140 = linux_llseek */
+ { AS(linux_getdents_args), (sy_call_t *)linux_getdents, AUE_GETDIRENTRIES, NULL, 0, 0 }, /* 141 = linux_getdents */
+ { AS(linux_select_args), (sy_call_t *)linux_select, AUE_SELECT, NULL, 0, 0 }, /* 142 = linux_select */
+ { AS(flock_args), (sy_call_t *)flock, AUE_FLOCK, NULL, 0, 0 }, /* 143 = flock */
+ { AS(linux_msync_args), (sy_call_t *)linux_msync, AUE_MSYNC, NULL, 0, 0 }, /* 144 = linux_msync */
+ { AS(linux_readv_args), (sy_call_t *)linux_readv, AUE_READV, NULL, 0, 0 }, /* 145 = linux_readv */
+ { AS(linux_writev_args), (sy_call_t *)linux_writev, AUE_WRITEV, NULL, 0, 0 }, /* 146 = linux_writev */
+ { AS(linux_getsid_args), (sy_call_t *)linux_getsid, AUE_GETSID, NULL, 0, 0 }, /* 147 = linux_getsid */
+ { AS(linux_fdatasync_args), (sy_call_t *)linux_fdatasync, AUE_NULL, NULL, 0, 0 }, /* 148 = linux_fdatasync */
+ { AS(linux_sysctl_args), (sy_call_t *)linux_sysctl, AUE_SYSCTL, NULL, 0, 0 }, /* 149 = linux_sysctl */
+ { AS(mlock_args), (sy_call_t *)mlock, AUE_MLOCK, NULL, 0, 0 }, /* 150 = mlock */
+ { AS(munlock_args), (sy_call_t *)munlock, AUE_MUNLOCK, NULL, 0, 0 }, /* 151 = munlock */
+ { AS(mlockall_args), (sy_call_t *)mlockall, AUE_MLOCKALL, NULL, 0, 0 }, /* 152 = mlockall */
+ { 0, (sy_call_t *)munlockall, AUE_MUNLOCKALL, NULL, 0, 0 }, /* 153 = munlockall */
+ { AS(sched_setparam_args), (sy_call_t *)sched_setparam, AUE_SCHED_SETPARAM, NULL, 0, 0 }, /* 154 = sched_setparam */
+ { AS(sched_getparam_args), (sy_call_t *)sched_getparam, AUE_SCHED_GETPARAM, NULL, 0, 0 }, /* 155 = sched_getparam */
+ { AS(linux_sched_setscheduler_args), (sy_call_t *)linux_sched_setscheduler, AUE_SCHED_SETSCHEDULER, NULL, 0, 0 }, /* 156 = linux_sched_setscheduler */
+ { AS(linux_sched_getscheduler_args), (sy_call_t *)linux_sched_getscheduler, AUE_SCHED_GETSCHEDULER, NULL, 0, 0 }, /* 157 = linux_sched_getscheduler */
+ { 0, (sy_call_t *)sched_yield, AUE_NULL, NULL, 0, 0 }, /* 158 = sched_yield */
+ { AS(linux_sched_get_priority_max_args), (sy_call_t *)linux_sched_get_priority_max, AUE_SCHED_GET_PRIORITY_MAX, NULL, 0, 0 }, /* 159 = linux_sched_get_priority_max */
+ { AS(linux_sched_get_priority_min_args), (sy_call_t *)linux_sched_get_priority_min, AUE_SCHED_GET_PRIORITY_MIN, NULL, 0, 0 }, /* 160 = linux_sched_get_priority_min */
+ { AS(linux_sched_rr_get_interval_args), (sy_call_t *)linux_sched_rr_get_interval, AUE_SCHED_RR_GET_INTERVAL, NULL, 0, 0 }, /* 161 = linux_sched_rr_get_interval */
+ { AS(linux_nanosleep_args), (sy_call_t *)linux_nanosleep, AUE_NULL, NULL, 0, 0 }, /* 162 = linux_nanosleep */
+ { AS(linux_mremap_args), (sy_call_t *)linux_mremap, AUE_NULL, NULL, 0, 0 }, /* 163 = linux_mremap */
+ { AS(linux_setresuid16_args), (sy_call_t *)linux_setresuid16, AUE_SETRESUID, NULL, 0, 0 }, /* 164 = linux_setresuid16 */
+ { AS(linux_getresuid16_args), (sy_call_t *)linux_getresuid16, AUE_GETRESUID, NULL, 0, 0 }, /* 165 = linux_getresuid16 */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 166 = vm86 */
+ { 0, (sy_call_t *)linux_query_module, AUE_NULL, NULL, 0, 0 }, /* 167 = linux_query_module */
+ { AS(poll_args), (sy_call_t *)poll, AUE_POLL, NULL, 0, 0 }, /* 168 = poll */
+ { 0, (sy_call_t *)linux_nfsservctl, AUE_NULL, NULL, 0, 0 }, /* 169 = linux_nfsservctl */
+ { AS(linux_setresgid16_args), (sy_call_t *)linux_setresgid16, AUE_SETRESGID, NULL, 0, 0 }, /* 170 = linux_setresgid16 */
+ { AS(linux_getresgid16_args), (sy_call_t *)linux_getresgid16, AUE_GETRESGID, NULL, 0, 0 }, /* 171 = linux_getresgid16 */
+ { AS(linux_prctl_args), (sy_call_t *)linux_prctl, AUE_PRCTL, NULL, 0, 0 }, /* 172 = linux_prctl */
+ { AS(linux_rt_sigreturn_args), (sy_call_t *)linux_rt_sigreturn, AUE_NULL, NULL, 0, 0 }, /* 173 = linux_rt_sigreturn */
+ { AS(linux_rt_sigaction_args), (sy_call_t *)linux_rt_sigaction, AUE_NULL, NULL, 0, 0 }, /* 174 = linux_rt_sigaction */
+ { AS(linux_rt_sigprocmask_args), (sy_call_t *)linux_rt_sigprocmask, AUE_NULL, NULL, 0, 0 }, /* 175 = linux_rt_sigprocmask */
+ { AS(linux_rt_sigpending_args), (sy_call_t *)linux_rt_sigpending, AUE_NULL, NULL, 0, 0 }, /* 176 = linux_rt_sigpending */
+ { AS(linux_rt_sigtimedwait_args), (sy_call_t *)linux_rt_sigtimedwait, AUE_NULL, NULL, 0, 0 }, /* 177 = linux_rt_sigtimedwait */
+ { 0, (sy_call_t *)linux_rt_sigqueueinfo, AUE_NULL, NULL, 0, 0 }, /* 178 = linux_rt_sigqueueinfo */
+ { AS(linux_rt_sigsuspend_args), (sy_call_t *)linux_rt_sigsuspend, AUE_NULL, NULL, 0, 0 }, /* 179 = linux_rt_sigsuspend */
+ { AS(linux_pread_args), (sy_call_t *)linux_pread, AUE_PREAD, NULL, 0, 0 }, /* 180 = linux_pread */
+ { AS(linux_pwrite_args), (sy_call_t *)linux_pwrite, AUE_PWRITE, NULL, 0, 0 }, /* 181 = linux_pwrite */
+ { AS(linux_chown16_args), (sy_call_t *)linux_chown16, AUE_CHOWN, NULL, 0, 0 }, /* 182 = linux_chown16 */
+ { AS(linux_getcwd_args), (sy_call_t *)linux_getcwd, AUE_GETCWD, NULL, 0, 0 }, /* 183 = linux_getcwd */
+ { 0, (sy_call_t *)linux_capget, AUE_CAPGET, NULL, 0, 0 }, /* 184 = linux_capget */
+ { 0, (sy_call_t *)linux_capset, AUE_CAPSET, NULL, 0, 0 }, /* 185 = linux_capset */
+ { AS(linux_sigaltstack_args), (sy_call_t *)linux_sigaltstack, AUE_NULL, NULL, 0, 0 }, /* 186 = linux_sigaltstack */
+ { 0, (sy_call_t *)linux_sendfile, AUE_SENDFILE, NULL, 0, 0 }, /* 187 = linux_sendfile */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 188 = getpmsg */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 189 = putpmsg */
+ { 0, (sy_call_t *)linux_vfork, AUE_VFORK, NULL, 0, 0 }, /* 190 = linux_vfork */
+ { AS(linux_getrlimit_args), (sy_call_t *)linux_getrlimit, AUE_GETRLIMIT, NULL, 0, 0 }, /* 191 = linux_getrlimit */
+ { AS(linux_mmap2_args), (sy_call_t *)linux_mmap2, AUE_MMAP, NULL, 0, 0 }, /* 192 = linux_mmap2 */
+ { AS(linux_truncate64_args), (sy_call_t *)linux_truncate64, AUE_TRUNCATE, NULL, 0, 0 }, /* 193 = linux_truncate64 */
+ { AS(linux_ftruncate64_args), (sy_call_t *)linux_ftruncate64, AUE_FTRUNCATE, NULL, 0, 0 }, /* 194 = linux_ftruncate64 */
+ { AS(linux_stat64_args), (sy_call_t *)linux_stat64, AUE_STAT, NULL, 0, 0 }, /* 195 = linux_stat64 */
+ { AS(linux_lstat64_args), (sy_call_t *)linux_lstat64, AUE_LSTAT, NULL, 0, 0 }, /* 196 = linux_lstat64 */
+ { AS(linux_fstat64_args), (sy_call_t *)linux_fstat64, AUE_FSTAT, NULL, 0, 0 }, /* 197 = linux_fstat64 */
+ { AS(linux_lchown_args), (sy_call_t *)linux_lchown, AUE_LCHOWN, NULL, 0, 0 }, /* 198 = linux_lchown */
+ { 0, (sy_call_t *)linux_getuid, AUE_GETUID, NULL, 0, 0 }, /* 199 = linux_getuid */
+ { 0, (sy_call_t *)linux_getgid, AUE_GETGID, NULL, 0, 0 }, /* 200 = linux_getgid */
+ { 0, (sy_call_t *)geteuid, AUE_GETEUID, NULL, 0, 0 }, /* 201 = geteuid */
+ { 0, (sy_call_t *)getegid, AUE_GETEGID, NULL, 0, 0 }, /* 202 = getegid */
+ { AS(setreuid_args), (sy_call_t *)setreuid, AUE_SETREUID, NULL, 0, 0 }, /* 203 = setreuid */
+ { AS(setregid_args), (sy_call_t *)setregid, AUE_SETREGID, NULL, 0, 0 }, /* 204 = setregid */
+ { AS(linux_getgroups_args), (sy_call_t *)linux_getgroups, AUE_GETGROUPS, NULL, 0, 0 }, /* 205 = linux_getgroups */
+ { AS(linux_setgroups_args), (sy_call_t *)linux_setgroups, AUE_SETGROUPS, NULL, 0, 0 }, /* 206 = linux_setgroups */
+ { AS(fchown_args), (sy_call_t *)fchown, AUE_NULL, NULL, 0, 0 }, /* 207 = fchown */
+ { AS(setresuid_args), (sy_call_t *)setresuid, AUE_SETRESUID, NULL, 0, 0 }, /* 208 = setresuid */
+ { AS(getresuid_args), (sy_call_t *)getresuid, AUE_GETRESUID, NULL, 0, 0 }, /* 209 = getresuid */
+ { AS(setresgid_args), (sy_call_t *)setresgid, AUE_SETRESGID, NULL, 0, 0 }, /* 210 = setresgid */
+ { AS(getresgid_args), (sy_call_t *)getresgid, AUE_GETRESGID, NULL, 0, 0 }, /* 211 = getresgid */
+ { AS(linux_chown_args), (sy_call_t *)linux_chown, AUE_CHOWN, NULL, 0, 0 }, /* 212 = linux_chown */
+ { AS(setuid_args), (sy_call_t *)setuid, AUE_SETUID, NULL, 0, 0 }, /* 213 = setuid */
+ { AS(setgid_args), (sy_call_t *)setgid, AUE_SETGID, NULL, 0, 0 }, /* 214 = setgid */
+ { AS(linux_setfsuid_args), (sy_call_t *)linux_setfsuid, AUE_SETFSUID, NULL, 0, 0 }, /* 215 = linux_setfsuid */
+ { AS(linux_setfsgid_args), (sy_call_t *)linux_setfsgid, AUE_SETFSGID, NULL, 0, 0 }, /* 216 = linux_setfsgid */
+ { AS(linux_pivot_root_args), (sy_call_t *)linux_pivot_root, AUE_PIVOT_ROOT, NULL, 0, 0 }, /* 217 = linux_pivot_root */
+ { AS(linux_mincore_args), (sy_call_t *)linux_mincore, AUE_MINCORE, NULL, 0, 0 }, /* 218 = linux_mincore */
+ { AS(madvise_args), (sy_call_t *)madvise, AUE_MADVISE, NULL, 0, 0 }, /* 219 = madvise */
+ { AS(linux_getdents64_args), (sy_call_t *)linux_getdents64, AUE_GETDIRENTRIES, NULL, 0, 0 }, /* 220 = linux_getdents64 */
+ { AS(linux_fcntl64_args), (sy_call_t *)linux_fcntl64, AUE_FCNTL, NULL, 0, 0 }, /* 221 = linux_fcntl64 */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 222 = */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 223 = */
+ { 0, (sy_call_t *)linux_gettid, AUE_NULL, NULL, 0, 0 }, /* 224 = linux_gettid */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 225 = linux_readahead */
+ { 0, (sy_call_t *)linux_setxattr, AUE_NULL, NULL, 0, 0 }, /* 226 = linux_setxattr */
+ { 0, (sy_call_t *)linux_lsetxattr, AUE_NULL, NULL, 0, 0 }, /* 227 = linux_lsetxattr */
+ { 0, (sy_call_t *)linux_fsetxattr, AUE_NULL, NULL, 0, 0 }, /* 228 = linux_fsetxattr */
+ { 0, (sy_call_t *)linux_getxattr, AUE_NULL, NULL, 0, 0 }, /* 229 = linux_getxattr */
+ { 0, (sy_call_t *)linux_lgetxattr, AUE_NULL, NULL, 0, 0 }, /* 230 = linux_lgetxattr */
+ { 0, (sy_call_t *)linux_fgetxattr, AUE_NULL, NULL, 0, 0 }, /* 231 = linux_fgetxattr */
+ { 0, (sy_call_t *)linux_listxattr, AUE_NULL, NULL, 0, 0 }, /* 232 = linux_listxattr */
+ { 0, (sy_call_t *)linux_llistxattr, AUE_NULL, NULL, 0, 0 }, /* 233 = linux_llistxattr */
+ { 0, (sy_call_t *)linux_flistxattr, AUE_NULL, NULL, 0, 0 }, /* 234 = linux_flistxattr */
+ { 0, (sy_call_t *)linux_removexattr, AUE_NULL, NULL, 0, 0 }, /* 235 = linux_removexattr */
+ { 0, (sy_call_t *)linux_lremovexattr, AUE_NULL, NULL, 0, 0 }, /* 236 = linux_lremovexattr */
+ { 0, (sy_call_t *)linux_fremovexattr, AUE_NULL, NULL, 0, 0 }, /* 237 = linux_fremovexattr */
+ { AS(linux_tkill_args), (sy_call_t *)linux_tkill, AUE_NULL, NULL, 0, 0 }, /* 238 = linux_tkill */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 239 = linux_sendfile64 */
+ { AS(linux_sys_futex_args), (sy_call_t *)linux_sys_futex, AUE_NULL, NULL, 0, 0 }, /* 240 = linux_sys_futex */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 241 = linux_sched_setaffinity */
+ { AS(linux_sched_getaffinity_args), (sy_call_t *)linux_sched_getaffinity, AUE_NULL, NULL, 0, 0 }, /* 242 = linux_sched_getaffinity */
+ { AS(linux_set_thread_area_args), (sy_call_t *)linux_set_thread_area, AUE_NULL, NULL, 0, 0 }, /* 243 = linux_set_thread_area */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 244 = linux_get_thread_area */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 245 = linux_io_setup */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 246 = linux_io_destroy */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 247 = linux_io_getevents */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 248 = inux_io_submit */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 249 = linux_io_cancel */
+ { 0, (sy_call_t *)linux_fadvise64, AUE_NULL, NULL, 0, 0 }, /* 250 = linux_fadvise64 */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 251 = */
+ { AS(linux_exit_group_args), (sy_call_t *)linux_exit_group, AUE_EXIT, NULL, 0, 0 }, /* 252 = linux_exit_group */
+ { 0, (sy_call_t *)linux_lookup_dcookie, AUE_NULL, NULL, 0, 0 }, /* 253 = linux_lookup_dcookie */
+ { 0, (sy_call_t *)linux_epoll_create, AUE_NULL, NULL, 0, 0 }, /* 254 = linux_epoll_create */
+ { 0, (sy_call_t *)linux_epoll_ctl, AUE_NULL, NULL, 0, 0 }, /* 255 = linux_epoll_ctl */
+ { 0, (sy_call_t *)linux_epoll_wait, AUE_NULL, NULL, 0, 0 }, /* 256 = linux_epoll_wait */
+ { 0, (sy_call_t *)linux_remap_file_pages, AUE_NULL, NULL, 0, 0 }, /* 257 = linux_remap_file_pages */
+ { AS(linux_set_tid_address_args), (sy_call_t *)linux_set_tid_address, AUE_NULL, NULL, 0, 0 }, /* 258 = linux_set_tid_address */
+ { 0, (sy_call_t *)linux_timer_create, AUE_NULL, NULL, 0, 0 }, /* 259 = linux_timer_create */
+ { 0, (sy_call_t *)linux_timer_settime, AUE_NULL, NULL, 0, 0 }, /* 260 = linux_timer_settime */
+ { 0, (sy_call_t *)linux_timer_gettime, AUE_NULL, NULL, 0, 0 }, /* 261 = linux_timer_gettime */
+ { 0, (sy_call_t *)linux_timer_getoverrun, AUE_NULL, NULL, 0, 0 }, /* 262 = linux_timer_getoverrun */
+ { 0, (sy_call_t *)linux_timer_delete, AUE_NULL, NULL, 0, 0 }, /* 263 = linux_timer_delete */
+ { AS(linux_clock_settime_args), (sy_call_t *)linux_clock_settime, AUE_CLOCK_SETTIME, NULL, 0, 0 }, /* 264 = linux_clock_settime */
+ { AS(linux_clock_gettime_args), (sy_call_t *)linux_clock_gettime, AUE_NULL, NULL, 0, 0 }, /* 265 = linux_clock_gettime */
+ { AS(linux_clock_getres_args), (sy_call_t *)linux_clock_getres, AUE_NULL, NULL, 0, 0 }, /* 266 = linux_clock_getres */
+ { AS(linux_clock_nanosleep_args), (sy_call_t *)linux_clock_nanosleep, AUE_NULL, NULL, 0, 0 }, /* 267 = linux_clock_nanosleep */
+ { AS(linux_statfs64_args), (sy_call_t *)linux_statfs64, AUE_STATFS, NULL, 0, 0 }, /* 268 = linux_statfs64 */
+ { 0, (sy_call_t *)linux_fstatfs64, AUE_FSTATFS, NULL, 0, 0 }, /* 269 = linux_fstatfs64 */
+ { AS(linux_tgkill_args), (sy_call_t *)linux_tgkill, AUE_NULL, NULL, 0, 0 }, /* 270 = linux_tgkill */
+ { AS(linux_utimes_args), (sy_call_t *)linux_utimes, AUE_UTIMES, NULL, 0, 0 }, /* 271 = linux_utimes */
+ { 0, (sy_call_t *)linux_fadvise64_64, AUE_NULL, NULL, 0, 0 }, /* 272 = linux_fadvise64_64 */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 273 = */
+ { 0, (sy_call_t *)linux_mbind, AUE_NULL, NULL, 0, 0 }, /* 274 = linux_mbind */
+ { 0, (sy_call_t *)linux_get_mempolicy, AUE_NULL, NULL, 0, 0 }, /* 275 = linux_get_mempolicy */
+ { 0, (sy_call_t *)linux_set_mempolicy, AUE_NULL, NULL, 0, 0 }, /* 276 = linux_set_mempolicy */
+ { 0, (sy_call_t *)linux_mq_open, AUE_NULL, NULL, 0, 0 }, /* 277 = linux_mq_open */
+ { 0, (sy_call_t *)linux_mq_unlink, AUE_NULL, NULL, 0, 0 }, /* 278 = linux_mq_unlink */
+ { 0, (sy_call_t *)linux_mq_timedsend, AUE_NULL, NULL, 0, 0 }, /* 279 = linux_mq_timedsend */
+ { 0, (sy_call_t *)linux_mq_timedreceive, AUE_NULL, NULL, 0, 0 }, /* 280 = linux_mq_timedreceive */
+ { 0, (sy_call_t *)linux_mq_notify, AUE_NULL, NULL, 0, 0 }, /* 281 = linux_mq_notify */
+ { 0, (sy_call_t *)linux_mq_getsetattr, AUE_NULL, NULL, 0, 0 }, /* 282 = linux_mq_getsetattr */
+ { 0, (sy_call_t *)linux_kexec_load, AUE_NULL, NULL, 0, 0 }, /* 283 = linux_kexec_load */
+ { 0, (sy_call_t *)linux_waitid, AUE_NULL, NULL, 0, 0 }, /* 284 = linux_waitid */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 285 = */
+ { 0, (sy_call_t *)linux_add_key, AUE_NULL, NULL, 0, 0 }, /* 286 = linux_add_key */
+ { 0, (sy_call_t *)linux_request_key, AUE_NULL, NULL, 0, 0 }, /* 287 = linux_request_key */
+ { 0, (sy_call_t *)linux_keyctl, AUE_NULL, NULL, 0, 0 }, /* 288 = linux_keyctl */
+ { 0, (sy_call_t *)linux_ioprio_set, AUE_NULL, NULL, 0, 0 }, /* 289 = linux_ioprio_set */
+ { 0, (sy_call_t *)linux_ioprio_get, AUE_NULL, NULL, 0, 0 }, /* 290 = linux_ioprio_get */
+ { 0, (sy_call_t *)linux_inotify_init, AUE_NULL, NULL, 0, 0 }, /* 291 = linux_inotify_init */
+ { 0, (sy_call_t *)linux_inotify_add_watch, AUE_NULL, NULL, 0, 0 }, /* 292 = linux_inotify_add_watch */
+ { 0, (sy_call_t *)linux_inotify_rm_watch, AUE_NULL, NULL, 0, 0 }, /* 293 = linux_inotify_rm_watch */
+ { 0, (sy_call_t *)linux_migrate_pages, AUE_NULL, NULL, 0, 0 }, /* 294 = linux_migrate_pages */
+ { AS(linux_openat_args), (sy_call_t *)linux_openat, AUE_OPEN_RWTC, NULL, 0, 0 }, /* 295 = linux_openat */
+ { 0, (sy_call_t *)linux_mkdirat, AUE_NULL, NULL, 0, 0 }, /* 296 = linux_mkdirat */
+ { 0, (sy_call_t *)linux_mknodat, AUE_NULL, NULL, 0, 0 }, /* 297 = linux_mknodat */
+ { 0, (sy_call_t *)linux_fchownat, AUE_NULL, NULL, 0, 0 }, /* 298 = linux_fchownat */
+ { 0, (sy_call_t *)linux_futimesat, AUE_NULL, NULL, 0, 0 }, /* 299 = linux_futimesat */
+ { 0, (sy_call_t *)linux_fstatat64, AUE_NULL, NULL, 0, 0 }, /* 300 = linux_fstatat64 */
+ { 0, (sy_call_t *)linux_unlinkat, AUE_NULL, NULL, 0, 0 }, /* 301 = linux_unlinkat */
+ { 0, (sy_call_t *)linux_renameat, AUE_NULL, NULL, 0, 0 }, /* 302 = linux_renameat */
+ { 0, (sy_call_t *)linux_linkat, AUE_NULL, NULL, 0, 0 }, /* 303 = linux_linkat */
+ { 0, (sy_call_t *)linux_symlinkat, AUE_NULL, NULL, 0, 0 }, /* 304 = linux_symlinkat */
+ { 0, (sy_call_t *)linux_readlinkat, AUE_NULL, NULL, 0, 0 }, /* 305 = linux_readlinkat */
+ { 0, (sy_call_t *)linux_fchmodat, AUE_NULL, NULL, 0, 0 }, /* 306 = linux_fchmodat */
+ { 0, (sy_call_t *)linux_faccessat, AUE_NULL, NULL, 0, 0 }, /* 307 = linux_faccessat */
+ { 0, (sy_call_t *)linux_pselect6, AUE_NULL, NULL, 0, 0 }, /* 308 = linux_pselect6 */
+ { 0, (sy_call_t *)linux_ppoll, AUE_NULL, NULL, 0, 0 }, /* 309 = linux_ppoll */
+ { 0, (sy_call_t *)linux_unshare, AUE_NULL, NULL, 0, 0 }, /* 310 = linux_unshare */
};
--- /dev/null
+++ sys/amd64/linux32/linux32_support.s
@@ -0,0 +1,124 @@
+/*-
+ * Copyright (c) 2007 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.
+ *
+ * $FreeBSD: src/sys/amd64/linux32/linux32_support.s,v 1.1 2007/05/23 08:33:05 kib Exp $
+ */
+
+#include "linux32_assym.h" /* system definitions */
+#include <machine/asmacros.h> /* miscellaneous asm macros */
+
+#include "assym.s"
+
+futex_fault:
+ movq $0,PCB_ONFAULT(%r8)
+ movl $-EFAULT,%eax
+ ret
+
+ENTRY(futex_xchgl)
+ movq PCPU(CURPCB),%r8
+ movq $futex_fault,PCB_ONFAULT(%r8)
+ movq $VM_MAXUSER_ADDRESS-4,%rax
+ cmpq %rax,%rsi
+ ja futex_fault
+ xchgl %edi,(%rsi)
+ movl %edi,(%rdx)
+ xorl %eax,%eax
+ movq %rax,PCB_ONFAULT(%r8)
+ ret
+
+ENTRY(futex_addl)
+ movq PCPU(CURPCB),%r8
+ movq $futex_fault,PCB_ONFAULT(%r8)
+ movq $VM_MAXUSER_ADDRESS-4,%rax
+ cmpq %rax,%rsi
+ ja futex_fault
+#ifdef SMP
+ lock
+#endif
+ xaddl %edi,(%rsi)
+ movl %edi,(%rdx)
+ xorl %eax,%eax
+ movq %rax,PCB_ONFAULT(%r8)
+ ret
+
+ENTRY(futex_orl)
+ movq PCPU(CURPCB),%r8
+ movq $futex_fault,PCB_ONFAULT(%r8)
+ movq $VM_MAXUSER_ADDRESS-4,%rax
+ cmpq %rax,%rsi
+ ja futex_fault
+ movl (%rsi),%eax
+1: movl %eax,%ecx
+ orl %edi,%ecx
+#ifdef SMP
+ lock
+#endif
+ cmpxchgl %ecx,(%rsi)
+ jnz 1b
+ movl %eax,(%rdx)
+ xorl %eax,%eax
+ movq %rax,PCB_ONFAULT(%r8)
+ ret
+
+ENTRY(futex_andl)
+ movq PCPU(CURPCB),%r8
+ movq $futex_fault,PCB_ONFAULT(%r8)
+ movq $VM_MAXUSER_ADDRESS-4,%rax
+ cmpq %rax,%rsi
+ ja futex_fault
+ movl (%rsi),%eax
+1: movl %eax,%ecx
+ andl %edi,%ecx
+#ifdef SMP
+ lock
+#endif
+ cmpxchgl %ecx,(%rsi)
+ jnz 1b
+ movl %eax,(%rdx)
+ xorl %eax,%eax
+ movq %rax,PCB_ONFAULT(%r8)
+ ret
+
+ENTRY(futex_xorl)
+ movq PCPU(CURPCB),%r8
+ movq $futex_fault,PCB_ONFAULT(%r8)
+ movq $VM_MAXUSER_ADDRESS-4,%rax
+ cmpq %rax,%rsi
+ ja futex_fault
+ movl (%rsi),%eax
+1: movl %eax,%ecx
+ xorl %edi,%ecx
+#ifdef SMP
+ lock
+#endif
+ cmpxchgl %ecx,(%rsi)
+ jnz 1b
+ movl %eax,(%rdx)
+ xorl %eax,%eax
+ movq %rax,PCB_ONFAULT(%r8)
+ ret
Index: linux32_machdep.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/linux32/linux32_machdep.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/linux32/linux32_machdep.c -L sys/amd64/linux32/linux32_machdep.c -u -r1.1.1.1 -r1.2
--- sys/amd64/linux32/linux32_machdep.c
+++ sys/amd64/linux32/linux32_machdep.c
@@ -29,24 +29,34 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/linux32/linux32_machdep.c,v 1.10 2005/06/24 17:41:27 jhb Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/linux32/linux32_machdep.c,v 1.45 2007/07/04 23:06:43 peter Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
+#include <sys/file.h>
+#include <sys/fcntl.h>
+#include <sys/clock.h>
#include <sys/imgact.h>
+#include <sys/limits.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mman.h>
#include <sys/mutex.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/resource.h>
#include <sys/resourcevar.h>
+#include <sys/sched.h>
#include <sys/syscallsubr.h>
#include <sys/sysproto.h>
#include <sys/unistd.h>
#include <machine/frame.h>
+#include <machine/pcb.h>
+#include <machine/psl.h>
+#include <machine/segments.h>
+#include <machine/specialreg.h>
#include <vm/vm.h>
#include <vm/pmap.h>
@@ -59,6 +69,7 @@
#include <compat/linux/linux_ipc.h>
#include <compat/linux/linux_signal.h>
#include <compat/linux/linux_util.h>
+#include <compat/linux/linux_emul.h>
struct l_old_select_argv {
l_int nfds;
@@ -113,7 +124,7 @@
* Allocate temporary demand zeroed space for argument and
* environment strings
*/
- args->buf = (char *) kmem_alloc_wait(exec_map,
+ args->buf = (char *)kmem_alloc_wait(exec_map,
PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
if (args->buf == NULL)
return (ENOMEM);
@@ -130,7 +141,7 @@
copystr(fname, args->fname, PATH_MAX, &length) :
copyinstr(fname, args->fname, PATH_MAX, &length);
if (error != 0)
- return (error);
+ goto err_exit;
/*
* extract arguments first
@@ -139,22 +150,22 @@
for (;;) {
error = copyin(p32++, &arg, sizeof(arg));
if (error)
- return (error);
+ goto err_exit;
if (arg == 0)
break;
argp = PTRIN(arg);
error = copyinstr(argp, args->endp, args->stringspace, &length);
if (error) {
if (error == ENAMETOOLONG)
- return (E2BIG);
- else
- return (error);
+ error = E2BIG;
+
+ goto err_exit;
}
args->stringspace -= length;
args->endp += length;
args->argc++;
}
-
+
args->begin_envv = args->endp;
/*
@@ -165,7 +176,7 @@
for (;;) {
error = copyin(p32++, &arg, sizeof(arg));
if (error)
- return (error);
+ goto err_exit;
if (arg == 0)
break;
envp = PTRIN(arg);
@@ -173,9 +184,8 @@
&length);
if (error) {
if (error == ENAMETOOLONG)
- return (E2BIG);
- else
- return (error);
+ error = E2BIG;
+ goto err_exit;
}
args->stringspace -= length;
args->endp += length;
@@ -184,6 +194,12 @@
}
return (0);
+
+err_exit:
+ kmem_free_wakeup(exec_map, (vm_offset_t)args->buf,
+ PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
+ args->buf = NULL;
+ return (error);
}
int
@@ -205,7 +221,14 @@
free(path, M_TEMP);
if (error == 0)
error = kern_execve(td, &eargs, NULL);
- exec_free_args(&eargs);
+ if (error == 0)
+ /* Linux process can execute FreeBSD one, do not attempt
+ * to create emuldata for such process using
+ * linux_proc_init, this leads to a panic on KASSERT
+ * because such process has p->p_emuldata == NULL.
+ */
+ if (td->td_proc->p_sysent == &elf_linux_sysvec)
+ error = linux_proc_init(td, 0, 0);
return (error);
}
@@ -229,7 +252,7 @@
if (iovcnt > UIO_MAXIOV)
return (EINVAL);
iovlen = iovcnt * sizeof(struct iovec);
- uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
+ uio = malloc(iovlen + sizeof(*uio), M_IOV, M_WAITOK);
iov = (struct iovec *)(uio + 1);
for (i = 0; i < iovcnt; i++) {
error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
@@ -436,17 +459,38 @@
linux_fork(struct thread *td, struct linux_fork_args *args)
{
int error;
+ struct proc *p2;
+ struct thread *td2;
#ifdef DEBUG
if (ldebug(fork))
printf(ARGS(fork, ""));
#endif
- if ((error = fork(td, (struct fork_args *)args)) != 0)
+ if ((error = fork1(td, RFFDG | RFPROC | RFSTOPPED, 0, &p2)) != 0)
return (error);
+ if (error == 0) {
+ td->td_retval[0] = p2->p_pid;
+ td->td_retval[1] = 0;
+ }
+
if (td->td_retval[1] == 1)
td->td_retval[0] = 0;
+ error = linux_proc_init(td, td->td_retval[0], 0);
+ if (error)
+ return (error);
+
+ td2 = FIRST_THREAD_IN_PROC(p2);
+
+ /*
+ * Make this runnable after we are finished with it.
+ */
+ thread_lock(td2);
+ TD_SET_CAN_RUN(td2);
+ sched_add(td2, SRQ_BORING);
+ thread_unlock(td2);
+
return (0);
}
@@ -454,26 +498,51 @@
linux_vfork(struct thread *td, struct linux_vfork_args *args)
{
int error;
+ struct proc *p2;
+ struct thread *td2;
#ifdef DEBUG
if (ldebug(vfork))
printf(ARGS(vfork, ""));
#endif
- if ((error = vfork(td, (struct vfork_args *)args)) != 0)
+ /* Exclude RFPPWAIT */
+ if ((error = fork1(td, RFFDG | RFPROC | RFMEM | RFSTOPPED, 0, &p2)) != 0)
return (error);
+ if (error == 0) {
+ td->td_retval[0] = p2->p_pid;
+ td->td_retval[1] = 0;
+ }
/* Are we the child? */
if (td->td_retval[1] == 1)
td->td_retval[0] = 0;
+ error = linux_proc_init(td, td->td_retval[0], 0);
+ if (error)
+ return (error);
+
+ PROC_LOCK(p2);
+ p2->p_flag |= P_PPWAIT;
+ PROC_UNLOCK(p2);
+
+ td2 = FIRST_THREAD_IN_PROC(p2);
+
+ /*
+ * Make this runnable after we are finished with it.
+ */
+ thread_lock(td2);
+ TD_SET_CAN_RUN(td2);
+ sched_add(td2, SRQ_BORING);
+ thread_unlock(td2);
+
+ /* wait for the children to exit, ie. emulate vfork */
+ PROC_LOCK(p2);
+ while (p2->p_flag & P_PPWAIT)
+ msleep(td->td_proc, &p2->p_mtx, PWAIT, "ppwait", 0);
+ PROC_UNLOCK(p2);
+
return (0);
}
-#define CLONE_VM 0x100
-#define CLONE_FS 0x200
-#define CLONE_FILES 0x400
-#define CLONE_SIGHAND 0x800
-#define CLONE_PID 0x1000
-
int
linux_clone(struct thread *td, struct linux_clone_args *args)
{
@@ -481,74 +550,190 @@
struct proc *p2;
struct thread *td2;
int exit_signal;
+ struct linux_emuldata *em;
#ifdef DEBUG
if (ldebug(clone)) {
- printf(ARGS(clone, "flags %x, stack %x"),
- (unsigned int)(uintptr_t)args->flags,
- (unsigned int)(uintptr_t)args->stack);
- if (args->flags & CLONE_PID)
- printf(LMSG("CLONE_PID not yet supported"));
+ printf(ARGS(clone, "flags %x, stack %p, parent tid: %p, "
+ "child tid: %p"), (unsigned)args->flags,
+ args->stack, args->parent_tidptr, args->child_tidptr);
}
#endif
- if (!args->stack)
- return (EINVAL);
-
exit_signal = args->flags & 0x000000ff;
- if (exit_signal >= LINUX_NSIG)
+ if (LINUX_SIG_VALID(exit_signal)) {
+ if (exit_signal <= LINUX_SIGTBLSZ)
+ exit_signal =
+ linux_to_bsd_signal[_SIG_IDX(exit_signal)];
+ } else if (exit_signal != 0)
return (EINVAL);
- if (exit_signal <= LINUX_SIGTBLSZ)
- exit_signal = linux_to_bsd_signal[_SIG_IDX(exit_signal)];
-
- if (args->flags & CLONE_VM)
+ if (args->flags & LINUX_CLONE_VM)
ff |= RFMEM;
- if (args->flags & CLONE_SIGHAND)
+ if (args->flags & LINUX_CLONE_SIGHAND)
ff |= RFSIGSHARE;
- if (!(args->flags & CLONE_FILES))
+ /*
+ * XXX: In Linux, sharing of fs info (chroot/cwd/umask)
+ * and open files is independant. In FreeBSD, its in one
+ * structure but in reality it does not cause any problems
+ * because both of these flags are usually set together.
+ */
+ if (!(args->flags & (LINUX_CLONE_FILES | LINUX_CLONE_FS)))
ff |= RFFDG;
+ /*
+ * Attempt to detect when linux_clone(2) is used for creating
+ * kernel threads. Unfortunately despite the existence of the
+ * CLONE_THREAD flag, version of linuxthreads package used in
+ * most popular distros as of beginning of 2005 doesn't make
+ * any use of it. Therefore, this detection relies on
+ * empirical observation that linuxthreads sets certain
+ * combination of flags, so that we can make more or less
+ * precise detection and notify the FreeBSD kernel that several
+ * processes are in fact part of the same threading group, so
+ * that special treatment is necessary for signal delivery
+ * between those processes and fd locking.
+ */
+ if ((args->flags & 0xffffff00) == LINUX_THREADING_FLAGS)
+ ff |= RFTHREAD;
+
+ if (args->flags & LINUX_CLONE_PARENT_SETTID)
+ if (args->parent_tidptr == NULL)
+ return (EINVAL);
+
error = fork1(td, ff, 0, &p2);
if (error)
return (error);
-
+
+ if (args->flags & (LINUX_CLONE_PARENT | LINUX_CLONE_THREAD)) {
+ sx_xlock(&proctree_lock);
+ PROC_LOCK(p2);
+ proc_reparent(p2, td->td_proc->p_pptr);
+ PROC_UNLOCK(p2);
+ sx_xunlock(&proctree_lock);
+ }
+
+ /* create the emuldata */
+ error = linux_proc_init(td, p2->p_pid, args->flags);
+ /* reference it - no need to check this */
+ em = em_find(p2, EMUL_DOLOCK);
+ KASSERT(em != NULL, ("clone: emuldata not found.\n"));
+ /* and adjust it */
+
+ if (args->flags & LINUX_CLONE_THREAD) {
+#ifdef notyet
+ PROC_LOCK(p2);
+ p2->p_pgrp = td->td_proc->p_pgrp;
+ PROC_UNLOCK(p2);
+#endif
+ exit_signal = 0;
+ }
+
+ if (args->flags & LINUX_CLONE_CHILD_SETTID)
+ em->child_set_tid = args->child_tidptr;
+ else
+ em->child_set_tid = NULL;
+
+ if (args->flags & LINUX_CLONE_CHILD_CLEARTID)
+ em->child_clear_tid = args->child_tidptr;
+ else
+ em->child_clear_tid = NULL;
+
+ EMUL_UNLOCK(&emul_lock);
+
+ if (args->flags & LINUX_CLONE_PARENT_SETTID) {
+ error = copyout(&p2->p_pid, args->parent_tidptr,
+ sizeof(p2->p_pid));
+ if (error)
+ printf(LMSG("copyout failed!"));
+ }
PROC_LOCK(p2);
p2->p_sigparent = exit_signal;
PROC_UNLOCK(p2);
td2 = FIRST_THREAD_IN_PROC(p2);
- td2->td_frame->tf_rsp = PTROUT(args->stack);
+ /*
+ * In a case of stack = NULL, we are supposed to COW calling process
+ * stack. This is what normal fork() does, so we just keep tf_rsp arg
+ * intact.
+ */
+ if (args->stack)
+ td2->td_frame->tf_rsp = PTROUT(args->stack);
+
+ if (args->flags & LINUX_CLONE_SETTLS) {
+ struct user_segment_descriptor sd;
+ struct l_user_desc info;
+ int a[2];
+
+ error = copyin((void *)td->td_frame->tf_rsi, &info,
+ sizeof(struct l_user_desc));
+ if (error) {
+ printf(LMSG("copyin failed!"));
+ } else {
+ /* We might copy out the entry_number as GUGS32_SEL. */
+ info.entry_number = GUGS32_SEL;
+ error = copyout(&info, (void *)td->td_frame->tf_rsi,
+ sizeof(struct l_user_desc));
+ if (error)
+ printf(LMSG("copyout failed!"));
+
+ a[0] = LINUX_LDT_entry_a(&info);
+ a[1] = LINUX_LDT_entry_b(&info);
+
+ memcpy(&sd, &a, sizeof(a));
+#ifdef DEBUG
+ if (ldebug(clone))
+ printf("Segment created in clone with "
+ "CLONE_SETTLS: lobase: %x, hibase: %x, "
+ "lolimit: %x, hilimit: %x, type: %i, "
+ "dpl: %i, p: %i, xx: %i, long: %i, "
+ "def32: %i, gran: %i\n", sd.sd_lobase,
+ sd.sd_hibase, sd.sd_lolimit, sd.sd_hilimit,
+ sd.sd_type, sd.sd_dpl, sd.sd_p, sd.sd_xx,
+ sd.sd_long, sd.sd_def32, sd.sd_gran);
+#endif
+ td2->td_pcb->pcb_gsbase = (register_t)info.base_addr;
+ td2->td_pcb->pcb_gs32sd = sd;
+ td2->td_pcb->pcb_gs32p = &gdt[GUGS32_SEL];
+ td2->td_pcb->pcb_gs = GSEL(GUGS32_SEL, SEL_UPL);
+ td2->td_pcb->pcb_flags |= PCB_32BIT;
+ }
+ }
#ifdef DEBUG
if (ldebug(clone))
- printf(LMSG("clone: successful rfork to %ld, stack %p sig = %d"),
- (long)p2->p_pid, args->stack, exit_signal);
+ printf(LMSG("clone: successful rfork to %d, "
+ "stack %p sig = %d"), (int)p2->p_pid, args->stack,
+ exit_signal);
#endif
+ if (args->flags & LINUX_CLONE_VFORK) {
+ PROC_LOCK(p2);
+ p2->p_flag |= P_PPWAIT;
+ PROC_UNLOCK(p2);
+ }
/*
* Make this runnable after we are finished with it.
*/
- mtx_lock_spin(&sched_lock);
+ thread_lock(td2);
TD_SET_CAN_RUN(td2);
- setrunqueue(td2, SRQ_BORING);
- mtx_unlock_spin(&sched_lock);
+ sched_add(td2, SRQ_BORING);
+ thread_unlock(td2);
td->td_retval[0] = p2->p_pid;
td->td_retval[1] = 0;
+
+ if (args->flags & LINUX_CLONE_VFORK) {
+ /* wait for the children to exit, ie. emulate vfork */
+ PROC_LOCK(p2);
+ while (p2->p_flag & P_PPWAIT)
+ msleep(td->td_proc, &p2->p_mtx, PWAIT, "ppwait", 0);
+ PROC_UNLOCK(p2);
+ }
+
return (0);
}
-/* XXX move */
-struct l_mmap_argv {
- l_ulong addr;
- l_ulong len;
- l_ulong prot;
- l_ulong flags;
- l_ulong fd;
- l_ulong pgoff;
-};
-
#define STACK_SIZE (2 * 1024 * 1024)
#define GUARD_SIZE (4 * PAGE_SIZE)
@@ -561,8 +746,8 @@
#ifdef DEBUG
if (ldebug(mmap2))
- printf(ARGS(mmap2, "%p, %d, %d, 0x%08x, %d, %d"),
- (void *)(intptr_t)args->addr, args->len, args->prot,
+ printf(ARGS(mmap2, "0x%08x, %d, %d, 0x%08x, %d, %d"),
+ args->addr, args->len, args->prot,
args->flags, args->fd, args->pgoff);
#endif
@@ -588,10 +773,9 @@
#ifdef DEBUG
if (ldebug(mmap))
- printf(ARGS(mmap, "%p, %d, %d, 0x%08x, %d, %d"),
- (void *)(intptr_t)linux_args.addr, linux_args.len,
- linux_args.prot, linux_args.flags, linux_args.fd,
- linux_args.pgoff);
+ printf(ARGS(mmap, "0x%08x, %d, %d, 0x%08x, %d, %d"),
+ linux_args.addr, linux_args.len, linux_args.prot,
+ linux_args.flags, linux_args.fd, linux_args.pgoff);
#endif
if ((linux_args.pgoff % PAGE_SIZE) != 0)
return (EINVAL);
@@ -614,9 +798,20 @@
off_t pos;
} */ bsd_args;
int error;
+ struct file *fp;
error = 0;
bsd_args.flags = 0;
+ fp = NULL;
+
+ /*
+ * Linux mmap(2):
+ * You must specify exactly one of MAP_SHARED and MAP_PRIVATE
+ */
+ if (! ((linux_args->flags & LINUX_MAP_SHARED) ^
+ (linux_args->flags & LINUX_MAP_PRIVATE)))
+ return (EINVAL);
+
if (linux_args->flags & LINUX_MAP_SHARED)
bsd_args.flags |= MAP_SHARED;
if (linux_args->flags & LINUX_MAP_PRIVATE)
@@ -627,23 +822,60 @@
bsd_args.flags |= MAP_ANON;
else
bsd_args.flags |= MAP_NOSYNC;
- if (linux_args->flags & LINUX_MAP_GROWSDOWN) {
+ if (linux_args->flags & LINUX_MAP_GROWSDOWN)
bsd_args.flags |= MAP_STACK;
- /* The linux MAP_GROWSDOWN option does not limit auto
+ /*
+ * PROT_READ, PROT_WRITE, or PROT_EXEC implies PROT_READ and PROT_EXEC
+ * on Linux/i386. We do this to ensure maximum compatibility.
+ * Linux/ia64 does the same in i386 emulation mode.
+ */
+ bsd_args.prot = linux_args->prot;
+ if (bsd_args.prot & (PROT_READ | PROT_WRITE | PROT_EXEC))
+ bsd_args.prot |= PROT_READ | PROT_EXEC;
+
+ /* Linux does not check file descriptor when MAP_ANONYMOUS is set. */
+ bsd_args.fd = (bsd_args.flags & MAP_ANON) ? -1 : linux_args->fd;
+ if (bsd_args.fd != -1) {
+ /*
+ * Linux follows Solaris mmap(2) description:
+ * The file descriptor fildes is opened with
+ * read permission, regardless of the
+ * protection options specified.
+ */
+
+ if ((error = fget(td, bsd_args.fd, &fp)) != 0)
+ return (error);
+ if (fp->f_type != DTYPE_VNODE) {
+ fdrop(fp, td);
+ return (EINVAL);
+ }
+
+ /* Linux mmap() just fails for O_WRONLY files */
+ if (!(fp->f_flag & FREAD)) {
+ fdrop(fp, td);
+ return (EACCES);
+ }
+
+ fdrop(fp, td);
+ }
+
+ if (linux_args->flags & LINUX_MAP_GROWSDOWN) {
+ /*
+ * The Linux MAP_GROWSDOWN option does not limit auto
* growth of the region. Linux mmap with this option
* takes as addr the inital BOS, and as len, the initial
* region size. It can then grow down from addr without
- * limit. However, linux threads has an implicit internal
+ * limit. However, Linux threads has an implicit internal
* limit to stack size of STACK_SIZE. Its just not
- * enforced explicitly in linux. But, here we impose
+ * enforced explicitly in Linux. But, here we impose
* a limit of (STACK_SIZE - GUARD_SIZE) on the stack
* region, since we can do this with our mmap.
*
* Our mmap with MAP_STACK takes addr as the maximum
* downsize limit on BOS, and as len the max size of
- * the region. It them maps the top SGROWSIZ bytes,
- * and autgrows the region down, up to the limit
+ * the region. It then maps the top SGROWSIZ bytes,
+ * and auto grows the region down, up to the limit
* in addr.
*
* If we don't use the MAP_STACK option, the effect
@@ -651,13 +883,10 @@
* fixed size of (STACK_SIZE - GUARD_SIZE).
*/
- /* This gives us TOS */
- bsd_args.addr = (caddr_t)PTRIN(linux_args->addr) +
- linux_args->len;
-
- if ((caddr_t)PTRIN(bsd_args.addr) >
+ if ((caddr_t)PTRIN(linux_args->addr) + linux_args->len >
p->p_vmspace->vm_maxsaddr) {
- /* Some linux apps will attempt to mmap
+ /*
+ * Some Linux apps will attempt to mmap
* thread stacks near the top of their
* address space. If their TOS is greater
* than vm_maxsaddr, vm_map_growstack()
@@ -673,8 +902,7 @@
* mmap's return value.
*/
PROC_LOCK(p);
- p->p_vmspace->vm_maxsaddr =
- (char *)LINUX32_USRSTACK -
+ p->p_vmspace->vm_maxsaddr = (char *)LINUX32_USRSTACK -
lim_cur(p, RLIMIT_STACK);
PROC_UNLOCK(p);
}
@@ -685,30 +913,20 @@
else
bsd_args.len = STACK_SIZE - GUARD_SIZE;
- /* This gives us a new BOS. If we're using VM_STACK, then
+ /*
+ * This gives us a new BOS. If we're using VM_STACK, then
* mmap will just map the top SGROWSIZ bytes, and let
* the stack grow down to the limit at BOS. If we're
* not using VM_STACK we map the full stack, since we
* don't have a way to autogrow it.
*/
- bsd_args.addr -= bsd_args.len;
+ bsd_args.addr = (caddr_t)PTRIN(linux_args->addr) -
+ bsd_args.len;
} else {
bsd_args.addr = (caddr_t)PTRIN(linux_args->addr);
bsd_args.len = linux_args->len;
}
- /*
- * XXX i386 Linux always emulator forces PROT_READ on (why?)
- * so we do the same. We add PROT_EXEC to work around buggy
- * applications (e.g. Java) that take advantage of the fact
- * that execute permissions are not enforced by x86 CPUs.
- */
- bsd_args.prot = linux_args->prot | PROT_EXEC | PROT_READ;
- if (linux_args->flags & LINUX_MAP_ANON)
- bsd_args.fd = -1;
- else
- bsd_args.fd = linux_args->fd;
bsd_args.pos = (off_t)linux_args->pgoff * PAGE_SIZE;
- bsd_args.pad = 0;
#ifdef DEBUG
if (ldebug(mmap))
@@ -727,6 +945,36 @@
}
int
+linux_mprotect(struct thread *td, struct linux_mprotect_args *uap)
+{
+ struct mprotect_args bsd_args;
+
+ bsd_args.addr = uap->addr;
+ bsd_args.len = uap->len;
+ bsd_args.prot = uap->prot;
+ if (bsd_args.prot & (PROT_READ | PROT_WRITE | PROT_EXEC))
+ bsd_args.prot |= PROT_READ | PROT_EXEC;
+ return (mprotect(td, &bsd_args));
+}
+
+int
+linux_iopl(struct thread *td, struct linux_iopl_args *args)
+{
+ int error;
+
+ if (args->level < 0 || args->level > 3)
+ return (EINVAL);
+ if ((error = priv_check(td, PRIV_IO)) != 0)
+ return (error);
+ if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
+ return (error);
+ td->td_frame->tf_rflags = (td->td_frame->tf_rflags & ~PSL_IOPL) |
+ (args->level * (PSL_IOPL / 3));
+
+ return (0);
+}
+
+int
linux_pipe(struct thread *td, struct linux_pipe_args *args)
{
int pip[2];
@@ -797,7 +1045,7 @@
}
/*
- * Linux has two extra args, restart and oldmask. We dont use these,
+ * Linux has two extra args, restart and oldmask. We don't use these,
* but it seems that "restart" is actually a context pointer that
* enables the signal to happen with a different register set.
*/
@@ -904,7 +1152,6 @@
#endif
sa.fd = args->fd;
- sa.pad = 0;
sa.length = args->length;
return ftruncate(td, &sa);
}
@@ -921,35 +1168,41 @@
microtime(&atv);
atv32.tv_sec = atv.tv_sec;
atv32.tv_usec = atv.tv_usec;
- error = copyout(&atv32, uap->tp, sizeof (atv32));
+ error = copyout(&atv32, uap->tp, sizeof(atv32));
}
if (error == 0 && uap->tzp != NULL) {
rtz.tz_minuteswest = tz_minuteswest;
rtz.tz_dsttime = tz_dsttime;
- error = copyout(&rtz, uap->tzp, sizeof (rtz));
+ error = copyout(&rtz, uap->tzp, sizeof(rtz));
}
return (error);
}
int
-linux_nanosleep(struct thread *td, struct linux_nanosleep_args *uap)
+linux_settimeofday(struct thread *td, struct linux_settimeofday_args *uap)
{
- struct timespec rqt, rmt;
- struct l_timespec ats32;
+ l_timeval atv32;
+ struct timeval atv, *tvp;
+ struct timezone atz, *tzp;
int error;
- error = copyin(uap->rqtp, &ats32, sizeof(ats32));
- if (error != 0)
- return (error);
- rqt.tv_sec = ats32.tv_sec;
- rqt.tv_nsec = ats32.tv_nsec;
- error = kern_nanosleep(td, &rqt, &rmt);
- if (uap->rmtp != NULL) {
- ats32.tv_sec = rmt.tv_sec;
- ats32.tv_nsec = rmt.tv_nsec;
- error = copyout(&ats32, uap->rmtp, sizeof(ats32));
- }
- return (error);
+ if (uap->tp) {
+ error = copyin(uap->tp, &atv32, sizeof(atv32));
+ if (error)
+ return (error);
+ atv.tv_sec = atv32.tv_sec;
+ atv.tv_usec = atv32.tv_usec;
+ tvp = &atv;
+ } else
+ tvp = NULL;
+ if (uap->tzp) {
+ error = copyin(uap->tzp, &atz, sizeof(atz));
+ if (error)
+ return (error);
+ tzp = &atz;
+ } else
+ tzp = NULL;
+ return (kern_settimeofday(td, tvp, tzp));
}
int
@@ -1003,15 +1256,106 @@
}
int
-linux_mprotect(struct thread *td, struct linux_mprotect_args *uap)
+linux_set_thread_area(struct thread *td,
+ struct linux_set_thread_area_args *args)
{
- struct mprotect_args bsd_args;
+ struct l_user_desc info;
+ struct user_segment_descriptor sd;
+ int a[2];
+ int error;
- bsd_args.addr = uap->addr;
- bsd_args.len = uap->len;
- bsd_args.prot = uap->prot;
- /* XXX PROT_READ implies PROT_EXEC; see linux_mmap_common(). */
- if ((bsd_args.prot & PROT_READ) != 0)
- bsd_args.prot |= PROT_EXEC;
- return (mprotect(td, &bsd_args));
+ error = copyin(args->desc, &info, sizeof(struct l_user_desc));
+ if (error)
+ return (error);
+
+#ifdef DEBUG
+ if (ldebug(set_thread_area))
+ printf(ARGS(set_thread_area, "%i, %x, %x, %i, %i, %i, "
+ "%i, %i, %i"), info.entry_number, info.base_addr,
+ info.limit, info.seg_32bit, info.contents,
+ info.read_exec_only, info.limit_in_pages,
+ info.seg_not_present, info.useable);
+#endif
+
+ /*
+ * Semantics of Linux version: every thread in the system has array
+ * of three TLS descriptors. 1st is GLIBC TLS, 2nd is WINE, 3rd unknown.
+ * This syscall loads one of the selected TLS decriptors with a value
+ * and also loads GDT descriptors 6, 7 and 8 with the content of
+ * the per-thread descriptors.
+ *
+ * Semantics of FreeBSD version: I think we can ignore that Linux has
+ * three per-thread descriptors and use just the first one.
+ * The tls_array[] is used only in [gs]et_thread_area() syscalls and
+ * for loading the GDT descriptors. We use just one GDT descriptor
+ * for TLS, so we will load just one.
+ *
+ * XXX: This doesn't work when a user space process tries to use more
+ * than one TLS segment. Comment in the Linux source says wine might
+ * do this.
+ */
+
+ /*
+ * GLIBC reads current %gs and call set_thread_area() with it.
+ * We should let GUDATA_SEL and GUGS32_SEL proceed as well because
+ * we use these segments.
+ */
+ switch (info.entry_number) {
+ case GUGS32_SEL:
+ case GUDATA_SEL:
+ case 6:
+ case -1:
+ info.entry_number = GUGS32_SEL;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ /*
+ * We have to copy out the GDT entry we use.
+ *
+ * XXX: What if a user space program does not check the return value
+ * and tries to use 6, 7 or 8?
+ */
+ error = copyout(&info, args->desc, sizeof(struct l_user_desc));
+ if (error)
+ return (error);
+
+ if (LINUX_LDT_empty(&info)) {
+ a[0] = 0;
+ a[1] = 0;
+ } else {
+ a[0] = LINUX_LDT_entry_a(&info);
+ a[1] = LINUX_LDT_entry_b(&info);
+ }
+
+ memcpy(&sd, &a, sizeof(a));
+#ifdef DEBUG
+ if (ldebug(set_thread_area))
+ printf("Segment created in set_thread_area: "
+ "lobase: %x, hibase: %x, lolimit: %x, hilimit: %x, "
+ "type: %i, dpl: %i, p: %i, xx: %i, long: %i, "
+ "def32: %i, gran: %i\n",
+ sd.sd_lobase,
+ sd.sd_hibase,
+ sd.sd_lolimit,
+ sd.sd_hilimit,
+ sd.sd_type,
+ sd.sd_dpl,
+ sd.sd_p,
+ sd.sd_xx,
+ sd.sd_long,
+ sd.sd_def32,
+ sd.sd_gran);
+#endif
+
+ critical_enter();
+ td->td_pcb->pcb_gsbase = (register_t)info.base_addr;
+ td->td_pcb->pcb_gs32sd = gdt[GUGS32_SEL] = sd;
+ td->td_pcb->pcb_gs32p = &gdt[GUGS32_SEL];
+ td->td_pcb->pcb_flags |= PCB_32BIT;
+ wrmsr(MSR_KGSBASE, td->td_pcb->pcb_gsbase);
+ critical_exit();
+
+ return (0);
}
Index: linux32_dummy.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/linux32/linux32_dummy.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/linux32/linux32_dummy.c -L sys/amd64/linux32/linux32_dummy.c -u -r1.1.1.1 -r1.2
--- sys/amd64/linux32/linux32_dummy.c
+++ sys/amd64/linux32/linux32_dummy.c
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/linux32/linux32_dummy.c,v 1.1 2004/08/16 07:55:06 tjr Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/linux32/linux32_dummy.c,v 1.9 2007/04/18 18:08:12 jkim Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -53,9 +53,6 @@
DUMMY(sysfs);
DUMMY(query_module);
DUMMY(nfsservctl);
-DUMMY(prctl);
-DUMMY(rt_sigpending);
-DUMMY(rt_sigtimedwait);
DUMMY(rt_sigqueueinfo);
DUMMY(capget);
DUMMY(capset);
@@ -67,7 +64,53 @@
DUMMY(mincore);
DUMMY(fadvise64);
DUMMY(ptrace);
-DUMMY(settimeofday);
+DUMMY(lookup_dcookie);
+DUMMY(epoll_create);
+DUMMY(epoll_ctl);
+DUMMY(epoll_wait);
+DUMMY(remap_file_pages);
+DUMMY(timer_create);
+DUMMY(timer_settime);
+DUMMY(timer_gettime);
+DUMMY(timer_getoverrun);
+DUMMY(timer_delete);
+DUMMY(fstatfs64);
+DUMMY(fadvise64_64);
+DUMMY(mbind);
+DUMMY(get_mempolicy);
+DUMMY(set_mempolicy);
+DUMMY(mq_open);
+DUMMY(mq_unlink);
+DUMMY(mq_timedsend);
+DUMMY(mq_timedreceive);
+DUMMY(mq_notify);
+DUMMY(mq_getsetattr);
+DUMMY(kexec_load);
+DUMMY(waitid);
+DUMMY(add_key);
+DUMMY(request_key);
+DUMMY(keyctl);
+DUMMY(ioprio_set);
+DUMMY(ioprio_get);
+DUMMY(inotify_init);
+DUMMY(inotify_add_watch);
+DUMMY(inotify_rm_watch);
+DUMMY(migrate_pages);
+DUMMY(mkdirat);
+DUMMY(mknodat);
+DUMMY(fchownat);
+DUMMY(futimesat);
+DUMMY(fstatat64);
+DUMMY(unlinkat);
+DUMMY(renameat);
+DUMMY(linkat);
+DUMMY(symlinkat);
+DUMMY(readlinkat);
+DUMMY(fchmodat);
+DUMMY(faccessat);
+DUMMY(pselect6);
+DUMMY(ppoll);
+DUMMY(unshare);
#define DUMMY_XATTR(s) \
int \
Index: linux32_locore.s
===================================================================
RCS file: /home/cvs/src/sys/amd64/linux32/linux32_locore.s,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/linux32/linux32_locore.s -L sys/amd64/linux32/linux32_locore.s -u -r1.1.1.1 -r1.2
--- sys/amd64/linux32/linux32_locore.s
+++ sys/amd64/linux32/linux32_locore.s
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/amd64/linux32/linux32_locore.s,v 1.1 2004/08/16 07:55:06 tjr Exp $ */
+/* $FreeBSD: src/sys/amd64/linux32/linux32_locore.s,v 1.2 2007/03/30 00:06:21 jkim Exp $ */
#include "linux32_assym.h" /* system definitions */
#include <machine/asmacros.h> /* miscellaneous asm macros */
@@ -11,8 +11,6 @@
NON_GPROF_ENTRY(linux_sigcode)
call *LINUX_SIGF_HANDLER(%esp)
leal LINUX_SIGF_SC(%esp),%ebx /* linux scp */
- movl LINUX_SC_GS(%ebx),%gs
- movl LINUX_SC_FS(%ebx),%fs
movl LINUX_SC_ES(%ebx),%es
movl LINUX_SC_DS(%ebx),%ds
movl %esp, %ebx /* pass sigframe */
@@ -25,8 +23,6 @@
linux_rt_sigcode:
call *LINUX_RT_SIGF_HANDLER(%esp)
leal LINUX_RT_SIGF_UC(%esp),%ebx /* linux ucp */
- movl LINUX_SC_GS(%ebx),%gs
- movl LINUX_SC_FS(%ebx),%fs
movl LINUX_SC_ES(%ebx),%es
movl LINUX_SC_DS(%ebx),%ds
push %eax /* fake ret addr */
Index: linux32_syscall.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/linux32/linux32_syscall.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/linux32/linux32_syscall.h -L sys/amd64/linux32/linux32_syscall.h -u -r1.1.1.1 -r1.2
--- sys/amd64/linux32/linux32_syscall.h
+++ sys/amd64/linux32/linux32_syscall.h
@@ -2,8 +2,8 @@
* System call numbers.
*
* DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/amd64/linux32/linux32_syscall.h,v 1.5.2.1 2005/07/20 17:43:52 jhb Exp $
- * created from FreeBSD: src/sys/amd64/linux32/syscalls.master,v 1.4.2.1 2005/07/20 17:42:14 jhb Exp
+ * $FreeBSD: src/sys/amd64/linux32/linux32_syscall.h,v 1.33 2007/09/18 19:50:32 dwmalone Exp $
+ * created from FreeBSD: src/sys/amd64/linux32/syscalls.master,v 1.29 2007/08/28 12:26:34 kib Exp
*/
#define LINUX_SYS_exit 1
@@ -22,6 +22,7 @@
#define LINUX_SYS_linux_mknod 14
#define LINUX_SYS_linux_chmod 15
#define LINUX_SYS_linux_lchown16 16
+#define LINUX_SYS_linux_stat 18
#define LINUX_SYS_linux_lseek 19
#define LINUX_SYS_linux_getpid 20
#define LINUX_SYS_linux_mount 21
@@ -59,7 +60,7 @@
#define LINUX_SYS_chroot 61
#define LINUX_SYS_linux_ustat 62
#define LINUX_SYS_dup2 63
-#define LINUX_SYS_getppid 64
+#define LINUX_SYS_linux_getppid 64
#define LINUX_SYS_getpgrp 65
#define LINUX_SYS_setsid 66
#define LINUX_SYS_linux_sigaction 67
@@ -69,7 +70,7 @@
#define LINUX_SYS_linux_setregid16 71
#define LINUX_SYS_linux_sigsuspend 72
#define LINUX_SYS_linux_sigpending 73
-#define LINUX_SYS_osethostname 74
+#define LINUX_SYS_linux_sethostname 74
#define LINUX_SYS_linux_setrlimit 75
#define LINUX_SYS_linux_old_getrlimit 76
#define LINUX_SYS_linux_getrusage 77
@@ -79,6 +80,7 @@
#define LINUX_SYS_linux_setgroups16 81
#define LINUX_SYS_linux_old_select 82
#define LINUX_SYS_linux_symlink 83
+#define LINUX_SYS_linux_lstat 84
#define LINUX_SYS_linux_readlink 85
#define LINUX_SYS_swapon 87
#define LINUX_SYS_linux_reboot 88
@@ -86,7 +88,7 @@
#define LINUX_SYS_linux_mmap 90
#define LINUX_SYS_munmap 91
#define LINUX_SYS_linux_truncate 92
-#define LINUX_SYS_oftruncate 93
+#define LINUX_SYS_linux_ftruncate 93
#define LINUX_SYS_fchmod 94
#define LINUX_SYS_fchown 95
#define LINUX_SYS_linux_getpriority 96
@@ -101,6 +103,7 @@
#define LINUX_SYS_linux_newlstat 107
#define LINUX_SYS_linux_newfstat 108
#define LINUX_SYS_linux_uname 109
+#define LINUX_SYS_linux_iopl 110
#define LINUX_SYS_linux_vhangup 111
#define LINUX_SYS_linux_wait4 114
#define LINUX_SYS_linux_swapoff 115
@@ -204,7 +207,7 @@
#define LINUX_SYS_madvise 219
#define LINUX_SYS_linux_getdents64 220
#define LINUX_SYS_linux_fcntl64 221
-#define LINUX_SYS_gettid 224
+#define LINUX_SYS_linux_gettid 224
#define LINUX_SYS_linux_setxattr 226
#define LINUX_SYS_linux_lsetxattr 227
#define LINUX_SYS_linux_fsetxattr 228
@@ -217,6 +220,66 @@
#define LINUX_SYS_linux_removexattr 235
#define LINUX_SYS_linux_lremovexattr 236
#define LINUX_SYS_linux_fremovexattr 237
+#define LINUX_SYS_linux_tkill 238
+#define LINUX_SYS_linux_sys_futex 240
+#define LINUX_SYS_linux_sched_getaffinity 242
+#define LINUX_SYS_linux_set_thread_area 243
#define LINUX_SYS_linux_fadvise64 250
-#define LINUX_SYS_exit_group 252
-#define LINUX_SYS_MAXSYSCALL 268
+#define LINUX_SYS_linux_exit_group 252
+#define LINUX_SYS_linux_lookup_dcookie 253
+#define LINUX_SYS_linux_epoll_create 254
+#define LINUX_SYS_linux_epoll_ctl 255
+#define LINUX_SYS_linux_epoll_wait 256
+#define LINUX_SYS_linux_remap_file_pages 257
+#define LINUX_SYS_linux_set_tid_address 258
+#define LINUX_SYS_linux_timer_create 259
+#define LINUX_SYS_linux_timer_settime 260
+#define LINUX_SYS_linux_timer_gettime 261
+#define LINUX_SYS_linux_timer_getoverrun 262
+#define LINUX_SYS_linux_timer_delete 263
+#define LINUX_SYS_linux_clock_settime 264
+#define LINUX_SYS_linux_clock_gettime 265
+#define LINUX_SYS_linux_clock_getres 266
+#define LINUX_SYS_linux_clock_nanosleep 267
+#define LINUX_SYS_linux_statfs64 268
+#define LINUX_SYS_linux_fstatfs64 269
+#define LINUX_SYS_linux_tgkill 270
+#define LINUX_SYS_linux_utimes 271
+#define LINUX_SYS_linux_fadvise64_64 272
+#define LINUX_SYS_linux_mbind 274
+#define LINUX_SYS_linux_get_mempolicy 275
+#define LINUX_SYS_linux_set_mempolicy 276
+#define LINUX_SYS_linux_mq_open 277
+#define LINUX_SYS_linux_mq_unlink 278
+#define LINUX_SYS_linux_mq_timedsend 279
+#define LINUX_SYS_linux_mq_timedreceive 280
+#define LINUX_SYS_linux_mq_notify 281
+#define LINUX_SYS_linux_mq_getsetattr 282
+#define LINUX_SYS_linux_kexec_load 283
+#define LINUX_SYS_linux_waitid 284
+#define LINUX_SYS_linux_add_key 286
+#define LINUX_SYS_linux_request_key 287
+#define LINUX_SYS_linux_keyctl 288
+#define LINUX_SYS_linux_ioprio_set 289
+#define LINUX_SYS_linux_ioprio_get 290
+#define LINUX_SYS_linux_inotify_init 291
+#define LINUX_SYS_linux_inotify_add_watch 292
+#define LINUX_SYS_linux_inotify_rm_watch 293
+#define LINUX_SYS_linux_migrate_pages 294
+#define LINUX_SYS_linux_openat 295
+#define LINUX_SYS_linux_mkdirat 296
+#define LINUX_SYS_linux_mknodat 297
+#define LINUX_SYS_linux_fchownat 298
+#define LINUX_SYS_linux_futimesat 299
+#define LINUX_SYS_linux_fstatat64 300
+#define LINUX_SYS_linux_unlinkat 301
+#define LINUX_SYS_linux_renameat 302
+#define LINUX_SYS_linux_linkat 303
+#define LINUX_SYS_linux_symlinkat 304
+#define LINUX_SYS_linux_readlinkat 305
+#define LINUX_SYS_linux_fchmodat 306
+#define LINUX_SYS_linux_faccessat 307
+#define LINUX_SYS_linux_pselect6 308
+#define LINUX_SYS_linux_ppoll 309
+#define LINUX_SYS_linux_unshare 310
+#define LINUX_SYS_MAXSYSCALL 311
Index: linux32_sysvec.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/linux32/linux32_sysvec.c,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -L sys/amd64/linux32/linux32_sysvec.c -L sys/amd64/linux32/linux32_sysvec.c -u -r1.1.1.2 -r1.2
--- sys/amd64/linux32/linux32_sysvec.c
+++ sys/amd64/linux32/linux32_sysvec.c
@@ -31,14 +31,9 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/linux32/linux32_sysvec.c,v 1.7.2.2 2005/12/22 21:25:19 jhb Exp $");
-
-/* XXX we use functions that might not exist. */
+__FBSDID("$FreeBSD: src/sys/amd64/linux32/linux32_sysvec.c,v 1.31 2007/09/20 13:46:26 kib Exp $");
#include "opt_compat.h"
-#ifndef COMPAT_43
-#error "Unable to compile Linux-emulator due to missing COMPAT_43 option!"
-#endif
#ifndef COMPAT_IA32
#error "Unable to compile Linux-emulator due to missing COMPAT_IA32 option!"
#endif
@@ -63,6 +58,7 @@
#include <sys/sysent.h>
#include <sys/sysproto.h>
#include <sys/vnode.h>
+#include <sys/eventhandler.h>
#include <vm/vm.h>
#include <vm/pmap.h>
@@ -79,14 +75,12 @@
#include <amd64/linux32/linux.h>
#include <amd64/linux32/linux32_proto.h>
+#include <compat/linux/linux_emul.h>
#include <compat/linux/linux_mib.h>
#include <compat/linux/linux_signal.h>
#include <compat/linux/linux_util.h>
MODULE_VERSION(linux, 1);
-MODULE_DEPEND(linux, sysvmsg, 1, 1, 1);
-MODULE_DEPEND(linux, sysvsem, 1, 1, 1);
-MODULE_DEPEND(linux, sysvshm, 1, 1, 1);
MALLOC_DEFINE(M_LINUX, "linux", "Linux mode structures");
@@ -117,20 +111,31 @@
extern struct sysent linux_sysent[LINUX_SYS_MAXSYSCALL];
SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler);
+SET_DECLARE(linux_device_handler_set, struct linux_device_handler);
static int elf_linux_fixup(register_t **stack_base,
struct image_params *iparams);
static register_t *linux_copyout_strings(struct image_params *imgp);
static void linux_prepsyscall(struct trapframe *tf, int *args, u_int *code,
caddr_t *params);
-static void linux_sendsig(sig_t catcher, int sig, sigset_t *mask,
- u_long code);
+static void linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask);
static void exec_linux_setregs(struct thread *td, u_long entry,
u_long stack, u_long ps_strings);
-static void linux32_fixlimits(struct image_params *imgp);
+static void linux32_fixlimit(struct rlimit *rl, int which);
+
+extern LIST_HEAD(futex_list, futex) futex_list;
+extern struct sx futex_sx;
+
+static eventhandler_tag linux_exit_tag;
+static eventhandler_tag linux_schedtail_tag;
+static eventhandler_tag linux_exec_tag;
/*
* Linux syscalls return negative errno's, we do positive and map them
+ * Reference:
+ * FreeBSD: src/sys/sys/errno.h
+ * Linux: linux-2.6.17.8/include/asm-generic/errno-base.h
+ * linux-2.6.17.8/include/asm-generic/errno.h
*/
static int bsd_to_linux_errno[ELAST + 1] = {
-0, -1, -2, -3, -4, -5, -6, -7, -8, -9,
@@ -141,7 +146,8 @@
-100,-101,-102,-103,-104,-105,-106,-107,-108,-109,
-110,-111, -40, -36,-112,-113, -39, -11, -87,-122,
-116, -66, -6, -6, -6, -6, -6, -37, -38, -9,
- -6, -6, -43, -42, -75, -6, -84
+ -6, -6, -43, -42, -75,-125, -84, -95, -16, -74,
+ -72, -67, -71
};
int bsd_to_linux_signal[LINUX_SIGTBLSZ] = {
@@ -278,7 +284,7 @@
extern unsigned long linux_sznonrtsigcode;
static void
-linux_rt_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
+linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
{
struct thread *td = curthread;
struct proc *p = td->td_proc;
@@ -286,7 +292,11 @@
struct trapframe *regs;
struct l_rt_sigframe *fp, frame;
int oonstack;
-
+ int sig;
+ int code;
+
+ sig = ksi->ksi_signo;
+ code = ksi->ksi_code;
PROC_LOCK_ASSERT(p, MA_OWNED);
psp = p->p_sigacts;
mtx_assert(&psp->ps_mtx, MA_OWNED);
@@ -295,7 +305,7 @@
#ifdef DEBUG
if (ldebug(rt_sendsig))
- printf(ARGS(rt_sendsig, "%p, %d, %p, %lu"),
+ printf(ARGS(rt_sendsig, "%p, %d, %p, %u"),
catcher, sig, (void*)mask, code);
#endif
/*
@@ -326,7 +336,7 @@
/* Fill in POSIX parts */
frame.sf_si.lsi_signo = sig;
frame.sf_si.lsi_code = code;
- frame.sf_si.lsi_addr = PTROUT(regs->tf_err);
+ frame.sf_si.lsi_addr = PTROUT(ksi->ksi_addr);
/*
* Build the signal context to be used by sigreturn.
@@ -362,6 +372,7 @@
frame.sf_sc.uc_mcontext.sc_esp_at_signal = regs->tf_rsp;
frame.sf_sc.uc_mcontext.sc_ss = regs->tf_ss;
frame.sf_sc.uc_mcontext.sc_err = regs->tf_err;
+ frame.sf_sc.uc_mcontext.sc_cr2 = (u_int32_t)(uintptr_t)ksi->ksi_addr;
frame.sf_sc.uc_mcontext.sc_trapno = bsd_to_linux_trapcode(code);
#ifdef DEBUG
@@ -398,6 +409,7 @@
td->td_pcb->pcb_ds = _udatasel;
load_es(_udatasel);
td->td_pcb->pcb_es = _udatasel;
+ /* leave user %fs and %gs untouched */
PROC_LOCK(p);
mtx_lock(&psp->ps_mtx);
}
@@ -414,7 +426,7 @@
* specified pc, psl.
*/
static void
-linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
+linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
{
struct thread *td = curthread;
struct proc *p = td->td_proc;
@@ -423,13 +435,16 @@
struct l_sigframe *fp, frame;
l_sigset_t lmask;
int oonstack, i;
+ int sig, code;
+ sig = ksi->ksi_signo;
+ code = ksi->ksi_code;
PROC_LOCK_ASSERT(p, MA_OWNED);
psp = p->p_sigacts;
mtx_assert(&psp->ps_mtx, MA_OWNED);
if (SIGISMEMBER(psp->ps_siginfo, sig)) {
/* Signal handler installed with SA_SIGINFO. */
- linux_rt_sendsig(catcher, sig, mask, code);
+ linux_rt_sendsig(catcher, ksi, mask);
return;
}
@@ -438,7 +453,7 @@
#ifdef DEBUG
if (ldebug(sendsig))
- printf(ARGS(sendsig, "%p, %d, %p, %lu"),
+ printf(ARGS(sendsig, "%p, %d, %p, %u"),
catcher, sig, (void*)mask, code);
#endif
@@ -489,6 +504,7 @@
frame.sf_sc.sc_esp_at_signal = regs->tf_rsp;
frame.sf_sc.sc_ss = regs->tf_ss;
frame.sf_sc.sc_err = regs->tf_err;
+ frame.sf_sc.sc_cr2 = (u_int32_t)(uintptr_t)ksi->ksi_addr;
frame.sf_sc.sc_trapno = bsd_to_linux_trapcode(code);
for (i = 0; i < (LINUX_NSIG_WORDS-1); i++)
@@ -515,6 +531,7 @@
td->td_pcb->pcb_ds = _udatasel;
load_es(_udatasel);
td->td_pcb->pcb_es = _udatasel;
+ /* leave user %fs and %gs untouched */
PROC_LOCK(p);
mtx_lock(&psp->ps_mtx);
}
@@ -537,6 +554,7 @@
struct trapframe *regs;
l_sigset_t lmask;
int eflags, i;
+ ksiginfo_t ksi;
regs = td->td_frame;
@@ -577,7 +595,12 @@
*/
#define CS_SECURE(cs) (ISPL(cs) == SEL_UPL)
if (!CS_SECURE(frame.sf_sc.sc_cs)) {
- trapsignal(td, SIGBUS, T_PROTFLT);
+ ksiginfo_init_trap(&ksi);
+ ksi.ksi_signo = SIGBUS;
+ ksi.ksi_code = BUS_OBJERR;
+ ksi.ksi_trapno = T_PROTFLT;
+ ksi.ksi_addr = (void *)regs->tf_rip;
+ trapsignal(td, &ksi);
return(EINVAL);
}
@@ -630,6 +653,7 @@
stack_t ss;
struct trapframe *regs;
int eflags;
+ ksiginfo_t ksi;
regs = td->td_frame;
@@ -672,7 +696,12 @@
*/
#define CS_SECURE(cs) (ISPL(cs) == SEL_UPL)
if (!CS_SECURE(context->sc_cs)) {
- trapsignal(td, SIGBUS, T_PROTFLT);
+ ksiginfo_init_trap(&ksi);
+ ksi.ksi_signo = SIGBUS;
+ ksi.ksi_code = BUS_OBJERR;
+ ksi.ksi_trapno = T_PROTFLT;
+ ksi.ksi_addr = (void *)regs->tf_rip;
+ trapsignal(td, &ksi);
return(EINVAL);
}
@@ -788,18 +817,20 @@
struct trapframe *regs = td->td_frame;
struct pcb *pcb = td->td_pcb;
+ critical_enter();
wrmsr(MSR_FSBASE, 0);
wrmsr(MSR_KGSBASE, 0); /* User value while we're in the kernel */
pcb->pcb_fsbase = 0;
pcb->pcb_gsbase = 0;
+ critical_exit();
load_ds(_udatasel);
load_es(_udatasel);
load_fs(_udatasel);
- load_gs(0);
+ load_gs(_udatasel);
pcb->pcb_ds = _udatasel;
pcb->pcb_es = _udatasel;
pcb->pcb_fs = _udatasel;
- pcb->pcb_gs = 0;
+ pcb->pcb_gs = _udatasel;
bzero((char *)regs, sizeof(struct trapframe));
regs->tf_rip = entry;
@@ -843,7 +874,7 @@
*/
if (sigcodesz)
copyout(imgp->proc->p_sysent->sv_sigcode,
- ((caddr_t)arginfo - sigcodesz), szsigcode);
+ ((caddr_t)arginfo - sigcodesz), sigcodesz);
/*
* If we have a valid auxargs ptr, prepare some room
@@ -936,49 +967,42 @@
SYSCTL_ULONG(_compat_linux32, OID_AUTO, maxvmem, CTLFLAG_RW,
&linux32_maxvmem, 0, "");
-/*
- * XXX copied from ia32_sysvec.c.
- */
static void
-linux32_fixlimits(struct image_params *imgp)
+linux32_fixlimit(struct rlimit *rl, int which)
{
- struct proc *p = imgp->proc;
- struct plimit *oldlim, *newlim;
- if (linux32_maxdsiz == 0 && linux32_maxssiz == 0 &&
- linux32_maxvmem == 0)
- return;
- newlim = lim_alloc();
- PROC_LOCK(p);
- oldlim = p->p_limit;
- lim_copy(newlim, oldlim);
- if (linux32_maxdsiz != 0) {
- if (newlim->pl_rlimit[RLIMIT_DATA].rlim_cur > linux32_maxdsiz)
- newlim->pl_rlimit[RLIMIT_DATA].rlim_cur = linux32_maxdsiz;
- if (newlim->pl_rlimit[RLIMIT_DATA].rlim_max > linux32_maxdsiz)
- newlim->pl_rlimit[RLIMIT_DATA].rlim_max = linux32_maxdsiz;
- }
- if (linux32_maxssiz != 0) {
- if (newlim->pl_rlimit[RLIMIT_STACK].rlim_cur > linux32_maxssiz)
- newlim->pl_rlimit[RLIMIT_STACK].rlim_cur = linux32_maxssiz;
- if (newlim->pl_rlimit[RLIMIT_STACK].rlim_max > linux32_maxssiz)
- newlim->pl_rlimit[RLIMIT_STACK].rlim_max = linux32_maxssiz;
- }
- if (linux32_maxvmem != 0) {
- if (newlim->pl_rlimit[RLIMIT_VMEM].rlim_cur > linux32_maxvmem)
- newlim->pl_rlimit[RLIMIT_VMEM].rlim_cur = linux32_maxvmem;
- if (newlim->pl_rlimit[RLIMIT_VMEM].rlim_max > linux32_maxvmem)
- newlim->pl_rlimit[RLIMIT_VMEM].rlim_max = linux32_maxvmem;
+ switch (which) {
+ case RLIMIT_DATA:
+ if (linux32_maxdsiz != 0) {
+ if (rl->rlim_cur > linux32_maxdsiz)
+ rl->rlim_cur = linux32_maxdsiz;
+ if (rl->rlim_max > linux32_maxdsiz)
+ rl->rlim_max = linux32_maxdsiz;
+ }
+ break;
+ case RLIMIT_STACK:
+ if (linux32_maxssiz != 0) {
+ if (rl->rlim_cur > linux32_maxssiz)
+ rl->rlim_cur = linux32_maxssiz;
+ if (rl->rlim_max > linux32_maxssiz)
+ rl->rlim_max = linux32_maxssiz;
+ }
+ break;
+ case RLIMIT_VMEM:
+ if (linux32_maxvmem != 0) {
+ if (rl->rlim_cur > linux32_maxvmem)
+ rl->rlim_cur = linux32_maxvmem;
+ if (rl->rlim_max > linux32_maxvmem)
+ rl->rlim_max = linux32_maxvmem;
+ }
+ break;
}
- p->p_limit = newlim;
- PROC_UNLOCK(p);
- lim_free(oldlim);
}
struct sysentvec elf_linux_sysvec = {
LINUX_SYS_MAXSYSCALL,
linux_sysent,
- 0xff,
+ 0,
LINUX_SIGTBLSZ,
bsd_to_linux_signal,
ELAST + 1,
@@ -1001,7 +1025,8 @@
VM_PROT_ALL,
linux_copyout_strings,
exec_linux_setregs,
- linux32_fixlimits
+ linux32_fixlimit,
+ &linux32_maxssiz,
};
static Elf32_Brandinfo linux_brand = {
@@ -1012,6 +1037,7 @@
"/lib/ld-linux.so.1",
&elf_linux_sysvec,
NULL,
+ BI_CAN_EXEC_DYN,
};
static Elf32_Brandinfo linux_glibc2brand = {
@@ -1022,6 +1048,7 @@
"/lib/ld-linux.so.2",
&elf_linux_sysvec,
NULL,
+ BI_CAN_EXEC_DYN,
};
Elf32_Brandinfo *linux_brandlist[] = {
@@ -1036,6 +1063,7 @@
Elf32_Brandinfo **brandinfo;
int error;
struct linux_ioctl_handler **lihp;
+ struct linux_device_handler **ldhp;
error = 0;
@@ -1048,6 +1076,18 @@
if (error == 0) {
SET_FOREACH(lihp, linux_ioctl_handler_set)
linux_ioctl_register_handler(*lihp);
+ SET_FOREACH(ldhp, linux_device_handler_set)
+ linux_device_register_handler(*ldhp);
+ mtx_init(&emul_lock, "emuldata lock", NULL, MTX_DEF);
+ sx_init(&emul_shared_lock, "emuldata->shared lock");
+ LIST_INIT(&futex_list);
+ sx_init(&futex_sx, "futex protection lock");
+ linux_exit_tag = EVENTHANDLER_REGISTER(process_exit, linux_proc_exit,
+ NULL, 1000);
+ linux_schedtail_tag = EVENTHANDLER_REGISTER(schedtail, linux_schedtail,
+ NULL, 1000);
+ linux_exec_tag = EVENTHANDLER_REGISTER(process_exec, linux_proc_exec,
+ NULL, 1000);
if (bootverbose)
printf("Linux ELF exec handler installed\n");
} else
@@ -1067,13 +1107,21 @@
if (error == 0) {
SET_FOREACH(lihp, linux_ioctl_handler_set)
linux_ioctl_unregister_handler(*lihp);
+ SET_FOREACH(ldhp, linux_device_handler_set)
+ linux_device_unregister_handler(*ldhp);
+ mtx_destroy(&emul_lock);
+ sx_destroy(&emul_shared_lock);
+ sx_destroy(&futex_sx);
+ EVENTHANDLER_DEREGISTER(process_exit, linux_exit_tag);
+ EVENTHANDLER_DEREGISTER(schedtail, linux_schedtail_tag);
+ EVENTHANDLER_DEREGISTER(process_exec, linux_exec_tag);
if (bootverbose)
printf("Linux ELF exec handler removed\n");
} else
printf("Could not deinstall ELF interpreter entry\n");
break;
default:
- break;
+ return EOPNOTSUPP;
}
return error;
}
Index: linux.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/linux32/linux.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/linux32/linux.h -L sys/amd64/linux32/linux.h -u -r1.1.1.1 -r1.2
--- sys/amd64/linux32/linux.h
+++ sys/amd64/linux32/linux.h
@@ -8,7 +8,7 @@
* 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
+ * notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
@@ -27,13 +27,11 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $FreeBSD: src/sys/amd64/linux32/linux.h,v 1.1 2004/08/16 07:55:06 tjr Exp $
+ * $FreeBSD: src/sys/amd64/linux32/linux.h,v 1.16 2007/09/18 19:50:32 dwmalone Exp $
*/
-#ifndef _AMD64_LINUX_LINUX_H_
-#define _AMD64_LINUX_LINUX_H_
-
-#include <sys/signal.h> /* for sigval union */
+#ifndef _AMD64_LINUX_H_
+#define _AMD64_LINUX_H_
#include <amd64/linux32/linux32_syscall.h>
@@ -41,20 +39,20 @@
* debugging support
*/
extern u_char linux_debug_map[];
-#define ldebug(name) isclr(linux_debug_map, LINUX_SYS_linux_ ## name)
-#define ARGS(nm, fmt) "linux(%ld): "#nm"("fmt")\n", (long)td->td_proc->p_pid
-#define LMSG(fmt) "linux(%ld): "fmt"\n", (long)td->td_proc->p_pid
+#define ldebug(name) isclr(linux_debug_map, LINUX_SYS_linux_ ## name)
+#define ARGS(nm, fmt) "linux(%ld): "#nm"("fmt")\n", (long)td->td_proc->p_pid
+#define LMSG(fmt) "linux(%ld): "fmt"\n", (long)td->td_proc->p_pid
#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_LINUX);
#endif
-#define LINUX32_USRSTACK ((1ul << 32) - PAGE_SIZE)
+#define LINUX32_USRSTACK ((1ul << 32) - PAGE_SIZE)
/* XXX 16 = sizeof(linux32_ps_strings) */
-#define LINUX32_PS_STRINGS (LINUX32_USRSTACK - 16)
-#define LINUX32_MAXDSIZ (512*1024*1024) /* 512MB */
-#define LINUX32_MAXSSIZ (64*1024*1024) /* 64MB */
-#define LINUX32_MAXVMEM 0 /* Unlimited */
+#define LINUX32_PS_STRINGS (LINUX32_USRSTACK - 16)
+#define LINUX32_MAXDSIZ (512 * 1024 * 1024) /* 512MB */
+#define LINUX32_MAXSSIZ (64 * 1024 * 1024) /* 64MB */
+#define LINUX32_MAXVMEM 0 /* Unlimited */
#define PTRIN(v) (void *)(uintptr_t)(v)
#define PTROUT(v) (l_uintptr_t)(uintptr_t)(v)
@@ -134,7 +132,7 @@
#define LINUX_RLIMIT_NPROC 6
#define LINUX_RLIMIT_NOFILE 7
#define LINUX_RLIMIT_MEMLOCK 8
-#define LINUX_RLIMIT_AS 9 /* address space limit */
+#define LINUX_RLIMIT_AS 9 /* Address space limit */
#define LINUX_RLIM_NLIMITS 10
@@ -169,12 +167,21 @@
#define LINUX_MAP_ANON 0x0020
#define LINUX_MAP_GROWSDOWN 0x0100
+struct l_mmap_argv {
+ l_uintptr_t addr;
+ l_size_t len;
+ l_int prot;
+ l_int flags;
+ l_int fd;
+ l_off_t pgoff;
+} __packed;
+
/*
* stat family of syscalls
*/
struct l_timespec {
- l_ulong tv_sec;
- l_ulong tv_nsec;
+ l_time_t tv_sec;
+ l_long tv_nsec;
} __packed;
struct l_newstat {
@@ -197,6 +204,24 @@
l_ulong __unused5;
} __packed;
+struct l_stat {
+ l_ushort st_dev;
+ l_ulong st_ino;
+ l_ushort st_mode;
+ l_ushort st_nlink;
+ l_ushort st_uid;
+ l_ushort st_gid;
+ l_ushort st_rdev;
+ l_long st_size;
+ struct l_timespec st_atimespec;
+ struct l_timespec st_mtimespec;
+ struct l_timespec st_ctimespec;
+ l_long st_blksize;
+ l_long st_blocks;
+ l_ulong st_flags;
+ l_ulong st_gen;
+};
+
struct l_stat64 {
l_ushort st_dev;
u_char __pad0[10];
@@ -217,6 +242,19 @@
l_ulonglong st_ino;
} __packed;
+struct l_statfs64 {
+ l_int f_type;
+ l_int f_bsize;
+ uint64_t f_blocks;
+ uint64_t f_bfree;
+ uint64_t f_bavail;
+ uint64_t f_files;
+ uint64_t f_ffree;
+ l_fsid_t f_fsid;
+ l_int f_namelen;
+ l_int f_spare[6];
+} __packed;
+
struct l_new_utsname {
char sysname[LINUX_MAX_UTSNAME];
char nodename[LINUX_MAX_UTSNAME];
@@ -290,9 +328,9 @@
#define LINUX_SIGADDSET(set, sig) SIGADDSET(set, sig)
/* sigaltstack */
-#define LINUX_MINSIGSTKSZ 2048
-#define LINUX_SS_ONSTACK 1
-#define LINUX_SS_DISABLE 2
+#define LINUX_MINSIGSTKSZ 2048
+#define LINUX_SS_ONSTACK 1
+#define LINUX_SS_DISABLE 2
int linux_to_bsd_sigaltstack(int lsa);
int bsd_to_linux_sigaltstack(int bsa);
@@ -355,11 +393,16 @@
l_uintptr_t uc_link;
l_stack_t uc_stack;
struct l_sigcontext uc_mcontext;
- l_sigset_t uc_sigmask;
+ l_sigset_t uc_sigmask;
} __packed;
-#define LINUX_SI_MAX_SIZE 128
-#define LINUX_SI_PAD_SIZE ((LINUX_SI_MAX_SIZE/sizeof(l_int)) - 3)
+#define LINUX_SI_MAX_SIZE 128
+#define LINUX_SI_PAD_SIZE ((LINUX_SI_MAX_SIZE/sizeof(l_int)) - 3)
+
+union l_sigval {
+ l_int sival_int;
+ l_uintptr_t sival_ptr;
+};
typedef struct l_siginfo {
l_int lsi_signo;
@@ -381,7 +424,7 @@
struct {
l_pid_t _pid; /* sender's pid */
l_uid16_t _uid; /* sender's uid */
- union sigval _sigval;
+ union l_sigval _sigval;
} __packed _rt;
struct {
@@ -393,41 +436,41 @@
} __packed _sigchld;
struct {
- l_uintptr_t _addr; /* faulting insn/memory ref. */
+ l_uintptr_t _addr; /* Faulting insn/memory ref. */
} __packed _sigfault;
struct {
- l_int _band; /* POLL_IN,POLL_OUT,POLL_MSG */
+ l_int _band; /* POLL_IN,POLL_OUT,POLL_MSG */
l_int _fd;
} __packed _sigpoll;
} _sifields;
} __packed l_siginfo_t;
-#define lsi_pid _sifields._kill._pid
-#define lsi_uid _sifields._kill._uid
-#define lsi_status _sifields._sigchld._status
-#define lsi_utime _sifields._sigchld._utime
-#define lsi_stime _sifields._sigchld._stime
-#define lsi_value _sifields._rt._sigval
-#define lsi_int _sifields._rt._sigval.sival_int
-#define lsi_ptr _sifields._rt._sigval.sival_ptr
-#define lsi_addr _sifields._sigfault._addr
-#define lsi_band _sifields._sigpoll._band
-#define lsi_fd _sifields._sigpoll._fd
+#define lsi_pid _sifields._kill._pid
+#define lsi_uid _sifields._kill._uid
+#define lsi_status _sifields._sigchld._status
+#define lsi_utime _sifields._sigchld._utime
+#define lsi_stime _sifields._sigchld._stime
+#define lsi_value _sifields._rt._sigval
+#define lsi_int _sifields._rt._sigval.sival_int
+#define lsi_ptr _sifields._rt._sigval.sival_ptr
+#define lsi_addr _sifields._sigfault._addr
+#define lsi_band _sifields._sigpoll._band
+#define lsi_fd _sifields._sigpoll._fd
struct l_fpreg {
- u_int16_t significand[4];
- u_int16_t exponent;
+ u_int16_t significand[4];
+ u_int16_t exponent;
} __packed;
struct l_fpxreg {
- u_int16_t significand[4];
- u_int16_t exponent;
- u_int16_t padding[3];
+ u_int16_t significand[4];
+ u_int16_t exponent;
+ u_int16_t padding[3];
} __packed;
struct l_xmmreg {
- u_int32_t element[4];
+ u_int32_t element[4];
} __packed;
struct l_fpstate {
@@ -441,13 +484,13 @@
u_int32_t datasel;
struct l_fpreg _st[8];
u_int16_t status;
- u_int16_t magic; /* 0xffff = regular FPU data */
+ u_int16_t magic; /* 0xffff = regular FPU data */
/* FXSR FPU environment */
- u_int32_t _fxsr_env[6]; /* env is ignored */
+ u_int32_t _fxsr_env[6]; /* env is ignored. */
u_int32_t mxcsr;
u_int32_t reserved;
- struct l_fpxreg _fxsr_st[8]; /* reg data is ignored */
+ struct l_fpxreg _fxsr_st[8]; /* reg data is ignored. */
struct l_xmmreg _xmm[8];
u_int32_t padding[56];
} __packed;
@@ -477,6 +520,7 @@
extern int bsd_to_linux_signal[];
extern int linux_to_bsd_signal[];
+extern struct sysentvec elf_linux_sysvec;
/*
* Pluggable ioctl handlers
@@ -497,18 +541,24 @@
/*
* open/fcntl flags
*/
-#define LINUX_O_RDONLY 00
-#define LINUX_O_WRONLY 01
-#define LINUX_O_RDWR 02
-#define LINUX_O_CREAT 0100
-#define LINUX_O_EXCL 0200
-#define LINUX_O_NOCTTY 0400
-#define LINUX_O_TRUNC 01000
-#define LINUX_O_APPEND 02000
-#define LINUX_O_NONBLOCK 04000
+#define LINUX_O_RDONLY 00000000
+#define LINUX_O_WRONLY 00000001
+#define LINUX_O_RDWR 00000002
+#define LINUX_O_ACCMODE 00000003
+#define LINUX_O_CREAT 00000100
+#define LINUX_O_EXCL 00000200
+#define LINUX_O_NOCTTY 00000400
+#define LINUX_O_TRUNC 00001000
+#define LINUX_O_APPEND 00002000
+#define LINUX_O_NONBLOCK 00004000
#define LINUX_O_NDELAY LINUX_O_NONBLOCK
-#define LINUX_O_SYNC 010000
-#define LINUX_FASYNC 020000
+#define LINUX_O_SYNC 00010000
+#define LINUX_FASYNC 00020000
+#define LINUX_O_DIRECT 00040000 /* Direct disk access hint */
+#define LINUX_O_LARGEFILE 00100000
+#define LINUX_O_DIRECTORY 00200000 /* Must be a directory */
+#define LINUX_O_NOFOLLOW 00400000 /* Do not follow links */
+#define LINUX_O_NOATIME 01000000
#define LINUX_F_DUPFD 0
#define LINUX_F_GETFD 1
@@ -529,15 +579,17 @@
#define LINUX_F_WRLCK 1
#define LINUX_F_UNLCK 2
+#define LINUX_AT_FDCWD -100
+
/*
* mount flags
*/
-#define LINUX_MS_RDONLY 0x0001
-#define LINUX_MS_NOSUID 0x0002
-#define LINUX_MS_NODEV 0x0004
-#define LINUX_MS_NOEXEC 0x0008
-#define LINUX_MS_REMOUNT 0x0020
-
+#define LINUX_MS_RDONLY 0x0001
+#define LINUX_MS_NOSUID 0x0002
+#define LINUX_MS_NODEV 0x0004
+#define LINUX_MS_NOEXEC 0x0008
+#define LINUX_MS_REMOUNT 0x0020
+
/*
* SystemV IPC defines
*/
@@ -635,6 +687,13 @@
#define LINUX_SO_NO_CHECK 11
#define LINUX_SO_PRIORITY 12
#define LINUX_SO_LINGER 13
+#define LINUX_SO_PEERCRED 17
+#define LINUX_SO_RCVLOWAT 18
+#define LINUX_SO_SNDLOWAT 19
+#define LINUX_SO_RCVTIMEO 20
+#define LINUX_SO_SNDTIMEO 21
+#define LINUX_SO_TIMESTAMP 29
+#define LINUX_SO_ACCEPTCONN 30
#define LINUX_IP_TOS 1
#define LINUX_IP_TTL 2
@@ -684,7 +743,7 @@
} ifr_ifru;
} __packed;
-#define ifr_name ifr_ifrn.ifrn_name /* interface name */
+#define ifr_name ifr_ifrn.ifrn_name /* Interface name */
#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */
struct l_ifconf {
@@ -719,4 +778,108 @@
l_short revents;
} __packed;
-#endif /* !_AMD64_LINUX_LINUX_H_ */
+struct l_user_desc {
+ l_uint entry_number;
+ l_uint base_addr;
+ l_uint limit;
+ l_uint seg_32bit:1;
+ l_uint contents:2;
+ l_uint read_exec_only:1;
+ l_uint limit_in_pages:1;
+ l_uint seg_not_present:1;
+ l_uint useable:1;
+};
+
+#define LINUX_LOWERWORD 0x0000ffff
+
+/*
+ * Macros which does the same thing as those in Linux include/asm-um/ldt-i386.h.
+ * These convert Linux user space descriptor to machine one.
+ */
+#define LINUX_LDT_entry_a(info) \
+ ((((info)->base_addr & LINUX_LOWERWORD) << 16) | \
+ ((info)->limit & LINUX_LOWERWORD))
+
+#define LINUX_ENTRY_B_READ_EXEC_ONLY 9
+#define LINUX_ENTRY_B_CONTENTS 10
+#define LINUX_ENTRY_B_SEG_NOT_PRESENT 15
+#define LINUX_ENTRY_B_BASE_ADDR 16
+#define LINUX_ENTRY_B_USEABLE 20
+#define LINUX_ENTRY_B_SEG32BIT 22
+#define LINUX_ENTRY_B_LIMIT 23
+
+#define LINUX_LDT_entry_b(info) \
+ (((info)->base_addr & 0xff000000) | \
+ ((info)->limit & 0xf0000) | \
+ ((info)->contents << LINUX_ENTRY_B_CONTENTS) | \
+ (((info)->seg_not_present == 0) << LINUX_ENTRY_B_SEG_NOT_PRESENT) | \
+ (((info)->base_addr & 0x00ff0000) >> LINUX_ENTRY_B_BASE_ADDR) | \
+ (((info)->read_exec_only == 0) << LINUX_ENTRY_B_READ_EXEC_ONLY) | \
+ ((info)->seg_32bit << LINUX_ENTRY_B_SEG32BIT) | \
+ ((info)->useable << LINUX_ENTRY_B_USEABLE) | \
+ ((info)->limit_in_pages << LINUX_ENTRY_B_LIMIT) | 0x7000)
+
+#define LINUX_LDT_empty(info) \
+ ((info)->base_addr == 0 && \
+ (info)->limit == 0 && \
+ (info)->contents == 0 && \
+ (info)->seg_not_present == 1 && \
+ (info)->read_exec_only == 1 && \
+ (info)->seg_32bit == 0 && \
+ (info)->limit_in_pages == 0 && \
+ (info)->useable == 0)
+
+/*
+ * Macros for converting segments.
+ * They do the same as those in arch/i386/kernel/process.c in Linux.
+ */
+#define LINUX_GET_BASE(desc) \
+ ((((desc)->a >> 16) & LINUX_LOWERWORD) | \
+ (((desc)->b << 16) & 0x00ff0000) | \
+ ((desc)->b & 0xff000000))
+
+#define LINUX_GET_LIMIT(desc) \
+ (((desc)->a & LINUX_LOWERWORD) | \
+ ((desc)->b & 0xf0000))
+
+#define LINUX_GET_32BIT(desc) \
+ (((desc)->b >> LINUX_ENTRY_B_SEG32BIT) & 1)
+#define LINUX_GET_CONTENTS(desc) \
+ (((desc)->b >> LINUX_ENTRY_B_CONTENTS) & 3)
+#define LINUX_GET_WRITABLE(desc) \
+ (((desc)->b >> LINUX_ENTRY_B_READ_EXEC_ONLY) & 1)
+#define LINUX_GET_LIMIT_PAGES(desc) \
+ (((desc)->b >> LINUX_ENTRY_B_LIMIT) & 1)
+#define LINUX_GET_PRESENT(desc) \
+ (((desc)->b >> LINUX_ENTRY_B_SEG_NOT_PRESENT) & 1)
+#define LINUX_GET_USEABLE(desc) \
+ (((desc)->b >> LINUX_ENTRY_B_USEABLE) & 1)
+
+#define LINUX_CLOCK_REALTIME 0
+#define LINUX_CLOCK_MONOTONIC 1
+#define LINUX_CLOCK_PROCESS_CPUTIME_ID 2
+#define LINUX_CLOCK_THREAD_CPUTIME_ID 3
+#define LINUX_CLOCK_REALTIME_HR 4
+#define LINUX_CLOCK_MONOTONIC_HR 5
+
+typedef int l_timer_t;
+typedef int l_mqd_t;
+
+#define LINUX_CLONE_VM 0x00000100
+#define LINUX_CLONE_FS 0x00000200
+#define LINUX_CLONE_FILES 0x00000400
+#define LINUX_CLONE_SIGHAND 0x00000800
+#define LINUX_CLONE_PID 0x00001000 /* No longer exist in Linux */
+#define LINUX_CLONE_VFORK 0x00004000
+#define LINUX_CLONE_PARENT 0x00008000
+#define LINUX_CLONE_THREAD 0x00010000
+#define LINUX_CLONE_SETTLS 0x00080000
+#define LINUX_CLONE_PARENT_SETTID 0x00100000
+#define LINUX_CLONE_CHILD_CLEARTID 0x00200000
+#define LINUX_CLONE_CHILD_SETTID 0x01000000
+
+#define LINUX_THREADING_FLAGS \
+ (LINUX_CLONE_VM | LINUX_CLONE_FS | LINUX_CLONE_FILES | \
+ LINUX_CLONE_SIGHAND | LINUX_CLONE_THREAD)
+
+#endif /* !_AMD64_LINUX_H_ */
Index: linux32_proto.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/linux32/linux32_proto.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/linux32/linux32_proto.h -L sys/amd64/linux32/linux32_proto.h -u -r1.1.1.1 -r1.2
--- sys/amd64/linux32/linux32_proto.h
+++ sys/amd64/linux32/linux32_proto.h
@@ -2,8 +2,8 @@
* System call prototypes.
*
* DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/amd64/linux32/linux32_proto.h,v 1.5.2.1 2005/07/20 17:43:52 jhb Exp $
- * created from FreeBSD: src/sys/amd64/linux32/syscalls.master,v 1.4.2.1 2005/07/20 17:42:14 jhb Exp
+ * $FreeBSD: src/sys/amd64/linux32/linux32_proto.h,v 1.33 2007/09/18 19:50:32 dwmalone Exp $
+ * created from FreeBSD: src/sys/amd64/linux32/syscalls.master,v 1.29 2007/08/28 12:26:34 kib Exp
*/
#ifndef _LINUX_SYSPROTO_H_
@@ -11,12 +11,11 @@
#include <sys/signal.h>
#include <sys/acl.h>
-#include <sys/thr.h>
-#include <sys/umtx.h>
-#include <posix4/_semaphore.h>
-
+#include <sys/_semaphore.h>
#include <sys/ucontext.h>
+#include <bsm/audit_kevents.h>
+
struct proc;
struct thread;
@@ -82,6 +81,10 @@
char uid_l_[PADL_(l_uid16_t)]; l_uid16_t uid; char uid_r_[PADR_(l_uid16_t)];
char gid_l_[PADL_(l_gid16_t)]; l_gid16_t gid; char gid_r_[PADR_(l_gid16_t)];
};
+struct linux_stat_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char up_l_[PADL_(struct linux_stat *)]; struct linux_stat * up; char up_r_[PADR_(struct linux_stat *)];
+};
struct linux_lseek_args {
char fdes_l_[PADL_(l_uint)]; l_uint fdes; char fdes_r_[PADR_(l_uint)];
char off_l_[PADL_(l_off_t)]; l_off_t off; char off_r_[PADR_(l_off_t)];
@@ -193,6 +196,9 @@
char dev_l_[PADL_(l_dev_t)]; l_dev_t dev; char dev_r_[PADR_(l_dev_t)];
char ubuf_l_[PADL_(struct l_ustat *)]; struct l_ustat * ubuf; char ubuf_r_[PADR_(struct l_ustat *)];
};
+struct linux_getppid_args {
+ register_t dummy;
+};
struct linux_sigaction_args {
char sig_l_[PADL_(l_int)]; l_int sig; char sig_r_[PADR_(l_int)];
char nsa_l_[PADL_(l_osigaction_t *)]; l_osigaction_t * nsa; char nsa_r_[PADR_(l_osigaction_t *)];
@@ -220,6 +226,10 @@
struct linux_sigpending_args {
char mask_l_[PADL_(l_osigset_t *)]; l_osigset_t * mask; char mask_r_[PADR_(l_osigset_t *)];
};
+struct linux_sethostname_args {
+ char hostname_l_[PADL_(char *)]; char * hostname; char hostname_r_[PADR_(char *)];
+ char len_l_[PADL_(u_int)]; u_int len; char len_r_[PADR_(u_int)];
+};
struct linux_setrlimit_args {
char resource_l_[PADL_(l_uint)]; l_uint resource; char resource_r_[PADR_(l_uint)];
char rlim_l_[PADL_(struct l_rlimit *)]; struct l_rlimit * rlim; char rlim_r_[PADR_(struct l_rlimit *)];
@@ -255,6 +265,10 @@
char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
char to_l_[PADL_(char *)]; char * to; char to_r_[PADR_(char *)];
};
+struct linux_lstat_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char up_l_[PADL_(struct linux_lstat *)]; struct linux_lstat * up; char up_r_[PADR_(struct linux_lstat *)];
+};
struct linux_readlink_args {
char name_l_[PADL_(char *)]; char * name; char name_r_[PADR_(char *)];
char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)];
@@ -278,6 +292,10 @@
char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
char length_l_[PADL_(l_ulong)]; l_ulong length; char length_r_[PADR_(l_ulong)];
};
+struct linux_ftruncate_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char length_l_[PADL_(long)]; long length; char length_r_[PADR_(long)];
+};
struct linux_getpriority_args {
char which_l_[PADL_(int)]; int which; char which_r_[PADR_(int)];
char who_l_[PADL_(int)]; int who; char who_r_[PADR_(int)];
@@ -323,6 +341,9 @@
struct linux_uname_args {
register_t dummy;
};
+struct linux_iopl_args {
+ char level_l_[PADL_(l_ulong)]; l_ulong level; char level_r_[PADR_(l_ulong)];
+};
struct linux_vhangup_args {
register_t dummy;
};
@@ -352,6 +373,9 @@
struct linux_clone_args {
char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)];
char stack_l_[PADL_(void *)]; void * stack; char stack_r_[PADR_(void *)];
+ char parent_tidptr_l_[PADL_(void *)]; void * parent_tidptr; char parent_tidptr_r_[PADR_(void *)];
+ char dummy_l_[PADL_(int)]; int dummy; char dummy_r_[PADR_(int)];
+ char child_tidptr_l_[PADL_(void *)]; void * child_tidptr; char child_tidptr_r_[PADR_(void *)];
};
struct linux_newuname_args {
char buf_l_[PADL_(struct l_new_utsname *)]; struct l_new_utsname * buf; char buf_r_[PADR_(struct l_new_utsname *)];
@@ -500,7 +524,11 @@
char sgid_l_[PADL_(l_gid16_t *)]; l_gid16_t * sgid; char sgid_r_[PADR_(l_gid16_t *)];
};
struct linux_prctl_args {
- register_t dummy;
+ char option_l_[PADL_(l_int)]; l_int option; char option_r_[PADR_(l_int)];
+ char arg2_l_[PADL_(l_int)]; l_int arg2; char arg2_r_[PADR_(l_int)];
+ char arg3_l_[PADL_(l_int)]; l_int arg3; char arg3_r_[PADR_(l_int)];
+ char arg4_l_[PADL_(l_int)]; l_int arg4; char arg4_r_[PADR_(l_int)];
+ char arg5_l_[PADL_(l_int)]; l_int arg5; char arg5_r_[PADR_(l_int)];
};
struct linux_rt_sigreturn_args {
char ucp_l_[PADL_(struct l_ucontext *)]; struct l_ucontext * ucp; char ucp_r_[PADR_(struct l_ucontext *)];
@@ -518,10 +546,14 @@
char sigsetsize_l_[PADL_(l_size_t)]; l_size_t sigsetsize; char sigsetsize_r_[PADR_(l_size_t)];
};
struct linux_rt_sigpending_args {
- register_t dummy;
+ char set_l_[PADL_(l_sigset_t *)]; l_sigset_t * set; char set_r_[PADR_(l_sigset_t *)];
+ char sigsetsize_l_[PADL_(l_size_t)]; l_size_t sigsetsize; char sigsetsize_r_[PADR_(l_size_t)];
};
struct linux_rt_sigtimedwait_args {
- register_t dummy;
+ char mask_l_[PADL_(l_sigset_t *)]; l_sigset_t * mask; char mask_r_[PADR_(l_sigset_t *)];
+ char ptr_l_[PADL_(l_siginfo_t *)]; l_siginfo_t * ptr; char ptr_r_[PADR_(l_siginfo_t *)];
+ char timeout_l_[PADL_(struct l_timeval *)]; struct l_timeval * timeout; char timeout_r_[PADR_(struct l_timeval *)];
+ char sigsetsize_l_[PADL_(l_size_t)]; l_size_t sigsetsize; char sigsetsize_r_[PADR_(l_size_t)];
};
struct linux_rt_sigqueueinfo_args {
register_t dummy;
@@ -651,6 +683,9 @@
char cmd_l_[PADL_(l_uint)]; l_uint cmd; char cmd_r_[PADR_(l_uint)];
char arg_l_[PADL_(uintptr_t)]; uintptr_t arg; char arg_r_[PADR_(uintptr_t)];
};
+struct linux_gettid_args {
+ register_t dummy;
+};
struct linux_setxattr_args {
register_t dummy;
};
@@ -687,9 +722,214 @@
struct linux_fremovexattr_args {
register_t dummy;
};
+struct linux_tkill_args {
+ char tid_l_[PADL_(int)]; int tid; char tid_r_[PADR_(int)];
+ char sig_l_[PADL_(int)]; int sig; char sig_r_[PADR_(int)];
+};
+struct linux_sys_futex_args {
+ char uaddr_l_[PADL_(void *)]; void * uaddr; char uaddr_r_[PADR_(void *)];
+ char op_l_[PADL_(int)]; int op; char op_r_[PADR_(int)];
+ char val_l_[PADL_(int)]; int val; char val_r_[PADR_(int)];
+ char timeout_l_[PADL_(struct l_timespec *)]; struct l_timespec * timeout; char timeout_r_[PADR_(struct l_timespec *)];
+ char uaddr2_l_[PADL_(void *)]; void * uaddr2; char uaddr2_r_[PADR_(void *)];
+ char val3_l_[PADL_(int)]; int val3; char val3_r_[PADR_(int)];
+};
+struct linux_sched_getaffinity_args {
+ char pid_l_[PADL_(l_pid_t)]; l_pid_t pid; char pid_r_[PADR_(l_pid_t)];
+ char len_l_[PADL_(l_uint)]; l_uint len; char len_r_[PADR_(l_uint)];
+ char user_mask_ptr_l_[PADL_(l_ulong *)]; l_ulong * user_mask_ptr; char user_mask_ptr_r_[PADR_(l_ulong *)];
+};
+struct linux_set_thread_area_args {
+ char desc_l_[PADL_(struct l_user_desc *)]; struct l_user_desc * desc; char desc_r_[PADR_(struct l_user_desc *)];
+};
struct linux_fadvise64_args {
register_t dummy;
};
+struct linux_exit_group_args {
+ char error_code_l_[PADL_(int)]; int error_code; char error_code_r_[PADR_(int)];
+};
+struct linux_lookup_dcookie_args {
+ register_t dummy;
+};
+struct linux_epoll_create_args {
+ register_t dummy;
+};
+struct linux_epoll_ctl_args {
+ register_t dummy;
+};
+struct linux_epoll_wait_args {
+ register_t dummy;
+};
+struct linux_remap_file_pages_args {
+ register_t dummy;
+};
+struct linux_set_tid_address_args {
+ char tidptr_l_[PADL_(int *)]; int * tidptr; char tidptr_r_[PADR_(int *)];
+};
+struct linux_timer_create_args {
+ register_t dummy;
+};
+struct linux_timer_settime_args {
+ register_t dummy;
+};
+struct linux_timer_gettime_args {
+ register_t dummy;
+};
+struct linux_timer_getoverrun_args {
+ register_t dummy;
+};
+struct linux_timer_delete_args {
+ register_t dummy;
+};
+struct linux_clock_settime_args {
+ char which_l_[PADL_(clockid_t)]; clockid_t which; char which_r_[PADR_(clockid_t)];
+ char tp_l_[PADL_(struct l_timespec *)]; struct l_timespec * tp; char tp_r_[PADR_(struct l_timespec *)];
+};
+struct linux_clock_gettime_args {
+ char which_l_[PADL_(clockid_t)]; clockid_t which; char which_r_[PADR_(clockid_t)];
+ char tp_l_[PADL_(struct l_timespec *)]; struct l_timespec * tp; char tp_r_[PADR_(struct l_timespec *)];
+};
+struct linux_clock_getres_args {
+ char which_l_[PADL_(clockid_t)]; clockid_t which; char which_r_[PADR_(clockid_t)];
+ char tp_l_[PADL_(struct l_timespec *)]; struct l_timespec * tp; char tp_r_[PADR_(struct l_timespec *)];
+};
+struct linux_clock_nanosleep_args {
+ char which_l_[PADL_(clockid_t)]; clockid_t which; char which_r_[PADR_(clockid_t)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+ char rqtp_l_[PADL_(struct l_timespec *)]; struct l_timespec * rqtp; char rqtp_r_[PADR_(struct l_timespec *)];
+ char rmtp_l_[PADL_(struct l_timespec *)]; struct l_timespec * rmtp; char rmtp_r_[PADR_(struct l_timespec *)];
+};
+struct linux_statfs64_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char bufsize_l_[PADL_(size_t)]; size_t bufsize; char bufsize_r_[PADR_(size_t)];
+ char buf_l_[PADL_(struct l_statfs64_buf *)]; struct l_statfs64_buf * buf; char buf_r_[PADR_(struct l_statfs64_buf *)];
+};
+struct linux_fstatfs64_args {
+ register_t dummy;
+};
+struct linux_tgkill_args {
+ char tgid_l_[PADL_(int)]; int tgid; char tgid_r_[PADR_(int)];
+ char pid_l_[PADL_(int)]; int pid; char pid_r_[PADR_(int)];
+ char sig_l_[PADL_(int)]; int sig; char sig_r_[PADR_(int)];
+};
+struct linux_utimes_args {
+ char fname_l_[PADL_(char *)]; char * fname; char fname_r_[PADR_(char *)];
+ char tptr_l_[PADL_(struct l_timeval *)]; struct l_timeval * tptr; char tptr_r_[PADR_(struct l_timeval *)];
+};
+struct linux_fadvise64_64_args {
+ register_t dummy;
+};
+struct linux_mbind_args {
+ register_t dummy;
+};
+struct linux_get_mempolicy_args {
+ register_t dummy;
+};
+struct linux_set_mempolicy_args {
+ register_t dummy;
+};
+struct linux_mq_open_args {
+ register_t dummy;
+};
+struct linux_mq_unlink_args {
+ register_t dummy;
+};
+struct linux_mq_timedsend_args {
+ register_t dummy;
+};
+struct linux_mq_timedreceive_args {
+ register_t dummy;
+};
+struct linux_mq_notify_args {
+ register_t dummy;
+};
+struct linux_mq_getsetattr_args {
+ register_t dummy;
+};
+struct linux_kexec_load_args {
+ register_t dummy;
+};
+struct linux_waitid_args {
+ register_t dummy;
+};
+struct linux_add_key_args {
+ register_t dummy;
+};
+struct linux_request_key_args {
+ register_t dummy;
+};
+struct linux_keyctl_args {
+ register_t dummy;
+};
+struct linux_ioprio_set_args {
+ register_t dummy;
+};
+struct linux_ioprio_get_args {
+ register_t dummy;
+};
+struct linux_inotify_init_args {
+ register_t dummy;
+};
+struct linux_inotify_add_watch_args {
+ register_t dummy;
+};
+struct linux_inotify_rm_watch_args {
+ register_t dummy;
+};
+struct linux_migrate_pages_args {
+ register_t dummy;
+};
+struct linux_openat_args {
+ char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)];
+ char filename_l_[PADL_(char *)]; char * filename; char filename_r_[PADR_(char *)];
+ char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)];
+ char mode_l_[PADL_(l_int)]; l_int mode; char mode_r_[PADR_(l_int)];
+};
+struct linux_mkdirat_args {
+ register_t dummy;
+};
+struct linux_mknodat_args {
+ register_t dummy;
+};
+struct linux_fchownat_args {
+ register_t dummy;
+};
+struct linux_futimesat_args {
+ register_t dummy;
+};
+struct linux_fstatat64_args {
+ register_t dummy;
+};
+struct linux_unlinkat_args {
+ register_t dummy;
+};
+struct linux_renameat_args {
+ register_t dummy;
+};
+struct linux_linkat_args {
+ register_t dummy;
+};
+struct linux_symlinkat_args {
+ register_t dummy;
+};
+struct linux_readlinkat_args {
+ register_t dummy;
+};
+struct linux_fchmodat_args {
+ register_t dummy;
+};
+struct linux_faccessat_args {
+ register_t dummy;
+};
+struct linux_pselect6_args {
+ register_t dummy;
+};
+struct linux_ppoll_args {
+ register_t dummy;
+};
+struct linux_unshare_args {
+ register_t dummy;
+};
#define nosys linux_nosys
int linux_fork(struct thread *, struct linux_fork_args *);
int linux_open(struct thread *, struct linux_open_args *);
@@ -703,6 +943,7 @@
int linux_mknod(struct thread *, struct linux_mknod_args *);
int linux_chmod(struct thread *, struct linux_chmod_args *);
int linux_lchown16(struct thread *, struct linux_lchown16_args *);
+int linux_stat(struct thread *, struct linux_stat_args *);
int linux_lseek(struct thread *, struct linux_lseek_args *);
int linux_getpid(struct thread *, struct linux_getpid_args *);
int linux_mount(struct thread *, struct linux_mount_args *);
@@ -733,6 +974,7 @@
int linux_fcntl(struct thread *, struct linux_fcntl_args *);
int linux_olduname(struct thread *, struct linux_olduname_args *);
int linux_ustat(struct thread *, struct linux_ustat_args *);
+int linux_getppid(struct thread *, struct linux_getppid_args *);
int linux_sigaction(struct thread *, struct linux_sigaction_args *);
int linux_sgetmask(struct thread *, struct linux_sgetmask_args *);
int linux_ssetmask(struct thread *, struct linux_ssetmask_args *);
@@ -740,6 +982,7 @@
int linux_setregid16(struct thread *, struct linux_setregid16_args *);
int linux_sigsuspend(struct thread *, struct linux_sigsuspend_args *);
int linux_sigpending(struct thread *, struct linux_sigpending_args *);
+int linux_sethostname(struct thread *, struct linux_sethostname_args *);
int linux_setrlimit(struct thread *, struct linux_setrlimit_args *);
int linux_old_getrlimit(struct thread *, struct linux_old_getrlimit_args *);
int linux_getrusage(struct thread *, struct linux_getrusage_args *);
@@ -749,11 +992,13 @@
int linux_setgroups16(struct thread *, struct linux_setgroups16_args *);
int linux_old_select(struct thread *, struct linux_old_select_args *);
int linux_symlink(struct thread *, struct linux_symlink_args *);
+int linux_lstat(struct thread *, struct linux_lstat_args *);
int linux_readlink(struct thread *, struct linux_readlink_args *);
int linux_reboot(struct thread *, struct linux_reboot_args *);
int linux_readdir(struct thread *, struct linux_readdir_args *);
int linux_mmap(struct thread *, struct linux_mmap_args *);
int linux_truncate(struct thread *, struct linux_truncate_args *);
+int linux_ftruncate(struct thread *, struct linux_ftruncate_args *);
int linux_getpriority(struct thread *, struct linux_getpriority_args *);
int linux_statfs(struct thread *, struct linux_statfs_args *);
int linux_fstatfs(struct thread *, struct linux_fstatfs_args *);
@@ -765,6 +1010,7 @@
int linux_newlstat(struct thread *, struct linux_newlstat_args *);
int linux_newfstat(struct thread *, struct linux_newfstat_args *);
int linux_uname(struct thread *, struct linux_uname_args *);
+int linux_iopl(struct thread *, struct linux_iopl_args *);
int linux_vhangup(struct thread *, struct linux_vhangup_args *);
int linux_wait4(struct thread *, struct linux_wait4_args *);
int linux_swapoff(struct thread *, struct linux_swapoff_args *);
@@ -844,6 +1090,7 @@
int linux_mincore(struct thread *, struct linux_mincore_args *);
int linux_getdents64(struct thread *, struct linux_getdents64_args *);
int linux_fcntl64(struct thread *, struct linux_fcntl64_args *);
+int linux_gettid(struct thread *, struct linux_gettid_args *);
int linux_setxattr(struct thread *, struct linux_setxattr_args *);
int linux_lsetxattr(struct thread *, struct linux_lsetxattr_args *);
int linux_fsetxattr(struct thread *, struct linux_fsetxattr_args *);
@@ -856,7 +1103,68 @@
int linux_removexattr(struct thread *, struct linux_removexattr_args *);
int linux_lremovexattr(struct thread *, struct linux_lremovexattr_args *);
int linux_fremovexattr(struct thread *, struct linux_fremovexattr_args *);
+int linux_tkill(struct thread *, struct linux_tkill_args *);
+int linux_sys_futex(struct thread *, struct linux_sys_futex_args *);
+int linux_sched_getaffinity(struct thread *, struct linux_sched_getaffinity_args *);
+int linux_set_thread_area(struct thread *, struct linux_set_thread_area_args *);
int linux_fadvise64(struct thread *, struct linux_fadvise64_args *);
+int linux_exit_group(struct thread *, struct linux_exit_group_args *);
+int linux_lookup_dcookie(struct thread *, struct linux_lookup_dcookie_args *);
+int linux_epoll_create(struct thread *, struct linux_epoll_create_args *);
+int linux_epoll_ctl(struct thread *, struct linux_epoll_ctl_args *);
+int linux_epoll_wait(struct thread *, struct linux_epoll_wait_args *);
+int linux_remap_file_pages(struct thread *, struct linux_remap_file_pages_args *);
+int linux_set_tid_address(struct thread *, struct linux_set_tid_address_args *);
+int linux_timer_create(struct thread *, struct linux_timer_create_args *);
+int linux_timer_settime(struct thread *, struct linux_timer_settime_args *);
+int linux_timer_gettime(struct thread *, struct linux_timer_gettime_args *);
+int linux_timer_getoverrun(struct thread *, struct linux_timer_getoverrun_args *);
+int linux_timer_delete(struct thread *, struct linux_timer_delete_args *);
+int linux_clock_settime(struct thread *, struct linux_clock_settime_args *);
+int linux_clock_gettime(struct thread *, struct linux_clock_gettime_args *);
+int linux_clock_getres(struct thread *, struct linux_clock_getres_args *);
+int linux_clock_nanosleep(struct thread *, struct linux_clock_nanosleep_args *);
+int linux_statfs64(struct thread *, struct linux_statfs64_args *);
+int linux_fstatfs64(struct thread *, struct linux_fstatfs64_args *);
+int linux_tgkill(struct thread *, struct linux_tgkill_args *);
+int linux_utimes(struct thread *, struct linux_utimes_args *);
+int linux_fadvise64_64(struct thread *, struct linux_fadvise64_64_args *);
+int linux_mbind(struct thread *, struct linux_mbind_args *);
+int linux_get_mempolicy(struct thread *, struct linux_get_mempolicy_args *);
+int linux_set_mempolicy(struct thread *, struct linux_set_mempolicy_args *);
+int linux_mq_open(struct thread *, struct linux_mq_open_args *);
+int linux_mq_unlink(struct thread *, struct linux_mq_unlink_args *);
+int linux_mq_timedsend(struct thread *, struct linux_mq_timedsend_args *);
+int linux_mq_timedreceive(struct thread *, struct linux_mq_timedreceive_args *);
+int linux_mq_notify(struct thread *, struct linux_mq_notify_args *);
+int linux_mq_getsetattr(struct thread *, struct linux_mq_getsetattr_args *);
+int linux_kexec_load(struct thread *, struct linux_kexec_load_args *);
+int linux_waitid(struct thread *, struct linux_waitid_args *);
+int linux_add_key(struct thread *, struct linux_add_key_args *);
+int linux_request_key(struct thread *, struct linux_request_key_args *);
+int linux_keyctl(struct thread *, struct linux_keyctl_args *);
+int linux_ioprio_set(struct thread *, struct linux_ioprio_set_args *);
+int linux_ioprio_get(struct thread *, struct linux_ioprio_get_args *);
+int linux_inotify_init(struct thread *, struct linux_inotify_init_args *);
+int linux_inotify_add_watch(struct thread *, struct linux_inotify_add_watch_args *);
+int linux_inotify_rm_watch(struct thread *, struct linux_inotify_rm_watch_args *);
+int linux_migrate_pages(struct thread *, struct linux_migrate_pages_args *);
+int linux_openat(struct thread *, struct linux_openat_args *);
+int linux_mkdirat(struct thread *, struct linux_mkdirat_args *);
+int linux_mknodat(struct thread *, struct linux_mknodat_args *);
+int linux_fchownat(struct thread *, struct linux_fchownat_args *);
+int linux_futimesat(struct thread *, struct linux_futimesat_args *);
+int linux_fstatat64(struct thread *, struct linux_fstatat64_args *);
+int linux_unlinkat(struct thread *, struct linux_unlinkat_args *);
+int linux_renameat(struct thread *, struct linux_renameat_args *);
+int linux_linkat(struct thread *, struct linux_linkat_args *);
+int linux_symlinkat(struct thread *, struct linux_symlinkat_args *);
+int linux_readlinkat(struct thread *, struct linux_readlinkat_args *);
+int linux_fchmodat(struct thread *, struct linux_fchmodat_args *);
+int linux_faccessat(struct thread *, struct linux_faccessat_args *);
+int linux_pselect6(struct thread *, struct linux_pselect6_args *);
+int linux_ppoll(struct thread *, struct linux_ppoll_args *);
+int linux_unshare(struct thread *, struct linux_unshare_args *);
#ifdef COMPAT_43
@@ -871,6 +1179,248 @@
#endif /* COMPAT_FREEBSD4 */
+
+#ifdef COMPAT_FREEBSD6
+
+#define nosys linux_nosys
+
+#endif /* COMPAT_FREEBSD6 */
+
+#define LINUX_SYS_AUE_linux_fork AUE_FORK
+#define LINUX_SYS_AUE_linux_open AUE_OPEN_RWTC
+#define LINUX_SYS_AUE_linux_waitpid AUE_WAIT4
+#define LINUX_SYS_AUE_linux_creat AUE_CREAT
+#define LINUX_SYS_AUE_linux_link AUE_LINK
+#define LINUX_SYS_AUE_linux_unlink AUE_UNLINK
+#define LINUX_SYS_AUE_linux_execve AUE_EXECVE
+#define LINUX_SYS_AUE_linux_chdir AUE_CHDIR
+#define LINUX_SYS_AUE_linux_time AUE_NULL
+#define LINUX_SYS_AUE_linux_mknod AUE_MKNOD
+#define LINUX_SYS_AUE_linux_chmod AUE_CHMOD
+#define LINUX_SYS_AUE_linux_lchown16 AUE_LCHOWN
+#define LINUX_SYS_AUE_linux_stat AUE_STAT
+#define LINUX_SYS_AUE_linux_lseek AUE_LSEEK
+#define LINUX_SYS_AUE_linux_getpid AUE_GETPID
+#define LINUX_SYS_AUE_linux_mount AUE_MOUNT
+#define LINUX_SYS_AUE_linux_oldumount AUE_UMOUNT
+#define LINUX_SYS_AUE_linux_setuid16 AUE_SETUID
+#define LINUX_SYS_AUE_linux_getuid16 AUE_GETUID
+#define LINUX_SYS_AUE_linux_stime AUE_SETTIMEOFDAY
+#define LINUX_SYS_AUE_linux_ptrace AUE_PTRACE
+#define LINUX_SYS_AUE_linux_alarm AUE_NULL
+#define LINUX_SYS_AUE_linux_pause AUE_NULL
+#define LINUX_SYS_AUE_linux_utime AUE_UTIME
+#define LINUX_SYS_AUE_linux_access AUE_ACCESS
+#define LINUX_SYS_AUE_linux_nice AUE_NICE
+#define LINUX_SYS_AUE_linux_kill AUE_KILL
+#define LINUX_SYS_AUE_linux_rename AUE_RENAME
+#define LINUX_SYS_AUE_linux_mkdir AUE_MKDIR
+#define LINUX_SYS_AUE_linux_rmdir AUE_RMDIR
+#define LINUX_SYS_AUE_linux_pipe AUE_PIPE
+#define LINUX_SYS_AUE_linux_times AUE_NULL
+#define LINUX_SYS_AUE_linux_brk AUE_NULL
+#define LINUX_SYS_AUE_linux_setgid16 AUE_SETGID
+#define LINUX_SYS_AUE_linux_getgid16 AUE_GETGID
+#define LINUX_SYS_AUE_linux_signal AUE_NULL
+#define LINUX_SYS_AUE_linux_geteuid16 AUE_GETEUID
+#define LINUX_SYS_AUE_linux_getegid16 AUE_GETEGID
+#define LINUX_SYS_AUE_linux_umount AUE_UMOUNT
+#define LINUX_SYS_AUE_linux_ioctl AUE_IOCTL
+#define LINUX_SYS_AUE_linux_fcntl AUE_FCNTL
+#define LINUX_SYS_AUE_linux_olduname AUE_NULL
+#define LINUX_SYS_AUE_linux_ustat AUE_NULL
+#define LINUX_SYS_AUE_linux_getppid AUE_GETPPID
+#define LINUX_SYS_AUE_linux_sigaction AUE_NULL
+#define LINUX_SYS_AUE_linux_sgetmask AUE_NULL
+#define LINUX_SYS_AUE_linux_ssetmask AUE_NULL
+#define LINUX_SYS_AUE_linux_setreuid16 AUE_SETREUID
+#define LINUX_SYS_AUE_linux_setregid16 AUE_SETREGID
+#define LINUX_SYS_AUE_linux_sigsuspend AUE_NULL
+#define LINUX_SYS_AUE_linux_sigpending AUE_NULL
+#define LINUX_SYS_AUE_linux_sethostname AUE_SYSCTL
+#define LINUX_SYS_AUE_linux_setrlimit AUE_SETRLIMIT
+#define LINUX_SYS_AUE_linux_old_getrlimit AUE_GETRLIMIT
+#define LINUX_SYS_AUE_linux_getrusage AUE_GETRUSAGE
+#define LINUX_SYS_AUE_linux_gettimeofday AUE_NULL
+#define LINUX_SYS_AUE_linux_settimeofday AUE_SETTIMEOFDAY
+#define LINUX_SYS_AUE_linux_getgroups16 AUE_GETGROUPS
+#define LINUX_SYS_AUE_linux_setgroups16 AUE_SETGROUPS
+#define LINUX_SYS_AUE_linux_old_select AUE_SELECT
+#define LINUX_SYS_AUE_linux_symlink AUE_SYMLINK
+#define LINUX_SYS_AUE_linux_lstat AUE_LSTAT
+#define LINUX_SYS_AUE_linux_readlink AUE_READLINK
+#define LINUX_SYS_AUE_linux_reboot AUE_REBOOT
+#define LINUX_SYS_AUE_linux_readdir AUE_GETDIRENTRIES
+#define LINUX_SYS_AUE_linux_mmap AUE_MMAP
+#define LINUX_SYS_AUE_linux_truncate AUE_TRUNCATE
+#define LINUX_SYS_AUE_linux_ftruncate AUE_FTRUNCATE
+#define LINUX_SYS_AUE_linux_getpriority AUE_GETPRIORITY
+#define LINUX_SYS_AUE_linux_statfs AUE_STATFS
+#define LINUX_SYS_AUE_linux_fstatfs AUE_FSTATFS
+#define LINUX_SYS_AUE_linux_socketcall AUE_NULL
+#define LINUX_SYS_AUE_linux_syslog AUE_NULL
+#define LINUX_SYS_AUE_linux_setitimer AUE_SETITIMER
+#define LINUX_SYS_AUE_linux_getitimer AUE_GETITIMER
+#define LINUX_SYS_AUE_linux_newstat AUE_STAT
+#define LINUX_SYS_AUE_linux_newlstat AUE_LSTAT
+#define LINUX_SYS_AUE_linux_newfstat AUE_FSTAT
+#define LINUX_SYS_AUE_linux_uname AUE_NULL
+#define LINUX_SYS_AUE_linux_iopl AUE_NULL
+#define LINUX_SYS_AUE_linux_vhangup AUE_NULL
+#define LINUX_SYS_AUE_linux_wait4 AUE_WAIT4
+#define LINUX_SYS_AUE_linux_swapoff AUE_SWAPOFF
+#define LINUX_SYS_AUE_linux_sysinfo AUE_NULL
+#define LINUX_SYS_AUE_linux_ipc AUE_NULL
+#define LINUX_SYS_AUE_linux_sigreturn AUE_SIGRETURN
+#define LINUX_SYS_AUE_linux_clone AUE_RFORK
+#define LINUX_SYS_AUE_linux_newuname AUE_NULL
+#define LINUX_SYS_AUE_linux_adjtimex AUE_ADJTIME
+#define LINUX_SYS_AUE_linux_mprotect AUE_MPROTECT
+#define LINUX_SYS_AUE_linux_sigprocmask AUE_SIGPROCMASK
+#define LINUX_SYS_AUE_linux_create_module AUE_NULL
+#define LINUX_SYS_AUE_linux_init_module AUE_NULL
+#define LINUX_SYS_AUE_linux_delete_module AUE_NULL
+#define LINUX_SYS_AUE_linux_get_kernel_syms AUE_NULL
+#define LINUX_SYS_AUE_linux_quotactl AUE_QUOTACTL
+#define LINUX_SYS_AUE_linux_bdflush AUE_BDFLUSH
+#define LINUX_SYS_AUE_linux_sysfs AUE_NULL
+#define LINUX_SYS_AUE_linux_personality AUE_PERSONALITY
+#define LINUX_SYS_AUE_linux_setfsuid16 AUE_SETFSUID
+#define LINUX_SYS_AUE_linux_setfsgid16 AUE_SETFSGID
+#define LINUX_SYS_AUE_linux_llseek AUE_LSEEK
+#define LINUX_SYS_AUE_linux_getdents AUE_GETDIRENTRIES
+#define LINUX_SYS_AUE_linux_select AUE_SELECT
+#define LINUX_SYS_AUE_linux_msync AUE_MSYNC
+#define LINUX_SYS_AUE_linux_readv AUE_READV
+#define LINUX_SYS_AUE_linux_writev AUE_WRITEV
+#define LINUX_SYS_AUE_linux_getsid AUE_GETSID
+#define LINUX_SYS_AUE_linux_fdatasync AUE_NULL
+#define LINUX_SYS_AUE_linux_sysctl AUE_SYSCTL
+#define LINUX_SYS_AUE_linux_sched_setscheduler AUE_SCHED_SETSCHEDULER
+#define LINUX_SYS_AUE_linux_sched_getscheduler AUE_SCHED_GETSCHEDULER
+#define LINUX_SYS_AUE_linux_sched_get_priority_max AUE_SCHED_GET_PRIORITY_MAX
+#define LINUX_SYS_AUE_linux_sched_get_priority_min AUE_SCHED_GET_PRIORITY_MIN
+#define LINUX_SYS_AUE_linux_sched_rr_get_interval AUE_SCHED_RR_GET_INTERVAL
+#define LINUX_SYS_AUE_linux_nanosleep AUE_NULL
+#define LINUX_SYS_AUE_linux_mremap AUE_NULL
+#define LINUX_SYS_AUE_linux_setresuid16 AUE_SETRESUID
+#define LINUX_SYS_AUE_linux_getresuid16 AUE_GETRESUID
+#define LINUX_SYS_AUE_linux_query_module AUE_NULL
+#define LINUX_SYS_AUE_linux_nfsservctl AUE_NULL
+#define LINUX_SYS_AUE_linux_setresgid16 AUE_SETRESGID
+#define LINUX_SYS_AUE_linux_getresgid16 AUE_GETRESGID
+#define LINUX_SYS_AUE_linux_prctl AUE_PRCTL
+#define LINUX_SYS_AUE_linux_rt_sigreturn AUE_NULL
+#define LINUX_SYS_AUE_linux_rt_sigaction AUE_NULL
+#define LINUX_SYS_AUE_linux_rt_sigprocmask AUE_NULL
+#define LINUX_SYS_AUE_linux_rt_sigpending AUE_NULL
+#define LINUX_SYS_AUE_linux_rt_sigtimedwait AUE_NULL
+#define LINUX_SYS_AUE_linux_rt_sigqueueinfo AUE_NULL
+#define LINUX_SYS_AUE_linux_rt_sigsuspend AUE_NULL
+#define LINUX_SYS_AUE_linux_pread AUE_PREAD
+#define LINUX_SYS_AUE_linux_pwrite AUE_PWRITE
+#define LINUX_SYS_AUE_linux_chown16 AUE_CHOWN
+#define LINUX_SYS_AUE_linux_getcwd AUE_GETCWD
+#define LINUX_SYS_AUE_linux_capget AUE_CAPGET
+#define LINUX_SYS_AUE_linux_capset AUE_CAPSET
+#define LINUX_SYS_AUE_linux_sigaltstack AUE_NULL
+#define LINUX_SYS_AUE_linux_sendfile AUE_SENDFILE
+#define LINUX_SYS_AUE_linux_vfork AUE_VFORK
+#define LINUX_SYS_AUE_linux_getrlimit AUE_GETRLIMIT
+#define LINUX_SYS_AUE_linux_mmap2 AUE_MMAP
+#define LINUX_SYS_AUE_linux_truncate64 AUE_TRUNCATE
+#define LINUX_SYS_AUE_linux_ftruncate64 AUE_FTRUNCATE
+#define LINUX_SYS_AUE_linux_stat64 AUE_STAT
+#define LINUX_SYS_AUE_linux_lstat64 AUE_LSTAT
+#define LINUX_SYS_AUE_linux_fstat64 AUE_FSTAT
+#define LINUX_SYS_AUE_linux_lchown AUE_LCHOWN
+#define LINUX_SYS_AUE_linux_getuid AUE_GETUID
+#define LINUX_SYS_AUE_linux_getgid AUE_GETGID
+#define LINUX_SYS_AUE_linux_getgroups AUE_GETGROUPS
+#define LINUX_SYS_AUE_linux_setgroups AUE_SETGROUPS
+#define LINUX_SYS_AUE_linux_chown AUE_CHOWN
+#define LINUX_SYS_AUE_linux_setfsuid AUE_SETFSUID
+#define LINUX_SYS_AUE_linux_setfsgid AUE_SETFSGID
+#define LINUX_SYS_AUE_linux_pivot_root AUE_PIVOT_ROOT
+#define LINUX_SYS_AUE_linux_mincore AUE_MINCORE
+#define LINUX_SYS_AUE_linux_getdents64 AUE_GETDIRENTRIES
+#define LINUX_SYS_AUE_linux_fcntl64 AUE_FCNTL
+#define LINUX_SYS_AUE_linux_gettid AUE_NULL
+#define LINUX_SYS_AUE_linux_setxattr AUE_NULL
+#define LINUX_SYS_AUE_linux_lsetxattr AUE_NULL
+#define LINUX_SYS_AUE_linux_fsetxattr AUE_NULL
+#define LINUX_SYS_AUE_linux_getxattr AUE_NULL
+#define LINUX_SYS_AUE_linux_lgetxattr AUE_NULL
+#define LINUX_SYS_AUE_linux_fgetxattr AUE_NULL
+#define LINUX_SYS_AUE_linux_listxattr AUE_NULL
+#define LINUX_SYS_AUE_linux_llistxattr AUE_NULL
+#define LINUX_SYS_AUE_linux_flistxattr AUE_NULL
+#define LINUX_SYS_AUE_linux_removexattr AUE_NULL
+#define LINUX_SYS_AUE_linux_lremovexattr AUE_NULL
+#define LINUX_SYS_AUE_linux_fremovexattr AUE_NULL
+#define LINUX_SYS_AUE_linux_tkill AUE_NULL
+#define LINUX_SYS_AUE_linux_sys_futex AUE_NULL
+#define LINUX_SYS_AUE_linux_sched_getaffinity AUE_NULL
+#define LINUX_SYS_AUE_linux_set_thread_area AUE_NULL
+#define LINUX_SYS_AUE_linux_fadvise64 AUE_NULL
+#define LINUX_SYS_AUE_linux_exit_group AUE_EXIT
+#define LINUX_SYS_AUE_linux_lookup_dcookie AUE_NULL
+#define LINUX_SYS_AUE_linux_epoll_create AUE_NULL
+#define LINUX_SYS_AUE_linux_epoll_ctl AUE_NULL
+#define LINUX_SYS_AUE_linux_epoll_wait AUE_NULL
+#define LINUX_SYS_AUE_linux_remap_file_pages AUE_NULL
+#define LINUX_SYS_AUE_linux_set_tid_address AUE_NULL
+#define LINUX_SYS_AUE_linux_timer_create AUE_NULL
+#define LINUX_SYS_AUE_linux_timer_settime AUE_NULL
+#define LINUX_SYS_AUE_linux_timer_gettime AUE_NULL
+#define LINUX_SYS_AUE_linux_timer_getoverrun AUE_NULL
+#define LINUX_SYS_AUE_linux_timer_delete AUE_NULL
+#define LINUX_SYS_AUE_linux_clock_settime AUE_CLOCK_SETTIME
+#define LINUX_SYS_AUE_linux_clock_gettime AUE_NULL
+#define LINUX_SYS_AUE_linux_clock_getres AUE_NULL
+#define LINUX_SYS_AUE_linux_clock_nanosleep AUE_NULL
+#define LINUX_SYS_AUE_linux_statfs64 AUE_STATFS
+#define LINUX_SYS_AUE_linux_fstatfs64 AUE_FSTATFS
+#define LINUX_SYS_AUE_linux_tgkill AUE_NULL
+#define LINUX_SYS_AUE_linux_utimes AUE_UTIMES
+#define LINUX_SYS_AUE_linux_fadvise64_64 AUE_NULL
+#define LINUX_SYS_AUE_linux_mbind AUE_NULL
+#define LINUX_SYS_AUE_linux_get_mempolicy AUE_NULL
+#define LINUX_SYS_AUE_linux_set_mempolicy AUE_NULL
+#define LINUX_SYS_AUE_linux_mq_open AUE_NULL
+#define LINUX_SYS_AUE_linux_mq_unlink AUE_NULL
+#define LINUX_SYS_AUE_linux_mq_timedsend AUE_NULL
+#define LINUX_SYS_AUE_linux_mq_timedreceive AUE_NULL
+#define LINUX_SYS_AUE_linux_mq_notify AUE_NULL
+#define LINUX_SYS_AUE_linux_mq_getsetattr AUE_NULL
+#define LINUX_SYS_AUE_linux_kexec_load AUE_NULL
+#define LINUX_SYS_AUE_linux_waitid AUE_NULL
+#define LINUX_SYS_AUE_linux_add_key AUE_NULL
+#define LINUX_SYS_AUE_linux_request_key AUE_NULL
+#define LINUX_SYS_AUE_linux_keyctl AUE_NULL
+#define LINUX_SYS_AUE_linux_ioprio_set AUE_NULL
+#define LINUX_SYS_AUE_linux_ioprio_get AUE_NULL
+#define LINUX_SYS_AUE_linux_inotify_init AUE_NULL
+#define LINUX_SYS_AUE_linux_inotify_add_watch AUE_NULL
+#define LINUX_SYS_AUE_linux_inotify_rm_watch AUE_NULL
+#define LINUX_SYS_AUE_linux_migrate_pages AUE_NULL
+#define LINUX_SYS_AUE_linux_openat AUE_OPEN_RWTC
+#define LINUX_SYS_AUE_linux_mkdirat AUE_NULL
+#define LINUX_SYS_AUE_linux_mknodat AUE_NULL
+#define LINUX_SYS_AUE_linux_fchownat AUE_NULL
+#define LINUX_SYS_AUE_linux_futimesat AUE_NULL
+#define LINUX_SYS_AUE_linux_fstatat64 AUE_NULL
+#define LINUX_SYS_AUE_linux_unlinkat AUE_NULL
+#define LINUX_SYS_AUE_linux_renameat AUE_NULL
+#define LINUX_SYS_AUE_linux_linkat AUE_NULL
+#define LINUX_SYS_AUE_linux_symlinkat AUE_NULL
+#define LINUX_SYS_AUE_linux_readlinkat AUE_NULL
+#define LINUX_SYS_AUE_linux_fchmodat AUE_NULL
+#define LINUX_SYS_AUE_linux_faccessat AUE_NULL
+#define LINUX_SYS_AUE_linux_pselect6 AUE_NULL
+#define LINUX_SYS_AUE_linux_ppoll AUE_NULL
+#define LINUX_SYS_AUE_linux_unshare AUE_NULL
+
#undef PAD_
#undef PADL_
#undef PADR_
Index: Makefile
===================================================================
RCS file: /home/cvs/src/sys/amd64/Makefile,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/Makefile -L sys/amd64/Makefile -u -r1.1.1.1 -r1.2
--- sys/amd64/Makefile
+++ sys/amd64/Makefile
@@ -1,3 +1,4 @@
+# $MidnightBSD$
# $FreeBSD: src/sys/amd64/Makefile,v 1.11 2002/06/21 06:18:02 mckusick Exp $
# @(#)Makefile 8.1 (Berkeley) 6/11/93
Index: specialreg.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/specialreg.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/amd64/include/specialreg.h -L sys/amd64/include/specialreg.h -u -r1.2 -r1.3
--- sys/amd64/include/specialreg.h
+++ sys/amd64/include/specialreg.h
@@ -27,7 +27,7 @@
* SUCH DAMAGE.
*
* from: @(#)specialreg.h 7.1 (Berkeley) 5/9/91
- * $FreeBSD: src/sys/amd64/include/specialreg.h,v 1.30.8.1 2006/04/24 18:21:54 jkim Exp $
+ * $FreeBSD: src/sys/amd64/include/specialreg.h,v 1.40 2007/08/15 19:26:01 des Exp $
*/
#ifndef _MACHINE_SPECIALREG_H_
@@ -109,33 +109,42 @@
#define CPUID_SS 0x08000000
#define CPUID_HTT 0x10000000
#define CPUID_TM 0x20000000
-#define CPUID_B30 0x40000000
+#define CPUID_IA64 0x40000000
#define CPUID_PBE 0x80000000
-#define CPUID2_SSE3 0x00000001
-#define CPUID2_MON 0x00000008
-#define CPUID2_DS_CPL 0x00000010
-#define CPUID2_EST 0x00000080
-#define CPUID2_TM2 0x00000100
-#define CPUID2_CNTXID 0x00000400
-#define CPUID2_CX16 0x00002000
+#define CPUID2_SSE3 0x00000001
+#define CPUID2_MON 0x00000008
+#define CPUID2_DS_CPL 0x00000010
+#define CPUID2_VMX 0x00000020
+#define CPUID2_SMX 0x00000040
+#define CPUID2_EST 0x00000080
+#define CPUID2_TM2 0x00000100
+#define CPUID2_SSSE3 0x00000200
+#define CPUID2_CNXTID 0x00000400
+#define CPUID2_CX16 0x00002000
+#define CPUID2_XTPR 0x00004000
+#define CPUID2_PDCM 0x00008000
+#define CPUID2_DCA 0x00040000
/*
* Important bits in the AMD extended cpuid flags
*/
-#define AMDID_SYSCALL 0x00000800
-#define AMDID_MP 0x00080000
-#define AMDID_NX 0x00100000
-#define AMDID_EXT_MMX 0x00400000
-#define AMDID_FFXSR 0x01000000
-#define AMDID_RDTSCP 0x08000000
-#define AMDID_LM 0x20000000
-#define AMDID_EXT_3DNOW 0x40000000
-#define AMDID_3DNOW 0x80000000
-
-#define AMDID2_LAHF 0x00000001
-#define AMDID2_CMP 0x00000002
-#define AMDID2_CR8 0x00000010
+#define AMDID_SYSCALL 0x00000800
+#define AMDID_MP 0x00080000
+#define AMDID_NX 0x00100000
+#define AMDID_EXT_MMX 0x00400000
+#define AMDID_FFXSR 0x01000000
+#define AMDID_RDTSCP 0x08000000
+#define AMDID_LM 0x20000000
+#define AMDID_EXT_3DNOW 0x40000000
+#define AMDID_3DNOW 0x80000000
+
+#define AMDID2_LAHF 0x00000001
+#define AMDID2_CMP 0x00000002
+#define AMDID2_SVM 0x00000004
+#define AMDID2_EXT_APIC 0x00000008
+#define AMDID2_CR8 0x00000010
+#define AMDID2_PREFETCH 0x00000100
/*
* CPUID instruction 1 ebx info
@@ -148,29 +157,30 @@
/*
* AMD extended function 8000_0008h ecx info
*/
-#define AMDID_CMP_CORES 0x000000ff
+#define AMDID_CMP_CORES 0x000000ff
/*
* Model-specific registers for the i386 family
*/
-#define MSR_P5_MC_ADDR 0x000
-#define MSR_P5_MC_TYPE 0x001
-#define MSR_TSC 0x010
+#define MSR_P5_MC_ADDR 0x000
+#define MSR_P5_MC_TYPE 0x001
+#define MSR_TSC 0x010
#define MSR_P5_CESR 0x011
#define MSR_P5_CTR0 0x012
#define MSR_P5_CTR1 0x013
#define MSR_IA32_PLATFORM_ID 0x017
-#define MSR_APICBASE 0x01b
-#define MSR_EBL_CR_POWERON 0x02a
+#define MSR_APICBASE 0x01b
+#define MSR_EBL_CR_POWERON 0x02a
#define MSR_TEST_CTL 0x033
-#define MSR_BIOS_UPDT_TRIG 0x079
+#define MSR_BIOS_UPDT_TRIG 0x079
#define MSR_BBL_CR_D0 0x088
#define MSR_BBL_CR_D1 0x089
#define MSR_BBL_CR_D2 0x08a
-#define MSR_BIOS_SIGN 0x08b
-#define MSR_PERFCTR0 0x0c1
-#define MSR_PERFCTR1 0x0c2
-#define MSR_MTRRcap 0x0fe
+#define MSR_BIOS_SIGN 0x08b
+#define MSR_PERFCTR0 0x0c1
+#define MSR_PERFCTR1 0x0c2
+#define MSR_IA32_EXT_CONFIG 0x0ee /* Undocumented. Core Solo/Duo only */
+#define MSR_MTRRcap 0x0fe
#define MSR_BBL_CR_ADDR 0x116
#define MSR_BBL_CR_DECC 0x118
#define MSR_BBL_CR_CTL 0x119
@@ -180,46 +190,47 @@
#define MSR_SYSENTER_CS_MSR 0x174
#define MSR_SYSENTER_ESP_MSR 0x175
#define MSR_SYSENTER_EIP_MSR 0x176
-#define MSR_MCG_CAP 0x179
-#define MSR_MCG_STATUS 0x17a
-#define MSR_MCG_CTL 0x17b
-#define MSR_EVNTSEL0 0x186
-#define MSR_EVNTSEL1 0x187
-#define MSR_THERM_CONTROL 0x19a
-#define MSR_THERM_INTERRUPT 0x19b
-#define MSR_THERM_STATUS 0x19c
-#define MSR_DEBUGCTLMSR 0x1d9
-#define MSR_LASTBRANCHFROMIP 0x1db
-#define MSR_LASTBRANCHTOIP 0x1dc
-#define MSR_LASTINTFROMIP 0x1dd
-#define MSR_LASTINTTOIP 0x1de
-#define MSR_ROB_CR_BKUPTMPDR6 0x1e0
-#define MSR_MTRRVarBase 0x200
-#define MSR_MTRR64kBase 0x250
-#define MSR_MTRR16kBase 0x258
-#define MSR_MTRR4kBase 0x268
-#define MSR_PAT 0x277
-#define MSR_MTRRdefType 0x2ff
-#define MSR_MC0_CTL 0x400
-#define MSR_MC0_STATUS 0x401
-#define MSR_MC0_ADDR 0x402
-#define MSR_MC0_MISC 0x403
-#define MSR_MC1_CTL 0x404
-#define MSR_MC1_STATUS 0x405
-#define MSR_MC1_ADDR 0x406
-#define MSR_MC1_MISC 0x407
-#define MSR_MC2_CTL 0x408
-#define MSR_MC2_STATUS 0x409
-#define MSR_MC2_ADDR 0x40a
-#define MSR_MC2_MISC 0x40b
-#define MSR_MC3_CTL 0x40c
-#define MSR_MC3_STATUS 0x40d
-#define MSR_MC3_ADDR 0x40e
-#define MSR_MC3_MISC 0x40f
-#define MSR_MC4_CTL 0x410
-#define MSR_MC4_STATUS 0x411
-#define MSR_MC4_ADDR 0x412
-#define MSR_MC4_MISC 0x413
+#define MSR_MCG_CAP 0x179
+#define MSR_MCG_STATUS 0x17a
+#define MSR_MCG_CTL 0x17b
+#define MSR_EVNTSEL0 0x186
+#define MSR_EVNTSEL1 0x187
+#define MSR_THERM_CONTROL 0x19a
+#define MSR_THERM_INTERRUPT 0x19b
+#define MSR_THERM_STATUS 0x19c
+#define MSR_IA32_MISC_ENABLE 0x1a0
+#define MSR_DEBUGCTLMSR 0x1d9
+#define MSR_LASTBRANCHFROMIP 0x1db
+#define MSR_LASTBRANCHTOIP 0x1dc
+#define MSR_LASTINTFROMIP 0x1dd
+#define MSR_LASTINTTOIP 0x1de
+#define MSR_ROB_CR_BKUPTMPDR6 0x1e0
+#define MSR_MTRRVarBase 0x200
+#define MSR_MTRR64kBase 0x250
+#define MSR_MTRR16kBase 0x258
+#define MSR_MTRR4kBase 0x268
+#define MSR_PAT 0x277
+#define MSR_MTRRdefType 0x2ff
+#define MSR_MC0_CTL 0x400
+#define MSR_MC0_STATUS 0x401
+#define MSR_MC0_ADDR 0x402
+#define MSR_MC0_MISC 0x403
+#define MSR_MC1_CTL 0x404
+#define MSR_MC1_STATUS 0x405
+#define MSR_MC1_ADDR 0x406
+#define MSR_MC1_MISC 0x407
+#define MSR_MC2_CTL 0x408
+#define MSR_MC2_STATUS 0x409
+#define MSR_MC2_ADDR 0x40a
+#define MSR_MC2_MISC 0x40b
+#define MSR_MC3_CTL 0x40c
+#define MSR_MC3_STATUS 0x40d
+#define MSR_MC3_ADDR 0x40e
+#define MSR_MC3_MISC 0x40f
+#define MSR_MC4_CTL 0x410
+#define MSR_MC4_STATUS 0x411
+#define MSR_MC4_ADDR 0x412
+#define MSR_MC4_MISC 0x413
/*
* Constants related to MSR's.
@@ -230,11 +241,23 @@
#define APICBASE_ADDRESS 0xfffff000
/*
+ * PAT modes.
+ */
+#define PAT_UNCACHEABLE 0x00
+#define PAT_WRITE_COMBINING 0x01
+#define PAT_WRITE_THROUGH 0x04
+#define PAT_WRITE_PROTECTED 0x05
+#define PAT_WRITE_BACK 0x06
+#define PAT_UNCACHED 0x07
+#define PAT_VALUE(i, m) ((long)(m) << (8 * (i)))
+#define PAT_MASK(i) PAT_VALUE(i, 0xff)
+
+/*
* Constants related to MTRRs
*/
-#define MTRR_N64K 8 /* numbers of fixed-size entries */
-#define MTRR_N16K 16
-#define MTRR_N4K 64
+#define MTRR_N64K 8 /* numbers of fixed-size entries */
+#define MTRR_N16K 16
+#define MTRR_N4K 64
/* Performance Control Register (5x86 only). */
#define PCR0 0x20
@@ -331,11 +354,11 @@
#define RCR6 0xe2
#define RCR7 0xe3
-#define RCR_RCD 0x01 /* Disables caching for ARRx (x = 0-6). */
-#define RCR_RCE 0x01 /* Enables caching for ARR7. */
-#define RCR_WWO 0x02 /* Weak write ordering. */
+#define RCR_RCD 0x01 /* Disables caching for ARRx (x = 0-6). */
+#define RCR_RCE 0x01 /* Enables caching for ARR7. */
+#define RCR_WWO 0x02 /* Weak write ordering. */
#define RCR_WL 0x04 /* Weak locking. */
-#define RCR_WG 0x08 /* Write gathering. */
+#define RCR_WG 0x08 /* Write gathering. */
#define RCR_WT 0x10 /* Write-through. */
#define RCR_NLB 0x20 /* LBA# pin is not asserted. */
@@ -344,7 +367,7 @@
#define AMD_WT_ALLOC_PRE 0x20000 /* programmable range enable */
#define AMD_WT_ALLOC_FRE 0x10000 /* fixed (A0000-FFFFF) range enable */
-/* X86-64 MSR's */
+/* AMD64 MSR's */
#define MSR_EFER 0xc0000080 /* extended features */
#define MSR_STAR 0xc0000081 /* legacy mode SYSCALL target/cs/ss */
#define MSR_LSTAR 0xc0000082 /* long mode SYSCALL target rip */
Index: signal.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/signal.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/signal.h -L sys/amd64/include/signal.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/signal.h
+++ sys/amd64/include/signal.h
@@ -28,7 +28,7 @@
* SUCH DAMAGE.
*
* @(#)signal.h 8.1 (Berkeley) 6/11/93
- * $FreeBSD: src/sys/amd64/include/signal.h,v 1.28 2005/01/05 20:17:20 imp Exp $
+ * $FreeBSD: src/sys/amd64/include/signal.h,v 1.29 2005/08/20 16:44:40 stefanf Exp $
*/
#ifndef _MACHINE_SIGNAL_H_
@@ -43,14 +43,6 @@
typedef long sig_atomic_t;
-#if __XSI_VISIBLE
-/*
- * Minimum signal stack size. The current signal frame
- * for i386 is 408 bytes large.
- */
-#define MINSIGSTKSZ (512 * 4)
-#endif
-
#if __BSD_VISIBLE
#include <machine/trap.h> /* codes for SIGILL, SIGFPE */
Index: cpu.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/cpu.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/cpu.h -L sys/amd64/include/cpu.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/cpu.h
+++ sys/amd64/include/cpu.h
@@ -30,7 +30,7 @@
* SUCH DAMAGE.
*
* from: @(#)cpu.h 5.4 (Berkeley) 5/9/91
- * $FreeBSD: src/sys/amd64/include/cpu.h,v 1.74 2004/08/03 18:44:26 mux Exp $
+ * $FreeBSD: src/sys/amd64/include/cpu.h,v 1.76 2006/05/11 17:29:24 phk Exp $
*/
#ifndef _MACHINE_CPU_H_
@@ -59,19 +59,6 @@
(ISPL((framep)->tf_cs) == SEL_UPL)
#define TRAPF_PC(framep) ((framep)->tf_rip)
-#define CLKF_USERMODE(framep) \
- (ISPL((framep)->cf_cs) == SEL_UPL)
-#define CLKF_PC(framep) ((framep)->cf_rip)
-
-/*
- * CTL_MACHDEP definitions.
- */
-#define CPU_CONSDEV 1 /* dev_t: console terminal device */
-#define CPU_ADJKERNTZ 2 /* int: timezone offset (seconds) */
-#define CPU_DISRTCSET 3 /* int: disable resettodr() call */
-#define CPU_WALLCLOCK 5 /* int: indicates wall CMOS clock */
-#define CPU_MAXID 6 /* number of valid machdep ids */
-
#ifdef _KERNEL
extern char btext[];
extern char etext[];
Index: setjmp.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/setjmp.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/setjmp.h -L sys/amd64/include/setjmp.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/setjmp.h
+++ sys/amd64/include/setjmp.h
@@ -10,10 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by John Birrell.
- * 4. Neither the name of the author nor the names of any co-contributors
+ * 3. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
@@ -29,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/amd64/include/setjmp.h,v 1.9 2003/06/02 21:49:35 peter Exp $
+ * $FreeBSD: src/sys/amd64/include/setjmp.h,v 1.10 2007/01/12 07:24:06 imp Exp $
*/
#ifndef _MACHINE_SETJMP_H_
Index: intr_machdep.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/intr_machdep.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/amd64/include/intr_machdep.h -L sys/amd64/include/intr_machdep.h -u -r1.2 -r1.3
--- sys/amd64/include/intr_machdep.h
+++ sys/amd64/include/intr_machdep.h
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/amd64/include/intr_machdep.h,v 1.5.2.3 2006/03/10 19:37:31 jhb Exp $
+ * $FreeBSD: src/sys/amd64/include/intr_machdep.h,v 1.18 2007/05/08 21:29:13 jhb Exp $
*/
#ifndef __MACHINE_INTR_MACHDEP_H__
@@ -43,11 +43,18 @@
* 191 and still be safe since only interrupt sources in actual use will
* allocate IDT vectors.
*
- * For now we stick with 255 as ISA IRQs and PCI intline IRQs only allow
- * for IRQs in the range 0 - 254. When MSI support is added this number
- * will likely increase.
+ * The first 255 IRQs (0 - 254) are reserved for ISA IRQs and PCI intline IRQs.
+ * IRQ values beyond 256 are used by MSI. We leave 255 unused to avoid
+ * confusion since 255 is used in PCI to indicate an invalid IRQ.
*/
-#define NUM_IO_INTS 255
+#define NUM_MSI_INTS 128
+#define FIRST_MSI_INT 256
+#define NUM_IO_INTS (FIRST_MSI_INT + NUM_MSI_INTS)
+
+/*
+ * Default base address for MSI messages on x86 platforms.
+ */
+#define MSI_INTEL_ADDR_BASE 0xfee00000
/*
* - 1 ??? dummy counter.
@@ -56,9 +63,9 @@
* - 7 counters for each CPU for IPI counters for SMP.
*/
#ifdef SMP
-#define INTRCNT_COUNT (1 + NUM_IO_INTS * 2 + 1)
-#else
#define INTRCNT_COUNT (1 + NUM_IO_INTS * 2 + (1 + 7) * MAXCPU)
+#else
+#define INTRCNT_COUNT (1 + NUM_IO_INTS * 2 + 1)
#endif
#ifndef LOCORE
@@ -79,13 +86,15 @@
void (*pic_disable_source)(struct intsrc *, int);
void (*pic_eoi_source)(struct intsrc *);
void (*pic_enable_intr)(struct intsrc *);
+ void (*pic_disable_intr)(struct intsrc *);
int (*pic_vector)(struct intsrc *);
int (*pic_source_pending)(struct intsrc *);
- void (*pic_suspend)(struct intsrc *);
- void (*pic_resume)(struct intsrc *);
+ void (*pic_suspend)(struct pic *);
+ void (*pic_resume)(struct pic *);
int (*pic_config_intr)(struct intsrc *, enum intr_trigger,
enum intr_polarity);
void (*pic_assign_cpu)(struct intsrc *, u_int apic_id);
+ STAILQ_ENTRY(pic) pics;
};
/* Flags for pic_disable_source() */
@@ -106,35 +115,45 @@
u_long *is_count;
u_long *is_straycount;
u_int is_index;
- u_int is_enabled:1;
+ u_int is_handlers;
};
-struct intrframe;
+struct trapframe;
extern struct mtx icu_lock;
extern int elcr_found;
+#ifndef DEV_ATPIC
+void atpic_reset(void);
+#endif
/* XXX: The elcr_* prototypes probably belong somewhere else. */
int elcr_probe(void);
enum intr_trigger elcr_read_trigger(u_int irq);
void elcr_resume(void);
void elcr_write_trigger(u_int irq, enum intr_trigger trigger);
#ifdef SMP
-void intr_add_cpu(u_int apic_id);
-#else
-#define intr_add_cpu(apic_id)
+void intr_add_cpu(u_int cpu);
#endif
-int intr_add_handler(const char *name, int vector, driver_intr_t handler,
- void *arg, enum intr_type flags, void **cookiep);
+int intr_add_handler(const char *name, int vector, driver_filter_t filter,
+ driver_intr_t handler, void *arg, enum intr_type flags,
+ void **cookiep);
int intr_config_intr(int vector, enum intr_trigger trig,
enum intr_polarity pol);
-void intr_execute_handlers(struct intsrc *isrc, struct intrframe *iframe);
+void intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame);
struct intsrc *intr_lookup_source(int vector);
+int intr_register_pic(struct pic *pic);
int intr_register_source(struct intsrc *isrc);
int intr_remove_handler(void *cookie);
void intr_resume(void);
void intr_suspend(void);
void intrcnt_add(const char *name, u_long **countp);
+void nexus_add_irq(u_long irq);
+int msi_alloc(device_t dev, int count, int maxcount, int *irqs);
+void msi_init(void);
+int msi_map(int irq, uint64_t *addr, uint32_t *data);
+int msi_release(int *irqs, int count);
+int msix_alloc(device_t dev, int *irq);
+int msix_release(int irq);
#endif /* !LOCORE */
#endif /* _KERNEL */
Index: bus.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/bus.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/bus.h -L sys/amd64/include/bus.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/bus.h
+++ sys/amd64/include/bus.h
@@ -28,7 +28,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $FreeBSD: src/sys/amd64/include/bus.h,v 1.16 2005/05/29 04:42:15 nyan Exp $
+ * $FreeBSD: src/sys/amd64/include/bus.h,v 1.17 2006/03/14 00:01:56 peter Exp $
*/
/* $NetBSD: bus.h,v 1.12 1997/10/01 08:25:15 fvdl Exp $ */
@@ -1004,6 +1004,17 @@
#endif
}
+#ifdef BUS_SPACE_NO_LEGACY
+#undef inb
+#undef outb
+#define inb(a) compiler_error
+#define inw(a) compiler_error
+#define inl(a) compiler_error
+#define outb(a, b) compiler_error
+#define outw(a, b) compiler_error
+#define outl(a, b) compiler_error
+#endif
+
#include <machine/bus_dma.h>
/*
Index: _limits.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/_limits.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/_limits.h -L sys/amd64/include/_limits.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/_limits.h
+++ sys/amd64/include/_limits.h
@@ -27,7 +27,7 @@
* SUCH DAMAGE.
*
* @(#)limits.h 8.3 (Berkeley) 1/4/94
- * $FreeBSD: src/sys/amd64/include/_limits.h,v 1.10 2005/01/05 20:17:20 imp Exp $
+ * $FreeBSD: src/sys/amd64/include/_limits.h,v 1.11 2005/08/20 16:44:40 stefanf Exp $
*/
#ifndef _MACHINE__LIMITS_H_
@@ -83,4 +83,10 @@
#define __LONG_BIT 64
#define __WORD_BIT 32
+/*
+ * Minimum signal stack size. The current signal frame
+ * for i386 is 408 bytes large.
+ */
+#define __MINSIGSTKSZ (512 * 4)
+
#endif /* !_MACHINE__LIMITS_H_ */
Index: gdb_machdep.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/gdb_machdep.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/gdb_machdep.h -L sys/amd64/include/gdb_machdep.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/gdb_machdep.h
+++ sys/amd64/include/gdb_machdep.h
@@ -23,15 +23,15 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $FreeBSD: src/sys/amd64/include/gdb_machdep.h,v 1.3 2005/01/05 20:17:20 imp Exp $
+ * $FreeBSD: src/sys/amd64/include/gdb_machdep.h,v 1.6 2007/02/05 21:48:32 jhb Exp $
*/
#ifndef _MACHINE_GDB_MACHDEP_H_
#define _MACHINE_GDB_MACHDEP_H_
-#define GDB_BUFSZ 500
+#define GDB_BUFSZ (GDB_NREGS * 16)
#define GDB_NREGS 56
-#define GDB_REG_PC 18
+#define GDB_REG_PC 16
static __inline size_t
gdb_cpu_regsz(int regnum)
@@ -40,12 +40,6 @@
}
static __inline int
-gdb_cpu_signal(int type, int code __unused)
-{
- return (type);
-}
-
-static __inline int
gdb_cpu_query(void)
{
return (0);
@@ -53,5 +47,6 @@
void *gdb_cpu_getreg(int, size_t *);
void gdb_cpu_setreg(int, void *);
+int gdb_cpu_signal(int, int);
#endif /* !_MACHINE_GDB_MACHDEP_H_ */
Index: bus_dma.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/bus_dma.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/bus_dma.h -L sys/amd64/include/bus_dma.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/bus_dma.h
+++ sys/amd64/include/bus_dma.h
@@ -22,8 +22,9 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/amd64/include/bus_dma.h,v 1.30 2005/07/22 04:03:25 obrien Exp $
*/
-/* $FreeBSD: src/sys/amd64/include/bus_dma.h,v 1.29 2005/03/14 16:46:27 scottl Exp $ */
#ifndef _AMD64_BUS_DMA_H_
#define _AMD64_BUS_DMA_H_
Index: asmacros.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/asmacros.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/asmacros.h -L sys/amd64/include/asmacros.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/asmacros.h
+++ sys/amd64/include/asmacros.h
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/amd64/include/asmacros.h,v 1.28 2004/04/05 21:25:51 imp Exp $
+ * $FreeBSD: src/sys/amd64/include/asmacros.h,v 1.33 2007/08/22 04:26:07 jkoshy Exp $
*/
#ifndef _MACHINE_ASMACROS_H_
@@ -37,14 +37,12 @@
/* XXX too much duplication in various asm*.h's. */
/*
- * CNAME and HIDENAME manage the relationship between symbol names in C
+ * CNAME is used to manage the relationship between symbol names in C
* and the equivalent assembly language names. CNAME is given a name as
* it would be used in a C program. It expands to the equivalent assembly
- * language name. HIDENAME is given an assembly-language name, and expands
- * to a possibly-modified form that will be invisible to C programs.
+ * language name.
*/
#define CNAME(csym) csym
-#define HIDENAME(asmsym) .asmsym
#define ALIGN_DATA .p2align 3 /* 8 byte alignment, zero filled */
#ifdef GPROF
@@ -59,11 +57,7 @@
#define NON_GPROF_ENTRY(name) GEN_ENTRY(name)
#define NON_GPROF_RET .byte 0xc3 /* opcode for `ret' */
-#ifdef LOCORE
-#define PCPU(member) %gs:PC_ ## member
-#define PCPU_ADDR(member, reg) movq %gs:PC_PRVSPACE,reg; \
- addq $PC_ ## member,reg
-#endif
+#define END(name) .size name, . - name
#ifdef GPROF
/*
@@ -114,8 +108,12 @@
#define FAKE_MCOUNT(caller) pushq caller ; call __mcount ; popq %rcx
#define MCOUNT call __mcount
#define MCOUNT_LABEL(name) GEN_ENTRY(name) ; nop ; ALIGN_TEXT
-#define MEXITCOUNT call HIDENAME(mexitcount)
+#ifdef GUPROF
+#define MEXITCOUNT call .mexitcount
#define ret MEXITCOUNT ; NON_GPROF_RET
+#else
+#define MEXITCOUNT
+#endif
#else /* !GPROF */
/*
@@ -136,11 +134,65 @@
#ifdef LOCORE
/*
- * Convenience macros for declaring interrupt entry points.
+ * Convenience macro for declaring interrupt entry points.
*/
#define IDTVEC(name) ALIGN_TEXT; .globl __CONCAT(X,name); \
.type __CONCAT(X,name), at function; __CONCAT(X,name):
+/*
+ * Macros to create and destroy a trap frame.
+ */
+#define PUSH_FRAME \
+ subq $TF_RIP,%rsp ; /* skip dummy tf_err and tf_trapno */ \
+ testb $SEL_RPL_MASK,TF_CS(%rsp) ; /* come from kernel? */ \
+ jz 1f ; /* Yes, dont swapgs again */ \
+ swapgs ; \
+1: movq %rdi,TF_RDI(%rsp) ; \
+ movq %rsi,TF_RSI(%rsp) ; \
+ movq %rdx,TF_RDX(%rsp) ; \
+ movq %rcx,TF_RCX(%rsp) ; \
+ movq %r8,TF_R8(%rsp) ; \
+ movq %r9,TF_R9(%rsp) ; \
+ movq %rax,TF_RAX(%rsp) ; \
+ movq %rbx,TF_RBX(%rsp) ; \
+ movq %rbp,TF_RBP(%rsp) ; \
+ movq %r10,TF_R10(%rsp) ; \
+ movq %r11,TF_R11(%rsp) ; \
+ movq %r12,TF_R12(%rsp) ; \
+ movq %r13,TF_R13(%rsp) ; \
+ movq %r14,TF_R14(%rsp) ; \
+ movq %r15,TF_R15(%rsp)
+
+#define POP_FRAME \
+ movq TF_RDI(%rsp),%rdi ; \
+ movq TF_RSI(%rsp),%rsi ; \
+ movq TF_RDX(%rsp),%rdx ; \
+ movq TF_RCX(%rsp),%rcx ; \
+ movq TF_R8(%rsp),%r8 ; \
+ movq TF_R9(%rsp),%r9 ; \
+ movq TF_RAX(%rsp),%rax ; \
+ movq TF_RBX(%rsp),%rbx ; \
+ movq TF_RBP(%rsp),%rbp ; \
+ movq TF_R10(%rsp),%r10 ; \
+ movq TF_R11(%rsp),%r11 ; \
+ movq TF_R12(%rsp),%r12 ; \
+ movq TF_R13(%rsp),%r13 ; \
+ movq TF_R14(%rsp),%r14 ; \
+ movq TF_R15(%rsp),%r15 ; \
+ testb $SEL_RPL_MASK,TF_CS(%rsp) ; /* come from kernel? */ \
+ jz 1f ; /* keep kernel GS.base */ \
+ cli ; \
+ swapgs ; \
+1: addq $TF_RIP,%rsp /* skip over tf_err, tf_trapno */
+
+/*
+ * Access per-CPU data.
+ */
+#define PCPU(member) %gs:PC_ ## member
+#define PCPU_ADDR(member, reg) \
+ movq %gs:PC_PRVSPACE, reg ; \
+ addq $PC_ ## member, reg
+
#endif /* LOCORE */
#endif /* !_MACHINE_ASMACROS_H_ */
Index: acpica_machdep.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/acpica_machdep.h,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -L sys/amd64/include/acpica_machdep.h -L sys/amd64/include/acpica_machdep.h -u -r1.1.1.2 -r1.2
--- sys/amd64/include/acpica_machdep.h
+++ sys/amd64/include/acpica_machdep.h
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/amd64/include/acpica_machdep.h,v 1.6 2004/10/11 05:39:15 njl Exp $
+ * $FreeBSD: src/sys/amd64/include/acpica_machdep.h,v 1.7 2007/03/22 18:16:39 jkim Exp $
*/
/******************************************************************************
@@ -34,7 +34,7 @@
*****************************************************************************/
#ifndef __ACPICA_MACHDEP_H__
-#define __ACPICA_MACHDEP_H__
+#define __ACPICA_MACHDEP_H__
#ifdef _KERNEL
/*
@@ -45,33 +45,35 @@
* ACPI_INTERNAL_XFACE - Internal ACPI interfaces
* ACPI_INTERNAL_VAR_XFACE - Internal variable-parameter list interfaces
*/
-#define ACPI_SYSTEM_XFACE
-#define ACPI_EXTERNAL_XFACE
-#define ACPI_INTERNAL_XFACE
-#define ACPI_INTERNAL_VAR_XFACE
+#define ACPI_SYSTEM_XFACE
+#define ACPI_EXTERNAL_XFACE
+#define ACPI_INTERNAL_XFACE
+#define ACPI_INTERNAL_VAR_XFACE
/* Asm macros */
-#define ACPI_ASM_MACROS
-#define BREAKPOINT3
-#define ACPI_DISABLE_IRQS() disable_intr()
-#define ACPI_ENABLE_IRQS() enable_intr()
+#define ACPI_ASM_MACROS
+#define BREAKPOINT3
+#define ACPI_DISABLE_IRQS() disable_intr()
+#define ACPI_ENABLE_IRQS() enable_intr()
-#define ACPI_FLUSH_CPU_CACHE() wbinvd()
+#define ACPI_FLUSH_CPU_CACHE() wbinvd()
/* Section 5.2.9.1: global lock acquire/release functions */
extern int acpi_acquire_global_lock(uint32_t *lock);
extern int acpi_release_global_lock(uint32_t *lock);
-#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \
- ((Acq) = acpi_acquire_global_lock(GLptr))
-#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) \
- ((Acq) = acpi_release_global_lock(GLptr))
+#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) do { \
+ (Acq) = acpi_acquire_global_lock(&((GLptr)->GlobalLock)); \
+} while (0)
+#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) do { \
+ (Acq) = acpi_release_global_lock(&((GLptr)->GlobalLock)); \
+} while (0)
#endif /* _KERNEL */
-#define ACPI_MACHINE_WIDTH 64
-#define COMPILER_DEPENDENT_INT64 long
-#define COMPILER_DEPENDENT_UINT64 unsigned long
+#define ACPI_MACHINE_WIDTH 64
+#define COMPILER_DEPENDENT_INT64 long
+#define COMPILER_DEPENDENT_UINT64 unsigned long
void acpi_SetDefaultIntrModel(int model);
void acpi_cpu_c1(void);
Index: stdarg.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/stdarg.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/amd64/include/stdarg.h -L sys/amd64/include/stdarg.h -u -r1.2 -r1.3
--- sys/amd64/include/stdarg.h
+++ sys/amd64/include/stdarg.h
@@ -1,5 +1,4 @@
/*-
- * Copyright (c) 2008 Lucas Holt. All rights reserved.
* Copyright (c) 2002 David E. O'Brien. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,8 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/amd64/include/stdarg.h,v 1.8 2005/03/11 22:16:09 peter Exp $
- * $MidnightBSD$
+ * $FreeBSD: src/sys/amd64/include/stdarg.h,v 1.9 2006/09/21 01:37:01 kan Exp $
*/
#ifndef _MACHINE_STDARG_H_
@@ -44,7 +42,7 @@
#ifdef __GNUCLIKE_BUILTIN_STDARG
#define va_start(ap, last) \
- __builtin_stdarg_start((ap), (last))
+ __builtin_va_start((ap), (last))
#define va_arg(ap, type) \
__builtin_va_arg((ap), type)
@@ -70,17 +68,6 @@
(*(type *)((ap) += __va_size(type), (ap) - __va_size(type)))
#define va_end(ap)
-#elif defined(__PCC__) /* !__GNUCLIKE_BUILTIN_STDARG */
-
-#define va_start(ap, last) \
- __builtin_stdarg_start((ap), last)
-#define va_arg(ap, type) \
- __builtin_va_arg((ap), type)
-#define va_end(ap) \
- __builtin_va_end((ap))
-#define __va_copy(dest, src) \
- __builtin_va_copy((dest), (src))
-
#else
#error this file needs to be ported to your compiler
#endif
Index: smp.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/smp.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/smp.h -L sys/amd64/include/smp.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/smp.h
+++ sys/amd64/include/smp.h
@@ -6,7 +6,7 @@
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*
- * $FreeBSD: src/sys/amd64/include/smp.h,v 1.84 2005/04/30 20:00:58 dwhite Exp $
+ * $FreeBSD: src/sys/amd64/include/smp.h,v 1.91 2007/09/20 20:38:43 attilio Exp $
*
*/
@@ -23,6 +23,7 @@
#include <machine/frame.h>
#include <machine/intr_machdep.h>
#include <machine/apicvar.h>
+#include <machine/pcb.h>
/* global symbols in mpboot.S */
extern char mptramp_start[];
@@ -33,28 +34,31 @@
extern int mp_naps;
extern int boot_cpu_id;
extern struct pcb stoppcbs[];
-extern struct mtx smp_tlb_mtx;
+extern int cpu_apic_ids[];
/* IPI handlers */
inthand_t
IDTVEC(invltlb), /* TLB shootdowns - global */
IDTVEC(invlpg), /* TLB shootdowns - 1 page */
IDTVEC(invlrng), /* TLB shootdowns - page range */
+ IDTVEC(invlcache), /* Write back and invalidate cache */
IDTVEC(ipi_intr_bitmap_handler), /* Bitmap based IPIs */
IDTVEC(cpustop), /* CPU stops & waits to be restarted */
IDTVEC(rendezvous); /* handle CPU rendezvous */
/* functions in mp_machdep.c */
void cpu_add(u_int apic_id, char boot_cpu);
+void cpustop_handler(void);
void init_secondary(void);
void ipi_selected(u_int cpus, u_int ipi);
void ipi_all(u_int ipi);
void ipi_all_but_self(u_int ipi);
void ipi_self(u_int ipi);
-void ipi_bitmap_handler(struct clockframe frame);
+void ipi_bitmap_handler(struct trapframe frame);
u_int mp_bootaddress(u_int);
int mp_grab_cpu_hlt(void);
void mp_topology(void);
+void smp_cache_flush(void);
void smp_invlpg(vm_offset_t addr);
void smp_masked_invlpg(u_int mask, vm_offset_t addr);
void smp_invlpg_range(vm_offset_t startva, vm_offset_t endva);
@@ -63,9 +67,8 @@
void smp_invltlb(void);
void smp_masked_invltlb(u_int mask);
-#ifdef KDB_STOP_NMI
-int ipi_nmi_handler(void);
-void ipi_nmi_selected(u_int32_t cpus);
+#ifdef STOP_NMI
+int ipi_nmi_handler(void);
#endif
#endif /* !LOCORE */
Index: param.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/param.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/param.h -L sys/amd64/include/param.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/param.h
+++ sys/amd64/include/param.h
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)param.h 8.1 (Berkeley) 6/10/93
- * $FreeBSD: src/sys/amd64/include/param.h,v 1.18 2005/06/29 15:13:25 jhb Exp $
+ * $FreeBSD: src/sys/amd64/include/param.h,v 1.20 2006/01/09 06:05:56 imp Exp $
*/
/*
@@ -64,15 +64,11 @@
#define _ALIGNED_POINTER(p,t) ((((u_long)(p)) & (sizeof(t)-1)) == 0)
#endif
-#ifndef _MACHINE
-#define _MACHINE amd64
-#endif
-#ifndef _MACHINE_ARCH
-#define _MACHINE_ARCH amd64
-#endif
-
#ifndef _NO_NAMESPACE_POLLUTION
+#define __HAVE_ACPI
+#define __PCI_REROUTE_INTERRUPT
+
#ifndef _MACHINE_PARAM_H_
#define _MACHINE_PARAM_H_
Index: trap.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/trap.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/trap.h -L sys/amd64/include/trap.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/trap.h
+++ sys/amd64/include/trap.h
@@ -30,7 +30,7 @@
* SUCH DAMAGE.
*
* from: @(#)trap.h 5.4 (Berkeley) 5/9/91
- * $FreeBSD: src/sys/amd64/include/trap.h,v 1.14 2004/04/05 21:25:51 imp Exp $
+ * $FreeBSD: src/sys/amd64/include/trap.h,v 1.15 2006/03/14 00:01:22 peter Exp $
*/
#ifndef _MACHINE_TRAP_H_
@@ -72,16 +72,6 @@
#define ILL_ALIGN_FAULT T_ALIGNFLT
#define ILL_FPOP_FAULT T_FPOPFLT /* coprocessor operand fault */
-/* portable macros for SIGFPE/ARITHTRAP */
-#define FPE_INTOVF 1 /* integer overflow */
-#define FPE_INTDIV 2 /* integer divide by zero */
-#define FPE_FLTDIV 3 /* floating point divide by zero */
-#define FPE_FLTOVF 4 /* floating point overflow */
-#define FPE_FLTUND 5 /* floating point underflow */
-#define FPE_FLTRES 6 /* floating point inexact result */
-#define FPE_FLTINV 7 /* invalid floating point operation */
-#define FPE_FLTSUB 8 /* subscript out of range */
-
/* old FreeBSD macros, deprecated */
#define FPE_INTOVF_TRAP 0x1 /* integer overflow */
#define FPE_INTDIV_TRAP 0x2 /* integer divide by zero */
Index: asm.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/asm.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/asm.h -L sys/amd64/include/asm.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/asm.h
+++ sys/amd64/include/asm.h
@@ -30,7 +30,7 @@
* SUCH DAMAGE.
*
* from: @(#)DEFS.h 5.1 (Berkeley) 4/23/90
- * $FreeBSD: src/sys/amd64/include/asm.h,v 1.17 2005/04/10 20:49:21 alc Exp $
+ * $FreeBSD: src/sys/amd64/include/asm.h,v 1.18 2007/08/22 04:26:07 jkoshy Exp $
*/
#ifndef _MACHINE_ASM_H_
@@ -77,6 +77,8 @@
#define ENTRY(x) _ENTRY(x)
#endif
+#define END(x) .size x, . - x
+
#define RCSID(x) .text; .asciz x
#undef __FBSDID
Index: reg.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/reg.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/reg.h -L sys/amd64/include/reg.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/reg.h
+++ sys/amd64/include/reg.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)reg.h 5.5 (Berkeley) 1/18/91
- * $FreeBSD: src/sys/amd64/include/reg.h,v 1.35 2004/04/05 23:55:14 imp Exp $
+ * $FreeBSD: src/sys/amd64/include/reg.h,v 1.38 2006/11/17 20:27:01 jhb Exp $
*/
#ifndef _MACHINE_REG_H_
@@ -92,11 +92,26 @@
/* Index 8-15: reserved */
};
-#define DBREG_DR7_EXEC 0x00 /* break on execute */
-#define DBREG_DR7_WRONLY 0x01 /* break on write */
-#define DBREG_DR7_RDWR 0x03 /* break on read or write */
-#define DBREG_DRX(d,x) ((d)->dr[(x)]) /* reference dr0 - dr15 by
- register number */
+#define DBREG_DR7_LOCAL_ENABLE 0x01
+#define DBREG_DR7_GLOBAL_ENABLE 0x02
+#define DBREG_DR7_LEN_1 0x00 /* 1 byte length */
+#define DBREG_DR7_LEN_2 0x01
+#define DBREG_DR7_LEN_4 0x03
+#define DBREG_DR7_LEN_8 0x02
+#define DBREG_DR7_EXEC 0x00 /* break on execute */
+#define DBREG_DR7_WRONLY 0x01 /* break on write */
+#define DBREG_DR7_RDWR 0x03 /* break on read or write */
+#define DBREG_DR7_MASK(i) ((u_long)0xf << ((i) * 4 + 16) | 0x3 << (i) * 2)
+#define DBREG_DR7_SET(i, len, access, enable) \
+ ((u_long)((len) << 2 | (access)) << ((i) * 4 + 16) | (enable) << (i) * 2)
+#define DBREG_DR7_GD 0x2000
+#define DBREG_DR7_ENABLED(d, i) (((d) & 0x3 << (i) * 2) != 0)
+#define DBREG_DR7_ACCESS(d, i) ((d) >> ((i) * 4 + 16) & 0x3)
+#define DBREG_DR7_LEN(d, i) ((d) >> ((i) * 4 + 18) & 0x3)
+
+#define DBREG_DRX(d,x) ((d)->dr[(x)]) /* reference dr0 - dr15 by
+ register number */
+
#ifdef _KERNEL
/*
* XXX these interfaces are MI, so they should be declared in a MI place.
Index: pci_cfgreg.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/pci_cfgreg.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/pci_cfgreg.h -L sys/amd64/include/pci_cfgreg.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/pci_cfgreg.h
+++ sys/amd64/include/pci_cfgreg.h
@@ -23,7 +23,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $FreeBSD: src/sys/amd64/include/pci_cfgreg.h,v 1.13 2005/01/05 20:17:20 imp Exp $
+ * $FreeBSD: src/sys/amd64/include/pci_cfgreg.h,v 1.13.10.1 2007/12/06 08:25:43 jhb Exp $
*
*/
@@ -37,11 +37,6 @@
#define CONF1_ENABLE_MSK1 0x80000001ul
#define CONF1_ENABLE_RES1 0x80000000ul
-#define CONF2_ENABLE_PORT 0x0cf8
-#define CONF2_FORWARD_PORT 0x0cfa
-#define CONF2_ENABLE_CHK 0x0e
-#define CONF2_ENABLE_RES 0x0e
-
int pci_cfgregopen(void);
u_int32_t pci_cfgregread(int bus, int slot, int func, int reg, int bytes);
void pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes);
Index: segments.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/segments.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/segments.h -L sys/amd64/include/segments.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/segments.h
+++ sys/amd64/include/segments.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)segments.h 7.1 (Berkeley) 5/9/91
- * $FreeBSD: src/sys/amd64/include/segments.h,v 1.38 2004/04/05 21:25:51 imp Exp $
+ * $FreeBSD: src/sys/amd64/include/segments.h,v 1.39 2007/03/30 00:06:21 jkim Exp $
*/
#ifndef _MACHINE_SEGMENTS_H_
@@ -200,9 +200,10 @@
#define GUCODE32_SEL 3 /* User 32 bit code Descriptor */
#define GUDATA_SEL 4 /* User 32/64 bit Data Descriptor */
#define GUCODE_SEL 5 /* User 64 bit Code Descriptor */
-#define GPROC0_SEL 6 /* TSS for entering kernel etc */
+#define GPROC0_SEL 6 /* TSS for entering kernel etc */
/* slot 6 is second half of GPROC0_SEL */
-#define NGDT 8
+#define GUGS32_SEL 8 /* User 32 bit GS Descriptor */
+#define NGDT 9
#ifdef _KERNEL
extern struct user_segment_descriptor gdt[];
Index: mptable.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/mptable.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/amd64/include/mptable.h -L sys/amd64/include/mptable.h -u -r1.2 -r1.3
--- sys/amd64/include/mptable.h
+++ sys/amd64/include/mptable.h
@@ -22,7 +22,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/amd64/include/mptable.h,v 1.222.2.1 2006/03/01 06:02:42 sam Exp $
+ * $FreeBSD: src/sys/amd64/include/mptable.h,v 1.223 2006/03/01 05:59:56 sam Exp $
*/
#ifndef __MACHINE_MPTABLE_H__
Index: md_var.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/md_var.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/amd64/include/md_var.h -L sys/amd64/include/md_var.h -u -r1.2 -r1.3
--- sys/amd64/include/md_var.h
+++ sys/amd64/include/md_var.h
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/amd64/include/md_var.h,v 1.75.8.3 2006/07/24 23:28:08 peter Exp $
+ * $FreeBSD: src/sys/amd64/include/md_var.h,v 1.81 2007/05/19 05:03:59 kan Exp $
*/
#ifndef _MACHINE_MD_VAR_H_
@@ -57,8 +57,6 @@
extern uint64_t *vm_page_dump;
extern int vm_page_dump_size;
-extern struct pcpu __pcpu[];
-
typedef void alias_for_inthand_t(u_int cs, u_int ef, u_int esp, u_int ss);
struct thread;
struct reg;
Index: _types.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/_types.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/_types.h -L sys/amd64/include/_types.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/_types.h
+++ sys/amd64/include/_types.h
@@ -33,7 +33,7 @@
*
* From: @(#)ansi.h 8.2 (Berkeley) 1/4/94
* From: @(#)types.h 8.3 (Berkeley) 1/5/94
- * $FreeBSD: src/sys/amd64/include/_types.h,v 1.9 2005/07/02 23:13:30 thompsa Exp $
+ * $FreeBSD: src/sys/amd64/include/_types.h,v 1.11 2006/01/09 06:05:56 imp Exp $
*/
#ifndef _MACHINE__TYPES_H_
Index: kdb.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/kdb.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/kdb.h -L sys/amd64/include/kdb.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/kdb.h
+++ sys/amd64/include/kdb.h
@@ -23,7 +23,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $FreeBSD: src/sys/amd64/include/kdb.h,v 1.2 2005/01/05 20:17:20 imp Exp $
+ * $FreeBSD: src/sys/amd64/include/kdb.h,v 1.4 2007/06/09 21:55:16 marcel Exp $
*/
#ifndef _MACHINE_KDB_H_
@@ -32,6 +32,8 @@
#include <machine/frame.h>
#include <machine/psl.h>
+#define KDB_STOPPEDPCB(pc) &stoppcbs[pc->pc_cpuid]
+
static __inline void
kdb_cpu_clear_singlestep(void)
{
@@ -45,6 +47,11 @@
}
static __inline void
+kdb_cpu_sync_icache(unsigned char *addr, size_t size)
+{
+}
+
+static __inline void
kdb_cpu_trap(int type, int code)
{
}
Index: legacyvar.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/legacyvar.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/legacyvar.h -L sys/amd64/include/legacyvar.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/legacyvar.h
+++ sys/amd64/include/legacyvar.h
@@ -23,19 +23,21 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/amd64/include/legacyvar.h,v 1.6.2.1 2005/09/18 02:55:10 imp Exp $
+ * $FreeBSD: src/sys/amd64/include/legacyvar.h,v 1.8 2007/09/30 11:05:13 marius Exp $
*/
#ifndef _MACHINE_LEGACYVAR_H_
#define _MACHINE_LEGACYVAR_H_
enum legacy_device_ivars {
+ LEGACY_IVAR_PCIDOMAIN,
LEGACY_IVAR_PCIBUS
};
#define LEGACY_ACCESSOR(var, ivar, type) \
__BUS_ACCESSOR(legacy, var, LEGACY, ivar, type)
+LEGACY_ACCESSOR(pcidomain, PCIDOMAIN, uint32_t)
LEGACY_ACCESSOR(pcibus, PCIBUS, uint32_t)
#undef LEGACY_ACCESSOR
Index: pmap.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/pmap.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/pmap.h -L sys/amd64/include/pmap.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/pmap.h
+++ sys/amd64/include/pmap.h
@@ -39,14 +39,14 @@
*
* from: hp300: @(#)pmap.h 7.2 (Berkeley) 12/16/90
* from: @(#)pmap.h 7.4 (Berkeley) 5/12/91
- * $FreeBSD: src/sys/amd64/include/pmap.h,v 1.127 2005/06/29 22:28:45 peter Exp $
+ * $FreeBSD: src/sys/amd64/include/pmap.h,v 1.138 2006/12/05 11:31:33 ru Exp $
*/
#ifndef _MACHINE_PMAP_H_
#define _MACHINE_PMAP_H_
/*
- * Page-directory and page-table entires follow this format, with a few
+ * Page-directory and page-table entries follow this format, with a few
* of the fields not present here and there, depending on a lot of things.
*/
/* ---- Intel Nomenclature ---- */
@@ -58,10 +58,12 @@
#define PG_A 0x020 /* A Accessed */
#define PG_M 0x040 /* D Dirty */
#define PG_PS 0x080 /* PS Page size (0=4k,1=4M) */
+#define PG_PTE_PAT 0x080 /* PAT PAT index */
#define PG_G 0x100 /* G Global */
#define PG_AVAIL1 0x200 /* / Available for system */
#define PG_AVAIL2 0x400 /* < programmers use */
#define PG_AVAIL3 0x800 /* \ */
+#define PG_PDE_PAT 0x1000 /* PAT PAT index */
#define PG_NX (1ul<<63) /* No-execute */
@@ -69,6 +71,7 @@
#define PG_W PG_AVAIL1 /* "Wired" pseudoflag */
#define PG_MANAGED PG_AVAIL2
#define PG_FRAME (0x000ffffffffff000ul)
+#define PG_PS_FRAME (0x000fffffffe00000ul)
#define PG_PROT (PG_RW|PG_U) /* all protection bits . */
#define PG_N (PG_NC_PWT|PG_NC_PCD) /* Non-cacheable */
@@ -79,6 +82,8 @@
#define PGEX_P 0x01 /* Protection violation vs. not present */
#define PGEX_W 0x02 /* during a Write cycle */
#define PGEX_U 0x04 /* access from User mode (UPL) */
+#define PGEX_RSV 0x08 /* reserved PTE field is non-zero */
+#define PGEX_I 0x10 /* during an instruction fetch */
/*
* Pte related macros. This is complicated by having to deal with
@@ -97,9 +102,10 @@
((unsigned long)(l2) << PDRSHIFT) | \
((unsigned long)(l1) << PAGE_SHIFT))
-/* Initial number of kernel page tables */
+/* Initial number of kernel page tables. */
#ifndef NKPT
-#define NKPT 240 /* Enough for 16GB (2MB page tables) */
+/* 240 page tables needed to map 16G (120B "struct vm_page", 2M page tables). */
+#define NKPT 240
#endif
#define NKPML4E 1 /* number of kernel PML4 slots */
@@ -171,13 +177,11 @@
#ifdef _KERNEL
/*
* virtual address to page table entry and
- * to physical address. Likewise for alternate address space.
+ * to physical address.
* Note: these work recursively, thus vtopte of a pte will give
* the corresponding pde that in turn maps it.
*/
pt_entry_t *vtopte(vm_offset_t);
-vm_paddr_t pmap_kextract(vm_offset_t);
-
#define vtophys(va) pmap_kextract(((vm_offset_t) (va)))
static __inline pt_entry_t
@@ -224,6 +228,7 @@
* Pmap stuff
*/
struct pv_entry;
+struct pv_chunk;
struct md_page {
int pv_list_count;
@@ -233,7 +238,7 @@
struct pmap {
struct mtx pm_mtx;
pml4_entry_t *pm_pml4; /* KVA of level 4 page table */
- TAILQ_HEAD(,pv_entry) pm_pvlist; /* list of mappings in pmap */
+ TAILQ_HEAD(,pv_chunk) pm_pvchunk; /* list of mappings in pmap */
u_int pm_active; /* active on cpus */
/* spare u_int here due to padding */
struct pmap_statistics pm_stats; /* pmap statistics */
@@ -259,15 +264,27 @@
/*
* For each vm_page_t, there is a list of all currently valid virtual
- * mappings of that page. An entry is a pv_entry_t, the list is pv_table.
+ * mappings of that page. An entry is a pv_entry_t, the list is pv_list.
*/
typedef struct pv_entry {
- pmap_t pv_pmap; /* pmap where mapping lies */
vm_offset_t pv_va; /* virtual address for mapping */
TAILQ_ENTRY(pv_entry) pv_list;
- TAILQ_ENTRY(pv_entry) pv_plist;
} *pv_entry_t;
+/*
+ * pv_entries are allocated in chunks per-process. This avoids the
+ * need to track per-pmap assignments.
+ */
+#define _NPCM 3
+#define _NPCPV 168
+struct pv_chunk {
+ pmap_t pc_pmap;
+ TAILQ_ENTRY(pv_chunk) pc_list;
+ uint64_t pc_map[_NPCM]; /* bitmap; 1 = free */
+ uint64_t pc_spare[2];
+ struct pv_entry pc_pventry[_NPCPV];
+};
+
#ifdef _KERNEL
#define NPPROVMTRR 8
@@ -280,23 +297,30 @@
extern caddr_t CADDR1;
extern pt_entry_t *CMAP1;
-extern vm_paddr_t avail_end;
extern vm_paddr_t phys_avail[];
extern vm_paddr_t dump_avail[];
extern vm_offset_t virtual_avail;
extern vm_offset_t virtual_end;
#define pmap_page_is_mapped(m) (!TAILQ_EMPTY(&(m)->md.pv_list))
+#define pmap_unmapbios(va, sz) pmap_unmapdev((va), (sz))
void pmap_bootstrap(vm_paddr_t *);
+int pmap_change_attr(vm_offset_t, vm_size_t, int);
+void pmap_init_pat(void);
void pmap_kenter(vm_offset_t va, vm_paddr_t pa);
+void pmap_kenter_attr(vm_offset_t va, vm_paddr_t pa, int mode);
void *pmap_kenter_temporary(vm_paddr_t pa, int i);
+vm_paddr_t pmap_kextract(vm_offset_t);
void pmap_kremove(vm_offset_t);
+void *pmap_mapbios(vm_paddr_t, vm_size_t);
void *pmap_mapdev(vm_paddr_t, vm_size_t);
+void *pmap_mapdev_attr(vm_paddr_t, vm_size_t, int);
void pmap_unmapdev(vm_offset_t, vm_size_t);
void pmap_invalidate_page(pmap_t, vm_offset_t);
void pmap_invalidate_range(pmap_t, vm_offset_t, vm_offset_t);
void pmap_invalidate_all(pmap_t);
+void pmap_invalidate_cache(void);
#endif /* _KERNEL */
Index: pcpu.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/pcpu.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/pcpu.h -L sys/amd64/include/pcpu.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/pcpu.h
+++ sys/amd64/include/pcpu.h
@@ -23,14 +23,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/amd64/include/pcpu.h,v 1.44 2005/03/11 22:16:09 peter Exp $
+ * $FreeBSD: src/sys/amd64/include/pcpu.h,v 1.48 2007/06/04 21:38:45 attilio Exp $
*/
#ifndef _MACHINE_PCPU_H_
-#define _MACHINE_PCPU_H_
+#define _MACHINE_PCPU_H_
#ifndef _SYS_CDEFS_H_
-#error this file needs sys/cdefs.h as a prerequisite
+#error "sys/cdefs.h is a prerequisite for this file"
#endif
#ifdef _KERNEL
@@ -51,16 +51,17 @@
u_int pc_apic_id; \
u_int pc_acpi_id /* ACPI CPU id */
-#if defined(lint)
-
+#ifdef lint
+
extern struct pcpu *pcpup;
-
-#define PCPU_GET(member) (pcpup->pc_ ## member)
-#define PCPU_PTR(member) (&pcpup->pc_ ## member)
-#define PCPU_SET(member,value) (pcpup->pc_ ## member = (value))
-
-#elif defined(__GNUCLIKE_ASM) && defined(__GNUCLIKE___TYPEOF) \
- && defined(__GNUCLIKE___OFFSETOF)
+
+#define PCPU_GET(member) (pcpup->pc_ ## member)
+#define PCPU_ADD(member, val) (pcpup->pc_ ## member += (val))
+#define PCPU_INC(member) PCPU_ADD(member, 1)
+#define PCPU_PTR(member) (&pcpup->pc_ ## member)
+#define PCPU_SET(member, val) (pcpup->pc_ ## member = (val))
+
+#elif defined(__GNUCLIKE_ASM) && defined(__GNUCLIKE___TYPEOF)
/*
* Evaluates to the byte offset of the per-cpu variable name.
@@ -92,75 +93,96 @@
* Evaluates to the value of the per-cpu variable name.
*/
#define __PCPU_GET(name) __extension__ ({ \
- __pcpu_type(name) __result; \
+ __pcpu_type(name) __res; \
+ struct __s { \
+ u_char __b[MIN(sizeof(__pcpu_type(name)), 8)]; \
+ } __s; \
\
- if (sizeof(__result) == 1) { \
- u_char __b; \
- __asm __volatile("movb %%gs:%1,%0" \
- : "=r" (__b) \
- : "m" (*(u_char *)(__pcpu_offset(name)))); \
- __result = *(__pcpu_type(name) *)&__b; \
- } else if (sizeof(__result) == 2) { \
- u_short __w; \
- __asm __volatile("movw %%gs:%1,%0" \
- : "=r" (__w) \
- : "m" (*(u_short *)(__pcpu_offset(name)))); \
- __result = *(__pcpu_type(name) *)&__w; \
- } else if (sizeof(__result) == 4) { \
- u_int __i; \
- __asm __volatile("movl %%gs:%1,%0" \
- : "=r" (__i) \
- : "m" (*(u_int *)(__pcpu_offset(name)))); \
- __result = *(__pcpu_type(name) *)&__i; \
- } else if (sizeof(__result) == 8) { \
- u_long __l; \
- __asm __volatile("movq %%gs:%1,%0" \
- : "=r" (__l) \
- : "m" (*(u_long *)(__pcpu_offset(name)))); \
- __result = *(__pcpu_type(name) *)&__l; \
+ if (sizeof(__res) == 1 || sizeof(__res) == 2 || \
+ sizeof(__res) == 4 || sizeof(__res) == 8) { \
+ __asm __volatile("mov %%gs:%1,%0" \
+ : "=r" (__s) \
+ : "m" (*(struct __s *)(__pcpu_offset(name)))); \
+ *(struct __s *)(void *)&__res = __s; \
} else { \
- __result = *__PCPU_PTR(name); \
+ __res = *__PCPU_PTR(name); \
} \
- \
- __result; \
+ __res; \
})
/*
+ * Adds the value to the per-cpu counter name. The implementation
+ * must be atomic with respect to interrupts.
+ */
+#define __PCPU_ADD(name, val) do { \
+ __pcpu_type(name) __val; \
+ struct __s { \
+ u_char __b[MIN(sizeof(__pcpu_type(name)), 8)]; \
+ } __s; \
+ \
+ __val = (val); \
+ if (sizeof(__val) == 1 || sizeof(__val) == 2 || \
+ sizeof(__val) == 4 || sizeof(__val) == 8) { \
+ __s = *(struct __s *)(void *)&__val; \
+ __asm __volatile("add %1,%%gs:%0" \
+ : "=m" (*(struct __s *)(__pcpu_offset(name))) \
+ : "r" (__s)); \
+ } else \
+ *__PCPU_PTR(name) += __val; \
+} while (0)
+
+/*
+ * Increments the value of the per-cpu counter name. The implementation
+ * must be atomic with respect to interrupts.
+ */
+#define __PCPU_INC(name) do { \
+ CTASSERT(sizeof(__pcpu_type(name)) == 1 || \
+ sizeof(__pcpu_type(name)) == 2 || \
+ sizeof(__pcpu_type(name)) == 4 || \
+ sizeof(__pcpu_type(name)) == 8); \
+ if (sizeof(__pcpu_type(name)) == 1) { \
+ __asm __volatile("incb %%gs:%0" \
+ : "=m" (*(__pcpu_type(name) *)(__pcpu_offset(name)))\
+ : "m" (*(__pcpu_type(name) *)(__pcpu_offset(name))));\
+ } else if (sizeof(__pcpu_type(name)) == 2) { \
+ __asm __volatile("incw %%gs:%0" \
+ : "=m" (*(__pcpu_type(name) *)(__pcpu_offset(name)))\
+ : "m" (*(__pcpu_type(name) *)(__pcpu_offset(name))));\
+ } else if (sizeof(__pcpu_type(name)) == 4) { \
+ __asm __volatile("incl %%gs:%0" \
+ : "=m" (*(__pcpu_type(name) *)(__pcpu_offset(name)))\
+ : "m" (*(__pcpu_type(name) *)(__pcpu_offset(name))));\
+ } else if (sizeof(__pcpu_type(name)) == 8) { \
+ __asm __volatile("incq %%gs:%0" \
+ : "=m" (*(__pcpu_type(name) *)(__pcpu_offset(name)))\
+ : "m" (*(__pcpu_type(name) *)(__pcpu_offset(name))));\
+ } \
+} while (0)
+
+/*
* Sets the value of the per-cpu variable name to value val.
*/
#define __PCPU_SET(name, val) { \
- __pcpu_type(name) __val = (val); \
+ __pcpu_type(name) __val; \
+ struct __s { \
+ u_char __b[MIN(sizeof(__pcpu_type(name)), 8)]; \
+ } __s; \
\
- if (sizeof(__val) == 1) { \
- u_char __b; \
- __b = *(u_char *)&__val; \
- __asm __volatile("movb %1,%%gs:%0" \
- : "=m" (*(u_char *)(__pcpu_offset(name))) \
- : "r" (__b)); \
- } else if (sizeof(__val) == 2) { \
- u_short __w; \
- __w = *(u_short *)&__val; \
- __asm __volatile("movw %1,%%gs:%0" \
- : "=m" (*(u_short *)(__pcpu_offset(name))) \
- : "r" (__w)); \
- } else if (sizeof(__val) == 4) { \
- u_int __i; \
- __i = *(u_int *)&__val; \
- __asm __volatile("movl %1,%%gs:%0" \
- : "=m" (*(u_int *)(__pcpu_offset(name))) \
- : "r" (__i)); \
- } else if (sizeof(__val) == 8) { \
- u_long __l; \
- __l = *(u_long *)&__val; \
- __asm __volatile("movq %1,%%gs:%0" \
- : "=m" (*(u_long *)(__pcpu_offset(name))) \
- : "r" (__l)); \
+ __val = (val); \
+ if (sizeof(__val) == 1 || sizeof(__val) == 2 || \
+ sizeof(__val) == 4 || sizeof(__val) == 8) { \
+ __s = *(struct __s *)(void *)&__val; \
+ __asm __volatile("mov %1,%%gs:%0" \
+ : "=m" (*(struct __s *)(__pcpu_offset(name))) \
+ : "r" (__s)); \
} else { \
*__PCPU_PTR(name) = __val; \
} \
}
#define PCPU_GET(member) __PCPU_GET(pc_ ## member)
+#define PCPU_ADD(member, val) __PCPU_ADD(pc_ ## member, val)
+#define PCPU_INC(member) __PCPU_INC(pc_ ## member)
#define PCPU_PTR(member) __PCPU_PTR(pc_ ## member)
#define PCPU_SET(member, val) __PCPU_SET(pc_ ## member, val)
@@ -172,12 +194,14 @@
__asm __volatile("movq %%gs:0,%0" : "=r" (td));
return (td);
}
-#define curthread (__curthread())
+#define curthread (__curthread())
-#else
-#error this file needs to be ported to your compiler
-#endif
+#else /* !lint || defined(__GNUCLIKE_ASM) && defined(__GNUCLIKE___TYPEOF) */
+
+#error "this file needs to be ported to your compiler"
+
+#endif /* lint, etc. */
-#endif /* _KERNEL */
+#endif /* _KERNEL */
-#endif /* ! _MACHINE_PCPU_H_ */
+#endif /* !_MACHINE_PCPU_H_ */
Index: elf.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/elf.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/elf.h -L sys/amd64/include/elf.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/elf.h
+++ sys/amd64/include/elf.h
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/amd64/include/elf.h,v 1.18 2004/08/03 08:21:48 dfr Exp $
+ * $FreeBSD: src/sys/amd64/include/elf.h,v 1.19 2006/10/04 21:37:09 jb Exp $
*/
#ifndef _MACHINE_ELF_H_
@@ -108,31 +108,6 @@
* Relocation types.
*/
-#define R_X86_64_NONE 0 /* No relocation. */
-#define R_X86_64_64 1 /* Add 64 bit symbol value. */
-#define R_X86_64_PC32 2 /* PC-relative 32 bit signed sym value. */
-#define R_X86_64_GOT32 3 /* PC-relative 32 bit GOT offset. */
-#define R_X86_64_PLT32 4 /* PC-relative 32 bit PLT offset. */
-#define R_X86_64_COPY 5 /* Copy data from shared object. */
-#define R_X86_64_GLOB_DAT 6 /* Set GOT entry to data address. */
-#define R_X86_64_JMP_SLOT 7 /* Set GOT entry to code address. */
-#define R_X86_64_RELATIVE 8 /* Add load address of shared object. */
-#define R_X86_64_GOTPCREL 9 /* Add 32 bit signed pcrel offset to GOT. */
-#define R_X86_64_32 10 /* Add 32 bit zero extended symbol value */
-#define R_X86_64_32S 11 /* Add 32 bit sign extended symbol value */
-#define R_X86_64_16 12 /* Add 16 bit zero extended symbol value */
-#define R_X86_64_PC16 13 /* Add 16 bit signed extended pc relative symbol value */
-#define R_X86_64_8 14 /* Add 8 bit zero extended symbol value */
-#define R_X86_64_PC8 15 /* Add 8 bit signed extended pc relative symbol value */
-#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */
-#define R_X86_64_DTPOFF64 17 /* Offset in TLS block */
-#define R_X86_64_TPOFF64 18 /* Offset in static TLS block */
-#define R_X86_64_TLSGD 19 /* PC relative offset to GD GOT entry */
-#define R_X86_64_TLSLD 20 /* PC relative offset to LD GOT entry */
-#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */
-#define R_X86_64_GOTTPOFF 22 /* PC relative offset to IE GOT entry */
-#define R_X86_64_TPOFF32 23 /* Offset in static TLS block */
-
#define R_X86_64_COUNT 24 /* Count of defined relocation types. */
/* Define "machine" characteristics */
Index: vmparam.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/vmparam.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/vmparam.h -L sys/amd64/include/vmparam.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/vmparam.h
+++ sys/amd64/include/vmparam.h
@@ -38,7 +38,7 @@
* SUCH DAMAGE.
*
* from: @(#)vmparam.h 5.9 (Berkeley) 5/12/91
- * $FreeBSD: src/sys/amd64/include/vmparam.h,v 1.45 2004/10/27 17:21:15 peter Exp $
+ * $FreeBSD: src/sys/amd64/include/vmparam.h,v 1.49 2007/09/25 06:25:04 alc Exp $
*/
@@ -88,6 +88,50 @@
#define UMA_MD_SMALL_ALLOC
/*
+ * The physical address space is densely populated.
+ */
+#define VM_PHYSSEG_DENSE
+
+/*
+ * The number of PHYSSEG entries must be one greater than the number
+ * of phys_avail entries because the phys_avail entry that spans the
+ * largest physical address that is accessible by ISA DMA is split
+ * into two PHYSSEG entries.
+ */
+#define VM_PHYSSEG_MAX 31
+
+/*
+ * Create three free page pools: VM_FREEPOOL_DEFAULT is the default pool
+ * from which physical pages are allocated and VM_FREEPOOL_DIRECT is
+ * the pool from which physical pages for page tables and small UMA
+ * objects are allocated.
+ */
+#define VM_NFREEPOOL 3
+#define VM_FREEPOOL_CACHE 2
+#define VM_FREEPOOL_DEFAULT 0
+#define VM_FREEPOOL_DIRECT 1
+
+/*
+ * Create two free page lists: VM_FREELIST_DEFAULT is for physical
+ * pages that are above the largest physical address that is
+ * accessible by ISA DMA and VM_FREELIST_ISADMA is for physical pages
+ * that are below that address.
+ */
+#define VM_NFREELIST 2
+#define VM_FREELIST_DEFAULT 0
+#define VM_FREELIST_ISADMA 1
+
+/*
+ * An allocation size of 16MB is supported in order to optimize the
+ * use of the direct map by UMA. Specifically, a cache line contains
+ * at most 8 PDEs, collectively mapping 16MB of physical memory. By
+ * reducing the number of distinct 16MB "pages" that are used by UMA,
+ * the physical memory allocator reduces the likelihood of both 2MB
+ * page TLB misses and cache misses caused by 2MB page TLB misses.
+ */
+#define VM_NFREEORDER 13
+
+/*
* Virtual addresses of things. Derived from the page directory and
* page table indexes from pmap.h for precision.
* Because of the page that is both a PD and PT, it looks a little
@@ -122,7 +166,8 @@
/*
* How many physical pages per KVA page allocated.
- * min(max(VM_KMEM_SIZE, Physical memory/VM_KMEM_SIZE_SCALE), VM_KMEM_SIZE_MAX)
+ * min(max(max(VM_KMEM_SIZE, Physical memory/VM_KMEM_SIZE_SCALE),
+ * VM_KMEM_SIZE_MIN), VM_KMEM_SIZE_MAX)
* is the total KVA space allocated for kmem_map.
*/
#ifndef VM_KMEM_SIZE_SCALE
Index: apicvar.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/apicvar.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/amd64/include/apicvar.h -L sys/amd64/include/apicvar.h -u -r1.2 -r1.3
--- sys/amd64/include/apicvar.h
+++ sys/amd64/include/apicvar.h
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/amd64/include/apicvar.h,v 1.13.2.2 2006/03/07 18:33:20 jhb Exp $
+ * $FreeBSD: src/sys/amd64/include/apicvar.h,v 1.25 2007/05/08 22:01:03 jhb Exp $
*/
#ifndef _MACHINE_APICVAR_H_
@@ -79,6 +79,7 @@
* I/O device!
*/
+#define MAX_APIC_ID 0xfe
#define APIC_ID_ALL 0xff
/* I/O Interrupts are used for external devices such as ISA, PCI, etc. */
@@ -118,8 +119,9 @@
#define IPI_INVLTLB (APIC_IPI_INTS + 1) /* TLB Shootdown IPIs */
#define IPI_INVLPG (APIC_IPI_INTS + 2)
#define IPI_INVLRNG (APIC_IPI_INTS + 3)
+#define IPI_INVLCACHE (APIC_IPI_INTS + 4)
/* Vector to handle bitmap based IPIs */
-#define IPI_BITMAP_VECTOR (APIC_IPI_INTS + 5)
+#define IPI_BITMAP_VECTOR (APIC_IPI_INTS + 6)
/* IPIs handled by IPI_BITMAPED_VECTOR (XXX ups is there a better place?) */
#define IPI_AST 0 /* Generate software trap. */
@@ -127,7 +129,7 @@
#define IPI_BITMAP_LAST IPI_PREEMPT
#define IPI_IS_BITMAPED(x) ((x) <= IPI_BITMAP_LAST)
-#define IPI_STOP (APIC_IPI_INTS + 6) /* Stop CPU until restarted. */
+#define IPI_STOP (APIC_IPI_INTS + 7) /* Stop CPU until restarted. */
/*
* The spurious interrupt can share the priority class with the IPIs since
@@ -173,12 +175,16 @@
IDTVEC(apic_isr4), IDTVEC(apic_isr5), IDTVEC(apic_isr6),
IDTVEC(apic_isr7), IDTVEC(spuriousint), IDTVEC(timerint);
+extern vm_paddr_t lapic_paddr;
+
u_int apic_alloc_vector(u_int irq);
+u_int apic_alloc_vectors(u_int *irqs, u_int count, u_int align);
+void apic_disable_vector(u_int vector);
void apic_enable_vector(u_int vector);
void apic_free_vector(u_int vector, u_int irq);
u_int apic_idt_to_irq(u_int vector);
void apic_register_enumerator(struct apic_enumerator *enumerator);
-void *ioapic_create(uintptr_t addr, int32_t id, int intbase);
+void *ioapic_create(vm_paddr_t addr, int32_t apic_id, int intbase);
int ioapic_disable_pin(void *cookie, u_int pin);
int ioapic_get_vector(void *cookie, u_int pin);
void ioapic_register(void *cookie);
@@ -195,13 +201,13 @@
void lapic_dump(const char *str);
void lapic_eoi(void);
int lapic_id(void);
-void lapic_init(uintptr_t addr);
+void lapic_init(vm_paddr_t addr);
int lapic_intr_pending(u_int vector);
void lapic_ipi_raw(register_t icrlo, u_int dest);
void lapic_ipi_vectored(u_int vector, int dest);
int lapic_ipi_wait(int delay);
-void lapic_handle_intr(void *cookie, struct intrframe frame);
-void lapic_handle_timer(struct clockframe frame);
+void lapic_handle_intr(int vector, struct trapframe *frame);
+void lapic_handle_timer(struct trapframe *frame);
void lapic_set_logical_id(u_int apic_id, u_int cluster, u_int cluster_id);
int lapic_set_lvt_mask(u_int apic_id, u_int lvt, u_char masked);
int lapic_set_lvt_mode(u_int apic_id, u_int lvt, u_int32_t mode);
@@ -210,7 +216,7 @@
int lapic_set_lvt_triggermode(u_int apic_id, u_int lvt,
enum intr_trigger trigger);
void lapic_set_tpr(u_int vector);
-void lapic_setup(void);
+void lapic_setup(int boot);
int lapic_setup_clock(void);
#endif /* !LOCORE */
Index: clock.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/clock.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/clock.h -L sys/amd64/include/clock.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/clock.h
+++ sys/amd64/include/clock.h
@@ -3,7 +3,7 @@
* Garrett Wollman, September 1994.
* This file is in the public domain.
*
- * $FreeBSD: src/sys/amd64/include/clock.h,v 1.50 2005/01/05 20:17:20 imp Exp $
+ * $FreeBSD: src/sys/amd64/include/clock.h,v 1.54.2.1 2007/10/29 22:26:33 peter Exp $
*/
#ifndef _MACHINE_CLOCK_H_
@@ -14,9 +14,7 @@
* i386 to clock driver interface.
* XXX large parts of the driver and its interface are misplaced.
*/
-extern int adjkerntz;
extern int clkintr_pending;
-extern int disable_rtc_set;
extern int pscnt;
extern int psdiv;
extern int statclock_disable;
@@ -24,16 +22,17 @@
extern int timer0_max_count;
extern uint64_t tsc_freq;
extern int tsc_is_broken;
-extern int wall_cmos_clock;
+
+void i8254_init(void);
/*
* Driver to clock driver interface.
*/
-struct clockframe;
int acquire_timer2(int mode);
int release_timer2(void);
-int rtcin(int val);
+int rtcin(int reg);
+void writertc(int reg, unsigned char val);
int sysbeep(int pitch, int period);
void init_TSC(void);
void init_TSC_tc(void);
Index: pcb.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/pcb.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/pcb.h -L sys/amd64/include/pcb.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/pcb.h
+++ sys/amd64/include/pcb.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)pcb.h 5.10 (Berkeley) 5/12/91
- * $FreeBSD: src/sys/amd64/include/pcb.h,v 1.60.8.1 2005/11/15 00:26:00 peter Exp $
+ * $FreeBSD: src/sys/amd64/include/pcb.h,v 1.63 2007/03/30 00:06:21 jkim Exp $
*/
#ifndef _AMD64_PCB_H_
@@ -41,9 +41,9 @@
* AMD64 process control block
*/
#include <machine/fpu.h>
+#include <machine/segments.h>
struct pcb {
- register_t __pad0[8]; /* Spare */
register_t pcb_cr3;
register_t pcb_r15;
register_t pcb_r14;
@@ -53,7 +53,6 @@
register_t pcb_rsp;
register_t pcb_rbx;
register_t pcb_rip;
- register_t __pad1; /* Spare */
register_t pcb_fsbase;
register_t pcb_gsbase;
u_int32_t pcb_ds;
@@ -75,6 +74,10 @@
#define PCB_FULLCTX 0x80 /* full context restore on sysret */
caddr_t pcb_onfault; /* copyin/out fault recovery */
+
+ /* 32-bit segment descriptor */
+ struct user_segment_descriptor *pcb_gs32p;
+ struct user_segment_descriptor pcb_gs32sd;
};
#ifdef _KERNEL
--- /dev/null
+++ sys/amd64/include/minidump.h
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2006 Peter Wemm
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/amd64/include/minidump.h,v 1.1 2006/04/21 04:24:50 peter Exp $
+ */
+
+#ifndef _MACHINE_MINIDUMP_H_
+#define _MACHINE_MINIDUMP_H_ 1
+
+#define MINIDUMP_MAGIC "minidump FreeBSD/amd64"
+#define MINIDUMP_VERSION 1
+
+struct minidumphdr {
+ char magic[24];
+ uint32_t version;
+ uint32_t msgbufsize;
+ uint32_t bitmapsize;
+ uint32_t ptesize;
+ uint64_t kernbase;
+ uint64_t dmapbase;
+ uint64_t dmapend;
+};
+
+#endif /* _MACHINE_MINIDUMP_H_ */
Index: frame.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/frame.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/frame.h -L sys/amd64/include/frame.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/frame.h
+++ sys/amd64/include/frame.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)frame.h 5.2 (Berkeley) 1/18/91
- * $FreeBSD: src/sys/amd64/include/frame.h,v 1.28 2004/07/10 22:39:56 marcel Exp $
+ * $FreeBSD: src/sys/amd64/include/frame.h,v 1.30 2005/12/22 22:16:05 jhb Exp $
*/
#ifndef _MACHINE_FRAME_H_
@@ -76,64 +76,4 @@
register_t tf_ss;
};
-/* Interrupt stack frame */
-
-struct intrframe {
- register_t if_rdi;
- register_t if_rsi;
- register_t if_rdx;
- register_t if_rcx;
- register_t if_r8;
- register_t if_r9;
- register_t if_rax;
- register_t if_rbx;
- register_t if_rbp;
- register_t if_r10;
- register_t if_r11;
- register_t if_r12;
- register_t if_r13;
- register_t if_r14;
- register_t if_r15;
- register_t :64; /* compat with trap frame - trapno */
- register_t :64; /* compat with trap frame - addr */
- register_t :64; /* compat with trap frame - flags */
- register_t :64; /* compat with trap frame - err */
- /* below portion defined in hardware */
- register_t if_rip;
- register_t if_cs;
- register_t if_rflags;
- register_t if_rsp;
- register_t if_ss;
-};
-
-/* frame of clock (same as interrupt frame) */
-
-struct clockframe {
- register_t cf_rdi;
- register_t cf_rsi;
- register_t cf_rdx;
- register_t cf_rcx;
- register_t cf_r8;
- register_t cf_r9;
- register_t cf_rax;
- register_t cf_rbx;
- register_t cf_rbp;
- register_t cf_r10;
- register_t cf_r11;
- register_t cf_r12;
- register_t cf_r13;
- register_t cf_r14;
- register_t cf_r15;
- register_t :64; /* compat with trap frame - trapno */
- register_t :64; /* compat with trap frame - addr */
- register_t :64; /* compat with trap frame - flags */
- register_t :64; /* compat with trap frame - err */
- /* below portion defined in hardware */
- register_t cf_rip;
- register_t cf_cs;
- register_t cf_rflags;
- register_t cf_rsp;
- register_t cf_ss;
-};
-
#endif /* _MACHINE_FRAME_H_ */
Index: atomic.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/atomic.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/atomic.h -L sys/amd64/include/atomic.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/atomic.h
+++ sys/amd64/include/atomic.h
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/amd64/include/atomic.h,v 1.34.2.4 2005/10/06 18:12:05 jhb Exp $
+ * $FreeBSD: src/sys/amd64/include/atomic.h,v 1.44 2006/12/29 15:29:49 bde Exp $
*/
#ifndef _MACHINE_ATOMIC_H_
#define _MACHINE_ATOMIC_H_
@@ -33,30 +33,30 @@
#endif
/*
- * Various simple arithmetic on memory which is atomic in the presence
- * of interrupts and multiple processors.
+ * Various simple operations on memory, each of which is atomic in the
+ * presence of interrupts and multiple processors.
*
- * atomic_set_char(P, V) (*(u_char*)(P) |= (V))
- * atomic_clear_char(P, V) (*(u_char*)(P) &= ~(V))
- * atomic_add_char(P, V) (*(u_char*)(P) += (V))
- * atomic_subtract_char(P, V) (*(u_char*)(P) -= (V))
+ * atomic_set_char(P, V) (*(u_char *)(P) |= (V))
+ * atomic_clear_char(P, V) (*(u_char *)(P) &= ~(V))
+ * atomic_add_char(P, V) (*(u_char *)(P) += (V))
+ * atomic_subtract_char(P, V) (*(u_char *)(P) -= (V))
*
- * atomic_set_short(P, V) (*(u_short*)(P) |= (V))
- * atomic_clear_short(P, V) (*(u_short*)(P) &= ~(V))
- * atomic_add_short(P, V) (*(u_short*)(P) += (V))
- * atomic_subtract_short(P, V) (*(u_short*)(P) -= (V))
+ * atomic_set_short(P, V) (*(u_short *)(P) |= (V))
+ * atomic_clear_short(P, V) (*(u_short *)(P) &= ~(V))
+ * atomic_add_short(P, V) (*(u_short *)(P) += (V))
+ * atomic_subtract_short(P, V) (*(u_short *)(P) -= (V))
*
- * atomic_set_int(P, V) (*(u_int*)(P) |= (V))
- * atomic_clear_int(P, V) (*(u_int*)(P) &= ~(V))
- * atomic_add_int(P, V) (*(u_int*)(P) += (V))
- * atomic_subtract_int(P, V) (*(u_int*)(P) -= (V))
- * atomic_readandclear_int(P) (return *(u_int*)P; *(u_int*)P = 0;)
+ * atomic_set_int(P, V) (*(u_int *)(P) |= (V))
+ * atomic_clear_int(P, V) (*(u_int *)(P) &= ~(V))
+ * atomic_add_int(P, V) (*(u_int *)(P) += (V))
+ * atomic_subtract_int(P, V) (*(u_int *)(P) -= (V))
+ * atomic_readandclear_int(P) (return (*(u_int *)(P)); *(u_int *)(P) = 0;)
*
- * atomic_set_long(P, V) (*(u_long*)(P) |= (V))
- * atomic_clear_long(P, V) (*(u_long*)(P) &= ~(V))
- * atomic_add_long(P, V) (*(u_long*)(P) += (V))
- * atomic_subtract_long(P, V) (*(u_long*)(P) -= (V))
- * atomic_readandclear_long(P) (return *(u_long*)P; *(u_long*)P = 0;)
+ * atomic_set_long(P, V) (*(u_long *)(P) |= (V))
+ * atomic_clear_long(P, V) (*(u_long *)(P) &= ~(V))
+ * atomic_add_long(P, V) (*(u_long *)(P) += (V))
+ * atomic_subtract_long(P, V) (*(u_long *)(P) -= (V))
+ * atomic_readandclear_long(P) (return (*(u_long *)(P)); *(u_long *)(P) = 0;)
*/
/*
@@ -67,26 +67,26 @@
* Kernel modules call real functions which are built into the kernel.
* This allows kernel modules to be portable between UP and SMP systems.
*/
-#if defined(KLD_MODULE) || !(defined(__GNUCLIKE_ASM) && defined(__CC_SUPPORTS___INLINE))
+#if defined(KLD_MODULE) || !defined(__GNUCLIKE_ASM)
#define ATOMIC_ASM(NAME, TYPE, OP, CONS, V) \
void atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v)
-int atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src);
-int atomic_cmpset_long(volatile u_long *dst, u_long exp, u_long src);
-u_int atomic_fetchadd_int(volatile u_int *p, u_int v);
+int atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src);
+int atomic_cmpset_long(volatile u_long *dst, u_long exp, u_long src);
+u_int atomic_fetchadd_int(volatile u_int *p, u_int v);
#define ATOMIC_STORE_LOAD(TYPE, LOP, SOP) \
u_##TYPE atomic_load_acq_##TYPE(volatile u_##TYPE *p); \
void atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v)
-#else /* !KLD_MODULE && __GNUCLIKE_ASM && __CC_SUPPORTS___INLINE */
+#else /* !KLD_MODULE && __GNUCLIKE_ASM */
/*
- * For userland, assume the SMP case and use lock prefixes so that
- * the binaries will run on both types of systems.
+ * For userland, always use lock prefixes so that the binaries will run
+ * on both SMP and !SMP systems.
*/
#if defined(SMP) || !defined(_KERNEL)
-#define MPLOCKED lock ;
+#define MPLOCKED "lock ; "
#else
#define MPLOCKED
#endif
@@ -99,9 +99,9 @@
static __inline void \
atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\
{ \
- __asm __volatile(__XSTRING(MPLOCKED) OP \
- : "=m" (*p) \
- : CONS (V), "m" (*p)); \
+ __asm __volatile(MPLOCKED OP \
+ : "=m" (*p) \
+ : CONS (V), "m" (*p)); \
} \
struct __hack
@@ -116,19 +116,19 @@
static __inline int
atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src)
{
- int res = exp;
+ u_char res;
- __asm __volatile (
- " " __XSTRING(MPLOCKED) " "
+ __asm __volatile(
+ " " MPLOCKED " "
" cmpxchgl %2,%1 ; "
- " setz %%al ; "
- " movzbl %%al,%0 ; "
+ " sete %0 ; "
"1: "
"# atomic_cmpset_int"
- : "+a" (res), /* 0 (result) */
+ : "=a" (res), /* 0 */
"=m" (*dst) /* 1 */
: "r" (src), /* 2 */
- "m" (*dst) /* 3 */
+ "a" (exp), /* 3 */
+ "m" (*dst) /* 4 */
: "memory");
return (res);
@@ -137,19 +137,19 @@
static __inline int
atomic_cmpset_long(volatile u_long *dst, u_long exp, u_long src)
{
- long res = exp;
+ u_char res;
- __asm __volatile (
- " " __XSTRING(MPLOCKED) " "
+ __asm __volatile(
+ " " MPLOCKED " "
" cmpxchgq %2,%1 ; "
- " setz %%al ; "
- " movzbq %%al,%0 ; "
+ " sete %0 ; "
"1: "
"# atomic_cmpset_long"
- : "+a" (res), /* 0 (result) */
+ : "=a" (res), /* 0 */
"=m" (*dst) /* 1 */
: "r" (src), /* 2 */
- "m" (*dst) /* 3 */
+ "a" (exp), /* 3 */
+ "m" (*dst) /* 4 */
: "memory");
return (res);
@@ -163,8 +163,8 @@
atomic_fetchadd_int(volatile u_int *p, u_int v)
{
- __asm __volatile (
- " " __XSTRING(MPLOCKED) " "
+ __asm __volatile(
+ " " MPLOCKED " "
" xaddl %0, %1 ; "
"# atomic_fetchadd_int"
: "+r" (v), /* 0 (result) */
@@ -174,17 +174,42 @@
return (v);
}
+#if defined(_KERNEL) && !defined(SMP)
+
+/*
+ * We assume that a = b will do atomic loads and stores. However, on a
+ * PentiumPro or higher, reads may pass writes, so for that case we have
+ * to use a serializing instruction (i.e. with LOCK) to do the load in
+ * SMP kernels. For UP kernels, however, the cache of the single processor
+ * is always consistent, so we don't need any memory barriers.
+ */
+#define ATOMIC_STORE_LOAD(TYPE, LOP, SOP) \
+static __inline u_##TYPE \
+atomic_load_acq_##TYPE(volatile u_##TYPE *p) \
+{ \
+ return (*p); \
+} \
+ \
+static __inline void \
+atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\
+{ \
+ *p = v; \
+} \
+struct __hack
+
+#else /* !(_KERNEL && !SMP) */
+
#define ATOMIC_STORE_LOAD(TYPE, LOP, SOP) \
static __inline u_##TYPE \
atomic_load_acq_##TYPE(volatile u_##TYPE *p) \
{ \
u_##TYPE res; \
\
- __asm __volatile(__XSTRING(MPLOCKED) LOP \
- : "=a" (res), /* 0 (result) */\
+ __asm __volatile(MPLOCKED LOP \
+ : "=a" (res), /* 0 */ \
"=m" (*p) /* 1 */ \
: "m" (*p) /* 2 */ \
- : "memory"); \
+ : "memory"); \
\
return (res); \
} \
@@ -202,7 +227,9 @@
} \
struct __hack
-#endif /* KLD_MODULE || !(__GNUCLIKE_ASM && __CC_SUPPORTS___INLINE) */
+#endif /* _KERNEL && !SMP */
+
+#endif /* KLD_MODULE || !__GNUCLIKE_ASM */
ATOMIC_ASM(set, char, "orb %b1,%0", "iq", v);
ATOMIC_ASM(clear, char, "andb %b1,%0", "iq", ~v);
@@ -232,49 +259,49 @@
#undef ATOMIC_ASM
#undef ATOMIC_STORE_LOAD
-#if !defined(WANT_FUNCTIONS)
+#ifndef WANT_FUNCTIONS
/* Read the current value and store a zero in the destination. */
-#if defined(__GNUCLIKE_ASM) && defined(__CC_SUPPORTS___INLINE)
+#ifdef __GNUCLIKE_ASM
static __inline u_int
atomic_readandclear_int(volatile u_int *addr)
{
- u_int result;
+ u_int res;
- result = 0;
- __asm __volatile (
+ res = 0;
+ __asm __volatile(
" xchgl %1,%0 ; "
"# atomic_readandclear_int"
- : "+r" (result), /* 0 (result) */
- "=m" (*addr) /* 1 (addr) */
+ : "+r" (res), /* 0 */
+ "=m" (*addr) /* 1 */
: "m" (*addr));
- return (result);
+ return (res);
}
static __inline u_long
atomic_readandclear_long(volatile u_long *addr)
{
- u_long result;
+ u_long res;
- result = 0;
- __asm __volatile (
+ res = 0;
+ __asm __volatile(
" xchgq %1,%0 ; "
"# atomic_readandclear_long"
- : "+r" (result), /* 0 (result) */
- "=m" (*addr) /* 1 (addr) */
+ : "+r" (res), /* 0 */
+ "=m" (*addr) /* 1 */
: "m" (*addr));
- return (result);
+ return (res);
}
-#else /* !(__GNUCLIKE_ASM && __CC_SUPPORTS___INLINE) */
+#else /* !__GNUCLIKE_ASM */
-u_int atomic_readandclear_int(volatile u_int *);
-u_long atomic_readandclear_long(volatile u_long *);
+u_int atomic_readandclear_int(volatile u_int *addr);
+u_long atomic_readandclear_long(volatile u_long *addr);
-#endif /* __GNUCLIKE_ASM && __CC_SUPPORTS___INLINE */
+#endif /* __GNUCLIKE_ASM */
/* Acquire and release variants are identical to the normal ones. */
#define atomic_set_acq_char atomic_set_char
@@ -410,5 +437,6 @@
#define atomic_cmpset_rel_ptr atomic_cmpset_rel_long
#define atomic_readandclear_ptr atomic_readandclear_long
-#endif /* !defined(WANT_FUNCTIONS) */
-#endif /* ! _MACHINE_ATOMIC_H_ */
+#endif /* !WANT_FUNCTIONS */
+
+#endif /* !_MACHINE_ATOMIC_H_ */
Index: mutex.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/mutex.h,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -L sys/amd64/include/mutex.h -L sys/amd64/include/mutex.h -u -r1.1.1.2 -r1.2
--- sys/amd64/include/mutex.h
+++ sys/amd64/include/mutex.h
@@ -26,19 +26,10 @@
* SUCH DAMAGE.
*
* from BSDI $Id: mutex.h,v 2.7.2.35 2000/04/27 03:10:26 cp Exp $
- * $FreeBSD: src/sys/amd64/include/mutex.h,v 1.38 2003/12/06 23:17:18 peter Exp $
+ * $FreeBSD: src/sys/amd64/include/mutex.h,v 1.39 2006/05/19 18:53:50 sobomax Exp $
*/
#ifndef _MACHINE_MUTEX_H_
#define _MACHINE_MUTEX_H_
-#ifndef LOCORE
-#ifdef _KERNEL
-
-/* Global locks */
-extern struct mtx clock_lock;
-
-#endif /* _KERNEL */
-
-#endif /* !LOCORE */
#endif /* __MACHINE_MUTEX_H */
Index: profile.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/profile.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/profile.h -L sys/amd64/include/profile.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/profile.h
+++ sys/amd64/include/profile.h
@@ -27,7 +27,7 @@
* SUCH DAMAGE.
*
* @(#)profile.h 8.1 (Berkeley) 6/11/93
- * $FreeBSD: src/sys/amd64/include/profile.h,v 1.45 2005/03/11 22:16:09 peter Exp $
+ * $FreeBSD: src/sys/amd64/include/profile.h,v 1.48 2006/10/28 13:12:06 bde Exp $
*/
#ifndef _MACHINE_PROFILE_H_
@@ -61,7 +61,7 @@
#define MCOUNT_OVERHEAD(label) \
__asm __volatile("pushq %0; call __mcount; popq %%rcx" \
: \
- : "i" (profil) \
+ : "i" (label) \
: "ax", "dx", "cx", "di", "si", "r8", "r9", "memory")
#define MEXITCOUNT_OVERHEAD() \
__asm __volatile("call .mexitcount; 1:" \
@@ -114,11 +114,11 @@
#ifdef __GNUCLIKE_ASM
#define MCOUNT __asm(" \n\
+ .text \n\
+ .p2align 4,0x90 \n\
.globl .mcount \n\
- .type .mcount @function \n\
+ .type .mcount, at function \n\
.mcount: \n\
- pushq %rbp \n\
- movq %rsp,%rbp \n\
pushq %rdi \n\
pushq %rsi \n\
pushq %rdx \n\
@@ -126,9 +126,8 @@
pushq %r8 \n\
pushq %r9 \n\
pushq %rax \n\
- movq 8(%rbp),%rsi \n\
- movq (%rbp),%rdi \n\
- movq 8(%rdi),%rdi \n\
+ movq 8(%rbp),%rdi \n\
+ movq 7*8(%rsp),%rsi \n\
call _mcount \n\
popq %rax \n\
popq %r9 \n\
@@ -137,7 +136,6 @@
popq %rdx \n\
popq %rsi \n\
popq %rdi \n\
- leave \n\
ret \n\
.size .mcount, . - .mcount");
#if 0
@@ -171,11 +169,7 @@
}
#endif
#else /* !__GNUCLIKE_ASM */
-#define MCOUNT \
-void \
-mcount() \
-{ \
-}
+#define MCOUNT
#endif /* __GNUCLIKE_ASM */
typedef u_long uintfptr_t;
Index: icu.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/isa/icu.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/isa/icu.h -L sys/amd64/isa/icu.h -u -r1.1.1.1 -r1.2
--- sys/amd64/isa/icu.h
+++ sys/amd64/isa/icu.h
@@ -30,7 +30,7 @@
* SUCH DAMAGE.
*
* from: @(#)icu.h 5.6 (Berkeley) 5/9/91
- * $FreeBSD: src/sys/amd64/isa/icu.h,v 1.34 2004/05/16 20:30:47 peter Exp $
+ * $FreeBSD: src/sys/amd64/isa/icu.h,v 1.36 2006/12/17 21:51:44 kmacy Exp $
*/
/*
@@ -43,7 +43,7 @@
#define ICU_IMR_OFFSET 1
-void atpic_handle_intr(void *cookie, struct intrframe iframe);
+void atpic_handle_intr(u_int vector, struct trapframe *frame);
void atpic_startup(void);
#endif /* !_AMD64_ISA_ICU_H_ */
Index: atpic_vector.S
===================================================================
RCS file: /home/cvs/src/sys/amd64/isa/atpic_vector.S,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/isa/atpic_vector.S -L sys/amd64/isa/atpic_vector.S -u -r1.1.1.1 -r1.2
--- sys/amd64/isa/atpic_vector.S
+++ sys/amd64/isa/atpic_vector.S
@@ -28,7 +28,7 @@
* SUCH DAMAGE.
*
* from: vector.s, 386BSD 0.1 unknown origin
- * $FreeBSD: src/sys/amd64/isa/atpic_vector.S,v 1.45 2004/05/24 12:08:56 bde Exp $
+ * $FreeBSD: src/sys/amd64/isa/atpic_vector.S,v 1.48 2006/12/17 06:48:40 kmacy Exp $
*/
/*
@@ -41,33 +41,16 @@
#include "assym.s"
/*
- * Macros for interrupt interrupt entry, call to handler, and exit.
+ * Macros for interrupt entry, call to handler, and exit.
*/
#define INTR(irq_num, vec_name) \
.text ; \
SUPERALIGN_TEXT ; \
IDTVEC(vec_name) ; \
- subq $TF_RIP,%rsp ; /* skip dummy tf_err and tf_trapno */ \
- testb $SEL_RPL_MASK,TF_CS(%rsp) ; /* come from kernel? */ \
- jz 1f ; /* Yes, dont swapgs again */ \
- swapgs ; \
-1: movq %rdi,TF_RDI(%rsp) ; \
- movq %rsi,TF_RSI(%rsp) ; \
- movq %rdx,TF_RDX(%rsp) ; \
- movq %rcx,TF_RCX(%rsp) ; \
- movq %r8,TF_R8(%rsp) ; \
- movq %r9,TF_R9(%rsp) ; \
- movq %rax,TF_RAX(%rsp) ; \
- movq %rbx,TF_RBX(%rsp) ; \
- movq %rbp,TF_RBP(%rsp) ; \
- movq %r10,TF_R10(%rsp) ; \
- movq %r11,TF_R11(%rsp) ; \
- movq %r12,TF_R12(%rsp) ; \
- movq %r13,TF_R13(%rsp) ; \
- movq %r14,TF_R14(%rsp) ; \
- movq %r15,TF_R15(%rsp) ; \
+ PUSH_FRAME ; \
FAKE_MCOUNT(TF_RIP(%rsp)) ; \
- movq $irq_num, %rdi; /* pass the IRQ */ \
+ movq %rsp, %rsi ; \
+ movl $irq_num, %edi; /* pass the IRQ */ \
call atpic_handle_intr ; \
MEXITCOUNT ; \
jmp doreti
Index: atpic.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/isa/atpic.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/amd64/isa/atpic.c -L sys/amd64/isa/atpic.c -u -r1.2 -r1.3
--- sys/amd64/isa/atpic.c
+++ sys/amd64/isa/atpic.c
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/isa/atpic.c,v 1.15.2.3 2006/03/10 19:37:31 jhb Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/isa/atpic.c,v 1.22 2007/05/08 21:29:13 jhb Exp $");
#include "opt_auto_eoi.h"
#include "opt_isa.h"
@@ -45,7 +45,6 @@
#include <sys/lock.h>
#include <sys/module.h>
#include <sys/mutex.h>
-#include <sys/proc.h>
#include <machine/cpufunc.h>
#include <machine/frame.h>
@@ -108,9 +107,10 @@
#define ATPIC(io, base, eoi, imenptr) \
{ { atpic_enable_source, atpic_disable_source, (eoi), \
- atpic_enable_intr, atpic_vector, atpic_source_pending, NULL, \
- atpic_resume, atpic_config_intr, atpic_assign_cpu }, (io), \
- (base), IDT_IO_INTS + (base), (imenptr) }
+ atpic_enable_intr, atpic_disable_intr, atpic_vector, \
+ atpic_source_pending, NULL, atpic_resume, atpic_config_intr,\
+ atpic_assign_cpu }, (io), (base), IDT_IO_INTS + (base), \
+ (imenptr) }
#define INTSRC(irq) \
{ { &atpics[(irq) / 8].at_pic }, IDTVEC(atpic_intr ## irq ), \
@@ -138,8 +138,9 @@
static void atpic_eoi_master(struct intsrc *isrc);
static void atpic_eoi_slave(struct intsrc *isrc);
static void atpic_enable_intr(struct intsrc *isrc);
+static void atpic_disable_intr(struct intsrc *isrc);
static int atpic_vector(struct intsrc *isrc);
-static void atpic_resume(struct intsrc *isrc);
+static void atpic_resume(struct pic *pic);
static int atpic_source_pending(struct intsrc *isrc);
static int atpic_config_intr(struct intsrc *isrc, enum intr_trigger trig,
enum intr_polarity pol);
@@ -267,6 +268,12 @@
{
}
+static void
+atpic_disable_intr(struct intsrc *isrc)
+{
+}
+
+
static int
atpic_vector(struct intsrc *isrc)
{
@@ -286,16 +293,13 @@
}
static void
-atpic_resume(struct intsrc *isrc)
+atpic_resume(struct pic *pic)
{
- struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
- struct atpic *ap = (struct atpic *)isrc->is_pic;
+ struct atpic *ap = (struct atpic *)pic;
- if (ai->at_irq == 0) {
- i8259_init(ap, ap == &atpics[SLAVE]);
- if (ap == &atpics[SLAVE] && elcr_found)
- elcr_resume();
- }
+ i8259_init(ap, ap == &atpics[SLAVE]);
+ if (ap == &atpics[SLAVE] && elcr_found)
+ elcr_resume();
}
static int
@@ -466,6 +470,14 @@
int i;
/*
+ * Register our PICs, even if we aren't going to use any of their
+ * pins so that they are suspended and resumed.
+ */
+ if (intr_register_pic(&atpics[0].at_pic) != 0 ||
+ intr_register_pic(&atpics[1].at_pic) != 0)
+ panic("Unable to register ATPICs");
+
+ /*
* If any of the ISA IRQs have an interrupt source already, then
* assume that the APICs are being used and don't register any
* of our interrupt sources. This makes sure we don't accidentally
@@ -490,19 +502,18 @@
SYSINIT(atpic_init, SI_SUB_INTR, SI_ORDER_SECOND + 1, atpic_init, NULL)
void
-atpic_handle_intr(void *cookie, struct intrframe iframe)
+atpic_handle_intr(u_int vector, struct trapframe *frame)
{
struct intsrc *isrc;
- int vec = (uintptr_t)cookie;
- KASSERT(vec < NUM_ISA_IRQS, ("unknown int %d\n", vec));
- isrc = &atintrs[vec].at_intsrc;
+ KASSERT(vector < NUM_ISA_IRQS, ("unknown int %u\n", vector));
+ isrc = &atintrs[vector].at_intsrc;
/*
* If we don't have an event, see if this is a spurious
* interrupt.
*/
- if (isrc->is_event == NULL && (vec == 7 || vec == 15)) {
+ if (isrc->is_event == NULL && (vector == 7 || vector == 15)) {
int port, isr;
/*
@@ -518,7 +529,7 @@
if ((isr & IRQ_MASK(7)) == 0)
return;
}
- intr_execute_handlers(isrc, &iframe);
+ intr_execute_handlers(isrc, frame);
}
#ifdef DEV_ISA
Index: isa.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/isa/isa.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/isa/isa.c -L sys/amd64/isa/isa.c -u -r1.1.1.1 -r1.2
--- sys/amd64/isa/isa.c
+++ sys/amd64/isa/isa.c
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/isa/isa.c,v 1.148 2005/01/21 05:56:41 peter Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/isa/isa.c,v 1.149 2007/02/23 12:18:26 piso Exp $");
/*-
* Modifications for Intel architecture by Garrett A. Wollman.
@@ -147,10 +147,11 @@
*/
int
isa_setup_intr(device_t bus, device_t child, struct resource *r, int flags,
- void (*ihand)(void *), void *arg, void **cookiep)
+ driver_filter_t *filter, void (*ihand)(void *), void *arg,
+ void **cookiep)
{
return (BUS_SETUP_INTR(device_get_parent(bus), child, r, flags,
- ihand, arg, cookiep));
+ filter, ihand, arg, cookiep));
}
int
Index: clock.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/isa/clock.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/isa/clock.c -L sys/amd64/isa/clock.c -u -r1.1.1.1 -r1.2
--- sys/amd64/isa/clock.c
+++ sys/amd64/isa/clock.c
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/isa/clock.c,v 1.221.2.1 2005/07/18 19:52:04 jhb Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/isa/clock.c,v 1.234.2.1 2007/10/29 22:26:34 peter Exp $");
/*
* Routines to handle clock hardware.
@@ -52,20 +52,26 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
+#include <sys/clock.h>
+#include <sys/conf.h>
+#include <sys/fcntl.h>
#include <sys/lock.h>
#include <sys/kdb.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/time.h>
#include <sys/timetc.h>
+#include <sys/uio.h>
#include <sys/kernel.h>
#include <sys/limits.h>
#include <sys/module.h>
+#include <sys/sched.h>
#include <sys/sysctl.h>
#include <sys/cons.h>
#include <sys/power.h>
#include <machine/clock.h>
+#include <machine/cpu.h>
#include <machine/frame.h>
#include <machine/intr_machdep.h>
#include <machine/md_var.h>
@@ -90,9 +96,7 @@
#define TIMER_DIV(x) ((timer_freq + (x) / 2) / (x))
-int adjkerntz; /* local offset from GMT in seconds */
int clkintr_pending;
-int disable_rtc_set; /* disable resettodr() if != 0 */
int pscnt = 1;
int psdiv = 1;
int statclock_disable;
@@ -102,12 +106,11 @@
u_int timer_freq = TIMER_FREQ;
int timer0_max_count;
int timer0_real_max_count;
-int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */
-struct mtx clock_lock;
#define RTC_LOCK mtx_lock_spin(&clock_lock)
#define RTC_UNLOCK mtx_unlock_spin(&clock_lock)
static int beeping = 0;
+static struct mtx clock_lock;
static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
static struct intsrc *i8254_intsrc;
static u_int32_t i8254_lastcount;
@@ -115,6 +118,7 @@
static int (*i8254_pending)(struct intsrc *);
static int i8254_ticked;
static int using_lapic_timer;
+static int rtc_reg = -1;
static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
static u_char rtc_statusb = RTCSB_24HR;
@@ -139,8 +143,8 @@
0 /* quality */
};
-static void
-clkintr(struct clockframe *frame)
+static int
+clkintr(struct trapframe *frame)
{
if (timecounter->tc_get_timecount == i8254_get_timecount) {
@@ -154,8 +158,9 @@
clkintr_pending = 0;
mtx_unlock_spin(&clock_lock);
}
- if (!using_lapic_timer)
- hardclock(frame);
+ KASSERT(!using_lapic_timer, ("clk interrupt enabled with lapic timer"));
+ hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
+ return (FILTER_HANDLED);
}
int
@@ -210,19 +215,22 @@
* Stat clock ticks can still be lost, causing minor loss of accuracy
* in the statistics, but the stat clock will no longer stop.
*/
-static void
-rtcintr(struct clockframe *frame)
+static int
+rtcintr(struct trapframe *frame)
{
+ int flag = 0;
while (rtcin(RTC_INTR) & RTCIR_PERIOD) {
+ flag = 1;
if (profprocs != 0) {
if (--pscnt == 0)
pscnt = psdiv;
- profclock(frame);
+ profclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
}
if (pscnt == psdiv)
- statclock(frame);
+ statclock(TRAPF_USERMODE(frame));
}
+ return(flag ? FILTER_HANDLED : FILTER_STRAY);
}
#include "opt_ddb.h"
@@ -269,7 +277,21 @@
int getit_calls = 1;
int n1;
static int state = 0;
+#endif
+
+ if (tsc_freq != 0 && !tsc_is_broken) {
+ uint64_t start, end, now;
+ sched_pin();
+ start = rdtsc();
+ end = start + (tsc_freq * n) / 1000000;
+ do {
+ now = rdtsc();
+ } while (now < end || (now > start && end < start));
+ sched_unpin();
+ return;
+ }
+#ifdef DELAYDEBUG
if (state == 0) {
state = 1;
for (n1 = 1; n1 <= 10000000; n1 *= 10)
@@ -280,13 +302,6 @@
printf("DELAY(%d)...", n);
#endif
/*
- * Guard against the timer being uninitialized if we are called
- * early for console i/o.
- */
- if (timer0_max_count == 0)
- set_timer_freq(timer_freq, hz);
-
- /*
* Read the counter first, so that the rest of the setup overhead is
* counted. Guess the initial overhead is 20 usec (on most systems it
* takes about 1.5 usec for each of the i/o's in getit(). The loop
@@ -407,24 +422,30 @@
u_char val;
RTC_LOCK;
- outb(IO_RTC, reg);
- inb(0x84);
+ if (rtc_reg != reg) {
+ inb(0x84);
+ outb(IO_RTC, reg);
+ rtc_reg = reg;
+ inb(0x84);
+ }
val = inb(IO_RTC + 1);
- inb(0x84);
RTC_UNLOCK;
return (val);
}
-static __inline void
-writertc(u_char reg, u_char val)
+void
+writertc(int reg, u_char val)
{
RTC_LOCK;
- inb(0x84);
- outb(IO_RTC, reg);
- inb(0x84);
+ if (rtc_reg != reg) {
+ inb(0x84);
+ outb(IO_RTC, reg);
+ rtc_reg = reg;
+ inb(0x84);
+ }
outb(IO_RTC + 1, val);
- inb(0x84); /* XXX work around wrong order in rtcin() */
+ inb(0x84);
RTC_UNLOCK;
}
@@ -539,10 +560,15 @@
mtx_unlock_spin(&clock_lock);
}
-/*
- * Initialize 8254 timer 0 early so that it can be used in DELAY().
- * XXX initialization of other timers is unintentionally left blank.
- */
+/* This is separate from startrtclock() so that it can be called early. */
+void
+i8254_init(void)
+{
+
+ mtx_init(&clock_lock, "clk", NULL, MTX_SPIN | MTX_NOPROFILE);
+ set_timer_freq(timer_freq, hz);
+}
+
void
startrtclock()
{
@@ -551,7 +577,6 @@
writertc(RTC_STATUSA, rtc_statusa);
writertc(RTC_STATUSB, RTCSB_24HR);
- set_timer_freq(timer_freq, hz);
freq = calibrate_clocks();
#ifdef CLK_CALIBRATION_LOOP
if (bootverbose) {
@@ -648,7 +673,7 @@
/* sec now contains the number of seconds, since Jan 1 1970,
in the local time zone */
- sec += tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0);
+ sec += utc_offset();
y = time_second - sec;
if (y <= -2 || y >= 2) {
@@ -661,8 +686,7 @@
return;
wrong_time:
- printf("Invalid time in real time clock.\n");
- printf("Check and reset the date immediately!\n");
+ printf("Invalid time in clock: check and reset the date!\n");
}
/*
@@ -686,7 +710,7 @@
/* Calculate local time to put in RTC */
- tm -= tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0);
+ tm -= utc_offset();
writertc(RTC_SEC, bin2bcd(tm%60)); tm /= 60; /* Write back Seconds */
writertc(RTC_MIN, bin2bcd(tm%60)); tm /= 60; /* Write back Minutes */
@@ -740,8 +764,8 @@
* timecounter to user a simpler algorithm.
*/
if (!using_lapic_timer) {
- intr_add_handler("clk", 0, (driver_intr_t *)clkintr, NULL,
- INTR_TYPE_CLK | INTR_FAST, NULL);
+ intr_add_handler("clk", 0, (driver_filter_t *)clkintr, NULL, NULL,
+ INTR_TYPE_CLK, NULL);
i8254_intsrc = intr_lookup_source(0);
if (i8254_intsrc != NULL)
i8254_pending =
@@ -774,8 +798,8 @@
/* Enable periodic interrupts from the RTC. */
rtc_statusb |= RTCSB_PINTR;
- intr_add_handler("rtc", 8, (driver_intr_t *)rtcintr, NULL,
- INTR_TYPE_CLK | INTR_FAST, NULL);
+ intr_add_handler("rtc", 8, (driver_filter_t *)rtcintr, NULL, NULL,
+ INTR_TYPE_CLK, NULL);
writertc(RTC_STATUSB, rtc_statusb);
rtcin(RTC_INTR);
@@ -817,7 +841,7 @@
* is is too generic. Should use it everywhere.
*/
freq = timer_freq;
- error = sysctl_handle_int(oidp, &freq, sizeof(freq), req);
+ error = sysctl_handle_int(oidp, &freq, 0, req);
if (error == 0 && req->newptr != NULL)
set_timer_freq(freq, hz);
return (error);
@@ -909,4 +933,5 @@
DRIVER_MODULE(attimer, isa, attimer_driver, attimer_devclass, 0, 0);
DRIVER_MODULE(attimer, acpi, attimer_driver, attimer_devclass, 0, 0);
+
#endif /* DEV_ISA */
Index: ia32_syscall.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/ia32/ia32_syscall.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/ia32/ia32_syscall.c -L sys/amd64/ia32/ia32_syscall.c -u -r1.1.1.1 -r1.2
--- sys/amd64/ia32/ia32_syscall.c
+++ sys/amd64/ia32/ia32_syscall.c
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/ia32/ia32_syscall.c,v 1.8 2005/04/12 23:18:53 jhb Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/ia32/ia32_syscall.c,v 1.19 2007/06/10 21:59:12 attilio Exp $");
/*
* 386 Trap and System call handling
@@ -56,6 +56,7 @@
#include <sys/ktr.h>
#include <sys/lock.h>
#include <sys/mutex.h>
+#include <sys/ptrace.h>
#include <sys/resourcevar.h>
#include <sys/signalvar.h>
#include <sys/syscall.h>
@@ -66,6 +67,7 @@
#ifdef KTRACE
#include <sys/ktrace.h>
#endif
+#include <security/audit/audit.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
@@ -84,10 +86,10 @@
extern inthand_t IDTVEC(int0x80_syscall), IDTVEC(rsvd);
extern const char *freebsd32_syscallnames[];
-void ia32_syscall(struct trapframe frame); /* Called from asm code */
+void ia32_syscall(struct trapframe *frame); /* Called from asm code */
void
-ia32_syscall(struct trapframe frame)
+ia32_syscall(struct trapframe *frame)
{
caddr_t params;
int i;
@@ -95,32 +97,27 @@
struct thread *td = curthread;
struct proc *p = td->td_proc;
register_t orig_tf_rflags;
- u_int sticks;
int error;
int narg;
u_int32_t args[8];
u_int64_t args64[8];
u_int code;
+ ksiginfo_t ksi;
- /*
- * note: PCPU_LAZY_INC() can only be used if we can afford
- * occassional inaccuracy in the count.
- */
- PCPU_LAZY_INC(cnt.v_syscall);
-
- sticks = td->td_sticks;
- td->td_frame = &frame;
+ PCPU_INC(cnt.v_syscall);
+ td->td_pticks = 0;
+ td->td_frame = frame;
if (td->td_ucred != p->p_ucred)
cred_update_thread(td);
- params = (caddr_t)frame.tf_rsp + sizeof(u_int32_t);
- code = frame.tf_rax;
- orig_tf_rflags = frame.tf_rflags;
+ params = (caddr_t)frame->tf_rsp + sizeof(u_int32_t);
+ code = frame->tf_rax;
+ orig_tf_rflags = frame->tf_rflags;
if (p->p_sysent->sv_prepsyscall) {
/*
* The prep code is MP aware.
*/
- (*p->p_sysent->sv_prepsyscall)(&frame, args, &code, ¶ms);
+ (*p->p_sysent->sv_prepsyscall)(frame, args, &code, ¶ms);
} else {
/*
* Need to check if this is a 32 bit or 64 bit syscall.
@@ -152,7 +149,7 @@
else
callp = &p->p_sysent->sv_table[code];
- narg = callp->sy_narg & SYF_ARGMASK;
+ narg = callp->sy_narg;
/*
* copyin and the ktrsyscall()/ktrsysret() code is MP-aware
@@ -170,27 +167,27 @@
if (KTRPOINT(td, KTR_SYSCALL))
ktrsyscall(code, narg, args64);
#endif
- /*
- * Try to run the syscall without Giant if the syscall
- * is MP safe.
- */
- if ((callp->sy_narg & SYF_MPSAFE) == 0)
- mtx_lock(&Giant);
+ CTR4(KTR_SYSC, "syscall enter thread %p pid %d proc %s code %d", td,
+ td->td_proc->p_pid, td->td_proc->p_comm, code);
if (error == 0) {
td->td_retval[0] = 0;
- td->td_retval[1] = frame.tf_rdx;
+ td->td_retval[1] = frame->tf_rdx;
STOPEVENT(p, S_SCE, narg);
+ PTRACESTOP_SC(p, td, S_PT_SCE);
+
+ AUDIT_SYSCALL_ENTER(code, td);
error = (*callp->sy_call)(td, args64);
+ AUDIT_SYSCALL_EXIT(error, td);
}
switch (error) {
case 0:
- frame.tf_rax = td->td_retval[0];
- frame.tf_rdx = td->td_retval[1];
- frame.tf_rflags &= ~PSL_C;
+ frame->tf_rax = td->td_retval[0];
+ frame->tf_rdx = td->td_retval[1];
+ frame->tf_rflags &= ~PSL_C;
break;
case ERESTART:
@@ -198,7 +195,7 @@
* Reconstruct pc, assuming lcall $X,y is 7 bytes,
* int 0x80 is 2 bytes. We saved this in tf_err.
*/
- frame.tf_rip -= frame.tf_err;
+ frame->tf_rip -= frame->tf_err;
break;
case EJUSTRETURN:
@@ -211,30 +208,43 @@
else
error = p->p_sysent->sv_errtbl[error];
}
- frame.tf_rax = error;
- frame.tf_rflags |= PSL_C;
+ frame->tf_rax = error;
+ frame->tf_rflags |= PSL_C;
break;
}
/*
- * Release Giant if we previously set it.
- */
- if ((callp->sy_narg & SYF_MPSAFE) == 0)
- mtx_unlock(&Giant);
-
- /*
* Traced syscall.
*/
if (orig_tf_rflags & PSL_T) {
- frame.tf_rflags &= ~PSL_T;
- trapsignal(td, SIGTRAP, 0);
+ frame->tf_rflags &= ~PSL_T;
+ ksiginfo_init_trap(&ksi);
+ ksi.ksi_signo = SIGTRAP;
+ ksi.ksi_code = TRAP_TRACE;
+ ksi.ksi_addr = (void *)frame->tf_rip;
+ trapsignal(td, &ksi);
}
/*
+ * Check for misbehavior.
+ */
+ WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
+ (code >= 0 && code < SYS_MAXSYSCALL) ? freebsd32_syscallnames[code] : "???");
+ KASSERT(td->td_critnest == 0,
+ ("System call %s returning in a critical section",
+ (code >= 0 && code < SYS_MAXSYSCALL) ? freebsd32_syscallnames[code] : "???"));
+ KASSERT(td->td_locks == 0,
+ ("System call %s returning with %d locks held",
+ (code >= 0 && code < SYS_MAXSYSCALL) ? freebsd32_syscallnames[code] : "???",
+ td->td_locks));
+
+ /*
* Handle reschedule and other end-of-syscall issues
*/
- userret(td, &frame, sticks);
+ userret(td, frame);
+ CTR4(KTR_SYSC, "syscall exit thread %p pid %d proc %s code %d", td,
+ td->td_proc->p_pid, td->td_proc->p_comm, code);
#ifdef KTRACE
if (KTRPOINT(td, KTR_SYSRET))
ktrsysret(code, error, td->td_retval[0]);
@@ -246,11 +256,8 @@
* is not the case, this code will need to be revisited.
*/
STOPEVENT(p, S_SCX, code);
-
- WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
- (code >= 0 && code < SYS_MAXSYSCALL) ? freebsd32_syscallnames[code] : "???");
- mtx_assert(&sched_lock, MA_NOTOWNED);
- mtx_assert(&Giant, MA_NOTOWNED);
+
+ PTRACESTOP_SC(p, td, S_PT_SCX);
}
Index: ia32_sigtramp.S
===================================================================
RCS file: /home/cvs/src/sys/amd64/ia32/ia32_sigtramp.S,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/ia32/ia32_sigtramp.S -L sys/amd64/ia32/ia32_sigtramp.S -u -r1.1.1.1 -r1.2
--- sys/amd64/ia32/ia32_sigtramp.S
+++ sys/amd64/ia32/ia32_sigtramp.S
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/amd64/ia32/ia32_sigtramp.S,v 1.2 2003/08/22 23:19:02 peter Exp $
+ * $FreeBSD: src/sys/amd64/ia32/ia32_sigtramp.S,v 1.3 2006/09/23 13:42:09 davidxu Exp $
*/
#include "opt_compat.h"
@@ -45,8 +45,6 @@
calll *IA32_SIGF_HANDLER(%esp)
leal IA32_SIGF_UC(%esp),%eax /* get ucontext */
pushl %eax
- movl IA32_UC_GS(%eax),%gs /* restore %gs */
- movl IA32_UC_FS(%eax),%fs /* restore %fs */
movl IA32_UC_ES(%eax),%es /* restore %es */
movl IA32_UC_DS(%eax),%ds /* restore %ds */
movl $SYS_sigreturn,%eax
@@ -62,8 +60,6 @@
calll *IA32_SIGF_HANDLER(%esp)
leal IA32_SIGF_UC4(%esp),%eax/* get ucontext */
pushl %eax
- movl IA32_UC4_GS(%eax),%gs /* restore %gs */
- movl IA32_UC4_FS(%eax),%fs /* restore %fs */
movl IA32_UC4_ES(%eax),%es /* restore %es */
movl IA32_UC4_DS(%eax),%ds /* restore %ds */
movl $344,%eax /* 4.x SYS_sigreturn */
Index: ia32_reg.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/ia32/ia32_reg.c,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -L sys/amd64/ia32/ia32_reg.c -L sys/amd64/ia32/ia32_reg.c -u -r1.1.1.2 -r1.2
--- sys/amd64/ia32/ia32_reg.c
+++ sys/amd64/ia32/ia32_reg.c
@@ -23,11 +23,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/amd64/ia32/ia32_reg.c,v 1.1.2.2 2005/12/28 19:30:40 ps Exp $
+ * $FreeBSD: src/sys/amd64/ia32/ia32_reg.c,v 1.3 2005/10/24 00:00:00 ps Exp $
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/ia32/ia32_reg.c,v 1.1.2.2 2005/12/28 19:30:40 ps Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/ia32/ia32_reg.c,v 1.3 2005/10/24 00:00:00 ps Exp $");
#include "opt_compat.h"
@@ -46,7 +46,6 @@
#include <sys/procfs.h>
#include <sys/resourcevar.h>
#include <sys/systm.h>
-#include <sys/signal.h>
#include <sys/signalvar.h>
#include <sys/stat.h>
#include <sys/sx.h>
Index: ia32_exception.S
===================================================================
RCS file: /home/cvs/src/sys/amd64/ia32/ia32_exception.S,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/ia32/ia32_exception.S -L sys/amd64/ia32/ia32_exception.S -u -r1.1.1.1 -r1.2
--- sys/amd64/ia32/ia32_exception.S
+++ sys/amd64/ia32/ia32_exception.S
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/amd64/ia32/ia32_exception.S,v 1.4 2004/05/24 11:28:11 bde Exp $
+ * $FreeBSD: src/sys/amd64/ia32/ia32_exception.S,v 1.5 2006/12/17 06:48:39 kmacy Exp $
*/
#include <machine/asmacros.h>
@@ -61,6 +61,7 @@
movq %r14,TF_R14(%rsp)
movq %r15,TF_R15(%rsp)
FAKE_MCOUNT(TF_RIP(%rsp))
+ movq %rsp, %rdi
call ia32_syscall
MEXITCOUNT
jmp doreti
Index: ia32_signal.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/ia32/ia32_signal.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/ia32/ia32_signal.c -L sys/amd64/ia32/ia32_signal.c -u -r1.1.1.1 -r1.2
--- sys/amd64/ia32/ia32_signal.c
+++ sys/amd64/ia32/ia32_signal.c
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/ia32/ia32_signal.c,v 1.10 2004/04/05 23:55:14 imp Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/ia32/ia32_signal.c,v 1.15 2006/10/05 01:56:10 davidxu Exp $");
#include "opt_compat.h"
@@ -67,6 +67,7 @@
#include <vm/vm_object.h>
#include <vm/vm_extern.h>
+#include <compat/freebsd32/freebsd32_signal.h>
#include <compat/freebsd32/freebsd32_util.h>
#include <compat/freebsd32/freebsd32_proto.h>
#include <compat/ia32/ia32_signal.h>
@@ -79,7 +80,7 @@
#include <machine/cpufunc.h>
#ifdef COMPAT_FREEBSD4
-static void freebsd4_ia32_sendsig(sig_t, int, sigset_t *, u_long);
+static void freebsd4_ia32_sendsig(sig_t, ksiginfo_t *, sigset_t *);
#endif
static void ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp);
static int ia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp);
@@ -92,38 +93,14 @@
static void
ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp)
{
- struct savefpu *addr;
- /*
- * XXX mc_fpstate might be misaligned, since its declaration is not
- * unportabilized using __attribute__((aligned(16))) like the
- * declaration of struct savemm, and anyway, alignment doesn't work
- * for auto variables since we don't use gcc's pessimal stack
- * alignment. Work around this by abusing the spare fields after
- * mcp->mc_fpstate.
- *
- * XXX unpessimize most cases by only aligning when fxsave might be
- * called, although this requires knowing too much about
- * fpugetregs()'s internals.
- */
- addr = (struct savefpu *)&mcp->mc_fpstate;
- if (td == PCPU_GET(fpcurthread) && ((uintptr_t)(void *)addr & 0xF)) {
- do
- addr = (void *)((char *)addr + 4);
- while ((uintptr_t)(void *)addr & 0xF);
- }
- mcp->mc_ownedfp = fpugetregs(td, addr);
- if (addr != (struct savefpu *)&mcp->mc_fpstate) {
- bcopy(addr, &mcp->mc_fpstate, sizeof(mcp->mc_fpstate));
- bzero(&mcp->mc_spare2, sizeof(mcp->mc_spare2));
- }
+ mcp->mc_ownedfp = fpugetregs(td, (struct savefpu *)&mcp->mc_fpstate);
mcp->mc_fpformat = fpuformat();
}
static int
ia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp)
{
- struct savefpu *addr;
if (mcp->mc_fpformat == _MC_FPFMT_NODEV)
return (0);
@@ -134,31 +111,180 @@
fpstate_drop(td);
else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU ||
mcp->mc_ownedfp == _MC_FPOWNED_PCB) {
- /* XXX align as above. */
- addr = (struct savefpu *)&mcp->mc_fpstate;
- if (td == PCPU_GET(fpcurthread) &&
- ((uintptr_t)(void *)addr & 0xF)) {
- do
- addr = (void *)((char *)addr + 4);
- while ((uintptr_t)(void *)addr & 0xF);
- bcopy(&mcp->mc_fpstate, addr, sizeof(mcp->mc_fpstate));
- }
/*
* XXX we violate the dubious requirement that fpusetregs()
* be called with interrupts disabled.
*/
- fpusetregs(td, addr);
- /*
- * Don't bother putting things back where they were in the
- * misaligned case, since we know that the caller won't use
- * them again.
- */
+ fpusetregs(td, (struct savefpu *)&mcp->mc_fpstate);
} else
return (EINVAL);
return (0);
}
/*
+ * Get machine context.
+ */
+static int
+ia32_get_mcontext(struct thread *td, struct ia32_mcontext *mcp, int flags)
+{
+ struct trapframe *tp;
+
+ tp = td->td_frame;
+
+ PROC_LOCK(curthread->td_proc);
+ mcp->mc_onstack = sigonstack(tp->tf_rsp);
+ PROC_UNLOCK(curthread->td_proc);
+ mcp->mc_gs = td->td_pcb->pcb_gs;
+ mcp->mc_fs = td->td_pcb->pcb_fs;
+ mcp->mc_es = td->td_pcb->pcb_es;
+ mcp->mc_ds = td->td_pcb->pcb_ds;
+ mcp->mc_edi = tp->tf_rdi;
+ mcp->mc_esi = tp->tf_rsi;
+ mcp->mc_ebp = tp->tf_rbp;
+ mcp->mc_isp = tp->tf_rsp;
+ if (flags & GET_MC_CLEAR_RET) {
+ mcp->mc_eax = 0;
+ mcp->mc_edx = 0;
+ } else {
+ mcp->mc_eax = tp->tf_rax;
+ mcp->mc_edx = tp->tf_rdx;
+ }
+ mcp->mc_ebx = tp->tf_rbx;
+ mcp->mc_ecx = tp->tf_rcx;
+ mcp->mc_eip = tp->tf_rip;
+ mcp->mc_cs = tp->tf_cs;
+ mcp->mc_eflags = tp->tf_rflags;
+ mcp->mc_esp = tp->tf_rsp;
+ mcp->mc_ss = tp->tf_ss;
+ mcp->mc_len = sizeof(*mcp);
+ ia32_get_fpcontext(td, mcp);
+ return (0);
+}
+
+/*
+ * Set machine context.
+ *
+ * However, we don't set any but the user modifiable flags, and we won't
+ * touch the cs selector.
+ */
+static int
+ia32_set_mcontext(struct thread *td, const struct ia32_mcontext *mcp)
+{
+ struct trapframe *tp;
+ long rflags;
+ int ret;
+
+ tp = td->td_frame;
+ if (mcp->mc_len != sizeof(*mcp))
+ return (EINVAL);
+ rflags = (mcp->mc_eflags & PSL_USERCHANGE) |
+ (tp->tf_rflags & ~PSL_USERCHANGE);
+ ret = ia32_set_fpcontext(td, mcp);
+ if (ret != 0)
+ return (ret);
+#if 0 /* XXX deal with load_fs() and friends */
+ tp->tf_fs = mcp->mc_fs;
+ tp->tf_es = mcp->mc_es;
+ tp->tf_ds = mcp->mc_ds;
+#endif
+ tp->tf_rdi = mcp->mc_edi;
+ tp->tf_rsi = mcp->mc_esi;
+ tp->tf_rbp = mcp->mc_ebp;
+ tp->tf_rbx = mcp->mc_ebx;
+ tp->tf_rdx = mcp->mc_edx;
+ tp->tf_rcx = mcp->mc_ecx;
+ tp->tf_rax = mcp->mc_eax;
+ /* trapno, err */
+ tp->tf_rip = mcp->mc_eip;
+ tp->tf_rflags = rflags;
+ tp->tf_rsp = mcp->mc_esp;
+ tp->tf_ss = mcp->mc_ss;
+#if 0 /* XXX deal with load_gs() and friends */
+ td->td_pcb->pcb_gs = mcp->mc_gs;
+#endif
+ td->td_pcb->pcb_flags |= PCB_FULLCTX;
+ return (0);
+}
+
+/*
+ * The first two fields of a ucontext_t are the signal mask and
+ * the machine context. The next field is uc_link; we want to
+ * avoid destroying the link when copying out contexts.
+ */
+#define UC_COPY_SIZE offsetof(struct ia32_ucontext, uc_link)
+
+int
+freebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap)
+{
+ struct ia32_ucontext uc;
+ int ret;
+
+ if (uap->ucp == NULL)
+ ret = EINVAL;
+ else {
+ ia32_get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
+ PROC_LOCK(td->td_proc);
+ uc.uc_sigmask = td->td_sigmask;
+ PROC_UNLOCK(td->td_proc);
+ ret = copyout(&uc, uap->ucp, UC_COPY_SIZE);
+ }
+ return (ret);
+}
+
+int
+freebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap)
+{
+ struct ia32_ucontext uc;
+ int ret;
+
+ if (uap->ucp == NULL)
+ ret = EINVAL;
+ else {
+ ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);
+ if (ret == 0) {
+ ret = ia32_set_mcontext(td, &uc.uc_mcontext);
+ if (ret == 0) {
+ SIG_CANTMASK(uc.uc_sigmask);
+ PROC_LOCK(td->td_proc);
+ td->td_sigmask = uc.uc_sigmask;
+ PROC_UNLOCK(td->td_proc);
+ }
+ }
+ }
+ return (ret == 0 ? EJUSTRETURN : ret);
+}
+
+int
+freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap)
+{
+ struct ia32_ucontext uc;
+ int ret;
+
+ if (uap->oucp == NULL || uap->ucp == NULL)
+ ret = EINVAL;
+ else {
+ ia32_get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
+ PROC_LOCK(td->td_proc);
+ uc.uc_sigmask = td->td_sigmask;
+ PROC_UNLOCK(td->td_proc);
+ ret = copyout(&uc, uap->oucp, UC_COPY_SIZE);
+ if (ret == 0) {
+ ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);
+ if (ret == 0) {
+ ret = ia32_set_mcontext(td, &uc.uc_mcontext);
+ if (ret == 0) {
+ SIG_CANTMASK(uc.uc_sigmask);
+ PROC_LOCK(td->td_proc);
+ td->td_sigmask = uc.uc_sigmask;
+ PROC_UNLOCK(td->td_proc);
+ }
+ }
+ }
+ }
+ return (ret == 0 ? EJUSTRETURN : ret);
+}
+
+/*
* Send an interrupt to process.
*
* Stack is set up to allow sigcode stored
@@ -170,18 +296,23 @@
*/
#ifdef COMPAT_FREEBSD4
static void
-freebsd4_ia32_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
+freebsd4_ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
{
struct ia32_sigframe4 sf, *sfp;
+ struct siginfo32 siginfo;
struct proc *p;
struct thread *td;
struct sigacts *psp;
struct trapframe *regs;
int oonstack;
+ int sig;
td = curthread;
p = td->td_proc;
+ siginfo_to_siginfo32(&ksi->ksi_info, &siginfo);
+
PROC_LOCK_ASSERT(p, MA_OWNED);
+ sig = siginfo.si_signo;
psp = p->p_sigacts;
mtx_assert(&psp->ps_mtx, MA_OWNED);
regs = td->td_frame;
@@ -237,13 +368,12 @@
sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
/* Fill in POSIX parts */
+ sf.sf_si = siginfo;
sf.sf_si.si_signo = sig;
- sf.sf_si.si_code = code;
- sf.sf_si.si_addr = regs->tf_addr;
} else {
/* Old FreeBSD-style arguments. */
- sf.sf_siginfo = code;
- sf.sf_addr = regs->tf_addr;
+ sf.sf_siginfo = siginfo.si_code;
+ sf.sf_addr = (u_int32_t)siginfo.si_addr;
sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
}
mtx_unlock(&psp->ps_mtx);
@@ -275,23 +405,27 @@
#endif /* COMPAT_FREEBSD4 */
void
-ia32_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
+ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
{
struct ia32_sigframe sf, *sfp;
+ struct siginfo32 siginfo;
struct proc *p;
struct thread *td;
struct sigacts *psp;
char *sp;
struct trapframe *regs;
int oonstack;
+ int sig;
+ siginfo_to_siginfo32(&ksi->ksi_info, &siginfo);
td = curthread;
p = td->td_proc;
PROC_LOCK_ASSERT(p, MA_OWNED);
+ sig = siginfo.si_signo;
psp = p->p_sigacts;
#ifdef COMPAT_FREEBSD4
if (SIGISMEMBER(psp->ps_freebsd4, sig)) {
- freebsd4_ia32_sendsig(catcher, sig, mask, code);
+ freebsd4_ia32_sendsig(catcher, ksi, mask);
return;
}
#endif
@@ -354,13 +488,12 @@
sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
/* Fill in POSIX parts */
+ sf.sf_si = siginfo;
sf.sf_si.si_signo = sig;
- sf.sf_si.si_code = code;
- sf.sf_si.si_addr = regs->tf_addr;
} else {
/* Old FreeBSD-style arguments. */
- sf.sf_siginfo = code;
- sf.sf_addr = regs->tf_addr;
+ sf.sf_siginfo = siginfo.si_code;
+ sf.sf_addr = (u_int32_t)siginfo.si_addr;
sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
}
mtx_unlock(&psp->ps_mtx);
@@ -415,6 +548,7 @@
struct trapframe *regs;
const struct ia32_ucontext4 *ucp;
int cs, eflags, error;
+ ksiginfo_t ksi;
error = copyin(uap->sigcntxp, &uc, sizeof(uc));
if (error != 0)
@@ -448,7 +582,12 @@
cs = ucp->uc_mcontext.mc_cs;
if (!CS_SECURE(cs)) {
printf("freebsd4_sigreturn: cs = 0x%x\n", cs);
- trapsignal(td, SIGBUS, T_PROTFLT);
+ ksiginfo_init_trap(&ksi);
+ ksi.ksi_signo = SIGBUS;
+ ksi.ksi_code = BUS_OBJERR;
+ ksi.ksi_trapno = T_PROTFLT;
+ ksi.ksi_addr = (void *)regs->tf_rip;
+ trapsignal(td, &ksi);
return (EINVAL);
}
@@ -492,6 +631,7 @@
struct trapframe *regs;
const struct ia32_ucontext *ucp;
int cs, eflags, error, ret;
+ ksiginfo_t ksi;
error = copyin(uap->sigcntxp, &uc, sizeof(uc));
if (error != 0)
@@ -525,7 +665,12 @@
cs = ucp->uc_mcontext.mc_cs;
if (!CS_SECURE(cs)) {
printf("sigreturn: cs = 0x%x\n", cs);
- trapsignal(td, SIGBUS, T_PROTFLT);
+ ksiginfo_init_trap(&ksi);
+ ksi.ksi_signo = SIGBUS;
+ ksi.ksi_code = BUS_OBJERR;
+ ksi.ksi_trapno = T_PROTFLT;
+ ksi.ksi_addr = (void *)regs->tf_rip;
+ trapsignal(td, &ksi);
return (EINVAL);
}
Index: bios.h
===================================================================
RCS file: /home/cvs/src/sys/amd64/include/pc/bios.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/include/pc/bios.h -L sys/amd64/include/pc/bios.h -u -r1.1.1.1 -r1.2
--- sys/amd64/include/pc/bios.h
+++ sys/amd64/include/pc/bios.h
@@ -24,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/amd64/include/pc/bios.h,v 1.18 2004/09/24 00:42:36 peter Exp $
+ * $FreeBSD: src/sys/amd64/include/pc/bios.h,v 1.19 2005/07/21 09:48:36 phk Exp $
*/
#ifndef _MACHINE_PC_BIOS_H_
@@ -48,7 +48,22 @@
u_int32_t type;
} __packed;
-const u_char *bios_string(u_int from, u_int to, const u_char *string, int len);
+struct bios_oem_signature {
+ char * anchor; /* search anchor string in BIOS memory */
+ size_t offset; /* offset from anchor (may be negative) */
+ size_t totlen; /* total length of BIOS string to copy */
+} __packed;
+struct bios_oem_range {
+ u_int from; /* shouldn't be below 0xe0000 */
+ u_int to; /* shouldn't be above 0xfffff */
+} __packed;
+struct bios_oem {
+ struct bios_oem_range range;
+ struct bios_oem_signature signature[];
+} __packed;
+
+extern int
+bios_oem_strings(struct bios_oem *oem, u_char *buffer, size_t maxlen);
#endif /* _MACHINE_PC_BIOS_H_ */
Index: pci_bus.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/pci/pci_bus.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/pci/pci_bus.c -L sys/amd64/pci/pci_bus.c -u -r1.1.1.1 -r1.2
--- sys/amd64/pci/pci_bus.c
+++ sys/amd64/pci/pci_bus.c
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/pci/pci_bus.c,v 1.113.2.1 2005/09/18 02:55:10 imp Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/pci/pci_bus.c,v 1.122 2007/09/30 11:05:13 marius Exp $");
#include "opt_cpu.h"
@@ -81,6 +81,38 @@
return (PCI_INVALID_IRQ);
}
+/* Pass MSI requests up to the nexus. */
+
+static int
+legacy_pcib_alloc_msi(device_t pcib, device_t dev, int count, int maxcount,
+ int *irqs)
+{
+ device_t bus;
+
+ bus = device_get_parent(pcib);
+ return (PCIB_ALLOC_MSI(device_get_parent(bus), dev, count, maxcount,
+ irqs));
+}
+
+static int
+legacy_pcib_alloc_msix(device_t pcib, device_t dev, int *irq)
+{
+ device_t bus;
+
+ bus = device_get_parent(pcib);
+ return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq));
+}
+
+static int
+legacy_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
+ uint32_t *data)
+{
+ device_t bus;
+
+ bus = device_get_parent(pcib);
+ return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data));
+}
+
static const char *
legacy_pcib_is_host_bridge(int bus, int slot, int func,
uint32_t id, uint8_t class, uint8_t subclass,
@@ -244,6 +276,9 @@
{
switch (which) {
+ case PCIB_IVAR_DOMAIN:
+ *result = 0;
+ return 0;
case PCIB_IVAR_BUS:
*result = legacy_get_pcibus(dev);
return 0;
@@ -257,6 +292,8 @@
{
switch (which) {
+ case PCIB_IVAR_DOMAIN:
+ return EINVAL;
case PCIB_IVAR_BUS:
legacy_set_pcibus(dev, value);
return 0;
@@ -322,75 +359,19 @@
DEVMETHOD(pcib_read_config, legacy_pcib_read_config),
DEVMETHOD(pcib_write_config, legacy_pcib_write_config),
DEVMETHOD(pcib_route_interrupt, legacy_pcib_route_interrupt),
+ DEVMETHOD(pcib_alloc_msi, legacy_pcib_alloc_msi),
+ DEVMETHOD(pcib_release_msi, pcib_release_msi),
+ DEVMETHOD(pcib_alloc_msix, legacy_pcib_alloc_msix),
+ DEVMETHOD(pcib_release_msix, pcib_release_msix),
+ DEVMETHOD(pcib_map_msi, legacy_pcib_map_msi),
{ 0, 0 }
};
-static driver_t legacy_pcib_driver = {
- "pcib",
- legacy_pcib_methods,
- 1,
-};
+static devclass_t hostb_devclass;
-DRIVER_MODULE(pcib, legacy, legacy_pcib_driver, pcib_devclass, 0, 0);
-
-
-/*
- * Provide a device to "eat" the host->pci bridges that we dug up above
- * and stop them showing up twice on the probes. This also stops them
- * showing up as 'none' in pciconf -l.
- */
-static int
-pci_hostb_probe(device_t dev)
-{
- u_int32_t id;
-
- id = pci_get_devid(dev);
-
- switch (id) {
-
- /* VIA VT82C596 Power Managment Function */
- case 0x30501106:
- return ENXIO;
-
- default:
- break;
- }
-
- if (pci_get_class(dev) == PCIC_BRIDGE &&
- pci_get_subclass(dev) == PCIS_BRIDGE_HOST) {
- device_set_desc(dev, "Host to PCI bridge");
- device_quiet(dev);
- return -10000;
- }
- return ENXIO;
-}
-
-static int
-pci_hostb_attach(device_t dev)
-{
-
- return 0;
-}
-
-static device_method_t pci_hostb_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, pci_hostb_probe),
- DEVMETHOD(device_attach, pci_hostb_attach),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
- DEVMETHOD(device_suspend, bus_generic_suspend),
- DEVMETHOD(device_resume, bus_generic_resume),
-
- { 0, 0 }
-};
-static driver_t pci_hostb_driver = {
- "hostb",
- pci_hostb_methods,
- 1,
-};
-static devclass_t pci_hostb_devclass;
-
-DRIVER_MODULE(hostb, pci, pci_hostb_driver, pci_hostb_devclass, 0, 0);
+DEFINE_CLASS_0(pcib, legacy_pcib_driver, legacy_pcib_methods, 1);
+DRIVER_MODULE(pcib, legacy, legacy_pcib_driver, hostb_devclass, 0, 0);
/*
@@ -435,12 +416,7 @@
{ 0, 0 }
};
-static driver_t pcibus_pnp_driver = {
- "pcibus_pnp",
- pcibus_pnp_methods,
- 1, /* no softc */
-};
-
static devclass_t pcibus_pnp_devclass;
+DEFINE_CLASS_0(pcibus_pnp, pcibus_pnp_driver, pcibus_pnp_methods, 1);
DRIVER_MODULE(pcibus_pnp, isa, pcibus_pnp_driver, pcibus_pnp_devclass, 0, 0);
Index: pci_cfgreg.c
===================================================================
RCS file: /home/cvs/src/sys/amd64/pci/pci_cfgreg.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/amd64/pci/pci_cfgreg.c -L sys/amd64/pci/pci_cfgreg.c -u -r1.1.1.1 -r1.2
--- sys/amd64/pci/pci_cfgreg.c
+++ sys/amd64/pci/pci_cfgreg.c
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/pci/pci_cfgreg.c,v 1.108 2005/01/21 05:56:41 peter Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/pci/pci_cfgreg.c,v 1.109.2.1 2007/12/06 08:25:43 jhb Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -38,12 +38,8 @@
#include <dev/pci/pcireg.h>
#include <machine/pci_cfgreg.h>
-static int cfgmech;
-static int devmax;
-
static int pcireg_cfgread(int bus, int slot, int func, int reg, int bytes);
static void pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes);
-static int pcireg_cfgopen(void);
static struct mtx pcicfg_mtx;
@@ -57,8 +53,6 @@
if (opened)
return (1);
- if (pcireg_cfgopen() == 0)
- return (0);
mtx_init(&pcicfg_mtx, "pcicfg", NULL, MTX_SPIN);
opened = 1;
return (1);
@@ -109,26 +103,12 @@
{
int dataport = 0;
- if (bus <= PCI_BUSMAX
- && slot < devmax
- && func <= PCI_FUNCMAX
- && reg <= PCI_REGMAX
- && bytes != 3
- && (unsigned) bytes <= 4
- && (reg & (bytes - 1)) == 0) {
- switch (cfgmech) {
- case 1:
- outl(CONF1_ADDR_PORT, (1 << 31)
- | (bus << 16) | (slot << 11)
- | (func << 8) | (reg & ~0x03));
- dataport = CONF1_DATA_PORT + (reg & 0x03);
- break;
- case 2:
- outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1));
- outb(CONF2_FORWARD_PORT, bus);
- dataport = 0xc000 | (slot << 8) | reg;
- break;
- }
+ if (bus <= PCI_BUSMAX && slot < 32 && func <= PCI_FUNCMAX &&
+ 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);
}
return (dataport);
}
@@ -137,15 +117,11 @@
static void
pci_cfgdisable(void)
{
- switch (cfgmech) {
- case 1:
- outl(CONF1_ADDR_PORT, 0);
- break;
- case 2:
- outb(CONF2_ENABLE_PORT, 0);
- outb(CONF2_FORWARD_PORT, 0);
- break;
- }
+
+ /*
+ * Do nothing. Writing a 0 to the address port can apparently
+ * confuse some bridges and cause spurious access failures.
+ */
}
static int
@@ -197,131 +173,3 @@
}
mtx_unlock_spin(&pcicfg_mtx);
}
-
-/* check whether the configuration mechanism has been correctly identified */
-static int
-pci_cfgcheck(int maxdev)
-{
- uint32_t id, class;
- uint8_t header;
- uint8_t device;
- int port;
-
- if (bootverbose)
- printf("pci_cfgcheck:\tdevice ");
-
- for (device = 0; device < maxdev; device++) {
- if (bootverbose)
- printf("%d ", device);
-
- port = pci_cfgenable(0, device, 0, 0, 4);
- id = inl(port);
- if (id == 0 || id == 0xffffffff)
- continue;
-
- port = pci_cfgenable(0, device, 0, 8, 4);
- class = inl(port) >> 8;
- if (bootverbose)
- printf("[class=%06x] ", class);
- if (class == 0 || (class & 0xf870ff) != 0)
- continue;
-
- port = pci_cfgenable(0, device, 0, 14, 1);
- header = inb(port);
- if (bootverbose)
- printf("[hdr=%02x] ", header);
- if ((header & 0x7e) != 0)
- continue;
-
- if (bootverbose)
- printf("is there (id=%08x)\n", id);
-
- pci_cfgdisable();
- return (1);
- }
- if (bootverbose)
- printf("-- nothing found\n");
-
- pci_cfgdisable();
- return (0);
-}
-
-static int
-pcireg_cfgopen(void)
-{
- uint32_t mode1res, oldval1;
- uint8_t mode2res, oldval2;
-
- oldval1 = inl(CONF1_ADDR_PORT);
-
- if (bootverbose) {
- printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08x\n",
- oldval1);
- }
-
- if ((oldval1 & CONF1_ENABLE_MSK) == 0) {
-
- cfgmech = 1;
- devmax = 32;
-
- outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK);
- DELAY(1);
- mode1res = inl(CONF1_ADDR_PORT);
- outl(CONF1_ADDR_PORT, oldval1);
-
- if (bootverbose)
- printf("pci_open(1a):\tmode1res=0x%08x (0x%08lx)\n",
- mode1res, CONF1_ENABLE_CHK);
-
- if (mode1res) {
- if (pci_cfgcheck(32))
- return (cfgmech);
- }
-
- outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
- mode1res = inl(CONF1_ADDR_PORT);
- outl(CONF1_ADDR_PORT, oldval1);
-
- if (bootverbose)
- printf("pci_open(1b):\tmode1res=0x%08x (0x%08lx)\n",
- mode1res, CONF1_ENABLE_CHK1);
-
- if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) {
- if (pci_cfgcheck(32))
- return (cfgmech);
- }
- }
-
- oldval2 = inb(CONF2_ENABLE_PORT);
-
- if (bootverbose) {
- printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n",
- oldval2);
- }
-
- if ((oldval2 & 0xf0) == 0) {
-
- cfgmech = 2;
- devmax = 16;
-
- outb(CONF2_ENABLE_PORT, CONF2_ENABLE_CHK);
- mode2res = inb(CONF2_ENABLE_PORT);
- outb(CONF2_ENABLE_PORT, oldval2);
-
- if (bootverbose)
- printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n",
- mode2res, CONF2_ENABLE_CHK);
-
- if (mode2res == CONF2_ENABLE_RES) {
- if (bootverbose)
- printf("pci_open(2a):\tnow trying mechanism 2\n");
-
- if (pci_cfgcheck(16))
- return (cfgmech);
- }
- }
-
- cfgmech = 0;
- devmax = 0;
- return (cfgmech);
-}
More information about the Midnightbsd-cvs
mailing list