aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>2003-05-01 01:05:25 +0000
committerPeter Wemm <peter@FreeBSD.org>2003-05-01 01:05:25 +0000
commitafa8862328041298fe0c059d65cea406f92bad4b (patch)
treedd665cefeba0e426ad2b212b76851de96f1ad18b /sys
parent4580c352e198e8e5191edb06bb1c9b5488d1bb90 (diff)
downloadsrc-afa8862328041298fe0c059d65cea406f92bad4b.tar.gz
src-afa8862328041298fe0c059d65cea406f92bad4b.zip
Commit MD parts of a loosely functional AMD64 port. This is based on
a heavily stripped down FreeBSD/i386 (brutally stripped down actually) to attempt to get a stable base to start from. There is a lot missing still. Worth noting: - The kernel runs at 1GB in order to cheat with the pmap code. pmap uses a variation of the PAE code in order to avoid having to worry about 4 levels of page tables yet. - It boots in 64 bit "long mode" with a tiny trampoline embedded in the i386 loader. This simplifies locore.s greatly. - There are still quite a few fragments of i386-specific code that have not been translated yet, and some that I cheated and wrote dumb C versions of (bcopy etc). - It has both int 0x80 for syscalls (but using registers for argument passing, as is native on the amd64 ABI), and the 'syscall' instruction for syscalls. int 0x80 preserves all registers, 'syscall' does not. - I have tried to minimize looking at the NetBSD code, except in a couple of places (eg: to find which register they use to replace the trashed %rcx register in the syscall instruction). As a result, there is not a lot of similarity. I did look at NetBSD a few times while debugging to get some ideas about what I might have done wrong in my first attempt.
Notes
Notes: svn path=/head/; revision=114349
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/acpica/OsdEnvironment.c2
-rw-r--r--sys/amd64/acpica/acpi_machdep.c297
-rw-r--r--sys/amd64/acpica/acpi_wakeup.c311
-rw-r--r--sys/amd64/amd64/autoconf.c56
-rw-r--r--sys/amd64/amd64/cpu_switch.S401
-rw-r--r--sys/amd64/amd64/critical.c130
-rw-r--r--sys/amd64/amd64/dump_machdep.c2
-rw-r--r--sys/amd64/amd64/elf_machdep.c29
-rw-r--r--sys/amd64/amd64/exception.S311
-rw-r--r--sys/amd64/amd64/exception.s311
-rw-r--r--sys/amd64/amd64/fpu.c488
-rw-r--r--sys/amd64/amd64/genassym.c122
-rw-r--r--sys/amd64/amd64/identcpu.c1076
-rw-r--r--sys/amd64/amd64/initcpu.c816
-rw-r--r--sys/amd64/amd64/legacy.c16
-rw-r--r--sys/amd64/amd64/locore.S881
-rw-r--r--sys/amd64/amd64/locore.s881
-rw-r--r--sys/amd64/amd64/machdep.c2095
-rw-r--r--sys/amd64/amd64/mem.c23
-rw-r--r--sys/amd64/amd64/nexus.c53
-rw-r--r--sys/amd64/amd64/pmap.c645
-rw-r--r--sys/amd64/amd64/sigtramp.S56
-rw-r--r--sys/amd64/amd64/sigtramp.s56
-rw-r--r--sys/amd64/amd64/support.S1556
-rw-r--r--sys/amd64/amd64/support.s1556
-rw-r--r--sys/amd64/amd64/swtch.s401
-rw-r--r--sys/amd64/amd64/sys_machdep.c501
-rw-r--r--sys/amd64/amd64/trap.c426
-rw-r--r--sys/amd64/amd64/tsc.c45
-rw-r--r--sys/amd64/amd64/vm_machdep.c300
-rw-r--r--sys/amd64/conf/GENERIC219
-rw-r--r--sys/amd64/conf/GENERIC.hints2
-rw-r--r--sys/amd64/include/_inttypes.h88
-rw-r--r--sys/amd64/include/_types.h4
-rw-r--r--sys/amd64/include/asm.h52
-rw-r--r--sys/amd64/include/asmacros.h12
-rw-r--r--sys/amd64/include/atomic.h96
-rw-r--r--sys/amd64/include/bus.h8
-rw-r--r--sys/amd64/include/bus_amd64.h16
-rw-r--r--sys/amd64/include/bus_at386.h16
-rw-r--r--sys/amd64/include/clock.h9
-rw-r--r--sys/amd64/include/cpu.h29
-rw-r--r--sys/amd64/include/cpufunc.h226
-rw-r--r--sys/amd64/include/cputypes.h27
-rw-r--r--sys/amd64/include/critical.h35
-rw-r--r--sys/amd64/include/db_machdep.h4
-rw-r--r--sys/amd64/include/elf.h49
-rw-r--r--sys/amd64/include/endian.h15
-rw-r--r--sys/amd64/include/fpu.h73
-rw-r--r--sys/amd64/include/frame.h167
-rw-r--r--sys/amd64/include/kse.h9
-rw-r--r--sys/amd64/include/md_var.h51
-rw-r--r--sys/amd64/include/mutex.h20
-rw-r--r--sys/amd64/include/npx.h73
-rw-r--r--sys/amd64/include/param.h65
-rw-r--r--sys/amd64/include/pcb.h41
-rw-r--r--sys/amd64/include/pcb_ext.h20
-rw-r--r--sys/amd64/include/pci_cfgreg.h6
-rw-r--r--sys/amd64/include/pcpu.h40
-rw-r--r--sys/amd64/include/pmap.h150
-rw-r--r--sys/amd64/include/proc.h25
-rw-r--r--sys/amd64/include/profile.h14
-rw-r--r--sys/amd64/include/psl.h6
-rw-r--r--sys/amd64/include/reg.h102
-rw-r--r--sys/amd64/include/segments.h183
-rw-r--r--sys/amd64/include/setjmp.h2
-rw-r--r--sys/amd64/include/sigframe.h67
-rw-r--r--sys/amd64/include/signal.h90
-rw-r--r--sys/amd64/include/smp.h146
-rw-r--r--sys/amd64/include/specialreg.h117
-rw-r--r--sys/amd64/include/sysarch.h42
-rw-r--r--sys/amd64/include/tss.h58
-rw-r--r--sys/amd64/include/ucontext.h83
-rw-r--r--sys/amd64/include/vmparam.h25
-rw-r--r--sys/amd64/isa/clock.c228
-rw-r--r--sys/amd64/isa/icu.h106
-rw-r--r--sys/amd64/isa/icu_ipl.S4
-rw-r--r--sys/amd64/isa/icu_ipl.s4
-rw-r--r--sys/amd64/isa/icu_vector.S257
-rw-r--r--sys/amd64/isa/icu_vector.s257
-rw-r--r--sys/amd64/isa/intr_machdep.c275
-rw-r--r--sys/amd64/isa/intr_machdep.h133
-rw-r--r--sys/amd64/isa/isa.c109
-rw-r--r--sys/amd64/isa/isa.h33
-rw-r--r--sys/amd64/isa/isa_dma.c5
-rw-r--r--sys/amd64/isa/ithread.c33
-rw-r--r--sys/amd64/isa/npx.c488
-rw-r--r--sys/amd64/isa/timerreg.h6
-rw-r--r--sys/amd64/isa/vector.S44
-rw-r--r--sys/amd64/isa/vector.s44
-rw-r--r--sys/amd64/pci/pci_bus.c72
-rw-r--r--sys/amd64/pci/pci_cfgreg.c504
92 files changed, 3160 insertions, 15867 deletions
diff --git a/sys/amd64/acpica/OsdEnvironment.c b/sys/amd64/acpica/OsdEnvironment.c
index a3d366169ff8..cd7fd6491fdb 100644
--- a/sys/amd64/acpica/OsdEnvironment.c
+++ b/sys/amd64/acpica/OsdEnvironment.c
@@ -36,8 +36,6 @@
#include "acpi.h"
-#include <machine/pc/bios.h>
-
u_long i386_acpi_root;
SYSCTL_ULONG(_machdep, OID_AUTO, acpi_root, CTLFLAG_RD, &i386_acpi_root, 0,
diff --git a/sys/amd64/acpica/acpi_machdep.c b/sys/amd64/acpica/acpi_machdep.c
index 6d48588e1c9a..66c71f41ebc7 100644
--- a/sys/amd64/acpica/acpi_machdep.c
+++ b/sys/amd64/acpica/acpi_machdep.c
@@ -28,315 +28,20 @@
#include <sys/param.h>
#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/fcntl.h>
-#include <sys/uio.h>
#include "acpi.h"
-
#include <dev/acpica/acpivar.h>
-#include <dev/acpica/acpiio.h>
-
-static device_t acpi_dev;
-
-/*
- * APM driver emulation
- */
-
-#if __FreeBSD_version < 500000
-#include <sys/select.h>
-#else
-#include <sys/selinfo.h>
-#endif
-
-#include <machine/apm_bios.h>
-#include <machine/pc/bios.h>
-
-#include <i386/bios/apm.h>
-
-static struct apm_softc apm_softc;
-
-static d_open_t apmopen;
-static d_close_t apmclose;
-static d_write_t apmwrite;
-static d_ioctl_t apmioctl;
-static d_poll_t apmpoll;
-
-#define CDEV_MAJOR 39
-static struct cdevsw apm_cdevsw = {
- .d_open = apmopen,
- .d_close = apmclose,
- .d_write = apmwrite,
- .d_ioctl = apmioctl,
- .d_poll = apmpoll,
- .d_name = "apm",
- .d_maj = CDEV_MAJOR,
-};
-
-static int
-acpi_capm_convert_battstate(struct acpi_battinfo *battp)
-{
- int state;
-
- state = 0xff; /* XXX unknown */
-
- if (battp->state & ACPI_BATT_STAT_DISCHARG) {
- if (battp->cap >= 50) {
- state = 0; /* high */
- } else {
- state = 1; /* low */
- }
- }
- if (battp->state & ACPI_BATT_STAT_CRITICAL) {
- state = 2; /* critical */
- }
- if (battp->state & ACPI_BATT_STAT_CHARGING) {
- state = 3; /* charging */
- }
- return (state);
-}
-
-static int
-acpi_capm_convert_battflags(struct acpi_battinfo *battp)
-{
- int flags;
-
- flags = 0;
-
- if (battp->cap >= 50) {
- flags |= APM_BATT_HIGH;
- } else {
- if (battp->state & ACPI_BATT_STAT_CRITICAL) {
- flags |= APM_BATT_CRITICAL;
- } else {
- flags |= APM_BATT_LOW;
- }
- }
- if (battp->state & ACPI_BATT_STAT_CHARGING) {
- flags |= APM_BATT_CHARGING;
- }
- if (battp->state == ACPI_BATT_STAT_NOT_PRESENT) {
- flags = APM_BATT_NOT_PRESENT;
- }
-
- return (flags);
-}
-
-static int
-acpi_capm_get_info(apm_info_t aip)
-{
- int acline;
- struct acpi_battinfo batt;
-
- aip->ai_infoversion = 1;
- aip->ai_major = 1;
- aip->ai_minor = 2;
- aip->ai_status = apm_softc.active;
- aip->ai_capabilities= 0xff00; /* XXX unknown */
-
- if (acpi_acad_get_acline(&acline)) {
- aip->ai_acline = 0xff; /* unknown */
- } else {
- aip->ai_acline = acline; /* on/off */
- }
-
- if (acpi_battery_get_battinfo(-1, &batt)) {
- aip->ai_batt_stat = 0xff; /* unknown */
- aip->ai_batt_life = 0xff; /* unknown */
- aip->ai_batt_time = -1; /* unknown */
- aip->ai_batteries = 0;
- } else {
- aip->ai_batt_stat = acpi_capm_convert_battstate(&batt);
- aip->ai_batt_life = batt.cap;
- aip->ai_batt_time = (batt.min == -1) ? -1 : batt.min * 60;
- aip->ai_batteries = acpi_battery_get_units();
- }
-
- return (0);
-}
-
-static int
-acpi_capm_get_pwstatus(apm_pwstatus_t app)
-{
- int batt_unit;
- int acline;
- struct acpi_battinfo batt;
-
- if (app->ap_device != PMDV_ALLDEV &&
- (app->ap_device < PMDV_BATT0 || app->ap_device > PMDV_BATT_ALL)) {
- return (1);
- }
-
- if (app->ap_device == PMDV_ALLDEV) {
- batt_unit = -1; /* all units */
- } else {
- batt_unit = app->ap_device - PMDV_BATT0;
- }
-
- if (acpi_battery_get_battinfo(batt_unit, &batt)) {
- return (1);
- }
-
- app->ap_batt_stat = acpi_capm_convert_battstate(&batt);
- app->ap_batt_flag = acpi_capm_convert_battflags(&batt);
- app->ap_batt_life = batt.cap;
- app->ap_batt_time = (batt.min == -1) ? -1 : batt.min * 60;
-
- if (acpi_acad_get_acline(&acline)) {
- app->ap_acline = 0xff; /* unknown */
- } else {
- app->ap_acline = acline; /* on/off */
- }
-
- return (0);
-}
-
-static int
-apmopen(dev_t dev, int flag, int fmt, d_thread_t *td)
-{
- return (0);
-}
-
-static int
-apmclose(dev_t dev, int flag, int fmt, d_thread_t *td)
-{
- return (0);
-}
-
-static int
-apmioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, d_thread_t *td)
-{
- int error = 0;
- struct acpi_softc *acpi_sc;
- struct apm_info info;
- apm_info_old_t aiop;
-
- if ((acpi_sc = device_get_softc(acpi_dev)) == NULL) {
- return (ENXIO);
- }
-
- switch (cmd) {
- case APMIO_SUSPEND:
- if (!(flag & FWRITE))
- return (EPERM);
- if (apm_softc.active)
- acpi_SetSleepState(acpi_sc, acpi_sc->acpi_suspend_sx);
- else
- error = EINVAL;
- break;
-
- case APMIO_STANDBY:
- if (!(flag & FWRITE))
- return (EPERM);
- if (apm_softc.active)
- acpi_SetSleepState(acpi_sc, acpi_sc->acpi_standby_sx);
- else
- error = EINVAL;
- break;
-
- case APMIO_GETINFO_OLD:
- if (acpi_capm_get_info(&info))
- error = ENXIO;
- aiop = (apm_info_old_t)addr;
- aiop->ai_major = info.ai_major;
- aiop->ai_minor = info.ai_minor;
- aiop->ai_acline = info.ai_acline;
- aiop->ai_batt_stat = info.ai_batt_stat;
- aiop->ai_batt_life = info.ai_batt_life;
- aiop->ai_status = info.ai_status;
- break;
-
- case APMIO_GETINFO:
- if (acpi_capm_get_info((apm_info_t)addr))
- error = ENXIO;
-
- break;
-
- case APMIO_GETPWSTATUS:
- if (acpi_capm_get_pwstatus((apm_pwstatus_t)addr))
- error = ENXIO;
- break;
-
- case APMIO_ENABLE:
- if (!(flag & FWRITE))
- return (EPERM);
- apm_softc.active = 1;
- break;
-
- case APMIO_DISABLE:
- if (!(flag & FWRITE))
- return (EPERM);
- apm_softc.active = 0;
- break;
-
- case APMIO_HALTCPU:
- break;
-
- case APMIO_NOTHALTCPU:
- break;
-
- case APMIO_DISPLAY:
- if (!(flag & FWRITE))
- return (EPERM);
- break;
-
- case APMIO_BIOS:
- if (!(flag & FWRITE))
- return (EPERM);
- bzero(addr, sizeof(struct apm_bios_arg));
- break;
-
- default:
- error = EINVAL;
- break;
- }
-
- return (error);
-}
-
-static int
-apmwrite(dev_t dev, struct uio *uio, int ioflag)
-{
-
- return (uio->uio_resid);
-}
-
-static int
-apmpoll(dev_t dev, int events, d_thread_t *td)
-{
- return (0);
-}
-
-static void
-acpi_capm_init(struct acpi_softc *sc)
-{
-
- make_dev(&apm_cdevsw, 0, 0, 5, 0664, "apm");
-}
int
acpi_machdep_init(device_t dev)
{
struct acpi_softc *sc;
- acpi_dev = dev;
- if ((sc = device_get_softc(acpi_dev)) == NULL) {
+ if ((sc = device_get_softc(dev)) == NULL) {
return (ENXIO);
}
- /*
- * XXX: Prevent the PnP BIOS code from interfering with
- * our own scan of ISA devices.
- */
- PnPBIOStable = NULL;
-
- acpi_capm_init(sc);
-
acpi_install_wakeup_handler(sc);
-#ifdef SMP
- acpi_SetIntrModel(ACPI_INTR_APIC);
-#endif
return (0);
}
-
diff --git a/sys/amd64/acpica/acpi_wakeup.c b/sys/amd64/acpica/acpi_wakeup.c
index 9f02e9358fb6..3a17e6c63661 100644
--- a/sys/amd64/acpica/acpi_wakeup.c
+++ b/sys/amd64/acpica/acpi_wakeup.c
@@ -26,329 +26,20 @@
*
* $FreeBSD$
*/
-
#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
#include <sys/bus.h>
-#include <sys/lock.h>
-#include <sys/proc.h>
-#include <sys/sysctl.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/pmap.h>
-#include <vm/vm_object.h>
-#include <vm/vm_page.h>
-#include <vm/vm_map.h>
-#include <vm/vm_kern.h>
-#include <vm/vm_extern.h>
-
-#include <machine/bus.h>
-#include <machine/cpufunc.h>
-#include <machine/segments.h>
-
-#include <i386/isa/intr_machdep.h>
#include "acpi.h"
-
-#include <dev/acpica/acpica_support.h>
-
#include <dev/acpica/acpivar.h>
-#include "acpi_wakecode.h"
-
-extern void initializecpu(void);
-
-static struct region_descriptor r_idt, r_gdt, *p_gdt;
-static u_int16_t r_ldt;
-
-static u_int32_t r_eax, r_ebx, r_ecx, r_edx, r_ebp, r_esi, r_edi,
- r_efl, r_cr0, r_cr2, r_cr3, r_cr4, ret_addr;
-
-static u_int16_t r_cs, r_ds, r_es, r_fs, r_gs, r_ss, r_tr;
-static u_int32_t r_esp = 0;
-
-static void acpi_printcpu(void);
-static void acpi_realmodeinst(void *arg, bus_dma_segment_t *segs,
- int nsegs, int error);
-static void acpi_alloc_wakeup_handler(void);
-
-/* XXX shut gcc up */
-extern int acpi_savecpu(void);
-extern int acpi_restorecpu(void);
-
-#ifdef __GNUC__
-__asm__(" \n\
- .text \n\
- .p2align 2, 0x90 \n\
- .type acpi_restorecpu, @function\n\
-acpi_restorecpu: \n\
- .align 4 \n\
- movl r_eax,%eax \n\
- movl r_ebx,%ebx \n\
- movl r_ecx,%ecx \n\
- movl r_edx,%edx \n\
- movl r_ebp,%ebp \n\
- movl r_esi,%esi \n\
- movl r_edi,%edi \n\
- movl r_esp,%esp \n\
- \n\
- pushl r_efl \n\
- popfl \n\
- \n\
- movl ret_addr,%eax \n\
- movl %eax,(%esp) \n\
- xorl %eax,%eax \n\
- ret \n\
- \n\
- .text \n\
- .p2align 2, 0x90 \n\
- .type acpi_savecpu, @function \n\
-acpi_savecpu: \n\
- movw %cs,r_cs \n\
- movw %ds,r_ds \n\
- movw %es,r_es \n\
- movw %fs,r_fs \n\
- movw %gs,r_gs \n\
- movw %ss,r_ss \n\
- \n\
- movl %eax,r_eax \n\
- movl %ebx,r_ebx \n\
- movl %ecx,r_ecx \n\
- movl %edx,r_edx \n\
- movl %ebp,r_ebp \n\
- movl %esi,r_esi \n\
- movl %edi,r_edi \n\
- \n\
- movl %cr0,%eax \n\
- movl %eax,r_cr0 \n\
- movl %cr2,%eax \n\
- movl %eax,r_cr2 \n\
- movl %cr3,%eax \n\
- movl %eax,r_cr3 \n\
- movl %cr4,%eax \n\
- movl %eax,r_cr4 \n\
- \n\
- pushfl \n\
- popl r_efl \n\
- \n\
- movl %esp,r_esp \n\
- \n\
- sgdt r_gdt \n\
- sidt r_idt \n\
- sldt r_ldt \n\
- str r_tr \n\
- \n\
- movl (%esp),%eax \n\
- movl %eax,ret_addr \n\
- movl $1,%eax \n\
- ret \n\
-");
-#endif /* __GNUC__ */
-
-static void
-acpi_printcpu(void)
-{
-
- printf("======== acpi_printcpu() debug dump ========\n");
- printf("gdt[%04x:%08x] idt[%04x:%08x] ldt[%04x] tr[%04x] efl[%08x]\n",
- r_gdt.rd_limit, r_gdt.rd_base, r_idt.rd_limit, r_idt.rd_base,
- r_ldt, r_tr, r_efl);
- printf("eax[%08x] ebx[%08x] ecx[%08x] edx[%08x]\n",
- r_eax, r_ebx, r_ecx, r_edx);
- printf("esi[%08x] edi[%08x] ebp[%08x] esp[%08x]\n",
- r_esi, r_edi, r_ebp, r_esp);
- printf("cr0[%08x] cr2[%08x] cr3[%08x] cr4[%08x]\n",
- r_cr0, r_cr2, r_cr3, r_cr4);
- printf("cs[%04x] ds[%04x] es[%04x] fs[%04x] gs[%04x] ss[%04x]\n",
- r_cs, r_ds, r_es, r_fs, r_gs, r_ss);
-}
-
-#define WAKECODE_FIXUP(offset, type, val) do { \
- void **addr; \
- addr = (void **)(sc->acpi_wakeaddr + offset); \
- (type *)*addr = val; \
-} while (0)
-
-#define WAKECODE_BCOPY(offset, type, val) do { \
- void **addr; \
- addr = (void **)(sc->acpi_wakeaddr + offset); \
- bcopy(&(val), addr, sizeof(type)); \
-} while (0)
-
int
acpi_sleep_machdep(struct acpi_softc *sc, int state)
{
- ACPI_STATUS status;
- vm_paddr_t oldphys;
- struct pmap *pm;
- vm_page_t page;
- static vm_page_t opage = NULL;
- int ret = 0;
- int pteobj_allocated = 0;
- u_long ef;
- struct proc *p;
-
- if (sc->acpi_wakeaddr == 0) {
- return (0);
- }
-
- AcpiSetFirmwareWakingVector(sc->acpi_wakephys);
-
- ef = read_eflags();
- disable_intr();
-
- /* Create Identity Mapping */
- if ((p = curproc) == NULL)
- p = &proc0;
- pm = vmspace_pmap(p->p_vmspace);
- if (pm->pm_pteobj == NULL) {
- pm->pm_pteobj = vm_object_allocate(OBJT_DEFAULT, PTDPTDI + 1);
- pteobj_allocated = 1;
- }
-
- oldphys = pmap_extract(pm, sc->acpi_wakephys);
- if (oldphys) {
- opage = PHYS_TO_VM_PAGE(oldphys);
- }
- page = PHYS_TO_VM_PAGE(sc->acpi_wakephys);
- pmap_enter(pm, sc->acpi_wakephys, page,
- VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE, 1);
-
- ret_addr = 0;
- if (acpi_savecpu()) {
- /* Execute Sleep */
- p_gdt = (struct region_descriptor *)(sc->acpi_wakeaddr + physical_gdt);
- p_gdt->rd_limit = r_gdt.rd_limit;
- p_gdt->rd_base = vtophys(r_gdt.rd_base);
-
- WAKECODE_FIXUP(physical_esp, u_int32_t, vtophys(r_esp));
- WAKECODE_FIXUP(previous_cr0, u_int32_t, r_cr0);
- WAKECODE_FIXUP(previous_cr2, u_int32_t, r_cr2);
- WAKECODE_FIXUP(previous_cr3, u_int32_t, r_cr3);
- WAKECODE_FIXUP(previous_cr4, u_int32_t, r_cr4);
-
- WAKECODE_FIXUP(previous_tr, u_int16_t, r_tr);
- WAKECODE_BCOPY(previous_gdt, struct region_descriptor, r_gdt);
- WAKECODE_FIXUP(previous_ldt, u_int16_t, r_ldt);
- WAKECODE_BCOPY(previous_idt, struct region_descriptor, r_idt);
- WAKECODE_FIXUP(where_to_recover, void, acpi_restorecpu);
-
- WAKECODE_FIXUP(previous_ds, u_int16_t, r_ds);
- WAKECODE_FIXUP(previous_es, u_int16_t, r_es);
- WAKECODE_FIXUP(previous_fs, u_int16_t, r_fs);
- WAKECODE_FIXUP(previous_gs, u_int16_t, r_gs);
- WAKECODE_FIXUP(previous_ss, u_int16_t, r_ss);
-
- if (acpi_get_verbose(sc)) {
- acpi_printcpu();
- }
-
- wbinvd();
-
- if (state == ACPI_STATE_S4 && sc->acpi_s4bios) {
- status = AcpiEnterSleepStateS4Bios();
- } else {
- status = AcpiEnterSleepState(state);
- }
-
- if (status != AE_OK) {
- device_printf(sc->acpi_dev,
- "AcpiEnterSleepState failed - %s\n",
- AcpiFormatException(status));
- ret = -1;
- goto out;
- }
-
- for (;;) ;
- } else {
- /* Execute Wakeup */
-#if 0
- initializecpu();
-#endif
- icu_reinit();
-
- if (acpi_get_verbose(sc)) {
- acpi_savecpu();
- acpi_printcpu();
- }
- }
-
-out:
- vm_page_lock_queues();
- pmap_remove(pm, sc->acpi_wakephys, sc->acpi_wakephys + PAGE_SIZE);
- vm_page_unlock_queues();
- if (opage) {
- pmap_enter(pm, sc->acpi_wakephys, page,
- VM_PROT_READ | VM_PROT_WRITE, 0);
- }
-
- if (pteobj_allocated) {
- vm_object_deallocate(pm->pm_pteobj);
- pm->pm_pteobj = NULL;
- }
-
- write_eflags(ef);
-
- return (ret);
-}
-
-static bus_dma_tag_t acpi_waketag;
-static bus_dmamap_t acpi_wakemap;
-static vm_offset_t acpi_wakeaddr = 0;
-
-static void
-acpi_alloc_wakeup_handler(void)
-{
-
- if (!cold)
- return;
-
- if (bus_dma_tag_create(/* parent */ NULL, /* alignment */ 2, 0,
- /* lowaddr below 1MB */ 0x9ffff,
- /* highaddr */ BUS_SPACE_MAXADDR, NULL, NULL,
- PAGE_SIZE, 1, PAGE_SIZE, 0, &acpi_waketag) != 0) {
- printf("acpi_alloc_wakeup_handler: unable to create wake tag\n");
- return;
- }
-
- if (bus_dmamem_alloc(acpi_waketag, (void **)&acpi_wakeaddr,
- BUS_DMA_NOWAIT, &acpi_wakemap)) {
- printf("acpi_alloc_wakeup_handler: unable to allocate wake memory\n");
- return;
- }
-}
-
-SYSINIT(acpiwakeup, SI_SUB_KMEM, SI_ORDER_ANY, acpi_alloc_wakeup_handler, 0)
-
-static void
-acpi_realmodeinst(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
-{
- struct acpi_softc *sc = arg;
- u_int32_t *addr;
-
- addr = (u_int32_t *)&wakecode[wakeup_sw32 + 2];
- *addr = segs[0].ds_addr + wakeup_32;
- bcopy(wakecode, (void *)sc->acpi_wakeaddr, sizeof(wakecode));
- sc->acpi_wakephys = segs[0].ds_addr;
+ return (0);
}
void
acpi_install_wakeup_handler(struct acpi_softc *sc)
{
-
- if (acpi_wakeaddr == 0) {
- return;
- }
-
- sc->acpi_waketag = acpi_waketag;
- sc->acpi_wakeaddr = acpi_wakeaddr;
- sc->acpi_wakemap = acpi_wakemap;
-
- bus_dmamap_load(sc->acpi_waketag, sc->acpi_wakemap,
- (void *)sc->acpi_wakeaddr, PAGE_SIZE,
- acpi_realmodeinst, sc, 0);
}
-
diff --git a/sys/amd64/amd64/autoconf.c b/sys/amd64/amd64/autoconf.c
index f97fbc01dec9..a19672acc00a 100644
--- a/sys/amd64/amd64/autoconf.c
+++ b/sys/amd64/amd64/autoconf.c
@@ -73,13 +73,8 @@
#include <nfsclient/nfs.h>
#include <nfsclient/nfsdiskless.h>
-#include <machine/bootinfo.h>
#include <machine/md_var.h>
-#ifdef APIC_IO
-#include <machine/smp.h>
-#else
-#include <i386/isa/icu.h>
-#endif /* APIC_IO */
+#include <amd64/isa/icu.h>
#ifdef DEV_ISA
#include <isa/isavar.h>
@@ -127,13 +122,8 @@ configure(dummy)
*
* This is all rather inconvenient.
*/
-#ifdef APIC_IO
- bsp_apic_configure();
- enable_intr();
-#else
enable_intr();
INTREN(IRQ_SLAVE);
-#endif /* APIC_IO */
/* nexus0 is the top of the i386 device tree */
device_add_child(root_bus, "nexus", 0);
@@ -163,50 +153,6 @@ configure_final(dummy)
{
cninit_finish();
-
- if (bootverbose) {
-
-#ifdef APIC_IO
- imen_dump();
-#endif /* APIC_IO */
-
-#ifdef PC98
- {
- int i;
- /*
- * Print out the BIOS's idea of the disk geometries.
- */
- printf("BIOS Geometries:\n");
- for (i = 0; i < N_BIOS_GEOM; i++) {
- unsigned long bios_geom;
- int max_cylinder, max_head, max_sector;
-
- bios_geom = bootinfo.bi_bios_geom[i];
-
- /*
- * XXX the bootstrap punts a 1200K floppy geometry
- * when the get-disk-geometry interrupt fails. Skip
- * drives that have this geometry.
- */
- if (bios_geom == 0x4f010f)
- continue;
-
- printf(" %x:%08lx ", i, bios_geom);
- max_cylinder = bios_geom >> 16;
- max_head = (bios_geom >> 8) & 0xff;
- max_sector = bios_geom & 0xff;
- printf(
- "0..%d=%d cylinders, 0..%d=%d heads, 1..%d=%d sectors\n",
- max_cylinder, max_cylinder + 1,
- max_head, max_head + 1,
- max_sector, max_sector);
- }
- printf(" %d accounted for\n", bootinfo.bi_n_bios_used);
- }
-#endif
-
- printf("Device configuration finished.\n");
- }
cold = 0;
}
diff --git a/sys/amd64/amd64/cpu_switch.S b/sys/amd64/amd64/cpu_switch.S
index a19baa705749..8cca838f0b8a 100644
--- a/sys/amd64/amd64/cpu_switch.S
+++ b/sys/amd64/amd64/cpu_switch.S
@@ -36,9 +36,6 @@
* $FreeBSD$
*/
-#include "opt_npx.h"
-#include "opt_swtch.h"
-
#include <machine/asmacros.h>
#include "assym.s"
@@ -57,37 +54,26 @@
* about its state. This is only a slight optimization and is probably
* not worth it anymore. Note that we need to clear the pm_active bits so
* we do need the old proc if it still exists.
- * 0(%esp) = ret
- * 4(%esp) = oldtd
- * 8(%esp) = newtd
+ * %rdi = oldtd
+ * %rsi = newtd
*/
ENTRY(cpu_throw)
- movl PCPU(CPUID), %esi
- movl 4(%esp),%ecx /* Old thread */
- testl %ecx,%ecx /* no thread? */
+ xorq %rax, %rax
+ movl PCPU(CPUID), %eax
+ testq %rdi,%rdi /* no thread? */
jz 1f
/* release bit from old pm_active */
- movl TD_PROC(%ecx), %eax /* thread->td_proc */
- movl P_VMSPACE(%eax), %ebx /* proc->p_vmspace */
-#ifdef SMP
- lock
-#endif
- btrl %esi, VM_PMAP+PM_ACTIVE(%ebx) /* clear old */
+ movq TD_PROC(%rdi), %rdx /* oldtd->td_proc */
+ movq P_VMSPACE(%rdx), %rdx /* proc->p_vmspace */
+ btrq %rax, VM_PMAP+PM_ACTIVE(%rdx) /* clear old */
1:
- movl 8(%esp),%ecx /* New thread */
- movl TD_PCB(%ecx),%edx
-#ifdef SWTCH_OPTIM_STATS
- incl tlb_flush_count
-#endif
- movl PCB_CR3(%edx),%eax
- movl %eax,%cr3 /* new address space */
+ 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 */
- movl TD_PROC(%ecx),%eax
- movl P_VMSPACE(%eax), %ebx
-#ifdef SMP
- lock
-#endif
- btsl %esi, VM_PMAP+PM_ACTIVE(%ebx) /* set new */
+ movq TD_PROC(%rsi),%rdx
+ movq P_VMSPACE(%rdx), %rdx
+ btsq %rax, VM_PMAP+PM_ACTIVE(%rdx) /* set new */
jmp sw1
/*
@@ -95,278 +81,184 @@ ENTRY(cpu_throw)
*
* Save the current thread state, then select the next thread to run
* and load its state.
- * 0(%esp) = ret
- * 4(%esp) = oldtd
- * 8(%esp) = newtd
+ * %rdi = oldtd
+ * %rsi = newtd
*/
ENTRY(cpu_switch)
/* Switch to new thread. First, save context. */
- movl 4(%esp),%ecx
-
#ifdef INVARIANTS
- testl %ecx,%ecx /* no thread? */
+ testq %rdi,%rdi /* no thread? */
jz badsw2 /* no, panic */
#endif
- movl TD_PCB(%ecx),%edx
+ movq TD_PCB(%rdi),%rdx
- movl (%esp),%eax /* Hardware registers */
- movl %eax,PCB_EIP(%edx)
- movl %ebx,PCB_EBX(%edx)
- movl %esp,PCB_ESP(%edx)
- movl %ebp,PCB_EBP(%edx)
- movl %esi,PCB_ESI(%edx)
- movl %edi,PCB_EDI(%edx)
- movl %gs,PCB_GS(%edx)
- pushfl /* PSL */
- popl PCB_PSL(%edx)
+ movq (%rsp),%rax /* Hardware registers */
+ movq %rax,PCB_RIP(%rdx)
+ movq %rbx,PCB_RBX(%rdx)
+ movq %rsp,PCB_RSP(%rdx)
+ movq %rbp,PCB_RBP(%rdx)
+ movq %r12,PCB_R12(%rdx)
+ movq %r13,PCB_R13(%rdx)
+ movq %r14,PCB_R14(%rdx)
+ movq %r15,PCB_R15(%rdx)
+ pushfq /* PSL */
+ popq PCB_RFLAGS(%rdx)
- /* Test if debug registers should be saved. */
- testl $PCB_DBREGS,PCB_FLAGS(%edx)
- jz 1f /* no, skip over */
- movl %dr7,%eax /* yes, do the save */
- movl %eax,PCB_DR7(%edx)
- andl $0x0000fc00, %eax /* disable all watchpoints */
- movl %eax,%dr7
- movl %dr6,%eax
- movl %eax,PCB_DR6(%edx)
- movl %dr3,%eax
- movl %eax,PCB_DR3(%edx)
- movl %dr2,%eax
- movl %eax,PCB_DR2(%edx)
- movl %dr1,%eax
- movl %eax,PCB_DR1(%edx)
- movl %dr0,%eax
- movl %eax,PCB_DR0(%edx)
-1:
-
-#ifdef DEV_NPX
/* have we used fp, and need a save? */
- cmpl %ecx,PCPU(FPCURTHREAD)
+ cmpq %rdi,PCPU(FPCURTHREAD)
jne 1f
- addl $PCB_SAVEFPU,%edx /* h/w bugs make saving complicated */
- pushl %edx
+ pushq %rdi
+ pushq %rsi
+ addq $PCB_SAVEFPU,%rdx /* h/w bugs make saving complicated */
+ movq %rdx, %rdi
call npxsave /* do it in a big C function */
- popl %eax
+ popq %rsi
+ popq %rdi
1:
-#endif
/* Save is done. Now fire up new thread. Leave old vmspace. */
- movl %ecx,%edi
- movl 8(%esp),%ecx /* New thread */
#ifdef INVARIANTS
- testl %ecx,%ecx /* no thread? */
+ testq %rsi,%rsi /* no thread? */
jz badsw3 /* no, panic */
#endif
- movl TD_PCB(%ecx),%edx
- movl PCPU(CPUID), %esi
+ movq TD_PCB(%rsi),%rdx
+ xorq %rax, %rax
+ movl PCPU(CPUID), %eax
/* switch address space */
- movl PCB_CR3(%edx),%eax
-#ifdef LAZY_SWITCH
- cmpl $0,lazy_flush_enable
- je 1f
- cmpl %eax,IdlePTD /* Kernel address space? */
-#ifdef SWTCH_OPTIM_STATS
- je 3f
-#else
- je sw1
-#endif
-1:
-#endif
- movl %cr3,%ebx /* The same address space? */
- cmpl %ebx,%eax
-#ifdef SWTCH_OPTIM_STATS
- je 2f /* Yes, skip all that cruft */
-#else
- je sw1
-#endif
-#ifdef SWTCH_OPTIM_STATS
- incl tlb_flush_count
-#endif
- movl %eax,%cr3 /* new address space */
+ movq PCB_CR3(%rdx),%rdx
+ movq %rdx,%cr3 /* new address space */
/* Release bit from old pmap->pm_active */
- movl TD_PROC(%edi), %eax /* oldproc */
- movl P_VMSPACE(%eax), %ebx
-#ifdef SMP
- lock
-#endif
- btrl %esi, VM_PMAP+PM_ACTIVE(%ebx) /* clear old */
+ movq TD_PROC(%rdi), %rdx /* oldproc */
+ movq P_VMSPACE(%rdx), %rdx
+ btrq %rax, VM_PMAP+PM_ACTIVE(%rdx) /* clear old */
/* Set bit in new pmap->pm_active */
- movl TD_PROC(%ecx),%eax /* newproc */
- movl P_VMSPACE(%eax), %ebx
-#ifdef SMP
- lock
-#endif
- btsl %esi, VM_PMAP+PM_ACTIVE(%ebx) /* set new */
-
-#ifdef LAZY_SWITCH
-#ifdef SWTCH_OPTIM_STATS
- jmp sw1
-
-2: /* same address space */
- incl swtch_optim_stats
- jmp sw1
-
-3: /* kernel address space */
- incl lazy_flush_count
-#endif
-#endif
+ movq TD_PROC(%rsi),%rdx /* newproc */
+ movq P_VMSPACE(%rdx), %rdx
+ btsq %rax, VM_PMAP+PM_ACTIVE(%rdx) /* set new */
sw1:
/*
* At this point, we've switched address spaces and are ready
* to load up the rest of the next context.
*/
- cmpl $0, PCB_EXT(%edx) /* has pcb extension? */
- je 1f /* If not, use the default */
- btsl %esi, private_tss /* mark use of private tss */
- movl PCB_EXT(%edx), %edi /* new tss descriptor */
- jmp 2f /* Load it up */
+ movq TD_PCB(%rsi),%rdx
-1: /*
- * Use the common default TSS instead of our own.
- * Set our stack pointer into the TSS, it's set to just
- * below the PCB. In C, common_tss.tss_esp0 = &pcb - 16;
- */
- leal -16(%edx), %ebx /* leave space for vm86 */
- movl %ebx, PCPU(COMMON_TSS) + TSS_ESP0
-
- /*
- * Test this CPU's bit in the bitmap to see if this
- * CPU was using a private TSS.
- */
- btrl %esi, private_tss /* Already using the common? */
- jae 3f /* if so, skip reloading */
- PCPU_ADDR(COMMON_TSSD, %edi)
-2:
- /* Move correct tss descriptor into GDT slot, then reload tr. */
- movl PCPU(TSS_GDT), %ebx /* entry in GDT */
- movl 0(%edi), %eax
- movl %eax, 0(%ebx)
- movl 4(%edi), %eax
- movl %eax, 4(%ebx)
- movl $GPROC0_SEL*8, %esi /* GSEL(entry, SEL_KPL) */
- ltr %si
-3:
+ /* Update the TSS_RSP0 pointer for the next interrupt */
+ leaq -16(%rdx), %rbx
+ movq %rbx, common_tss + COMMON_TSS_RSP0
/* Restore context. */
- movl PCB_EBX(%edx),%ebx
- movl PCB_ESP(%edx),%esp
- movl PCB_EBP(%edx),%ebp
- movl PCB_ESI(%edx),%esi
- movl PCB_EDI(%edx),%edi
- movl PCB_EIP(%edx),%eax
- movl %eax,(%esp)
- pushl PCB_PSL(%edx)
- popfl
-
- movl %edx, PCPU(CURPCB)
- movl %ecx, PCPU(CURTHREAD) /* into next thread */
+ movq PCB_RBX(%rdx),%rbx
+ movq PCB_RSP(%rdx),%rsp
+ movq PCB_RBP(%rdx),%rbp
+ movq PCB_R12(%rdx),%r12
+ movq PCB_R13(%rdx),%r13
+ movq PCB_R14(%rdx),%r14
+ movq PCB_R15(%rdx),%r15
+ movq PCB_RIP(%rdx),%rax
+ movq %rax,(%rsp)
+ pushq PCB_RFLAGS(%rdx)
+ popfq
+
+ movq %rdx, PCPU(CURPCB)
+ movq %rsi, PCPU(CURTHREAD) /* into next thread */
- /*
- * Determine the LDT to use and load it if is the default one and
- * that is not the current one.
- */
- movl TD_PROC(%ecx),%eax
- cmpl $0,P_MD+MD_LDT(%eax)
- jnz 1f
- movl _default_ldt,%eax
- cmpl PCPU(CURRENTLDT),%eax
- je 2f
- lldt _default_ldt
- movl %eax,PCPU(CURRENTLDT)
- jmp 2f
-1:
- /* Load the LDT when it is not the default one. */
- pushl %edx /* Preserve pointer to pcb. */
- addl $P_MD,%eax /* Pointer to mdproc is arg. */
- pushl %eax
- call set_user_ldt
- addl $4,%esp
- popl %edx
-2:
-
- /* This must be done after loading the user LDT. */
- .globl cpu_switch_load_gs
-cpu_switch_load_gs:
- movl PCB_GS(%edx),%gs
-
- /* Test if debug registers should be restored. */
- testl $PCB_DBREGS,PCB_FLAGS(%edx)
- jz 1f
-
- /*
- * Restore debug registers. The special code for dr7 is to
- * preserve the current values of its reserved bits.
- */
- movl PCB_DR6(%edx),%eax
- movl %eax,%dr6
- movl PCB_DR3(%edx),%eax
- movl %eax,%dr3
- movl PCB_DR2(%edx),%eax
- movl %eax,%dr2
- movl PCB_DR1(%edx),%eax
- movl %eax,%dr1
- movl PCB_DR0(%edx),%eax
- movl %eax,%dr0
- movl %dr7,%eax
- andl $0x0000fc00,%eax
- movl PCB_DR7(%edx),%ecx
- andl $~0x0000fc00,%ecx
- orl %ecx,%eax
- movl %eax,%dr7
-1:
ret
#ifdef INVARIANTS
badsw1:
- pushal
- pushl $sw0_1
+ pushq %rax
+ pushq %rcx
+ pushq %rdx
+ pushq %rbx
+ pushq %rbp
+ pushq %rsi
+ pushq %rdi
+ pushq %r8
+ pushq %r9
+ pushq %r10
+ pushq %r11
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ pushq $sw0_1
call panic
sw0_1: .asciz "cpu_throw: no newthread supplied"
badsw2:
- pushal
- pushl $sw0_2
+ pushq %rax
+ pushq %rcx
+ pushq %rdx
+ pushq %rbx
+ pushq %rbp
+ pushq %rsi
+ pushq %rdi
+ pushq %r8
+ pushq %r9
+ pushq %r10
+ pushq %r11
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ pushq $sw0_2
call panic
sw0_2: .asciz "cpu_switch: no curthread supplied"
badsw3:
- pushal
- pushl $sw0_3
+ pushq %rax
+ pushq %rcx
+ pushq %rdx
+ pushq %rbx
+ pushq %rbp
+ pushq %rsi
+ pushq %rdi
+ pushq %r8
+ pushq %r9
+ pushq %r10
+ pushq %r11
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ pushq $sw0_3
call panic
sw0_3: .asciz "cpu_switch: no newthread supplied"
#endif
+noswitch: .asciz "cpu_switch: called!"
+nothrow: .asciz "cpu_throw: called!"
/*
* savectx(pcb)
* Update pcb, saving current processor state.
*/
ENTRY(savectx)
/* Fetch PCB. */
- movl 4(%esp),%ecx
+ movq %rdi,%rcx
- /* Save caller's return address. Child won't execute this routine. */
- movl (%esp),%eax
- movl %eax,PCB_EIP(%ecx)
+ /* Save caller's return address. */
+ movq (%rsp),%rax
+ movq %rax,PCB_RIP(%rcx)
- movl %cr3,%eax
- movl %eax,PCB_CR3(%ecx)
+ movq %cr3,%rax
+ movq %rax,PCB_CR3(%rcx)
- movl %ebx,PCB_EBX(%ecx)
- movl %esp,PCB_ESP(%ecx)
- movl %ebp,PCB_EBP(%ecx)
- movl %esi,PCB_ESI(%ecx)
- movl %edi,PCB_EDI(%ecx)
- movl %gs,PCB_GS(%ecx)
- pushfl
- popl PCB_PSL(%ecx)
+ movq %rbx,PCB_RBX(%rcx)
+ movq %rsp,PCB_RSP(%rcx)
+ movq %rbp,PCB_RBP(%rcx)
+ movq %r12,PCB_R12(%rcx)
+ movq %r13,PCB_R13(%rcx)
+ movq %r14,PCB_R14(%rcx)
+ movq %r15,PCB_R15(%rcx)
+ pushfq
+ popq PCB_RFLAGS(%rcx)
-#ifdef DEV_NPX
/*
* If fpcurthread == NULL, then the npx h/w state is irrelevant and the
* state had better already be in the pcb. This is true for forks
@@ -379,30 +271,25 @@ ENTRY(savectx)
* have to handle h/w bugs for reloading. We used to lose the
* parent's npx state for forks by forgetting to reload.
*/
- pushfl
+ pushfq
cli
- movl PCPU(FPCURTHREAD),%eax
- testl %eax,%eax
+ movq PCPU(FPCURTHREAD),%rax
+ testq %rax,%rax
je 1f
- pushl %ecx
- movl TD_PCB(%eax),%eax
- leal PCB_SAVEFPU(%eax),%eax
- pushl %eax
- pushl %eax
+ pushq %rcx
+ pushq %rax
+ movq TD_PCB(%rax),%rdi
+ leaq PCB_SAVEFPU(%rdi),%rdi
call npxsave
- addl $4,%esp
- popl %eax
- popl %ecx
+ popq %rax
+ popq %rcx
- pushl $PCB_SAVEFPU_SIZE
- leal PCB_SAVEFPU(%ecx),%ecx
- pushl %ecx
- pushl %eax
+ movq $PCB_SAVEFPU_SIZE,%rdx /* arg 3 */
+ leaq PCB_SAVEFPU(%rcx),%rsi /* arg 2 */
+ movq %rax,%rdi /* arg 1 */
call bcopy
- addl $12,%esp
1:
- popfl
-#endif /* DEV_NPX */
+ popfq
ret
diff --git a/sys/amd64/amd64/critical.c b/sys/amd64/amd64/critical.c
index 1a74b954faf6..c8a1a88e4982 100644
--- a/sys/amd64/amd64/critical.c
+++ b/sys/amd64/amd64/critical.c
@@ -18,145 +18,25 @@
#include <machine/clock.h>
#include <machine/critical.h>
-#ifdef SMP
-#include <machine/privatespace.h>
-#include <machine/smp.h>
-#else
/*
- * XXX this mess to get sched_ithd() and call_fast_unpend()
- */
-#include <sys/bus.h>
-#include <machine/apic.h>
-#include <machine/frame.h>
-#include <i386/isa/icu.h>
-#include <i386/isa/intr_machdep.h>
-#endif
-
-void i386_unpend(void); /* NOTE: not static, called from assembly */
-
-/*
- * cpu_unpend() - called from critical_exit() inline after quick
- * interrupt-pending check.
+ * cpu_critical_fork_exit() - cleanup after fork
*/
void
-cpu_unpend(void)
+cpu_critical_fork_exit(void)
{
- register_t eflags;
struct thread *td;
td = curthread;
- eflags = intr_disable();
- if (PCPU_GET(int_pending)) {
- ++td->td_intr_nesting_level;
- i386_unpend();
- --td->td_intr_nesting_level;
- }
- intr_restore(eflags);
-}
-
-/*
- * cpu_critical_fork_exit() - cleanup after fork
- *
- * For i386 we do not have to do anything, td_critnest is
- * handled by the fork trampoline code.
- */
-void
-cpu_critical_fork_exit(void)
-{
+ td->td_critnest = 1;
+ td->td_md.md_savecrit = read_rflags() | PSL_I;
}
/*
* cpu_thread_link() - thread linkup, initialize machine-dependant fields
- *
- * There are currently no machine-dependant fields that require
- * initialization.
*/
void
cpu_thread_link(struct thread *td)
{
-}
-
-/*
- * Called from cpu_unpend or called from the assembly vector code
- * to process any interrupts which may have occured while we were in
- * a critical section.
- *
- * - interrupts must be disabled
- * - td_critnest must be 0
- * - td_intr_nesting_level must be incremented by the caller
- *
- * NOT STATIC (called from assembly)
- */
-void
-i386_unpend(void)
-{
- struct clockframe frame;
-
- frame.cf_cs = SEL_KPL;
- frame.cf_eip = (register_t)i386_unpend;
- frame.cf_eflags = PSL_KERNEL;
- KASSERT(curthread->td_critnest == 0, ("unpend critnest != 0"));
- KASSERT((read_eflags() & PSL_I) == 0, ("unpend interrupts enabled1"));
- curthread->td_critnest = 1;
- for (;;) {
- u_int32_t mask;
- int irq;
-
- /*
- * Fast interrupts have priority
- */
- if ((mask = PCPU_GET(fpending)) != 0) {
- irq = bsfl(mask);
- PCPU_SET(fpending, mask & ~(1 << irq));
- call_fast_unpend(irq);
- KASSERT((read_eflags() & PSL_I) == 0,
- ("unpend interrupts enabled2 %d", irq));
- continue;
- }
-
- /*
- * Threaded interrupts come next
- */
- if ((mask = PCPU_GET(ipending)) != 0) {
- irq = bsfl(mask);
- PCPU_SET(ipending, mask & ~(1 << irq));
- sched_ithd((void *)irq);
- KASSERT((read_eflags() & PSL_I) == 0,
- ("unpend interrupts enabled3 %d", irq));
- continue;
- }
- /*
- * Software interrupts and delayed IPIs are last
- *
- * XXX give the bits #defined names. see also
- * isa/xxx_vector.s
- */
- if ((mask = PCPU_GET(spending)) != 0) {
- irq = bsfl(mask);
- PCPU_SET(spending, mask & ~(1 << irq));
- switch(irq) {
- case 0: /* bit 0 - hardclock */
- hardclock_process(&frame);
- break;
- case 1: /* bit 1 - statclock */
- if (profprocs != 0)
- profclock(&frame);
- if (pscnt == psdiv)
- statclock(&frame);
- break;
- }
- KASSERT((read_eflags() & PSL_I) == 0,
- ("unpend interrupts enabled4 %d", irq));
- continue;
- }
- break;
- }
- /*
- * Interrupts are still disabled, we can safely clear int_pending
- * and td_critnest.
- */
- KASSERT((read_eflags() & PSL_I) == 0, ("unpend interrupts enabled5"));
- PCPU_SET(int_pending, 0);
- curthread->td_critnest = 0;
+ td->td_md.md_savecrit = 0;
}
diff --git a/sys/amd64/amd64/dump_machdep.c b/sys/amd64/amd64/dump_machdep.c
index 3f3acc729d76..91f53ec8ffbd 100644
--- a/sys/amd64/amd64/dump_machdep.c
+++ b/sys/amd64/amd64/dump_machdep.c
@@ -63,7 +63,7 @@ dumpsys(struct dumperinfo *di)
/* Fill in the kernel dump header */
strcpy(kdh.magic, KERNELDUMPMAGIC);
- strcpy(kdh.architecture, "i386");
+ strcpy(kdh.architecture, "amd64");
kdh.version = htod32(KERNELDUMPVERSION);
kdh.architectureversion = htod32(KERNELDUMP_I386_VERSION);
kdh.dumplength = htod64(Maxmem * (off_t)PAGE_SIZE);
diff --git a/sys/amd64/amd64/elf_machdep.c b/sys/amd64/amd64/elf_machdep.c
index 4cf9f216e8e8..d7a9fb9f37bc 100644
--- a/sys/amd64/amd64/elf_machdep.c
+++ b/sys/amd64/amd64/elf_machdep.c
@@ -44,7 +44,7 @@
#include <machine/elf.h>
#include <machine/md_var.h>
-struct sysentvec elf32_freebsd_sysvec = {
+struct sysentvec elf64_freebsd_sysvec = {
SYS_MAXSYSCALL,
sysent,
0,
@@ -58,7 +58,7 @@ struct sysentvec elf32_freebsd_sysvec = {
sigcode,
&szsigcode,
NULL,
- "FreeBSD ELF32",
+ "FreeBSD ELF64",
__elfN(coredump),
NULL,
MINSIGSTKSZ,
@@ -72,17 +72,17 @@ struct sysentvec elf32_freebsd_sysvec = {
exec_setregs
};
-static Elf32_Brandinfo freebsd_brand_info = {
+static Elf64_Brandinfo freebsd_brand_info = {
ELFOSABI_FREEBSD,
- EM_386,
+ EM_X86_64,
"FreeBSD",
"",
"/usr/libexec/ld-elf.so.1",
- &elf32_freebsd_sysvec
+ &elf64_freebsd_sysvec
};
-SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY,
- (sysinit_cfunc_t) elf32_insert_brand_entry,
+SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t) elf64_insert_brand_entry,
&freebsd_brand_info);
/* Process one elf relocation with addend. */
@@ -117,7 +117,7 @@ elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
}
if (local) {
- if (rtype == R_386_RELATIVE) { /* A + B */
+ if (rtype == R_X86_64_RELATIVE) { /* A + B */
addr = relocbase + addend;
if (*where != addr)
*where = addr;
@@ -127,10 +127,10 @@ elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
switch (rtype) {
- case R_386_NONE: /* none */
+ case R_X86_64_NONE: /* none */
break;
- case R_386_32: /* S + A */
+ case R_X86_64_64: /* S + A */
addr = elf_lookup(lf, symidx, 1);
if (addr == 0)
return -1;
@@ -139,16 +139,17 @@ elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
*where = addr;
break;
- case R_386_PC32: /* S + A - P */
+ case R_X86_64_PC32: /* S + A - P */
addr = elf_lookup(lf, symidx, 1);
if (addr == 0)
return -1;
addr += addend - (Elf_Addr)where;
+ /* XXX needs to be 32 bit *where, not 64 bit */
if (*where != addr)
*where = addr;
break;
- case R_386_COPY: /* none */
+ case R_X86_64_COPY: /* none */
/*
* There shouldn't be copy relocations in kernel
* objects.
@@ -157,7 +158,7 @@ elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
return -1;
break;
- case R_386_GLOB_DAT: /* S */
+ case R_X86_64_GLOB_DAT: /* S */
addr = elf_lookup(lf, symidx, 1);
if (addr == 0)
return -1;
@@ -165,7 +166,7 @@ elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
*where = addr;
break;
- case R_386_RELATIVE:
+ case R_X86_64_RELATIVE: /* B + A */
break;
default:
diff --git a/sys/amd64/amd64/exception.S b/sys/amd64/amd64/exception.S
index ce07659daef2..8ff6020a93ca 100644
--- a/sys/amd64/amd64/exception.S
+++ b/sys/amd64/amd64/exception.S
@@ -34,15 +34,10 @@
* $FreeBSD$
*/
-#include "opt_npx.h"
-
#include <machine/asmacros.h>
#include <sys/mutex.h>
#include <machine/psl.h>
#include <machine/trap.h>
-#ifdef SMP
-#include <machine/smptests.h> /** various SMP options */
-#endif
#include "assym.s"
@@ -79,29 +74,29 @@
*/
#define IDTVEC(name) ALIGN_TEXT; .globl __CONCAT(X,name); \
.type __CONCAT(X,name),@function; __CONCAT(X,name):
-#define TRAP(a) pushl $(a) ; jmp alltraps
+#define TRAP(a) pushq $(a) ; jmp alltraps
MCOUNT_LABEL(user)
MCOUNT_LABEL(btrap)
IDTVEC(div)
- pushl $0; TRAP(T_DIVIDE)
+ pushq $0; TRAP(T_DIVIDE)
IDTVEC(dbg)
- pushl $0; TRAP(T_TRCTRAP)
+ pushq $0; TRAP(T_TRCTRAP)
IDTVEC(nmi)
- pushl $0; TRAP(T_NMI)
+ pushq $0; TRAP(T_NMI)
IDTVEC(bpt)
- pushl $0; TRAP(T_BPTFLT)
+ pushq $0; TRAP(T_BPTFLT)
IDTVEC(ofl)
- pushl $0; TRAP(T_OFLOW)
+ pushq $0; TRAP(T_OFLOW)
IDTVEC(bnd)
- pushl $0; TRAP(T_BOUND)
+ pushq $0; TRAP(T_BOUND)
IDTVEC(ill)
- pushl $0; TRAP(T_PRIVINFLT)
+ pushq $0; TRAP(T_PRIVINFLT)
IDTVEC(dna)
- pushl $0; TRAP(T_DNA)
+ pushq $0; TRAP(T_DNA)
IDTVEC(fpusegm)
- pushl $0; TRAP(T_FPOPFLT)
+ pushq $0; TRAP(T_FPOPFLT)
IDTVEC(tss)
TRAP(T_TSSFLT)
IDTVEC(missing)
@@ -113,16 +108,15 @@ IDTVEC(prot)
IDTVEC(page)
TRAP(T_PAGEFLT)
IDTVEC(mchk)
- pushl $0; TRAP(T_MCHK)
+ pushq $0; TRAP(T_MCHK)
IDTVEC(rsvd)
- pushl $0; TRAP(T_RESERVED)
+ pushq $0; TRAP(T_RESERVED)
IDTVEC(fpu)
- pushl $0; TRAP(T_ARITHTRAP)
+ pushq $0; TRAP(T_ARITHTRAP)
IDTVEC(align)
TRAP(T_ALIGNFLT)
-
IDTVEC(xmm)
- pushl $0; TRAP(T_XMMFLT)
+ pushq $0; TRAP(T_XMMFLT)
/*
* alltraps entry point. Interrupts are enabled if this was a trap
@@ -135,31 +129,36 @@ IDTVEC(xmm)
.globl alltraps
.type alltraps,@function
alltraps:
- pushal
- pushl %ds
- pushl %es
- pushl %fs
+ subq $TF_TRAPNO,%rsp /* tf_err and tf_trapno already pushed */
+ 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)
alltraps_with_regs_pushed:
- mov $KDSEL,%ax
- mov %ax,%ds
- mov %ax,%es
- mov $KPSEL,%ax
- mov %ax,%fs
- FAKE_MCOUNT(13*4(%esp))
+ FAKE_MCOUNT(13*4(%rsp))
calltrap:
FAKE_MCOUNT(btrap) /* init "from" btrap -> calltrap */
call trap
-
- /*
- * Return via doreti to handle ASTs.
- */
MEXITCOUNT
- jmp doreti
+ jmp doreti /* Handle any pending ASTs */
/*
- * SYSCALL CALL GATE (old entry point for a.out binaries)
+ * Call gate entry for FreeBSD ELF and Linux/NetBSD syscall (int 0x80)
*
- * The intersegment call has been set up to specify one dummy parameter.
+ * Even though the name says 'int0x80', this is actually a TGT (trap gate)
+ * rather then an IGT (interrupt gate). Thus interrupts are enabled on
+ * entry just as they are for a normal syscall.
*
* This leaves a place to put eflags so that the call frame can be
* converted to a trap frame. Note that the eflags is (semi-)bogusly
@@ -169,79 +168,122 @@ calltrap:
* and clobber the saved cs/eip.
*/
SUPERALIGN_TEXT
-IDTVEC(lcall_syscall)
- pushfl /* save eflags */
- popl 8(%esp) /* shuffle into tf_eflags */
- pushl $7 /* sizeof "lcall 7,0" */
- subl $4,%esp /* skip over tf_trapno */
- pushal
- pushl %ds
- pushl %es
- pushl %fs
- mov $KDSEL,%ax /* switch to kernel segments */
- mov %ax,%ds
- mov %ax,%es
- mov $KPSEL,%ax
- mov %ax,%fs
- FAKE_MCOUNT(13*4(%esp))
+IDTVEC(int0x80_syscall)
+ pushq $2 /* sizeof "int 0x80" */
+ subq $TF_ERR,%rsp /* skip over tf_trapno */
+ 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)
+ FAKE_MCOUNT(13*4(%rsp))
call syscall
MEXITCOUNT
jmp doreti
/*
- * Call gate entry for FreeBSD ELF and Linux/NetBSD syscall (int 0x80)
- *
- * Even though the name says 'int0x80', this is actually a TGT (trap gate)
- * rather then an IGT (interrupt gate). Thus interrupts are enabled on
- * entry just as they are for a normal syscall.
+ * Fast syscall entry point. We enter here with just our new %cs/%ss set,
+ * and the new privilige level. We are still running on the old user stack
+ * pointer. We have to juggle a few things around to find our stack etc.
+ * swapgs gives us access to our PCPU space only.
+ * XXX The PCPU stuff is stubbed out right now...
*/
- SUPERALIGN_TEXT
-IDTVEC(int0x80_syscall)
- pushl $2 /* sizeof "int 0x80" */
- subl $4,%esp /* skip over tf_trapno */
- pushal
- pushl %ds
- pushl %es
- pushl %fs
- mov $KDSEL,%ax /* switch to kernel segments */
- mov %ax,%ds
- mov %ax,%es
- mov $KPSEL,%ax
- mov %ax,%fs
- FAKE_MCOUNT(13*4(%esp))
+IDTVEC(fast_syscall)
+ #swapgs
+ movq %rsp,PCPU(SCRATCH_RSP)
+ movq common_tss+COMMON_TSS_RSP0,%rsp
+ sti
+ /* Now emulate a trapframe. Ugh. */
+ subq $TF_SIZE,%rsp
+ movq $KUDSEL,TF_SS(%rsp)
+ /* defer TF_RSP till we have a spare register */
+ movq %r11,TF_RFLAGS(%rsp)
+ movq $KUCSEL,TF_CS(%rsp)
+ movq %rcx,TF_RIP(%rsp) /* %rcx original value is in %r10 */
+ movq $2,TF_ERR(%rsp)
+ movq %rdi,TF_RDI(%rsp) /* arg 1 */
+ movq %rsi,TF_RSI(%rsp) /* arg 2 */
+ movq %rdx,TF_RDX(%rsp) /* arg 3 */
+ movq %r10,TF_RCX(%rsp) /* arg 4 */
+ movq %r8,TF_R8(%rsp) /* arg 5 */
+ movq %r9,TF_R9(%rsp) /* arg 6 */
+ movq %rax,TF_RAX(%rsp) /* syscall number */
+ movq %rbx,TF_RBX(%rsp) /* C preserved */
+ movq %rbp,TF_RBP(%rsp) /* C preserved */
+ movq %r12,TF_R12(%rsp) /* C preserved */
+ movq %r13,TF_R13(%rsp) /* C preserved */
+ movq %r14,TF_R14(%rsp) /* C preserved */
+ movq %r15,TF_R15(%rsp) /* C preserved */
+ movq PCPU(SCRATCH_RSP),%r12 /* %r12 already saved */
+ movq %r12,TF_RSP(%rsp) /* user stack pointer */
call syscall
- MEXITCOUNT
+ movq PCPU(CURPCB),%rax
+ testq $PCB_FULLCTX,PCB_FLAGS(%rax)
+ jne 3f
+ /* simplified from doreti */
+1: /* Check for and handle AST's on return to userland */
+ cli
+ movq PCPU(CURTHREAD),%rax
+ testl $TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%rax)
+ je 2f
+ sti
+ movq %rsp, %rdi
+ call ast
+ jmp 1b
+2: /* restore preserved registers */
+ movq TF_RDI(%rsp),%rdi /* bonus; preserve arg 1 */
+ movq TF_RSI(%rsp),%rsi /* bonus: preserve arg 2 */
+ movq TF_RDX(%rsp),%rdx /* return value 2 */
+ movq TF_RAX(%rsp),%rax /* return value 1 */
+ movq TF_RBX(%rsp),%rbx /* C preserved */
+ movq TF_RBP(%rsp),%rbp /* C preserved */
+ movq TF_R12(%rsp),%r12 /* C preserved */
+ movq TF_R13(%rsp),%r13 /* C preserved */
+ movq TF_R14(%rsp),%r14 /* C preserved */
+ movq TF_R15(%rsp),%r15 /* C preserved */
+ movq TF_RFLAGS(%rsp),%r11 /* original %rflags */
+ movq TF_RIP(%rsp),%rcx /* original %rip */
+ movq TF_RSP(%rsp),%r9 /* user stack pointer */
+ movq %r9,%rsp /* original %rsp */
+ #swapgs
+ sysretq
+3: /* Requested full context restore, use doreti for that */
+ andq $~PCB_FULLCTX,PCB_FLAGS(%rax)
jmp doreti
+/*
+ * Here for CYA insurance, in case a "syscall" instruction gets
+ * issued from 32 bit compatability mode. MSR_CSTAR has to point
+ * to *something* if EFER_SCE is enabled.
+ */
+IDTVEC(fast_syscall32)
+ sysret
+
ENTRY(fork_trampoline)
- pushl %esp /* trapframe pointer */
- pushl %ebx /* arg1 */
- pushl %esi /* function */
- movl PCPU(CURTHREAD),%ebx /* setup critnest */
- movl $1,TD_CRITNEST(%ebx)
- sti /* enable interrupts */
+ movq %r12, %rdi /* function */
+ movq %rbx, %rsi /* arg1 */
+ movq %rsp, %rdx /* trapframe pointer */
call fork_exit
- addl $12,%esp
- /* cut from syscall */
-
- /*
- * Return via doreti to handle ASTs.
- */
MEXITCOUNT
- jmp doreti
+ jmp doreti /* Handle any ASTs */
/*
- * Include vm86 call routines, which want to call doreti.
- */
-#include "i386/i386/vm86bios.s"
-
-/*
* Include what was once config+isa-dependent code.
* XXX it should be in a stand-alone file. It's still icu-dependent and
* belongs in i386/isa.
*/
-#include "i386/isa/vector.s"
+#include "amd64/isa/vector.s"
.data
ALIGN_DATA
@@ -256,20 +298,10 @@ ENTRY(fork_trampoline)
.type doreti,@function
doreti:
FAKE_MCOUNT(bintr) /* init "from" bintr -> doreti */
-doreti_next:
/*
- * Check if ASTs can be handled now. PSL_VM must be checked first
- * since segment registers only have an RPL in non-VM86 mode.
+ * Check if ASTs can be handled now.
*/
- testl $PSL_VM,TF_EFLAGS(%esp) /* are we in vm86 mode? */
- jz doreti_notvm86
- movl PCPU(CURPCB),%ecx
- testl $PCB_VM86CALL,PCB_FLAGS(%ecx) /* are we in a vm86 call? */
- jz doreti_ast /* can handle ASTS now if not */
- jmp doreti_exit
-
-doreti_notvm86:
- testb $SEL_RPL_MASK,TF_CS(%esp) /* are we returning to user mode? */
+ testb $SEL_RPL_MASK,TF_CS(%rsp) /* are we returning to user mode? */
jz doreti_exit /* can't handle ASTs now if not */
doreti_ast:
@@ -279,13 +311,12 @@ doreti_ast:
* since we will be informed of any new ASTs by an IPI.
*/
cli
- movl PCPU(CURTHREAD),%eax
- testl $TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%eax)
+ movq PCPU(CURTHREAD),%rax
+ testl $TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%rax)
je doreti_exit
sti
- pushl %esp /* pass a pointer to the trapframe */
+ movq %rsp, %rdi /* pass a pointer to the trapframe */
call ast
- add $4,%esp
jmp doreti_ast
/*
@@ -298,20 +329,25 @@ doreti_ast:
doreti_exit:
MEXITCOUNT
- .globl doreti_popl_fs
-doreti_popl_fs:
- popl %fs
- .globl doreti_popl_es
-doreti_popl_es:
- popl %es
- .globl doreti_popl_ds
-doreti_popl_ds:
- popl %ds
- popal
- addl $8,%esp
+ 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
+ addq $TF_RIP,%rsp /* skip over tf_err, tf_trapno */
.globl doreti_iret
doreti_iret:
- iret
+ iretq
/*
* doreti_iret_fault and friends. Alternative return code for
@@ -323,23 +359,24 @@ doreti_iret:
ALIGN_TEXT
.globl doreti_iret_fault
doreti_iret_fault:
- subl $8,%esp
- pushal
- pushl %ds
- .globl doreti_popl_ds_fault
-doreti_popl_ds_fault:
- pushl %es
- .globl doreti_popl_es_fault
-doreti_popl_es_fault:
- pushl %fs
- .globl doreti_popl_fs_fault
-doreti_popl_fs_fault:
- movl $0,TF_ERR(%esp) /* XXX should be the error code */
- movl $T_PROTFLT,TF_TRAPNO(%esp)
+ subq $TF_RIP,%rsp /* space including tf_err, tf_trapno */
+ 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)
+ movq $T_PROTFLT,TF_TRAPNO(%rsp)
+ movq $0,TF_ERR(%rsp) /* XXX should be the error code */
jmp alltraps_with_regs_pushed
-#ifdef APIC_IO
-#include "i386/isa/apic_ipl.s"
-#else
-#include "i386/isa/icu_ipl.s"
-#endif /* APIC_IO */
+#include "amd64/isa/icu_ipl.s"
diff --git a/sys/amd64/amd64/exception.s b/sys/amd64/amd64/exception.s
index ce07659daef2..8ff6020a93ca 100644
--- a/sys/amd64/amd64/exception.s
+++ b/sys/amd64/amd64/exception.s
@@ -34,15 +34,10 @@
* $FreeBSD$
*/
-#include "opt_npx.h"
-
#include <machine/asmacros.h>
#include <sys/mutex.h>
#include <machine/psl.h>
#include <machine/trap.h>
-#ifdef SMP
-#include <machine/smptests.h> /** various SMP options */
-#endif
#include "assym.s"
@@ -79,29 +74,29 @@
*/
#define IDTVEC(name) ALIGN_TEXT; .globl __CONCAT(X,name); \
.type __CONCAT(X,name),@function; __CONCAT(X,name):
-#define TRAP(a) pushl $(a) ; jmp alltraps
+#define TRAP(a) pushq $(a) ; jmp alltraps
MCOUNT_LABEL(user)
MCOUNT_LABEL(btrap)
IDTVEC(div)
- pushl $0; TRAP(T_DIVIDE)
+ pushq $0; TRAP(T_DIVIDE)
IDTVEC(dbg)
- pushl $0; TRAP(T_TRCTRAP)
+ pushq $0; TRAP(T_TRCTRAP)
IDTVEC(nmi)
- pushl $0; TRAP(T_NMI)
+ pushq $0; TRAP(T_NMI)
IDTVEC(bpt)
- pushl $0; TRAP(T_BPTFLT)
+ pushq $0; TRAP(T_BPTFLT)
IDTVEC(ofl)
- pushl $0; TRAP(T_OFLOW)
+ pushq $0; TRAP(T_OFLOW)
IDTVEC(bnd)
- pushl $0; TRAP(T_BOUND)
+ pushq $0; TRAP(T_BOUND)
IDTVEC(ill)
- pushl $0; TRAP(T_PRIVINFLT)
+ pushq $0; TRAP(T_PRIVINFLT)
IDTVEC(dna)
- pushl $0; TRAP(T_DNA)
+ pushq $0; TRAP(T_DNA)
IDTVEC(fpusegm)
- pushl $0; TRAP(T_FPOPFLT)
+ pushq $0; TRAP(T_FPOPFLT)
IDTVEC(tss)
TRAP(T_TSSFLT)
IDTVEC(missing)
@@ -113,16 +108,15 @@ IDTVEC(prot)
IDTVEC(page)
TRAP(T_PAGEFLT)
IDTVEC(mchk)
- pushl $0; TRAP(T_MCHK)
+ pushq $0; TRAP(T_MCHK)
IDTVEC(rsvd)
- pushl $0; TRAP(T_RESERVED)
+ pushq $0; TRAP(T_RESERVED)
IDTVEC(fpu)
- pushl $0; TRAP(T_ARITHTRAP)
+ pushq $0; TRAP(T_ARITHTRAP)
IDTVEC(align)
TRAP(T_ALIGNFLT)
-
IDTVEC(xmm)
- pushl $0; TRAP(T_XMMFLT)
+ pushq $0; TRAP(T_XMMFLT)
/*
* alltraps entry point. Interrupts are enabled if this was a trap
@@ -135,31 +129,36 @@ IDTVEC(xmm)
.globl alltraps
.type alltraps,@function
alltraps:
- pushal
- pushl %ds
- pushl %es
- pushl %fs
+ subq $TF_TRAPNO,%rsp /* tf_err and tf_trapno already pushed */
+ 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)
alltraps_with_regs_pushed:
- mov $KDSEL,%ax
- mov %ax,%ds
- mov %ax,%es
- mov $KPSEL,%ax
- mov %ax,%fs
- FAKE_MCOUNT(13*4(%esp))
+ FAKE_MCOUNT(13*4(%rsp))
calltrap:
FAKE_MCOUNT(btrap) /* init "from" btrap -> calltrap */
call trap
-
- /*
- * Return via doreti to handle ASTs.
- */
MEXITCOUNT
- jmp doreti
+ jmp doreti /* Handle any pending ASTs */
/*
- * SYSCALL CALL GATE (old entry point for a.out binaries)
+ * Call gate entry for FreeBSD ELF and Linux/NetBSD syscall (int 0x80)
*
- * The intersegment call has been set up to specify one dummy parameter.
+ * Even though the name says 'int0x80', this is actually a TGT (trap gate)
+ * rather then an IGT (interrupt gate). Thus interrupts are enabled on
+ * entry just as they are for a normal syscall.
*
* This leaves a place to put eflags so that the call frame can be
* converted to a trap frame. Note that the eflags is (semi-)bogusly
@@ -169,79 +168,122 @@ calltrap:
* and clobber the saved cs/eip.
*/
SUPERALIGN_TEXT
-IDTVEC(lcall_syscall)
- pushfl /* save eflags */
- popl 8(%esp) /* shuffle into tf_eflags */
- pushl $7 /* sizeof "lcall 7,0" */
- subl $4,%esp /* skip over tf_trapno */
- pushal
- pushl %ds
- pushl %es
- pushl %fs
- mov $KDSEL,%ax /* switch to kernel segments */
- mov %ax,%ds
- mov %ax,%es
- mov $KPSEL,%ax
- mov %ax,%fs
- FAKE_MCOUNT(13*4(%esp))
+IDTVEC(int0x80_syscall)
+ pushq $2 /* sizeof "int 0x80" */
+ subq $TF_ERR,%rsp /* skip over tf_trapno */
+ 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)
+ FAKE_MCOUNT(13*4(%rsp))
call syscall
MEXITCOUNT
jmp doreti
/*
- * Call gate entry for FreeBSD ELF and Linux/NetBSD syscall (int 0x80)
- *
- * Even though the name says 'int0x80', this is actually a TGT (trap gate)
- * rather then an IGT (interrupt gate). Thus interrupts are enabled on
- * entry just as they are for a normal syscall.
+ * Fast syscall entry point. We enter here with just our new %cs/%ss set,
+ * and the new privilige level. We are still running on the old user stack
+ * pointer. We have to juggle a few things around to find our stack etc.
+ * swapgs gives us access to our PCPU space only.
+ * XXX The PCPU stuff is stubbed out right now...
*/
- SUPERALIGN_TEXT
-IDTVEC(int0x80_syscall)
- pushl $2 /* sizeof "int 0x80" */
- subl $4,%esp /* skip over tf_trapno */
- pushal
- pushl %ds
- pushl %es
- pushl %fs
- mov $KDSEL,%ax /* switch to kernel segments */
- mov %ax,%ds
- mov %ax,%es
- mov $KPSEL,%ax
- mov %ax,%fs
- FAKE_MCOUNT(13*4(%esp))
+IDTVEC(fast_syscall)
+ #swapgs
+ movq %rsp,PCPU(SCRATCH_RSP)
+ movq common_tss+COMMON_TSS_RSP0,%rsp
+ sti
+ /* Now emulate a trapframe. Ugh. */
+ subq $TF_SIZE,%rsp
+ movq $KUDSEL,TF_SS(%rsp)
+ /* defer TF_RSP till we have a spare register */
+ movq %r11,TF_RFLAGS(%rsp)
+ movq $KUCSEL,TF_CS(%rsp)
+ movq %rcx,TF_RIP(%rsp) /* %rcx original value is in %r10 */
+ movq $2,TF_ERR(%rsp)
+ movq %rdi,TF_RDI(%rsp) /* arg 1 */
+ movq %rsi,TF_RSI(%rsp) /* arg 2 */
+ movq %rdx,TF_RDX(%rsp) /* arg 3 */
+ movq %r10,TF_RCX(%rsp) /* arg 4 */
+ movq %r8,TF_R8(%rsp) /* arg 5 */
+ movq %r9,TF_R9(%rsp) /* arg 6 */
+ movq %rax,TF_RAX(%rsp) /* syscall number */
+ movq %rbx,TF_RBX(%rsp) /* C preserved */
+ movq %rbp,TF_RBP(%rsp) /* C preserved */
+ movq %r12,TF_R12(%rsp) /* C preserved */
+ movq %r13,TF_R13(%rsp) /* C preserved */
+ movq %r14,TF_R14(%rsp) /* C preserved */
+ movq %r15,TF_R15(%rsp) /* C preserved */
+ movq PCPU(SCRATCH_RSP),%r12 /* %r12 already saved */
+ movq %r12,TF_RSP(%rsp) /* user stack pointer */
call syscall
- MEXITCOUNT
+ movq PCPU(CURPCB),%rax
+ testq $PCB_FULLCTX,PCB_FLAGS(%rax)
+ jne 3f
+ /* simplified from doreti */
+1: /* Check for and handle AST's on return to userland */
+ cli
+ movq PCPU(CURTHREAD),%rax
+ testl $TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%rax)
+ je 2f
+ sti
+ movq %rsp, %rdi
+ call ast
+ jmp 1b
+2: /* restore preserved registers */
+ movq TF_RDI(%rsp),%rdi /* bonus; preserve arg 1 */
+ movq TF_RSI(%rsp),%rsi /* bonus: preserve arg 2 */
+ movq TF_RDX(%rsp),%rdx /* return value 2 */
+ movq TF_RAX(%rsp),%rax /* return value 1 */
+ movq TF_RBX(%rsp),%rbx /* C preserved */
+ movq TF_RBP(%rsp),%rbp /* C preserved */
+ movq TF_R12(%rsp),%r12 /* C preserved */
+ movq TF_R13(%rsp),%r13 /* C preserved */
+ movq TF_R14(%rsp),%r14 /* C preserved */
+ movq TF_R15(%rsp),%r15 /* C preserved */
+ movq TF_RFLAGS(%rsp),%r11 /* original %rflags */
+ movq TF_RIP(%rsp),%rcx /* original %rip */
+ movq TF_RSP(%rsp),%r9 /* user stack pointer */
+ movq %r9,%rsp /* original %rsp */
+ #swapgs
+ sysretq
+3: /* Requested full context restore, use doreti for that */
+ andq $~PCB_FULLCTX,PCB_FLAGS(%rax)
jmp doreti
+/*
+ * Here for CYA insurance, in case a "syscall" instruction gets
+ * issued from 32 bit compatability mode. MSR_CSTAR has to point
+ * to *something* if EFER_SCE is enabled.
+ */
+IDTVEC(fast_syscall32)
+ sysret
+
ENTRY(fork_trampoline)
- pushl %esp /* trapframe pointer */
- pushl %ebx /* arg1 */
- pushl %esi /* function */
- movl PCPU(CURTHREAD),%ebx /* setup critnest */
- movl $1,TD_CRITNEST(%ebx)
- sti /* enable interrupts */
+ movq %r12, %rdi /* function */
+ movq %rbx, %rsi /* arg1 */
+ movq %rsp, %rdx /* trapframe pointer */
call fork_exit
- addl $12,%esp
- /* cut from syscall */
-
- /*
- * Return via doreti to handle ASTs.
- */
MEXITCOUNT
- jmp doreti
+ jmp doreti /* Handle any ASTs */
/*
- * Include vm86 call routines, which want to call doreti.
- */
-#include "i386/i386/vm86bios.s"
-
-/*
* Include what was once config+isa-dependent code.
* XXX it should be in a stand-alone file. It's still icu-dependent and
* belongs in i386/isa.
*/
-#include "i386/isa/vector.s"
+#include "amd64/isa/vector.s"
.data
ALIGN_DATA
@@ -256,20 +298,10 @@ ENTRY(fork_trampoline)
.type doreti,@function
doreti:
FAKE_MCOUNT(bintr) /* init "from" bintr -> doreti */
-doreti_next:
/*
- * Check if ASTs can be handled now. PSL_VM must be checked first
- * since segment registers only have an RPL in non-VM86 mode.
+ * Check if ASTs can be handled now.
*/
- testl $PSL_VM,TF_EFLAGS(%esp) /* are we in vm86 mode? */
- jz doreti_notvm86
- movl PCPU(CURPCB),%ecx
- testl $PCB_VM86CALL,PCB_FLAGS(%ecx) /* are we in a vm86 call? */
- jz doreti_ast /* can handle ASTS now if not */
- jmp doreti_exit
-
-doreti_notvm86:
- testb $SEL_RPL_MASK,TF_CS(%esp) /* are we returning to user mode? */
+ testb $SEL_RPL_MASK,TF_CS(%rsp) /* are we returning to user mode? */
jz doreti_exit /* can't handle ASTs now if not */
doreti_ast:
@@ -279,13 +311,12 @@ doreti_ast:
* since we will be informed of any new ASTs by an IPI.
*/
cli
- movl PCPU(CURTHREAD),%eax
- testl $TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%eax)
+ movq PCPU(CURTHREAD),%rax
+ testl $TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%rax)
je doreti_exit
sti
- pushl %esp /* pass a pointer to the trapframe */
+ movq %rsp, %rdi /* pass a pointer to the trapframe */
call ast
- add $4,%esp
jmp doreti_ast
/*
@@ -298,20 +329,25 @@ doreti_ast:
doreti_exit:
MEXITCOUNT
- .globl doreti_popl_fs
-doreti_popl_fs:
- popl %fs
- .globl doreti_popl_es
-doreti_popl_es:
- popl %es
- .globl doreti_popl_ds
-doreti_popl_ds:
- popl %ds
- popal
- addl $8,%esp
+ 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
+ addq $TF_RIP,%rsp /* skip over tf_err, tf_trapno */
.globl doreti_iret
doreti_iret:
- iret
+ iretq
/*
* doreti_iret_fault and friends. Alternative return code for
@@ -323,23 +359,24 @@ doreti_iret:
ALIGN_TEXT
.globl doreti_iret_fault
doreti_iret_fault:
- subl $8,%esp
- pushal
- pushl %ds
- .globl doreti_popl_ds_fault
-doreti_popl_ds_fault:
- pushl %es
- .globl doreti_popl_es_fault
-doreti_popl_es_fault:
- pushl %fs
- .globl doreti_popl_fs_fault
-doreti_popl_fs_fault:
- movl $0,TF_ERR(%esp) /* XXX should be the error code */
- movl $T_PROTFLT,TF_TRAPNO(%esp)
+ subq $TF_RIP,%rsp /* space including tf_err, tf_trapno */
+ 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)
+ movq $T_PROTFLT,TF_TRAPNO(%rsp)
+ movq $0,TF_ERR(%rsp) /* XXX should be the error code */
jmp alltraps_with_regs_pushed
-#ifdef APIC_IO
-#include "i386/isa/apic_ipl.s"
-#else
-#include "i386/isa/icu_ipl.s"
-#endif /* APIC_IO */
+#include "amd64/isa/icu_ipl.s"
diff --git a/sys/amd64/amd64/fpu.c b/sys/amd64/amd64/fpu.c
index 8dadb6bcc9c3..2116701c696a 100644
--- a/sys/amd64/amd64/fpu.c
+++ b/sys/amd64/amd64/fpu.c
@@ -35,11 +35,8 @@
* $FreeBSD$
*/
-#include "opt_cpu.h"
#include "opt_debug_npx.h"
#include "opt_isa.h"
-#include "opt_math_emulate.h"
-#include "opt_npx.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -60,66 +57,34 @@
#include <sys/signalvar.h>
#include <sys/user.h>
-#ifndef SMP
-#include <machine/asmacros.h>
-#endif
#include <machine/cputypes.h>
#include <machine/frame.h>
#include <machine/md_var.h>
#include <machine/pcb.h>
#include <machine/psl.h>
-#ifndef SMP
-#include <machine/clock.h>
-#endif
#include <machine/resource.h>
#include <machine/specialreg.h>
#include <machine/segments.h>
#include <machine/ucontext.h>
-#ifndef SMP
-#include <i386/isa/icu.h>
-#ifdef PC98
-#include <pc98/pc98/pc98.h>
-#else
-#include <i386/isa/isa.h>
-#endif
-#endif
-#include <i386/isa/intr_machdep.h>
+#include <amd64/isa/intr_machdep.h>
#ifdef DEV_ISA
#include <isa/isavar.h>
#endif
-#if !defined(CPU_ENABLE_SSE) && defined(I686_CPU)
-#define CPU_ENABLE_SSE
-#endif
-#if defined(CPU_DISABLE_SSE)
-#undef CPU_ENABLE_SSE
-#endif
-
/*
* 387 and 287 Numeric Coprocessor Extension (NPX) Driver.
*/
-/* Configuration flags. */
-#define NPX_DISABLE_I586_OPTIMIZED_BCOPY (1 << 0)
-#define NPX_DISABLE_I586_OPTIMIZED_BZERO (1 << 1)
-#define NPX_DISABLE_I586_OPTIMIZED_COPYIO (1 << 2)
-#define NPX_PREFER_EMULATOR (1 << 3)
-
#if defined(__GNUC__) && !defined(lint)
#define fldcw(addr) __asm("fldcw %0" : : "m" (*(addr)))
#define fnclex() __asm("fnclex")
#define fninit() __asm("fninit")
-#define fnsave(addr) __asm __volatile("fnsave %0" : "=m" (*(addr)))
#define fnstcw(addr) __asm __volatile("fnstcw %0" : "=m" (*(addr)))
#define fnstsw(addr) __asm __volatile("fnstsw %0" : "=m" (*(addr)))
-#define fp_divide_by_0() __asm("fldz; fld1; fdiv %st,%st(1); fnop")
-#define frstor(addr) __asm("frstor %0" : : "m" (*(addr)))
-#ifdef CPU_ENABLE_SSE
#define fxrstor(addr) __asm("fxrstor %0" : : "m" (*(addr)))
#define fxsave(addr) __asm __volatile("fxsave %0" : "=m" (*(addr)))
-#endif
#define start_emulating() __asm("smsw %%ax; orb %0,%%al; lmsw %%ax" \
: : "n" (CR0_TS) : "ax")
#define stop_emulating() __asm("clts")
@@ -129,81 +94,31 @@
void fldcw(caddr_t addr);
void fnclex(void);
void fninit(void);
-void fnsave(caddr_t addr);
void fnstcw(caddr_t addr);
void fnstsw(caddr_t addr);
-void fp_divide_by_0(void);
-void frstor(caddr_t addr);
-#ifdef CPU_ENABLE_SSE
void fxsave(caddr_t addr);
void fxrstor(caddr_t addr);
-#endif
void start_emulating(void);
void stop_emulating(void);
#endif /* __GNUC__ */
-#ifdef CPU_ENABLE_SSE
-#define GET_FPU_CW(thread) \
- (cpu_fxsr ? \
- (thread)->td_pcb->pcb_save.sv_xmm.sv_env.en_cw : \
- (thread)->td_pcb->pcb_save.sv_87.sv_env.en_cw)
-#define GET_FPU_SW(thread) \
- (cpu_fxsr ? \
- (thread)->td_pcb->pcb_save.sv_xmm.sv_env.en_sw : \
- (thread)->td_pcb->pcb_save.sv_87.sv_env.en_sw)
-#else /* CPU_ENABLE_SSE */
-#define GET_FPU_CW(thread) \
- (thread->td_pcb->pcb_save.sv_87.sv_env.en_cw)
-#define GET_FPU_SW(thread) \
- (thread->td_pcb->pcb_save.sv_87.sv_env.en_sw)
-#endif /* CPU_ENABLE_SSE */
+#define GET_FPU_CW(thread) ((thread)->td_pcb->pcb_save.sv_env.en_cw)
+#define GET_FPU_SW(thread) ((thread)->td_pcb->pcb_save.sv_env.en_sw)
typedef u_char bool_t;
-static void fpusave(union savefpu *);
-static void fpurstor(union savefpu *);
static int npx_attach(device_t dev);
static void npx_identify(driver_t *driver, device_t parent);
-#ifndef SMP
-static void npx_intr(void *);
-#endif
static int npx_probe(device_t dev);
-#ifdef I586_CPU_XXX
-static long timezero(const char *funcname,
- void (*func)(void *buf, size_t len));
-#endif /* I586_CPU */
-
-int hw_float; /* XXX currently just alias for npx_exists */
+int hw_float = 1;
SYSCTL_INT(_hw,HW_FLOATINGPT, floatingpoint,
CTLFLAG_RD, &hw_float, 0,
"Floatingpoint instructions executed in hardware");
-#ifndef SMP
-static volatile u_int npx_intrs_while_probing;
-static volatile u_int npx_traps_while_probing;
-#endif
-
-static union savefpu npx_cleanstate;
+static struct savefpu npx_cleanstate;
static bool_t npx_cleanstate_ready;
-static bool_t npx_ex16;
-static bool_t npx_exists;
-static bool_t npx_irq13;
-
-#ifndef SMP
-alias_for_inthand_t probetrap;
-__asm(" \n\
- .text \n\
- .p2align 2,0x90 \n\
- .type " __XSTRING(CNAME(probetrap)) ",@function \n\
-" __XSTRING(CNAME(probetrap)) ": \n\
- ss \n\
- incl " __XSTRING(CNAME(npx_traps_while_probing)) " \n\
- fnclex \n\
- iret \n\
-");
-#endif /* SMP */
/*
* Identify routine. Create a connection point on our parent for probing.
@@ -220,104 +135,23 @@ npx_identify(driver, parent)
panic("npx_identify");
}
-#ifndef SMP
-/*
- * Do minimal handling of npx interrupts to convert them to traps.
- */
-static void
-npx_intr(dummy)
- void *dummy;
-{
- struct thread *td;
-
-#ifndef SMP
- npx_intrs_while_probing++;
-#endif
-
- /*
- * The BUSY# latch must be cleared in all cases so that the next
- * unmasked npx exception causes an interrupt.
- */
-#ifdef PC98
- outb(0xf8, 0);
-#else
- outb(0xf0, 0);
-#endif
-
- /*
- * fpcurthread is normally non-null here. In that case, schedule an
- * AST to finish the exception handling in the correct context
- * (this interrupt may occur after the thread has entered the
- * kernel via a syscall or an interrupt). Otherwise, the npx
- * state of the thread that caused this interrupt must have been
- * pushed to the thread's pcb, and clearing of the busy latch
- * above has finished the (essentially null) handling of this
- * interrupt. Control will eventually return to the instruction
- * that caused it and it will repeat. We will eventually (usually
- * soon) win the race to handle the interrupt properly.
- */
- td = PCPU_GET(fpcurthread);
- if (td != NULL) {
- td->td_pcb->pcb_flags |= PCB_NPXTRAP;
- mtx_lock_spin(&sched_lock);
- td->td_flags |= TDF_ASTPENDING;
- mtx_unlock_spin(&sched_lock);
- }
-}
-#endif /* !SMP */
-
/*
* Probe routine. Initialize cr0 to give correct behaviour for [f]wait
- * whether the device exists or not (XXX should be elsewhere). Set flags
- * to tell npxattach() what to do. Modify device struct if npx doesn't
- * need to use interrupts. Return 0 if device exists.
+ * whether the device exists or not (XXX should be elsewhere).
+ * Modify device struct if npx doesn't need to use interrupts.
+ * Return 0 if device exists.
*/
static int
npx_probe(dev)
device_t dev;
{
-#ifndef SMP
- struct gate_descriptor save_idt_npxtrap;
- struct resource *ioport_res, *irq_res;
- void *irq_cookie;
- int ioport_rid, irq_num, irq_rid;
- u_short control;
- u_short status;
-
- save_idt_npxtrap = idt[16];
- setidt(16, probetrap, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
- ioport_rid = 0;
- ioport_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &ioport_rid,
- IO_NPX, IO_NPX, IO_NPXSIZE, RF_ACTIVE);
- if (ioport_res == NULL)
- panic("npx: can't get ports");
-#ifdef PC98
- if (resource_int_value("npx", 0, "irq", &irq_num) != 0)
- irq_num = 8;
-#else
- if (resource_int_value("npx", 0, "irq", &irq_num) != 0)
- irq_num = 13;
-#endif
- irq_rid = 0;
- irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &irq_rid, irq_num,
- irq_num, 1, RF_ACTIVE);
- if (irq_res == NULL)
- panic("npx: can't get IRQ");
- if (bus_setup_intr(dev, irq_res, INTR_TYPE_MISC | INTR_FAST, npx_intr,
- NULL, &irq_cookie) != 0)
- panic("npx: can't create intr");
-#endif /* !SMP */
/*
* Partially reset the coprocessor, if any. Some BIOS's don't reset
* it after a warm boot.
*/
-#ifdef PC98
- outb(0xf8,0);
-#else
outb(0xf1, 0); /* full reset on some systems, NOP on others */
outb(0xf0, 0); /* clear BUSY# latch */
-#endif
/*
* Prepare to trap all ESC (i.e., NPX) instructions and all WAIT
* instructions. We must set the CR0_MP bit and use the CR0_TS
@@ -338,116 +172,13 @@ npx_probe(dev)
*/
stop_emulating();
/*
- * Finish resetting the coprocessor, if any. If there is an error
- * pending, then we may get a bogus IRQ13, but npx_intr() will handle
- * it OK. Bogus halts have never been observed, but we enabled
- * IRQ13 and cleared the BUSY# latch early to handle them anyway.
+ * Finish resetting the coprocessor.
*/
fninit();
device_set_desc(dev, "math processor");
-#ifdef SMP
-
- /*
- * Exception 16 MUST work for SMP.
- */
- npx_ex16 = hw_float = npx_exists = 1;
- return (0);
-
-#else /* !SMP */
-
- /*
- * Don't use fwait here because it might hang.
- * Don't use fnop here because it usually hangs if there is no FPU.
- */
- DELAY(1000); /* wait for any IRQ13 */
-#ifdef DIAGNOSTIC
- if (npx_intrs_while_probing != 0)
- printf("fninit caused %u bogus npx interrupt(s)\n",
- npx_intrs_while_probing);
- if (npx_traps_while_probing != 0)
- printf("fninit caused %u bogus npx trap(s)\n",
- npx_traps_while_probing);
-#endif
- /*
- * Check for a status of mostly zero.
- */
- status = 0x5a5a;
- fnstsw(&status);
- if ((status & 0xb8ff) == 0) {
- /*
- * Good, now check for a proper control word.
- */
- control = 0x5a5a;
- fnstcw(&control);
- if ((control & 0x1f3f) == 0x033f) {
- hw_float = npx_exists = 1;
- /*
- * We have an npx, now divide by 0 to see if exception
- * 16 works.
- */
- control &= ~(1 << 2); /* enable divide by 0 trap */
- fldcw(&control);
-#ifdef FPU_ERROR_BROKEN
- /*
- * FPU error signal doesn't work on some CPU
- * accelerator board.
- */
- npx_ex16 = 1;
- return (0);
-#endif
- npx_traps_while_probing = npx_intrs_while_probing = 0;
- fp_divide_by_0();
- if (npx_traps_while_probing != 0) {
- /*
- * Good, exception 16 works.
- */
- npx_ex16 = 1;
- goto no_irq13;
- }
- if (npx_intrs_while_probing != 0) {
- /*
- * Bad, we are stuck with IRQ13.
- */
- npx_irq13 = 1;
- idt[16] = save_idt_npxtrap;
- return (0);
- }
- /*
- * Worse, even IRQ13 is broken. Use emulator.
- */
- }
- }
- /*
- * Probe failed, but we want to get to npxattach to initialize the
- * emulator and say that it has been installed. XXX handle devices
- * that aren't really devices better.
- */
- /* FALLTHROUGH */
-no_irq13:
- idt[16] = save_idt_npxtrap;
- bus_teardown_intr(dev, irq_res, irq_cookie);
-
- /*
- * XXX hack around brokenness of bus_teardown_intr(). If we left the
- * irq active then we would get it instead of exception 16.
- */
- {
- register_t crit;
-
- crit = intr_disable();
- mtx_lock_spin(&icu_lock);
- INTRDIS(1 << irq_num);
- mtx_unlock_spin(&icu_lock);
- intr_restore(crit);
- }
-
- bus_release_resource(dev, SYS_RES_IRQ, irq_rid, irq_res);
- bus_release_resource(dev, SYS_RES_IOPORT, ioport_rid, ioport_res);
return (0);
-
-#endif /* SMP */
}
/*
@@ -457,67 +188,19 @@ static int
npx_attach(dev)
device_t dev;
{
- int flags;
register_t s;
- if (resource_int_value("npx", 0, "flags", &flags) != 0)
- flags = 0;
-
- if (flags)
- device_printf(dev, "flags 0x%x ", flags);
- if (npx_irq13) {
- device_printf(dev, "using IRQ 13 interface\n");
- } else {
-#if defined(MATH_EMULATE) || defined(GPL_MATH_EMULATE)
- if (npx_ex16) {
- if (!(flags & NPX_PREFER_EMULATOR))
- device_printf(dev, "INT 16 interface\n");
- else {
- device_printf(dev, "FPU exists, but flags request "
- "emulator\n");
- hw_float = npx_exists = 0;
- }
- } else if (npx_exists) {
- device_printf(dev, "error reporting broken; using 387 emulator\n");
- hw_float = npx_exists = 0;
- } else
- device_printf(dev, "387 emulator\n");
-#else
- if (npx_ex16) {
- device_printf(dev, "INT 16 interface\n");
- if (flags & NPX_PREFER_EMULATOR) {
- device_printf(dev, "emulator requested, but none compiled "
- "into kernel, using FPU\n");
- }
- } else
- device_printf(dev, "no 387 emulator in kernel and no FPU!\n");
-#endif
- }
+ device_printf(dev, "INT 16 interface\n");
npxinit(__INITIAL_NPXCW__);
if (npx_cleanstate_ready == 0) {
s = intr_disable();
stop_emulating();
- fpusave(&npx_cleanstate);
+ fxsave(&npx_cleanstate);
start_emulating();
npx_cleanstate_ready = 1;
intr_restore(s);
}
-#ifdef I586_CPU_XXX
- if (cpu_class == CPUCLASS_586 && npx_ex16 && npx_exists &&
- timezero("i586_bzero()", i586_bzero) <
- timezero("bzero()", bzero) * 4 / 5) {
- if (!(flags & NPX_DISABLE_I586_OPTIMIZED_BCOPY))
- bcopy_vector = i586_bcopy;
- if (!(flags & NPX_DISABLE_I586_OPTIMIZED_BZERO))
- bzero_vector = i586_bzero;
- if (!(flags & NPX_DISABLE_I586_OPTIMIZED_COPYIO)) {
- copyin_vector = i586_copyin;
- copyout_vector = i586_copyout;
- }
- }
-#endif
-
return (0); /* XXX unused */
}
@@ -528,11 +211,9 @@ void
npxinit(control)
u_short control;
{
- static union savefpu dummy;
+ static struct savefpu dummy;
register_t savecrit;
- if (!npx_exists)
- return;
/*
* fninit has the same h/w bugs as fnsave. Use the detoxified
* fnsave to throw away any junk in the fpu. npxsave() initializes
@@ -541,11 +222,8 @@ npxinit(control)
savecrit = intr_disable();
npxsave(&dummy);
stop_emulating();
-#ifdef CPU_ENABLE_SSE
/* XXX npxsave() doesn't actually initialize the fpu in the SSE case. */
- if (cpu_fxsr)
- fninit();
-#endif
+ fninit();
fldcw(&control);
start_emulating();
intr_restore(savecrit);
@@ -558,6 +236,9 @@ void
npxexit(td)
struct thread *td;
{
+#ifdef NPX_DEBUG
+ u_int masked_exceptions;
+#endif
register_t savecrit;
savecrit = intr_disable();
@@ -565,20 +246,16 @@ npxexit(td)
npxsave(&PCPU_GET(curpcb)->pcb_save);
intr_restore(savecrit);
#ifdef NPX_DEBUG
- if (npx_exists) {
- u_int masked_exceptions;
-
- masked_exceptions = GET_FPU_CW(td) & GET_FPU_SW(td) & 0x7f;
- /*
- * Log exceptions that would have trapped with the old
- * control word (overflow, divide by 0, and invalid operand).
- */
- if (masked_exceptions & 0x0d)
- log(LOG_ERR,
- "pid %d (%s) exited with masked floating point exceptions 0x%02x\n",
- td->td_proc->p_pid, td->td_proc->p_comm,
- masked_exceptions);
- }
+ masked_exceptions = GET_FPU_CW(td) & GET_FPU_SW(td) & 0x7f;
+ /*
+ * Log exceptions that would have trapped with the old
+ * control word (overflow, divide by 0, and invalid operand).
+ */
+ if (masked_exceptions & 0x0d)
+ log(LOG_ERR,
+"pid %d (%s) exited with masked floating point exceptions 0x%02x\n",
+ td->td_proc->p_pid, td->td_proc->p_comm,
+ masked_exceptions);
#endif
}
@@ -586,13 +263,7 @@ int
npxformat()
{
- if (!npx_exists)
- return (_MC_FPFMT_NODEV);
-#ifdef CPU_ENABLE_SSE
- if (cpu_fxsr)
- return (_MC_FPFMT_XMM);
-#endif
- return (_MC_FPFMT_387);
+ return (_MC_FPFMT_XMM);
}
/*
@@ -789,11 +460,6 @@ npxtrap()
register_t savecrit;
u_short control, status;
- if (!npx_exists) {
- printf("npxtrap: fpcurthread = %p, curthread = %p, npx_exists = %d\n",
- PCPU_GET(fpcurthread), curthread, npx_exists);
- panic("npxtrap from nowhere");
- }
savecrit = intr_disable();
/*
@@ -832,8 +498,6 @@ npxdna()
register_t s;
u_short control;
- if (!npx_exists)
- return (0);
if (PCPU_GET(fpcurthread) == curthread) {
printf("npxdna: fpcurthread == curthread %d times\n",
++err_count);
@@ -867,20 +531,15 @@ npxdna()
pcb->pcb_flags |= PCB_NPXINITDONE;
} else {
/*
- * The following frstor may cause an IRQ13 when the state
+ * The following frstor may cause a trap when the state
* being restored has a pending error. The error will
* appear to have been triggered by the current (npx) user
* instruction even when that instruction is a no-wait
* instruction that should not trigger an error (e.g.,
- * fnclex). On at least one 486 system all of the no-wait
* instructions are broken the same as frstor, so our
- * treatment does not amplify the breakage. On at least
- * one 386/Cyrix 387 system, fnclex works correctly while
- * frstor and fnsave are broken, so our treatment breaks
- * fnclex if it is the first FPU instruction after a context
- * switch.
+ * treatment does not amplify the breakage.
*/
- fpurstor(&pcb->pcb_save);
+ fxrstor(&pcb->pcb_save);
}
intr_restore(s);
@@ -912,11 +571,11 @@ npxdna()
*/
void
npxsave(addr)
- union savefpu *addr;
+ struct savefpu *addr;
{
stop_emulating();
- fpusave(addr);
+ fxsave(addr);
start_emulating();
PCPU_SET(fpcurthread, NULL);
@@ -944,13 +603,10 @@ npxdrop()
int
npxgetregs(td, addr)
struct thread *td;
- union savefpu *addr;
+ struct savefpu *addr;
{
register_t s;
- if (!npx_exists)
- return (_MC_FPOWNED_NONE);
-
if ((td->td_pcb->pcb_flags & PCB_NPXINITDONE) == 0) {
if (npx_cleanstate_ready)
bcopy(&npx_cleanstate, addr, sizeof(npx_cleanstate));
@@ -960,16 +616,7 @@ npxgetregs(td, addr)
}
s = intr_disable();
if (td == PCPU_GET(fpcurthread)) {
- fpusave(addr);
-#ifdef CPU_ENABLE_SSE
- if (!cpu_fxsr)
-#endif
- /*
- * fnsave initializes the FPU and destroys whatever
- * context it contains. Make sure the FPU owner
- * starts with a clean state next time.
- */
- npxdrop();
+ fxsave(addr);
intr_restore(s);
return (_MC_FPOWNED_FPU);
} else {
@@ -985,16 +632,13 @@ npxgetregs(td, addr)
void
npxsetregs(td, addr)
struct thread *td;
- union savefpu *addr;
+ struct savefpu *addr;
{
register_t s;
- if (!npx_exists)
- return;
-
s = intr_disable();
if (td == PCPU_GET(fpcurthread)) {
- fpurstor(addr);
+ fxrstor(addr);
intr_restore(s);
} else {
intr_restore(s);
@@ -1003,62 +647,6 @@ npxsetregs(td, addr)
curthread->td_pcb->pcb_flags |= PCB_NPXINITDONE;
}
-static void
-fpusave(addr)
- union savefpu *addr;
-{
-
-#ifdef CPU_ENABLE_SSE
- if (cpu_fxsr)
- fxsave(addr);
- else
-#endif
- fnsave(addr);
-}
-
-static void
-fpurstor(addr)
- union savefpu *addr;
-{
-
-#ifdef CPU_ENABLE_SSE
- if (cpu_fxsr)
- fxrstor(addr);
- else
-#endif
- frstor(addr);
-}
-
-#ifdef I586_CPU_XXX
-static long
-timezero(funcname, func)
- const char *funcname;
- void (*func)(void *buf, size_t len);
-
-{
- void *buf;
-#define BUFSIZE 1048576
- long usec;
- struct timeval finish, start;
-
- buf = malloc(BUFSIZE, M_TEMP, M_NOWAIT);
- if (buf == NULL)
- return (BUFSIZE);
- microtime(&start);
- (*func)(buf, BUFSIZE);
- microtime(&finish);
- usec = 1000000 * (finish.tv_sec - start.tv_sec) +
- finish.tv_usec - start.tv_usec;
- if (usec <= 0)
- usec = 1;
- if (bootverbose)
- printf("%s bandwidth = %u kBps\n", funcname,
- (u_int32_t)(((BUFSIZE >> 10) * 1000000) / usec));
- free(buf, M_TEMP);
- return (usec);
-}
-#endif /* I586_CPU */
-
static device_method_t npx_methods[] = {
/* Device interface */
DEVMETHOD(device_identify, npx_identify),
@@ -1080,13 +668,13 @@ static driver_t npx_driver = {
static devclass_t npx_devclass;
-#ifdef DEV_ISA
/*
* We prefer to attach to the root nexus so that the usual case (exception 16)
* doesn't describe the processor as being `on isa'.
*/
DRIVER_MODULE(npx, nexus, npx_driver, npx_devclass, 0, 0);
+#ifdef DEV_ISA
/*
* This sucks up the legacy ISA support assignments from PNPBIOS/ACPI.
*/
@@ -1132,7 +720,5 @@ static driver_t npxisa_driver = {
static devclass_t npxisa_devclass;
DRIVER_MODULE(npxisa, isa, npxisa_driver, npxisa_devclass, 0, 0);
-#ifndef PC98
DRIVER_MODULE(npxisa, acpi, npxisa_driver, npxisa_devclass, 0, 0);
-#endif
#endif /* DEV_ISA */
diff --git a/sys/amd64/amd64/genassym.c b/sys/amd64/amd64/genassym.c
index 7c287d62ffcd..8e25e042caf5 100644
--- a/sys/amd64/amd64/genassym.c
+++ b/sys/amd64/amd64/genassym.c
@@ -53,7 +53,6 @@
#include <sys/resourcevar.h>
#include <sys/ucontext.h>
#include <sys/user.h>
-#include <machine/bootinfo.h>
#include <machine/tss.h>
#include <sys/vmmeter.h>
#include <vm/vm.h>
@@ -68,12 +67,8 @@
#include <nfs/rpcv2.h>
#include <nfsclient/nfs.h>
#include <nfsclient/nfsdiskless.h>
-#ifdef SMP
-#include <machine/apic.h>
-#endif
#include <machine/cpu.h>
#include <machine/sigframe.h>
-#include <machine/vm86.h>
#include <machine/proc.h>
ASSYM(P_VMSPACE, offsetof(struct proc, p_vmspace));
@@ -91,7 +86,6 @@ ASSYM(TD_SWITCHIN, offsetof(struct thread, td_switchin));
ASSYM(TD_MD, offsetof(struct thread, td_md));
ASSYM(P_MD, offsetof(struct proc, p_md));
-ASSYM(MD_LDT, offsetof(struct mdproc, md_ldt));
ASSYM(TDF_ASTPENDING, TDF_ASTPENDING);
ASSYM(TDF_NEEDRESCHED, TDF_NEEDRESCHED);
@@ -99,7 +93,6 @@ ASSYM(TDF_NEEDRESCHED, TDF_NEEDRESCHED);
ASSYM(V_TRAP, offsetof(struct vmmeter, v_trap));
ASSYM(V_SYSCALL, offsetof(struct vmmeter, v_syscall));
ASSYM(V_INTR, offsetof(struct vmmeter, v_intr));
-/* ASSYM(UPAGES, UPAGES);*/
ASSYM(UAREA_PAGES, UAREA_PAGES);
ASSYM(KSTACK_PAGES, KSTACK_PAGES);
ASSYM(PAGE_SIZE, PAGE_SIZE);
@@ -118,111 +111,72 @@ ASSYM(VM_MAXUSER_ADDRESS, VM_MAXUSER_ADDRESS);
ASSYM(KERNBASE, KERNBASE);
ASSYM(MCLBYTES, MCLBYTES);
ASSYM(PCB_CR3, offsetof(struct pcb, pcb_cr3));
-ASSYM(PCB_EDI, offsetof(struct pcb, pcb_edi));
-ASSYM(PCB_ESI, offsetof(struct pcb, pcb_esi));
-ASSYM(PCB_EBP, offsetof(struct pcb, pcb_ebp));
-ASSYM(PCB_ESP, offsetof(struct pcb, pcb_esp));
-ASSYM(PCB_EBX, offsetof(struct pcb, pcb_ebx));
-ASSYM(PCB_EIP, offsetof(struct pcb, pcb_eip));
-ASSYM(TSS_ESP0, offsetof(struct i386tss, tss_esp0));
+ASSYM(PCB_R15, offsetof(struct pcb, pcb_r15));
+ASSYM(PCB_R14, offsetof(struct pcb, pcb_r14));
+ASSYM(PCB_R13, offsetof(struct pcb, pcb_r13));
+ASSYM(PCB_R12, offsetof(struct pcb, pcb_r12));
+ASSYM(PCB_RBP, offsetof(struct pcb, pcb_rbp));
+ASSYM(PCB_RSP, offsetof(struct pcb, pcb_rsp));
+ASSYM(PCB_RBX, offsetof(struct pcb, pcb_rbx));
+ASSYM(PCB_RIP, offsetof(struct pcb, pcb_rip));
+ASSYM(PCB_RFLAGS, offsetof(struct pcb, pcb_rflags));
-ASSYM(PCB_GS, offsetof(struct pcb, pcb_gs));
-ASSYM(PCB_DR0, offsetof(struct pcb, pcb_dr0));
-ASSYM(PCB_DR1, offsetof(struct pcb, pcb_dr1));
-ASSYM(PCB_DR2, offsetof(struct pcb, pcb_dr2));
-ASSYM(PCB_DR3, offsetof(struct pcb, pcb_dr3));
-ASSYM(PCB_DR6, offsetof(struct pcb, pcb_dr6));
-ASSYM(PCB_DR7, offsetof(struct pcb, pcb_dr7));
-ASSYM(PCB_PSL, offsetof(struct pcb, pcb_psl));
-ASSYM(PCB_DBREGS, PCB_DBREGS);
-ASSYM(PCB_EXT, offsetof(struct pcb, pcb_ext));
-
-ASSYM(PCB_SPARE, offsetof(struct pcb, __pcb_spare));
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(union savefpu));
+ASSYM(PCB_SAVEFPU_SIZE, sizeof(struct savefpu));
ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault));
ASSYM(PCB_SIZE, sizeof(struct pcb));
-ASSYM(PCB_VM86CALL, PCB_VM86CALL);
+ASSYM(COMMON_TSS_RSP0, offsetof(struct amd64tss, tss_rsp0));
+
+ASSYM(TF_R15, offsetof(struct trapframe, tf_r15));
+ASSYM(TF_R14, offsetof(struct trapframe, tf_r14));
+ASSYM(TF_R13, offsetof(struct trapframe, tf_r13));
+ASSYM(TF_R12, offsetof(struct trapframe, tf_r12));
+ASSYM(TF_R11, offsetof(struct trapframe, tf_r11));
+ASSYM(TF_R10, offsetof(struct trapframe, tf_r10));
+ASSYM(TF_R9, offsetof(struct trapframe, tf_r9));
+ASSYM(TF_R8, offsetof(struct trapframe, tf_r8));
+ASSYM(TF_RDI, offsetof(struct trapframe, tf_rdi));
+ASSYM(TF_RSI, offsetof(struct trapframe, tf_rsi));
+ASSYM(TF_RBP, offsetof(struct trapframe, tf_rbp));
+ASSYM(TF_RBX, offsetof(struct trapframe, tf_rbx));
+ASSYM(TF_RDX, offsetof(struct trapframe, tf_rdx));
+ASSYM(TF_RCX, offsetof(struct trapframe, tf_rcx));
+ASSYM(TF_RAX, offsetof(struct trapframe, tf_rax));
ASSYM(TF_TRAPNO, offsetof(struct trapframe, tf_trapno));
ASSYM(TF_ERR, offsetof(struct trapframe, tf_err));
+ASSYM(TF_RIP, offsetof(struct trapframe, tf_rip));
ASSYM(TF_CS, offsetof(struct trapframe, tf_cs));
-ASSYM(TF_EFLAGS, offsetof(struct trapframe, tf_eflags));
+ASSYM(TF_RFLAGS, offsetof(struct trapframe, tf_rflags));
+ASSYM(TF_RSP, offsetof(struct trapframe, tf_rsp));
+ASSYM(TF_SS, offsetof(struct trapframe, tf_ss));
+ASSYM(TF_SIZE, sizeof(struct trapframe));
+
ASSYM(SIGF_HANDLER, offsetof(struct sigframe, sf_ahu.sf_handler));
-#ifdef COMPAT_43
-ASSYM(SIGF_SC, offsetof(struct osigframe, sf_siginfo.si_sc));
-#endif
ASSYM(SIGF_UC, offsetof(struct sigframe, sf_uc));
-#ifdef COMPAT_FREEBSD4
-ASSYM(SIGF_UC4, offsetof(struct sigframe4, sf_uc));
-#endif
-#ifdef COMPAT_43
-ASSYM(SC_PS, offsetof(struct osigcontext, sc_ps));
-ASSYM(SC_FS, offsetof(struct osigcontext, sc_fs));
-ASSYM(SC_GS, offsetof(struct osigcontext, sc_gs));
-ASSYM(SC_TRAPNO, offsetof(struct osigcontext, sc_trapno));
-#endif
-#ifdef COMPAT_FREEBSD4
-ASSYM(UC4_EFLAGS, offsetof(struct ucontext4, uc_mcontext.mc_eflags));
-ASSYM(UC4_GS, offsetof(struct ucontext4, uc_mcontext.mc_gs));
-#endif
-ASSYM(UC_EFLAGS, offsetof(ucontext_t, uc_mcontext.mc_eflags));
-ASSYM(UC_GS, offsetof(ucontext_t, uc_mcontext.mc_gs));
+ASSYM(UC_EFLAGS, offsetof(ucontext_t, uc_mcontext.mc_rflags));
ASSYM(ENOENT, ENOENT);
ASSYM(EFAULT, EFAULT);
ASSYM(ENAMETOOLONG, ENAMETOOLONG);
ASSYM(MAXPATHLEN, MAXPATHLEN);
-ASSYM(BOOTINFO_SIZE, sizeof(struct bootinfo));
-ASSYM(BI_VERSION, offsetof(struct bootinfo, bi_version));
-ASSYM(BI_KERNELNAME, offsetof(struct bootinfo, bi_kernelname));
-ASSYM(BI_NFS_DISKLESS, offsetof(struct bootinfo, bi_nfs_diskless));
-ASSYM(BI_ENDCOMMON, offsetof(struct bootinfo, bi_endcommon));
-ASSYM(NFSDISKLESS_SIZE, sizeof(struct nfs_diskless));
-ASSYM(BI_SIZE, offsetof(struct bootinfo, bi_size));
-ASSYM(BI_SYMTAB, offsetof(struct bootinfo, bi_symtab));
-ASSYM(BI_ESYMTAB, offsetof(struct bootinfo, bi_esymtab));
-ASSYM(BI_KERNEND, offsetof(struct bootinfo, bi_kernend));
ASSYM(PC_SIZEOF, sizeof(struct pcpu));
ASSYM(PC_PRVSPACE, offsetof(struct pcpu, pc_prvspace));
ASSYM(PC_CURTHREAD, offsetof(struct pcpu, pc_curthread));
-ASSYM(PC_INT_PENDING, offsetof(struct pcpu, pc_int_pending));
-ASSYM(PC_IPENDING, offsetof(struct pcpu, pc_ipending));
-ASSYM(PC_FPENDING, offsetof(struct pcpu, pc_fpending));
-ASSYM(PC_SPENDING, offsetof(struct pcpu, pc_spending));
ASSYM(PC_FPCURTHREAD, offsetof(struct pcpu, pc_fpcurthread));
ASSYM(PC_IDLETHREAD, offsetof(struct pcpu, pc_idlethread));
ASSYM(PC_CURPCB, offsetof(struct pcpu, pc_curpcb));
-ASSYM(PC_COMMON_TSS, offsetof(struct pcpu, pc_common_tss));
-ASSYM(PC_COMMON_TSSD, offsetof(struct pcpu, pc_common_tssd));
-ASSYM(PC_TSS_GDT, offsetof(struct pcpu, pc_tss_gdt));
-ASSYM(PC_CURRENTLDT, offsetof(struct pcpu, pc_currentldt));
ASSYM(PC_CPUID, offsetof(struct pcpu, pc_cpuid));
-
-#ifdef SMP
-ASSYM(LA_VER, offsetof(struct LAPIC, version));
-ASSYM(LA_TPR, offsetof(struct LAPIC, tpr));
-ASSYM(LA_EOI, offsetof(struct LAPIC, eoi));
-ASSYM(LA_SVR, offsetof(struct LAPIC, svr));
-ASSYM(LA_ICR_LO, offsetof(struct LAPIC, icr_lo));
-ASSYM(LA_ICR_HI, offsetof(struct LAPIC, icr_hi));
-#endif
+ASSYM(PC_SCRATCH_RSP, offsetof(struct pcpu, pc_scratch_rsp));
ASSYM(KCSEL, GSEL(GCODE_SEL, SEL_KPL));
ASSYM(KDSEL, GSEL(GDATA_SEL, SEL_KPL));
-ASSYM(KPSEL, GSEL(GPRIV_SEL, SEL_KPL));
+ASSYM(KUCSEL, GSEL(GUCODE_SEL, SEL_UPL));
+ASSYM(KUDSEL, GSEL(GUDATA_SEL, SEL_UPL));
-ASSYM(BC32SEL, GSEL(GBIOSCODE32_SEL, SEL_KPL));
ASSYM(GPROC0_SEL, GPROC0_SEL);
-ASSYM(VM86_FRAMESIZE, sizeof(struct vm86frame));
ASSYM(MTX_LOCK, offsetof(struct mtx, mtx_lock));
ASSYM(MTX_RECURSECNT, offsetof(struct mtx, mtx_recurse));
-
-#ifdef PC98
-#include <machine/bus.h>
-
-ASSYM(BUS_SPACE_HANDLE_BASE, offsetof(struct bus_space_handle, bsh_base));
-ASSYM(BUS_SPACE_HANDLE_IAT, offsetof(struct bus_space_handle, bsh_iat));
-#endif
diff --git a/sys/amd64/amd64/identcpu.c b/sys/amd64/amd64/identcpu.c
index 0e8d80935eb1..62ae33de76bd 100644
--- a/sys/amd64/amd64/identcpu.c
+++ b/sys/amd64/amd64/identcpu.c
@@ -57,37 +57,22 @@
#include <machine/specialreg.h>
#include <machine/md_var.h>
-#include <i386/isa/icu.h>
-#include <i386/isa/intr_machdep.h>
-
-#define IDENTBLUE_CYRIX486 0
-#define IDENTBLUE_IBMCPU 1
-#define IDENTBLUE_CYRIXM2 2
+#include <amd64/isa/icu.h>
+#include <amd64/isa/intr_machdep.h>
/* XXX - should be in header file: */
void printcpuinfo(void);
-void finishidentcpu(void);
+void identify_cpu(void);
void earlysetcpuclass(void);
-#if defined(I586_CPU) && defined(CPU_WT_ALLOC)
-void enable_K5_wt_alloc(void);
-void enable_K6_wt_alloc(void);
-void enable_K6_2_wt_alloc(void);
-#endif
void panicifcpuunsupported(void);
-static void identifycyrix(void);
-#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
static void print_AMD_features(void);
-#endif
static void print_AMD_info(void);
static void print_AMD_assoc(int i);
-static void print_transmeta_info(void);
-static void setup_tmx86_longrun(void);
int cpu_class;
u_int cpu_exthigh; /* Highest arg to extended CPUID */
-u_int cyrix_did; /* Device ID of Cyrix CPU */
-char machine[] = "i386";
+char machine[] = "amd64";
SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD,
machine, 0, "Machine class");
@@ -99,67 +84,27 @@ static int hw_clockrate;
SYSCTL_INT(_hw, OID_AUTO, clockrate, CTLFLAG_RD,
&hw_clockrate, 0, "CPU instruction clock rate");
-#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
static char cpu_brand[48];
-#define MAX_BRAND_INDEX 8
-
-static const char *cpu_brandtable[MAX_BRAND_INDEX + 1] = {
- NULL, /* No brand */
- "Intel Celeron",
- "Intel Pentium III",
- "Intel Pentium III Xeon",
- NULL,
- NULL,
- NULL,
- NULL,
- "Intel Pentium 4"
-};
-#endif
-
-static struct cpu_nameclass i386_cpus[] = {
- { "Intel 80286", CPUCLASS_286 }, /* CPU_286 */
- { "i386SX", CPUCLASS_386 }, /* CPU_386SX */
- { "i386DX", CPUCLASS_386 }, /* CPU_386 */
- { "i486SX", CPUCLASS_486 }, /* CPU_486SX */
- { "i486DX", CPUCLASS_486 }, /* CPU_486 */
- { "Pentium", CPUCLASS_586 }, /* CPU_586 */
- { "Cyrix 486", CPUCLASS_486 }, /* CPU_486DLC */
- { "Pentium Pro", CPUCLASS_686 }, /* CPU_686 */
- { "Cyrix 5x86", CPUCLASS_486 }, /* CPU_M1SC */
- { "Cyrix 6x86", CPUCLASS_486 }, /* CPU_M1 */
- { "Blue Lightning", CPUCLASS_486 }, /* CPU_BLUE */
- { "Cyrix 6x86MX", CPUCLASS_686 }, /* CPU_M2 */
- { "NexGen 586", CPUCLASS_386 }, /* CPU_NX586 (XXX) */
- { "Cyrix 486S/DX", CPUCLASS_486 }, /* CPU_CY486DX */
- { "Pentium II", CPUCLASS_686 }, /* CPU_PII */
- { "Pentium III", CPUCLASS_686 }, /* CPU_PIII */
- { "Pentium 4", CPUCLASS_686 }, /* CPU_P4 */
+static struct cpu_nameclass amd64_cpus[] = {
+ { "Clawhammer", CPUCLASS_K8 }, /* CPU_CLAWHAMMER */
+ { "Sledgehammer", CPUCLASS_K8 }, /* CPU_SLEDGEHAMMER */
};
-#if defined(I586_CPU) && !defined(NO_F00F_HACK)
-int has_f00f_bug = 0; /* Initialized so that it can be patched. */
-#endif
-
void
printcpuinfo(void)
{
-#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
u_int regs[4], i;
char *brand;
-#endif
- cpu_class = i386_cpus[cpu].cpu_class;
+ cpu_class = amd64_cpus[cpu].cpu_class;
printf("CPU: ");
- strncpy(cpu_model, i386_cpus[cpu].cpu_name, sizeof (cpu_model));
+ strncpy(cpu_model, amd64_cpus[cpu].cpu_name, sizeof (cpu_model));
-#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
/* Check for extended CPUID information and a processor name. */
if (cpu_high > 0 &&
(strcmp(cpu_vendor, "GenuineIntel") == 0 ||
- strcmp(cpu_vendor, "AuthenticAMD") == 0 ||
- strcmp(cpu_vendor, "GenuineTMx86") == 0 ||
- strcmp(cpu_vendor, "TransmetaCPU") == 0)) {
+ strcmp(cpu_vendor, "AuthenticAMD") == 0)) {
do_cpuid(0x80000000, regs);
if (regs[0] >= 0x80000000) {
cpu_exthigh = regs[0];
@@ -175,138 +120,8 @@ printcpuinfo(void)
}
if (strcmp(cpu_vendor, "GenuineIntel") == 0) {
- if ((cpu_id & 0xf00) > 0x300) {
- u_int brand_index;
-
- cpu_model[0] = '\0';
-
- switch (cpu_id & 0x3000) {
- case 0x1000:
- strcpy(cpu_model, "Overdrive ");
- break;
- case 0x2000:
- strcpy(cpu_model, "Dual ");
- break;
- }
-
- switch (cpu_id & 0xf00) {
- case 0x400:
- strcat(cpu_model, "i486 ");
- /* Check the particular flavor of 486 */
- switch (cpu_id & 0xf0) {
- case 0x00:
- case 0x10:
- strcat(cpu_model, "DX");
- break;
- case 0x20:
- strcat(cpu_model, "SX");
- break;
- case 0x30:
- strcat(cpu_model, "DX2");
- break;
- case 0x40:
- strcat(cpu_model, "SL");
- break;
- case 0x50:
- strcat(cpu_model, "SX2");
- break;
- case 0x70:
- strcat(cpu_model,
- "DX2 Write-Back Enhanced");
- break;
- case 0x80:
- strcat(cpu_model, "DX4");
- break;
- }
- break;
- case 0x500:
- /* Check the particular flavor of 586 */
- strcat(cpu_model, "Pentium");
- switch (cpu_id & 0xf0) {
- case 0x00:
- strcat(cpu_model, " A-step");
- break;
- case 0x10:
- strcat(cpu_model, "/P5");
- break;
- case 0x20:
- strcat(cpu_model, "/P54C");
- break;
- case 0x30:
- strcat(cpu_model, "/P54T Overdrive");
- break;
- case 0x40:
- strcat(cpu_model, "/P55C");
- break;
- case 0x70:
- strcat(cpu_model, "/P54C");
- break;
- case 0x80:
- strcat(cpu_model, "/P55C (quarter-micron)");
- break;
- default:
- /* nothing */
- break;
- }
-#if defined(I586_CPU) && !defined(NO_F00F_HACK)
- /*
- * XXX - If/when Intel fixes the bug, this
- * should also check the version of the
- * CPU, not just that it's a Pentium.
- */
- has_f00f_bug = 1;
-#endif
- break;
- case 0x600:
- /* Check the particular flavor of 686 */
- switch (cpu_id & 0xf0) {
- case 0x00:
- strcat(cpu_model, "Pentium Pro A-step");
- break;
- case 0x10:
- strcat(cpu_model, "Pentium Pro");
- break;
- case 0x30:
- case 0x50:
- case 0x60:
- strcat(cpu_model,
- "Pentium II/Pentium II Xeon/Celeron");
- cpu = CPU_PII;
- break;
- case 0x70:
- case 0x80:
- case 0xa0:
- case 0xb0:
- strcat(cpu_model,
- "Pentium III/Pentium III Xeon/Celeron");
- cpu = CPU_PIII;
- break;
- default:
- strcat(cpu_model, "Unknown 80686");
- break;
- }
- break;
- case 0xf00:
- strcat(cpu_model, "Pentium 4");
- cpu = CPU_P4;
- break;
- default:
- strcat(cpu_model, "unknown");
- break;
- }
-
- /*
- * If we didn't get a brand name from the extended
- * CPUID, try to look it up in the brand table.
- */
- if (cpu_high > 0 && *cpu_brand == '\0') {
- brand_index = cpu_procinfo & CPUID_BRAND_INDEX;
- if (brand_index <= MAX_BRAND_INDEX &&
- cpu_brandtable[brand_index] != NULL)
- strcpy(cpu_brand,
- cpu_brandtable[brand_index]);
- }
- }
+ /* How the hell did you get here?? */
+ strcat(cpu_model, "Yamhill?");
} else if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
/*
* Values taken from AMD Processor Recognition
@@ -315,231 +130,13 @@ printcpuinfo(void)
*/
strcpy(cpu_model, "AMD ");
switch (cpu_id & 0xFF0) {
- case 0x410:
- strcat(cpu_model, "Standard Am486DX");
- break;
- case 0x430:
- strcat(cpu_model, "Enhanced Am486DX2 Write-Through");
- break;
- case 0x470:
- strcat(cpu_model, "Enhanced Am486DX2 Write-Back");
- break;
- case 0x480:
- strcat(cpu_model, "Enhanced Am486DX4/Am5x86 Write-Through");
- break;
- case 0x490:
- strcat(cpu_model, "Enhanced Am486DX4/Am5x86 Write-Back");
- break;
- case 0x4E0:
- strcat(cpu_model, "Am5x86 Write-Through");
- break;
- case 0x4F0:
- strcat(cpu_model, "Am5x86 Write-Back");
- break;
- case 0x500:
- strcat(cpu_model, "K5 model 0");
- tsc_is_broken = 1;
- break;
- case 0x510:
- strcat(cpu_model, "K5 model 1");
- break;
- case 0x520:
- strcat(cpu_model, "K5 PR166 (model 2)");
- break;
- case 0x530:
- strcat(cpu_model, "K5 PR200 (model 3)");
- break;
- case 0x560:
- strcat(cpu_model, "K6");
- break;
- case 0x570:
- strcat(cpu_model, "K6 266 (model 1)");
- break;
- case 0x580:
- strcat(cpu_model, "K6-2");
- break;
- case 0x590:
- strcat(cpu_model, "K6-III");
+ case 0xf00:
+ strcat(cpu_model, "Hammer");
break;
default:
strcat(cpu_model, "Unknown");
break;
}
-#if defined(I586_CPU) && defined(CPU_WT_ALLOC)
- if ((cpu_id & 0xf00) == 0x500) {
- if (((cpu_id & 0x0f0) > 0)
- && ((cpu_id & 0x0f0) < 0x60)
- && ((cpu_id & 0x00f) > 3))
- enable_K5_wt_alloc();
- else if (((cpu_id & 0x0f0) > 0x80)
- || (((cpu_id & 0x0f0) == 0x80)
- && (cpu_id & 0x00f) > 0x07))
- enable_K6_2_wt_alloc();
- else if ((cpu_id & 0x0f0) > 0x50)
- enable_K6_wt_alloc();
- }
-#endif
- } else if (strcmp(cpu_vendor, "CyrixInstead") == 0) {
- strcpy(cpu_model, "Cyrix ");
- switch (cpu_id & 0xff0) {
- case 0x440:
- strcat(cpu_model, "MediaGX");
- break;
- case 0x520:
- strcat(cpu_model, "6x86");
- break;
- case 0x540:
- cpu_class = CPUCLASS_586;
- strcat(cpu_model, "GXm");
- break;
- case 0x600:
- strcat(cpu_model, "6x86MX");
- break;
- default:
- /*
- * Even though CPU supports the cpuid
- * instruction, it can be disabled.
- * Therefore, this routine supports all Cyrix
- * CPUs.
- */
- switch (cyrix_did & 0xf0) {
- case 0x00:
- switch (cyrix_did & 0x0f) {
- case 0x00:
- strcat(cpu_model, "486SLC");
- break;
- case 0x01:
- strcat(cpu_model, "486DLC");
- break;
- case 0x02:
- strcat(cpu_model, "486SLC2");
- break;
- case 0x03:
- strcat(cpu_model, "486DLC2");
- break;
- case 0x04:
- strcat(cpu_model, "486SRx");
- break;
- case 0x05:
- strcat(cpu_model, "486DRx");
- break;
- case 0x06:
- strcat(cpu_model, "486SRx2");
- break;
- case 0x07:
- strcat(cpu_model, "486DRx2");
- break;
- case 0x08:
- strcat(cpu_model, "486SRu");
- break;
- case 0x09:
- strcat(cpu_model, "486DRu");
- break;
- case 0x0a:
- strcat(cpu_model, "486SRu2");
- break;
- case 0x0b:
- strcat(cpu_model, "486DRu2");
- break;
- default:
- strcat(cpu_model, "Unknown");
- break;
- }
- break;
- case 0x10:
- switch (cyrix_did & 0x0f) {
- case 0x00:
- strcat(cpu_model, "486S");
- break;
- case 0x01:
- strcat(cpu_model, "486S2");
- break;
- case 0x02:
- strcat(cpu_model, "486Se");
- break;
- case 0x03:
- strcat(cpu_model, "486S2e");
- break;
- case 0x0a:
- strcat(cpu_model, "486DX");
- break;
- case 0x0b:
- strcat(cpu_model, "486DX2");
- break;
- case 0x0f:
- strcat(cpu_model, "486DX4");
- break;
- default:
- strcat(cpu_model, "Unknown");
- break;
- }
- break;
- case 0x20:
- if ((cyrix_did & 0x0f) < 8)
- strcat(cpu_model, "6x86"); /* Where did you get it? */
- else
- strcat(cpu_model, "5x86");
- break;
- case 0x30:
- strcat(cpu_model, "6x86");
- break;
- case 0x40:
- if ((cyrix_did & 0xf000) == 0x3000) {
- cpu_class = CPUCLASS_586;
- strcat(cpu_model, "GXm");
- } else
- strcat(cpu_model, "MediaGX");
- break;
- case 0x50:
- strcat(cpu_model, "6x86MX");
- break;
- case 0xf0:
- switch (cyrix_did & 0x0f) {
- case 0x0d:
- strcat(cpu_model, "Overdrive CPU");
- case 0x0e:
- strcpy(cpu_model, "Texas Instruments 486SXL");
- break;
- case 0x0f:
- strcat(cpu_model, "486SLC/DLC");
- break;
- default:
- strcat(cpu_model, "Unknown");
- break;
- }
- break;
- default:
- strcat(cpu_model, "Unknown");
- break;
- }
- break;
- }
- } else if (strcmp(cpu_vendor, "RiseRiseRise") == 0) {
- strcpy(cpu_model, "Rise ");
- switch (cpu_id & 0xff0) {
- case 0x500:
- strcat(cpu_model, "mP6");
- break;
- default:
- strcat(cpu_model, "Unknown");
- }
- } else if (strcmp(cpu_vendor, "CentaurHauls") == 0) {
- switch (cpu_id & 0xff0) {
- case 0x540:
- strcpy(cpu_model, "IDT WinChip C6");
- tsc_is_broken = 1;
- break;
- case 0x580:
- strcpy(cpu_model, "IDT WinChip 2");
- break;
- case 0x670:
- strcpy(cpu_model, "VIA C3 Samuel 2");
- break;
- default:
- strcpy(cpu_model, "VIA/IDT Unknown");
- }
- } else if (strcmp(cpu_vendor, "IBM") == 0) {
- strcpy(cpu_model, "Blue Lightning CPU");
}
/*
@@ -552,61 +149,27 @@ printcpuinfo(void)
if (*brand != '\0')
strcpy(cpu_model, brand);
-#endif
-
printf("%s (", cpu_model);
switch(cpu_class) {
- case CPUCLASS_286:
- printf("286");
- break;
-#if defined(I386_CPU)
- case CPUCLASS_386:
- printf("386");
- break;
-#endif
-#if defined(I486_CPU)
- case CPUCLASS_486:
- printf("486");
- bzero_vector = i486_bzero;
- break;
-#endif
-#if defined(I586_CPU)
- case CPUCLASS_586:
- hw_clockrate = (tsc_freq + 5000) / 1000000;
- printf("%jd.%02d-MHz ",
- (intmax_t)(tsc_freq + 4999) / 1000000,
- (u_int)((tsc_freq + 4999) / 10000) % 100);
- printf("586");
- break;
-#endif
-#if defined(I686_CPU)
- case CPUCLASS_686:
+ case CPUCLASS_K8:
hw_clockrate = (tsc_freq + 5000) / 1000000;
printf("%jd.%02d-MHz ",
(intmax_t)(tsc_freq + 4999) / 1000000,
(u_int)((tsc_freq + 4999) / 10000) % 100);
- printf("686");
+ printf("K8");
break;
-#endif
default:
printf("Unknown"); /* will panic below... */
}
printf("-class CPU)\n");
-#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
if(*cpu_vendor)
printf(" Origin = \"%s\"",cpu_vendor);
if(cpu_id)
printf(" Id = 0x%x", cpu_id);
if (strcmp(cpu_vendor, "GenuineIntel") == 0 ||
- strcmp(cpu_vendor, "AuthenticAMD") == 0 ||
- strcmp(cpu_vendor, "RiseRiseRise") == 0 ||
- strcmp(cpu_vendor, "CentaurHauls") == 0 ||
- ((strcmp(cpu_vendor, "CyrixInstead") == 0) &&
- ((cpu_id & 0xf00) > 0x500))) {
+ strcmp(cpu_vendor, "AuthenticAMD") == 0) {
printf(" Stepping = %u", cpu_id & 0xf);
- if (strcmp(cpu_vendor, "CyrixInstead") == 0)
- printf(" DIR=0x%04x", cyrix_did);
if (cpu_high > 0) {
/*
* Here we should probably set up flags indicating
@@ -665,72 +228,33 @@ printcpuinfo(void)
cpu_exthigh >= 0x80000001)
print_AMD_features();
} else if (strcmp(cpu_vendor, "CyrixInstead") == 0) {
- printf(" DIR=0x%04x", cyrix_did);
- printf(" Stepping=%u", (cyrix_did & 0xf000) >> 12);
- printf(" Revision=%u", (cyrix_did & 0x0f00) >> 8);
-#ifndef CYRIX_CACHE_REALLY_WORKS
- if (cpu == CPU_M1 && (cyrix_did & 0xff00) < 0x1700)
- printf("\n CPU cache: write-through mode");
-#endif
}
/* Avoid ugly blank lines: only print newline when we have to. */
if (*cpu_vendor || cpu_id)
printf("\n");
-#endif
- if (strcmp(cpu_vendor, "GenuineTMx86") == 0 ||
- strcmp(cpu_vendor, "TransmetaCPU") == 0) {
- setup_tmx86_longrun();
- }
-
if (!bootverbose)
return;
if (strcmp(cpu_vendor, "AuthenticAMD") == 0)
print_AMD_info();
- else if (strcmp(cpu_vendor, "GenuineTMx86") == 0 ||
- strcmp(cpu_vendor, "TransmetaCPU") == 0)
- print_transmeta_info();
-
-#ifdef I686_CPU
- /*
- * XXX - Do PPro CPUID level=2 stuff here?
- *
- * No, but maybe in a print_Intel_info() function called from here.
- */
-#endif
}
void
panicifcpuunsupported(void)
{
-#if !defined(lint)
-#if !defined(I386_CPU) && !defined(I486_CPU) && !defined(I586_CPU) && !defined(I686_CPU)
-#error This kernel is not configured for one of the supported CPUs
-#endif
-#else /* lint */
-#endif /* lint */
-#if defined(I386_CPU) && (defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU))
-#error I386_CPU is mutually exclusive with the other cpu types.
+#ifndef HAMMER
+#error "You need to specify a cpu type"
#endif
/*
* Now that we have told the user what they have,
* let them know if that machine type isn't configured.
*/
switch (cpu_class) {
- case CPUCLASS_286: /* a 286 should not make it this far, anyway */
-#if !defined(I386_CPU)
- case CPUCLASS_386:
-#endif
-#if !defined(I486_CPU)
- case CPUCLASS_486:
-#endif
-#if !defined(I586_CPU)
- case CPUCLASS_586:
-#endif
-#if !defined(I686_CPU)
- case CPUCLASS_686:
+ case CPUCLASS_X86:
+#ifndef HAMMER
+ case CPUCLASS_K8:
#endif
panic("CPU class not configured");
default:
@@ -739,231 +263,28 @@ panicifcpuunsupported(void)
}
-static volatile u_int trap_by_rdmsr;
-
-/*
- * Special exception 6 handler.
- * The rdmsr instruction generates invalid opcodes fault on 486-class
- * Cyrix CPU. Stacked eip register points the rdmsr instruction in the
- * function identblue() when this handler is called. Stacked eip should
- * be advanced.
- */
-inthand_t bluetrap6;
-#ifdef __GNUC__
-__asm
-(" \
- .text; \
- .p2align 2,0x90; \
- .type " __XSTRING(CNAME(bluetrap6)) ",@function; \
-" __XSTRING(CNAME(bluetrap6)) ": \
- ss; \
- movl $0xa8c1d," __XSTRING(CNAME(trap_by_rdmsr)) "; \
- addl $2, (%esp); /* rdmsr is a 2-byte instruction */ \
- iret \
-");
-#endif
-
-/*
- * Special exception 13 handler.
- * Accessing non-existent MSR generates general protection fault.
- */
-inthand_t bluetrap13;
-#ifdef __GNUC__
-__asm
-(" \
- .text; \
- .p2align 2,0x90; \
- .type " __XSTRING(CNAME(bluetrap13)) ",@function; \
-" __XSTRING(CNAME(bluetrap13)) ": \
- ss; \
- movl $0xa89c4," __XSTRING(CNAME(trap_by_rdmsr)) "; \
- popl %eax; /* discard errorcode. */ \
- addl $2, (%esp); /* rdmsr is a 2-bytes instruction. */ \
- iret; \
-");
-#endif
-
-/*
- * Distinguish IBM Blue Lightning CPU from Cyrix CPUs that does not
- * support cpuid instruction. This function should be called after
- * loading interrupt descriptor table register.
- *
- * I don't like this method that handles fault, but I couldn't get
- * information for any other methods. Does blue giant know?
- */
-static int
-identblue(void)
-{
-
- trap_by_rdmsr = 0;
-
- /*
- * Cyrix 486-class CPU does not support rdmsr instruction.
- * The rdmsr instruction generates invalid opcode fault, and exception
- * will be trapped by bluetrap6() on Cyrix 486-class CPU. The
- * bluetrap6() set the magic number to trap_by_rdmsr.
- */
- setidt(6, bluetrap6, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
-
- /*
- * Certain BIOS disables cpuid instruction of Cyrix 6x86MX CPU.
- * In this case, rdmsr generates general protection fault, and
- * exception will be trapped by bluetrap13().
- */
- setidt(13, bluetrap13, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
-
- rdmsr(0x1002); /* Cyrix CPU generates fault. */
-
- if (trap_by_rdmsr == 0xa8c1d)
- return IDENTBLUE_CYRIX486;
- else if (trap_by_rdmsr == 0xa89c4)
- return IDENTBLUE_CYRIXM2;
- return IDENTBLUE_IBMCPU;
-}
-
-
-/*
- * identifycyrix() set lower 16 bits of cyrix_did as follows:
- *
- * F E D C B A 9 8 7 6 5 4 3 2 1 0
- * +-------+-------+---------------+
- * | SID | RID | Device ID |
- * | (DIR 1) | (DIR 0) |
- * +-------+-------+---------------+
- */
-static void
-identifycyrix(void)
-{
- u_int eflags;
- int ccr2_test = 0, dir_test = 0;
- u_char ccr2, ccr3;
-
- eflags = read_eflags();
- disable_intr();
-
- ccr2 = read_cyrix_reg(CCR2);
- write_cyrix_reg(CCR2, ccr2 ^ CCR2_LOCK_NW);
- read_cyrix_reg(CCR2);
- if (read_cyrix_reg(CCR2) != ccr2)
- ccr2_test = 1;
- write_cyrix_reg(CCR2, ccr2);
-
- ccr3 = read_cyrix_reg(CCR3);
- write_cyrix_reg(CCR3, ccr3 ^ CCR3_MAPEN3);
- read_cyrix_reg(CCR3);
- if (read_cyrix_reg(CCR3) != ccr3)
- dir_test = 1; /* CPU supports DIRs. */
- write_cyrix_reg(CCR3, ccr3);
-
- if (dir_test) {
- /* Device ID registers are available. */
- cyrix_did = read_cyrix_reg(DIR1) << 8;
- cyrix_did += read_cyrix_reg(DIR0);
- } else if (ccr2_test)
- cyrix_did = 0x0010; /* 486S A-step */
- else
- cyrix_did = 0x00ff; /* Old 486SLC/DLC and TI486SXLC/SXL */
-
- write_eflags(eflags);
-}
-
/*
* Final stage of CPU identification. -- Should I check TI?
*/
void
-finishidentcpu(void)
+identify_cpu(void)
{
- int isblue = 0;
- u_char ccr3;
- u_int regs[4];
+ u_int regs[4];
- if (strcmp(cpu_vendor, "CyrixInstead") == 0) {
- if (cpu == CPU_486) {
- /*
- * These conditions are equivalent to:
- * - CPU does not support cpuid instruction.
- * - Cyrix/IBM CPU is detected.
- */
- isblue = identblue();
- if (isblue == IDENTBLUE_IBMCPU) {
- strcpy(cpu_vendor, "IBM");
- cpu = CPU_BLUE;
- return;
- }
- }
- switch (cpu_id & 0xf00) {
- case 0x600:
- /*
- * Cyrix's datasheet does not describe DIRs.
- * Therefor, I assume it does not have them
- * and use the result of the cpuid instruction.
- * XXX they seem to have it for now at least. -Peter
- */
- identifycyrix();
- cpu = CPU_M2;
- break;
- default:
- identifycyrix();
- /*
- * This routine contains a trick.
- * Don't check (cpu_id & 0x00f0) == 0x50 to detect M2, now.
- */
- switch (cyrix_did & 0x00f0) {
- case 0x00:
- case 0xf0:
- cpu = CPU_486DLC;
- break;
- case 0x10:
- cpu = CPU_CY486DX;
- break;
- case 0x20:
- if ((cyrix_did & 0x000f) < 8)
- cpu = CPU_M1;
- else
- cpu = CPU_M1SC;
- break;
- case 0x30:
- cpu = CPU_M1;
- break;
- case 0x40:
- /* MediaGX CPU */
- cpu = CPU_M1SC;
- break;
- default:
- /* M2 and later CPUs are treated as M2. */
- cpu = CPU_M2;
+ do_cpuid(0, regs);
+ cpu_high = regs[0];
+ ((u_int *)&cpu_vendor)[0] = regs[1];
+ ((u_int *)&cpu_vendor)[1] = regs[3];
+ ((u_int *)&cpu_vendor)[2] = regs[2];
+ cpu_vendor[12] = '\0';
- /*
- * enable cpuid instruction.
- */
- ccr3 = read_cyrix_reg(CCR3);
- write_cyrix_reg(CCR3, CCR3_MAPEN0);
- write_cyrix_reg(CCR4, read_cyrix_reg(CCR4) | CCR4_CPUID);
- write_cyrix_reg(CCR3, ccr3);
+ do_cpuid(1, regs);
+ cpu_id = regs[0];
+ cpu_procinfo = regs[1];
+ cpu_feature = regs[3];
- do_cpuid(0, regs);
- cpu_high = regs[0]; /* eax */
- do_cpuid(1, regs);
- cpu_id = regs[0]; /* eax */
- cpu_feature = regs[3]; /* edx */
- break;
- }
- }
- } else if (cpu == CPU_486 && *cpu_vendor == '\0') {
- /*
- * There are BlueLightning CPUs that do not change
- * undefined flags by dividing 5 by 2. In this case,
- * the CPU identification routine in locore.s leaves
- * cpu_vendor null string and puts CPU_486 into the
- * cpu.
- */
- isblue = identblue();
- if (isblue == IDENTBLUE_IBMCPU) {
- strcpy(cpu_vendor, "IBM");
- cpu = CPU_BLUE;
- return;
- }
- }
+ /* XXX */
+ cpu = CPU_CLAWHAMMER;
}
static void
@@ -978,7 +299,6 @@ print_AMD_assoc(int i)
static void
print_AMD_info(void)
{
- quad_t amd_whcr;
if (cpu_exthigh >= 0x80000005) {
u_int regs[4];
@@ -1004,38 +324,8 @@ print_AMD_info(void)
print_AMD_assoc((regs[2] >> 12) & 0x0f);
}
}
- if (((cpu_id & 0xf00) == 0x500)
- && (((cpu_id & 0x0f0) > 0x80)
- || (((cpu_id & 0x0f0) == 0x80)
- && (cpu_id & 0x00f) > 0x07))) {
- /* K6-2(new core [Stepping 8-F]), K6-III or later */
- amd_whcr = rdmsr(0xc0000082);
- if (!(amd_whcr & (0x3ff << 22))) {
- printf("Write Allocate Disable\n");
- } else {
- printf("Write Allocate Enable Limit: %dM bytes\n",
- (u_int32_t)((amd_whcr & (0x3ff << 22)) >> 22) * 4);
- printf("Write Allocate 15-16M bytes: %s\n",
- (amd_whcr & (1 << 16)) ? "Enable" : "Disable");
- }
- } else if (((cpu_id & 0xf00) == 0x500)
- && ((cpu_id & 0x0f0) > 0x50)) {
- /* K6, K6-2(old core) */
- amd_whcr = rdmsr(0xc0000082);
- if (!(amd_whcr & (0x7f << 1))) {
- printf("Write Allocate Disable\n");
- } else {
- printf("Write Allocate Enable Limit: %dM bytes\n",
- (u_int32_t)((amd_whcr & (0x7f << 1)) >> 1) * 4);
- printf("Write Allocate 15-16M bytes: %s\n",
- (amd_whcr & 0x0001) ? "Enable" : "Disable");
- printf("Hardware Write Allocate Control: %s\n",
- (amd_whcr & 0x0100) ? "Enable" : "Disable");
- }
- }
}
-#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
static void
print_AMD_features(void)
{
@@ -1082,297 +372,3 @@ print_AMD_features(void)
"\0403DNow!"
);
}
-#endif
-
-/*
- * Transmeta Crusoe LongRun Support by Tamotsu Hattori.
- */
-
-#define MSR_TMx86_LONGRUN 0x80868010
-#define MSR_TMx86_LONGRUN_FLAGS 0x80868011
-
-#define LONGRUN_MODE_MASK(x) ((x) & 0x000000007f)
-#define LONGRUN_MODE_RESERVED(x) ((x) & 0xffffff80)
-#define LONGRUN_MODE_WRITE(x, y) (LONGRUN_MODE_RESERVED(x) | LONGRUN_MODE_MASK(y))
-
-#define LONGRUN_MODE_MINFREQUENCY 0x00
-#define LONGRUN_MODE_ECONOMY 0x01
-#define LONGRUN_MODE_PERFORMANCE 0x02
-#define LONGRUN_MODE_MAXFREQUENCY 0x03
-#define LONGRUN_MODE_UNKNOWN 0x04
-#define LONGRUN_MODE_MAX 0x04
-
-union msrinfo {
- u_int64_t msr;
- u_int32_t regs[2];
-};
-
-static u_int32_t longrun_modes[LONGRUN_MODE_MAX][3] = {
- /* MSR low, MSR high, flags bit0 */
- { 0, 0, 0}, /* LONGRUN_MODE_MINFREQUENCY */
- { 0, 100, 0}, /* LONGRUN_MODE_ECONOMY */
- { 0, 100, 1}, /* LONGRUN_MODE_PERFORMANCE */
- { 100, 100, 1}, /* LONGRUN_MODE_MAXFREQUENCY */
-};
-
-static u_int
-tmx86_get_longrun_mode(void)
-{
- u_long eflags;
- union msrinfo msrinfo;
- u_int low, high, flags, mode;
-
- eflags = read_eflags();
- disable_intr();
-
- msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN);
- low = LONGRUN_MODE_MASK(msrinfo.regs[0]);
- high = LONGRUN_MODE_MASK(msrinfo.regs[1]);
- flags = rdmsr(MSR_TMx86_LONGRUN_FLAGS) & 0x01;
-
- for (mode = 0; mode < LONGRUN_MODE_MAX; mode++) {
- if (low == longrun_modes[mode][0] &&
- high == longrun_modes[mode][1] &&
- flags == longrun_modes[mode][2]) {
- goto out;
- }
- }
- mode = LONGRUN_MODE_UNKNOWN;
-out:
- write_eflags(eflags);
- return (mode);
-}
-
-static u_int
-tmx86_get_longrun_status(u_int * frequency, u_int * voltage, u_int * percentage)
-{
- u_long eflags;
- u_int regs[4];
-
- eflags = read_eflags();
- disable_intr();
-
- do_cpuid(0x80860007, regs);
- *frequency = regs[0];
- *voltage = regs[1];
- *percentage = regs[2];
-
- write_eflags(eflags);
- return (1);
-}
-
-static u_int
-tmx86_set_longrun_mode(u_int mode)
-{
- u_long eflags;
- union msrinfo msrinfo;
-
- if (mode >= LONGRUN_MODE_UNKNOWN) {
- return (0);
- }
-
- eflags = read_eflags();
- disable_intr();
-
- /* Write LongRun mode values to Model Specific Register. */
- msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN);
- msrinfo.regs[0] = LONGRUN_MODE_WRITE(msrinfo.regs[0],
- longrun_modes[mode][0]);
- msrinfo.regs[1] = LONGRUN_MODE_WRITE(msrinfo.regs[1],
- longrun_modes[mode][1]);
- wrmsr(MSR_TMx86_LONGRUN, msrinfo.msr);
-
- /* Write LongRun mode flags to Model Specific Register. */
- msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN_FLAGS);
- msrinfo.regs[0] = (msrinfo.regs[0] & ~0x01) | longrun_modes[mode][2];
- wrmsr(MSR_TMx86_LONGRUN_FLAGS, msrinfo.msr);
-
- write_eflags(eflags);
- return (1);
-}
-
-static u_int crusoe_longrun;
-static u_int crusoe_frequency;
-static u_int crusoe_voltage;
-static u_int crusoe_percentage;
-static u_int crusoe_performance_longrun = LONGRUN_MODE_PERFORMANCE;
-static u_int crusoe_economy_longrun = LONGRUN_MODE_ECONOMY;
-static struct sysctl_ctx_list crusoe_sysctl_ctx;
-static struct sysctl_oid *crusoe_sysctl_tree;
-
-static void
-tmx86_longrun_power_profile(void *arg)
-{
- int state;
- u_int new;
-
- state = power_profile_get_state();
- if (state != POWER_PROFILE_PERFORMANCE &&
- state != POWER_PROFILE_ECONOMY) {
- return;
- }
-
- switch (state) {
- case POWER_PROFILE_PERFORMANCE:
- new =crusoe_performance_longrun;
- break;
- case POWER_PROFILE_ECONOMY:
- new = crusoe_economy_longrun;
- break;
- default:
- new = tmx86_get_longrun_mode();
- break;
- }
-
- if (tmx86_get_longrun_mode() != new) {
- tmx86_set_longrun_mode(new);
- }
-}
-
-static int
-tmx86_longrun_sysctl(SYSCTL_HANDLER_ARGS)
-{
- u_int mode;
- int error;
-
- crusoe_longrun = tmx86_get_longrun_mode();
- mode = crusoe_longrun;
- error = sysctl_handle_int(oidp, &mode, 0, req);
- if (error || !req->newptr) {
- return (error);
- }
- if (mode >= LONGRUN_MODE_UNKNOWN) {
- error = EINVAL;
- return (error);
- }
- if (crusoe_longrun != mode) {
- crusoe_longrun = mode;
- tmx86_set_longrun_mode(crusoe_longrun);
- }
-
- return (error);
-}
-
-static int
-tmx86_status_sysctl(SYSCTL_HANDLER_ARGS)
-{
- u_int val;
- int error;
-
- tmx86_get_longrun_status(&crusoe_frequency,
- &crusoe_voltage, &crusoe_percentage);
- val = *(u_int *)oidp->oid_arg1;
- error = sysctl_handle_int(oidp, &val, 0, req);
- return (error);
-}
-
-static int
-tmx86_longrun_profile_sysctl(SYSCTL_HANDLER_ARGS)
-{
- u_int32_t *argp;
- u_int32_t arg;
- int error;
-
- argp = (u_int32_t *)oidp->oid_arg1;
- arg = *argp;
- error = sysctl_handle_int(oidp, &arg, 0, req);
-
- /* error or no new value */
- if ((error != 0) || (req->newptr == NULL))
- return (error);
-
- /* range check */
- if (arg >= LONGRUN_MODE_UNKNOWN)
- return (EINVAL);
-
- /* set new value and possibly switch */
- *argp = arg;
-
- tmx86_longrun_power_profile(NULL);
-
- return (0);
-
-}
-
-static void
-setup_tmx86_longrun(void)
-{
- static int done = 0;
-
- if (done)
- return;
- done++;
-
- sysctl_ctx_init(&crusoe_sysctl_ctx);
- crusoe_sysctl_tree = SYSCTL_ADD_NODE(&crusoe_sysctl_ctx,
- SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
- "crusoe", CTLFLAG_RD, 0,
- "Transmeta Crusoe LongRun support");
- SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree),
- OID_AUTO, "longrun", CTLTYPE_INT | CTLFLAG_RW,
- &crusoe_longrun, 0, tmx86_longrun_sysctl, "I",
- "LongRun mode [0-3]");
- SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree),
- OID_AUTO, "frequency", CTLTYPE_INT | CTLFLAG_RD,
- &crusoe_frequency, 0, tmx86_status_sysctl, "I",
- "Current frequency (MHz)");
- SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree),
- OID_AUTO, "voltage", CTLTYPE_INT | CTLFLAG_RD,
- &crusoe_voltage, 0, tmx86_status_sysctl, "I",
- "Current voltage (mV)");
- SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree),
- OID_AUTO, "percentage", CTLTYPE_INT | CTLFLAG_RD,
- &crusoe_percentage, 0, tmx86_status_sysctl, "I",
- "Processing performance (%)");
- SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree),
- OID_AUTO, "performance_longrun", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_RW,
- &crusoe_performance_longrun, 0, tmx86_longrun_profile_sysctl, "I", "");
- SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree),
- OID_AUTO, "economy_longrun", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_RW,
- &crusoe_economy_longrun, 0, tmx86_longrun_profile_sysctl, "I", "");
-
- /* register performance profile change handler */
- EVENTHANDLER_REGISTER(power_profile_change, tmx86_longrun_power_profile, NULL, 0);
-
-}
-
-static void
-print_transmeta_info()
-{
- u_int regs[4], nreg = 0;
-
- do_cpuid(0x80860000, regs);
- nreg = regs[0];
- if (nreg >= 0x80860001) {
- do_cpuid(0x80860001, regs);
- printf(" Processor revision %u.%u.%u.%u\n",
- (regs[1] >> 24) & 0xff,
- (regs[1] >> 16) & 0xff,
- (regs[1] >> 8) & 0xff,
- regs[1] & 0xff);
- }
- if (nreg >= 0x80860002) {
- do_cpuid(0x80860002, regs);
- printf(" Code Morphing Software revision %u.%u.%u-%u-%u\n",
- (regs[1] >> 24) & 0xff,
- (regs[1] >> 16) & 0xff,
- (regs[1] >> 8) & 0xff,
- regs[1] & 0xff,
- regs[2]);
- }
- if (nreg >= 0x80860006) {
- char info[65];
- do_cpuid(0x80860003, (u_int*) &info[0]);
- do_cpuid(0x80860004, (u_int*) &info[16]);
- do_cpuid(0x80860005, (u_int*) &info[32]);
- do_cpuid(0x80860006, (u_int*) &info[48]);
- info[64] = 0;
- printf(" %s\n", info);
- }
-
- crusoe_longrun = tmx86_get_longrun_mode();
- tmx86_get_longrun_status(&crusoe_frequency,
- &crusoe_voltage, &crusoe_percentage);
- printf(" LongRun mode: %d <%dMHz %dmV %d%%>\n", crusoe_longrun,
- crusoe_frequency, crusoe_voltage, crusoe_percentage);
-}
diff --git a/sys/amd64/amd64/initcpu.c b/sys/amd64/amd64/initcpu.c
index 3331c7ba1051..a93968ee5dcb 100644
--- a/sys/amd64/amd64/initcpu.c
+++ b/sys/amd64/amd64/initcpu.c
@@ -40,492 +40,19 @@
#include <machine/md_var.h>
#include <machine/specialreg.h>
-#if !defined(CPU_ENABLE_SSE) && defined(I686_CPU)
-#define CPU_ENABLE_SSE
-#endif
-#if defined(CPU_DISABLE_SSE)
-#undef CPU_ENABLE_SSE
-#endif
-
void initializecpu(void);
-#if defined(I586_CPU) && defined(CPU_WT_ALLOC)
-void enable_K5_wt_alloc(void);
-void enable_K6_wt_alloc(void);
-void enable_K6_2_wt_alloc(void);
-#endif
-
-#ifdef I486_CPU
-static void init_5x86(void);
-static void init_bluelightning(void);
-static void init_486dlc(void);
-static void init_cy486dx(void);
-#ifdef CPU_I486_ON_386
-static void init_i486_on_386(void);
-#endif
-static void init_6x86(void);
-#endif /* I486_CPU */
-
-#ifdef I686_CPU
-static void init_6x86MX(void);
-static void init_ppro(void);
-static void init_mendocino(void);
-#endif
static int hw_instruction_sse;
SYSCTL_INT(_hw, OID_AUTO, instruction_sse, CTLFLAG_RD,
&hw_instruction_sse, 0, "SIMD/MMX2 instructions available in CPU");
-/* Must *NOT* be BSS or locore will bzero these after setting them */
-int cpu = 0; /* Are we 386, 386sx, 486, etc? */
-u_int cpu_feature = 0; /* Feature flags */
-u_int cpu_high = 0; /* Highest arg to CPUID */
-u_int cpu_id = 0; /* Stepping ID */
-u_int cpu_procinfo = 0; /* HyperThreading Info / Brand Index / CLFUSH */
-char cpu_vendor[20] = ""; /* CPU Origin code */
-
-#ifdef CPU_ENABLE_SSE
+int cpu; /* Are we 386, 386sx, 486, etc? */
+u_int cpu_feature; /* Feature flags */
+u_int cpu_high; /* Highest arg to CPUID */
+u_int cpu_id; /* Stepping ID */
+u_int cpu_procinfo; /* HyperThreading Info / Brand Index / CLFUSH */
+char cpu_vendor[20]; /* CPU Origin code */
u_int cpu_fxsr; /* SSE enabled */
-#endif
-
-#ifdef I486_CPU
-/*
- * IBM Blue Lightning
- */
-static void
-init_bluelightning(void)
-{
- u_long eflags;
-
-#if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE)
- need_post_dma_flush = 1;
-#endif
-
- eflags = read_eflags();
- disable_intr();
-
- load_cr0(rcr0() | CR0_CD | CR0_NW);
- invd();
-
-#ifdef CPU_BLUELIGHTNING_FPU_OP_CACHE
- wrmsr(0x1000, 0x9c92LL); /* FP operand can be cacheable on Cyrix FPU */
-#else
- wrmsr(0x1000, 0x1c92LL); /* Intel FPU */
-#endif
- /* Enables 13MB and 0-640KB cache. */
- wrmsr(0x1001, (0xd0LL << 32) | 0x3ff);
-#ifdef CPU_BLUELIGHTNING_3X
- wrmsr(0x1002, 0x04000000LL); /* Enables triple-clock mode. */
-#else
- wrmsr(0x1002, 0x03000000LL); /* Enables double-clock mode. */
-#endif
-
- /* Enable caching in CR0. */
- load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); /* CD = 0 and NW = 0 */
- invd();
- write_eflags(eflags);
-}
-
-/*
- * Cyrix 486SLC/DLC/SR/DR series
- */
-static void
-init_486dlc(void)
-{
- u_long eflags;
- u_char ccr0;
-
- eflags = read_eflags();
- disable_intr();
- invd();
-
- ccr0 = read_cyrix_reg(CCR0);
-#ifndef CYRIX_CACHE_WORKS
- ccr0 |= CCR0_NC1 | CCR0_BARB;
- write_cyrix_reg(CCR0, ccr0);
- invd();
-#else
- ccr0 &= ~CCR0_NC0;
-#ifndef CYRIX_CACHE_REALLY_WORKS
- ccr0 |= CCR0_NC1 | CCR0_BARB;
-#else
- ccr0 |= CCR0_NC1;
-#endif
-#ifdef CPU_DIRECT_MAPPED_CACHE
- ccr0 |= CCR0_CO; /* Direct mapped mode. */
-#endif
- write_cyrix_reg(CCR0, ccr0);
-
- /* Clear non-cacheable region. */
- write_cyrix_reg(NCR1+2, NCR_SIZE_0K);
- write_cyrix_reg(NCR2+2, NCR_SIZE_0K);
- write_cyrix_reg(NCR3+2, NCR_SIZE_0K);
- write_cyrix_reg(NCR4+2, NCR_SIZE_0K);
-
- write_cyrix_reg(0, 0); /* dummy write */
-
- /* Enable caching in CR0. */
- load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); /* CD = 0 and NW = 0 */
- invd();
-#endif /* !CYRIX_CACHE_WORKS */
- write_eflags(eflags);
-}
-
-
-/*
- * Cyrix 486S/DX series
- */
-static void
-init_cy486dx(void)
-{
- u_long eflags;
- u_char ccr2;
-
- eflags = read_eflags();
- disable_intr();
- invd();
-
- ccr2 = read_cyrix_reg(CCR2);
-#ifdef CPU_SUSP_HLT
- ccr2 |= CCR2_SUSP_HLT;
-#endif
-
-#ifdef PC98
- /* Enables WB cache interface pin and Lock NW bit in CR0. */
- ccr2 |= CCR2_WB | CCR2_LOCK_NW;
- /* Unlock NW bit in CR0. */
- write_cyrix_reg(CCR2, ccr2 & ~CCR2_LOCK_NW);
- load_cr0((rcr0() & ~CR0_CD) | CR0_NW); /* CD = 0, NW = 1 */
-#endif
-
- write_cyrix_reg(CCR2, ccr2);
- write_eflags(eflags);
-}
-
-
-/*
- * Cyrix 5x86
- */
-static void
-init_5x86(void)
-{
- u_long eflags;
- u_char ccr2, ccr3, ccr4, pcr0;
-
- eflags = read_eflags();
- disable_intr();
-
- load_cr0(rcr0() | CR0_CD | CR0_NW);
- wbinvd();
-
- (void)read_cyrix_reg(CCR3); /* dummy */
-
- /* Initialize CCR2. */
- ccr2 = read_cyrix_reg(CCR2);
- ccr2 |= CCR2_WB;
-#ifdef CPU_SUSP_HLT
- ccr2 |= CCR2_SUSP_HLT;
-#else
- ccr2 &= ~CCR2_SUSP_HLT;
-#endif
- ccr2 |= CCR2_WT1;
- write_cyrix_reg(CCR2, ccr2);
-
- /* Initialize CCR4. */
- ccr3 = read_cyrix_reg(CCR3);
- write_cyrix_reg(CCR3, CCR3_MAPEN0);
-
- ccr4 = read_cyrix_reg(CCR4);
- ccr4 |= CCR4_DTE;
- ccr4 |= CCR4_MEM;
-#ifdef CPU_FASTER_5X86_FPU
- ccr4 |= CCR4_FASTFPE;
-#else
- ccr4 &= ~CCR4_FASTFPE;
-#endif
- ccr4 &= ~CCR4_IOMASK;
- /********************************************************************
- * WARNING: The "BIOS Writers Guide" mentions that I/O recovery time
- * should be 0 for errata fix.
- ********************************************************************/
-#ifdef CPU_IORT
- ccr4 |= CPU_IORT & CCR4_IOMASK;
-#endif
- write_cyrix_reg(CCR4, ccr4);
-
- /* Initialize PCR0. */
- /****************************************************************
- * WARNING: RSTK_EN and LOOP_EN could make your system unstable.
- * BTB_EN might make your system unstable.
- ****************************************************************/
- pcr0 = read_cyrix_reg(PCR0);
-#ifdef CPU_RSTK_EN
- pcr0 |= PCR0_RSTK;
-#else
- pcr0 &= ~PCR0_RSTK;
-#endif
-#ifdef CPU_BTB_EN
- pcr0 |= PCR0_BTB;
-#else
- pcr0 &= ~PCR0_BTB;
-#endif
-#ifdef CPU_LOOP_EN
- pcr0 |= PCR0_LOOP;
-#else
- pcr0 &= ~PCR0_LOOP;
-#endif
-
- /****************************************************************
- * WARNING: if you use a memory mapped I/O device, don't use
- * DISABLE_5X86_LSSER option, which may reorder memory mapped
- * I/O access.
- * IF YOUR MOTHERBOARD HAS PCI BUS, DON'T DISABLE LSSER.
- ****************************************************************/
-#ifdef CPU_DISABLE_5X86_LSSER
- pcr0 &= ~PCR0_LSSER;
-#else
- pcr0 |= PCR0_LSSER;
-#endif
- write_cyrix_reg(PCR0, pcr0);
-
- /* Restore CCR3. */
- write_cyrix_reg(CCR3, ccr3);
-
- (void)read_cyrix_reg(0x80); /* dummy */
-
- /* Unlock NW bit in CR0. */
- write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW);
- load_cr0((rcr0() & ~CR0_CD) | CR0_NW); /* CD = 0, NW = 1 */
- /* Lock NW bit in CR0. */
- write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW);
-
- write_eflags(eflags);
-}
-
-#ifdef CPU_I486_ON_386
-/*
- * There are i486 based upgrade products for i386 machines.
- * In this case, BIOS doesn't enables CPU cache.
- */
-static void
-init_i486_on_386(void)
-{
- u_long eflags;
-
-#if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE)
- need_post_dma_flush = 1;
-#endif
-
- eflags = read_eflags();
- disable_intr();
-
- load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); /* CD = 0, NW = 0 */
-
- write_eflags(eflags);
-}
-#endif
-
-/*
- * Cyrix 6x86
- *
- * XXX - What should I do here? Please let me know.
- */
-static void
-init_6x86(void)
-{
- u_long eflags;
- u_char ccr3, ccr4;
-
- eflags = read_eflags();
- disable_intr();
-
- load_cr0(rcr0() | CR0_CD | CR0_NW);
- wbinvd();
-
- /* Initialize CCR0. */
- write_cyrix_reg(CCR0, read_cyrix_reg(CCR0) | CCR0_NC1);
-
- /* Initialize CCR1. */
-#ifdef CPU_CYRIX_NO_LOCK
- write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) | CCR1_NO_LOCK);
-#else
- write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) & ~CCR1_NO_LOCK);
-#endif
-
- /* Initialize CCR2. */
-#ifdef CPU_SUSP_HLT
- write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_SUSP_HLT);
-#else
- write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_SUSP_HLT);
-#endif
-
- ccr3 = read_cyrix_reg(CCR3);
- write_cyrix_reg(CCR3, CCR3_MAPEN0);
-
- /* Initialize CCR4. */
- ccr4 = read_cyrix_reg(CCR4);
- ccr4 |= CCR4_DTE;
- ccr4 &= ~CCR4_IOMASK;
-#ifdef CPU_IORT
- write_cyrix_reg(CCR4, ccr4 | (CPU_IORT & CCR4_IOMASK));
-#else
- write_cyrix_reg(CCR4, ccr4 | 7);
-#endif
-
- /* Initialize CCR5. */
-#ifdef CPU_WT_ALLOC
- write_cyrix_reg(CCR5, read_cyrix_reg(CCR5) | CCR5_WT_ALLOC);
-#endif
-
- /* Restore CCR3. */
- write_cyrix_reg(CCR3, ccr3);
-
- /* Unlock NW bit in CR0. */
- write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW);
-
- /*
- * Earlier revision of the 6x86 CPU could crash the system if
- * L1 cache is in write-back mode.
- */
- if ((cyrix_did & 0xff00) > 0x1600)
- load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); /* CD = 0 and NW = 0 */
- else {
- /* Revision 2.6 and lower. */
-#ifdef CYRIX_CACHE_REALLY_WORKS
- load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); /* CD = 0 and NW = 0 */
-#else
- load_cr0((rcr0() & ~CR0_CD) | CR0_NW); /* CD = 0 and NW = 1 */
-#endif
- }
-
- /* Lock NW bit in CR0. */
- write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW);
-
- write_eflags(eflags);
-}
-#endif /* I486_CPU */
-
-#ifdef I686_CPU
-/*
- * Cyrix 6x86MX (code-named M2)
- *
- * XXX - What should I do here? Please let me know.
- */
-static void
-init_6x86MX(void)
-{
- u_long eflags;
- u_char ccr3, ccr4;
-
- eflags = read_eflags();
- disable_intr();
-
- load_cr0(rcr0() | CR0_CD | CR0_NW);
- wbinvd();
-
- /* Initialize CCR0. */
- write_cyrix_reg(CCR0, read_cyrix_reg(CCR0) | CCR0_NC1);
-
- /* Initialize CCR1. */
-#ifdef CPU_CYRIX_NO_LOCK
- write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) | CCR1_NO_LOCK);
-#else
- write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) & ~CCR1_NO_LOCK);
-#endif
-
- /* Initialize CCR2. */
-#ifdef CPU_SUSP_HLT
- write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_SUSP_HLT);
-#else
- write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_SUSP_HLT);
-#endif
-
- ccr3 = read_cyrix_reg(CCR3);
- write_cyrix_reg(CCR3, CCR3_MAPEN0);
-
- /* Initialize CCR4. */
- ccr4 = read_cyrix_reg(CCR4);
- ccr4 &= ~CCR4_IOMASK;
-#ifdef CPU_IORT
- write_cyrix_reg(CCR4, ccr4 | (CPU_IORT & CCR4_IOMASK));
-#else
- write_cyrix_reg(CCR4, ccr4 | 7);
-#endif
-
- /* Initialize CCR5. */
-#ifdef CPU_WT_ALLOC
- write_cyrix_reg(CCR5, read_cyrix_reg(CCR5) | CCR5_WT_ALLOC);
-#endif
-
- /* Restore CCR3. */
- write_cyrix_reg(CCR3, ccr3);
-
- /* Unlock NW bit in CR0. */
- write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW);
-
- load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); /* CD = 0 and NW = 0 */
-
- /* Lock NW bit in CR0. */
- write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW);
-
- write_eflags(eflags);
-}
-
-static void
-init_ppro(void)
-{
-#ifndef SMP
- u_int64_t apicbase;
-
- /*
- * Local APIC should be diabled in UP kernel.
- */
- apicbase = rdmsr(0x1b);
- apicbase &= ~0x800LL;
- wrmsr(0x1b, apicbase);
-#endif
-}
-
-/*
- * Initialize BBL_CR_CTL3 (Control register 3: used to configure the
- * L2 cache).
- */
-static void
-init_mendocino(void)
-{
-#ifdef CPU_PPRO2CELERON
- u_long eflags;
- u_int64_t bbl_cr_ctl3;
-
- eflags = read_eflags();
- disable_intr();
-
- load_cr0(rcr0() | CR0_CD | CR0_NW);
- wbinvd();
-
- bbl_cr_ctl3 = rdmsr(0x11e);
-
- /* If the L2 cache is configured, do nothing. */
- if (!(bbl_cr_ctl3 & 1)) {
- bbl_cr_ctl3 = 0x134052bLL;
-
- /* Set L2 Cache Latency (Default: 5). */
-#ifdef CPU_CELERON_L2_LATENCY
-#if CPU_L2_LATENCY > 15
-#error invalid CPU_L2_LATENCY.
-#endif
- bbl_cr_ctl3 |= CPU_L2_LATENCY << 1;
-#else
- bbl_cr_ctl3 |= 5 << 1;
-#endif
- wrmsr(0x11e, bbl_cr_ctl3);
- }
-
- load_cr0(rcr0() & ~(CR0_CD | CR0_NW));
- write_eflags(eflags);
-#endif /* CPU_PPRO2CELERON */
-}
-
-#endif /* I686_CPU */
/*
* Initialize CR4 (Control register 4) to enable SSE instructions.
@@ -533,12 +60,10 @@ init_mendocino(void)
void
enable_sse(void)
{
-#if defined(CPU_ENABLE_SSE)
if ((cpu_feature & CPUID_XMM) && (cpu_feature & CPUID_FXSR)) {
load_cr4(rcr4() | CR4_FXSR | CR4_XMM);
cpu_fxsr = hw_instruction_sse = 1;
}
-#endif
}
void
@@ -546,337 +71,8 @@ initializecpu(void)
{
switch (cpu) {
-#ifdef I486_CPU
- case CPU_BLUE:
- init_bluelightning();
- break;
- case CPU_486DLC:
- init_486dlc();
- break;
- case CPU_CY486DX:
- init_cy486dx();
- break;
- case CPU_M1SC:
- init_5x86();
- break;
-#ifdef CPU_I486_ON_386
- case CPU_486:
- init_i486_on_386();
- break;
-#endif
- case CPU_M1:
- init_6x86();
- break;
-#endif /* I486_CPU */
-#ifdef I686_CPU
- case CPU_M2:
- init_6x86MX();
- break;
- case CPU_686:
- if (strcmp(cpu_vendor, "GenuineIntel") == 0) {
- switch (cpu_id & 0xff0) {
- case 0x610:
- init_ppro();
- break;
- case 0x660:
- init_mendocino();
- break;
- }
- } else if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
-#if defined(I686_CPU) && defined(CPU_ATHLON_SSE_HACK)
- /*
- * Sometimes the BIOS doesn't enable SSE instructions.
- * According to AMD document 20734, the mobile
- * Duron, the (mobile) Athlon 4 and the Athlon MP
- * support SSE. These correspond to cpu_id 0x66X
- * or 0x67X.
- */
- if ((cpu_feature & CPUID_XMM) == 0 &&
- ((cpu_id & ~0xf) == 0x660 ||
- (cpu_id & ~0xf) == 0x670 ||
- (cpu_id & ~0xf) == 0x680)) {
- u_int regs[4];
- wrmsr(0xC0010015, rdmsr(0xC0010015) & ~0x08000);
- do_cpuid(1, regs);
- cpu_feature = regs[3];
- }
-#endif
- }
- break;
-#endif
default:
break;
}
enable_sse();
-
-#if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE)
- /*
- * OS should flush L1 cache by itself because no PC-98 supports
- * non-Intel CPUs. Use wbinvd instruction before DMA transfer
- * when need_pre_dma_flush = 1, use invd instruction after DMA
- * transfer when need_post_dma_flush = 1. If your CPU upgrade
- * product supports hardware cache control, you can add the
- * CPU_UPGRADE_HW_CACHE option in your kernel configuration file.
- * This option eliminates unneeded cache flush instruction(s).
- */
- if (strcmp(cpu_vendor, "CyrixInstead") == 0) {
- switch (cpu) {
-#ifdef I486_CPU
- case CPU_486DLC:
- need_post_dma_flush = 1;
- break;
- case CPU_M1SC:
- need_pre_dma_flush = 1;
- break;
- case CPU_CY486DX:
- need_pre_dma_flush = 1;
-#ifdef CPU_I486_ON_386
- need_post_dma_flush = 1;
-#endif
- break;
-#endif
- default:
- break;
- }
- } else if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
- switch (cpu_id & 0xFF0) {
- case 0x470: /* Enhanced Am486DX2 WB */
- case 0x490: /* Enhanced Am486DX4 WB */
- case 0x4F0: /* Am5x86 WB */
- need_pre_dma_flush = 1;
- break;
- }
- } else if (strcmp(cpu_vendor, "IBM") == 0) {
- need_post_dma_flush = 1;
- } else {
-#ifdef CPU_I486_ON_386
- need_pre_dma_flush = 1;
-#endif
- }
-#endif /* PC98 && !CPU_UPGRADE_HW_CACHE */
-}
-
-#if defined(I586_CPU) && defined(CPU_WT_ALLOC)
-/*
- * Enable write allocate feature of AMD processors.
- * Following two functions require the Maxmem variable being set.
- */
-void
-enable_K5_wt_alloc(void)
-{
- u_int64_t msr;
- register_t savecrit;
-
- /*
- * Write allocate is supported only on models 1, 2, and 3, with
- * a stepping of 4 or greater.
- */
- if (((cpu_id & 0xf0) > 0) && ((cpu_id & 0x0f) > 3)) {
- savecrit = intr_disable();
- msr = rdmsr(0x83); /* HWCR */
- wrmsr(0x83, msr & !(0x10));
-
- /*
- * We have to tell the chip where the top of memory is,
- * since video cards could have frame bufferes there,
- * memory-mapped I/O could be there, etc.
- */
- if(Maxmem > 0)
- msr = Maxmem / 16;
- else
- msr = 0;
- msr |= AMD_WT_ALLOC_TME | AMD_WT_ALLOC_FRE;
-#ifdef PC98
- if (!(inb(0x43b) & 4)) {
- wrmsr(0x86, 0x0ff00f0);
- msr |= AMD_WT_ALLOC_PRE;
- }
-#else
- /*
- * There is no way to know wheter 15-16M hole exists or not.
- * Therefore, we disable write allocate for this range.
- */
- wrmsr(0x86, 0x0ff00f0);
- msr |= AMD_WT_ALLOC_PRE;
-#endif
- wrmsr(0x85, msr);
-
- msr=rdmsr(0x83);
- wrmsr(0x83, msr|0x10); /* enable write allocate */
- intr_restore(savecrit);
- }
-}
-
-void
-enable_K6_wt_alloc(void)
-{
- quad_t size;
- u_int64_t whcr;
- u_long eflags;
-
- eflags = read_eflags();
- disable_intr();
- wbinvd();
-
-#ifdef CPU_DISABLE_CACHE
- /*
- * Certain K6-2 box becomes unstable when write allocation is
- * enabled.
- */
- /*
- * The AMD-K6 processer provides the 64-bit Test Register 12(TR12),
- * but only the Cache Inhibit(CI) (bit 3 of TR12) is suppported.
- * All other bits in TR12 have no effect on the processer's operation.
- * The I/O Trap Restart function (bit 9 of TR12) is always enabled
- * on the AMD-K6.
- */
- wrmsr(0x0000000e, (u_int64_t)0x0008);
-#endif
- /* Don't assume that memory size is aligned with 4M. */
- if (Maxmem > 0)
- size = ((Maxmem >> 8) + 3) >> 2;
- else
- size = 0;
-
- /* Limit is 508M bytes. */
- if (size > 0x7f)
- size = 0x7f;
- whcr = (rdmsr(0xc0000082) & ~(0x7fLL << 1)) | (size << 1);
-
-#if defined(PC98) || defined(NO_MEMORY_HOLE)
- if (whcr & (0x7fLL << 1)) {
-#ifdef PC98
- /*
- * If bit 2 of port 0x43b is 0, disable wrte allocate for the
- * 15-16M range.
- */
- if (!(inb(0x43b) & 4))
- whcr &= ~0x0001LL;
- else
-#endif
- whcr |= 0x0001LL;
- }
-#else
- /*
- * There is no way to know wheter 15-16M hole exists or not.
- * Therefore, we disable write allocate for this range.
- */
- whcr &= ~0x0001LL;
-#endif
- wrmsr(0x0c0000082, whcr);
-
- write_eflags(eflags);
-}
-
-void
-enable_K6_2_wt_alloc(void)
-{
- quad_t size;
- u_int64_t whcr;
- u_long eflags;
-
- eflags = read_eflags();
- disable_intr();
- wbinvd();
-
-#ifdef CPU_DISABLE_CACHE
- /*
- * Certain K6-2 box becomes unstable when write allocation is
- * enabled.
- */
- /*
- * The AMD-K6 processer provides the 64-bit Test Register 12(TR12),
- * but only the Cache Inhibit(CI) (bit 3 of TR12) is suppported.
- * All other bits in TR12 have no effect on the processer's operation.
- * The I/O Trap Restart function (bit 9 of TR12) is always enabled
- * on the AMD-K6.
- */
- wrmsr(0x0000000e, (u_int64_t)0x0008);
-#endif
- /* Don't assume that memory size is aligned with 4M. */
- if (Maxmem > 0)
- size = ((Maxmem >> 8) + 3) >> 2;
- else
- size = 0;
-
- /* Limit is 4092M bytes. */
- if (size > 0x3fff)
- size = 0x3ff;
- whcr = (rdmsr(0xc0000082) & ~(0x3ffLL << 22)) | (size << 22);
-
-#if defined(PC98) || defined(NO_MEMORY_HOLE)
- if (whcr & (0x3ffLL << 22)) {
-#ifdef PC98
- /*
- * If bit 2 of port 0x43b is 0, disable wrte allocate for the
- * 15-16M range.
- */
- if (!(inb(0x43b) & 4))
- whcr &= ~(1LL << 16);
- else
-#endif
- whcr |= 1LL << 16;
- }
-#else
- /*
- * There is no way to know wheter 15-16M hole exists or not.
- * Therefore, we disable write allocate for this range.
- */
- whcr &= ~(1LL << 16);
-#endif
- wrmsr(0x0c0000082, whcr);
-
- write_eflags(eflags);
-}
-#endif /* I585_CPU && CPU_WT_ALLOC */
-
-#include "opt_ddb.h"
-#ifdef DDB
-#include <ddb/ddb.h>
-
-DB_SHOW_COMMAND(cyrixreg, cyrixreg)
-{
- u_long eflags;
- u_int cr0;
- u_char ccr1, ccr2, ccr3;
- u_char ccr0 = 0, ccr4 = 0, ccr5 = 0, pcr0 = 0;
-
- cr0 = rcr0();
- if (strcmp(cpu_vendor,"CyrixInstead") == 0) {
- eflags = read_eflags();
- disable_intr();
-
-
- if ((cpu != CPU_M1SC) && (cpu != CPU_CY486DX)) {
- ccr0 = read_cyrix_reg(CCR0);
- }
- ccr1 = read_cyrix_reg(CCR1);
- ccr2 = read_cyrix_reg(CCR2);
- ccr3 = read_cyrix_reg(CCR3);
- if ((cpu == CPU_M1SC) || (cpu == CPU_M1) || (cpu == CPU_M2)) {
- write_cyrix_reg(CCR3, CCR3_MAPEN0);
- ccr4 = read_cyrix_reg(CCR4);
- if ((cpu == CPU_M1) || (cpu == CPU_M2))
- ccr5 = read_cyrix_reg(CCR5);
- else
- pcr0 = read_cyrix_reg(PCR0);
- write_cyrix_reg(CCR3, ccr3); /* Restore CCR3. */
- }
- write_eflags(eflags);
-
- if ((cpu != CPU_M1SC) && (cpu != CPU_CY486DX))
- printf("CCR0=%x, ", (u_int)ccr0);
-
- printf("CCR1=%x, CCR2=%x, CCR3=%x",
- (u_int)ccr1, (u_int)ccr2, (u_int)ccr3);
- if ((cpu == CPU_M1SC) || (cpu == CPU_M1) || (cpu == CPU_M2)) {
- printf(", CCR4=%x, ", (u_int)ccr4);
- if (cpu == CPU_M1SC)
- printf("PCR0=%x\n", pcr0);
- else
- printf("CCR5=%x\n", ccr5);
- }
- }
- printf("CR0=%x\n", cr0);
}
-#endif /* DDB */
diff --git a/sys/amd64/amd64/legacy.c b/sys/amd64/amd64/legacy.c
index 3effb94fe753..7f0e89c1e568 100644
--- a/sys/amd64/amd64/legacy.c
+++ b/sys/amd64/amd64/legacy.c
@@ -148,21 +148,9 @@ legacy_attach(device_t dev)
bus_generic_attach(dev);
/*
- * If we didn't see EISA or ISA on a pci bridge, create some
- * connection points now so they show up "on motherboard".
+ * If we didn't see ISA on a pci bridge, create some
+ * connection points now so it shows up "on motherboard".
*/
- if (!devclass_get_device(devclass_find("eisa"), 0)) {
- child = BUS_ADD_CHILD(dev, 0, "eisa", 0);
- if (child == NULL)
- panic("legacy_attach eisa");
- device_probe_and_attach(child);
- }
- if (!devclass_get_device(devclass_find("mca"), 0)) {
- child = BUS_ADD_CHILD(dev, 0, "mca", 0);
- if (child == 0)
- panic("legacy_probe mca");
- device_probe_and_attach(child);
- }
if (!devclass_get_device(devclass_find("isa"), 0)) {
child = BUS_ADD_CHILD(dev, 0, "isa", 0);
if (child == NULL)
diff --git a/sys/amd64/amd64/locore.S b/sys/amd64/amd64/locore.S
index 8115e2399749..65b01ac9845b 100644
--- a/sys/amd64/amd64/locore.S
+++ b/sys/amd64/amd64/locore.S
@@ -1,10 +1,7 @@
/*-
- * Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 2003 Peter Wemm <peter@FreeBSD.org>
* All rights reserved.
*
- * This code is derived from software contributed to Berkeley by
- * William Jolitz.
- *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -13,18 +10,11 @@
* 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 the University of
- * California, Berkeley and its contributors.
- * 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
+ * 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 REGENTS OR CONTRIBUTORS BE LIABLE
+ * 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)
@@ -33,25 +23,10 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * from: @(#)locore.s 7.3 (Berkeley) 5/13/91
* $FreeBSD$
- *
- * originally from: locore.s, by William F. Jolitz
- *
- * Substantially rewritten by David Greenman, Rod Grimes,
- * Bruce Evans, Wolfgang Solfrank, Poul-Henning Kamp
- * and many others.
*/
-#include "opt_bootp.h"
-#include "opt_compat.h"
-#include "opt_nfsroot.h"
-
-#include <sys/syscall.h>
-#include <sys/reboot.h>
-
#include <machine/asmacros.h>
-#include <machine/cputypes.h>
#include <machine/psl.h>
#include <machine/pmap.h>
#include <machine/specialreg.h>
@@ -59,14 +34,6 @@
#include "assym.s"
/*
- * XXX
- *
- * Note: This version greatly munged to avoid various assembler errors
- * that may be fixed in newer versions of gas. Perhaps newer versions
- * will have more pleasant appearance.
- */
-
-/*
* PTmap is recursive pagemap at top of virtual address space.
* Within PTmap, the page directory can be found (third indirection).
*/
@@ -75,837 +42,51 @@
.set PTD,PTmap + (PTDPTDI * PAGE_SIZE)
.set PTDpde,PTD + (PTDPTDI * PDESIZE)
-#ifdef SMP
-/*
- * Define layout of per-cpu address space.
- * This is "constructed" in locore.s on the BSP and in mp_machdep.c
- * for each AP. DO NOT REORDER THESE WITHOUT UPDATING THE REST!
- */
- .globl SMP_prvspace, lapic
- .set SMP_prvspace,(MPPTDI << PDRSHIFT)
- .set lapic,SMP_prvspace + (NPTEPG-1) * PAGE_SIZE
-#endif /* SMP */
-
/*
* Compiled KERNBASE location
*/
.globl kernbase
.set kernbase,KERNBASE
-/*
- * Globals
- */
- .data
- ALIGN_DATA /* just to be sure */
-
- .globl HIDENAME(tmpstk)
- .space 0x2000 /* space for tmpstk - temporary stack */
-HIDENAME(tmpstk):
-
- .globl bootinfo
-bootinfo: .space BOOTINFO_SIZE /* bootinfo that we can handle */
-
- .globl KERNend
-KERNend: .long 0 /* phys addr end of kernel (just after bss) */
-physfree: .long 0 /* phys addr of next free page */
-
-#ifdef SMP
- .globl cpu0prvpage
-cpu0pp: .long 0 /* phys addr cpu0 private pg */
-cpu0prvpage: .long 0 /* relocated version */
-
- .globl SMPpt
-SMPptpa: .long 0 /* phys addr SMP page table */
-SMPpt: .long 0 /* relocated version */
-#endif /* SMP */
-
- .globl IdlePTD
-IdlePTD: .long 0 /* phys addr of kernel PTD */
-
-#ifdef PAE
- .globl IdlePDPT
-IdlePDPT: .long 0 /* phys addr of kernel PDPT */
-#endif
-
-#ifdef SMP
- .globl KPTphys
-#endif
-KPTphys: .long 0 /* phys addr of kernel page tables */
-
- .globl proc0uarea, proc0kstack
-proc0uarea: .long 0 /* address of proc 0 uarea space */
-proc0kstack: .long 0 /* address of proc 0 kstack space */
-p0upa: .long 0 /* phys addr of proc0's UAREA */
-p0kpa: .long 0 /* phys addr of proc0's STACK */
-
-vm86phystk: .long 0 /* PA of vm86/bios stack */
-
- .globl vm86paddr, vm86pa
-vm86paddr: .long 0 /* address of vm86 region */
-vm86pa: .long 0 /* phys addr of vm86 region */
-
-#ifdef PC98
- .globl pc98_system_parameter
-pc98_system_parameter:
- .space 0x240
-#endif
-
-/**********************************************************************
- *
- * Some handy macros
- *
- */
-
-#define R(foo) ((foo)-KERNBASE)
-
-#define ALLOCPAGES(foo) \
- movl R(physfree), %esi ; \
- movl $((foo)*PAGE_SIZE), %eax ; \
- addl %esi, %eax ; \
- movl %eax, R(physfree) ; \
- movl %esi, %edi ; \
- movl $((foo)*PAGE_SIZE),%ecx ; \
- xorl %eax,%eax ; \
- cld ; \
- rep ; \
- stosb
-
-/*
- * fillkpt
- * eax = page frame address
- * ebx = index into page table
- * ecx = how many pages to map
- * base = base address of page dir/table
- * prot = protection bits
- */
-#define fillkpt(base, prot) \
- shll $PTESHIFT,%ebx ; \
- addl base,%ebx ; \
- orl $PG_V,%eax ; \
- orl prot,%eax ; \
-1: movl %eax,(%ebx) ; \
- addl $PAGE_SIZE,%eax ; /* increment physical address */ \
- addl $PTESIZE,%ebx ; /* next pte */ \
- loop 1b
-
-/*
- * fillkptphys(prot)
- * eax = physical address
- * ecx = how many pages to map
- * prot = protection bits
- */
-#define fillkptphys(prot) \
- movl %eax, %ebx ; \
- shrl $PAGE_SHIFT, %ebx ; \
- fillkpt(R(KPTphys), prot)
-
.text
/**********************************************************************
*
- * This is where the bootblocks start us, set the ball rolling...
+ * This is where the loader trampoline start us, set the ball rolling...
+ *
+ * We are called with the stack looking like this:
+ * 0(%rsp) = 32 bit return address (cannot be used)
+ * 4(%rsp) = 32 bit modulep
+ * 8(%rsp) = 32 bit kernend
*
+ * We are already in long mode, on a 64 bit %cs and running at KERNBASE.
*/
NON_GPROF_ENTRY(btext)
-#ifdef PC98
- /* save SYSTEM PARAMETER for resume (NS/T or other) */
- movl $0xa1400,%esi
- movl $R(pc98_system_parameter),%edi
- movl $0x0240,%ecx
- cld
- rep
- movsb
-#else /* IBM-PC */
-/* Tell the bios to warmboot next time */
+ /* Tell the bios to warmboot next time */
movw $0x1234,0x472
-#endif /* PC98 */
-
-/* Set up a real frame in case the double return in newboot is executed. */
- pushl %ebp
- movl %esp, %ebp
-
-/* Don't trust what the BIOS gives for eflags. */
- pushl $PSL_KERNEL
- popfl
-
-/*
- * Don't trust what the BIOS gives for %fs and %gs. Trust the bootstrap
- * to set %cs, %ds, %es and %ss.
- */
- mov %ds, %ax
- mov %ax, %fs
- mov %ax, %gs
-
- call recover_bootinfo
-
-/* Get onto a stack that we can trust. */
-/*
- * XXX this step is delayed in case recover_bootinfo needs to return via
- * the old stack, but it need not be, since recover_bootinfo actually
- * returns via the old frame.
- */
- movl $R(HIDENAME(tmpstk)),%esp
-
-#ifdef PC98
- /* pc98_machine_type & M_EPSON_PC98 */
- testb $0x02,R(pc98_system_parameter)+220
- jz 3f
- /* epson_machine_id <= 0x0b */
- cmpb $0x0b,R(pc98_system_parameter)+224
- ja 3f
-
- /* count up memory */
- movl $0x100000,%eax /* next, talley remaining memory */
- movl $0xFFF-0x100,%ecx
-1: movl 0(%eax),%ebx /* save location to check */
- movl $0xa55a5aa5,0(%eax) /* write test pattern */
- cmpl $0xa55a5aa5,0(%eax) /* does not check yet for rollover */
- jne 2f
- movl %ebx,0(%eax) /* restore memory */
- addl $PAGE_SIZE,%eax
- loop 1b
-2: subl $0x100000,%eax
- shrl $17,%eax
- movb %al,R(pc98_system_parameter)+1
-3:
-
- movw R(pc98_system_parameter+0x86),%ax
- movw %ax,R(cpu_id)
-#endif
-
- call identify_cpu
-/* clear bss */
-/*
- * XXX this should be done a little earlier.
- *
- * XXX we don't check that there is memory for our bss and page tables
- * before using it.
- *
- * XXX the boot program somewhat bogusly clears the bss. We still have
- * to do it in case we were unzipped by kzipboot. Then the boot program
- * only clears kzipboot's bss.
- *
- * XXX the gdt and idt are still somewhere in the boot program. We
- * depend on the convention that the boot program is below 1MB and we
- * are above 1MB to keep the gdt and idt away from the bss and page
- * tables.
- */
- movl $R(end),%ecx
- movl $R(edata),%edi
- subl %edi,%ecx
- xorl %eax,%eax
- cld
- rep
- stosb
-
- call create_pagetables
-
-/*
- * If the CPU has support for VME, turn it on.
- */
- testl $CPUID_VME, R(cpu_feature)
- jz 1f
- movl %cr4, %eax
- orl $CR4_VME, %eax
- movl %eax, %cr4
-1:
-
-/* Now enable paging */
-#ifdef PAE
- movl R(IdlePDPT), %eax
- movl %eax, %cr3
- movl %cr4, %eax
- orl $CR4_PAE, %eax
- movl %eax, %cr4
-#else
- movl R(IdlePTD), %eax
- movl %eax,%cr3 /* load ptd addr into mmu */
-#endif
- movl %cr0,%eax /* get control word */
- orl $CR0_PE|CR0_PG,%eax /* enable paging */
- movl %eax,%cr0 /* and let's page NOW! */
+ /* Don't trust what the loader gives for rflags. */
+ pushq $PSL_KERNEL
+ popfq
- pushl $begin /* jump to high virtualized address */
- ret
+ /* Find the metadata pointers before we lose them */
+ movq %rsp, %rbp
+ xorq %rax, %rax
+ movl 4(%rbp),%eax /* modulep */
+ movq %rax,modulep
+ movl 8(%rbp),%eax /* kernend */
+ movq %rax,physfree
-/* now running relocated at KERNBASE where the system is linked to run */
-begin:
- /* set up bootstrap stack */
- movl proc0kstack,%eax /* location of in-kernel stack */
- /* bootstrap stack end location */
- leal (KSTACK_PAGES*PAGE_SIZE-PCB_SIZE)(%eax),%esp
-
- xorl %ebp,%ebp /* mark end of frames */
-
-#ifdef PAE
- movl IdlePDPT,%esi
-#else
- movl IdlePTD,%esi
-#endif
- movl %esi,(KSTACK_PAGES*PAGE_SIZE-PCB_SIZE+PCB_CR3)(%eax)
-
- pushl physfree /* value of first for init386(first) */
- call init386 /* wire 386 chip for unix operation */
-
- /*
- * Clean up the stack in a way that db_numargs() understands, so
- * that backtraces in ddb don't underrun the stack. Traps for
- * inaccessible memory are more fatal than usual this early.
- */
- addl $4,%esp
+ /* Get onto a stack that we can trust - there is no going back now. */
+ movq $bootstack,%rsp
+ xorq %rbp, %rbp
+ call hammer_time /* set up cpu for unix operation */
call mi_startup /* autoconfiguration, mountroot etc */
- /* NOTREACHED */
- addl $0,%esp /* for db_numargs() again */
-
-/*
- * Signal trampoline, copied to top of user stack
- */
-NON_GPROF_ENTRY(sigcode)
- calll *SIGF_HANDLER(%esp)
- leal SIGF_UC(%esp),%eax /* get ucontext */
- pushl %eax
- testl $PSL_VM,UC_EFLAGS(%eax)
- jne 1f
- movl UC_GS(%eax),%gs /* restore %gs */
-1:
- movl $SYS_sigreturn,%eax
- pushl %eax /* junk to fake return addr. */
- int $0x80 /* enter kernel with args */
- /* on stack */
-1:
- jmp 1b
-
-#ifdef COMPAT_FREEBSD4
- ALIGN_TEXT
-freebsd4_sigcode:
- calll *SIGF_HANDLER(%esp)
- leal SIGF_UC4(%esp),%eax /* get ucontext */
- pushl %eax
- testl $PSL_VM,UC4_EFLAGS(%eax)
- jne 1f
- movl UC4_GS(%eax),%gs /* restore %gs */
-1:
- movl $344,%eax /* 4.x SYS_sigreturn */
- pushl %eax /* junk to fake return addr. */
- int $0x80 /* enter kernel with args */
- /* on stack */
-1:
- jmp 1b
-#endif
-
-#ifdef COMPAT_43
- ALIGN_TEXT
-osigcode:
- call *SIGF_HANDLER(%esp) /* call signal handler */
- lea SIGF_SC(%esp),%eax /* get sigcontext */
- pushl %eax
- testl $PSL_VM,SC_PS(%eax)
- jne 9f
- movl SC_GS(%eax),%gs /* restore %gs */
-9:
- movl $103,%eax /* 3.x SYS_sigreturn */
- pushl %eax /* junk to fake return addr. */
- int $0x80 /* enter kernel with args */
-0: jmp 0b
-#endif /* COMPAT_43 */
+0: hlt
+ jmp 0b
- ALIGN_TEXT
-esigcode:
-
- .data
- .globl szsigcode
-szsigcode:
- .long esigcode-sigcode
-#ifdef COMPAT_FREEBSD4
- .globl szfreebsd4_sigcode
-szfreebsd4_sigcode:
- .long esigcode-freebsd4_sigcode
-#endif
-#ifdef COMPAT_43
- .globl szosigcode
-szosigcode:
- .long esigcode-osigcode
-#endif
- .text
-
-/**********************************************************************
- *
- * Recover the bootinfo passed to us from the boot program
- *
- */
-recover_bootinfo:
- /*
- * This code is called in different ways depending on what loaded
- * and started the kernel. This is used to detect how we get the
- * arguments from the other code and what we do with them.
- *
- * Old disk boot blocks:
- * (*btext)(howto, bootdev, cyloffset, esym);
- * [return address == 0, and can NOT be returned to]
- * [cyloffset was not supported by the FreeBSD boot code
- * and always passed in as 0]
- * [esym is also known as total in the boot code, and
- * was never properly supported by the FreeBSD boot code]
- *
- * Old diskless netboot code:
- * (*btext)(0,0,0,0,&nfsdiskless,0,0,0);
- * [return address != 0, and can NOT be returned to]
- * If we are being booted by this code it will NOT work,
- * so we are just going to halt if we find this case.
- *
- * New uniform boot code:
- * (*btext)(howto, bootdev, 0, 0, 0, &bootinfo)
- * [return address != 0, and can be returned to]
- *
- * There may seem to be a lot of wasted arguments in here, but
- * that is so the newer boot code can still load very old kernels
- * and old boot code can load new kernels.
- */
-
- /*
- * The old style disk boot blocks fake a frame on the stack and
- * did an lret to get here. The frame on the stack has a return
- * address of 0.
- */
- cmpl $0,4(%ebp)
- je olddiskboot
-
- /*
- * We have some form of return address, so this is either the
- * old diskless netboot code, or the new uniform code. That can
- * be detected by looking at the 5th argument, if it is 0
- * we are being booted by the new uniform boot code.
- */
- cmpl $0,24(%ebp)
- je newboot
-
- /*
- * Seems we have been loaded by the old diskless boot code, we
- * don't stand a chance of running as the diskless structure
- * changed considerably between the two, so just halt.
- */
- hlt
-
- /*
- * We have been loaded by the new uniform boot code.
- * Let's check the bootinfo version, and if we do not understand
- * it we return to the loader with a status of 1 to indicate this error
- */
-newboot:
- movl 28(%ebp),%ebx /* &bootinfo.version */
- movl BI_VERSION(%ebx),%eax
- cmpl $1,%eax /* We only understand version 1 */
- je 1f
- movl $1,%eax /* Return status */
- leave
- /*
- * XXX this returns to our caller's caller (as is required) since
- * we didn't set up a frame and our caller did.
- */
- ret
-
-1:
- /*
- * If we have a kernelname copy it in
- */
- movl BI_KERNELNAME(%ebx),%esi
- cmpl $0,%esi
- je 2f /* No kernelname */
- movl $MAXPATHLEN,%ecx /* Brute force!!! */
- movl $R(kernelname),%edi
- cmpb $'/',(%esi) /* Make sure it starts with a slash */
- je 1f
- movb $'/',(%edi)
- incl %edi
- decl %ecx
-1:
- cld
- rep
- movsb
-
-2:
- /*
- * Determine the size of the boot loader's copy of the bootinfo
- * struct. This is impossible to do properly because old versions
- * of the struct don't contain a size field and there are 2 old
- * versions with the same version number.
- */
- movl $BI_ENDCOMMON,%ecx /* prepare for sizeless version */
- testl $RB_BOOTINFO,8(%ebp) /* bi_size (and bootinfo) valid? */
- je got_bi_size /* no, sizeless version */
- movl BI_SIZE(%ebx),%ecx
-got_bi_size:
-
- /*
- * Copy the common part of the bootinfo struct
- */
- movl %ebx,%esi
- movl $R(bootinfo),%edi
- cmpl $BOOTINFO_SIZE,%ecx
- jbe got_common_bi_size
- movl $BOOTINFO_SIZE,%ecx
-got_common_bi_size:
- cld
- rep
- movsb
-
-#ifdef NFS_ROOT
-#ifndef BOOTP_NFSV3
- /*
- * If we have a nfs_diskless structure copy it in
- */
- movl BI_NFS_DISKLESS(%ebx),%esi
- cmpl $0,%esi
- je olddiskboot
- movl $R(nfs_diskless),%edi
- movl $NFSDISKLESS_SIZE,%ecx
- cld
- rep
- movsb
- movl $R(nfs_diskless_valid),%edi
- movl $1,(%edi)
-#endif
-#endif
-
- /*
- * The old style disk boot.
- * (*btext)(howto, bootdev, cyloffset, esym);
- * Note that the newer boot code just falls into here to pick
- * up howto and bootdev, cyloffset and esym are no longer used
- */
-olddiskboot:
- movl 8(%ebp),%eax
- movl %eax,R(boothowto)
- movl 12(%ebp),%eax
- movl %eax,R(bootdev)
-
- ret
-
-
-/**********************************************************************
- *
- * Identify the CPU and initialize anything special about it
- *
- */
-identify_cpu:
-
- /* Try to toggle alignment check flag; does not exist on 386. */
- pushfl
- popl %eax
- movl %eax,%ecx
- orl $PSL_AC,%eax
- pushl %eax
- popfl
- pushfl
- popl %eax
- xorl %ecx,%eax
- andl $PSL_AC,%eax
- pushl %ecx
- popfl
-
- testl %eax,%eax
- jnz try486
-
- /* NexGen CPU does not have aligment check flag. */
- pushfl
- movl $0x5555, %eax
- xorl %edx, %edx
- movl $2, %ecx
- clc
- divl %ecx
- jz trynexgen
- popfl
- movl $CPU_386,R(cpu)
- jmp 3f
-
-trynexgen:
- popfl
- movl $CPU_NX586,R(cpu)
- movl $0x4778654e,R(cpu_vendor) # store vendor string
- movl $0x72446e65,R(cpu_vendor+4)
- movl $0x6e657669,R(cpu_vendor+8)
- movl $0,R(cpu_vendor+12)
- jmp 3f
-
-try486: /* Try to toggle identification flag; does not exist on early 486s. */
- pushfl
- popl %eax
- movl %eax,%ecx
- xorl $PSL_ID,%eax
- pushl %eax
- popfl
- pushfl
- popl %eax
- xorl %ecx,%eax
- andl $PSL_ID,%eax
- pushl %ecx
- popfl
-
- testl %eax,%eax
- jnz trycpuid
- movl $CPU_486,R(cpu)
-
- /*
- * Check Cyrix CPU
- * Cyrix CPUs do not change the undefined flags following
- * execution of the divide instruction which divides 5 by 2.
- *
- * Note: CPUID is enabled on M2, so it passes another way.
- */
- pushfl
- movl $0x5555, %eax
- xorl %edx, %edx
- movl $2, %ecx
- clc
- divl %ecx
- jnc trycyrix
- popfl
- jmp 3f /* You may use Intel CPU. */
-
-trycyrix:
- popfl
- /*
- * IBM Bluelighting CPU also doesn't change the undefined flags.
- * Because IBM doesn't disclose the information for Bluelighting
- * CPU, we couldn't distinguish it from Cyrix's (including IBM
- * brand of Cyrix CPUs).
- */
- movl $0x69727943,R(cpu_vendor) # store vendor string
- movl $0x736e4978,R(cpu_vendor+4)
- movl $0x64616574,R(cpu_vendor+8)
- jmp 3f
-
-trycpuid: /* Use the `cpuid' instruction. */
- xorl %eax,%eax
- cpuid # cpuid 0
- movl %eax,R(cpu_high) # highest capability
- movl %ebx,R(cpu_vendor) # store vendor string
- movl %edx,R(cpu_vendor+4)
- movl %ecx,R(cpu_vendor+8)
- movb $0,R(cpu_vendor+12)
-
- movl $1,%eax
- cpuid # cpuid 1
- movl %eax,R(cpu_id) # store cpu_id
- movl %ebx,R(cpu_procinfo) # store cpu_procinfo
- movl %edx,R(cpu_feature) # store cpu_feature
- rorl $8,%eax # extract family type
- andl $15,%eax
- cmpl $5,%eax
- jae 1f
-
- /* less than Pentium; must be 486 */
- movl $CPU_486,R(cpu)
- jmp 3f
-1:
- /* a Pentium? */
- cmpl $5,%eax
- jne 2f
- movl $CPU_586,R(cpu)
- jmp 3f
-2:
- /* Greater than Pentium...call it a Pentium Pro */
- movl $CPU_686,R(cpu)
-3:
- ret
-
-
-/**********************************************************************
- *
- * Create the first page directory and its page tables.
- *
- */
-
-create_pagetables:
-
-/* Find end of kernel image (rounded up to a page boundary). */
- movl $R(_end),%esi
-
-/* Include symbols, if any. */
- movl R(bootinfo+BI_ESYMTAB),%edi
- testl %edi,%edi
- je over_symalloc
- movl %edi,%esi
- movl $KERNBASE,%edi
- addl %edi,R(bootinfo+BI_SYMTAB)
- addl %edi,R(bootinfo+BI_ESYMTAB)
-over_symalloc:
-
-/* If we are told where the end of the kernel space is, believe it. */
- movl R(bootinfo+BI_KERNEND),%edi
- testl %edi,%edi
- je no_kernend
- movl %edi,%esi
-no_kernend:
-
- addl $PAGE_MASK,%esi
- andl $~PAGE_MASK,%esi
- movl %esi,R(KERNend) /* save end of kernel */
- movl %esi,R(physfree) /* next free page is at end of kernel */
-
-/* Allocate Kernel Page Tables */
- ALLOCPAGES(NKPT)
- movl %esi,R(KPTphys)
-
-/* Allocate Page Table Directory */
-#ifdef PAE
- /* XXX only need 32 bytes (easier for now) */
- ALLOCPAGES(1)
- movl %esi,R(IdlePDPT)
-#endif
- ALLOCPAGES(NPGPTD)
- movl %esi,R(IdlePTD)
-
-/* Allocate UPAGES */
- ALLOCPAGES(UAREA_PAGES)
- movl %esi,R(p0upa)
- addl $KERNBASE, %esi
- movl %esi, R(proc0uarea)
-
- ALLOCPAGES(KSTACK_PAGES)
- movl %esi,R(p0kpa)
- addl $KERNBASE, %esi
- movl %esi, R(proc0kstack)
-
- ALLOCPAGES(1) /* vm86/bios stack */
- movl %esi,R(vm86phystk)
-
- ALLOCPAGES(3) /* pgtable + ext + IOPAGES */
- movl %esi,R(vm86pa)
- addl $KERNBASE, %esi
- movl %esi, R(vm86paddr)
-
-#ifdef SMP
-/* Allocate cpu0's private data page */
- ALLOCPAGES(1)
- movl %esi,R(cpu0pp)
- addl $KERNBASE, %esi
- movl %esi, R(cpu0prvpage) /* relocated to KVM space */
-
-/* Allocate SMP page table page */
- ALLOCPAGES(1)
- movl %esi,R(SMPptpa)
- addl $KERNBASE, %esi
- movl %esi, R(SMPpt) /* relocated to KVM space */
-#endif /* SMP */
-
-/* Map read-only from zero to the end of the kernel text section */
- xorl %eax, %eax
- xorl %edx,%edx
- movl $R(etext),%ecx
- addl $PAGE_MASK,%ecx
- shrl $PAGE_SHIFT,%ecx
- fillkptphys(%edx)
-
-/* Map read-write, data, bss and symbols */
- movl $R(etext),%eax
- addl $PAGE_MASK, %eax
- andl $~PAGE_MASK, %eax
- movl $PG_RW,%edx
- movl R(KERNend),%ecx
- subl %eax,%ecx
- shrl $PAGE_SHIFT,%ecx
- fillkptphys(%edx)
-
-/* Map page directory. */
-#ifdef PAE
- movl R(IdlePDPT), %eax
- movl $1, %ecx
- fillkptphys($PG_RW)
-#endif
-
- movl R(IdlePTD), %eax
- movl $NPGPTD, %ecx
- fillkptphys($PG_RW)
-
-/* Map proc0's UPAGES in the physical way ... */
- movl R(p0upa), %eax
- movl $(UAREA_PAGES), %ecx
- fillkptphys($PG_RW)
-
-/* Map proc0's KSTACK in the physical way ... */
- movl R(p0kpa), %eax
- movl $(KSTACK_PAGES), %ecx
- fillkptphys($PG_RW)
-
-/* Map ISA hole */
- movl $ISA_HOLE_START, %eax
- movl $ISA_HOLE_LENGTH>>PAGE_SHIFT, %ecx
- fillkptphys($PG_RW)
-
-/* Map space for the vm86 region */
- movl R(vm86phystk), %eax
- movl $4, %ecx
- fillkptphys($PG_RW)
-
-/* Map page 0 into the vm86 page table */
- movl $0, %eax
- movl $0, %ebx
- movl $1, %ecx
- fillkpt(R(vm86pa), $PG_RW|PG_U)
-
-/* ...likewise for the ISA hole */
- movl $ISA_HOLE_START, %eax
- movl $ISA_HOLE_START>>PAGE_SHIFT, %ebx
- movl $ISA_HOLE_LENGTH>>PAGE_SHIFT, %ecx
- fillkpt(R(vm86pa), $PG_RW|PG_U)
-
-#ifdef SMP
-/* Map cpu0's private page into global kmem (4K @ cpu0prvpage) */
- movl R(cpu0pp), %eax
- movl $1, %ecx
- fillkptphys($PG_RW)
-
-/* Map SMP page table page into global kmem FWIW */
- movl R(SMPptpa), %eax
- movl $1, %ecx
- fillkptphys($PG_RW)
-
-/* Map the private page into the SMP page table */
- movl R(cpu0pp), %eax
- movl $0, %ebx /* pte offset = 0 */
- movl $1, %ecx /* one private page coming right up */
- fillkpt(R(SMPptpa), $PG_RW)
-
-/* ... and put the page table table in the pde. */
- movl R(SMPptpa), %eax
- movl $MPPTDI, %ebx
- movl $1, %ecx
- fillkpt(R(IdlePTD), $PG_RW)
-
-/* Fakeup VA for the local apic to allow early traps. */
- ALLOCPAGES(1)
- movl %esi, %eax
- movl $(NPTEPG-1), %ebx /* pte offset = NTEPG-1 */
- movl $1, %ecx /* one private pt coming right up */
- fillkpt(R(SMPptpa), $PG_RW)
-#endif /* SMP */
-
-/* install a pde for temporary double map of bottom of VA */
- movl R(KPTphys), %eax
- xorl %ebx, %ebx
- movl $NKPT, %ecx
- fillkpt(R(IdlePTD), $PG_RW)
-
-/* install pde's for pt's */
- movl R(KPTphys), %eax
- movl $KPTDI, %ebx
- movl $NKPT, %ecx
- fillkpt(R(IdlePTD), $PG_RW)
-
-/* install a pde recursively mapping page directory as a page table */
- movl R(IdlePTD), %eax
- movl $PTDPTDI, %ebx
- movl $NPGPTD,%ecx
- fillkpt(R(IdlePTD), $PG_RW)
-
-#ifdef PAE
- movl R(IdlePTD), %eax
- xorl %ebx, %ebx
- movl $NPGPTD, %ecx
- fillkpt(R(IdlePDPT), $0x0)
-#endif
-
- ret
+ .bss
+ ALIGN_DATA /* just to be sure */
+ .space 0x1000 /* space for bootstack - temporary stack */
+bootstack:
diff --git a/sys/amd64/amd64/locore.s b/sys/amd64/amd64/locore.s
index 8115e2399749..65b01ac9845b 100644
--- a/sys/amd64/amd64/locore.s
+++ b/sys/amd64/amd64/locore.s
@@ -1,10 +1,7 @@
/*-
- * Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 2003 Peter Wemm <peter@FreeBSD.org>
* All rights reserved.
*
- * This code is derived from software contributed to Berkeley by
- * William Jolitz.
- *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -13,18 +10,11 @@
* 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 the University of
- * California, Berkeley and its contributors.
- * 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
+ * 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 REGENTS OR CONTRIBUTORS BE LIABLE
+ * 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)
@@ -33,25 +23,10 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * from: @(#)locore.s 7.3 (Berkeley) 5/13/91
* $FreeBSD$
- *
- * originally from: locore.s, by William F. Jolitz
- *
- * Substantially rewritten by David Greenman, Rod Grimes,
- * Bruce Evans, Wolfgang Solfrank, Poul-Henning Kamp
- * and many others.
*/
-#include "opt_bootp.h"
-#include "opt_compat.h"
-#include "opt_nfsroot.h"
-
-#include <sys/syscall.h>
-#include <sys/reboot.h>
-
#include <machine/asmacros.h>
-#include <machine/cputypes.h>
#include <machine/psl.h>
#include <machine/pmap.h>
#include <machine/specialreg.h>
@@ -59,14 +34,6 @@
#include "assym.s"
/*
- * XXX
- *
- * Note: This version greatly munged to avoid various assembler errors
- * that may be fixed in newer versions of gas. Perhaps newer versions
- * will have more pleasant appearance.
- */
-
-/*
* PTmap is recursive pagemap at top of virtual address space.
* Within PTmap, the page directory can be found (third indirection).
*/
@@ -75,837 +42,51 @@
.set PTD,PTmap + (PTDPTDI * PAGE_SIZE)
.set PTDpde,PTD + (PTDPTDI * PDESIZE)
-#ifdef SMP
-/*
- * Define layout of per-cpu address space.
- * This is "constructed" in locore.s on the BSP and in mp_machdep.c
- * for each AP. DO NOT REORDER THESE WITHOUT UPDATING THE REST!
- */
- .globl SMP_prvspace, lapic
- .set SMP_prvspace,(MPPTDI << PDRSHIFT)
- .set lapic,SMP_prvspace + (NPTEPG-1) * PAGE_SIZE
-#endif /* SMP */
-
/*
* Compiled KERNBASE location
*/
.globl kernbase
.set kernbase,KERNBASE
-/*
- * Globals
- */
- .data
- ALIGN_DATA /* just to be sure */
-
- .globl HIDENAME(tmpstk)
- .space 0x2000 /* space for tmpstk - temporary stack */
-HIDENAME(tmpstk):
-
- .globl bootinfo
-bootinfo: .space BOOTINFO_SIZE /* bootinfo that we can handle */
-
- .globl KERNend
-KERNend: .long 0 /* phys addr end of kernel (just after bss) */
-physfree: .long 0 /* phys addr of next free page */
-
-#ifdef SMP
- .globl cpu0prvpage
-cpu0pp: .long 0 /* phys addr cpu0 private pg */
-cpu0prvpage: .long 0 /* relocated version */
-
- .globl SMPpt
-SMPptpa: .long 0 /* phys addr SMP page table */
-SMPpt: .long 0 /* relocated version */
-#endif /* SMP */
-
- .globl IdlePTD
-IdlePTD: .long 0 /* phys addr of kernel PTD */
-
-#ifdef PAE
- .globl IdlePDPT
-IdlePDPT: .long 0 /* phys addr of kernel PDPT */
-#endif
-
-#ifdef SMP
- .globl KPTphys
-#endif
-KPTphys: .long 0 /* phys addr of kernel page tables */
-
- .globl proc0uarea, proc0kstack
-proc0uarea: .long 0 /* address of proc 0 uarea space */
-proc0kstack: .long 0 /* address of proc 0 kstack space */
-p0upa: .long 0 /* phys addr of proc0's UAREA */
-p0kpa: .long 0 /* phys addr of proc0's STACK */
-
-vm86phystk: .long 0 /* PA of vm86/bios stack */
-
- .globl vm86paddr, vm86pa
-vm86paddr: .long 0 /* address of vm86 region */
-vm86pa: .long 0 /* phys addr of vm86 region */
-
-#ifdef PC98
- .globl pc98_system_parameter
-pc98_system_parameter:
- .space 0x240
-#endif
-
-/**********************************************************************
- *
- * Some handy macros
- *
- */
-
-#define R(foo) ((foo)-KERNBASE)
-
-#define ALLOCPAGES(foo) \
- movl R(physfree), %esi ; \
- movl $((foo)*PAGE_SIZE), %eax ; \
- addl %esi, %eax ; \
- movl %eax, R(physfree) ; \
- movl %esi, %edi ; \
- movl $((foo)*PAGE_SIZE),%ecx ; \
- xorl %eax,%eax ; \
- cld ; \
- rep ; \
- stosb
-
-/*
- * fillkpt
- * eax = page frame address
- * ebx = index into page table
- * ecx = how many pages to map
- * base = base address of page dir/table
- * prot = protection bits
- */
-#define fillkpt(base, prot) \
- shll $PTESHIFT,%ebx ; \
- addl base,%ebx ; \
- orl $PG_V,%eax ; \
- orl prot,%eax ; \
-1: movl %eax,(%ebx) ; \
- addl $PAGE_SIZE,%eax ; /* increment physical address */ \
- addl $PTESIZE,%ebx ; /* next pte */ \
- loop 1b
-
-/*
- * fillkptphys(prot)
- * eax = physical address
- * ecx = how many pages to map
- * prot = protection bits
- */
-#define fillkptphys(prot) \
- movl %eax, %ebx ; \
- shrl $PAGE_SHIFT, %ebx ; \
- fillkpt(R(KPTphys), prot)
-
.text
/**********************************************************************
*
- * This is where the bootblocks start us, set the ball rolling...
+ * This is where the loader trampoline start us, set the ball rolling...
+ *
+ * We are called with the stack looking like this:
+ * 0(%rsp) = 32 bit return address (cannot be used)
+ * 4(%rsp) = 32 bit modulep
+ * 8(%rsp) = 32 bit kernend
*
+ * We are already in long mode, on a 64 bit %cs and running at KERNBASE.
*/
NON_GPROF_ENTRY(btext)
-#ifdef PC98
- /* save SYSTEM PARAMETER for resume (NS/T or other) */
- movl $0xa1400,%esi
- movl $R(pc98_system_parameter),%edi
- movl $0x0240,%ecx
- cld
- rep
- movsb
-#else /* IBM-PC */
-/* Tell the bios to warmboot next time */
+ /* Tell the bios to warmboot next time */
movw $0x1234,0x472
-#endif /* PC98 */
-
-/* Set up a real frame in case the double return in newboot is executed. */
- pushl %ebp
- movl %esp, %ebp
-
-/* Don't trust what the BIOS gives for eflags. */
- pushl $PSL_KERNEL
- popfl
-
-/*
- * Don't trust what the BIOS gives for %fs and %gs. Trust the bootstrap
- * to set %cs, %ds, %es and %ss.
- */
- mov %ds, %ax
- mov %ax, %fs
- mov %ax, %gs
-
- call recover_bootinfo
-
-/* Get onto a stack that we can trust. */
-/*
- * XXX this step is delayed in case recover_bootinfo needs to return via
- * the old stack, but it need not be, since recover_bootinfo actually
- * returns via the old frame.
- */
- movl $R(HIDENAME(tmpstk)),%esp
-
-#ifdef PC98
- /* pc98_machine_type & M_EPSON_PC98 */
- testb $0x02,R(pc98_system_parameter)+220
- jz 3f
- /* epson_machine_id <= 0x0b */
- cmpb $0x0b,R(pc98_system_parameter)+224
- ja 3f
-
- /* count up memory */
- movl $0x100000,%eax /* next, talley remaining memory */
- movl $0xFFF-0x100,%ecx
-1: movl 0(%eax),%ebx /* save location to check */
- movl $0xa55a5aa5,0(%eax) /* write test pattern */
- cmpl $0xa55a5aa5,0(%eax) /* does not check yet for rollover */
- jne 2f
- movl %ebx,0(%eax) /* restore memory */
- addl $PAGE_SIZE,%eax
- loop 1b
-2: subl $0x100000,%eax
- shrl $17,%eax
- movb %al,R(pc98_system_parameter)+1
-3:
-
- movw R(pc98_system_parameter+0x86),%ax
- movw %ax,R(cpu_id)
-#endif
-
- call identify_cpu
-/* clear bss */
-/*
- * XXX this should be done a little earlier.
- *
- * XXX we don't check that there is memory for our bss and page tables
- * before using it.
- *
- * XXX the boot program somewhat bogusly clears the bss. We still have
- * to do it in case we were unzipped by kzipboot. Then the boot program
- * only clears kzipboot's bss.
- *
- * XXX the gdt and idt are still somewhere in the boot program. We
- * depend on the convention that the boot program is below 1MB and we
- * are above 1MB to keep the gdt and idt away from the bss and page
- * tables.
- */
- movl $R(end),%ecx
- movl $R(edata),%edi
- subl %edi,%ecx
- xorl %eax,%eax
- cld
- rep
- stosb
-
- call create_pagetables
-
-/*
- * If the CPU has support for VME, turn it on.
- */
- testl $CPUID_VME, R(cpu_feature)
- jz 1f
- movl %cr4, %eax
- orl $CR4_VME, %eax
- movl %eax, %cr4
-1:
-
-/* Now enable paging */
-#ifdef PAE
- movl R(IdlePDPT), %eax
- movl %eax, %cr3
- movl %cr4, %eax
- orl $CR4_PAE, %eax
- movl %eax, %cr4
-#else
- movl R(IdlePTD), %eax
- movl %eax,%cr3 /* load ptd addr into mmu */
-#endif
- movl %cr0,%eax /* get control word */
- orl $CR0_PE|CR0_PG,%eax /* enable paging */
- movl %eax,%cr0 /* and let's page NOW! */
+ /* Don't trust what the loader gives for rflags. */
+ pushq $PSL_KERNEL
+ popfq
- pushl $begin /* jump to high virtualized address */
- ret
+ /* Find the metadata pointers before we lose them */
+ movq %rsp, %rbp
+ xorq %rax, %rax
+ movl 4(%rbp),%eax /* modulep */
+ movq %rax,modulep
+ movl 8(%rbp),%eax /* kernend */
+ movq %rax,physfree
-/* now running relocated at KERNBASE where the system is linked to run */
-begin:
- /* set up bootstrap stack */
- movl proc0kstack,%eax /* location of in-kernel stack */
- /* bootstrap stack end location */
- leal (KSTACK_PAGES*PAGE_SIZE-PCB_SIZE)(%eax),%esp
-
- xorl %ebp,%ebp /* mark end of frames */
-
-#ifdef PAE
- movl IdlePDPT,%esi
-#else
- movl IdlePTD,%esi
-#endif
- movl %esi,(KSTACK_PAGES*PAGE_SIZE-PCB_SIZE+PCB_CR3)(%eax)
-
- pushl physfree /* value of first for init386(first) */
- call init386 /* wire 386 chip for unix operation */
-
- /*
- * Clean up the stack in a way that db_numargs() understands, so
- * that backtraces in ddb don't underrun the stack. Traps for
- * inaccessible memory are more fatal than usual this early.
- */
- addl $4,%esp
+ /* Get onto a stack that we can trust - there is no going back now. */
+ movq $bootstack,%rsp
+ xorq %rbp, %rbp
+ call hammer_time /* set up cpu for unix operation */
call mi_startup /* autoconfiguration, mountroot etc */
- /* NOTREACHED */
- addl $0,%esp /* for db_numargs() again */
-
-/*
- * Signal trampoline, copied to top of user stack
- */
-NON_GPROF_ENTRY(sigcode)
- calll *SIGF_HANDLER(%esp)
- leal SIGF_UC(%esp),%eax /* get ucontext */
- pushl %eax
- testl $PSL_VM,UC_EFLAGS(%eax)
- jne 1f
- movl UC_GS(%eax),%gs /* restore %gs */
-1:
- movl $SYS_sigreturn,%eax
- pushl %eax /* junk to fake return addr. */
- int $0x80 /* enter kernel with args */
- /* on stack */
-1:
- jmp 1b
-
-#ifdef COMPAT_FREEBSD4
- ALIGN_TEXT
-freebsd4_sigcode:
- calll *SIGF_HANDLER(%esp)
- leal SIGF_UC4(%esp),%eax /* get ucontext */
- pushl %eax
- testl $PSL_VM,UC4_EFLAGS(%eax)
- jne 1f
- movl UC4_GS(%eax),%gs /* restore %gs */
-1:
- movl $344,%eax /* 4.x SYS_sigreturn */
- pushl %eax /* junk to fake return addr. */
- int $0x80 /* enter kernel with args */
- /* on stack */
-1:
- jmp 1b
-#endif
-
-#ifdef COMPAT_43
- ALIGN_TEXT
-osigcode:
- call *SIGF_HANDLER(%esp) /* call signal handler */
- lea SIGF_SC(%esp),%eax /* get sigcontext */
- pushl %eax
- testl $PSL_VM,SC_PS(%eax)
- jne 9f
- movl SC_GS(%eax),%gs /* restore %gs */
-9:
- movl $103,%eax /* 3.x SYS_sigreturn */
- pushl %eax /* junk to fake return addr. */
- int $0x80 /* enter kernel with args */
-0: jmp 0b
-#endif /* COMPAT_43 */
+0: hlt
+ jmp 0b
- ALIGN_TEXT
-esigcode:
-
- .data
- .globl szsigcode
-szsigcode:
- .long esigcode-sigcode
-#ifdef COMPAT_FREEBSD4
- .globl szfreebsd4_sigcode
-szfreebsd4_sigcode:
- .long esigcode-freebsd4_sigcode
-#endif
-#ifdef COMPAT_43
- .globl szosigcode
-szosigcode:
- .long esigcode-osigcode
-#endif
- .text
-
-/**********************************************************************
- *
- * Recover the bootinfo passed to us from the boot program
- *
- */
-recover_bootinfo:
- /*
- * This code is called in different ways depending on what loaded
- * and started the kernel. This is used to detect how we get the
- * arguments from the other code and what we do with them.
- *
- * Old disk boot blocks:
- * (*btext)(howto, bootdev, cyloffset, esym);
- * [return address == 0, and can NOT be returned to]
- * [cyloffset was not supported by the FreeBSD boot code
- * and always passed in as 0]
- * [esym is also known as total in the boot code, and
- * was never properly supported by the FreeBSD boot code]
- *
- * Old diskless netboot code:
- * (*btext)(0,0,0,0,&nfsdiskless,0,0,0);
- * [return address != 0, and can NOT be returned to]
- * If we are being booted by this code it will NOT work,
- * so we are just going to halt if we find this case.
- *
- * New uniform boot code:
- * (*btext)(howto, bootdev, 0, 0, 0, &bootinfo)
- * [return address != 0, and can be returned to]
- *
- * There may seem to be a lot of wasted arguments in here, but
- * that is so the newer boot code can still load very old kernels
- * and old boot code can load new kernels.
- */
-
- /*
- * The old style disk boot blocks fake a frame on the stack and
- * did an lret to get here. The frame on the stack has a return
- * address of 0.
- */
- cmpl $0,4(%ebp)
- je olddiskboot
-
- /*
- * We have some form of return address, so this is either the
- * old diskless netboot code, or the new uniform code. That can
- * be detected by looking at the 5th argument, if it is 0
- * we are being booted by the new uniform boot code.
- */
- cmpl $0,24(%ebp)
- je newboot
-
- /*
- * Seems we have been loaded by the old diskless boot code, we
- * don't stand a chance of running as the diskless structure
- * changed considerably between the two, so just halt.
- */
- hlt
-
- /*
- * We have been loaded by the new uniform boot code.
- * Let's check the bootinfo version, and if we do not understand
- * it we return to the loader with a status of 1 to indicate this error
- */
-newboot:
- movl 28(%ebp),%ebx /* &bootinfo.version */
- movl BI_VERSION(%ebx),%eax
- cmpl $1,%eax /* We only understand version 1 */
- je 1f
- movl $1,%eax /* Return status */
- leave
- /*
- * XXX this returns to our caller's caller (as is required) since
- * we didn't set up a frame and our caller did.
- */
- ret
-
-1:
- /*
- * If we have a kernelname copy it in
- */
- movl BI_KERNELNAME(%ebx),%esi
- cmpl $0,%esi
- je 2f /* No kernelname */
- movl $MAXPATHLEN,%ecx /* Brute force!!! */
- movl $R(kernelname),%edi
- cmpb $'/',(%esi) /* Make sure it starts with a slash */
- je 1f
- movb $'/',(%edi)
- incl %edi
- decl %ecx
-1:
- cld
- rep
- movsb
-
-2:
- /*
- * Determine the size of the boot loader's copy of the bootinfo
- * struct. This is impossible to do properly because old versions
- * of the struct don't contain a size field and there are 2 old
- * versions with the same version number.
- */
- movl $BI_ENDCOMMON,%ecx /* prepare for sizeless version */
- testl $RB_BOOTINFO,8(%ebp) /* bi_size (and bootinfo) valid? */
- je got_bi_size /* no, sizeless version */
- movl BI_SIZE(%ebx),%ecx
-got_bi_size:
-
- /*
- * Copy the common part of the bootinfo struct
- */
- movl %ebx,%esi
- movl $R(bootinfo),%edi
- cmpl $BOOTINFO_SIZE,%ecx
- jbe got_common_bi_size
- movl $BOOTINFO_SIZE,%ecx
-got_common_bi_size:
- cld
- rep
- movsb
-
-#ifdef NFS_ROOT
-#ifndef BOOTP_NFSV3
- /*
- * If we have a nfs_diskless structure copy it in
- */
- movl BI_NFS_DISKLESS(%ebx),%esi
- cmpl $0,%esi
- je olddiskboot
- movl $R(nfs_diskless),%edi
- movl $NFSDISKLESS_SIZE,%ecx
- cld
- rep
- movsb
- movl $R(nfs_diskless_valid),%edi
- movl $1,(%edi)
-#endif
-#endif
-
- /*
- * The old style disk boot.
- * (*btext)(howto, bootdev, cyloffset, esym);
- * Note that the newer boot code just falls into here to pick
- * up howto and bootdev, cyloffset and esym are no longer used
- */
-olddiskboot:
- movl 8(%ebp),%eax
- movl %eax,R(boothowto)
- movl 12(%ebp),%eax
- movl %eax,R(bootdev)
-
- ret
-
-
-/**********************************************************************
- *
- * Identify the CPU and initialize anything special about it
- *
- */
-identify_cpu:
-
- /* Try to toggle alignment check flag; does not exist on 386. */
- pushfl
- popl %eax
- movl %eax,%ecx
- orl $PSL_AC,%eax
- pushl %eax
- popfl
- pushfl
- popl %eax
- xorl %ecx,%eax
- andl $PSL_AC,%eax
- pushl %ecx
- popfl
-
- testl %eax,%eax
- jnz try486
-
- /* NexGen CPU does not have aligment check flag. */
- pushfl
- movl $0x5555, %eax
- xorl %edx, %edx
- movl $2, %ecx
- clc
- divl %ecx
- jz trynexgen
- popfl
- movl $CPU_386,R(cpu)
- jmp 3f
-
-trynexgen:
- popfl
- movl $CPU_NX586,R(cpu)
- movl $0x4778654e,R(cpu_vendor) # store vendor string
- movl $0x72446e65,R(cpu_vendor+4)
- movl $0x6e657669,R(cpu_vendor+8)
- movl $0,R(cpu_vendor+12)
- jmp 3f
-
-try486: /* Try to toggle identification flag; does not exist on early 486s. */
- pushfl
- popl %eax
- movl %eax,%ecx
- xorl $PSL_ID,%eax
- pushl %eax
- popfl
- pushfl
- popl %eax
- xorl %ecx,%eax
- andl $PSL_ID,%eax
- pushl %ecx
- popfl
-
- testl %eax,%eax
- jnz trycpuid
- movl $CPU_486,R(cpu)
-
- /*
- * Check Cyrix CPU
- * Cyrix CPUs do not change the undefined flags following
- * execution of the divide instruction which divides 5 by 2.
- *
- * Note: CPUID is enabled on M2, so it passes another way.
- */
- pushfl
- movl $0x5555, %eax
- xorl %edx, %edx
- movl $2, %ecx
- clc
- divl %ecx
- jnc trycyrix
- popfl
- jmp 3f /* You may use Intel CPU. */
-
-trycyrix:
- popfl
- /*
- * IBM Bluelighting CPU also doesn't change the undefined flags.
- * Because IBM doesn't disclose the information for Bluelighting
- * CPU, we couldn't distinguish it from Cyrix's (including IBM
- * brand of Cyrix CPUs).
- */
- movl $0x69727943,R(cpu_vendor) # store vendor string
- movl $0x736e4978,R(cpu_vendor+4)
- movl $0x64616574,R(cpu_vendor+8)
- jmp 3f
-
-trycpuid: /* Use the `cpuid' instruction. */
- xorl %eax,%eax
- cpuid # cpuid 0
- movl %eax,R(cpu_high) # highest capability
- movl %ebx,R(cpu_vendor) # store vendor string
- movl %edx,R(cpu_vendor+4)
- movl %ecx,R(cpu_vendor+8)
- movb $0,R(cpu_vendor+12)
-
- movl $1,%eax
- cpuid # cpuid 1
- movl %eax,R(cpu_id) # store cpu_id
- movl %ebx,R(cpu_procinfo) # store cpu_procinfo
- movl %edx,R(cpu_feature) # store cpu_feature
- rorl $8,%eax # extract family type
- andl $15,%eax
- cmpl $5,%eax
- jae 1f
-
- /* less than Pentium; must be 486 */
- movl $CPU_486,R(cpu)
- jmp 3f
-1:
- /* a Pentium? */
- cmpl $5,%eax
- jne 2f
- movl $CPU_586,R(cpu)
- jmp 3f
-2:
- /* Greater than Pentium...call it a Pentium Pro */
- movl $CPU_686,R(cpu)
-3:
- ret
-
-
-/**********************************************************************
- *
- * Create the first page directory and its page tables.
- *
- */
-
-create_pagetables:
-
-/* Find end of kernel image (rounded up to a page boundary). */
- movl $R(_end),%esi
-
-/* Include symbols, if any. */
- movl R(bootinfo+BI_ESYMTAB),%edi
- testl %edi,%edi
- je over_symalloc
- movl %edi,%esi
- movl $KERNBASE,%edi
- addl %edi,R(bootinfo+BI_SYMTAB)
- addl %edi,R(bootinfo+BI_ESYMTAB)
-over_symalloc:
-
-/* If we are told where the end of the kernel space is, believe it. */
- movl R(bootinfo+BI_KERNEND),%edi
- testl %edi,%edi
- je no_kernend
- movl %edi,%esi
-no_kernend:
-
- addl $PAGE_MASK,%esi
- andl $~PAGE_MASK,%esi
- movl %esi,R(KERNend) /* save end of kernel */
- movl %esi,R(physfree) /* next free page is at end of kernel */
-
-/* Allocate Kernel Page Tables */
- ALLOCPAGES(NKPT)
- movl %esi,R(KPTphys)
-
-/* Allocate Page Table Directory */
-#ifdef PAE
- /* XXX only need 32 bytes (easier for now) */
- ALLOCPAGES(1)
- movl %esi,R(IdlePDPT)
-#endif
- ALLOCPAGES(NPGPTD)
- movl %esi,R(IdlePTD)
-
-/* Allocate UPAGES */
- ALLOCPAGES(UAREA_PAGES)
- movl %esi,R(p0upa)
- addl $KERNBASE, %esi
- movl %esi, R(proc0uarea)
-
- ALLOCPAGES(KSTACK_PAGES)
- movl %esi,R(p0kpa)
- addl $KERNBASE, %esi
- movl %esi, R(proc0kstack)
-
- ALLOCPAGES(1) /* vm86/bios stack */
- movl %esi,R(vm86phystk)
-
- ALLOCPAGES(3) /* pgtable + ext + IOPAGES */
- movl %esi,R(vm86pa)
- addl $KERNBASE, %esi
- movl %esi, R(vm86paddr)
-
-#ifdef SMP
-/* Allocate cpu0's private data page */
- ALLOCPAGES(1)
- movl %esi,R(cpu0pp)
- addl $KERNBASE, %esi
- movl %esi, R(cpu0prvpage) /* relocated to KVM space */
-
-/* Allocate SMP page table page */
- ALLOCPAGES(1)
- movl %esi,R(SMPptpa)
- addl $KERNBASE, %esi
- movl %esi, R(SMPpt) /* relocated to KVM space */
-#endif /* SMP */
-
-/* Map read-only from zero to the end of the kernel text section */
- xorl %eax, %eax
- xorl %edx,%edx
- movl $R(etext),%ecx
- addl $PAGE_MASK,%ecx
- shrl $PAGE_SHIFT,%ecx
- fillkptphys(%edx)
-
-/* Map read-write, data, bss and symbols */
- movl $R(etext),%eax
- addl $PAGE_MASK, %eax
- andl $~PAGE_MASK, %eax
- movl $PG_RW,%edx
- movl R(KERNend),%ecx
- subl %eax,%ecx
- shrl $PAGE_SHIFT,%ecx
- fillkptphys(%edx)
-
-/* Map page directory. */
-#ifdef PAE
- movl R(IdlePDPT), %eax
- movl $1, %ecx
- fillkptphys($PG_RW)
-#endif
-
- movl R(IdlePTD), %eax
- movl $NPGPTD, %ecx
- fillkptphys($PG_RW)
-
-/* Map proc0's UPAGES in the physical way ... */
- movl R(p0upa), %eax
- movl $(UAREA_PAGES), %ecx
- fillkptphys($PG_RW)
-
-/* Map proc0's KSTACK in the physical way ... */
- movl R(p0kpa), %eax
- movl $(KSTACK_PAGES), %ecx
- fillkptphys($PG_RW)
-
-/* Map ISA hole */
- movl $ISA_HOLE_START, %eax
- movl $ISA_HOLE_LENGTH>>PAGE_SHIFT, %ecx
- fillkptphys($PG_RW)
-
-/* Map space for the vm86 region */
- movl R(vm86phystk), %eax
- movl $4, %ecx
- fillkptphys($PG_RW)
-
-/* Map page 0 into the vm86 page table */
- movl $0, %eax
- movl $0, %ebx
- movl $1, %ecx
- fillkpt(R(vm86pa), $PG_RW|PG_U)
-
-/* ...likewise for the ISA hole */
- movl $ISA_HOLE_START, %eax
- movl $ISA_HOLE_START>>PAGE_SHIFT, %ebx
- movl $ISA_HOLE_LENGTH>>PAGE_SHIFT, %ecx
- fillkpt(R(vm86pa), $PG_RW|PG_U)
-
-#ifdef SMP
-/* Map cpu0's private page into global kmem (4K @ cpu0prvpage) */
- movl R(cpu0pp), %eax
- movl $1, %ecx
- fillkptphys($PG_RW)
-
-/* Map SMP page table page into global kmem FWIW */
- movl R(SMPptpa), %eax
- movl $1, %ecx
- fillkptphys($PG_RW)
-
-/* Map the private page into the SMP page table */
- movl R(cpu0pp), %eax
- movl $0, %ebx /* pte offset = 0 */
- movl $1, %ecx /* one private page coming right up */
- fillkpt(R(SMPptpa), $PG_RW)
-
-/* ... and put the page table table in the pde. */
- movl R(SMPptpa), %eax
- movl $MPPTDI, %ebx
- movl $1, %ecx
- fillkpt(R(IdlePTD), $PG_RW)
-
-/* Fakeup VA for the local apic to allow early traps. */
- ALLOCPAGES(1)
- movl %esi, %eax
- movl $(NPTEPG-1), %ebx /* pte offset = NTEPG-1 */
- movl $1, %ecx /* one private pt coming right up */
- fillkpt(R(SMPptpa), $PG_RW)
-#endif /* SMP */
-
-/* install a pde for temporary double map of bottom of VA */
- movl R(KPTphys), %eax
- xorl %ebx, %ebx
- movl $NKPT, %ecx
- fillkpt(R(IdlePTD), $PG_RW)
-
-/* install pde's for pt's */
- movl R(KPTphys), %eax
- movl $KPTDI, %ebx
- movl $NKPT, %ecx
- fillkpt(R(IdlePTD), $PG_RW)
-
-/* install a pde recursively mapping page directory as a page table */
- movl R(IdlePTD), %eax
- movl $PTDPTDI, %ebx
- movl $NPGPTD,%ecx
- fillkpt(R(IdlePTD), $PG_RW)
-
-#ifdef PAE
- movl R(IdlePTD), %eax
- xorl %ebx, %ebx
- movl $NPGPTD, %ecx
- fillkpt(R(IdlePDPT), $0x0)
-#endif
-
- ret
+ .bss
+ ALIGN_DATA /* just to be sure */
+ .space 0x1000 /* space for bootstack - temporary stack */
+bootstack:
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index e5377d4477e6..51afb57a3332 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -47,9 +47,7 @@
#include "opt_isa.h"
#include "opt_maxmem.h"
#include "opt_msgbuf.h"
-#include "opt_npx.h"
#include "opt_perfmon.h"
-#include "opt_swtch.h"
#include "opt_kstack_pages.h"
#include <sys/param.h>
@@ -100,104 +98,49 @@
#include <machine/reg.h>
#include <machine/clock.h>
#include <machine/specialreg.h>
-#include <machine/bootinfo.h>
#include <machine/md_var.h>
-#include <machine/pc/bios.h>
-#include <machine/pcb_ext.h> /* pcb.h included via sys/user.h */
#include <machine/proc.h>
#ifdef PERFMON
#include <machine/perfmon.h>
#endif
-#ifdef SMP
-#include <machine/privatespace.h>
-#include <machine/smp.h>
-#endif
+#include <machine/tss.h>
-#include <i386/isa/icu.h>
-#include <i386/isa/intr_machdep.h>
+#include <amd64/isa/icu.h>
+#include <amd64/isa/intr_machdep.h>
#include <isa/rtc.h>
-#include <machine/vm86.h>
#include <sys/ptrace.h>
#include <machine/sigframe.h>
-extern void init386(int first);
+extern void hammer_time(void);
extern void dblfault_handler(void);
extern void printcpuinfo(void); /* XXX header file */
-extern void finishidentcpu(void);
+extern void identify_cpu(void);
extern void panicifcpuunsupported(void);
extern void initializecpu(void);
#define CS_SECURE(cs) (ISPL(cs) == SEL_UPL)
#define EFL_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
-#if !defined(CPU_ENABLE_SSE) && defined(I686_CPU)
-#define CPU_ENABLE_SSE
-#endif
-#if defined(CPU_DISABLE_SSE)
-#undef CPU_ENABLE_SSE
-#endif
-
static void cpu_startup(void *);
static void fpstate_drop(struct thread *td);
static void get_fpcontext(struct thread *td, mcontext_t *mcp);
static int set_fpcontext(struct thread *td, const mcontext_t *mcp);
-#ifdef CPU_ENABLE_SSE
-static void set_fpregs_xmm(struct save87 *, struct savexmm *);
-static void fill_fpregs_xmm(struct savexmm *, struct save87 *);
-#endif /* CPU_ENABLE_SSE */
SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
int _udatasel, _ucodesel;
u_int atdevbase;
-#if defined(SWTCH_OPTIM_STATS)
-int stupid_switch;
-SYSCTL_INT(_debug, OID_AUTO, stupid_switch,
- CTLFLAG_RW, &stupid_switch, 0, "");
-int swtch_optim_stats;
-SYSCTL_INT(_debug, OID_AUTO, swtch_optim_stats,
- CTLFLAG_RW, &swtch_optim_stats, 0, "");
-int tlb_flush_count;
-SYSCTL_INT(_debug, OID_AUTO, tlb_flush_count,
- CTLFLAG_RW, &tlb_flush_count, 0, "");
-int lazy_flush_count;
-SYSCTL_INT(_debug, OID_AUTO, lazy_flush_count,
- CTLFLAG_RW, &lazy_flush_count, 0, "");
-int lazy_flush_fixup;
-SYSCTL_INT(_debug, OID_AUTO, lazy_flush_fixup,
- CTLFLAG_RW, &lazy_flush_fixup, 0, "");
-#ifdef SMP
-int lazy_flush_smpfixup;
-SYSCTL_INT(_debug, OID_AUTO, lazy_flush_smpfixup,
- CTLFLAG_RW, &lazy_flush_smpfixup, 0, "");
-int lazy_flush_smpipi;
-SYSCTL_INT(_debug, OID_AUTO, lazy_flush_smpipi,
- CTLFLAG_RW, &lazy_flush_smpipi, 0, "");
-int lazy_flush_smpbadcr3;
-SYSCTL_INT(_debug, OID_AUTO, lazy_flush_smpbadcr3,
- CTLFLAG_RW, &lazy_flush_smpbadcr3, 0, "");
-int lazy_flush_smpmiss;
-SYSCTL_INT(_debug, OID_AUTO, lazy_flush_smpmiss,
- CTLFLAG_RW, &lazy_flush_smpmiss, 0, "");
-#endif
-#endif
-#ifdef LAZY_SWITCH
-int lazy_flush_enable = 1;
-SYSCTL_INT(_debug, OID_AUTO, lazy_flush_enable,
- CTLFLAG_RW, &lazy_flush_enable, 0, "");
-#endif
+u_int64_t modulep; /* phys addr of metadata table */
+u_int64_t physfree; /* first free page after kernel */
+u_int64_t IdlePTD; /* phys addr of kernel PTD */
+u_int64_t IdlePDP; /* phys addr of kernel level 3 */
+u_int64_t IdlePML4; /* phys addr of kernel level 4 */
+struct user *proc0uarea; /* address of proc 0 uarea space */
+vm_offset_t proc0kstack; /* address of proc 0 kstack space */
int cold = 1;
-#ifdef COMPAT_43
-static void osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code);
-#endif
-#ifdef COMPAT_FREEBSD4
-static void freebsd4_sendsig(sig_t catcher, int sig, sigset_t *mask,
- u_long code);
-#endif
-
long Maxmem = 0;
vm_paddr_t phys_avail[10];
@@ -208,9 +151,7 @@ vm_paddr_t phys_avail[10];
struct kva_md_info kmi;
static struct trapframe proc0_tf;
-#ifndef SMP
static struct pcpu __pcpu;
-#endif
struct mtx icu_lock;
@@ -260,10 +201,8 @@ cpu_startup(dummy)
bufinit();
vm_pager_bufferinit();
-#ifndef SMP
/* For SMP, we delay the cpu_setregs() until after SMP startup. */
cpu_setregs();
-#endif
}
/*
@@ -276,256 +215,6 @@ cpu_startup(dummy)
* frame pointer, it returns to the user
* specified pc, psl.
*/
-#ifdef COMPAT_43
-static void
-osendsig(catcher, sig, mask, code)
- sig_t catcher;
- int sig;
- sigset_t *mask;
- u_long code;
-{
- struct osigframe sf, *fp;
- struct proc *p;
- struct thread *td;
- struct sigacts *psp;
- struct trapframe *regs;
- int oonstack;
-
- td = curthread;
- p = td->td_proc;
- PROC_LOCK_ASSERT(p, MA_OWNED);
- psp = p->p_sigacts;
- regs = td->td_frame;
- oonstack = sigonstack(regs->tf_esp);
-
- /* Allocate space for the signal handler context. */
- if ((p->p_flag & P_ALTSTACK) && !oonstack &&
- SIGISMEMBER(psp->ps_sigonstack, sig)) {
- fp = (struct osigframe *)(p->p_sigstk.ss_sp +
- p->p_sigstk.ss_size - sizeof(struct osigframe));
-#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
- p->p_sigstk.ss_flags |= SS_ONSTACK;
-#endif
- } else
- fp = (struct osigframe *)regs->tf_esp - 1;
- PROC_UNLOCK(p);
-
- /* Translate the signal if appropriate. */
- if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
- sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
-
- /* Build the argument list for the signal handler. */
- sf.sf_signum = sig;
- sf.sf_scp = (register_t)&fp->sf_siginfo.si_sc;
- PROC_LOCK(p);
- if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
- /* Signal handler installed with SA_SIGINFO. */
- sf.sf_arg2 = (register_t)&fp->sf_siginfo;
- sf.sf_siginfo.si_signo = sig;
- sf.sf_siginfo.si_code = code;
- sf.sf_ahu.sf_action = (__osiginfohandler_t *)catcher;
- } else {
- /* Old FreeBSD-style arguments. */
- sf.sf_arg2 = code;
- sf.sf_addr = regs->tf_err;
- sf.sf_ahu.sf_handler = catcher;
- }
- PROC_UNLOCK(p);
-
- /* Save most if not all of trap frame. */
- sf.sf_siginfo.si_sc.sc_eax = regs->tf_eax;
- sf.sf_siginfo.si_sc.sc_ebx = regs->tf_ebx;
- sf.sf_siginfo.si_sc.sc_ecx = regs->tf_ecx;
- sf.sf_siginfo.si_sc.sc_edx = regs->tf_edx;
- sf.sf_siginfo.si_sc.sc_esi = regs->tf_esi;
- sf.sf_siginfo.si_sc.sc_edi = regs->tf_edi;
- sf.sf_siginfo.si_sc.sc_cs = regs->tf_cs;
- sf.sf_siginfo.si_sc.sc_ds = regs->tf_ds;
- sf.sf_siginfo.si_sc.sc_ss = regs->tf_ss;
- sf.sf_siginfo.si_sc.sc_es = regs->tf_es;
- sf.sf_siginfo.si_sc.sc_fs = regs->tf_fs;
- sf.sf_siginfo.si_sc.sc_gs = rgs();
- sf.sf_siginfo.si_sc.sc_isp = regs->tf_isp;
-
- /* Build the signal context to be used by osigreturn(). */
- sf.sf_siginfo.si_sc.sc_onstack = (oonstack) ? 1 : 0;
- SIG2OSIG(*mask, sf.sf_siginfo.si_sc.sc_mask);
- sf.sf_siginfo.si_sc.sc_sp = regs->tf_esp;
- sf.sf_siginfo.si_sc.sc_fp = regs->tf_ebp;
- sf.sf_siginfo.si_sc.sc_pc = regs->tf_eip;
- sf.sf_siginfo.si_sc.sc_ps = regs->tf_eflags;
- sf.sf_siginfo.si_sc.sc_trapno = regs->tf_trapno;
- sf.sf_siginfo.si_sc.sc_err = regs->tf_err;
-
- /*
- * If we're a vm86 process, we want to save the segment registers.
- * We also change eflags to be our emulated eflags, not the actual
- * eflags.
- */
- if (regs->tf_eflags & PSL_VM) {
- /* XXX confusing names: `tf' isn't a trapframe; `regs' is. */
- struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
- struct vm86_kernel *vm86 = &td->td_pcb->pcb_ext->ext_vm86;
-
- sf.sf_siginfo.si_sc.sc_gs = tf->tf_vm86_gs;
- sf.sf_siginfo.si_sc.sc_fs = tf->tf_vm86_fs;
- sf.sf_siginfo.si_sc.sc_es = tf->tf_vm86_es;
- sf.sf_siginfo.si_sc.sc_ds = tf->tf_vm86_ds;
-
- if (vm86->vm86_has_vme == 0)
- sf.sf_siginfo.si_sc.sc_ps =
- (tf->tf_eflags & ~(PSL_VIF | PSL_VIP)) |
- (vm86->vm86_eflags & (PSL_VIF | PSL_VIP));
-
- /* See sendsig() for comments. */
- tf->tf_eflags &= ~(PSL_VM | PSL_NT | PSL_VIF | PSL_VIP);
- }
-
- /*
- * Copy the sigframe out to the user's stack.
- */
- if (copyout(&sf, fp, sizeof(*fp)) != 0) {
-#ifdef DEBUG
- printf("process %ld has trashed its stack\n", (long)p->p_pid);
-#endif
- PROC_LOCK(p);
- sigexit(td, SIGILL);
- }
-
- regs->tf_esp = (int)fp;
- regs->tf_eip = PS_STRINGS - szosigcode;
- regs->tf_eflags &= ~PSL_T;
- regs->tf_cs = _ucodesel;
- regs->tf_ds = _udatasel;
- regs->tf_es = _udatasel;
- regs->tf_fs = _udatasel;
- load_gs(_udatasel);
- regs->tf_ss = _udatasel;
- PROC_LOCK(p);
-}
-#endif /* COMPAT_43 */
-
-#ifdef COMPAT_FREEBSD4
-static void
-freebsd4_sendsig(catcher, sig, mask, code)
- sig_t catcher;
- int sig;
- sigset_t *mask;
- u_long code;
-{
- struct sigframe4 sf, *sfp;
- struct proc *p;
- struct thread *td;
- struct sigacts *psp;
- struct trapframe *regs;
- int oonstack;
-
- td = curthread;
- p = td->td_proc;
- PROC_LOCK_ASSERT(p, MA_OWNED);
- psp = p->p_sigacts;
- regs = td->td_frame;
- oonstack = sigonstack(regs->tf_esp);
-
- /* Save user context. */
- bzero(&sf, sizeof(sf));
- sf.sf_uc.uc_sigmask = *mask;
- sf.sf_uc.uc_stack = p->p_sigstk;
- sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK)
- ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
- sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
- sf.sf_uc.uc_mcontext.mc_gs = rgs();
- bcopy(regs, &sf.sf_uc.uc_mcontext.mc_fs, sizeof(*regs));
-
- /* Allocate space for the signal handler context. */
- if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack &&
- SIGISMEMBER(psp->ps_sigonstack, sig)) {
- sfp = (struct sigframe4 *)(p->p_sigstk.ss_sp +
- p->p_sigstk.ss_size - sizeof(struct sigframe4));
-#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
- p->p_sigstk.ss_flags |= SS_ONSTACK;
-#endif
- } else
- sfp = (struct sigframe4 *)regs->tf_esp - 1;
- PROC_UNLOCK(p);
-
- /* Translate the signal if appropriate. */
- if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
- sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
-
- /* Build the argument list for the signal handler. */
- sf.sf_signum = sig;
- sf.sf_ucontext = (register_t)&sfp->sf_uc;
- PROC_LOCK(p);
- if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
- /* Signal handler installed with SA_SIGINFO. */
- sf.sf_siginfo = (register_t)&sfp->sf_si;
- sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher;
-
- /* Fill in POSIX parts */
- sf.sf_si.si_signo = sig;
- sf.sf_si.si_code = code;
- sf.sf_si.si_addr = (void *)regs->tf_err;
- } else {
- /* Old FreeBSD-style arguments. */
- sf.sf_siginfo = code;
- sf.sf_addr = regs->tf_err;
- sf.sf_ahu.sf_handler = catcher;
- }
- PROC_UNLOCK(p);
-
- /*
- * If we're a vm86 process, we want to save the segment registers.
- * We also change eflags to be our emulated eflags, not the actual
- * eflags.
- */
- if (regs->tf_eflags & PSL_VM) {
- struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
- struct vm86_kernel *vm86 = &td->td_pcb->pcb_ext->ext_vm86;
-
- sf.sf_uc.uc_mcontext.mc_gs = tf->tf_vm86_gs;
- sf.sf_uc.uc_mcontext.mc_fs = tf->tf_vm86_fs;
- sf.sf_uc.uc_mcontext.mc_es = tf->tf_vm86_es;
- sf.sf_uc.uc_mcontext.mc_ds = tf->tf_vm86_ds;
-
- if (vm86->vm86_has_vme == 0)
- sf.sf_uc.uc_mcontext.mc_eflags =
- (tf->tf_eflags & ~(PSL_VIF | PSL_VIP)) |
- (vm86->vm86_eflags & (PSL_VIF | PSL_VIP));
-
- /*
- * Clear PSL_NT to inhibit T_TSSFLT faults on return from
- * syscalls made by the signal handler. This just avoids
- * wasting time for our lazy fixup of such faults. PSL_NT
- * does nothing in vm86 mode, but vm86 programs can set it
- * almost legitimately in probes for old cpu types.
- */
- tf->tf_eflags &= ~(PSL_VM | PSL_NT | PSL_VIF | PSL_VIP);
- }
-
- /*
- * Copy the sigframe out to the user's stack.
- */
- if (copyout(&sf, sfp, sizeof(*sfp)) != 0) {
-#ifdef DEBUG
- printf("process %ld has trashed its stack\n", (long)p->p_pid);
-#endif
- PROC_LOCK(p);
- sigexit(td, SIGILL);
- }
-
- regs->tf_esp = (int)sfp;
- regs->tf_eip = PS_STRINGS - szfreebsd4_sigcode;
- regs->tf_eflags &= ~PSL_T;
- regs->tf_cs = _ucodesel;
- regs->tf_ds = _udatasel;
- regs->tf_es = _udatasel;
- regs->tf_fs = _udatasel;
- regs->tf_ss = _udatasel;
- PROC_LOCK(p);
-}
-#endif /* COMPAT_FREEBSD4 */
-
void
sendsig(catcher, sig, mask, code)
sig_t catcher;
@@ -545,20 +234,8 @@ sendsig(catcher, sig, mask, code)
p = td->td_proc;
PROC_LOCK_ASSERT(p, MA_OWNED);
psp = p->p_sigacts;
-#ifdef COMPAT_FREEBSD4
- if (SIGISMEMBER(psp->ps_freebsd4, sig)) {
- freebsd4_sendsig(catcher, sig, mask, code);
- return;
- }
-#endif
-#ifdef COMPAT_43
- if (SIGISMEMBER(psp->ps_osigset, sig)) {
- osendsig(catcher, sig, mask, code);
- return;
- }
-#endif
regs = td->td_frame;
- oonstack = sigonstack(regs->tf_esp);
+ oonstack = sigonstack(regs->tf_rsp);
/* Save user context. */
bzero(&sf, sizeof(sf));
@@ -567,8 +244,7 @@ sendsig(catcher, sig, mask, code)
sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK)
? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
- sf.sf_uc.uc_mcontext.mc_gs = rgs();
- bcopy(regs, &sf.sf_uc.uc_mcontext.mc_fs, sizeof(*regs));
+ bcopy(regs, &sf.sf_uc.uc_mcontext.mc_r15, sizeof(*regs));
sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */
get_fpcontext(td, &sf.sf_uc.uc_mcontext);
fpstate_drop(td);
@@ -582,9 +258,9 @@ sendsig(catcher, sig, mask, code)
p->p_sigstk.ss_flags |= SS_ONSTACK;
#endif
} else
- sp = (char *)regs->tf_esp - sizeof(struct sigframe);
+ sp = (char *)regs->tf_rsp - sizeof(struct sigframe);
/* Align to 16 bytes. */
- sfp = (struct sigframe *)((unsigned int)sp & ~0xF);
+ sfp = (struct sigframe *)((unsigned long)sp & ~0xF);
PROC_UNLOCK(p);
/* Translate the signal if appropriate. */
@@ -592,56 +268,27 @@ sendsig(catcher, sig, mask, code)
sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
/* Build the argument list for the signal handler. */
- sf.sf_signum = sig;
- sf.sf_ucontext = (register_t)&sfp->sf_uc;
+ regs->tf_rdi = sig; /* arg 1 in %rdi */
+ regs->tf_rdx = (register_t)&sfp->sf_uc; /* arg 3 in %rdx */
PROC_LOCK(p);
if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
/* Signal handler installed with SA_SIGINFO. */
- sf.sf_siginfo = (register_t)&sfp->sf_si;
+ regs->tf_rsi = (register_t)&sfp->sf_si; /* arg 2 in %rsi */
sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher;
/* Fill in POSIX parts */
sf.sf_si.si_signo = sig;
sf.sf_si.si_code = code;
- sf.sf_si.si_addr = (void *)regs->tf_err;
+ regs->tf_rcx = regs->tf_err; /* arg 4 in %rcx */
} else {
/* Old FreeBSD-style arguments. */
- sf.sf_siginfo = code;
- sf.sf_addr = regs->tf_err;
+ regs->tf_rsi = code; /* arg 2 in %rsi */
+ regs->tf_rcx = regs->tf_err; /* arg 4 in %rcx */
sf.sf_ahu.sf_handler = catcher;
}
PROC_UNLOCK(p);
/*
- * If we're a vm86 process, we want to save the segment registers.
- * We also change eflags to be our emulated eflags, not the actual
- * eflags.
- */
- if (regs->tf_eflags & PSL_VM) {
- struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
- struct vm86_kernel *vm86 = &td->td_pcb->pcb_ext->ext_vm86;
-
- sf.sf_uc.uc_mcontext.mc_gs = tf->tf_vm86_gs;
- sf.sf_uc.uc_mcontext.mc_fs = tf->tf_vm86_fs;
- sf.sf_uc.uc_mcontext.mc_es = tf->tf_vm86_es;
- sf.sf_uc.uc_mcontext.mc_ds = tf->tf_vm86_ds;
-
- if (vm86->vm86_has_vme == 0)
- sf.sf_uc.uc_mcontext.mc_eflags =
- (tf->tf_eflags & ~(PSL_VIF | PSL_VIP)) |
- (vm86->vm86_eflags & (PSL_VIF | PSL_VIP));
-
- /*
- * Clear PSL_NT to inhibit T_TSSFLT faults on return from
- * syscalls made by the signal handler. This just avoids
- * wasting time for our lazy fixup of such faults. PSL_NT
- * does nothing in vm86 mode, but vm86 programs can set it
- * almost legitimately in probes for old cpu types.
- */
- tf->tf_eflags &= ~(PSL_VM | PSL_NT | PSL_VIF | PSL_VIP);
- }
-
- /*
* Copy the sigframe out to the user's stack.
*/
if (copyout(&sf, sfp, sizeof(*sfp)) != 0) {
@@ -652,14 +299,10 @@ sendsig(catcher, sig, mask, code)
sigexit(td, SIGILL);
}
- regs->tf_esp = (int)sfp;
- regs->tf_eip = PS_STRINGS - *(p->p_sysent->sv_szsigcode);
- regs->tf_eflags &= ~PSL_T;
+ regs->tf_rsp = (long)sfp;
+ regs->tf_rip = PS_STRINGS - *(p->p_sysent->sv_szsigcode);
+ regs->tf_rflags &= ~PSL_T;
regs->tf_cs = _ucodesel;
- regs->tf_ds = _udatasel;
- regs->tf_es = _udatasel;
- regs->tf_fs = _udatasel;
- regs->tf_ss = _udatasel;
PROC_LOCK(p);
}
@@ -674,232 +317,6 @@ sendsig(catcher, sig, mask, code)
*
* MPSAFE
*/
-#ifdef COMPAT_43
-int
-osigreturn(td, uap)
- struct thread *td;
- struct osigreturn_args /* {
- struct osigcontext *sigcntxp;
- } */ *uap;
-{
- struct osigcontext sc;
- struct trapframe *regs;
- struct osigcontext *scp;
- struct proc *p = td->td_proc;
- int eflags, error;
-
- regs = td->td_frame;
- error = copyin(uap->sigcntxp, &sc, sizeof(sc));
- if (error != 0)
- return (error);
- scp = &sc;
- eflags = scp->sc_ps;
- if (eflags & PSL_VM) {
- struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
- struct vm86_kernel *vm86;
-
- /*
- * if pcb_ext == 0 or vm86_inited == 0, the user hasn't
- * set up the vm86 area, and we can't enter vm86 mode.
- */
- if (td->td_pcb->pcb_ext == 0)
- return (EINVAL);
- vm86 = &td->td_pcb->pcb_ext->ext_vm86;
- if (vm86->vm86_inited == 0)
- return (EINVAL);
-
- /* Go back to user mode if both flags are set. */
- if ((eflags & PSL_VIP) && (eflags & PSL_VIF))
- trapsignal(td, SIGBUS, 0);
-
- if (vm86->vm86_has_vme) {
- eflags = (tf->tf_eflags & ~VME_USERCHANGE) |
- (eflags & VME_USERCHANGE) | PSL_VM;
- } else {
- vm86->vm86_eflags = eflags; /* save VIF, VIP */
- eflags = (tf->tf_eflags & ~VM_USERCHANGE) |
- (eflags & VM_USERCHANGE) | PSL_VM;
- }
- tf->tf_vm86_ds = scp->sc_ds;
- tf->tf_vm86_es = scp->sc_es;
- tf->tf_vm86_fs = scp->sc_fs;
- tf->tf_vm86_gs = scp->sc_gs;
- tf->tf_ds = _udatasel;
- tf->tf_es = _udatasel;
- tf->tf_fs = _udatasel;
- } else {
- /*
- * Don't allow users to change privileged or reserved flags.
- */
- /*
- * XXX do allow users to change the privileged flag PSL_RF.
- * The cpu sets PSL_RF in tf_eflags for faults. Debuggers
- * should sometimes set it there too. tf_eflags is kept in
- * the signal context during signal handling and there is no
- * other place to remember it, so the PSL_RF bit may be
- * corrupted by the signal handler without us knowing.
- * Corruption of the PSL_RF bit at worst causes one more or
- * one less debugger trap, so allowing it is fairly harmless.
- */
- if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) {
- return (EINVAL);
- }
-
- /*
- * Don't allow users to load a valid privileged %cs. Let the
- * hardware check for invalid selectors, excess privilege in
- * other selectors, invalid %eip's and invalid %esp's.
- */
- if (!CS_SECURE(scp->sc_cs)) {
- trapsignal(td, SIGBUS, T_PROTFLT);
- return (EINVAL);
- }
- regs->tf_ds = scp->sc_ds;
- regs->tf_es = scp->sc_es;
- regs->tf_fs = scp->sc_fs;
- }
-
- /* Restore remaining registers. */
- regs->tf_eax = scp->sc_eax;
- regs->tf_ebx = scp->sc_ebx;
- regs->tf_ecx = scp->sc_ecx;
- regs->tf_edx = scp->sc_edx;
- regs->tf_esi = scp->sc_esi;
- regs->tf_edi = scp->sc_edi;
- regs->tf_cs = scp->sc_cs;
- regs->tf_ss = scp->sc_ss;
- regs->tf_isp = scp->sc_isp;
- regs->tf_ebp = scp->sc_fp;
- regs->tf_esp = scp->sc_sp;
- regs->tf_eip = scp->sc_pc;
- regs->tf_eflags = eflags;
-
- PROC_LOCK(p);
-#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
- if (scp->sc_onstack & 1)
- p->p_sigstk.ss_flags |= SS_ONSTACK;
- else
- p->p_sigstk.ss_flags &= ~SS_ONSTACK;
-#endif
- SIGSETOLD(td->td_sigmask, scp->sc_mask);
- SIG_CANTMASK(td->td_sigmask);
- signotify(td);
- PROC_UNLOCK(p);
- return (EJUSTRETURN);
-}
-#endif /* COMPAT_43 */
-
-#ifdef COMPAT_FREEBSD4
-/*
- * MPSAFE
- */
-int
-freebsd4_sigreturn(td, uap)
- struct thread *td;
- struct freebsd4_sigreturn_args /* {
- const ucontext4 *sigcntxp;
- } */ *uap;
-{
- struct ucontext4 uc;
- struct proc *p = td->td_proc;
- struct trapframe *regs;
- const struct ucontext4 *ucp;
- int cs, eflags, error;
-
- error = copyin(uap->sigcntxp, &uc, sizeof(uc));
- if (error != 0)
- return (error);
- ucp = &uc;
- regs = td->td_frame;
- eflags = ucp->uc_mcontext.mc_eflags;
- if (eflags & PSL_VM) {
- struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
- struct vm86_kernel *vm86;
-
- /*
- * if pcb_ext == 0 or vm86_inited == 0, the user hasn't
- * set up the vm86 area, and we can't enter vm86 mode.
- */
- if (td->td_pcb->pcb_ext == 0)
- return (EINVAL);
- vm86 = &td->td_pcb->pcb_ext->ext_vm86;
- if (vm86->vm86_inited == 0)
- return (EINVAL);
-
- /* Go back to user mode if both flags are set. */
- if ((eflags & PSL_VIP) && (eflags & PSL_VIF))
- trapsignal(td, SIGBUS, 0);
-
- if (vm86->vm86_has_vme) {
- eflags = (tf->tf_eflags & ~VME_USERCHANGE) |
- (eflags & VME_USERCHANGE) | PSL_VM;
- } else {
- vm86->vm86_eflags = eflags; /* save VIF, VIP */
- eflags = (tf->tf_eflags & ~VM_USERCHANGE) |
- (eflags & VM_USERCHANGE) | PSL_VM;
- }
- bcopy(&ucp->uc_mcontext.mc_fs, tf, sizeof(struct trapframe));
- tf->tf_eflags = eflags;
- tf->tf_vm86_ds = tf->tf_ds;
- tf->tf_vm86_es = tf->tf_es;
- tf->tf_vm86_fs = tf->tf_fs;
- tf->tf_vm86_gs = ucp->uc_mcontext.mc_gs;
- tf->tf_ds = _udatasel;
- tf->tf_es = _udatasel;
- tf->tf_fs = _udatasel;
- } else {
- /*
- * Don't allow users to change privileged or reserved flags.
- */
- /*
- * XXX do allow users to change the privileged flag PSL_RF.
- * The cpu sets PSL_RF in tf_eflags for faults. Debuggers
- * should sometimes set it there too. tf_eflags is kept in
- * the signal context during signal handling and there is no
- * other place to remember it, so the PSL_RF bit may be
- * corrupted by the signal handler without us knowing.
- * Corruption of the PSL_RF bit at worst causes one more or
- * one less debugger trap, so allowing it is fairly harmless.
- */
- if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) {
- printf("freebsd4_sigreturn: eflags = 0x%x\n", eflags);
- return (EINVAL);
- }
-
- /*
- * Don't allow users to load a valid privileged %cs. Let the
- * hardware check for invalid selectors, excess privilege in
- * other selectors, invalid %eip's and invalid %esp's.
- */
- cs = ucp->uc_mcontext.mc_cs;
- if (!CS_SECURE(cs)) {
- printf("freebsd4_sigreturn: cs = 0x%x\n", cs);
- trapsignal(td, SIGBUS, T_PROTFLT);
- return (EINVAL);
- }
-
- bcopy(&ucp->uc_mcontext.mc_fs, regs, sizeof(*regs));
- }
-
- PROC_LOCK(p);
-#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
- if (ucp->uc_mcontext.mc_onstack & 1)
- p->p_sigstk.ss_flags |= SS_ONSTACK;
- else
- p->p_sigstk.ss_flags &= ~SS_ONSTACK;
-#endif
-
- td->td_sigmask = ucp->uc_sigmask;
- SIG_CANTMASK(td->td_sigmask);
- signotify(td);
- PROC_UNLOCK(p);
- return (EJUSTRETURN);
-}
-#endif /* COMPAT_FREEBSD4 */
-
-/*
- * MPSAFE
- */
int
sigreturn(td, uap)
struct thread *td;
@@ -911,86 +328,50 @@ sigreturn(td, uap)
struct proc *p = td->td_proc;
struct trapframe *regs;
const ucontext_t *ucp;
- int cs, eflags, error, ret;
+ long rflags;
+ int cs, error, ret;
error = copyin(uap->sigcntxp, &uc, sizeof(uc));
if (error != 0)
return (error);
ucp = &uc;
regs = td->td_frame;
- eflags = ucp->uc_mcontext.mc_eflags;
- if (eflags & PSL_VM) {
- struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
- struct vm86_kernel *vm86;
-
- /*
- * if pcb_ext == 0 or vm86_inited == 0, the user hasn't
- * set up the vm86 area, and we can't enter vm86 mode.
- */
- if (td->td_pcb->pcb_ext == 0)
- return (EINVAL);
- vm86 = &td->td_pcb->pcb_ext->ext_vm86;
- if (vm86->vm86_inited == 0)
- return (EINVAL);
-
- /* Go back to user mode if both flags are set. */
- if ((eflags & PSL_VIP) && (eflags & PSL_VIF))
- trapsignal(td, SIGBUS, 0);
-
- if (vm86->vm86_has_vme) {
- eflags = (tf->tf_eflags & ~VME_USERCHANGE) |
- (eflags & VME_USERCHANGE) | PSL_VM;
- } else {
- vm86->vm86_eflags = eflags; /* save VIF, VIP */
- eflags = (tf->tf_eflags & ~VM_USERCHANGE) |
- (eflags & VM_USERCHANGE) | PSL_VM;
- }
- bcopy(&ucp->uc_mcontext.mc_fs, tf, sizeof(struct trapframe));
- tf->tf_eflags = eflags;
- tf->tf_vm86_ds = tf->tf_ds;
- tf->tf_vm86_es = tf->tf_es;
- tf->tf_vm86_fs = tf->tf_fs;
- tf->tf_vm86_gs = ucp->uc_mcontext.mc_gs;
- tf->tf_ds = _udatasel;
- tf->tf_es = _udatasel;
- tf->tf_fs = _udatasel;
- } else {
- /*
- * Don't allow users to change privileged or reserved flags.
- */
- /*
- * XXX do allow users to change the privileged flag PSL_RF.
- * The cpu sets PSL_RF in tf_eflags for faults. Debuggers
- * should sometimes set it there too. tf_eflags is kept in
- * the signal context during signal handling and there is no
- * other place to remember it, so the PSL_RF bit may be
- * corrupted by the signal handler without us knowing.
- * Corruption of the PSL_RF bit at worst causes one more or
- * one less debugger trap, so allowing it is fairly harmless.
- */
- if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) {
- printf("sigreturn: eflags = 0x%x\n", eflags);
- return (EINVAL);
- }
-
- /*
- * Don't allow users to load a valid privileged %cs. Let the
- * hardware check for invalid selectors, excess privilege in
- * other selectors, invalid %eip's and invalid %esp's.
- */
- cs = ucp->uc_mcontext.mc_cs;
- if (!CS_SECURE(cs)) {
- printf("sigreturn: cs = 0x%x\n", cs);
- trapsignal(td, SIGBUS, T_PROTFLT);
- return (EINVAL);
- }
+ rflags = ucp->uc_mcontext.mc_rflags;
+ /*
+ * Don't allow users to change privileged or reserved flags.
+ */
+ /*
+ * XXX do allow users to change the privileged flag PSL_RF.
+ * The cpu sets PSL_RF in tf_rflags for faults. Debuggers
+ * should sometimes set it there too. tf_rflags is kept in
+ * the signal context during signal handling and there is no
+ * other place to remember it, so the PSL_RF bit may be
+ * corrupted by the signal handler without us knowing.
+ * Corruption of the PSL_RF bit at worst causes one more or
+ * one less debugger trap, so allowing it is fairly harmless.
+ */
+ if (!EFL_SECURE(rflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) {
+ printf("sigreturn: rflags = 0x%x\n", rflags);
+ return (EINVAL);
+ }
- ret = set_fpcontext(td, &ucp->uc_mcontext);
- if (ret != 0)
- return (ret);
- bcopy(&ucp->uc_mcontext.mc_fs, regs, sizeof(*regs));
+ /*
+ * Don't allow users to load a valid privileged %cs. Let the
+ * hardware check for invalid selectors, excess privilege in
+ * other selectors, invalid %eip's and invalid %esp's.
+ */
+ cs = ucp->uc_mcontext.mc_cs;
+ if (!CS_SECURE(cs)) {
+ printf("sigreturn: cs = 0x%x\n", cs);
+ trapsignal(td, SIGBUS, T_PROTFLT);
+ return (EINVAL);
}
+ ret = set_fpcontext(td, &ucp->uc_mcontext);
+ if (ret != 0)
+ return (ret);
+ bcopy(&ucp->uc_mcontext.mc_r15, regs, sizeof(*regs));
+
PROC_LOCK(p);
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
if (ucp->uc_mcontext.mc_onstack & 1)
@@ -1003,6 +384,7 @@ sigreturn(td, uap)
SIG_CANTMASK(td->td_sigmask);
signotify(td);
PROC_UNLOCK(p);
+ td->td_pcb->pcb_flags |= PCB_FULLCTX;
return (EJUSTRETURN);
}
@@ -1056,11 +438,6 @@ void
cpu_idle(void)
{
-#ifdef SMP
- if (mp_grab_cpu_hlt())
- return;
-#endif
-
if (cpu_idle_hlt) {
disable_intr();
if (sched_runnable()) {
@@ -1087,59 +464,16 @@ exec_setregs(td, entry, stack, ps_strings)
u_long ps_strings;
{
struct trapframe *regs = td->td_frame;
- struct pcb *pcb = td->td_pcb;
- /* Reset pc->pcb_gs and %gs before possibly invalidating it. */
- pcb->pcb_gs = _udatasel;
- load_gs(_udatasel);
-
- if (td->td_proc->p_md.md_ldt)
- user_ldt_free(td);
-
bzero((char *)regs, sizeof(struct trapframe));
- regs->tf_eip = entry;
- regs->tf_esp = stack;
- regs->tf_eflags = PSL_USER | (regs->tf_eflags & PSL_T);
+ regs->tf_rip = entry;
+ /* This strangeness is to ensure alignment after the implied return address */
+ regs->tf_rsp = ((stack - 8) & ~0xF) + 8;
+ regs->tf_rdi = stack; /* argv */
+ regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T);
regs->tf_ss = _udatasel;
- regs->tf_ds = _udatasel;
- regs->tf_es = _udatasel;
- regs->tf_fs = _udatasel;
regs->tf_cs = _ucodesel;
- /* PS_STRINGS value for BSD/OS binaries. It is 0 for non-BSD/OS. */
- regs->tf_ebx = ps_strings;
-
- /*
- * Reset the hardware debug registers if they were in use.
- * They won't have any meaning for the newly exec'd process.
- */
- if (pcb->pcb_flags & PCB_DBREGS) {
- pcb->pcb_dr0 = 0;
- pcb->pcb_dr1 = 0;
- pcb->pcb_dr2 = 0;
- pcb->pcb_dr3 = 0;
- pcb->pcb_dr6 = 0;
- pcb->pcb_dr7 = 0;
- if (pcb == PCPU_GET(curpcb)) {
- /*
- * Clear the debug registers on the running
- * CPU, otherwise they will end up affecting
- * the next process we switch to.
- */
- reset_dbregs();
- }
- pcb->pcb_flags &= ~PCB_DBREGS;
- }
-
- /*
- * Initialize the math emulator (if any) for the current process.
- * Actually, just clear the bit that says that the emulator has
- * been initialized. Initialization is delayed until the process
- * traps to the emulator (if it is done at all) mainly because
- * emulators don't provide an entry point for initialization.
- */
- td->td_pcb->pcb_flags &= ~FP_SOFTFP;
-
/*
* Arrange to trap the next npx or `fwait' instruction (see npx.c
* for why fwait must be trapped at least if there is an npx or an
@@ -1164,30 +498,18 @@ exec_setregs(td, entry, stack, ps_strings)
* soon.
*/
fpstate_drop(td);
-
- /*
- * XXX - Linux emulator
- * Make sure sure edx is 0x0 on entry. Linux binaries depend
- * on it.
- */
- td->td_retval[1] = 0;
}
void
cpu_setregs(void)
{
- unsigned int cr0;
+ register_t cr0;
cr0 = rcr0();
-#ifdef SMP
cr0 |= CR0_NE; /* Done by npxinit() */
-#endif
cr0 |= CR0_MP | CR0_TS; /* Done at every execve() too. */
-#ifndef I386_CPU
cr0 |= CR0_WP | CR0_AM;
-#endif
load_cr0(cr0);
- load_gs(_udatasel);
}
static int
@@ -1207,16 +529,9 @@ SYSCTL_PROC(_machdep, CPU_ADJKERNTZ, adjkerntz, CTLTYPE_INT|CTLFLAG_RW,
SYSCTL_INT(_machdep, CPU_DISRTCSET, disable_rtc_set,
CTLFLAG_RW, &disable_rtc_set, 0, "");
-SYSCTL_STRUCT(_machdep, CPU_BOOTINFO, bootinfo,
- CTLFLAG_RD, &bootinfo, bootinfo, "");
-
SYSCTL_INT(_machdep, CPU_WALLCLOCK, wall_cmos_clock,
CTLFLAG_RW, &wall_cmos_clock, 0, "");
-u_long bootdev; /* not a dev_t - encoding is different */
-SYSCTL_ULONG(_machdep, OID_AUTO, guessed_bootdev,
- CTLFLAG_RD, &bootdev, 0, "Maybe the Boot device (not in dev_t format)");
-
/*
* Initialize 386 and configure to run kernel
*/
@@ -1225,28 +540,13 @@ SYSCTL_ULONG(_machdep, OID_AUTO, guessed_bootdev,
* Initialize segments & interrupt table
*/
-int _default_ldt;
-union descriptor gdt[NGDT * MAXCPU]; /* global descriptor table */
+struct user_segment_descriptor gdt[NGDT];/* global descriptor table */
static struct gate_descriptor idt0[NIDT];
struct gate_descriptor *idt = &idt0[0]; /* interrupt descriptor table */
-union descriptor ldt[NLDT]; /* local descriptor table */
-#ifdef SMP
-/* table descriptors - used to load tables by microp */
-struct region_descriptor r_gdt, r_idt;
-#endif
-int private_tss; /* flag indicating private tss */
-
-#if defined(I586_CPU) && !defined(NO_F00F_HACK)
-extern int has_f00f_bug;
-#endif
-
-static struct i386tss dblfault_tss;
-static char dblfault_stack[PAGE_SIZE];
-
-extern struct user *proc0uarea;
-extern vm_offset_t proc0kstack;
+static char dblfault_stack[PAGE_SIZE] __aligned(16);
+struct amd64tss common_tss;
/* software prototypes -- in more palatable form */
struct soft_segment_descriptor gdt_segs[] = {
@@ -1256,214 +556,94 @@ struct soft_segment_descriptor gdt_segs[] = {
0, /* segment type */
0, /* segment descriptor priority level */
0, /* segment descriptor present */
- 0, 0,
+ 0, /* long */
0, /* default 32 vs 16 bit size */
0 /* limit granularity (byte/page units)*/ },
/* GCODE_SEL 1 Code Descriptor for kernel */
{ 0x0, /* segment base address */
0xfffff, /* length - all address space */
SDT_MEMERA, /* segment type */
- 0, /* segment descriptor priority level */
+ SEL_KPL, /* segment descriptor priority level */
1, /* segment descriptor present */
- 0, 0,
- 1, /* default 32 vs 16 bit size */
+ 1, /* long */
+ 0, /* default 32 vs 16 bit size */
1 /* limit granularity (byte/page units)*/ },
/* GDATA_SEL 2 Data Descriptor for kernel */
{ 0x0, /* segment base address */
0xfffff, /* length - all address space */
SDT_MEMRWA, /* segment type */
- 0, /* segment descriptor priority level */
+ SEL_KPL, /* segment descriptor priority level */
1, /* segment descriptor present */
- 0, 0,
- 1, /* default 32 vs 16 bit size */
+ 1, /* long */
+ 0, /* default 32 vs 16 bit size */
1 /* limit granularity (byte/page units)*/ },
-/* GPRIV_SEL 3 SMP Per-Processor Private Data Descriptor */
+/* GUCODE32_SEL 3 32 bit Code Descriptor for user */
{ 0x0, /* segment base address */
0xfffff, /* length - all address space */
- SDT_MEMRWA, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
-/* GPROC0_SEL 4 Proc 0 Tss Descriptor */
-{
- 0x0, /* segment base address */
- sizeof(struct i386tss)-1,/* length - all address space */
- SDT_SYS386TSS, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 0, /* unused - default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
-/* GLDT_SEL 5 LDT Descriptor */
-{ (int) ldt, /* segment base address */
- sizeof(ldt)-1, /* length - all address space */
- SDT_SYSLDT, /* segment type */
+ SDT_MEMERA, /* segment type */
SEL_UPL, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 0, /* unused - default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
-/* GUSERLDT_SEL 6 User LDT Descriptor per process */
-{ (int) ldt, /* segment base address */
- (512 * sizeof(union descriptor)-1), /* length */
- SDT_SYSLDT, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 0, /* unused - default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
-/* GTGATE_SEL 7 Null Descriptor - Placeholder */
-{ 0x0, /* segment base address */
- 0x0, /* length - all address space */
- 0, /* segment type */
- 0, /* segment descriptor priority level */
0, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
-/* GBIOSLOWMEM_SEL 8 BIOS access to realmode segment 0x40, must be #8 in GDT */
-{ 0x400, /* segment base address */
- 0xfffff, /* length */
- SDT_MEMRWA, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
+ 0, /* long */
1, /* default 32 vs 16 bit size */
1 /* limit granularity (byte/page units)*/ },
-/* GPANIC_SEL 9 Panic Tss Descriptor */
-{ (int) &dblfault_tss, /* segment base address */
- sizeof(struct i386tss)-1,/* length - all address space */
- SDT_SYS386TSS, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 0, /* unused - default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
-/* GBIOSCODE32_SEL 10 BIOS 32-bit interface (32bit Code) */
-{ 0, /* segment base address (overwritten) */
- 0xfffff, /* length */
- SDT_MEMERA, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
-/* GBIOSCODE16_SEL 11 BIOS 32-bit interface (16bit Code) */
-{ 0, /* segment base address (overwritten) */
- 0xfffff, /* length */
- SDT_MEMERA, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
-/* GBIOSDATA_SEL 12 BIOS 32-bit interface (Data) */
-{ 0, /* segment base address (overwritten) */
- 0xfffff, /* length */
+/* GUDATA_SEL 4 32/64 bit Data Descriptor for user */
+{ 0x0, /* segment base address */
+ 0xfffff, /* length - all address space */
SDT_MEMRWA, /* segment type */
- 0, /* segment descriptor priority level */
+ SEL_UPL, /* segment descriptor priority level */
1, /* segment descriptor present */
- 0, 0,
+ 0, /* long */
1, /* default 32 vs 16 bit size */
1 /* limit granularity (byte/page units)*/ },
-/* GBIOSUTIL_SEL 13 BIOS 16-bit interface (Utility) */
-{ 0, /* segment base address (overwritten) */
- 0xfffff, /* length */
- SDT_MEMRWA, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
-/* GBIOSARGS_SEL 14 BIOS 16-bit interface (Arguments) */
-{ 0, /* segment base address (overwritten) */
- 0xfffff, /* length */
- SDT_MEMRWA, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
-};
-
-static struct soft_segment_descriptor ldt_segs[] = {
- /* Null Descriptor - overwritten by call gate */
-{ 0x0, /* segment base address */
- 0x0, /* length - all address space */
- 0, /* segment type */
- 0, /* segment descriptor priority level */
- 0, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
- /* Null Descriptor - overwritten by call gate */
-{ 0x0, /* segment base address */
- 0x0, /* length - all address space */
- 0, /* segment type */
- 0, /* segment descriptor priority level */
- 0, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
- /* Null Descriptor - overwritten by call gate */
-{ 0x0, /* segment base address */
- 0x0, /* length - all address space */
- 0, /* segment type */
- 0, /* segment descriptor priority level */
- 0, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
- /* Code Descriptor for user */
+/* GUCODE_SEL 5 64 bit Code Descriptor for user */
{ 0x0, /* segment base address */
0xfffff, /* length - all address space */
SDT_MEMERA, /* segment type */
SEL_UPL, /* segment descriptor priority level */
1, /* segment descriptor present */
- 0, 0,
- 1, /* default 32 vs 16 bit size */
+ 1, /* long */
+ 0, /* default 32 vs 16 bit size */
1 /* limit granularity (byte/page units)*/ },
- /* Null Descriptor - overwritten by call gate */
+/* GPROC0_SEL 6 Proc 0 Tss Descriptor */
+{
+ 0x0, /* segment base address */
+ sizeof(struct amd64tss)-1,/* length - all address space */
+ SDT_SYSTSS, /* segment type */
+ SEL_KPL, /* segment descriptor priority level */
+ 1, /* segment descriptor present */
+ 0, /* long */
+ 0, /* unused - default 32 vs 16 bit size */
+ 0 /* limit granularity (byte/page units)*/ },
+/* Actually, the TSS is a system descriptor which is double size */
{ 0x0, /* segment base address */
- 0x0, /* length - all address space */
+ 0x0, /* length */
0, /* segment type */
0, /* segment descriptor priority level */
0, /* segment descriptor present */
- 0, 0,
+ 0, /* long */
0, /* default 32 vs 16 bit size */
0 /* limit granularity (byte/page units)*/ },
- /* Data 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, 0,
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
};
void
-setidt(idx, func, typ, dpl, selec)
+setidt(idx, func, typ, dpl, ist)
int idx;
inthand_t *func;
int typ;
int dpl;
- int selec;
+ int ist;
{
struct gate_descriptor *ip;
ip = idt + idx;
- ip->gd_looffset = (int)func;
- ip->gd_selector = selec;
- ip->gd_stkcpy = 0;
+ ip->gd_looffset = (uintptr_t)func;
+ ip->gd_selector = GSEL(GCODE_SEL, SEL_KPL);
+ ip->gd_ist = ist;
ip->gd_xx = 0;
ip->gd_type = typ;
ip->gd_dpl = dpl;
ip->gd_p = 1;
- ip->gd_hioffset = ((int)func)>>16 ;
+ ip->gd_hioffset = ((uintptr_t)func)>>16 ;
}
#define IDTVEC(name) __CONCAT(X,name)
@@ -1473,24 +653,68 @@ extern inthand_t
IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(fpusegm),
IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot),
IDTVEC(page), IDTVEC(mchk), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(align),
- IDTVEC(xmm), IDTVEC(lcall_syscall), IDTVEC(int0x80_syscall);
+ IDTVEC(xmm), IDTVEC(int0x80_syscall),
+ IDTVEC(fast_syscall), IDTVEC(fast_syscall32);
void
sdtossd(sd, ssd)
- struct segment_descriptor *sd;
+ struct user_segment_descriptor *sd;
struct soft_segment_descriptor *ssd;
{
+
ssd->ssd_base = (sd->sd_hibase << 24) | sd->sd_lobase;
ssd->ssd_limit = (sd->sd_hilimit << 16) | sd->sd_lolimit;
ssd->ssd_type = sd->sd_type;
ssd->ssd_dpl = sd->sd_dpl;
ssd->ssd_p = sd->sd_p;
+ ssd->ssd_long = sd->sd_long;
ssd->ssd_def32 = sd->sd_def32;
ssd->ssd_gran = sd->sd_gran;
}
+void
+ssdtosd(ssd, sd)
+ struct soft_segment_descriptor *ssd;
+ struct user_segment_descriptor *sd;
+{
+
+ sd->sd_lobase = (ssd->ssd_base) & 0xffffff;
+ sd->sd_hibase = (ssd->ssd_base >> 24) & 0xff;
+ sd->sd_lolimit = (ssd->ssd_limit) & 0xffff;
+ sd->sd_hilimit = (ssd->ssd_limit >> 16) & 0xf;
+ sd->sd_type = ssd->ssd_type;
+ sd->sd_dpl = ssd->ssd_dpl;
+ sd->sd_p = ssd->ssd_p;
+ sd->sd_long = ssd->ssd_long;
+ sd->sd_def32 = ssd->ssd_def32;
+ sd->sd_gran = ssd->ssd_gran;
+}
+
+void
+ssdtosyssd(ssd, sd)
+ struct soft_segment_descriptor *ssd;
+ struct system_segment_descriptor *sd;
+{
+
+ sd->sd_lobase = (ssd->ssd_base) & 0xffffff;
+ sd->sd_hibase = (ssd->ssd_base >> 24) & 0xffffff;
+ sd->sd_lolimit = (ssd->ssd_limit) & 0xffff;
+ sd->sd_hilimit = (ssd->ssd_limit >> 16) & 0xf;
+ sd->sd_type = ssd->ssd_type;
+ sd->sd_dpl = ssd->ssd_dpl;
+ sd->sd_p = ssd->ssd_p;
+ sd->sd_gran = ssd->ssd_gran;
+}
+
+
#define PHYSMAP_SIZE (2 * 8)
+struct bios_smap {
+ u_int64_t base;
+ u_int64_t length;
+ u_int32_t type;
+} __packed;
+
/*
* Populate the (physmap) array with base/bound pairs describing the
* available physical memory in the system, then test this memory and
@@ -1505,116 +729,48 @@ sdtossd(sd, ssd)
* XXX first should be vm_paddr_t.
*/
static void
-getmemsize(int first)
+getmemsize(caddr_t kmdp, u_int64_t first)
{
int i, physmap_idx, pa_indx;
- int hasbrokenint12;
u_int basemem, extmem;
- struct vm86frame vmf;
- struct vm86context vmc;
vm_paddr_t pa, physmap[PHYSMAP_SIZE];
pt_entry_t *pte;
char *cp;
- struct bios_smap *smap;
+ struct bios_smap *smapbase, *smap, *smapend;
+ u_int32_t smapsize;
- hasbrokenint12 = 0;
- TUNABLE_INT_FETCH("hw.hasbrokenint12", &hasbrokenint12);
- bzero(&vmf, sizeof(struct vm86frame));
bzero(physmap, sizeof(physmap));
basemem = 0;
+ physmap_idx = 0;
/*
- * Some newer BIOSes has broken INT 12H implementation which cause
- * kernel panic immediately. In this case, we need to scan SMAP
- * with INT 15:E820 first, then determine base memory size.
- */
- if (hasbrokenint12) {
- goto int15e820;
- }
-
- /*
- * Perform "base memory" related probes & setup
- */
- vm86_intcall(0x12, &vmf);
- basemem = vmf.vmf_ax;
- if (basemem > 640) {
- printf("Preposterous BIOS basemem of %uK, truncating to 640K\n",
- basemem);
- basemem = 640;
- }
-
- /*
- * XXX if biosbasemem is now < 640, there is a `hole'
- * between the end of base memory and the start of
- * ISA memory. The hole may be empty or it may
- * contain BIOS code or data. Map it read/write so
- * that the BIOS can write to it. (Memory from 0 to
- * the physical end of the kernel is mapped read-only
- * to begin with and then parts of it are remapped.
- * The parts that aren't remapped form holes that
- * remain read-only and are unused by the kernel.
- * The base memory area is below the physical end of
- * the kernel and right now forms a read-only hole.
- * The part of it from PAGE_SIZE to
- * (trunc_page(biosbasemem * 1024) - 1) will be
- * remapped and used by the kernel later.)
+ * get memory map from INT 15:E820, kindly supplied by the loader.
*
- * This code is similar to the code used in
- * pmap_mapdev, but since no memory needs to be
- * allocated we simply change the mapping.
- */
- for (pa = trunc_page(basemem * 1024);
- pa < ISA_HOLE_START; pa += PAGE_SIZE)
- pmap_kenter(KERNBASE + pa, pa);
-
- /*
- * if basemem != 640, map pages r/w into vm86 page table so
- * that the bios can scribble on it.
- */
- pte = (pt_entry_t *)vm86paddr;
- for (i = basemem / 4; i < 160; i++)
- pte[i] = (i << PAGE_SHIFT) | PG_V | PG_RW | PG_U;
-
-int15e820:
- /*
- * map page 1 R/W into the kernel page table so we can use it
- * as a buffer. The kernel will unmap this page later.
- */
- pmap_kenter(KERNBASE + (1 << PAGE_SHIFT), 1 << PAGE_SHIFT);
-
- /*
- * get memory map with INT 15:E820
+ * subr_module.c says:
+ * "Consumer may safely assume that size value precedes data."
+ * ie: an int32_t immediately precedes smap.
*/
- vmc.npages = 0;
- smap = (void *)vm86_addpage(&vmc, 1, KERNBASE + (1 << PAGE_SHIFT));
- vm86_getptr(&vmc, (vm_offset_t)smap, &vmf.vmf_es, &vmf.vmf_di);
+ smapbase = (struct bios_smap *)preload_search_info(kmdp, MODINFO_METADATA | MODINFOMD_SMAP);
+ if (smapbase == 0) {
+ panic("No BIOS smap info from loader!");
+ goto deep_shit;
+ }
+ smapsize = *((u_int32_t *)smapbase - 1);
+ smapend = (struct bios_smap *)((uintptr_t)smapbase + smapsize);
- physmap_idx = 0;
- vmf.vmf_ebx = 0;
- do {
- vmf.vmf_eax = 0xE820;
- vmf.vmf_edx = SMAP_SIG;
- vmf.vmf_ecx = sizeof(struct bios_smap);
- i = vm86_datacall(0x15, &vmf, &vmc);
- if (i || vmf.vmf_eax != SMAP_SIG)
- break;
+ for (smap = smapbase; smap < smapend; smap++) {
if (boothowto & RB_VERBOSE)
- printf("SMAP type=%02x base=%016llx len=%016llx\n",
+ printf("SMAP type=%02x base=%016lx len=%016lx\n",
smap->type, smap->base, smap->length);
- if (smap->type != 0x01)
- goto next_run;
-
- if (smap->length == 0)
- goto next_run;
+ if (smap->type != 0x01) {
+ continue;
+ }
-#ifndef PAE
- if (smap->base >= 0xffffffff) {
- printf("%uK of memory above 4GB ignored\n",
- (u_int)(smap->length / 1024));
- goto next_run;
+ if (smap->length == 0) {
+next_run:
+ continue;
}
-#endif
for (i = 0; i <= physmap_idx; i += 2) {
if (smap->base < physmap[i + 1]) {
@@ -1627,7 +783,7 @@ int15e820:
if (smap->base == physmap[physmap_idx + 1]) {
physmap[physmap_idx + 1] += smap->length;
- goto next_run;
+ continue;
}
physmap_idx += 2;
@@ -1638,12 +794,12 @@ int15e820:
}
physmap[physmap_idx] = smap->base;
physmap[physmap_idx + 1] = smap->base + smap->length;
-next_run: ;
- } while (vmf.vmf_ebx != 0);
+ }
/*
* Perform "base memory" related probes & setup based on SMAP
*/
+deep_shit:
if (basemem == 0) {
for (i = 0; i <= physmap_idx; i += 2) {
if (physmap[i] == 0x00000000) {
@@ -1653,6 +809,10 @@ next_run: ;
}
if (basemem == 0) {
+ basemem = rtcin(RTC_BASELO) + (rtcin(RTC_BASEHI) << 8);
+ }
+
+ if (basemem == 0) {
basemem = 640;
}
@@ -1662,36 +822,20 @@ next_run: ;
basemem = 640;
}
+#if 0
for (pa = trunc_page(basemem * 1024);
pa < ISA_HOLE_START; pa += PAGE_SIZE)
pmap_kenter(KERNBASE + pa, pa);
-
- pte = (pt_entry_t *)vm86paddr;
- for (i = basemem / 4; i < 160; i++)
- pte[i] = (i << PAGE_SHIFT) | PG_V | PG_RW | PG_U;
+#endif
}
if (physmap[1] != 0)
goto physmap_done;
/*
- * If we failed above, try memory map with INT 15:E801
+ * Prefer the RTC value for extended memory.
*/
- vmf.vmf_ax = 0xE801;
- if (vm86_intcall(0x15, &vmf) == 0) {
- extmem = vmf.vmf_cx + vmf.vmf_dx * 64;
- } else {
-#if 0
- vmf.vmf_ah = 0x88;
- vm86_intcall(0x15, &vmf);
- extmem = vmf.vmf_ax;
-#else
- /*
- * Prefer the RTC value for extended memory.
- */
- extmem = rtcin(RTC_EXTLO) + (rtcin(RTC_EXTHI) << 8);
-#endif
- }
+ extmem = rtcin(RTC_EXTLO) + (rtcin(RTC_EXTHI) << 8);
/*
* Special hack for chipsets that still remap the 384k hole when
@@ -1716,19 +860,10 @@ physmap_done:
/*
* Now, physmap contains a map of physical memory.
*/
-
-#ifdef SMP
- /* make hole for AP bootstrap code */
- physmap[1] = mp_bootaddress(physmap[1] / 1024);
-
- /* look for the MP hardware - needed for apic addresses */
- i386_mp_probe();
-#endif
-
/*
* Maxmem isn't the "maximum memory", it's one larger than the
* highest page of the physical address space. It should be
- * called something like "Maxphyspage". We may adjust this
+ * called something like "Maxphyspage". We may adjust this
* based on ``hw.physmem'' and the results of the memory test.
*/
Maxmem = atop(physmap[physmap_idx + 1]);
@@ -1778,7 +913,7 @@ physmap_done:
/*
* 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);
@@ -1813,7 +948,7 @@ physmap_done:
*/
if (pa >= 0x100000 && pa < first)
continue;
-
+
page_bad = FALSE;
/*
@@ -1913,17 +1048,97 @@ physmap_done:
avail_end = phys_avail[pa_indx];
}
+static u_int64_t
+allocpages(int n)
+{
+ u_int64_t ret;
+
+ ret = physfree;
+ bzero((void *)ret, n * PAGE_SIZE);
+ physfree += n * PAGE_SIZE;
+ return (ret);
+}
+
+static void
+create_pagetables(void)
+{
+ u_int64_t p0kpa;
+ u_int64_t p0upa;
+ u_int64_t KPTphys;
+ int i;
+
+ /* Allocate pages */
+ KPTphys = allocpages(NKPT);
+ IdlePML4 = allocpages(NKPML4E);
+ IdlePDP = allocpages(NKPDPE);
+ IdlePTD = allocpages(NPGPTD);
+ p0upa = allocpages(UAREA_PAGES);
+ p0kpa = allocpages(KSTACK_PAGES);
+
+ proc0uarea = (struct user *)(p0upa + KERNBASE);
+ proc0kstack = p0kpa + KERNBASE;
+
+ /* 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) < physfree; i++) {
+ ((pt_entry_t *)KPTphys)[i] = i << PAGE_SHIFT;
+ ((pt_entry_t *)KPTphys)[i] |= PG_RW | PG_V;
+ }
+
+ /* Now map the page tables at their location within PTmap */
+ for (i = 0; i < NKPT; i++) {
+ ((pd_entry_t *)IdlePTD)[i + KPTDI] = KPTphys + (i << PAGE_SHIFT);
+ ((pd_entry_t *)IdlePTD)[i + KPTDI] |= PG_RW | PG_V;
+ }
+
+ /* Map from zero to end of allocations under 2M pages */
+ /* This replaces some of the PTD entries above */
+ for (i = 0; (i << PDRSHIFT) < physfree; i++) {
+ ((pd_entry_t *)IdlePTD)[i] = i << PDRSHIFT;
+ ((pd_entry_t *)IdlePTD)[i] |= PG_RW | PG_V | PG_PS;
+ }
+
+ /* Now map the page tables at their location within PTmap */
+ for (i = 0; i < NKPT; i++) {
+ ((pd_entry_t *)IdlePTD)[i] = KPTphys + (i << PAGE_SHIFT);
+ ((pd_entry_t *)IdlePTD)[i] |= PG_RW | PG_V;
+ }
+
+ /* Now map the PTD at the top of the PTmap (ie: PTD[]) */
+ for (i = 0; i < NPGPTD; i++) {
+ ((pd_entry_t *)IdlePTD)[i + PTDPTDI] = IdlePTD + (i << PAGE_SHIFT);
+ ((pd_entry_t *)IdlePTD)[i + PTDPTDI] |= PG_RW | PG_V;
+ }
+
+ /* And connect up the PTD to the PDP */
+ for (i = 0; i < NPGPTD; i++) {
+ ((pdp_entry_t *)IdlePDP)[i] = IdlePTD + (i << PAGE_SHIFT);
+ ((pdp_entry_t *)IdlePDP)[i] |= PG_RW | PG_V | PG_U;
+ }
+
+ /* And connect up the PDP to the PML4 */
+ ((pdp_entry_t *)IdlePML4)[0] = IdlePDP;
+ ((pdp_entry_t *)IdlePML4)[0] |= PG_RW | PG_V | PG_U;
+}
+
void
-init386(first)
- int first;
+hammer_time(void)
{
- struct gate_descriptor *gdp;
- int gsel_tss, metadata_missing, off, x;
-#ifndef SMP
- /* table descriptors - used to load tables by microp */
+ caddr_t kmdp;
+ int gsel_tss, off, x;
struct region_descriptor r_gdt, r_idt;
-#endif
struct pcpu *pc;
+ u_int64_t msr;
+
+ /* Turn on PTE NX (no execute) bit */
+ msr = rdmsr(MSR_EFER) | EFER_NXE;
+ wrmsr(MSR_EFER, msr);
+ create_pagetables();
+
+ /* XXX do %cr0 as well */
+ load_cr4(rcr4() | CR4_PGE | CR4_PSE);
+ load_cr3(IdlePML4);
proc0.p_uarea = proc0uarea;
thread0.td_kstack = proc0kstack;
@@ -1937,50 +1152,36 @@ init386(first)
*/
proc_linkup(&proc0, &ksegrp0, &kse0, &thread0);
- metadata_missing = 0;
- if (bootinfo.bi_modulep) {
- preload_metadata = (caddr_t)bootinfo.bi_modulep + KERNBASE;
- preload_bootstrap_relocate(KERNBASE);
- } else {
- metadata_missing = 1;
- }
- if (envmode == 1)
- kern_envp = static_env;
- else if (bootinfo.bi_envp)
- kern_envp = (caddr_t)bootinfo.bi_envp + KERNBASE;
+ preload_metadata = (caddr_t)(uintptr_t)(modulep + KERNBASE);
+ preload_bootstrap_relocate(KERNBASE);
+ kmdp = preload_search_by_type("elf64 kernel");
+ if (kmdp == NULL)
+ kmdp = preload_search_by_type("elf kernel");
+ boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
+ kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *) + KERNBASE;
/* Init basic tunables, hz etc */
init_param1();
/*
- * make gdt memory segments, the code segment goes up to end of the
- * page with etext in it, the data segment goes to the end of
- * the address space
+ * make gdt memory segments
*/
- /*
- * XXX text protection is temporarily (?) disabled. The limit was
- * i386_btop(round_page(etext)) - 1.
- */
- gdt_segs[GCODE_SEL].ssd_limit = atop(0 - 1);
- gdt_segs[GDATA_SEL].ssd_limit = atop(0 - 1);
-#ifdef SMP
- pc = &SMP_prvspace[0].pcpu;
- gdt_segs[GPRIV_SEL].ssd_limit =
- atop(sizeof(struct privatespace) - 1);
-#else
- pc = &__pcpu;
- gdt_segs[GPRIV_SEL].ssd_limit =
- atop(sizeof(struct pcpu) - 1);
-#endif
- gdt_segs[GPRIV_SEL].ssd_base = (int) pc;
- gdt_segs[GPROC0_SEL].ssd_base = (int) &pc->pc_common_tss;
+ gdt_segs[GPROC0_SEL].ssd_base = (uintptr_t)&common_tss;
- for (x = 0; x < NGDT; x++)
- ssdtosd(&gdt_segs[x], &gdt[x].sd);
+ for (x = 0; x < NGDT; x++) {
+ if (x != GPROC0_SEL && x != (GPROC0_SEL + 1))
+ ssdtosd(&gdt_segs[x], &gdt[x]);
+ }
+ ssdtosyssd(&gdt_segs[GPROC0_SEL], (struct system_segment_descriptor *)&gdt[GPROC0_SEL]);
r_gdt.rd_limit = NGDT * sizeof(gdt[0]) - 1;
- r_gdt.rd_base = (int) gdt;
+ r_gdt.rd_base = (long) gdt;
lgdt(&r_gdt);
+ pc = &__pcpu;
+
+ wrmsr(MSR_FSBASE, (u_int64_t)pc);
+ wrmsr(MSR_GSBASE, (u_int64_t)pc);
+ wrmsr(MSR_KGSBASE, (u_int64_t)pc);
pcpu_init(pc, 0, sizeof(struct pcpu));
PCPU_SET(prvspace, pc);
@@ -1998,68 +1199,33 @@ init386(first)
mtx_init(&clock_lock, "clk", NULL, MTX_SPIN | MTX_RECURSE);
mtx_init(&icu_lock, "icu", NULL, MTX_SPIN | MTX_NOWITNESS);
- /* make ldt memory segments */
- /*
- * XXX - VM_MAXUSER_ADDRESS is an end address, not a max. And it
- * should be spelled ...MAX_USER...
- */
- ldt_segs[LUCODE_SEL].ssd_limit = atop(VM_MAXUSER_ADDRESS - 1);
- ldt_segs[LUDATA_SEL].ssd_limit = atop(VM_MAXUSER_ADDRESS - 1);
- for (x = 0; x < sizeof ldt_segs / sizeof ldt_segs[0]; x++)
- ssdtosd(&ldt_segs[x], &ldt[x].sd);
-
- _default_ldt = GSEL(GLDT_SEL, SEL_KPL);
- lldt(_default_ldt);
- PCPU_SET(currentldt, _default_ldt);
-
/* exceptions */
for (x = 0; x < NIDT; x++)
- setidt(x, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(0, &IDTVEC(div), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(1, &IDTVEC(dbg), SDT_SYS386IGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(2, &IDTVEC(nmi), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(3, &IDTVEC(bpt), SDT_SYS386IGT, SEL_UPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(4, &IDTVEC(ofl), SDT_SYS386TGT, SEL_UPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(5, &IDTVEC(bnd), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(7, &IDTVEC(dna), SDT_SYS386TGT, SEL_KPL
- , GSEL(GCODE_SEL, SEL_KPL));
- setidt(8, 0, SDT_SYSTASKGT, SEL_KPL, GSEL(GPANIC_SEL, SEL_KPL));
- setidt(9, &IDTVEC(fpusegm), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(10, &IDTVEC(tss), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(11, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(12, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(14, &IDTVEC(page), SDT_SYS386IGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(15, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(17, &IDTVEC(align), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(18, &IDTVEC(mchk), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(19, &IDTVEC(xmm), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(0x80, &IDTVEC(int0x80_syscall), SDT_SYS386TGT, SEL_UPL,
- GSEL(GCODE_SEL, SEL_KPL));
+ setidt(x, &IDTVEC(rsvd), SDT_SYSTGT, SEL_KPL, 0);
+ setidt(0, &IDTVEC(div), SDT_SYSTGT, SEL_KPL, 0);
+ setidt(1, &IDTVEC(dbg), SDT_SYSIGT, SEL_KPL, 0);
+ setidt(2, &IDTVEC(nmi), SDT_SYSTGT, SEL_KPL, 0);
+ setidt(3, &IDTVEC(bpt), SDT_SYSIGT, SEL_KPL, 0);
+ setidt(4, &IDTVEC(ofl), SDT_SYSTGT, SEL_KPL, 0);
+ setidt(5, &IDTVEC(bnd), SDT_SYSTGT, SEL_KPL, 0);
+ setidt(6, &IDTVEC(ill), SDT_SYSTGT, SEL_KPL, 0);
+ setidt(7, &IDTVEC(dna), SDT_SYSTGT, SEL_KPL, 0);
+ setidt(8, (inthand_t *)dblfault_handler, SDT_SYSIGT, SEL_KPL, 1);
+ setidt(9, &IDTVEC(fpusegm), SDT_SYSTGT, SEL_KPL, 0);
+ setidt(10, &IDTVEC(tss), SDT_SYSTGT, SEL_KPL, 0);
+ setidt(11, &IDTVEC(missing), SDT_SYSTGT, SEL_KPL, 0);
+ setidt(12, &IDTVEC(stk), SDT_SYSTGT, SEL_KPL, 0);
+ setidt(13, &IDTVEC(prot), SDT_SYSTGT, SEL_KPL, 0);
+ setidt(14, &IDTVEC(page), SDT_SYSTGT, SEL_KPL, 0);
+ setidt(15, &IDTVEC(rsvd), SDT_SYSTGT, SEL_KPL, 0);
+ setidt(16, &IDTVEC(fpu), SDT_SYSTGT, SEL_KPL, 0);
+ setidt(17, &IDTVEC(align), SDT_SYSTGT, SEL_KPL, 0);
+ setidt(18, &IDTVEC(mchk), SDT_SYSTGT, SEL_KPL, 0);
+ setidt(19, &IDTVEC(xmm), SDT_SYSTGT, SEL_KPL, 0);
+ setidt(0x80, &IDTVEC(int0x80_syscall), SDT_SYSTGT, SEL_UPL, 0);
r_idt.rd_limit = sizeof(idt0) - 1;
- r_idt.rd_base = (int) idt;
+ r_idt.rd_base = (long) idt;
lidt(&r_idt);
/*
@@ -2067,9 +1233,6 @@ init386(first)
*/
cninit();
- if (metadata_missing)
- printf("WARNING: loader(8) metadata is missing!\n");
-
#ifdef DEV_ISA
isa_defaultirq();
#endif
@@ -2080,44 +1243,31 @@ init386(first)
Debugger("Boot flags requested debugger");
#endif
- finishidentcpu(); /* Final stage of CPU initialization */
- setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
+ identify_cpu(); /* Final stage of CPU initialization */
initializecpu(); /* Initialize CPU registers */
/* make an initial tss so cpu can get interrupt stack on syscall! */
- /* Note: -16 is so we can grow the trapframe if we came from vm86 */
- PCPU_SET(common_tss.tss_esp0, thread0.td_kstack +
- KSTACK_PAGES * PAGE_SIZE - sizeof(struct pcb) - 16);
- PCPU_SET(common_tss.tss_ss0, GSEL(GDATA_SEL, SEL_KPL));
+ common_tss.tss_rsp0 = thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE - sizeof(struct pcb);
+ /* XXX we need to update tss_rsp0 in cpu_switch */
+ /* XXX maybe not yet, everything is still running in supervisor mode */
+
+ /* doublefault stack space, runs on ist1 */
+ common_tss.tss_ist1 = (long)&dblfault_stack[sizeof(dblfault_stack)];
+
gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
- private_tss = 0;
- PCPU_SET(tss_gdt, &gdt[GPROC0_SEL].sd);
- PCPU_SET(common_tssd, *PCPU_GET(tss_gdt));
- PCPU_SET(common_tss.tss_ioopt, (sizeof (struct i386tss)) << 16);
ltr(gsel_tss);
- dblfault_tss.tss_esp = dblfault_tss.tss_esp0 = dblfault_tss.tss_esp1 =
- dblfault_tss.tss_esp2 = (int)&dblfault_stack[sizeof(dblfault_stack)];
- dblfault_tss.tss_ss = dblfault_tss.tss_ss0 = dblfault_tss.tss_ss1 =
- dblfault_tss.tss_ss2 = GSEL(GDATA_SEL, SEL_KPL);
-#ifdef PAE
- dblfault_tss.tss_cr3 = (int)IdlePDPT;
-#else
- dblfault_tss.tss_cr3 = (int)IdlePTD;
-#endif
- dblfault_tss.tss_eip = (int)dblfault_handler;
- dblfault_tss.tss_eflags = PSL_KERNEL;
- dblfault_tss.tss_ds = dblfault_tss.tss_es =
- dblfault_tss.tss_gs = GSEL(GDATA_SEL, SEL_KPL);
- dblfault_tss.tss_fs = GSEL(GPRIV_SEL, SEL_KPL);
- dblfault_tss.tss_cs = GSEL(GCODE_SEL, SEL_KPL);
- dblfault_tss.tss_ldt = GSEL(GLDT_SEL, SEL_KPL);
-
- vm86_initialize();
- getmemsize(first);
+ /* Set up the fast syscall stuff */
+ msr = rdmsr(MSR_EFER) | EFER_SCE;
+ wrmsr(MSR_EFER, msr);
+ wrmsr(MSR_LSTAR, (u_int64_t)IDTVEC(fast_syscall));
+ wrmsr(MSR_CSTAR, (u_int64_t)IDTVEC(fast_syscall32));
+ msr = ((u_int64_t)GSEL(GCODE_SEL, SEL_KPL) << 32) |
+ ((u_int64_t)GSEL(GUCODE32_SEL, SEL_UPL) << 48);
+ wrmsr(MSR_STAR, msr);
+ wrmsr(MSR_SF_MASK, PSL_NT|PSL_T|PSL_I|PSL_C|PSL_D);
+
+ getmemsize(kmdp, physfree);
init_param2(physmem);
/* now running on new page tables, configured,and u/iom is accessible */
@@ -2128,35 +1278,14 @@ init386(first)
msgbufinit(msgbufp, MSGBUF_SIZE);
- /* make a call gate to reenter kernel with */
- gdp = &ldt[LSYS5CALLS_SEL].gd;
-
- x = (int) &IDTVEC(lcall_syscall);
- gdp->gd_looffset = x;
- gdp->gd_selector = GSEL(GCODE_SEL,SEL_KPL);
- gdp->gd_stkcpy = 1;
- gdp->gd_type = SDT_SYS386CGT;
- gdp->gd_dpl = SEL_UPL;
- gdp->gd_p = 1;
- gdp->gd_hioffset = x >> 16;
-
- /* XXX does this work? */
- ldt[LBSDICALLS_SEL] = ldt[LSYS5CALLS_SEL];
- ldt[LSOL26CALLS_SEL] = ldt[LSYS5CALLS_SEL];
-
/* transfer to user mode */
- _ucodesel = LSEL(LUCODE_SEL, SEL_UPL);
- _udatasel = LSEL(LUDATA_SEL, SEL_UPL);
+ _ucodesel = GSEL(GUCODE_SEL, SEL_UPL);
+ _udatasel = GSEL(GUDATA_SEL, SEL_UPL);
/* setup proc 0's pcb */
thread0.td_pcb->pcb_flags = 0; /* XXXKSE */
-#ifdef PAE
- thread0.td_pcb->pcb_cr3 = (int)IdlePDPT;
-#else
- thread0.td_pcb->pcb_cr3 = (int)IdlePTD;
-#endif
- thread0.td_pcb->pcb_ext = 0;
+ thread0.td_pcb->pcb_cr3 = IdlePML4;
thread0.td_frame = &proc0_tf;
}
@@ -2165,56 +1294,17 @@ cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
{
}
-#if defined(I586_CPU) && !defined(NO_F00F_HACK)
-static void f00f_hack(void *unused);
-SYSINIT(f00f_hack, SI_SUB_INTRINSIC, SI_ORDER_FIRST, f00f_hack, NULL);
-
-static void
-f00f_hack(void *unused) {
- struct gate_descriptor *new_idt;
-#ifndef SMP
- struct region_descriptor r_idt;
-#endif
- vm_offset_t tmp;
-
- if (!has_f00f_bug)
- return;
-
- GIANT_REQUIRED;
-
- printf("Intel Pentium detected, installing workaround for F00F bug\n");
-
- r_idt.rd_limit = sizeof(idt0) - 1;
-
- tmp = kmem_alloc(kernel_map, PAGE_SIZE * 2);
- if (tmp == 0)
- panic("kmem_alloc returned 0");
- if (((unsigned int)tmp & (PAGE_SIZE-1)) != 0)
- panic("kmem_alloc returned non-page-aligned memory");
- /* Put the first seven entries in the lower page */
- new_idt = (struct gate_descriptor*)(tmp + PAGE_SIZE - (7*8));
- bcopy(idt, new_idt, sizeof(idt0));
- r_idt.rd_base = (int)new_idt;
- lidt(&r_idt);
- idt = new_idt;
- if (vm_map_protect(kernel_map, tmp, tmp + PAGE_SIZE,
- VM_PROT_READ, FALSE) != KERN_SUCCESS)
- panic("vm_map_protect failed");
- return;
-}
-#endif /* defined(I586_CPU) && !NO_F00F_HACK */
-
int
ptrace_set_pc(struct thread *td, unsigned long addr)
{
- td->td_frame->tf_eip = addr;
+ td->td_frame->tf_rip = addr;
return (0);
}
int
ptrace_single_step(struct thread *td)
{
- td->td_frame->tf_eflags |= PSL_T;
+ td->td_frame->tf_rflags |= PSL_T;
return (0);
}
@@ -2225,23 +1315,27 @@ fill_regs(struct thread *td, struct reg *regs)
struct trapframe *tp;
tp = td->td_frame;
- regs->r_fs = tp->tf_fs;
- regs->r_es = tp->tf_es;
- regs->r_ds = tp->tf_ds;
- regs->r_edi = tp->tf_edi;
- regs->r_esi = tp->tf_esi;
- regs->r_ebp = tp->tf_ebp;
- regs->r_ebx = tp->tf_ebx;
- regs->r_edx = tp->tf_edx;
- regs->r_ecx = tp->tf_ecx;
- regs->r_eax = tp->tf_eax;
- regs->r_eip = tp->tf_eip;
+ regs->r_r15 = tp->tf_r15;
+ regs->r_r14 = tp->tf_r14;
+ regs->r_r13 = tp->tf_r13;
+ regs->r_r12 = tp->tf_r12;
+ regs->r_r11 = tp->tf_r11;
+ regs->r_r10 = tp->tf_r10;
+ regs->r_r9 = tp->tf_r9;
+ regs->r_r8 = tp->tf_r8;
+ regs->r_rdi = tp->tf_rdi;
+ regs->r_rsi = tp->tf_rsi;
+ regs->r_rbp = tp->tf_rbp;
+ regs->r_rbx = tp->tf_rbx;
+ regs->r_rdx = tp->tf_rdx;
+ regs->r_rcx = tp->tf_rcx;
+ regs->r_rax = tp->tf_rax;
+ regs->r_rip = tp->tf_rip;
regs->r_cs = tp->tf_cs;
- regs->r_eflags = tp->tf_eflags;
- regs->r_esp = tp->tf_esp;
+ regs->r_rflags = tp->tf_rflags;
+ regs->r_rsp = tp->tf_rsp;
regs->r_ss = tp->tf_ss;
pcb = td->td_pcb;
- regs->r_gs = pcb->pcb_gs;
return (0);
}
@@ -2252,106 +1346,107 @@ set_regs(struct thread *td, struct reg *regs)
struct trapframe *tp;
tp = td->td_frame;
- if (!EFL_SECURE(regs->r_eflags, tp->tf_eflags) ||
+ if (!EFL_SECURE(regs->r_rflags, tp->tf_rflags) ||
!CS_SECURE(regs->r_cs))
return (EINVAL);
- tp->tf_fs = regs->r_fs;
- tp->tf_es = regs->r_es;
- tp->tf_ds = regs->r_ds;
- tp->tf_edi = regs->r_edi;
- tp->tf_esi = regs->r_esi;
- tp->tf_ebp = regs->r_ebp;
- tp->tf_ebx = regs->r_ebx;
- tp->tf_edx = regs->r_edx;
- tp->tf_ecx = regs->r_ecx;
- tp->tf_eax = regs->r_eax;
- tp->tf_eip = regs->r_eip;
+ tp->tf_r15 = regs->r_r15;
+ tp->tf_r14 = regs->r_r14;
+ tp->tf_r13 = regs->r_r13;
+ tp->tf_r12 = regs->r_r12;
+ tp->tf_r11 = regs->r_r11;
+ tp->tf_r10 = regs->r_r10;
+ tp->tf_r9 = regs->r_r9;
+ tp->tf_r8 = regs->r_r8;
+ tp->tf_rdi = regs->r_rdi;
+ tp->tf_rsi = regs->r_rsi;
+ tp->tf_rbp = regs->r_rbp;
+ tp->tf_rbx = regs->r_rbx;
+ tp->tf_rdx = regs->r_rdx;
+ tp->tf_rcx = regs->r_rcx;
+ tp->tf_rax = regs->r_rax;
+ tp->tf_rip = regs->r_rip;
tp->tf_cs = regs->r_cs;
- tp->tf_eflags = regs->r_eflags;
- tp->tf_esp = regs->r_esp;
+ tp->tf_rflags = regs->r_rflags;
+ tp->tf_rsp = regs->r_rsp;
tp->tf_ss = regs->r_ss;
pcb = td->td_pcb;
- pcb->pcb_gs = regs->r_gs;
return (0);
}
-#ifdef CPU_ENABLE_SSE
+/* XXX check all this stuff! */
+/* externalize from sv_xmm */
static void
-fill_fpregs_xmm(sv_xmm, sv_87)
- struct savexmm *sv_xmm;
- struct save87 *sv_87;
+fill_fpregs_xmm(struct savefpu *sv_xmm, struct fpreg *fpregs)
{
- register struct env87 *penv_87 = &sv_87->sv_env;
- register struct envxmm *penv_xmm = &sv_xmm->sv_env;
+ struct envxmm *penv_fpreg = (struct envxmm *)&fpregs->fpr_env;
+ struct envxmm *penv_xmm = &sv_xmm->sv_env;
int i;
- bzero(sv_87, sizeof(*sv_87));
+ /* pcb -> fpregs */
+ bzero(fpregs, sizeof(*fpregs));
/* FPU control/status */
- penv_87->en_cw = penv_xmm->en_cw;
- penv_87->en_sw = penv_xmm->en_sw;
- penv_87->en_tw = penv_xmm->en_tw;
- penv_87->en_fip = penv_xmm->en_fip;
- penv_87->en_fcs = penv_xmm->en_fcs;
- penv_87->en_opcode = penv_xmm->en_opcode;
- penv_87->en_foo = penv_xmm->en_foo;
- penv_87->en_fos = penv_xmm->en_fos;
+ penv_fpreg->en_cw = penv_xmm->en_cw;
+ penv_fpreg->en_sw = penv_xmm->en_sw;
+ penv_fpreg->en_tw = penv_xmm->en_tw;
+ penv_fpreg->en_opcode = penv_xmm->en_opcode;
+ penv_fpreg->en_rip = penv_xmm->en_rip;
+ penv_fpreg->en_rdp = penv_xmm->en_rdp;
+ penv_fpreg->en_mxcsr = penv_xmm->en_mxcsr;
+ penv_fpreg->en_mxcsr_mask = penv_xmm->en_mxcsr_mask;
/* FPU registers */
for (i = 0; i < 8; ++i)
- sv_87->sv_ac[i] = sv_xmm->sv_fp[i].fp_acc;
+ bcopy(sv_xmm->sv_fp[i].fp_acc.fp_bytes, fpregs->fpr_acc[i], 10);
+
+ /* SSE registers */
+ for (i = 0; i < 16; ++i)
+ bcopy(sv_xmm->sv_xmm[i].xmm_bytes, fpregs->fpr_xacc[i], 16);
}
+/* internalize from fpregs into sv_xmm */
static void
-set_fpregs_xmm(sv_87, sv_xmm)
- struct save87 *sv_87;
- struct savexmm *sv_xmm;
+set_fpregs_xmm(struct fpreg *fpregs, struct savefpu *sv_xmm)
{
- register struct env87 *penv_87 = &sv_87->sv_env;
- register struct envxmm *penv_xmm = &sv_xmm->sv_env;
+ struct envxmm *penv_xmm = &sv_xmm->sv_env;
+ struct envxmm *penv_fpreg = (struct envxmm *)&fpregs->fpr_env;
int i;
+ /* fpregs -> pcb */
/* FPU control/status */
- penv_xmm->en_cw = penv_87->en_cw;
- penv_xmm->en_sw = penv_87->en_sw;
- penv_xmm->en_tw = penv_87->en_tw;
- penv_xmm->en_fip = penv_87->en_fip;
- penv_xmm->en_fcs = penv_87->en_fcs;
- penv_xmm->en_opcode = penv_87->en_opcode;
- penv_xmm->en_foo = penv_87->en_foo;
- penv_xmm->en_fos = penv_87->en_fos;
+ penv_xmm->en_cw = penv_fpreg->en_cw;
+ penv_xmm->en_sw = penv_fpreg->en_sw;
+ penv_xmm->en_tw = penv_fpreg->en_tw;
+ penv_xmm->en_opcode = penv_fpreg->en_opcode;
+ 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;
/* FPU registers */
for (i = 0; i < 8; ++i)
- sv_xmm->sv_fp[i].fp_acc = sv_87->sv_ac[i];
+ bcopy(fpregs->fpr_acc[i], sv_xmm->sv_fp[i].fp_acc.fp_bytes, 10);
+
+ /* SSE registers */
+ for (i = 0; i < 16; ++i)
+ bcopy(fpregs->fpr_xacc[i], sv_xmm->sv_xmm[i].xmm_bytes, 16);
}
-#endif /* CPU_ENABLE_SSE */
+/* externalize from td->pcb */
int
fill_fpregs(struct thread *td, struct fpreg *fpregs)
{
-#ifdef CPU_ENABLE_SSE
- if (cpu_fxsr) {
- fill_fpregs_xmm(&td->td_pcb->pcb_save.sv_xmm,
- (struct save87 *)fpregs);
- return (0);
- }
-#endif /* CPU_ENABLE_SSE */
- bcopy(&td->td_pcb->pcb_save.sv_87, fpregs, sizeof *fpregs);
+
+ fill_fpregs_xmm(&td->td_pcb->pcb_save, fpregs);
return (0);
}
+/* internalize to td->pcb */
int
set_fpregs(struct thread *td, struct fpreg *fpregs)
{
-#ifdef CPU_ENABLE_SSE
- if (cpu_fxsr) {
- set_fpregs_xmm((struct save87 *)fpregs,
- &td->td_pcb->pcb_save.sv_xmm);
- return (0);
- }
-#endif /* CPU_ENABLE_SSE */
- bcopy(fpregs, &td->td_pcb->pcb_save.sv_87, sizeof *fpregs);
+
+ set_fpregs_xmm(fpregs, &td->td_pcb->pcb_save);
return (0);
}
@@ -2366,29 +1461,32 @@ get_mcontext(struct thread *td, mcontext_t *mcp, int clear_ret)
tp = td->td_frame;
PROC_LOCK(curthread->td_proc);
- mcp->mc_onstack = sigonstack(tp->tf_esp);
+ mcp->mc_onstack = sigonstack(tp->tf_rsp);
PROC_UNLOCK(curthread->td_proc);
- mcp->mc_gs = td->td_pcb->pcb_gs;
- mcp->mc_fs = tp->tf_fs;
- mcp->mc_es = tp->tf_es;
- mcp->mc_ds = tp->tf_ds;
- mcp->mc_edi = tp->tf_edi;
- mcp->mc_esi = tp->tf_esi;
- mcp->mc_ebp = tp->tf_ebp;
- mcp->mc_isp = tp->tf_isp;
+ mcp->mc_r15 = tp->tf_r15;
+ mcp->mc_r14 = tp->tf_r14;
+ mcp->mc_r13 = tp->tf_r13;
+ mcp->mc_r12 = tp->tf_r12;
+ mcp->mc_r11 = tp->tf_r11;
+ mcp->mc_r10 = tp->tf_r10;
+ mcp->mc_r9 = tp->tf_r9;
+ mcp->mc_r8 = tp->tf_r8;
+ mcp->mc_rdi = tp->tf_rdi;
+ mcp->mc_rsi = tp->tf_rsi;
+ mcp->mc_rbp = tp->tf_rbp;
+ mcp->mc_rbx = tp->tf_rbx;
+ mcp->mc_rcx = tp->tf_rcx;
if (clear_ret != 0) {
- mcp->mc_eax = 0;
- mcp->mc_edx = 0;
+ mcp->mc_rax = 0;
+ mcp->mc_rdx = 0;
} else {
- mcp->mc_eax = tp->tf_eax;
- mcp->mc_edx = tp->tf_edx;
+ mcp->mc_rax = tp->tf_rax;
+ mcp->mc_rdx = tp->tf_rdx;
}
- mcp->mc_ebx = tp->tf_ebx;
- mcp->mc_ecx = tp->tf_ecx;
- mcp->mc_eip = tp->tf_eip;
+ mcp->mc_rip = tp->tf_rip;
mcp->mc_cs = tp->tf_cs;
- mcp->mc_eflags = tp->tf_eflags;
- mcp->mc_esp = tp->tf_esp;
+ mcp->mc_rflags = tp->tf_rflags;
+ mcp->mc_rsp = tp->tf_rsp;
mcp->mc_ss = tp->tf_ss;
mcp->mc_len = sizeof(*mcp);
get_fpcontext(td, mcp);
@@ -2405,29 +1503,34 @@ int
set_mcontext(struct thread *td, const mcontext_t *mcp)
{
struct trapframe *tp;
- int eflags, ret;
+ long rflags;
+ int ret;
tp = td->td_frame;
if (mcp->mc_len != sizeof(*mcp))
return (EINVAL);
- eflags = (mcp->mc_eflags & PSL_USERCHANGE) |
- (tp->tf_eflags & ~PSL_USERCHANGE);
+ rflags = (mcp->mc_rflags & PSL_USERCHANGE) |
+ (tp->tf_rflags & ~PSL_USERCHANGE);
if ((ret = set_fpcontext(td, mcp)) == 0) {
- tp->tf_fs = mcp->mc_fs;
- tp->tf_es = mcp->mc_es;
- tp->tf_ds = mcp->mc_ds;
- tp->tf_edi = mcp->mc_edi;
- tp->tf_esi = mcp->mc_esi;
- tp->tf_ebp = mcp->mc_ebp;
- tp->tf_ebx = mcp->mc_ebx;
- tp->tf_edx = mcp->mc_edx;
- tp->tf_ecx = mcp->mc_ecx;
- tp->tf_eax = mcp->mc_eax;
- tp->tf_eip = mcp->mc_eip;
- tp->tf_eflags = eflags;
- tp->tf_esp = mcp->mc_esp;
+ tp->tf_r15 = mcp->mc_r15;
+ tp->tf_r14 = mcp->mc_r14;
+ tp->tf_r13 = mcp->mc_r13;
+ tp->tf_r12 = mcp->mc_r12;
+ tp->tf_r11 = mcp->mc_r11;
+ tp->tf_r10 = mcp->mc_r10;
+ tp->tf_r9 = mcp->mc_r9;
+ tp->tf_r8 = mcp->mc_r8;
+ tp->tf_rdi = mcp->mc_rdi;
+ tp->tf_rsi = mcp->mc_rsi;
+ tp->tf_rbp = mcp->mc_rbp;
+ tp->tf_rbx = mcp->mc_rbx;
+ tp->tf_rdx = mcp->mc_rdx;
+ tp->tf_rcx = mcp->mc_rcx;
+ tp->tf_rax = mcp->mc_rax;
+ tp->tf_rip = mcp->mc_rip;
+ tp->tf_rflags = rflags;
+ tp->tf_rsp = mcp->mc_rsp;
tp->tf_ss = mcp->mc_ss;
- td->td_pcb->pcb_gs = mcp->mc_gs;
ret = 0;
}
return (ret);
@@ -2436,11 +1539,7 @@ set_mcontext(struct thread *td, const mcontext_t *mcp)
static void
get_fpcontext(struct thread *td, mcontext_t *mcp)
{
-#ifndef DEV_NPX
- mcp->mc_fpformat = _MC_FPFMT_NODEV;
- mcp->mc_ownedfp = _MC_FPOWNED_NONE;
-#else
- union savefpu *addr;
+ struct savefpu *addr;
/*
* XXX mc_fpstate might be misaligned, since its declaration is not
@@ -2454,34 +1553,28 @@ get_fpcontext(struct thread *td, mcontext_t *mcp)
* called, although this requires knowing too much about
* npxgetregs()'s internals.
*/
- addr = (union savefpu *)&mcp->mc_fpstate;
- if (td == PCPU_GET(fpcurthread) &&
-#ifdef CPU_ENABLE_SSE
- cpu_fxsr &&
-#endif
- ((uintptr_t)(void *)addr & 0xF)) {
+ 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 = npxgetregs(td, addr);
- if (addr != (union savefpu *)&mcp->mc_fpstate) {
+ 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_fpformat = npxformat();
-#endif
}
static int
set_fpcontext(struct thread *td, const mcontext_t *mcp)
{
- union savefpu *addr;
+ struct savefpu *addr;
if (mcp->mc_fpformat == _MC_FPFMT_NODEV)
return (0);
- else if (mcp->mc_fpformat != _MC_FPFMT_387 &&
- mcp->mc_fpformat != _MC_FPFMT_XMM)
+ else if (mcp->mc_fpformat != _MC_FPFMT_XMM)
return (EINVAL);
else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE)
/* We don't care what state is left in the FPU or PCB. */
@@ -2489,24 +1582,19 @@ set_fpcontext(struct thread *td, const mcontext_t *mcp)
else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU ||
mcp->mc_ownedfp == _MC_FPOWNED_PCB) {
/* XXX align as above. */
- addr = (union savefpu *)&mcp->mc_fpstate;
+ addr = (struct savefpu *)&mcp->mc_fpstate;
if (td == PCPU_GET(fpcurthread) &&
-#ifdef CPU_ENABLE_SSE
- cpu_fxsr &&
-#endif
((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));
}
-#ifdef DEV_NPX
/*
* XXX we violate the dubious requirement that npxsetregs()
* be called with interrupts disabled.
*/
npxsetregs(td, addr);
-#endif
/*
* Don't bother putting things back where they were in the
* misaligned case, since we know that the caller won't use
@@ -2523,13 +1611,11 @@ fpstate_drop(struct thread *td)
register_t s;
s = intr_disable();
-#ifdef DEV_NPX
if (PCPU_GET(fpcurthread) == td)
npxdrop();
-#endif
/*
* XXX force a full drop of the npx. The above only drops it if we
- * owned it. npxgetregs() has the same bug in the !cpu_fxsr case.
+ * owned it.
*
* XXX I don't much like npxgetregs()'s semantics of doing a full
* drop. Dropping only to the pcb matches fnsave's behaviour.
@@ -2544,185 +1630,17 @@ fpstate_drop(struct thread *td)
int
fill_dbregs(struct thread *td, struct dbreg *dbregs)
{
- struct pcb *pcb;
- if (td == NULL) {
- dbregs->dr[0] = rdr0();
- dbregs->dr[1] = rdr1();
- dbregs->dr[2] = rdr2();
- dbregs->dr[3] = rdr3();
- dbregs->dr[4] = rdr4();
- dbregs->dr[5] = rdr5();
- dbregs->dr[6] = rdr6();
- dbregs->dr[7] = rdr7();
- } else {
- pcb = td->td_pcb;
- dbregs->dr[0] = pcb->pcb_dr0;
- dbregs->dr[1] = pcb->pcb_dr1;
- dbregs->dr[2] = pcb->pcb_dr2;
- dbregs->dr[3] = pcb->pcb_dr3;
- dbregs->dr[4] = 0;
- dbregs->dr[5] = 0;
- dbregs->dr[6] = pcb->pcb_dr6;
- dbregs->dr[7] = pcb->pcb_dr7;
- }
return (0);
}
int
set_dbregs(struct thread *td, struct dbreg *dbregs)
{
- struct pcb *pcb;
- int i;
- u_int32_t mask1, mask2;
-
- if (td == NULL) {
- load_dr0(dbregs->dr[0]);
- load_dr1(dbregs->dr[1]);
- load_dr2(dbregs->dr[2]);
- load_dr3(dbregs->dr[3]);
- load_dr4(dbregs->dr[4]);
- load_dr5(dbregs->dr[5]);
- load_dr6(dbregs->dr[6]);
- load_dr7(dbregs->dr[7]);
- } else {
- /*
- * Don't let an illegal value for dr7 get set. Specifically,
- * check for undefined settings. Setting these bit patterns
- * result in undefined behaviour and can lead to an unexpected
- * TRCTRAP.
- */
- for (i = 0, mask1 = 0x3<<16, mask2 = 0x2<<16; i < 8;
- i++, mask1 <<= 2, mask2 <<= 2)
- if ((dbregs->dr[7] & mask1) == mask2)
- return (EINVAL);
-
- pcb = td->td_pcb;
-
- /*
- * Don't let a process set a breakpoint that is not within the
- * process's address space. If a process could do this, it
- * could halt the system by setting a breakpoint in the kernel
- * (if ddb was enabled). Thus, we need to check to make sure
- * that no breakpoints are being enabled for addresses outside
- * process's address space, unless, perhaps, we were called by
- * uid 0.
- *
- * XXX - what about when the watched area of the user's
- * address space is written into from within the kernel
- * ... wouldn't that still cause a breakpoint to be generated
- * from within kernel mode?
- */
-
- if (suser(td) != 0) {
- if (dbregs->dr[7] & 0x3) {
- /* dr0 is enabled */
- if (dbregs->dr[0] >= VM_MAXUSER_ADDRESS)
- return (EINVAL);
- }
-
- if (dbregs->dr[7] & (0x3<<2)) {
- /* dr1 is enabled */
- if (dbregs->dr[1] >= VM_MAXUSER_ADDRESS)
- return (EINVAL);
- }
-
- if (dbregs->dr[7] & (0x3<<4)) {
- /* dr2 is enabled */
- if (dbregs->dr[2] >= VM_MAXUSER_ADDRESS)
- return (EINVAL);
- }
-
- if (dbregs->dr[7] & (0x3<<6)) {
- /* dr3 is enabled */
- if (dbregs->dr[3] >= VM_MAXUSER_ADDRESS)
- return (EINVAL);
- }
- }
-
- pcb->pcb_dr0 = dbregs->dr[0];
- pcb->pcb_dr1 = dbregs->dr[1];
- pcb->pcb_dr2 = dbregs->dr[2];
- pcb->pcb_dr3 = dbregs->dr[3];
- pcb->pcb_dr6 = dbregs->dr[6];
- pcb->pcb_dr7 = dbregs->dr[7];
-
- pcb->pcb_flags |= PCB_DBREGS;
- }
return (0);
}
-/*
- * Return > 0 if a hardware breakpoint has been hit, and the
- * breakpoint was in user space. Return 0, otherwise.
- */
-int
-user_dbreg_trap(void)
-{
- u_int32_t dr7, dr6; /* debug registers dr6 and dr7 */
- u_int32_t bp; /* breakpoint bits extracted from dr6 */
- int nbp; /* number of breakpoints that triggered */
- caddr_t addr[4]; /* breakpoint addresses */
- int i;
-
- dr7 = rdr7();
- if ((dr7 & 0x000000ff) == 0) {
- /*
- * all GE and LE bits in the dr7 register are zero,
- * thus the trap couldn't have been caused by the
- * hardware debug registers
- */
- return 0;
- }
-
- nbp = 0;
- dr6 = rdr6();
- bp = dr6 & 0x0000000f;
-
- if (!bp) {
- /*
- * None of the breakpoint bits are set meaning this
- * trap was not caused by any of the debug registers
- */
- return 0;
- }
-
- /*
- * at least one of the breakpoints were hit, check to see
- * which ones and if any of them are user space addresses
- */
-
- if (bp & 0x01) {
- addr[nbp++] = (caddr_t)rdr0();
- }
- if (bp & 0x02) {
- addr[nbp++] = (caddr_t)rdr1();
- }
- if (bp & 0x04) {
- addr[nbp++] = (caddr_t)rdr2();
- }
- if (bp & 0x08) {
- addr[nbp++] = (caddr_t)rdr3();
- }
-
- for (i=0; i<nbp; i++) {
- if (addr[i] <
- (caddr_t)VM_MAXUSER_ADDRESS) {
- /*
- * addr[i] is in user space
- */
- return nbp;
- }
- }
-
- /*
- * None of the breakpoints are in user space.
- */
- return 0;
-}
-
-
#ifndef DDB
void
Debugger(const char *msg)
@@ -2776,3 +1694,64 @@ outb(u_int port, u_char data)
}
#endif /* DDB */
+
+void
+bcopy(const void *src, void *dest, size_t len)
+{
+ const char *csrc;
+ char *cdest;
+ size_t i;
+
+ csrc = (const char *)src;
+ cdest = (char *)dest;
+ if (src < dest) {
+ for (i = len - 1; i != (size_t)-1; i--)
+ cdest[i] = csrc[i];
+ } else {
+ for (i = 0; i < len; i++)
+ cdest[i] = csrc[i];
+ }
+}
+
+void *
+memcpy(void *dest, const void *src, size_t len)
+{
+
+ bcopy(src, dest, len);
+ return dest;
+}
+
+void
+bzero(void *buf, size_t len)
+{
+ char *cbuf;
+ size_t i;
+
+ cbuf = (char *)buf;
+ for (i = 0; i < len; i++)
+ cbuf[i] = 0;
+}
+
+void
+pagezero(void *buf)
+{
+
+ bzero(buf, PAGE_SIZE);
+}
+
+int
+bcmp(const void *s1, const void *s2, size_t len)
+{
+ const char *cs1, *cs2;
+ int diff;
+ size_t i;
+
+ cs1 = (const char *)s1;
+ cs2 = (const char *)s2;
+ for (i = 0; i < len; i++) {
+ diff = cs2[i] - cs1[i];
+ if (diff)
+ return diff;
+ }
+ return 0;
+}
diff --git a/sys/amd64/amd64/mem.c b/sys/amd64/amd64/mem.c
index 8ec934f0f40e..38a6e13a09e6 100644
--- a/sys/amd64/amd64/mem.c
+++ b/sys/amd64/amd64/mem.c
@@ -98,7 +98,7 @@ mmclose(dev_t dev, int flags, int fmt, struct thread *td)
{
switch (minor(dev)) {
case 14:
- td->td_frame->tf_eflags &= ~PSL_IOPL;
+ td->td_frame->tf_rflags &= ~PSL_IOPL;
}
return (0);
}
@@ -124,7 +124,7 @@ mmopen(dev_t dev, int flags, int fmt, struct thread *td)
error = securelevel_gt(td->td_ucred, 0);
if (error != 0)
return (error);
- td->td_frame->tf_eflags |= PSL_IOPL;
+ td->td_frame->tf_rflags |= PSL_IOPL;
break;
}
return (0);
@@ -135,7 +135,7 @@ static int
mmrw(dev_t dev, struct uio *uio, int flags)
{
int o;
- u_int c = 0, v;
+ u_long c = 0, v;
struct iovec *iov;
int error = 0;
vm_offset_t addr, eaddr;
@@ -159,7 +159,7 @@ mmrw(dev_t dev, struct uio *uio, int flags)
v &= ~PAGE_MASK;
pmap_kenter((vm_offset_t)ptvmmap, v);
o = (int)uio->uio_offset & PAGE_MASK;
- c = (u_int)(PAGE_SIZE - ((int)iov->iov_base & PAGE_MASK));
+ c = (u_long)(PAGE_SIZE - ((long)iov->iov_base & PAGE_MASK));
c = min(c, (u_int)(PAGE_SIZE - o));
c = min(c, (u_int)iov->iov_len);
error = uiomove((caddr_t)&ptvmmap[o], (int)c, uio);
@@ -177,17 +177,17 @@ mmrw(dev_t dev, struct uio *uio, int flags)
addr = trunc_page(uio->uio_offset);
eaddr = round_page(uio->uio_offset + c);
- if (addr < (vm_offset_t)VADDR(PTDPTDI, 0))
+ if (addr < (vm_offset_t)VADDR(0, 0, PTDPTDI, 0))
return (EFAULT);
for (; addr < eaddr; addr += PAGE_SIZE)
if (pmap_extract(kernel_pmap, addr) == 0)
return (EFAULT);
- if (!kernacc((caddr_t)(int)uio->uio_offset, c,
+ if (!kernacc((caddr_t)(long)uio->uio_offset, c,
uio->uio_rw == UIO_READ ?
VM_PROT_READ : VM_PROT_WRITE))
return (EFAULT);
- error = uiomove((caddr_t)(int)uio->uio_offset, (int)c, uio);
+ error = uiomove((caddr_t)(long)uio->uio_offset, (int)c, uio);
continue;
default:
@@ -317,15 +317,6 @@ mem_range_attr_set(struct mem_range_desc *mrd, int *arg)
return (mem_range_softc.mr_op->set(&mem_range_softc, mrd, arg));
}
-#ifdef SMP
-void
-mem_range_AP_init(void)
-{
- if (mem_range_softc.mr_op && mem_range_softc.mr_op->initAP)
- (mem_range_softc.mr_op->initAP(&mem_range_softc));
-}
-#endif
-
static int
mem_modevent(module_t mod, int type, void *data)
{
diff --git a/sys/amd64/amd64/nexus.c b/sys/amd64/amd64/nexus.c
index 389422250c2f..07d117ef3648 100644
--- a/sys/amd64/amd64/nexus.c
+++ b/sys/amd64/amd64/nexus.c
@@ -58,21 +58,13 @@
#include <machine/pmap.h>
#include <machine/resource.h>
-#ifdef APIC_IO
-#include <machine/smp.h>
-#include <machine/mpapic.h>
-#endif
#ifdef DEV_ISA
#include <isa/isavar.h>
-#ifdef PC98
-#include <pc98/pc98/pc98.h>
-#else
-#include <i386/isa/isa.h>
-#endif
+#include <amd64/isa/isa.h>
#endif
-#include <i386/isa/icu.h>
-#include <i386/isa/intr_machdep.h>
+#include <amd64/isa/icu.h>
+#include <amd64/isa/intr_machdep.h>
#include <sys/rtprio.h>
static MALLOC_DEFINE(M_NEXUSDEV, "nexusdev", "Nexus device");
@@ -165,16 +157,12 @@ nexus_probe(device_t dev)
* APIC interrupts are global though.
*
* XXX We depend on the AT PIC driver correctly claiming IRQ 2
- * to prevent its reuse elsewhere in the !APIC_IO case.
+ * to prevent its reuse elsewhere.
*/
irq_rman.rm_start = 0;
irq_rman.rm_type = RMAN_ARRAY;
irq_rman.rm_descr = "Interrupt request lines";
-#ifdef APIC_IO
- irq_rman.rm_end = APIC_INTMAPSIZE - 1;
-#else
irq_rman.rm_end = 15;
-#endif
if (rman_init(&irq_rman)
|| rman_manage_region(&irq_rman,
irq_rman.rm_start, irq_rman.rm_end))
@@ -186,11 +174,7 @@ nexus_probe(device_t dev)
* multiple bridges. (eg: laptops with docking stations)
*/
drq_rman.rm_start = 0;
-#ifdef PC98
- drq_rman.rm_end = 3;
-#else
drq_rman.rm_end = 7;
-#endif
drq_rman.rm_type = RMAN_ARRAY;
drq_rman.rm_descr = "DMA request lines";
/* XXX drq 0 not available on some machines */
@@ -342,28 +326,11 @@ nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
rman_set_bustag(rv, I386_BUS_SPACE_MEM);
} else if (type == SYS_RES_IOPORT) {
rman_set_bustag(rv, I386_BUS_SPACE_IO);
-#ifndef PC98
rman_set_bushandle(rv, rv->r_start);
-#endif
}
-#ifdef PC98
- if ((type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) &&
- i386_bus_space_handle_alloc(rv->r_bustag, rv->r_start, count,
- &rv->r_bushandle) != 0) {
- rman_release_resource(rv);
- return 0;
- }
-#endif
-
if (needactivate) {
if (bus_activate_resource(child, type, *rid, rv)) {
-#ifdef PC98
- if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
- i386_bus_space_handle_free(rv->r_bustag,
- rv->r_bushandle, rv->r_bushandle->bsh_sz);
- }
-#endif
rman_release_resource(rv);
return 0;
}
@@ -399,13 +366,7 @@ nexus_activate_resource(device_t bus, device_t child, int type, int rid,
vaddr = (caddr_t) pmap_mapdev(paddr-poffs, psize+poffs) + poffs;
}
rman_set_virtual(r, vaddr);
-#ifdef PC98
- /* PC-98: the type of bus_space_handle_t is the structure. */
- r->r_bushandle->bsh_base = (bus_addr_t) vaddr;
-#else
- /* IBM-PC: the type of bus_space_handle_t is u_int */
rman_set_bushandle(r, (bus_space_handle_t) vaddr);
-#endif
}
return (rman_activate_resource(r));
}
@@ -437,12 +398,6 @@ nexus_release_resource(device_t bus, device_t child, int type, int rid,
if (error)
return error;
}
-#ifdef PC98
- if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
- i386_bus_space_handle_free(r->r_bustag, r->r_bushandle,
- r->r_bushandle->bsh_sz);
- }
-#endif
return (rman_release_resource(r));
}
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index 037dafbe4fce..20bc3f0c52a6 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -99,10 +99,8 @@
* and to when physical maps must be made correct.
*/
-#include "opt_pmap.h"
#include "opt_msgbuf.h"
#include "opt_kstack_pages.h"
-#include "opt_swtch.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -116,9 +114,6 @@
#include <sys/user.h>
#include <sys/vmmeter.h>
#include <sys/sysctl.h>
-#ifdef SMP
-#include <sys/smp.h>
-#endif
#include <vm/vm.h>
#include <vm/vm_param.h>
@@ -135,12 +130,6 @@
#include <machine/cputypes.h>
#include <machine/md_var.h>
#include <machine/specialreg.h>
-#if defined(SMP) || defined(APIC_IO)
-#include <machine/smp.h>
-#include <machine/apic.h>
-#include <machine/segments.h>
-#include <machine/tss.h>
-#endif /* SMP || APIC_IO */
#define PMAP_KEEP_PDIRS
#ifndef PMAP_SHPGPERPROC
@@ -185,25 +174,15 @@ struct pmap kernel_pmap_store;
LIST_HEAD(pmaplist, pmap);
static struct pmaplist allpmaps;
static struct mtx allpmaps_lock;
-#if defined(SMP) && defined(LAZY_SWITCH)
-static struct mtx lazypmap_lock;
-#endif
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) */
static boolean_t pmap_initialized = FALSE; /* Has pmap_init completed? */
-static int pgeflag; /* PG_G or-in */
-static int pseflag; /* PG_PS or-in */
static int nkpt;
vm_offset_t kernel_vm_end;
-extern u_int32_t KERNend;
-
-#ifdef PAE
-static uma_zone_t pdptzone;
-#endif
/*
* Data for the pv entry allocation mechanism
@@ -230,9 +209,6 @@ struct msgbuf *msgbufp = 0;
static pt_entry_t *pt_crashdumpmap;
static caddr_t crashdumpmap;
-#ifdef SMP
-extern pt_entry_t *SMPpt;
-#endif
static pt_entry_t *PMAP1 = 0;
static pt_entry_t *PADDR1 = 0;
@@ -257,19 +233,14 @@ static vm_page_t pmap_page_lookup(vm_object_t object, vm_pindex_t pindex);
static int pmap_unuse_pt(pmap_t, vm_offset_t, vm_page_t);
static vm_offset_t pmap_kmem_choose(vm_offset_t addr);
static void *pmap_pv_allocf(uma_zone_t zone, int bytes, u_int8_t *flags, int wait);
-#ifdef PAE
-static void *pmap_pdpt_allocf(uma_zone_t zone, int bytes, u_int8_t *flags, int wait);
-#endif
-
-static pd_entry_t pdir4mb;
CTASSERT(1 << PDESHIFT == sizeof(pd_entry_t));
CTASSERT(1 << PTESHIFT == sizeof(pt_entry_t));
/*
* Move the kernel virtual free pointer to the next
- * 4MB. This is used to help improve performance
- * by using a large (4MB) page for much of the kernel
+ * 2MB. This is used to help improve performance
+ * by using a large (2MB) page for much of the kernel
* (.text, .data, .bss)
*/
static vm_offset_t
@@ -277,17 +248,7 @@ pmap_kmem_choose(vm_offset_t addr)
{
vm_offset_t newaddr = addr;
-#ifdef I686_CPU_not /* Problem seems to have gone away */
- /* Deal with un-resolved Pentium4 issues */
- if (cpu_class == CPUCLASS_686 &&
- strcmp(cpu_vendor, "GenuineIntel") == 0 &&
- (cpu_id & 0xf00) == 0xf00)
- return newaddr;
-#endif
-#ifndef DISABLE_PSE
- if (cpu_feature & CPUID_PSE)
- newaddr = (addr + (NBPDR - 1)) & ~(NBPDR - 1);
-#endif
+ newaddr = (addr + (NBPDR - 1)) & ~(NBPDR - 1);
return newaddr;
}
@@ -333,16 +294,12 @@ pmap_bootstrap(firstaddr, loadaddr)
/*
* Initialize the kernel pmap (which is statically allocated).
*/
- kernel_pmap->pm_pdir = (pd_entry_t *) (KERNBASE + (u_int)IdlePTD);
-#ifdef PAE
- kernel_pmap->pm_pdpt = (pdpt_entry_t *) (KERNBASE + (u_int)IdlePDPT);
-#endif
+ kernel_pmap->pm_pdir = (pd_entry_t *) (KERNBASE + IdlePTD);
+ kernel_pmap->pm_pdp = (pdp_entry_t *) (KERNBASE + IdlePDP);
+ kernel_pmap->pm_pml4 = (pdp_entry_t *) (KERNBASE + IdlePML4);
kernel_pmap->pm_active = -1; /* don't allow deactivation */
TAILQ_INIT(&kernel_pmap->pm_pvlist);
LIST_INIT(&allpmaps);
-#if defined(SMP) && defined(LAZY_SWITCH)
- mtx_init(&lazypmap_lock, "lazypmap", NULL, MTX_SPIN);
-#endif
mtx_init(&allpmaps_lock, "allpmaps", NULL, MTX_SPIN);
mtx_lock_spin(&allpmaps_lock);
LIST_INSERT_HEAD(&allpmaps, kernel_pmap, pm_list);
@@ -398,128 +355,9 @@ pmap_bootstrap(firstaddr, loadaddr)
for (i = 0; i < NKPT; i++)
PTD[i] = 0;
- pgeflag = 0;
-#ifndef DISABLE_PG_G
- if (cpu_feature & CPUID_PGE)
- pgeflag = PG_G;
-#endif
-#ifdef I686_CPU_not /* Problem seems to have gone away */
- /* Deal with un-resolved Pentium4 issues */
- if (cpu_class == CPUCLASS_686 &&
- strcmp(cpu_vendor, "GenuineIntel") == 0 &&
- (cpu_id & 0xf00) == 0xf00) {
- printf("Warning: Pentium 4 cpu: PG_G disabled (global flag)\n");
- pgeflag = 0;
- }
-#endif
-
-/*
- * Initialize the 4MB page size flag
- */
- pseflag = 0;
-/*
- * The 4MB page version of the initial
- * kernel page mapping.
- */
- pdir4mb = 0;
-
-#ifndef DISABLE_PSE
- if (cpu_feature & CPUID_PSE)
- pseflag = PG_PS;
-#endif
-#ifdef I686_CPU_not /* Problem seems to have gone away */
- /* Deal with un-resolved Pentium4 issues */
- if (cpu_class == CPUCLASS_686 &&
- strcmp(cpu_vendor, "GenuineIntel") == 0 &&
- (cpu_id & 0xf00) == 0xf00) {
- printf("Warning: Pentium 4 cpu: PG_PS disabled (4MB pages)\n");
- pseflag = 0;
- }
-#endif
-#ifndef DISABLE_PSE
- if (pseflag) {
- pd_entry_t ptditmp;
- /*
- * Note that we have enabled PSE mode
- */
- ptditmp = *(PTmap + i386_btop(KERNBASE));
- ptditmp &= ~(NBPDR - 1);
- ptditmp |= PG_V | PG_RW | PG_PS | PG_U | pgeflag;
- pdir4mb = ptditmp;
- }
-#endif
-#ifndef SMP
- /*
- * Turn on PGE/PSE. SMP does this later on since the
- * 4K page tables are required for AP boot (for now).
- * XXX fixme.
- */
- pmap_set_opt();
-#endif
-#ifdef SMP
- if (cpu_apic_address == 0)
- panic("pmap_bootstrap: no local apic! (non-SMP hardware?)");
-
- /* local apic is mapped on last page */
- SMPpt[NPTEPG - 1] = (pt_entry_t)(PG_V | PG_RW | PG_N | pgeflag |
- (cpu_apic_address & PG_FRAME));
-#endif
invltlb();
}
-/*
- * Enable 4MB page mode for MP startup. Turn on PG_G support.
- * BSP will run this after all the AP's have started up.
- */
-void
-pmap_set_opt(void)
-{
- pt_entry_t *pte;
- vm_offset_t va, endva;
-
- if (pgeflag && (cpu_feature & CPUID_PGE)) {
- load_cr4(rcr4() | CR4_PGE);
- invltlb(); /* Insurance */
- }
-#ifndef DISABLE_PSE
- if (pseflag && (cpu_feature & CPUID_PSE)) {
- load_cr4(rcr4() | CR4_PSE);
- invltlb(); /* Insurance */
- }
-#endif
- if (PCPU_GET(cpuid) == 0) {
-#ifndef DISABLE_PSE
- if (pdir4mb) {
- kernel_pmap->pm_pdir[KPTDI] = PTD[KPTDI] = pdir4mb;
- invltlb(); /* Insurance */
- }
-#endif
- if (pgeflag) {
- /* Turn on PG_G for text, data, bss pages. */
- va = (vm_offset_t)btext;
-#ifndef DISABLE_PSE
- if (pseflag && (cpu_feature & CPUID_PSE)) {
- if (va < KERNBASE + (1 << PDRSHIFT))
- va = KERNBASE + (1 << PDRSHIFT);
- }
-#endif
- endva = KERNBASE + KERNend;
- while (va < endva) {
- pte = vtopte(va);
- if (*pte)
- *pte |= pgeflag;
- va += PAGE_SIZE;
- }
- invltlb(); /* Insurance */
- }
- /*
- * We do not need to broadcast the invltlb here, because
- * each AP does it the moment it is released from the boot
- * lock. See ap_init().
- */
- }
-}
-
static void *
pmap_pv_allocf(uma_zone_t zone, int bytes, u_int8_t *flags, int wait)
{
@@ -527,15 +365,6 @@ pmap_pv_allocf(uma_zone_t zone, int bytes, u_int8_t *flags, int wait)
return (void *)kmem_alloc(kernel_map, bytes);
}
-#ifdef PAE
-static void *
-pmap_pdpt_allocf(uma_zone_t zone, int bytes, u_int8_t *flags, int wait)
-{
- *flags = UMA_SLAB_PRIV;
- return (contigmalloc(PAGE_SIZE, NULL, 0, 0x0ULL, 0xffffffffULL, 1, 0));
-}
-#endif
-
/*
* Initialize the pmap module.
* Called by vm_init, to initialize any structures that the pmap
@@ -574,12 +403,6 @@ pmap_init(phys_start, phys_end)
uma_zone_set_allocf(pvzone, pmap_pv_allocf);
uma_prealloc(pvzone, initial_pvs);
-#ifdef PAE
- pdptzone = uma_zcreate("PDPT", NPGPTD * sizeof(pdpt_entry_t), NULL,
- NULL, NULL, NULL, (NPGPTD * sizeof(pdpt_entry_t)) - 1, 0);
- uma_zone_set_allocf(pdptzone, pmap_pdpt_allocf);
-#endif
-
/*
* Now it is safe to enable pv_table recording.
*/
@@ -642,125 +465,8 @@ pmap_track_modified(vm_offset_t va)
return 0;
}
-#ifdef I386_CPU
-/*
- * i386 only has "invalidate everything" and no SMP to worry about.
- */
-PMAP_INLINE void
-pmap_invalidate_page(pmap_t pmap, vm_offset_t va)
-{
-
- if (pmap == kernel_pmap || pmap->pm_active)
- invltlb();
-}
-
-PMAP_INLINE void
-pmap_invalidate_range(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
-{
-
- if (pmap == kernel_pmap || pmap->pm_active)
- invltlb();
-}
-
-PMAP_INLINE void
-pmap_invalidate_all(pmap_t pmap)
-{
-
- if (pmap == kernel_pmap || pmap->pm_active)
- invltlb();
-}
-#else /* !I386_CPU */
-#ifdef SMP
/*
- * For SMP, these functions have to use the IPI mechanism for coherence.
- */
-void
-pmap_invalidate_page(pmap_t pmap, vm_offset_t va)
-{
- u_int cpumask;
- u_int other_cpus;
-
- 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
- */
- if (pmap->pm_active == -1 || pmap->pm_active == all_cpus) {
- invlpg(va);
- smp_invlpg(va);
- } else {
- cpumask = PCPU_GET(cpumask);
- other_cpus = PCPU_GET(other_cpus);
- if (pmap->pm_active & cpumask)
- invlpg(va);
- if (pmap->pm_active & other_cpus)
- smp_masked_invlpg(pmap->pm_active & other_cpus, va);
- }
- critical_exit();
-}
-
-void
-pmap_invalidate_range(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
-{
- u_int cpumask;
- u_int other_cpus;
- vm_offset_t addr;
-
- 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
- */
- if (pmap->pm_active == -1 || pmap->pm_active == all_cpus) {
- for (addr = sva; addr < eva; addr += PAGE_SIZE)
- invlpg(addr);
- smp_invlpg_range(sva, eva);
- } else {
- cpumask = PCPU_GET(cpumask);
- other_cpus = PCPU_GET(other_cpus);
- if (pmap->pm_active & cpumask)
- for (addr = sva; addr < eva; addr += PAGE_SIZE)
- invlpg(addr);
- if (pmap->pm_active & other_cpus)
- smp_masked_invlpg_range(pmap->pm_active & other_cpus,
- sva, eva);
- }
- critical_exit();
-}
-
-void
-pmap_invalidate_all(pmap_t pmap)
-{
- u_int cpumask;
- u_int other_cpus;
-
-#ifdef SWTCH_OPTIM_STATS
- tlb_flush_count++;
-#endif
- 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
- */
- if (pmap->pm_active == -1 || pmap->pm_active == all_cpus) {
- invltlb();
- smp_invltlb();
- } else {
- cpumask = PCPU_GET(cpumask);
- other_cpus = PCPU_GET(other_cpus);
- if (pmap->pm_active & cpumask)
- invltlb();
- if (pmap->pm_active & other_cpus)
- smp_masked_invltlb(pmap->pm_active & other_cpus);
- }
- critical_exit();
-}
-#else /* !SMP */
-/*
- * Normal, non-SMP, 486+ invalidation functions.
+ * Normal invalidation functions.
* We inline these within pmap.c for speed.
*/
PMAP_INLINE void
@@ -788,8 +494,6 @@ pmap_invalidate_all(pmap_t pmap)
if (pmap == kernel_pmap || pmap->pm_active)
invltlb();
}
-#endif /* !SMP */
-#endif /* !I386_CPU */
/*
* Are we current address space or kernel?
@@ -828,7 +532,7 @@ pmap_pte_quick(pmap, va)
*PMAP1 = newpf | PG_RW | PG_V;
pmap_invalidate_page(kernel_pmap, (vm_offset_t)PADDR1);
}
- return PADDR1 + (i386_btop(va) & (NPTEPG - 1));
+ return PADDR1 + (amd64_btop(va) & (NPTEPG - 1));
}
return (0);
}
@@ -878,7 +582,7 @@ pmap_kenter(vm_offset_t va, vm_paddr_t pa)
pt_entry_t *pte;
pte = vtopte(va);
- pte_store(pte, pa | PG_RW | PG_V | pgeflag);
+ pte_store(pte, pa | PG_RW | PG_V | PG_G);
}
/*
@@ -1213,7 +917,7 @@ _pmap_unwire_pte_hold(pmap_t pmap, vm_page_t m)
* Do an invltlb to make the invalidated mapping
* take effect immediately.
*/
- pteva = VM_MAXUSER_ADDRESS + i386_ptob(m->pindex);
+ pteva = VM_MAXUSER_ADDRESS + amd64_ptob(m->pindex);
pmap_invalidate_page(pmap, pteva);
}
@@ -1272,10 +976,9 @@ pmap_pinit0(pmap)
struct pmap *pmap;
{
- pmap->pm_pdir = (pd_entry_t *)(KERNBASE + (vm_offset_t)IdlePTD);
-#ifdef PAE
- pmap->pm_pdpt = (pdpt_entry_t *)(KERNBASE + (vm_offset_t)IdlePDPT);
-#endif
+ pmap->pm_pdir = (pd_entry_t *)(KERNBASE + IdlePTD);
+ pmap->pm_pdp = (pdp_entry_t *)(KERNBASE + IdlePDP);
+ pmap->pm_pml4 = (pml4_entry_t *)(KERNBASE + IdlePML4);
pmap->pm_active = 0;
TAILQ_INIT(&pmap->pm_pvlist);
bzero(&pmap->pm_stats, sizeof pmap->pm_stats);
@@ -1293,6 +996,8 @@ pmap_pinit(pmap)
register struct pmap *pmap;
{
vm_page_t ptdpg[NPGPTD];
+ vm_page_t pdppg;
+ vm_page_t pml4pg;
vm_paddr_t pa;
int i;
@@ -1303,14 +1008,10 @@ pmap_pinit(pmap)
if (pmap->pm_pdir == NULL) {
pmap->pm_pdir = (pd_entry_t *)kmem_alloc_pageable(kernel_map,
NBPTD);
-#ifdef PAE
- pmap->pm_pdpt = uma_zalloc(pdptzone, M_WAITOK | M_ZERO);
- KASSERT(((vm_offset_t)pmap->pm_pdpt &
- ((NPGPTD * sizeof(pdpt_entry_t)) - 1)) == 0,
- ("pmap_pinit: pdpt misaligned"));
- KASSERT(pmap_kextract((vm_offset_t)pmap->pm_pdpt) < (4ULL<<30),
- ("pmap_pinit: pdpt above 4g"));
-#endif
+ pmap->pm_pdp = (pdp_entry_t *)kmem_alloc_pageable(kernel_map,
+ PAGE_SIZE);
+ pmap->pm_pml4 = (pml4_entry_t *)kmem_alloc_pageable(kernel_map,
+ PAGE_SIZE);
}
/*
@@ -1318,7 +1019,7 @@ pmap_pinit(pmap)
*/
if (pmap->pm_pteobj == NULL)
pmap->pm_pteobj = vm_object_allocate(OBJT_DEFAULT, PTDPTDI +
- NPGPTD);
+ NPGPTD + 2);
/*
* allocate the page directory page(s)
@@ -1333,31 +1034,51 @@ pmap_pinit(pmap)
vm_page_unlock_queues();
}
+ pml4pg = vm_page_grab(pmap->pm_pteobj, PTDPTDI + NPGPTD,
+ VM_ALLOC_NORMAL | VM_ALLOC_RETRY | VM_ALLOC_WIRED | VM_ALLOC_ZERO);
+ vm_page_lock_queues();
+ vm_page_flag_clear(pml4pg, PG_BUSY);
+ pml4pg->valid = VM_PAGE_BITS_ALL;
+ vm_page_unlock_queues();
+
+ pdppg = vm_page_grab(pmap->pm_pteobj, PTDPTDI + NPGPTD + 1,
+ VM_ALLOC_NORMAL | VM_ALLOC_RETRY | VM_ALLOC_WIRED | VM_ALLOC_ZERO);
+ vm_page_lock_queues();
+ vm_page_flag_clear(pdppg, PG_BUSY);
+ pdppg->valid = VM_PAGE_BITS_ALL;
+ vm_page_unlock_queues();
+
pmap_qenter((vm_offset_t)pmap->pm_pdir, ptdpg, NPGPTD);
+ pmap_qenter((vm_offset_t)pmap->pm_pdp, &pdppg, 1);
+ pmap_qenter((vm_offset_t)pmap->pm_pml4, &pml4pg, 1);
for (i = 0; i < NPGPTD; i++) {
if ((ptdpg[i]->flags & PG_ZERO) == 0)
bzero(pmap->pm_pdir + (i * NPDEPG), PAGE_SIZE);
}
+ if ((pdppg->flags & PG_ZERO) == 0)
+ bzero(pmap->pm_pdp, PAGE_SIZE);
+ if ((pml4pg->flags & PG_ZERO) == 0)
+ bzero(pmap->pm_pml4, PAGE_SIZE);
mtx_lock_spin(&allpmaps_lock);
LIST_INSERT_HEAD(&allpmaps, pmap, pm_list);
mtx_unlock_spin(&allpmaps_lock);
/* Wire in kernel global address entries. */
- /* XXX copies current process, does not fill in MPPTDI */
bcopy(PTD + KPTDI, pmap->pm_pdir + KPTDI, nkpt * sizeof(pd_entry_t));
-#ifdef SMP
- pmap->pm_pdir[MPPTDI] = PTD[MPPTDI];
-#endif
/* install self-referential address mapping entry(s) */
for (i = 0; i < NPGPTD; i++) {
pa = VM_PAGE_TO_PHYS(ptdpg[i]);
pmap->pm_pdir[PTDPTDI + i] = pa | PG_V | PG_RW | PG_A | PG_M;
-#ifdef PAE
- pmap->pm_pdpt[i] = pa | PG_V;
-#endif
}
+ /* Connect ptd pages to pdp */
+ for (i = 0; i < NPGPTD; i++) {
+ pa = VM_PAGE_TO_PHYS(ptdpg[i]);
+ pmap->pm_pdp[i] = pa | PG_RW | PG_V | PG_U;
+ }
+ /* connect pdp to pml4 */
+ pmap->pm_pml4[0] = VM_PAGE_TO_PHYS(pdppg) | PG_RW | PG_V | PG_U;
pmap->pm_active = 0;
TAILQ_INIT(&pmap->pm_pvlist);
@@ -1422,7 +1143,7 @@ _pmap_allocpte(pmap, ptepindex)
*/
if ((m->flags & PG_ZERO) == 0) {
if (pmap_is_current(pmap)) {
- pteva = VM_MAXUSER_ADDRESS + i386_ptob(ptepindex);
+ pteva = VM_MAXUSER_ADDRESS + amd64_ptob(ptepindex);
bzero((caddr_t) pteva, PAGE_SIZE);
} else {
pmap_zero_page(m);
@@ -1455,7 +1176,7 @@ pmap_allocpte(pmap_t pmap, vm_offset_t va)
ptepa = pmap->pm_pdir[ptepindex];
/*
- * This supports switching from a 4MB page to a
+ * This supports switching from a 2MB page to a
* normal 4K page.
*/
if (ptepa & PG_PS) {
@@ -1493,121 +1214,6 @@ pmap_allocpte(pmap_t pmap, vm_offset_t va)
* Pmap allocation/deallocation routines.
***************************************************/
-#ifdef LAZY_SWITCH
-#ifdef SMP
-/*
- * Deal with a SMP shootdown of other users of the pmap that we are
- * trying to dispose of. This can be a bit hairy.
- */
-static u_int *lazymask;
-static u_int lazyptd;
-static volatile u_int lazywait;
-
-void pmap_lazyfix_action(void);
-
-void
-pmap_lazyfix_action(void)
-{
- u_int mymask = PCPU_GET(cpumask);
-
- if (rcr3() == lazyptd) {
- load_cr3(PCPU_GET(curpcb)->pcb_cr3);
-#ifdef SWTCH_OPTIM_STATS
- atomic_add_int(&lazy_flush_smpfixup, 1);
- } else {
- if (*lazymask & mymask)
- lazy_flush_smpbadcr3++;
- else
- lazy_flush_smpmiss++;
-#endif
- }
- atomic_clear_int(lazymask, mymask);
- atomic_store_rel_int(&lazywait, 1);
-}
-
-static void
-pmap_lazyfix_self(u_int mymask)
-{
-
- if (rcr3() == lazyptd) {
- load_cr3(PCPU_GET(curpcb)->pcb_cr3);
-#ifdef SWTCH_OPTIM_STATS
- lazy_flush_fixup++;
- } else {
- if (*lazymask & mymask)
- lazy_flush_smpbadcr3++;
- else
- lazy_flush_smpmiss++;
-#endif
- }
- atomic_clear_int(lazymask, mymask);
-}
-
-
-static void
-pmap_lazyfix(pmap_t pmap)
-{
- u_int mymask = PCPU_GET(cpumask);
- u_int mask;
- register u_int spins;
-
- while ((mask = pmap->pm_active) != 0) {
- spins = 50000000;
- mask = mask & -mask; /* Find least significant set bit */
- mtx_lock_spin(&lazypmap_lock);
-#ifdef PAE
- lazyptd = vtophys(pmap->pm_pdpt);
-#else
- lazyptd = vtophys(pmap->pm_pdir);
-#endif
- if (mask == mymask) {
- lazymask = &pmap->pm_active;
- pmap_lazyfix_self(mymask);
- } else {
- atomic_store_rel_int((u_int *)&lazymask,
- (u_int)&pmap->pm_active);
- atomic_store_rel_int(&lazywait, 0);
- ipi_selected(mask, IPI_LAZYPMAP);
- while (lazywait == 0) {
- ia32_pause();
- if (--spins == 0)
- break;
- }
-#ifdef SWTCH_OPTIM_STATS
- lazy_flush_smpipi++;
-#endif
- }
- mtx_unlock_spin(&lazypmap_lock);
- if (spins == 0)
- printf("pmap_lazyfix: spun for 50000000\n");
- }
-}
-
-#else /* SMP */
-
-/*
- * Cleaning up on uniprocessor is easy. For various reasons, we're
- * unlikely to have to even execute this code, including the fact
- * that the cleanup is deferred until the parent does a wait(2), which
- * means that another userland process has run.
- */
-static void
-pmap_lazyfix(pmap_t pmap)
-{
- u_int cr3;
-
- cr3 = vtophys(pmap->pm_pdir);
- if (cr3 == rcr3()) {
- load_cr3(PCPU_GET(curpcb)->pcb_cr3);
- pmap->pm_active &= ~(PCPU_GET(cpumask));
-#ifdef SWTCH_OPTIM_STATS
- lazy_flush_fixup++;
-#endif
- }
-}
-#endif /* SMP */
-#endif /* LAZY_SWITCH */
-
/*
* Release any resources held by the given physical map.
* Called when a pmap initialized by pmap_pinit is being released.
@@ -1629,33 +1235,33 @@ pmap_release(pmap_t pmap)
("pmap_release: pmap resident count %ld != 0",
pmap->pm_stats.resident_count));
-#ifdef LAZY_SWITCH
- pmap_lazyfix(pmap);
-#endif
mtx_lock_spin(&allpmaps_lock);
LIST_REMOVE(pmap, pm_list);
mtx_unlock_spin(&allpmaps_lock);
bzero(pmap->pm_pdir + PTDPTDI, (nkpt + NPGPTD) *
sizeof(*pmap->pm_pdir));
-#ifdef SMP
- pmap->pm_pdir[MPPTDI] = 0;
-#endif
pmap_qremove((vm_offset_t)pmap->pm_pdir, NPGPTD);
vm_page_lock_queues();
for (i = 0; i < NPGPTD; i++) {
m = TAILQ_FIRST(&object->memq);
-#ifdef PAE
- KASSERT(VM_PAGE_TO_PHYS(m) == (pmap->pm_pdpt[i] & PG_FRAME),
+ KASSERT(VM_PAGE_TO_PHYS(m) == (pmap->pm_pdp[i] & PG_FRAME),
("pmap_release: got wrong ptd page"));
-#endif
m->wire_count--;
atomic_subtract_int(&cnt.v_wire_count, 1);
vm_page_busy(m);
vm_page_free_zero(m);
}
+ /* now free pdp and pml4 */
+ for (i = 0; i < 2; i++) {
+ m = TAILQ_FIRST(&object->memq);
+ m->wire_count--;
+ atomic_subtract_int(&cnt.v_wire_count, 1);
+ vm_page_busy(m);
+ vm_page_free(m);
+ }
KASSERT(TAILQ_EMPTY(&object->memq),
("pmap_release: leaking page table pages"));
vm_page_unlock_queues();
@@ -2200,7 +1806,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
opa = origpte & PG_FRAME;
if (origpte & PG_PS)
- panic("pmap_enter: attempted pmap_enter on 4MB page");
+ panic("pmap_enter: attempted pmap_enter on 2MB page");
/*
* Mapping has not changed, must be protection or wiring change.
@@ -2295,7 +1901,7 @@ validate:
if (va < VM_MAXUSER_ADDRESS)
newpte |= PG_U;
if (pmap == kernel_pmap)
- newpte |= pgeflag;
+ newpte |= PG_G;
/*
* if the mapping or permission bits are different, we need
@@ -2353,7 +1959,7 @@ retry:
*/
if (ptepa) {
if (ptepa & PG_PS)
- panic("pmap_enter_quick: unexpected mapping into 4MB page");
+ panic("pmap_enter_quick: unexpected mapping into 2MB page");
if (pmap->pm_pteobj->root &&
(pmap->pm_pteobj->root->pindex == ptepindex)) {
mpte = pmap->pm_pteobj->root;
@@ -2424,11 +2030,7 @@ pmap_kenter_temporary(vm_offset_t pa, int i)
va = (vm_offset_t)crashdumpmap + (i * PAGE_SIZE);
pmap_kenter(va, pa);
-#ifndef I386_CPU
invlpg(va);
-#else
- invltlb();
-#endif
return ((void *)crashdumpmap);
}
@@ -2455,7 +2057,7 @@ pmap_object_init_pt(pmap_t pmap, vm_offset_t addr,
* processor address space. Note that some shortcuts
* are taken, but the code works.
*/
- if (pseflag && (object->type == OBJT_DEVICE) &&
+ if ((object->type == OBJT_DEVICE) &&
((addr & (NBPDR - 1)) == 0) && ((size & (NBPDR - 1)) == 0)) {
int i;
vm_page_t m[1];
@@ -2510,7 +2112,7 @@ retry:
return;
}
- psize = i386_btop(size);
+ psize = amd64_btop(size);
if ((object->type != OBJT_VNODE) ||
((limit & MAP_PREFAULT_PARTIAL) && (psize > MAX_INIT_PT) &&
@@ -2558,7 +2160,7 @@ retry:
vm_page_busy(p);
vm_page_unlock_queues();
mpte = pmap_enter_quick(pmap,
- addr + i386_ptob(tmpidx), p, mpte);
+ addr + amd64_ptob(tmpidx), p, mpte);
vm_page_lock_queues();
vm_page_wakeup(p);
}
@@ -2801,38 +2403,6 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len,
}
}
-#ifdef SMP
-
-/*
- * pmap_zpi_switchin*()
- *
- * These functions allow us to avoid doing IPIs alltogether in certain
- * temporary page-mapping situations (page zeroing). Instead to deal
- * with being preempted and moved onto a different cpu we invalidate
- * the page when the scheduler switches us in. This does not occur
- * very often so we remain relatively optimal with very little effort.
- */
-static void
-pmap_zpi_switchin12(void)
-{
- invlpg((u_int)CADDR1);
- invlpg((u_int)CADDR2);
-}
-
-static void
-pmap_zpi_switchin2(void)
-{
- invlpg((u_int)CADDR2);
-}
-
-static void
-pmap_zpi_switchin3(void)
-{
- invlpg((u_int)CADDR3);
-}
-
-#endif
-
/*
* pmap_zero_page zeros the specified hardware page by mapping
* the page into KVM and using bzero to clear its contents.
@@ -2845,23 +2415,8 @@ pmap_zero_page(vm_page_t m)
if (*CMAP2)
panic("pmap_zero_page: CMAP2 busy");
*CMAP2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | PG_A | PG_M;
-#ifdef I386_CPU
- invltlb();
-#else
-#ifdef SMP
- curthread->td_switchin = pmap_zpi_switchin2;
-#endif
- invlpg((u_int)CADDR2);
-#endif
-#if defined(I686_CPU)
- if (cpu_class == CPUCLASS_686)
- i686_pagezero(CADDR2);
- else
-#endif
- bzero(CADDR2, PAGE_SIZE);
-#ifdef SMP
- curthread->td_switchin = NULL;
-#endif
+ invlpg((u_long)CADDR2);
+ pagezero(CADDR2);
*CMAP2 = 0;
mtx_unlock(&CMAPCADDR12_lock);
}
@@ -2880,23 +2435,11 @@ pmap_zero_page_area(vm_page_t m, int off, int size)
if (*CMAP2)
panic("pmap_zero_page: CMAP2 busy");
*CMAP2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | PG_A | PG_M;
-#ifdef I386_CPU
- invltlb();
-#else
-#ifdef SMP
- curthread->td_switchin = pmap_zpi_switchin2;
-#endif
- invlpg((u_int)CADDR2);
-#endif
-#if defined(I686_CPU)
- if (cpu_class == CPUCLASS_686 && off == 0 && size == PAGE_SIZE)
- i686_pagezero(CADDR2);
+ invlpg((u_long)CADDR2);
+ if (off == 0 && size == PAGE_SIZE)
+ pagezero(CADDR2);
else
-#endif
bzero((char *)CADDR2 + off, size);
-#ifdef SMP
- curthread->td_switchin = NULL;
-#endif
*CMAP2 = 0;
mtx_unlock(&CMAPCADDR12_lock);
}
@@ -2914,23 +2457,8 @@ pmap_zero_page_idle(vm_page_t m)
if (*CMAP3)
panic("pmap_zero_page: CMAP3 busy");
*CMAP3 = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | PG_A | PG_M;
-#ifdef I386_CPU
- invltlb();
-#else
-#ifdef SMP
- curthread->td_switchin = pmap_zpi_switchin3;
-#endif
- invlpg((u_int)CADDR3);
-#endif
-#if defined(I686_CPU)
- if (cpu_class == CPUCLASS_686)
- i686_pagezero(CADDR3);
- else
-#endif
- bzero(CADDR3, PAGE_SIZE);
-#ifdef SMP
- curthread->td_switchin = NULL;
-#endif
+ invlpg((u_long)CADDR3);
+ pagezero(CADDR3);
*CMAP3 = 0;
}
@@ -2951,19 +2479,9 @@ pmap_copy_page(vm_page_t src, vm_page_t dst)
panic("pmap_copy_page: CMAP2 busy");
*CMAP1 = PG_V | VM_PAGE_TO_PHYS(src) | PG_A;
*CMAP2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(dst) | PG_A | PG_M;
-#ifdef I386_CPU
- invltlb();
-#else
-#ifdef SMP
- curthread->td_switchin = pmap_zpi_switchin12;
-#endif
- invlpg((u_int)CADDR1);
- invlpg((u_int)CADDR2);
-#endif
+ invlpg((u_long)CADDR1);
+ invlpg((u_long)CADDR2);
bcopy(CADDR1, CADDR2, PAGE_SIZE);
-#ifdef SMP
- curthread->td_switchin = NULL;
-#endif
*CMAP1 = 0;
*CMAP2 = 0;
mtx_unlock(&CMAPCADDR12_lock);
@@ -3443,20 +2961,12 @@ pmap_activate(struct thread *td)
{
struct proc *p = td->td_proc;
pmap_t pmap;
- u_int32_t cr3;
+ u_int64_t cr3;
critical_enter();
pmap = vmspace_pmap(td->td_proc->p_vmspace);
-#if defined(SMP)
- atomic_set_int(&pmap->pm_active, PCPU_GET(cpumask));
-#else
- pmap->pm_active |= 1;
-#endif
-#ifdef PAE
- cr3 = vtophys(pmap->pm_pdpt);
-#else
- cr3 = vtophys(pmap->pm_pdir);
-#endif
+ pmap->pm_active |= PCPU_GET(cpumask);
+ cr3 = vtophys(pmap->pm_pml4);
/* XXXKSE this is wrong.
* pmap_activate is for the current thread on the current cpu
*/
@@ -3470,9 +2980,6 @@ pmap_activate(struct thread *td)
td->td_pcb->pcb_cr3 = cr3;
}
load_cr3(cr3);
-#ifdef SWTCH_OPTIM_STATS
- tlb_flush_count++;
-#endif
critical_exit();
}
diff --git a/sys/amd64/amd64/sigtramp.S b/sys/amd64/amd64/sigtramp.S
new file mode 100644
index 000000000000..a05ea8587b56
--- /dev/null
+++ b/sys/amd64/amd64/sigtramp.S
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 2003 Peter Wemm <peter@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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/syscall.h>
+
+#include <machine/asmacros.h>
+
+#include "assym.s"
+
+ .text
+/**********************************************************************
+ *
+ * Signal trampoline, copied to top of user stack
+ *
+ */
+NON_GPROF_ENTRY(sigcode)
+ call *SIGF_HANDLER(%rsp) /* call signal handler */
+ lea SIGF_UC(%rsp),%rdi /* get ucontext_t */
+ pushq $0 /* junk to fake return addr. */
+ movq $SYS_sigreturn,%rax
+ syscall /* enter kernel with args */
+0: hlt /* trap priviliged instruction */
+ jmp 0b
+
+ ALIGN_TEXT
+esigcode:
+
+ .data
+ .globl szsigcode
+szsigcode:
+ .long esigcode-sigcode
diff --git a/sys/amd64/amd64/sigtramp.s b/sys/amd64/amd64/sigtramp.s
new file mode 100644
index 000000000000..a05ea8587b56
--- /dev/null
+++ b/sys/amd64/amd64/sigtramp.s
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 2003 Peter Wemm <peter@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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/syscall.h>
+
+#include <machine/asmacros.h>
+
+#include "assym.s"
+
+ .text
+/**********************************************************************
+ *
+ * Signal trampoline, copied to top of user stack
+ *
+ */
+NON_GPROF_ENTRY(sigcode)
+ call *SIGF_HANDLER(%rsp) /* call signal handler */
+ lea SIGF_UC(%rsp),%rdi /* get ucontext_t */
+ pushq $0 /* junk to fake return addr. */
+ movq $SYS_sigreturn,%rax
+ syscall /* enter kernel with args */
+0: hlt /* trap priviliged instruction */
+ jmp 0b
+
+ ALIGN_TEXT
+esigcode:
+
+ .data
+ .globl szsigcode
+szsigcode:
+ .long esigcode-sigcode
diff --git a/sys/amd64/amd64/support.S b/sys/amd64/amd64/support.S
index f0f99e4a7346..06a3c4e6d8f2 100644
--- a/sys/amd64/amd64/support.S
+++ b/sys/amd64/amd64/support.S
@@ -33,8 +33,6 @@
* $FreeBSD$
*/
-#include "opt_npx.h"
-
#include <machine/asmacros.h>
#include <machine/cputypes.h>
#include <machine/pmap.h>
@@ -42,632 +40,20 @@
#include "assym.s"
-#define IDXSHIFT 10
-
- .data
- .globl bcopy_vector
-bcopy_vector:
- .long generic_bcopy
- .globl bzero_vector
-bzero_vector:
- .long generic_bzero
- .globl copyin_vector
-copyin_vector:
- .long generic_copyin
- .globl copyout_vector
-copyout_vector:
- .long generic_copyout
-#if defined(I586_CPU) && defined(DEV_NPX)
-kernel_fpu_lock:
- .byte 0xfe
- .space 3
-#endif
.text
-/*
- * bcopy family
- * void bzero(void *buf, u_int len)
- */
-
-ENTRY(bzero)
- MEXITCOUNT
- jmp *bzero_vector
-
-ENTRY(generic_bzero)
- pushl %edi
- movl 8(%esp),%edi
- movl 12(%esp),%ecx
- xorl %eax,%eax
- shrl $2,%ecx
- cld
- rep
- stosl
- movl 12(%esp),%ecx
- andl $3,%ecx
- rep
- stosb
- popl %edi
- ret
-
-#ifdef I486_CPU
-ENTRY(i486_bzero)
- movl 4(%esp),%edx
- movl 8(%esp),%ecx
- xorl %eax,%eax
-/*
- * do 64 byte chunks first
- *
- * XXX this is probably over-unrolled at least for DX2's
- */
-2:
- cmpl $64,%ecx
- jb 3f
- movl %eax,(%edx)
- movl %eax,4(%edx)
- movl %eax,8(%edx)
- movl %eax,12(%edx)
- movl %eax,16(%edx)
- movl %eax,20(%edx)
- movl %eax,24(%edx)
- movl %eax,28(%edx)
- movl %eax,32(%edx)
- movl %eax,36(%edx)
- movl %eax,40(%edx)
- movl %eax,44(%edx)
- movl %eax,48(%edx)
- movl %eax,52(%edx)
- movl %eax,56(%edx)
- movl %eax,60(%edx)
- addl $64,%edx
- subl $64,%ecx
- jnz 2b
- ret
-
-/*
- * do 16 byte chunks
- */
- SUPERALIGN_TEXT
-3:
- cmpl $16,%ecx
- jb 4f
- movl %eax,(%edx)
- movl %eax,4(%edx)
- movl %eax,8(%edx)
- movl %eax,12(%edx)
- addl $16,%edx
- subl $16,%ecx
- jnz 3b
- ret
-
-/*
- * do 4 byte chunks
- */
- SUPERALIGN_TEXT
-4:
- cmpl $4,%ecx
- jb 5f
- movl %eax,(%edx)
- addl $4,%edx
- subl $4,%ecx
- jnz 4b
- ret
-
-/*
- * do 1 byte chunks
- * a jump table seems to be faster than a loop or more range reductions
- *
- * XXX need a const section for non-text
- */
- .data
-jtab:
- .long do0
- .long do1
- .long do2
- .long do3
-
- .text
- SUPERALIGN_TEXT
-5:
- jmp *jtab(,%ecx,4)
-
- SUPERALIGN_TEXT
-do3:
- movw %ax,(%edx)
- movb %al,2(%edx)
- ret
-
- SUPERALIGN_TEXT
-do2:
- movw %ax,(%edx)
- ret
-
- SUPERALIGN_TEXT
-do1:
- movb %al,(%edx)
- ret
-
- SUPERALIGN_TEXT
-do0:
- ret
-#endif
-
-#if defined(I586_CPU) && defined(DEV_NPX)
-ENTRY(i586_bzero)
- movl 4(%esp),%edx
- movl 8(%esp),%ecx
-
- /*
- * The FPU register method is twice as fast as the integer register
- * method unless the target is in the L1 cache and we pre-allocate a
- * cache line for it (then the integer register method is 4-5 times
- * faster). However, we never pre-allocate cache lines, since that
- * would make the integer method 25% or more slower for the common
- * case when the target isn't in either the L1 cache or the L2 cache.
- * Thus we normally use the FPU register method unless the overhead
- * would be too large.
- */
- cmpl $256,%ecx /* empirical; clts, fninit, smsw cost a lot */
- jb intreg_i586_bzero
-
- /*
- * The FPU registers may belong to an application or to fastmove()
- * or to another invocation of bcopy() or ourself in a higher level
- * interrupt or trap handler. Preserving the registers is
- * complicated since we avoid it if possible at all levels. We
- * want to localize the complications even when that increases them.
- * Here the extra work involves preserving CR0_TS in TS.
- * `fpcurthread != NULL' is supposed to be the condition that all the
- * FPU resources belong to an application, but fpcurthread and CR0_TS
- * aren't set atomically enough for this condition to work in
- * interrupt handlers.
- *
- * Case 1: FPU registers belong to the application: we must preserve
- * the registers if we use them, so we only use the FPU register
- * method if the target size is large enough to amortize the extra
- * overhead for preserving them. CR0_TS must be preserved although
- * it is very likely to end up as set.
- *
- * Case 2: FPU registers belong to fastmove(): fastmove() currently
- * makes the registers look like they belong to an application so
- * that cpu_switch() and savectx() don't have to know about it, so
- * this case reduces to case 1.
- *
- * Case 3: FPU registers belong to the kernel: don't use the FPU
- * register method. This case is unlikely, and supporting it would
- * be more complicated and might take too much stack.
- *
- * Case 4: FPU registers don't belong to anyone: the FPU registers
- * don't need to be preserved, so we always use the FPU register
- * method. CR0_TS must be preserved although it is very likely to
- * always end up as clear.
- */
- cmpl $0,PCPU(FPCURTHREAD)
- je i586_bz1
-
- /*
- * XXX don't use the FPU for cases 1 and 2, since preemptive
- * scheduling of ithreads broke these cases. Note that we can
- * no longer get here from an interrupt handler, since the
- * context sitch to the interrupt handler will have saved the
- * FPU state.
- */
- jmp intreg_i586_bzero
-
- cmpl $256+184,%ecx /* empirical; not quite 2*108 more */
- jb intreg_i586_bzero
- sarb $1,kernel_fpu_lock
- jc intreg_i586_bzero
- smsw %ax
- clts
- subl $108,%esp
- fnsave 0(%esp)
- jmp i586_bz2
-
-i586_bz1:
- sarb $1,kernel_fpu_lock
- jc intreg_i586_bzero
- smsw %ax
- clts
- fninit /* XXX should avoid needing this */
-i586_bz2:
- fldz
-
- /*
- * Align to an 8 byte boundary (misalignment in the main loop would
- * cost a factor of >= 2). Avoid jumps (at little cost if it is
- * already aligned) by always zeroing 8 bytes and using the part up
- * to the _next_ alignment position.
- */
- fstl 0(%edx)
- addl %edx,%ecx /* part of %ecx -= new_%edx - %edx */
- addl $8,%edx
- andl $~7,%edx
- subl %edx,%ecx
-
- /*
- * Similarly align `len' to a multiple of 8.
- */
- fstl -8(%edx,%ecx)
- decl %ecx
- andl $~7,%ecx
-
- /*
- * This wouldn't be any faster if it were unrolled, since the loop
- * control instructions are much faster than the fstl and/or done
- * in parallel with it so their overhead is insignificant.
- */
-fpureg_i586_bzero_loop:
- fstl 0(%edx)
- addl $8,%edx
- subl $8,%ecx
- cmpl $8,%ecx
- jae fpureg_i586_bzero_loop
-
- cmpl $0,PCPU(FPCURTHREAD)
- je i586_bz3
-
- /* XXX check that the condition for cases 1-2 stayed false. */
-i586_bzero_oops:
- int $3
- jmp i586_bzero_oops
-
- frstor 0(%esp)
- addl $108,%esp
- lmsw %ax
- movb $0xfe,kernel_fpu_lock
- ret
-
-i586_bz3:
- fstp %st(0)
- lmsw %ax
- movb $0xfe,kernel_fpu_lock
- ret
-
-intreg_i586_bzero:
- /*
- * `rep stos' seems to be the best method in practice for small
- * counts. Fancy methods usually take too long to start up due
- * to cache and BTB misses.
- */
- pushl %edi
- movl %edx,%edi
- xorl %eax,%eax
- shrl $2,%ecx
- cld
- rep
- stosl
- movl 12(%esp),%ecx
- andl $3,%ecx
- jne 1f
- popl %edi
- ret
-
-1:
- rep
- stosb
- popl %edi
- ret
-#endif /* I586_CPU && defined(DEV_NPX) */
-
-ENTRY(i686_pagezero)
- pushl %edi
- pushl %ebx
-
- movl 12(%esp), %edi
- movl $1024, %ecx
- cld
-
- ALIGN_TEXT
-1:
- xorl %eax, %eax
- repe
- scasl
- jnz 2f
-
- popl %ebx
- popl %edi
- ret
-
- ALIGN_TEXT
-
-2:
- incl %ecx
- subl $4, %edi
-
- movl %ecx, %edx
- cmpl $16, %ecx
-
- jge 3f
-
- movl %edi, %ebx
- andl $0x3f, %ebx
- shrl %ebx
- shrl %ebx
- movl $16, %ecx
- subl %ebx, %ecx
-
-3:
- subl %ecx, %edx
- rep
- stosl
-
- movl %edx, %ecx
- testl %edx, %edx
- jnz 1b
-
- popl %ebx
- popl %edi
- ret
-
-/* fillw(pat, base, cnt) */
+/* fillw(pat, base, cnt) */
+/* %rdi,%rsi, %rdx */
ENTRY(fillw)
- pushl %edi
- movl 8(%esp),%eax
- movl 12(%esp),%edi
- movl 16(%esp),%ecx
+ movq %rdi,%rax
+ movq %rsi,%rdi
+ movq %rdx,%rcx
cld
rep
stosw
- popl %edi
- ret
-
-ENTRY(bcopyb)
- pushl %esi
- pushl %edi
- movl 12(%esp),%esi
- movl 16(%esp),%edi
- movl 20(%esp),%ecx
- movl %edi,%eax
- subl %esi,%eax
- cmpl %ecx,%eax /* overlapping && src < dst? */
- jb 1f
- cld /* nope, copy forwards */
- rep
- movsb
- popl %edi
- popl %esi
- ret
-
- ALIGN_TEXT
-1:
- addl %ecx,%edi /* copy backwards. */
- addl %ecx,%esi
- decl %edi
- decl %esi
- std
- rep
- movsb
- popl %edi
- popl %esi
- cld
ret
-ENTRY(bcopy)
- MEXITCOUNT
- jmp *bcopy_vector
-
-/*
- * generic_bcopy(src, dst, cnt)
- * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800
- */
-ENTRY(generic_bcopy)
- pushl %esi
- pushl %edi
- movl 12(%esp),%esi
- movl 16(%esp),%edi
- movl 20(%esp),%ecx
-
- movl %edi,%eax
- subl %esi,%eax
- cmpl %ecx,%eax /* overlapping && src < dst? */
- jb 1f
-
- shrl $2,%ecx /* copy by 32-bit words */
- cld /* nope, copy forwards */
- rep
- movsl
- movl 20(%esp),%ecx
- andl $3,%ecx /* any bytes left? */
- rep
- movsb
- popl %edi
- popl %esi
- ret
-
- ALIGN_TEXT
-1:
- addl %ecx,%edi /* copy backwards */
- addl %ecx,%esi
- decl %edi
- decl %esi
- andl $3,%ecx /* any fractional bytes? */
- std
- rep
- movsb
- movl 20(%esp),%ecx /* copy remainder by 32-bit words */
- shrl $2,%ecx
- subl $3,%esi
- subl $3,%edi
- rep
- movsl
- popl %edi
- popl %esi
- cld
- ret
-
-#if defined(I586_CPU) && defined(DEV_NPX)
-ENTRY(i586_bcopy)
- pushl %esi
- pushl %edi
- movl 12(%esp),%esi
- movl 16(%esp),%edi
- movl 20(%esp),%ecx
-
- movl %edi,%eax
- subl %esi,%eax
- cmpl %ecx,%eax /* overlapping && src < dst? */
- jb 1f
-
- cmpl $1024,%ecx
- jb small_i586_bcopy
-
- sarb $1,kernel_fpu_lock
- jc small_i586_bcopy
- cmpl $0,PCPU(FPCURTHREAD)
- je i586_bc1
-
- /* XXX turn off handling of cases 1-2, as above. */
- movb $0xfe,kernel_fpu_lock
- jmp small_i586_bcopy
-
- smsw %dx
- clts
- subl $108,%esp
- fnsave 0(%esp)
- jmp 4f
-
-i586_bc1:
- smsw %dx
- clts
- fninit /* XXX should avoid needing this */
-
- ALIGN_TEXT
-4:
- pushl %ecx
-#define DCACHE_SIZE 8192
- cmpl $(DCACHE_SIZE-512)/2,%ecx
- jbe 2f
- movl $(DCACHE_SIZE-512)/2,%ecx
-2:
- subl %ecx,0(%esp)
- cmpl $256,%ecx
- jb 5f /* XXX should prefetch if %ecx >= 32 */
- pushl %esi
- pushl %ecx
- ALIGN_TEXT
-3:
- movl 0(%esi),%eax
- movl 32(%esi),%eax
- movl 64(%esi),%eax
- movl 96(%esi),%eax
- movl 128(%esi),%eax
- movl 160(%esi),%eax
- movl 192(%esi),%eax
- movl 224(%esi),%eax
- addl $256,%esi
- subl $256,%ecx
- cmpl $256,%ecx
- jae 3b
- popl %ecx
- popl %esi
-5:
- ALIGN_TEXT
-large_i586_bcopy_loop:
- fildq 0(%esi)
- fildq 8(%esi)
- fildq 16(%esi)
- fildq 24(%esi)
- fildq 32(%esi)
- fildq 40(%esi)
- fildq 48(%esi)
- fildq 56(%esi)
- fistpq 56(%edi)
- fistpq 48(%edi)
- fistpq 40(%edi)
- fistpq 32(%edi)
- fistpq 24(%edi)
- fistpq 16(%edi)
- fistpq 8(%edi)
- fistpq 0(%edi)
- addl $64,%esi
- addl $64,%edi
- subl $64,%ecx
- cmpl $64,%ecx
- jae large_i586_bcopy_loop
- popl %eax
- addl %eax,%ecx
- cmpl $64,%ecx
- jae 4b
-
- cmpl $0,PCPU(FPCURTHREAD)
- je i586_bc2
-
- /* XXX check that the condition for cases 1-2 stayed false. */
-i586_bcopy_oops:
- int $3
- jmp i586_bcopy_oops
-
- frstor 0(%esp)
- addl $108,%esp
-i586_bc2:
- lmsw %dx
- movb $0xfe,kernel_fpu_lock
-
-/*
- * This is a duplicate of the main part of generic_bcopy. See the comments
- * there. Jumping into generic_bcopy would cost a whole 0-1 cycles and
- * would mess up high resolution profiling.
- */
- ALIGN_TEXT
-small_i586_bcopy:
- shrl $2,%ecx
- cld
- rep
- movsl
- movl 20(%esp),%ecx
- andl $3,%ecx
- rep
- movsb
- popl %edi
- popl %esi
- ret
-
- ALIGN_TEXT
-1:
- addl %ecx,%edi
- addl %ecx,%esi
- decl %edi
- decl %esi
- andl $3,%ecx
- std
- rep
- movsb
- movl 20(%esp),%ecx
- shrl $2,%ecx
- subl $3,%esi
- subl $3,%edi
- rep
- movsl
- popl %edi
- popl %esi
- cld
- ret
-#endif /* I586_CPU && defined(DEV_NPX) */
-
-/*
- * Note: memcpy does not support overlapping copies
- */
-ENTRY(memcpy)
- pushl %edi
- pushl %esi
- movl 12(%esp),%edi
- movl 16(%esp),%esi
- movl 20(%esp),%ecx
- movl %edi,%eax
- shrl $2,%ecx /* copy by 32-bit words */
- cld /* nope, copy forwards */
- rep
- movsl
- movl 20(%esp),%ecx
- andl $3,%ecx /* any bytes left? */
- rep
- movsb
- popl %esi
- popl %edi
- ret
-
-
/*****************************************************************************/
/* copyout and fubyte family */
/*****************************************************************************/
@@ -687,22 +73,13 @@ ENTRY(memcpy)
*/
/*
- * copyout(from_kernel, to_user, len) - MP SAFE (if not I386_CPU)
+ * copyout(from_kernel, to_user, len) - MP SAFE
+ * %rdi, %rsi, %rdx
*/
ENTRY(copyout)
- MEXITCOUNT
- jmp *copyout_vector
-
-ENTRY(generic_copyout)
- movl PCPU(CURPCB),%eax
- movl $copyout_fault,PCB_ONFAULT(%eax)
- pushl %esi
- pushl %edi
- pushl %ebx
- movl 16(%esp),%esi
- movl 20(%esp),%edi
- movl 24(%esp),%ebx
- testl %ebx,%ebx /* anything to do? */
+ movq PCPU(CURPCB),%rax
+ movq $copyout_fault,PCB_ONFAULT(%rax)
+ testq %rdx,%rdx /* anything to do? */
jz done_copyout
/*
@@ -715,8 +92,8 @@ ENTRY(generic_copyout)
/*
* First, prevent address wrapping.
*/
- movl %edi,%eax
- addl %ebx,%eax
+ movq %rsi,%rax
+ addq %rdx,%rax
jc copyout_fault
/*
* XXX STOP USING VM_MAXUSER_ADDRESS.
@@ -724,469 +101,95 @@ ENTRY(generic_copyout)
* looks like there is an off by one error, and of course it caused an off
* by one error in several places.
*/
- cmpl $VM_MAXUSER_ADDRESS,%eax
+ movq $VM_MAXUSER_ADDRESS,%rcx
+ cmpq %rcx,%rax
ja copyout_fault
-#ifdef I386_CPU
-
-/*
- * We have to check each PTE for user write permission.
- * The checking may cause a page fault, so it is important to set
- * up everything for return via copyout_fault before here.
- */
- /* compute number of pages */
- movl %edi,%ecx
- andl $PAGE_MASK,%ecx
- addl %ebx,%ecx
- decl %ecx
- shrl $IDXSHIFT+2,%ecx
- incl %ecx
-
- /* compute PTE offset for start address */
- movl %edi,%edx
- shrl $IDXSHIFT,%edx
- andb $0xfc,%dl
-
-1:
- /* check PTE for each page */
- leal PTmap(%edx),%eax
- shrl $IDXSHIFT,%eax
- andb $0xfc,%al
- testb $PG_V,PTmap(%eax) /* PTE page must be valid */
- je 4f
- movb PTmap(%edx),%al
- andb $PG_V|PG_RW|PG_U,%al /* page must be valid and user writable */
- cmpb $PG_V|PG_RW|PG_U,%al
- je 2f
-
-4:
- /* simulate a trap */
- pushl %edx
- pushl %ecx
- shll $IDXSHIFT,%edx
- pushl %edx
- call trapwrite /* trapwrite(addr) */
- popl %edx
- popl %ecx
- popl %edx
-
- testl %eax,%eax /* if not ok, return EFAULT */
- jnz copyout_fault
-
-2:
- addl $4,%edx
- decl %ecx
- jnz 1b /* check next page */
-#endif /* I386_CPU */
+ xchgq %rdi, %rsi
+ /* bcopy(%rsi, %rdi, %rdx) */
+ movq %rdx,%rcx
- /* bcopy(%esi, %edi, %ebx) */
- movl %ebx,%ecx
-
-#if defined(I586_CPU) && defined(DEV_NPX)
- ALIGN_TEXT
-slow_copyout:
-#endif
- shrl $2,%ecx
+ shrq $3,%rcx
cld
rep
- movsl
- movb %bl,%cl
- andb $3,%cl
+ movsq
+ movb %dl,%cl
+ andb $7,%cl
rep
movsb
done_copyout:
- popl %ebx
- popl %edi
- popl %esi
- xorl %eax,%eax
- movl PCPU(CURPCB),%edx
- movl %eax,PCB_ONFAULT(%edx)
+ xorq %rax,%rax
+ movq PCPU(CURPCB),%rdx
+ movq %rax,PCB_ONFAULT(%rdx)
ret
ALIGN_TEXT
copyout_fault:
- popl %ebx
- popl %edi
- popl %esi
- movl PCPU(CURPCB),%edx
- movl $0,PCB_ONFAULT(%edx)
- movl $EFAULT,%eax
+ movq PCPU(CURPCB),%rdx
+ movq $0,PCB_ONFAULT(%rdx)
+ movq $EFAULT,%rax
ret
-#if defined(I586_CPU) && defined(DEV_NPX)
-ENTRY(i586_copyout)
- /*
- * Duplicated from generic_copyout. Could be done a bit better.
- */
- movl PCPU(CURPCB),%eax
- movl $copyout_fault,PCB_ONFAULT(%eax)
- pushl %esi
- pushl %edi
- pushl %ebx
- movl 16(%esp),%esi
- movl 20(%esp),%edi
- movl 24(%esp),%ebx
- testl %ebx,%ebx /* anything to do? */
- jz done_copyout
-
- /*
- * Check explicitly for non-user addresses. If 486 write protection
- * is being used, this check is essential because we are in kernel
- * mode so the h/w does not provide any protection against writing
- * kernel addresses.
- */
-
- /*
- * First, prevent address wrapping.
- */
- movl %edi,%eax
- addl %ebx,%eax
- jc copyout_fault
-/*
- * XXX STOP USING VM_MAXUSER_ADDRESS.
- * It is an end address, not a max, so every time it is used correctly it
- * looks like there is an off by one error, and of course it caused an off
- * by one error in several places.
- */
- cmpl $VM_MAXUSER_ADDRESS,%eax
- ja copyout_fault
-
- /* bcopy(%esi, %edi, %ebx) */
-3:
- movl %ebx,%ecx
- /*
- * End of duplicated code.
- */
-
- cmpl $1024,%ecx
- jb slow_copyout
-
- pushl %ecx
- call fastmove
- addl $4,%esp
- jmp done_copyout
-#endif /* I586_CPU && defined(DEV_NPX) */
-
/*
* copyin(from_user, to_kernel, len) - MP SAFE
+ * %rdi, %rsi, %rdx
*/
ENTRY(copyin)
- MEXITCOUNT
- jmp *copyin_vector
-
-ENTRY(generic_copyin)
- movl PCPU(CURPCB),%eax
- movl $copyin_fault,PCB_ONFAULT(%eax)
- pushl %esi
- pushl %edi
- movl 12(%esp),%esi /* caddr_t from */
- movl 16(%esp),%edi /* caddr_t to */
- movl 20(%esp),%ecx /* size_t len */
+ movq PCPU(CURPCB),%rax
+ movq $copyin_fault,PCB_ONFAULT(%rax)
+ testq %rdx,%rdx /* anything to do? */
+ jz done_copyin
/*
* make sure address is valid
*/
- movl %esi,%edx
- addl %ecx,%edx
+ movq %rdi,%rax
+ addq %rdx,%rax
jc copyin_fault
- cmpl $VM_MAXUSER_ADDRESS,%edx
+ movq $VM_MAXUSER_ADDRESS,%rcx
+ cmpq %rcx,%rax
ja copyin_fault
-#if defined(I586_CPU) && defined(DEV_NPX)
- ALIGN_TEXT
-slow_copyin:
-#endif
+ xchgq %rdi, %rsi
+ movq %rdx, %rcx
movb %cl,%al
- shrl $2,%ecx /* copy longword-wise */
+ shrq $3,%rcx /* copy longword-wise */
cld
rep
- movsl
+ movsq
movb %al,%cl
- andb $3,%cl /* copy remaining bytes */
+ andb $7,%cl /* copy remaining bytes */
rep
movsb
-#if defined(I586_CPU) && defined(DEV_NPX)
- ALIGN_TEXT
done_copyin:
-#endif
- popl %edi
- popl %esi
- xorl %eax,%eax
- movl PCPU(CURPCB),%edx
- movl %eax,PCB_ONFAULT(%edx)
+ xorq %rax,%rax
+ movq PCPU(CURPCB),%rdx
+ movq %rax,PCB_ONFAULT(%rdx)
ret
ALIGN_TEXT
copyin_fault:
- popl %edi
- popl %esi
- movl PCPU(CURPCB),%edx
- movl $0,PCB_ONFAULT(%edx)
- movl $EFAULT,%eax
+ movq PCPU(CURPCB),%rdx
+ movq $0,PCB_ONFAULT(%rdx)
+ movq $EFAULT,%rax
ret
-#if defined(I586_CPU) && defined(DEV_NPX)
-ENTRY(i586_copyin)
- /*
- * Duplicated from generic_copyin. Could be done a bit better.
- */
- movl PCPU(CURPCB),%eax
- movl $copyin_fault,PCB_ONFAULT(%eax)
- pushl %esi
- pushl %edi
- movl 12(%esp),%esi /* caddr_t from */
- movl 16(%esp),%edi /* caddr_t to */
- movl 20(%esp),%ecx /* size_t len */
-
- /*
- * make sure address is valid
- */
- movl %esi,%edx
- addl %ecx,%edx
- jc copyin_fault
- cmpl $VM_MAXUSER_ADDRESS,%edx
- ja copyin_fault
- /*
- * End of duplicated code.
- */
-
- cmpl $1024,%ecx
- jb slow_copyin
-
- pushl %ebx /* XXX prepare for fastmove_fault */
- pushl %ecx
- call fastmove
- addl $8,%esp
- jmp done_copyin
-#endif /* I586_CPU && defined(DEV_NPX) */
-
-#if defined(I586_CPU) && defined(DEV_NPX)
-/* fastmove(src, dst, len)
- src in %esi
- dst in %edi
- len in %ecx XXX changed to on stack for profiling
- uses %eax and %edx for tmp. storage
- */
-/* XXX use ENTRY() to get profiling. fastmove() is actually a non-entry. */
-ENTRY(fastmove)
- pushl %ebp
- movl %esp,%ebp
- subl $PCB_SAVEFPU_SIZE+3*4,%esp
-
- movl 8(%ebp),%ecx
- cmpl $63,%ecx
- jbe fastmove_tail
-
- testl $7,%esi /* check if src addr is multiple of 8 */
- jnz fastmove_tail
-
- testl $7,%edi /* check if dst addr is multiple of 8 */
- jnz fastmove_tail
-
- /* XXX grab FPU context atomically. */
- cli
-
-/* if (fpcurthread != NULL) { */
- cmpl $0,PCPU(FPCURTHREAD)
- je 6f
-/* fnsave(&curpcb->pcb_savefpu); */
- movl PCPU(CURPCB),%eax
- fnsave PCB_SAVEFPU(%eax)
-/* FPCURTHREAD = NULL; */
- movl $0,PCPU(FPCURTHREAD)
-/* } */
-6:
-/* now we own the FPU. */
-
-/*
- * The process' FP state is saved in the pcb, but if we get
- * switched, the cpu_switch() will store our FP state in the
- * pcb. It should be possible to avoid all the copying for
- * this, e.g., by setting a flag to tell cpu_switch() to
- * save the state somewhere else.
- */
-/* tmp = curpcb->pcb_savefpu; */
- movl %ecx,-12(%ebp)
- movl %esi,-8(%ebp)
- movl %edi,-4(%ebp)
- movl %esp,%edi
- movl PCPU(CURPCB),%esi
- addl $PCB_SAVEFPU,%esi
- cld
- movl $PCB_SAVEFPU_SIZE>>2,%ecx
- rep
- movsl
- movl -12(%ebp),%ecx
- movl -8(%ebp),%esi
- movl -4(%ebp),%edi
-/* stop_emulating(); */
- clts
-/* fpcurthread = curthread; */
- movl PCPU(CURTHREAD),%eax
- movl %eax,PCPU(FPCURTHREAD)
- movl PCPU(CURPCB),%eax
-
- /* XXX end of atomic FPU context grab. */
- sti
-
- movl $fastmove_fault,PCB_ONFAULT(%eax)
-4:
- movl %ecx,-12(%ebp)
- cmpl $1792,%ecx
- jbe 2f
- movl $1792,%ecx
-2:
- subl %ecx,-12(%ebp)
- cmpl $256,%ecx
- jb 5f
- movl %ecx,-8(%ebp)
- movl %esi,-4(%ebp)
- ALIGN_TEXT
-3:
- movl 0(%esi),%eax
- movl 32(%esi),%eax
- movl 64(%esi),%eax
- movl 96(%esi),%eax
- movl 128(%esi),%eax
- movl 160(%esi),%eax
- movl 192(%esi),%eax
- movl 224(%esi),%eax
- addl $256,%esi
- subl $256,%ecx
- cmpl $256,%ecx
- jae 3b
- movl -8(%ebp),%ecx
- movl -4(%ebp),%esi
-5:
- ALIGN_TEXT
-fastmove_loop:
- fildq 0(%esi)
- fildq 8(%esi)
- fildq 16(%esi)
- fildq 24(%esi)
- fildq 32(%esi)
- fildq 40(%esi)
- fildq 48(%esi)
- fildq 56(%esi)
- fistpq 56(%edi)
- fistpq 48(%edi)
- fistpq 40(%edi)
- fistpq 32(%edi)
- fistpq 24(%edi)
- fistpq 16(%edi)
- fistpq 8(%edi)
- fistpq 0(%edi)
- addl $-64,%ecx
- addl $64,%esi
- addl $64,%edi
- cmpl $63,%ecx
- ja fastmove_loop
- movl -12(%ebp),%eax
- addl %eax,%ecx
- cmpl $64,%ecx
- jae 4b
-
- /* XXX ungrab FPU context atomically. */
- cli
-
-/* curpcb->pcb_savefpu = tmp; */
- movl %ecx,-12(%ebp)
- movl %esi,-8(%ebp)
- movl %edi,-4(%ebp)
- movl PCPU(CURPCB),%edi
- addl $PCB_SAVEFPU,%edi
- movl %esp,%esi
- cld
- movl $PCB_SAVEFPU_SIZE>>2,%ecx
- rep
- movsl
- movl -12(%ebp),%ecx
- movl -8(%ebp),%esi
- movl -4(%ebp),%edi
-
-/* start_emulating(); */
- smsw %ax
- orb $CR0_TS,%al
- lmsw %ax
-/* fpcurthread = NULL; */
- movl $0,PCPU(FPCURTHREAD)
-
- /* XXX end of atomic FPU context ungrab. */
- sti
-
- ALIGN_TEXT
-fastmove_tail:
- movl PCPU(CURPCB),%eax
- movl $fastmove_tail_fault,PCB_ONFAULT(%eax)
-
- movb %cl,%al
- shrl $2,%ecx /* copy longword-wise */
- cld
- rep
- movsl
- movb %al,%cl
- andb $3,%cl /* copy remaining bytes */
- rep
- movsb
-
- movl %ebp,%esp
- popl %ebp
- ret
-
- ALIGN_TEXT
-fastmove_fault:
- /* XXX ungrab FPU context atomically. */
- cli
-
- movl PCPU(CURPCB),%edi
- addl $PCB_SAVEFPU,%edi
- movl %esp,%esi
- cld
- movl $PCB_SAVEFPU_SIZE>>2,%ecx
- rep
- movsl
-
- smsw %ax
- orb $CR0_TS,%al
- lmsw %ax
- movl $0,PCPU(FPCURTHREAD)
-
- /* XXX end of atomic FPU context ungrab. */
- sti
-
-fastmove_tail_fault:
- movl %ebp,%esp
- popl %ebp
- addl $8,%esp
- popl %ebx
- popl %edi
- popl %esi
- movl PCPU(CURPCB),%edx
- movl $0,PCB_ONFAULT(%edx)
- movl $EFAULT,%eax
- ret
-#endif /* I586_CPU && defined(DEV_NPX) */
-
/*
* casuptr. Compare and set user pointer. Returns -1 or the current value.
+ * dst = %rdi, old = %rsi, new = %rdx
*/
ENTRY(casuptr)
- movl PCPU(CURPCB),%ecx
- movl $fusufault,PCB_ONFAULT(%ecx)
- movl 4(%esp),%edx /* dst */
- movl 8(%esp),%eax /* old */
- movl 12(%esp),%ecx /* new */
+ movq PCPU(CURPCB),%rcx
+ movq $fusufault,PCB_ONFAULT(%rcx)
- cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address is valid */
+ movq $VM_MAXUSER_ADDRESS-4,%rax
+ cmpq %rax,%rdi /* verify address is valid */
ja fusufault
-#if defined(SMP)
- lock cmpxchgl %ecx, (%edx) /* Compare and set. */
-#else /* !SMP */
- cmpxchgl %ecx, (%edx)
-#endif /* !SMP */
+ movq %rsi, %rax /* old */
+ cmpxchgq %rdx, (%rdi) /* new = %rdx */
/*
* The old value is in %eax. If the store succeeded it will be the
@@ -1194,30 +197,45 @@ ENTRY(casuptr)
* be the current value.
*/
- movl PCPU(CURPCB),%ecx
- movl $fusufault,PCB_ONFAULT(%ecx)
- movl $0,PCB_ONFAULT(%ecx)
+ movq PCPU(CURPCB),%rcx
+ movq $fusufault,PCB_ONFAULT(%rcx)
+ movq $0,PCB_ONFAULT(%rcx)
ret
/*
* fu{byte,sword,word} - MP SAFE
*
* Fetch a byte (sword, word) from user memory
+ * %rdi
*/
-ENTRY(fuword)
- movl PCPU(CURPCB),%ecx
- movl $fusufault,PCB_ONFAULT(%ecx)
- movl 4(%esp),%edx /* from */
+ENTRY(fuword64)
+ movq PCPU(CURPCB),%rcx
+ movq $fusufault,PCB_ONFAULT(%rcx)
- cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address is valid */
+ movq $VM_MAXUSER_ADDRESS-8,%rax
+ cmpq %rax,%rdi /* verify address is valid */
ja fusufault
- movl (%edx),%eax
- movl $0,PCB_ONFAULT(%ecx)
+ movq (%rdi),%rax
+ movq $0,PCB_ONFAULT(%rcx)
ret
ENTRY(fuword32)
- jmp fuword
+ movq PCPU(CURPCB),%rcx
+ movq $fusufault,PCB_ONFAULT(%rcx)
+
+ movq $VM_MAXUSER_ADDRESS-4,%rax
+ cmpq %rax,%rdi /* verify address is valid */
+ ja fusufault
+
+# XXX use the 64 extend
+ xorq %rax, %rax
+ movl (%rdi),%eax
+ movq $0,PCB_ONFAULT(%rcx)
+ ret
+
+ENTRY(fuword)
+ jmp fuword32
/*
* These two routines are called from the profiling code, potentially
@@ -1227,191 +245,126 @@ ENTRY(fuword32)
*/
ALTENTRY(suswintr)
ENTRY(fuswintr)
- movl $-1,%eax
+ movq $-1,%rax
ret
/*
* fuword16 - MP SAFE
*/
ENTRY(fuword16)
- movl PCPU(CURPCB),%ecx
- movl $fusufault,PCB_ONFAULT(%ecx)
- movl 4(%esp),%edx
+ movq PCPU(CURPCB),%rcx
+ movq $fusufault,PCB_ONFAULT(%rcx)
- cmpl $VM_MAXUSER_ADDRESS-2,%edx
+ movq $VM_MAXUSER_ADDRESS-2,%rax
+ cmpq %rax,%rdi
ja fusufault
- movzwl (%edx),%eax
- movl $0,PCB_ONFAULT(%ecx)
+# XXX use the 64 extend
+ xorq %rax, %rax
+ movzwl (%rdi),%eax
+ movq $0,PCB_ONFAULT(%rcx)
ret
/*
* fubyte - MP SAFE
*/
ENTRY(fubyte)
- movl PCPU(CURPCB),%ecx
- movl $fusufault,PCB_ONFAULT(%ecx)
- movl 4(%esp),%edx
+ movq PCPU(CURPCB),%rcx
+ movq $fusufault,PCB_ONFAULT(%rcx)
- cmpl $VM_MAXUSER_ADDRESS-1,%edx
+ movq $VM_MAXUSER_ADDRESS-1,%rax
+ cmpq %rax,%rdi
ja fusufault
- movzbl (%edx),%eax
- movl $0,PCB_ONFAULT(%ecx)
+# XXX use the 64 extend
+ xorq %rax, %rax
+ movzbl (%rdi),%eax
+ movq $0,PCB_ONFAULT(%rcx)
ret
ALIGN_TEXT
fusufault:
- movl PCPU(CURPCB),%ecx
- xorl %eax,%eax
- movl %eax,PCB_ONFAULT(%ecx)
- decl %eax
+ movq PCPU(CURPCB),%rcx
+ xorq %rax,%rax
+ movq %rax,PCB_ONFAULT(%rcx)
+ decq %rax
ret
/*
- * su{byte,sword,word} - MP SAFE (if not I386_CPU)
+ * su{byte,sword,word} - MP SAFE
*
* Write a byte (word, longword) to user memory
+ * addr = %rdi, value = %rsi
*/
-ENTRY(suword)
- movl PCPU(CURPCB),%ecx
- movl $fusufault,PCB_ONFAULT(%ecx)
- movl 4(%esp),%edx
-
-#ifdef I386_CPU
-
- /* XXX - page boundary crossing is still not handled */
- movl %edx,%eax
- shrl $IDXSHIFT,%edx
- andb $0xfc,%dl
-
- leal PTmap(%edx),%ecx
- shrl $IDXSHIFT,%ecx
- andb $0xfc,%cl
- testb $PG_V,PTmap(%ecx) /* PTE page must be valid */
- je 4f
- movb PTmap(%edx),%dl
- andb $PG_V|PG_RW|PG_U,%dl /* page must be valid and user writable */
- cmpb $PG_V|PG_RW|PG_U,%dl
- je 1f
+ENTRY(suword64)
+ movq PCPU(CURPCB),%rcx
+ movq $fusufault,PCB_ONFAULT(%rcx)
-4:
- /* simulate a trap */
- pushl %eax
- call trapwrite
- popl %edx /* remove junk parameter from stack */
- testl %eax,%eax
- jnz fusufault
-1:
- movl 4(%esp),%edx
-#endif
-
- cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address validity */
+ movq $VM_MAXUSER_ADDRESS-8,%rax
+ cmpq %rax,%rdi /* verify address validity */
ja fusufault
- movl 8(%esp),%eax
- movl %eax,(%edx)
- xorl %eax,%eax
- movl PCPU(CURPCB),%ecx
- movl %eax,PCB_ONFAULT(%ecx)
+ movq %rsi,(%rdi)
+ xorq %rax,%rax
+ movq PCPU(CURPCB),%rcx
+ movq %rax,PCB_ONFAULT(%rcx)
ret
ENTRY(suword32)
- jmp suword
+ movq PCPU(CURPCB),%rcx
+ movq $fusufault,PCB_ONFAULT(%rcx)
+
+ movq $VM_MAXUSER_ADDRESS-4,%rax
+ cmpq %rax,%rdi /* verify address validity */
+ ja fusufault
+
+ movl %esi,(%rdi)
+ xorq %rax,%rax
+ movq PCPU(CURPCB),%rcx
+ movq %rax,PCB_ONFAULT(%rcx)
+ ret
+
+ENTRY(suword)
+ jmp suword32
/*
- * suword16 - MP SAFE (if not I386_CPU)
+ * suword16 - MP SAFE
*/
ENTRY(suword16)
- movl PCPU(CURPCB),%ecx
- movl $fusufault,PCB_ONFAULT(%ecx)
- movl 4(%esp),%edx
-
-#ifdef I386_CPU
-
- /* XXX - page boundary crossing is still not handled */
- movl %edx,%eax
- shrl $IDXSHIFT,%edx
- andb $0xfc,%dl
-
- leal PTmap(%edx),%ecx
- shrl $IDXSHIFT,%ecx
- andb $0xfc,%cl
- testb $PG_V,PTmap(%ecx) /* PTE page must be valid */
- je 4f
- movb PTmap(%edx),%dl
- andb $PG_V|PG_RW|PG_U,%dl /* page must be valid and user writable */
- cmpb $PG_V|PG_RW|PG_U,%dl
- je 1f
+ movq PCPU(CURPCB),%rcx
+ movq $fusufault,PCB_ONFAULT(%rcx)
-4:
- /* simulate a trap */
- pushl %eax
- call trapwrite
- popl %edx /* remove junk parameter from stack */
- testl %eax,%eax
- jnz fusufault
-1:
- movl 4(%esp),%edx
-#endif
-
- cmpl $VM_MAXUSER_ADDRESS-2,%edx /* verify address validity */
+ movq $VM_MAXUSER_ADDRESS-2,%rax
+ cmpq %rax,%rdi /* verify address validity */
ja fusufault
- movw 8(%esp),%ax
- movw %ax,(%edx)
- xorl %eax,%eax
- movl PCPU(CURPCB),%ecx /* restore trashed register */
- movl %eax,PCB_ONFAULT(%ecx)
+ movw %si,(%rdi)
+ xorq %rax,%rax
+ movq PCPU(CURPCB),%rcx /* restore trashed register */
+ movq %rax,PCB_ONFAULT(%rcx)
ret
/*
- * subyte - MP SAFE (if not I386_CPU)
+ * subyte - MP SAFE
*/
ENTRY(subyte)
- movl PCPU(CURPCB),%ecx
- movl $fusufault,PCB_ONFAULT(%ecx)
- movl 4(%esp),%edx
-
-#ifdef I386_CPU
-
- movl %edx,%eax
- shrl $IDXSHIFT,%edx
- andb $0xfc,%dl
-
- leal PTmap(%edx),%ecx
- shrl $IDXSHIFT,%ecx
- andb $0xfc,%cl
- testb $PG_V,PTmap(%ecx) /* PTE page must be valid */
- je 4f
- movb PTmap(%edx),%dl
- andb $PG_V|PG_RW|PG_U,%dl /* page must be valid and user writable */
- cmpb $PG_V|PG_RW|PG_U,%dl
- je 1f
-
-4:
- /* simulate a trap */
- pushl %eax
- call trapwrite
- popl %edx /* remove junk parameter from stack */
- testl %eax,%eax
- jnz fusufault
-1:
- movl 4(%esp),%edx
-#endif
+ movq PCPU(CURPCB),%rcx
+ movq $fusufault,PCB_ONFAULT(%rcx)
- cmpl $VM_MAXUSER_ADDRESS-1,%edx /* verify address validity */
+ movq $VM_MAXUSER_ADDRESS-1,%rax
+ cmpq %rax,%rdi /* verify address validity */
ja fusufault
- movb 8(%esp),%al
- movb %al,(%edx)
- xorl %eax,%eax
- movl PCPU(CURPCB),%ecx /* restore trashed register */
- movl %eax,PCB_ONFAULT(%ecx)
+ movl %esi, %eax
+ movb %al,(%rdi)
+ xorq %rax,%rax
+ movq PCPU(CURPCB),%rcx /* restore trashed register */
+ movq %rax,PCB_ONFAULT(%rcx)
ret
/*
* copyinstr(from, to, maxlen, int *lencopied) - MP SAFE
+ * %rdi, %rsi, %rdx, %rcx
*
* copy a string from from to to, stop when a 0 character is reached.
* return ENAMETOOLONG if string is longer than maxlen, and
@@ -1419,32 +372,29 @@ ENTRY(subyte)
* return the actual length in *lencopied.
*/
ENTRY(copyinstr)
- pushl %esi
- pushl %edi
- movl PCPU(CURPCB),%ecx
- movl $cpystrflt,PCB_ONFAULT(%ecx)
-
- movl 12(%esp),%esi /* %esi = from */
- movl 16(%esp),%edi /* %edi = to */
- movl 20(%esp),%edx /* %edx = maxlen */
+ 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)
- movl $VM_MAXUSER_ADDRESS,%eax
+ movq $VM_MAXUSER_ADDRESS,%rax
/* make sure 'from' is within bounds */
- subl %esi,%eax
+ subq %rsi,%rax
jbe cpystrflt
/* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */
- cmpl %edx,%eax
+ cmpq %rdx,%rax
jae 1f
- movl %eax,%edx
- movl %eax,20(%esp)
+ movq %rax,%rdx
+ movq %rax,%r8
1:
- incl %edx
+ incq %rdx
cld
2:
- decl %edx
+ decq %rdx
jz 3f
lodsb
@@ -1453,50 +403,46 @@ ENTRY(copyinstr)
jnz 2b
/* Success -- 0 byte reached */
- decl %edx
- xorl %eax,%eax
+ decq %rdx
+ xorq %rax,%rax
jmp cpystrflt_x
3:
- /* edx is zero - return ENAMETOOLONG or EFAULT */
- cmpl $VM_MAXUSER_ADDRESS,%esi
+ /* rdx is zero - return ENAMETOOLONG or EFAULT */
+ movq $VM_MAXUSER_ADDRESS,%rax
+ cmpq %rax,%rsi
jae cpystrflt
4:
- movl $ENAMETOOLONG,%eax
+ movq $ENAMETOOLONG,%rax
jmp cpystrflt_x
cpystrflt:
- movl $EFAULT,%eax
+ movq $EFAULT,%rax
cpystrflt_x:
/* set *lencopied and return %eax */
- movl PCPU(CURPCB),%ecx
- movl $0,PCB_ONFAULT(%ecx)
- movl 20(%esp),%ecx
- subl %edx,%ecx
- movl 24(%esp),%edx
- testl %edx,%edx
+ movq PCPU(CURPCB),%rcx
+ movq $0,PCB_ONFAULT(%rcx)
+
+ testq %r9,%r9
jz 1f
- movl %ecx,(%edx)
+ subq %rdx,%r8
+ movq %r8,(%r9)
1:
- popl %edi
- popl %esi
ret
/*
* copystr(from, to, maxlen, int *lencopied) - MP SAFE
+ * %rdi, %rsi, %rdx, %rcx
*/
ENTRY(copystr)
- pushl %esi
- pushl %edi
+ movq %rdx, %r8 /* %r8 = maxlen */
- movl 12(%esp),%esi /* %esi = from */
- movl 16(%esp),%edi /* %edi = to */
- movl 20(%esp),%edx /* %edx = maxlen */
- incl %edx
+ xchgq %rdi, %rsi
+ incq %rdx
cld
1:
- decl %edx
+ decq %rdx
jz 4f
lodsb
stosb
@@ -1504,159 +450,45 @@ ENTRY(copystr)
jnz 1b
/* Success -- 0 byte reached */
- decl %edx
- xorl %eax,%eax
+ decq %rdx
+ xorq %rax,%rax
jmp 6f
4:
- /* edx is zero -- return ENAMETOOLONG */
- movl $ENAMETOOLONG,%eax
+ /* rdx is zero -- return ENAMETOOLONG */
+ movq $ENAMETOOLONG,%rax
6:
- /* set *lencopied and return %eax */
- movl 20(%esp),%ecx
- subl %edx,%ecx
- movl 24(%esp),%edx
- testl %edx,%edx
+
+ testq %rcx, %rcx
jz 7f
- movl %ecx,(%edx)
+ /* set *lencopied and return %rax */
+ subq %rdx, %r8
+ movq %r8, (%rcx)
7:
- popl %edi
- popl %esi
- ret
-
-ENTRY(bcmp)
- pushl %edi
- pushl %esi
- movl 12(%esp),%edi
- movl 16(%esp),%esi
- movl 20(%esp),%edx
- xorl %eax,%eax
-
- movl %edx,%ecx
- shrl $2,%ecx
- cld /* compare forwards */
- repe
- cmpsl
- jne 1f
-
- movl %edx,%ecx
- andl $3,%ecx
- repe
- cmpsb
- je 2f
-1:
- incl %eax
-2:
- popl %esi
- popl %edi
ret
-
/*
* Handling of special 386 registers and descriptor tables etc
+ * %rdi
*/
/* void lgdt(struct region_descriptor *rdp); */
ENTRY(lgdt)
/* reload the descriptor table */
- movl 4(%esp),%eax
- lgdt (%eax)
+ lgdt (%rdi)
/* flush the prefetch q */
jmp 1f
nop
1:
- /* reload "stale" selectors */
- movl $KDSEL,%eax
+ movl $KDSEL, %eax
mov %ax,%ds
mov %ax,%es
+ mov %ax,%fs /* Beware, use wrmsr to set 64 bit base */
mov %ax,%gs
mov %ax,%ss
- movl $KPSEL,%eax
- mov %ax,%fs
/* reload code selector by turning return into intersegmental return */
- movl (%esp),%eax
- pushl %eax
- movl $KCSEL,4(%esp)
- lret
-
-/* ssdtosd(*ssdp,*sdp) */
-ENTRY(ssdtosd)
- pushl %ebx
- movl 8(%esp),%ecx
- movl 8(%ecx),%ebx
- shll $16,%ebx
- movl (%ecx),%edx
- roll $16,%edx
- movb %dh,%bl
- movb %dl,%bh
- rorl $8,%ebx
- movl 4(%ecx),%eax
- movw %ax,%dx
- andl $0xf0000,%eax
- orl %eax,%ebx
- movl 12(%esp),%ecx
- movl %edx,(%ecx)
- movl %ebx,4(%ecx)
- popl %ebx
- ret
-
-/* void reset_dbregs() */
-ENTRY(reset_dbregs)
- movl $0,%eax
- movl %eax,%dr7 /* disable all breapoints first */
- movl %eax,%dr0
- movl %eax,%dr1
- movl %eax,%dr2
- movl %eax,%dr3
- movl %eax,%dr6
- ret
-
-/*****************************************************************************/
-/* setjump, longjump */
-/*****************************************************************************/
-
-ENTRY(setjmp)
- movl 4(%esp),%eax
- movl %ebx,(%eax) /* save ebx */
- movl %esp,4(%eax) /* save esp */
- movl %ebp,8(%eax) /* save ebp */
- movl %esi,12(%eax) /* save esi */
- movl %edi,16(%eax) /* save edi */
- movl (%esp),%edx /* get rta */
- movl %edx,20(%eax) /* save eip */
- xorl %eax,%eax /* return(0); */
- ret
-
-ENTRY(longjmp)
- movl 4(%esp),%eax
- movl (%eax),%ebx /* restore ebx */
- movl 4(%eax),%esp /* restore esp */
- movl 8(%eax),%ebp /* restore ebp */
- movl 12(%eax),%esi /* restore esi */
- movl 16(%eax),%edi /* restore edi */
- movl 20(%eax),%edx /* get rta */
- movl %edx,(%esp) /* put in return frame */
- xorl %eax,%eax /* return(1); */
- incl %eax
- ret
-
-/*
- * Support for BB-profiling (gcc -a). The kernbb program will extract
- * the data from the kernel.
- */
-
- .data
- ALIGN_DATA
- .globl bbhead
-bbhead:
- .long 0
-
- .text
-NON_GPROF_ENTRY(__bb_init_func)
- movl 4(%esp),%eax
- movl $1,(%eax)
- movl bbhead,%edx
- movl %edx,16(%eax)
- movl %eax,bbhead
- NON_GPROF_RET
+ popq %rax
+ pushq $KCSEL
+ pushq %rax
+ lretq
diff --git a/sys/amd64/amd64/support.s b/sys/amd64/amd64/support.s
index f0f99e4a7346..06a3c4e6d8f2 100644
--- a/sys/amd64/amd64/support.s
+++ b/sys/amd64/amd64/support.s
@@ -33,8 +33,6 @@
* $FreeBSD$
*/
-#include "opt_npx.h"
-
#include <machine/asmacros.h>
#include <machine/cputypes.h>
#include <machine/pmap.h>
@@ -42,632 +40,20 @@
#include "assym.s"
-#define IDXSHIFT 10
-
- .data
- .globl bcopy_vector
-bcopy_vector:
- .long generic_bcopy
- .globl bzero_vector
-bzero_vector:
- .long generic_bzero
- .globl copyin_vector
-copyin_vector:
- .long generic_copyin
- .globl copyout_vector
-copyout_vector:
- .long generic_copyout
-#if defined(I586_CPU) && defined(DEV_NPX)
-kernel_fpu_lock:
- .byte 0xfe
- .space 3
-#endif
.text
-/*
- * bcopy family
- * void bzero(void *buf, u_int len)
- */
-
-ENTRY(bzero)
- MEXITCOUNT
- jmp *bzero_vector
-
-ENTRY(generic_bzero)
- pushl %edi
- movl 8(%esp),%edi
- movl 12(%esp),%ecx
- xorl %eax,%eax
- shrl $2,%ecx
- cld
- rep
- stosl
- movl 12(%esp),%ecx
- andl $3,%ecx
- rep
- stosb
- popl %edi
- ret
-
-#ifdef I486_CPU
-ENTRY(i486_bzero)
- movl 4(%esp),%edx
- movl 8(%esp),%ecx
- xorl %eax,%eax
-/*
- * do 64 byte chunks first
- *
- * XXX this is probably over-unrolled at least for DX2's
- */
-2:
- cmpl $64,%ecx
- jb 3f
- movl %eax,(%edx)
- movl %eax,4(%edx)
- movl %eax,8(%edx)
- movl %eax,12(%edx)
- movl %eax,16(%edx)
- movl %eax,20(%edx)
- movl %eax,24(%edx)
- movl %eax,28(%edx)
- movl %eax,32(%edx)
- movl %eax,36(%edx)
- movl %eax,40(%edx)
- movl %eax,44(%edx)
- movl %eax,48(%edx)
- movl %eax,52(%edx)
- movl %eax,56(%edx)
- movl %eax,60(%edx)
- addl $64,%edx
- subl $64,%ecx
- jnz 2b
- ret
-
-/*
- * do 16 byte chunks
- */
- SUPERALIGN_TEXT
-3:
- cmpl $16,%ecx
- jb 4f
- movl %eax,(%edx)
- movl %eax,4(%edx)
- movl %eax,8(%edx)
- movl %eax,12(%edx)
- addl $16,%edx
- subl $16,%ecx
- jnz 3b
- ret
-
-/*
- * do 4 byte chunks
- */
- SUPERALIGN_TEXT
-4:
- cmpl $4,%ecx
- jb 5f
- movl %eax,(%edx)
- addl $4,%edx
- subl $4,%ecx
- jnz 4b
- ret
-
-/*
- * do 1 byte chunks
- * a jump table seems to be faster than a loop or more range reductions
- *
- * XXX need a const section for non-text
- */
- .data
-jtab:
- .long do0
- .long do1
- .long do2
- .long do3
-
- .text
- SUPERALIGN_TEXT
-5:
- jmp *jtab(,%ecx,4)
-
- SUPERALIGN_TEXT
-do3:
- movw %ax,(%edx)
- movb %al,2(%edx)
- ret
-
- SUPERALIGN_TEXT
-do2:
- movw %ax,(%edx)
- ret
-
- SUPERALIGN_TEXT
-do1:
- movb %al,(%edx)
- ret
-
- SUPERALIGN_TEXT
-do0:
- ret
-#endif
-
-#if defined(I586_CPU) && defined(DEV_NPX)
-ENTRY(i586_bzero)
- movl 4(%esp),%edx
- movl 8(%esp),%ecx
-
- /*
- * The FPU register method is twice as fast as the integer register
- * method unless the target is in the L1 cache and we pre-allocate a
- * cache line for it (then the integer register method is 4-5 times
- * faster). However, we never pre-allocate cache lines, since that
- * would make the integer method 25% or more slower for the common
- * case when the target isn't in either the L1 cache or the L2 cache.
- * Thus we normally use the FPU register method unless the overhead
- * would be too large.
- */
- cmpl $256,%ecx /* empirical; clts, fninit, smsw cost a lot */
- jb intreg_i586_bzero
-
- /*
- * The FPU registers may belong to an application or to fastmove()
- * or to another invocation of bcopy() or ourself in a higher level
- * interrupt or trap handler. Preserving the registers is
- * complicated since we avoid it if possible at all levels. We
- * want to localize the complications even when that increases them.
- * Here the extra work involves preserving CR0_TS in TS.
- * `fpcurthread != NULL' is supposed to be the condition that all the
- * FPU resources belong to an application, but fpcurthread and CR0_TS
- * aren't set atomically enough for this condition to work in
- * interrupt handlers.
- *
- * Case 1: FPU registers belong to the application: we must preserve
- * the registers if we use them, so we only use the FPU register
- * method if the target size is large enough to amortize the extra
- * overhead for preserving them. CR0_TS must be preserved although
- * it is very likely to end up as set.
- *
- * Case 2: FPU registers belong to fastmove(): fastmove() currently
- * makes the registers look like they belong to an application so
- * that cpu_switch() and savectx() don't have to know about it, so
- * this case reduces to case 1.
- *
- * Case 3: FPU registers belong to the kernel: don't use the FPU
- * register method. This case is unlikely, and supporting it would
- * be more complicated and might take too much stack.
- *
- * Case 4: FPU registers don't belong to anyone: the FPU registers
- * don't need to be preserved, so we always use the FPU register
- * method. CR0_TS must be preserved although it is very likely to
- * always end up as clear.
- */
- cmpl $0,PCPU(FPCURTHREAD)
- je i586_bz1
-
- /*
- * XXX don't use the FPU for cases 1 and 2, since preemptive
- * scheduling of ithreads broke these cases. Note that we can
- * no longer get here from an interrupt handler, since the
- * context sitch to the interrupt handler will have saved the
- * FPU state.
- */
- jmp intreg_i586_bzero
-
- cmpl $256+184,%ecx /* empirical; not quite 2*108 more */
- jb intreg_i586_bzero
- sarb $1,kernel_fpu_lock
- jc intreg_i586_bzero
- smsw %ax
- clts
- subl $108,%esp
- fnsave 0(%esp)
- jmp i586_bz2
-
-i586_bz1:
- sarb $1,kernel_fpu_lock
- jc intreg_i586_bzero
- smsw %ax
- clts
- fninit /* XXX should avoid needing this */
-i586_bz2:
- fldz
-
- /*
- * Align to an 8 byte boundary (misalignment in the main loop would
- * cost a factor of >= 2). Avoid jumps (at little cost if it is
- * already aligned) by always zeroing 8 bytes and using the part up
- * to the _next_ alignment position.
- */
- fstl 0(%edx)
- addl %edx,%ecx /* part of %ecx -= new_%edx - %edx */
- addl $8,%edx
- andl $~7,%edx
- subl %edx,%ecx
-
- /*
- * Similarly align `len' to a multiple of 8.
- */
- fstl -8(%edx,%ecx)
- decl %ecx
- andl $~7,%ecx
-
- /*
- * This wouldn't be any faster if it were unrolled, since the loop
- * control instructions are much faster than the fstl and/or done
- * in parallel with it so their overhead is insignificant.
- */
-fpureg_i586_bzero_loop:
- fstl 0(%edx)
- addl $8,%edx
- subl $8,%ecx
- cmpl $8,%ecx
- jae fpureg_i586_bzero_loop
-
- cmpl $0,PCPU(FPCURTHREAD)
- je i586_bz3
-
- /* XXX check that the condition for cases 1-2 stayed false. */
-i586_bzero_oops:
- int $3
- jmp i586_bzero_oops
-
- frstor 0(%esp)
- addl $108,%esp
- lmsw %ax
- movb $0xfe,kernel_fpu_lock
- ret
-
-i586_bz3:
- fstp %st(0)
- lmsw %ax
- movb $0xfe,kernel_fpu_lock
- ret
-
-intreg_i586_bzero:
- /*
- * `rep stos' seems to be the best method in practice for small
- * counts. Fancy methods usually take too long to start up due
- * to cache and BTB misses.
- */
- pushl %edi
- movl %edx,%edi
- xorl %eax,%eax
- shrl $2,%ecx
- cld
- rep
- stosl
- movl 12(%esp),%ecx
- andl $3,%ecx
- jne 1f
- popl %edi
- ret
-
-1:
- rep
- stosb
- popl %edi
- ret
-#endif /* I586_CPU && defined(DEV_NPX) */
-
-ENTRY(i686_pagezero)
- pushl %edi
- pushl %ebx
-
- movl 12(%esp), %edi
- movl $1024, %ecx
- cld
-
- ALIGN_TEXT
-1:
- xorl %eax, %eax
- repe
- scasl
- jnz 2f
-
- popl %ebx
- popl %edi
- ret
-
- ALIGN_TEXT
-
-2:
- incl %ecx
- subl $4, %edi
-
- movl %ecx, %edx
- cmpl $16, %ecx
-
- jge 3f
-
- movl %edi, %ebx
- andl $0x3f, %ebx
- shrl %ebx
- shrl %ebx
- movl $16, %ecx
- subl %ebx, %ecx
-
-3:
- subl %ecx, %edx
- rep
- stosl
-
- movl %edx, %ecx
- testl %edx, %edx
- jnz 1b
-
- popl %ebx
- popl %edi
- ret
-
-/* fillw(pat, base, cnt) */
+/* fillw(pat, base, cnt) */
+/* %rdi,%rsi, %rdx */
ENTRY(fillw)
- pushl %edi
- movl 8(%esp),%eax
- movl 12(%esp),%edi
- movl 16(%esp),%ecx
+ movq %rdi,%rax
+ movq %rsi,%rdi
+ movq %rdx,%rcx
cld
rep
stosw
- popl %edi
- ret
-
-ENTRY(bcopyb)
- pushl %esi
- pushl %edi
- movl 12(%esp),%esi
- movl 16(%esp),%edi
- movl 20(%esp),%ecx
- movl %edi,%eax
- subl %esi,%eax
- cmpl %ecx,%eax /* overlapping && src < dst? */
- jb 1f
- cld /* nope, copy forwards */
- rep
- movsb
- popl %edi
- popl %esi
- ret
-
- ALIGN_TEXT
-1:
- addl %ecx,%edi /* copy backwards. */
- addl %ecx,%esi
- decl %edi
- decl %esi
- std
- rep
- movsb
- popl %edi
- popl %esi
- cld
ret
-ENTRY(bcopy)
- MEXITCOUNT
- jmp *bcopy_vector
-
-/*
- * generic_bcopy(src, dst, cnt)
- * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800
- */
-ENTRY(generic_bcopy)
- pushl %esi
- pushl %edi
- movl 12(%esp),%esi
- movl 16(%esp),%edi
- movl 20(%esp),%ecx
-
- movl %edi,%eax
- subl %esi,%eax
- cmpl %ecx,%eax /* overlapping && src < dst? */
- jb 1f
-
- shrl $2,%ecx /* copy by 32-bit words */
- cld /* nope, copy forwards */
- rep
- movsl
- movl 20(%esp),%ecx
- andl $3,%ecx /* any bytes left? */
- rep
- movsb
- popl %edi
- popl %esi
- ret
-
- ALIGN_TEXT
-1:
- addl %ecx,%edi /* copy backwards */
- addl %ecx,%esi
- decl %edi
- decl %esi
- andl $3,%ecx /* any fractional bytes? */
- std
- rep
- movsb
- movl 20(%esp),%ecx /* copy remainder by 32-bit words */
- shrl $2,%ecx
- subl $3,%esi
- subl $3,%edi
- rep
- movsl
- popl %edi
- popl %esi
- cld
- ret
-
-#if defined(I586_CPU) && defined(DEV_NPX)
-ENTRY(i586_bcopy)
- pushl %esi
- pushl %edi
- movl 12(%esp),%esi
- movl 16(%esp),%edi
- movl 20(%esp),%ecx
-
- movl %edi,%eax
- subl %esi,%eax
- cmpl %ecx,%eax /* overlapping && src < dst? */
- jb 1f
-
- cmpl $1024,%ecx
- jb small_i586_bcopy
-
- sarb $1,kernel_fpu_lock
- jc small_i586_bcopy
- cmpl $0,PCPU(FPCURTHREAD)
- je i586_bc1
-
- /* XXX turn off handling of cases 1-2, as above. */
- movb $0xfe,kernel_fpu_lock
- jmp small_i586_bcopy
-
- smsw %dx
- clts
- subl $108,%esp
- fnsave 0(%esp)
- jmp 4f
-
-i586_bc1:
- smsw %dx
- clts
- fninit /* XXX should avoid needing this */
-
- ALIGN_TEXT
-4:
- pushl %ecx
-#define DCACHE_SIZE 8192
- cmpl $(DCACHE_SIZE-512)/2,%ecx
- jbe 2f
- movl $(DCACHE_SIZE-512)/2,%ecx
-2:
- subl %ecx,0(%esp)
- cmpl $256,%ecx
- jb 5f /* XXX should prefetch if %ecx >= 32 */
- pushl %esi
- pushl %ecx
- ALIGN_TEXT
-3:
- movl 0(%esi),%eax
- movl 32(%esi),%eax
- movl 64(%esi),%eax
- movl 96(%esi),%eax
- movl 128(%esi),%eax
- movl 160(%esi),%eax
- movl 192(%esi),%eax
- movl 224(%esi),%eax
- addl $256,%esi
- subl $256,%ecx
- cmpl $256,%ecx
- jae 3b
- popl %ecx
- popl %esi
-5:
- ALIGN_TEXT
-large_i586_bcopy_loop:
- fildq 0(%esi)
- fildq 8(%esi)
- fildq 16(%esi)
- fildq 24(%esi)
- fildq 32(%esi)
- fildq 40(%esi)
- fildq 48(%esi)
- fildq 56(%esi)
- fistpq 56(%edi)
- fistpq 48(%edi)
- fistpq 40(%edi)
- fistpq 32(%edi)
- fistpq 24(%edi)
- fistpq 16(%edi)
- fistpq 8(%edi)
- fistpq 0(%edi)
- addl $64,%esi
- addl $64,%edi
- subl $64,%ecx
- cmpl $64,%ecx
- jae large_i586_bcopy_loop
- popl %eax
- addl %eax,%ecx
- cmpl $64,%ecx
- jae 4b
-
- cmpl $0,PCPU(FPCURTHREAD)
- je i586_bc2
-
- /* XXX check that the condition for cases 1-2 stayed false. */
-i586_bcopy_oops:
- int $3
- jmp i586_bcopy_oops
-
- frstor 0(%esp)
- addl $108,%esp
-i586_bc2:
- lmsw %dx
- movb $0xfe,kernel_fpu_lock
-
-/*
- * This is a duplicate of the main part of generic_bcopy. See the comments
- * there. Jumping into generic_bcopy would cost a whole 0-1 cycles and
- * would mess up high resolution profiling.
- */
- ALIGN_TEXT
-small_i586_bcopy:
- shrl $2,%ecx
- cld
- rep
- movsl
- movl 20(%esp),%ecx
- andl $3,%ecx
- rep
- movsb
- popl %edi
- popl %esi
- ret
-
- ALIGN_TEXT
-1:
- addl %ecx,%edi
- addl %ecx,%esi
- decl %edi
- decl %esi
- andl $3,%ecx
- std
- rep
- movsb
- movl 20(%esp),%ecx
- shrl $2,%ecx
- subl $3,%esi
- subl $3,%edi
- rep
- movsl
- popl %edi
- popl %esi
- cld
- ret
-#endif /* I586_CPU && defined(DEV_NPX) */
-
-/*
- * Note: memcpy does not support overlapping copies
- */
-ENTRY(memcpy)
- pushl %edi
- pushl %esi
- movl 12(%esp),%edi
- movl 16(%esp),%esi
- movl 20(%esp),%ecx
- movl %edi,%eax
- shrl $2,%ecx /* copy by 32-bit words */
- cld /* nope, copy forwards */
- rep
- movsl
- movl 20(%esp),%ecx
- andl $3,%ecx /* any bytes left? */
- rep
- movsb
- popl %esi
- popl %edi
- ret
-
-
/*****************************************************************************/
/* copyout and fubyte family */
/*****************************************************************************/
@@ -687,22 +73,13 @@ ENTRY(memcpy)
*/
/*
- * copyout(from_kernel, to_user, len) - MP SAFE (if not I386_CPU)
+ * copyout(from_kernel, to_user, len) - MP SAFE
+ * %rdi, %rsi, %rdx
*/
ENTRY(copyout)
- MEXITCOUNT
- jmp *copyout_vector
-
-ENTRY(generic_copyout)
- movl PCPU(CURPCB),%eax
- movl $copyout_fault,PCB_ONFAULT(%eax)
- pushl %esi
- pushl %edi
- pushl %ebx
- movl 16(%esp),%esi
- movl 20(%esp),%edi
- movl 24(%esp),%ebx
- testl %ebx,%ebx /* anything to do? */
+ movq PCPU(CURPCB),%rax
+ movq $copyout_fault,PCB_ONFAULT(%rax)
+ testq %rdx,%rdx /* anything to do? */
jz done_copyout
/*
@@ -715,8 +92,8 @@ ENTRY(generic_copyout)
/*
* First, prevent address wrapping.
*/
- movl %edi,%eax
- addl %ebx,%eax
+ movq %rsi,%rax
+ addq %rdx,%rax
jc copyout_fault
/*
* XXX STOP USING VM_MAXUSER_ADDRESS.
@@ -724,469 +101,95 @@ ENTRY(generic_copyout)
* looks like there is an off by one error, and of course it caused an off
* by one error in several places.
*/
- cmpl $VM_MAXUSER_ADDRESS,%eax
+ movq $VM_MAXUSER_ADDRESS,%rcx
+ cmpq %rcx,%rax
ja copyout_fault
-#ifdef I386_CPU
-
-/*
- * We have to check each PTE for user write permission.
- * The checking may cause a page fault, so it is important to set
- * up everything for return via copyout_fault before here.
- */
- /* compute number of pages */
- movl %edi,%ecx
- andl $PAGE_MASK,%ecx
- addl %ebx,%ecx
- decl %ecx
- shrl $IDXSHIFT+2,%ecx
- incl %ecx
-
- /* compute PTE offset for start address */
- movl %edi,%edx
- shrl $IDXSHIFT,%edx
- andb $0xfc,%dl
-
-1:
- /* check PTE for each page */
- leal PTmap(%edx),%eax
- shrl $IDXSHIFT,%eax
- andb $0xfc,%al
- testb $PG_V,PTmap(%eax) /* PTE page must be valid */
- je 4f
- movb PTmap(%edx),%al
- andb $PG_V|PG_RW|PG_U,%al /* page must be valid and user writable */
- cmpb $PG_V|PG_RW|PG_U,%al
- je 2f
-
-4:
- /* simulate a trap */
- pushl %edx
- pushl %ecx
- shll $IDXSHIFT,%edx
- pushl %edx
- call trapwrite /* trapwrite(addr) */
- popl %edx
- popl %ecx
- popl %edx
-
- testl %eax,%eax /* if not ok, return EFAULT */
- jnz copyout_fault
-
-2:
- addl $4,%edx
- decl %ecx
- jnz 1b /* check next page */
-#endif /* I386_CPU */
+ xchgq %rdi, %rsi
+ /* bcopy(%rsi, %rdi, %rdx) */
+ movq %rdx,%rcx
- /* bcopy(%esi, %edi, %ebx) */
- movl %ebx,%ecx
-
-#if defined(I586_CPU) && defined(DEV_NPX)
- ALIGN_TEXT
-slow_copyout:
-#endif
- shrl $2,%ecx
+ shrq $3,%rcx
cld
rep
- movsl
- movb %bl,%cl
- andb $3,%cl
+ movsq
+ movb %dl,%cl
+ andb $7,%cl
rep
movsb
done_copyout:
- popl %ebx
- popl %edi
- popl %esi
- xorl %eax,%eax
- movl PCPU(CURPCB),%edx
- movl %eax,PCB_ONFAULT(%edx)
+ xorq %rax,%rax
+ movq PCPU(CURPCB),%rdx
+ movq %rax,PCB_ONFAULT(%rdx)
ret
ALIGN_TEXT
copyout_fault:
- popl %ebx
- popl %edi
- popl %esi
- movl PCPU(CURPCB),%edx
- movl $0,PCB_ONFAULT(%edx)
- movl $EFAULT,%eax
+ movq PCPU(CURPCB),%rdx
+ movq $0,PCB_ONFAULT(%rdx)
+ movq $EFAULT,%rax
ret
-#if defined(I586_CPU) && defined(DEV_NPX)
-ENTRY(i586_copyout)
- /*
- * Duplicated from generic_copyout. Could be done a bit better.
- */
- movl PCPU(CURPCB),%eax
- movl $copyout_fault,PCB_ONFAULT(%eax)
- pushl %esi
- pushl %edi
- pushl %ebx
- movl 16(%esp),%esi
- movl 20(%esp),%edi
- movl 24(%esp),%ebx
- testl %ebx,%ebx /* anything to do? */
- jz done_copyout
-
- /*
- * Check explicitly for non-user addresses. If 486 write protection
- * is being used, this check is essential because we are in kernel
- * mode so the h/w does not provide any protection against writing
- * kernel addresses.
- */
-
- /*
- * First, prevent address wrapping.
- */
- movl %edi,%eax
- addl %ebx,%eax
- jc copyout_fault
-/*
- * XXX STOP USING VM_MAXUSER_ADDRESS.
- * It is an end address, not a max, so every time it is used correctly it
- * looks like there is an off by one error, and of course it caused an off
- * by one error in several places.
- */
- cmpl $VM_MAXUSER_ADDRESS,%eax
- ja copyout_fault
-
- /* bcopy(%esi, %edi, %ebx) */
-3:
- movl %ebx,%ecx
- /*
- * End of duplicated code.
- */
-
- cmpl $1024,%ecx
- jb slow_copyout
-
- pushl %ecx
- call fastmove
- addl $4,%esp
- jmp done_copyout
-#endif /* I586_CPU && defined(DEV_NPX) */
-
/*
* copyin(from_user, to_kernel, len) - MP SAFE
+ * %rdi, %rsi, %rdx
*/
ENTRY(copyin)
- MEXITCOUNT
- jmp *copyin_vector
-
-ENTRY(generic_copyin)
- movl PCPU(CURPCB),%eax
- movl $copyin_fault,PCB_ONFAULT(%eax)
- pushl %esi
- pushl %edi
- movl 12(%esp),%esi /* caddr_t from */
- movl 16(%esp),%edi /* caddr_t to */
- movl 20(%esp),%ecx /* size_t len */
+ movq PCPU(CURPCB),%rax
+ movq $copyin_fault,PCB_ONFAULT(%rax)
+ testq %rdx,%rdx /* anything to do? */
+ jz done_copyin
/*
* make sure address is valid
*/
- movl %esi,%edx
- addl %ecx,%edx
+ movq %rdi,%rax
+ addq %rdx,%rax
jc copyin_fault
- cmpl $VM_MAXUSER_ADDRESS,%edx
+ movq $VM_MAXUSER_ADDRESS,%rcx
+ cmpq %rcx,%rax
ja copyin_fault
-#if defined(I586_CPU) && defined(DEV_NPX)
- ALIGN_TEXT
-slow_copyin:
-#endif
+ xchgq %rdi, %rsi
+ movq %rdx, %rcx
movb %cl,%al
- shrl $2,%ecx /* copy longword-wise */
+ shrq $3,%rcx /* copy longword-wise */
cld
rep
- movsl
+ movsq
movb %al,%cl
- andb $3,%cl /* copy remaining bytes */
+ andb $7,%cl /* copy remaining bytes */
rep
movsb
-#if defined(I586_CPU) && defined(DEV_NPX)
- ALIGN_TEXT
done_copyin:
-#endif
- popl %edi
- popl %esi
- xorl %eax,%eax
- movl PCPU(CURPCB),%edx
- movl %eax,PCB_ONFAULT(%edx)
+ xorq %rax,%rax
+ movq PCPU(CURPCB),%rdx
+ movq %rax,PCB_ONFAULT(%rdx)
ret
ALIGN_TEXT
copyin_fault:
- popl %edi
- popl %esi
- movl PCPU(CURPCB),%edx
- movl $0,PCB_ONFAULT(%edx)
- movl $EFAULT,%eax
+ movq PCPU(CURPCB),%rdx
+ movq $0,PCB_ONFAULT(%rdx)
+ movq $EFAULT,%rax
ret
-#if defined(I586_CPU) && defined(DEV_NPX)
-ENTRY(i586_copyin)
- /*
- * Duplicated from generic_copyin. Could be done a bit better.
- */
- movl PCPU(CURPCB),%eax
- movl $copyin_fault,PCB_ONFAULT(%eax)
- pushl %esi
- pushl %edi
- movl 12(%esp),%esi /* caddr_t from */
- movl 16(%esp),%edi /* caddr_t to */
- movl 20(%esp),%ecx /* size_t len */
-
- /*
- * make sure address is valid
- */
- movl %esi,%edx
- addl %ecx,%edx
- jc copyin_fault
- cmpl $VM_MAXUSER_ADDRESS,%edx
- ja copyin_fault
- /*
- * End of duplicated code.
- */
-
- cmpl $1024,%ecx
- jb slow_copyin
-
- pushl %ebx /* XXX prepare for fastmove_fault */
- pushl %ecx
- call fastmove
- addl $8,%esp
- jmp done_copyin
-#endif /* I586_CPU && defined(DEV_NPX) */
-
-#if defined(I586_CPU) && defined(DEV_NPX)
-/* fastmove(src, dst, len)
- src in %esi
- dst in %edi
- len in %ecx XXX changed to on stack for profiling
- uses %eax and %edx for tmp. storage
- */
-/* XXX use ENTRY() to get profiling. fastmove() is actually a non-entry. */
-ENTRY(fastmove)
- pushl %ebp
- movl %esp,%ebp
- subl $PCB_SAVEFPU_SIZE+3*4,%esp
-
- movl 8(%ebp),%ecx
- cmpl $63,%ecx
- jbe fastmove_tail
-
- testl $7,%esi /* check if src addr is multiple of 8 */
- jnz fastmove_tail
-
- testl $7,%edi /* check if dst addr is multiple of 8 */
- jnz fastmove_tail
-
- /* XXX grab FPU context atomically. */
- cli
-
-/* if (fpcurthread != NULL) { */
- cmpl $0,PCPU(FPCURTHREAD)
- je 6f
-/* fnsave(&curpcb->pcb_savefpu); */
- movl PCPU(CURPCB),%eax
- fnsave PCB_SAVEFPU(%eax)
-/* FPCURTHREAD = NULL; */
- movl $0,PCPU(FPCURTHREAD)
-/* } */
-6:
-/* now we own the FPU. */
-
-/*
- * The process' FP state is saved in the pcb, but if we get
- * switched, the cpu_switch() will store our FP state in the
- * pcb. It should be possible to avoid all the copying for
- * this, e.g., by setting a flag to tell cpu_switch() to
- * save the state somewhere else.
- */
-/* tmp = curpcb->pcb_savefpu; */
- movl %ecx,-12(%ebp)
- movl %esi,-8(%ebp)
- movl %edi,-4(%ebp)
- movl %esp,%edi
- movl PCPU(CURPCB),%esi
- addl $PCB_SAVEFPU,%esi
- cld
- movl $PCB_SAVEFPU_SIZE>>2,%ecx
- rep
- movsl
- movl -12(%ebp),%ecx
- movl -8(%ebp),%esi
- movl -4(%ebp),%edi
-/* stop_emulating(); */
- clts
-/* fpcurthread = curthread; */
- movl PCPU(CURTHREAD),%eax
- movl %eax,PCPU(FPCURTHREAD)
- movl PCPU(CURPCB),%eax
-
- /* XXX end of atomic FPU context grab. */
- sti
-
- movl $fastmove_fault,PCB_ONFAULT(%eax)
-4:
- movl %ecx,-12(%ebp)
- cmpl $1792,%ecx
- jbe 2f
- movl $1792,%ecx
-2:
- subl %ecx,-12(%ebp)
- cmpl $256,%ecx
- jb 5f
- movl %ecx,-8(%ebp)
- movl %esi,-4(%ebp)
- ALIGN_TEXT
-3:
- movl 0(%esi),%eax
- movl 32(%esi),%eax
- movl 64(%esi),%eax
- movl 96(%esi),%eax
- movl 128(%esi),%eax
- movl 160(%esi),%eax
- movl 192(%esi),%eax
- movl 224(%esi),%eax
- addl $256,%esi
- subl $256,%ecx
- cmpl $256,%ecx
- jae 3b
- movl -8(%ebp),%ecx
- movl -4(%ebp),%esi
-5:
- ALIGN_TEXT
-fastmove_loop:
- fildq 0(%esi)
- fildq 8(%esi)
- fildq 16(%esi)
- fildq 24(%esi)
- fildq 32(%esi)
- fildq 40(%esi)
- fildq 48(%esi)
- fildq 56(%esi)
- fistpq 56(%edi)
- fistpq 48(%edi)
- fistpq 40(%edi)
- fistpq 32(%edi)
- fistpq 24(%edi)
- fistpq 16(%edi)
- fistpq 8(%edi)
- fistpq 0(%edi)
- addl $-64,%ecx
- addl $64,%esi
- addl $64,%edi
- cmpl $63,%ecx
- ja fastmove_loop
- movl -12(%ebp),%eax
- addl %eax,%ecx
- cmpl $64,%ecx
- jae 4b
-
- /* XXX ungrab FPU context atomically. */
- cli
-
-/* curpcb->pcb_savefpu = tmp; */
- movl %ecx,-12(%ebp)
- movl %esi,-8(%ebp)
- movl %edi,-4(%ebp)
- movl PCPU(CURPCB),%edi
- addl $PCB_SAVEFPU,%edi
- movl %esp,%esi
- cld
- movl $PCB_SAVEFPU_SIZE>>2,%ecx
- rep
- movsl
- movl -12(%ebp),%ecx
- movl -8(%ebp),%esi
- movl -4(%ebp),%edi
-
-/* start_emulating(); */
- smsw %ax
- orb $CR0_TS,%al
- lmsw %ax
-/* fpcurthread = NULL; */
- movl $0,PCPU(FPCURTHREAD)
-
- /* XXX end of atomic FPU context ungrab. */
- sti
-
- ALIGN_TEXT
-fastmove_tail:
- movl PCPU(CURPCB),%eax
- movl $fastmove_tail_fault,PCB_ONFAULT(%eax)
-
- movb %cl,%al
- shrl $2,%ecx /* copy longword-wise */
- cld
- rep
- movsl
- movb %al,%cl
- andb $3,%cl /* copy remaining bytes */
- rep
- movsb
-
- movl %ebp,%esp
- popl %ebp
- ret
-
- ALIGN_TEXT
-fastmove_fault:
- /* XXX ungrab FPU context atomically. */
- cli
-
- movl PCPU(CURPCB),%edi
- addl $PCB_SAVEFPU,%edi
- movl %esp,%esi
- cld
- movl $PCB_SAVEFPU_SIZE>>2,%ecx
- rep
- movsl
-
- smsw %ax
- orb $CR0_TS,%al
- lmsw %ax
- movl $0,PCPU(FPCURTHREAD)
-
- /* XXX end of atomic FPU context ungrab. */
- sti
-
-fastmove_tail_fault:
- movl %ebp,%esp
- popl %ebp
- addl $8,%esp
- popl %ebx
- popl %edi
- popl %esi
- movl PCPU(CURPCB),%edx
- movl $0,PCB_ONFAULT(%edx)
- movl $EFAULT,%eax
- ret
-#endif /* I586_CPU && defined(DEV_NPX) */
-
/*
* casuptr. Compare and set user pointer. Returns -1 or the current value.
+ * dst = %rdi, old = %rsi, new = %rdx
*/
ENTRY(casuptr)
- movl PCPU(CURPCB),%ecx
- movl $fusufault,PCB_ONFAULT(%ecx)
- movl 4(%esp),%edx /* dst */
- movl 8(%esp),%eax /* old */
- movl 12(%esp),%ecx /* new */
+ movq PCPU(CURPCB),%rcx
+ movq $fusufault,PCB_ONFAULT(%rcx)
- cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address is valid */
+ movq $VM_MAXUSER_ADDRESS-4,%rax
+ cmpq %rax,%rdi /* verify address is valid */
ja fusufault
-#if defined(SMP)
- lock cmpxchgl %ecx, (%edx) /* Compare and set. */
-#else /* !SMP */
- cmpxchgl %ecx, (%edx)
-#endif /* !SMP */
+ movq %rsi, %rax /* old */
+ cmpxchgq %rdx, (%rdi) /* new = %rdx */
/*
* The old value is in %eax. If the store succeeded it will be the
@@ -1194,30 +197,45 @@ ENTRY(casuptr)
* be the current value.
*/
- movl PCPU(CURPCB),%ecx
- movl $fusufault,PCB_ONFAULT(%ecx)
- movl $0,PCB_ONFAULT(%ecx)
+ movq PCPU(CURPCB),%rcx
+ movq $fusufault,PCB_ONFAULT(%rcx)
+ movq $0,PCB_ONFAULT(%rcx)
ret
/*
* fu{byte,sword,word} - MP SAFE
*
* Fetch a byte (sword, word) from user memory
+ * %rdi
*/
-ENTRY(fuword)
- movl PCPU(CURPCB),%ecx
- movl $fusufault,PCB_ONFAULT(%ecx)
- movl 4(%esp),%edx /* from */
+ENTRY(fuword64)
+ movq PCPU(CURPCB),%rcx
+ movq $fusufault,PCB_ONFAULT(%rcx)
- cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address is valid */
+ movq $VM_MAXUSER_ADDRESS-8,%rax
+ cmpq %rax,%rdi /* verify address is valid */
ja fusufault
- movl (%edx),%eax
- movl $0,PCB_ONFAULT(%ecx)
+ movq (%rdi),%rax
+ movq $0,PCB_ONFAULT(%rcx)
ret
ENTRY(fuword32)
- jmp fuword
+ movq PCPU(CURPCB),%rcx
+ movq $fusufault,PCB_ONFAULT(%rcx)
+
+ movq $VM_MAXUSER_ADDRESS-4,%rax
+ cmpq %rax,%rdi /* verify address is valid */
+ ja fusufault
+
+# XXX use the 64 extend
+ xorq %rax, %rax
+ movl (%rdi),%eax
+ movq $0,PCB_ONFAULT(%rcx)
+ ret
+
+ENTRY(fuword)
+ jmp fuword32
/*
* These two routines are called from the profiling code, potentially
@@ -1227,191 +245,126 @@ ENTRY(fuword32)
*/
ALTENTRY(suswintr)
ENTRY(fuswintr)
- movl $-1,%eax
+ movq $-1,%rax
ret
/*
* fuword16 - MP SAFE
*/
ENTRY(fuword16)
- movl PCPU(CURPCB),%ecx
- movl $fusufault,PCB_ONFAULT(%ecx)
- movl 4(%esp),%edx
+ movq PCPU(CURPCB),%rcx
+ movq $fusufault,PCB_ONFAULT(%rcx)
- cmpl $VM_MAXUSER_ADDRESS-2,%edx
+ movq $VM_MAXUSER_ADDRESS-2,%rax
+ cmpq %rax,%rdi
ja fusufault
- movzwl (%edx),%eax
- movl $0,PCB_ONFAULT(%ecx)
+# XXX use the 64 extend
+ xorq %rax, %rax
+ movzwl (%rdi),%eax
+ movq $0,PCB_ONFAULT(%rcx)
ret
/*
* fubyte - MP SAFE
*/
ENTRY(fubyte)
- movl PCPU(CURPCB),%ecx
- movl $fusufault,PCB_ONFAULT(%ecx)
- movl 4(%esp),%edx
+ movq PCPU(CURPCB),%rcx
+ movq $fusufault,PCB_ONFAULT(%rcx)
- cmpl $VM_MAXUSER_ADDRESS-1,%edx
+ movq $VM_MAXUSER_ADDRESS-1,%rax
+ cmpq %rax,%rdi
ja fusufault
- movzbl (%edx),%eax
- movl $0,PCB_ONFAULT(%ecx)
+# XXX use the 64 extend
+ xorq %rax, %rax
+ movzbl (%rdi),%eax
+ movq $0,PCB_ONFAULT(%rcx)
ret
ALIGN_TEXT
fusufault:
- movl PCPU(CURPCB),%ecx
- xorl %eax,%eax
- movl %eax,PCB_ONFAULT(%ecx)
- decl %eax
+ movq PCPU(CURPCB),%rcx
+ xorq %rax,%rax
+ movq %rax,PCB_ONFAULT(%rcx)
+ decq %rax
ret
/*
- * su{byte,sword,word} - MP SAFE (if not I386_CPU)
+ * su{byte,sword,word} - MP SAFE
*
* Write a byte (word, longword) to user memory
+ * addr = %rdi, value = %rsi
*/
-ENTRY(suword)
- movl PCPU(CURPCB),%ecx
- movl $fusufault,PCB_ONFAULT(%ecx)
- movl 4(%esp),%edx
-
-#ifdef I386_CPU
-
- /* XXX - page boundary crossing is still not handled */
- movl %edx,%eax
- shrl $IDXSHIFT,%edx
- andb $0xfc,%dl
-
- leal PTmap(%edx),%ecx
- shrl $IDXSHIFT,%ecx
- andb $0xfc,%cl
- testb $PG_V,PTmap(%ecx) /* PTE page must be valid */
- je 4f
- movb PTmap(%edx),%dl
- andb $PG_V|PG_RW|PG_U,%dl /* page must be valid and user writable */
- cmpb $PG_V|PG_RW|PG_U,%dl
- je 1f
+ENTRY(suword64)
+ movq PCPU(CURPCB),%rcx
+ movq $fusufault,PCB_ONFAULT(%rcx)
-4:
- /* simulate a trap */
- pushl %eax
- call trapwrite
- popl %edx /* remove junk parameter from stack */
- testl %eax,%eax
- jnz fusufault
-1:
- movl 4(%esp),%edx
-#endif
-
- cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address validity */
+ movq $VM_MAXUSER_ADDRESS-8,%rax
+ cmpq %rax,%rdi /* verify address validity */
ja fusufault
- movl 8(%esp),%eax
- movl %eax,(%edx)
- xorl %eax,%eax
- movl PCPU(CURPCB),%ecx
- movl %eax,PCB_ONFAULT(%ecx)
+ movq %rsi,(%rdi)
+ xorq %rax,%rax
+ movq PCPU(CURPCB),%rcx
+ movq %rax,PCB_ONFAULT(%rcx)
ret
ENTRY(suword32)
- jmp suword
+ movq PCPU(CURPCB),%rcx
+ movq $fusufault,PCB_ONFAULT(%rcx)
+
+ movq $VM_MAXUSER_ADDRESS-4,%rax
+ cmpq %rax,%rdi /* verify address validity */
+ ja fusufault
+
+ movl %esi,(%rdi)
+ xorq %rax,%rax
+ movq PCPU(CURPCB),%rcx
+ movq %rax,PCB_ONFAULT(%rcx)
+ ret
+
+ENTRY(suword)
+ jmp suword32
/*
- * suword16 - MP SAFE (if not I386_CPU)
+ * suword16 - MP SAFE
*/
ENTRY(suword16)
- movl PCPU(CURPCB),%ecx
- movl $fusufault,PCB_ONFAULT(%ecx)
- movl 4(%esp),%edx
-
-#ifdef I386_CPU
-
- /* XXX - page boundary crossing is still not handled */
- movl %edx,%eax
- shrl $IDXSHIFT,%edx
- andb $0xfc,%dl
-
- leal PTmap(%edx),%ecx
- shrl $IDXSHIFT,%ecx
- andb $0xfc,%cl
- testb $PG_V,PTmap(%ecx) /* PTE page must be valid */
- je 4f
- movb PTmap(%edx),%dl
- andb $PG_V|PG_RW|PG_U,%dl /* page must be valid and user writable */
- cmpb $PG_V|PG_RW|PG_U,%dl
- je 1f
+ movq PCPU(CURPCB),%rcx
+ movq $fusufault,PCB_ONFAULT(%rcx)
-4:
- /* simulate a trap */
- pushl %eax
- call trapwrite
- popl %edx /* remove junk parameter from stack */
- testl %eax,%eax
- jnz fusufault
-1:
- movl 4(%esp),%edx
-#endif
-
- cmpl $VM_MAXUSER_ADDRESS-2,%edx /* verify address validity */
+ movq $VM_MAXUSER_ADDRESS-2,%rax
+ cmpq %rax,%rdi /* verify address validity */
ja fusufault
- movw 8(%esp),%ax
- movw %ax,(%edx)
- xorl %eax,%eax
- movl PCPU(CURPCB),%ecx /* restore trashed register */
- movl %eax,PCB_ONFAULT(%ecx)
+ movw %si,(%rdi)
+ xorq %rax,%rax
+ movq PCPU(CURPCB),%rcx /* restore trashed register */
+ movq %rax,PCB_ONFAULT(%rcx)
ret
/*
- * subyte - MP SAFE (if not I386_CPU)
+ * subyte - MP SAFE
*/
ENTRY(subyte)
- movl PCPU(CURPCB),%ecx
- movl $fusufault,PCB_ONFAULT(%ecx)
- movl 4(%esp),%edx
-
-#ifdef I386_CPU
-
- movl %edx,%eax
- shrl $IDXSHIFT,%edx
- andb $0xfc,%dl
-
- leal PTmap(%edx),%ecx
- shrl $IDXSHIFT,%ecx
- andb $0xfc,%cl
- testb $PG_V,PTmap(%ecx) /* PTE page must be valid */
- je 4f
- movb PTmap(%edx),%dl
- andb $PG_V|PG_RW|PG_U,%dl /* page must be valid and user writable */
- cmpb $PG_V|PG_RW|PG_U,%dl
- je 1f
-
-4:
- /* simulate a trap */
- pushl %eax
- call trapwrite
- popl %edx /* remove junk parameter from stack */
- testl %eax,%eax
- jnz fusufault
-1:
- movl 4(%esp),%edx
-#endif
+ movq PCPU(CURPCB),%rcx
+ movq $fusufault,PCB_ONFAULT(%rcx)
- cmpl $VM_MAXUSER_ADDRESS-1,%edx /* verify address validity */
+ movq $VM_MAXUSER_ADDRESS-1,%rax
+ cmpq %rax,%rdi /* verify address validity */
ja fusufault
- movb 8(%esp),%al
- movb %al,(%edx)
- xorl %eax,%eax
- movl PCPU(CURPCB),%ecx /* restore trashed register */
- movl %eax,PCB_ONFAULT(%ecx)
+ movl %esi, %eax
+ movb %al,(%rdi)
+ xorq %rax,%rax
+ movq PCPU(CURPCB),%rcx /* restore trashed register */
+ movq %rax,PCB_ONFAULT(%rcx)
ret
/*
* copyinstr(from, to, maxlen, int *lencopied) - MP SAFE
+ * %rdi, %rsi, %rdx, %rcx
*
* copy a string from from to to, stop when a 0 character is reached.
* return ENAMETOOLONG if string is longer than maxlen, and
@@ -1419,32 +372,29 @@ ENTRY(subyte)
* return the actual length in *lencopied.
*/
ENTRY(copyinstr)
- pushl %esi
- pushl %edi
- movl PCPU(CURPCB),%ecx
- movl $cpystrflt,PCB_ONFAULT(%ecx)
-
- movl 12(%esp),%esi /* %esi = from */
- movl 16(%esp),%edi /* %edi = to */
- movl 20(%esp),%edx /* %edx = maxlen */
+ 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)
- movl $VM_MAXUSER_ADDRESS,%eax
+ movq $VM_MAXUSER_ADDRESS,%rax
/* make sure 'from' is within bounds */
- subl %esi,%eax
+ subq %rsi,%rax
jbe cpystrflt
/* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */
- cmpl %edx,%eax
+ cmpq %rdx,%rax
jae 1f
- movl %eax,%edx
- movl %eax,20(%esp)
+ movq %rax,%rdx
+ movq %rax,%r8
1:
- incl %edx
+ incq %rdx
cld
2:
- decl %edx
+ decq %rdx
jz 3f
lodsb
@@ -1453,50 +403,46 @@ ENTRY(copyinstr)
jnz 2b
/* Success -- 0 byte reached */
- decl %edx
- xorl %eax,%eax
+ decq %rdx
+ xorq %rax,%rax
jmp cpystrflt_x
3:
- /* edx is zero - return ENAMETOOLONG or EFAULT */
- cmpl $VM_MAXUSER_ADDRESS,%esi
+ /* rdx is zero - return ENAMETOOLONG or EFAULT */
+ movq $VM_MAXUSER_ADDRESS,%rax
+ cmpq %rax,%rsi
jae cpystrflt
4:
- movl $ENAMETOOLONG,%eax
+ movq $ENAMETOOLONG,%rax
jmp cpystrflt_x
cpystrflt:
- movl $EFAULT,%eax
+ movq $EFAULT,%rax
cpystrflt_x:
/* set *lencopied and return %eax */
- movl PCPU(CURPCB),%ecx
- movl $0,PCB_ONFAULT(%ecx)
- movl 20(%esp),%ecx
- subl %edx,%ecx
- movl 24(%esp),%edx
- testl %edx,%edx
+ movq PCPU(CURPCB),%rcx
+ movq $0,PCB_ONFAULT(%rcx)
+
+ testq %r9,%r9
jz 1f
- movl %ecx,(%edx)
+ subq %rdx,%r8
+ movq %r8,(%r9)
1:
- popl %edi
- popl %esi
ret
/*
* copystr(from, to, maxlen, int *lencopied) - MP SAFE
+ * %rdi, %rsi, %rdx, %rcx
*/
ENTRY(copystr)
- pushl %esi
- pushl %edi
+ movq %rdx, %r8 /* %r8 = maxlen */
- movl 12(%esp),%esi /* %esi = from */
- movl 16(%esp),%edi /* %edi = to */
- movl 20(%esp),%edx /* %edx = maxlen */
- incl %edx
+ xchgq %rdi, %rsi
+ incq %rdx
cld
1:
- decl %edx
+ decq %rdx
jz 4f
lodsb
stosb
@@ -1504,159 +450,45 @@ ENTRY(copystr)
jnz 1b
/* Success -- 0 byte reached */
- decl %edx
- xorl %eax,%eax
+ decq %rdx
+ xorq %rax,%rax
jmp 6f
4:
- /* edx is zero -- return ENAMETOOLONG */
- movl $ENAMETOOLONG,%eax
+ /* rdx is zero -- return ENAMETOOLONG */
+ movq $ENAMETOOLONG,%rax
6:
- /* set *lencopied and return %eax */
- movl 20(%esp),%ecx
- subl %edx,%ecx
- movl 24(%esp),%edx
- testl %edx,%edx
+
+ testq %rcx, %rcx
jz 7f
- movl %ecx,(%edx)
+ /* set *lencopied and return %rax */
+ subq %rdx, %r8
+ movq %r8, (%rcx)
7:
- popl %edi
- popl %esi
- ret
-
-ENTRY(bcmp)
- pushl %edi
- pushl %esi
- movl 12(%esp),%edi
- movl 16(%esp),%esi
- movl 20(%esp),%edx
- xorl %eax,%eax
-
- movl %edx,%ecx
- shrl $2,%ecx
- cld /* compare forwards */
- repe
- cmpsl
- jne 1f
-
- movl %edx,%ecx
- andl $3,%ecx
- repe
- cmpsb
- je 2f
-1:
- incl %eax
-2:
- popl %esi
- popl %edi
ret
-
/*
* Handling of special 386 registers and descriptor tables etc
+ * %rdi
*/
/* void lgdt(struct region_descriptor *rdp); */
ENTRY(lgdt)
/* reload the descriptor table */
- movl 4(%esp),%eax
- lgdt (%eax)
+ lgdt (%rdi)
/* flush the prefetch q */
jmp 1f
nop
1:
- /* reload "stale" selectors */
- movl $KDSEL,%eax
+ movl $KDSEL, %eax
mov %ax,%ds
mov %ax,%es
+ mov %ax,%fs /* Beware, use wrmsr to set 64 bit base */
mov %ax,%gs
mov %ax,%ss
- movl $KPSEL,%eax
- mov %ax,%fs
/* reload code selector by turning return into intersegmental return */
- movl (%esp),%eax
- pushl %eax
- movl $KCSEL,4(%esp)
- lret
-
-/* ssdtosd(*ssdp,*sdp) */
-ENTRY(ssdtosd)
- pushl %ebx
- movl 8(%esp),%ecx
- movl 8(%ecx),%ebx
- shll $16,%ebx
- movl (%ecx),%edx
- roll $16,%edx
- movb %dh,%bl
- movb %dl,%bh
- rorl $8,%ebx
- movl 4(%ecx),%eax
- movw %ax,%dx
- andl $0xf0000,%eax
- orl %eax,%ebx
- movl 12(%esp),%ecx
- movl %edx,(%ecx)
- movl %ebx,4(%ecx)
- popl %ebx
- ret
-
-/* void reset_dbregs() */
-ENTRY(reset_dbregs)
- movl $0,%eax
- movl %eax,%dr7 /* disable all breapoints first */
- movl %eax,%dr0
- movl %eax,%dr1
- movl %eax,%dr2
- movl %eax,%dr3
- movl %eax,%dr6
- ret
-
-/*****************************************************************************/
-/* setjump, longjump */
-/*****************************************************************************/
-
-ENTRY(setjmp)
- movl 4(%esp),%eax
- movl %ebx,(%eax) /* save ebx */
- movl %esp,4(%eax) /* save esp */
- movl %ebp,8(%eax) /* save ebp */
- movl %esi,12(%eax) /* save esi */
- movl %edi,16(%eax) /* save edi */
- movl (%esp),%edx /* get rta */
- movl %edx,20(%eax) /* save eip */
- xorl %eax,%eax /* return(0); */
- ret
-
-ENTRY(longjmp)
- movl 4(%esp),%eax
- movl (%eax),%ebx /* restore ebx */
- movl 4(%eax),%esp /* restore esp */
- movl 8(%eax),%ebp /* restore ebp */
- movl 12(%eax),%esi /* restore esi */
- movl 16(%eax),%edi /* restore edi */
- movl 20(%eax),%edx /* get rta */
- movl %edx,(%esp) /* put in return frame */
- xorl %eax,%eax /* return(1); */
- incl %eax
- ret
-
-/*
- * Support for BB-profiling (gcc -a). The kernbb program will extract
- * the data from the kernel.
- */
-
- .data
- ALIGN_DATA
- .globl bbhead
-bbhead:
- .long 0
-
- .text
-NON_GPROF_ENTRY(__bb_init_func)
- movl 4(%esp),%eax
- movl $1,(%eax)
- movl bbhead,%edx
- movl %edx,16(%eax)
- movl %eax,bbhead
- NON_GPROF_RET
+ popq %rax
+ pushq $KCSEL
+ pushq %rax
+ lretq
diff --git a/sys/amd64/amd64/swtch.s b/sys/amd64/amd64/swtch.s
index a19baa705749..8cca838f0b8a 100644
--- a/sys/amd64/amd64/swtch.s
+++ b/sys/amd64/amd64/swtch.s
@@ -36,9 +36,6 @@
* $FreeBSD$
*/
-#include "opt_npx.h"
-#include "opt_swtch.h"
-
#include <machine/asmacros.h>
#include "assym.s"
@@ -57,37 +54,26 @@
* about its state. This is only a slight optimization and is probably
* not worth it anymore. Note that we need to clear the pm_active bits so
* we do need the old proc if it still exists.
- * 0(%esp) = ret
- * 4(%esp) = oldtd
- * 8(%esp) = newtd
+ * %rdi = oldtd
+ * %rsi = newtd
*/
ENTRY(cpu_throw)
- movl PCPU(CPUID), %esi
- movl 4(%esp),%ecx /* Old thread */
- testl %ecx,%ecx /* no thread? */
+ xorq %rax, %rax
+ movl PCPU(CPUID), %eax
+ testq %rdi,%rdi /* no thread? */
jz 1f
/* release bit from old pm_active */
- movl TD_PROC(%ecx), %eax /* thread->td_proc */
- movl P_VMSPACE(%eax), %ebx /* proc->p_vmspace */
-#ifdef SMP
- lock
-#endif
- btrl %esi, VM_PMAP+PM_ACTIVE(%ebx) /* clear old */
+ movq TD_PROC(%rdi), %rdx /* oldtd->td_proc */
+ movq P_VMSPACE(%rdx), %rdx /* proc->p_vmspace */
+ btrq %rax, VM_PMAP+PM_ACTIVE(%rdx) /* clear old */
1:
- movl 8(%esp),%ecx /* New thread */
- movl TD_PCB(%ecx),%edx
-#ifdef SWTCH_OPTIM_STATS
- incl tlb_flush_count
-#endif
- movl PCB_CR3(%edx),%eax
- movl %eax,%cr3 /* new address space */
+ 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 */
- movl TD_PROC(%ecx),%eax
- movl P_VMSPACE(%eax), %ebx
-#ifdef SMP
- lock
-#endif
- btsl %esi, VM_PMAP+PM_ACTIVE(%ebx) /* set new */
+ movq TD_PROC(%rsi),%rdx
+ movq P_VMSPACE(%rdx), %rdx
+ btsq %rax, VM_PMAP+PM_ACTIVE(%rdx) /* set new */
jmp sw1
/*
@@ -95,278 +81,184 @@ ENTRY(cpu_throw)
*
* Save the current thread state, then select the next thread to run
* and load its state.
- * 0(%esp) = ret
- * 4(%esp) = oldtd
- * 8(%esp) = newtd
+ * %rdi = oldtd
+ * %rsi = newtd
*/
ENTRY(cpu_switch)
/* Switch to new thread. First, save context. */
- movl 4(%esp),%ecx
-
#ifdef INVARIANTS
- testl %ecx,%ecx /* no thread? */
+ testq %rdi,%rdi /* no thread? */
jz badsw2 /* no, panic */
#endif
- movl TD_PCB(%ecx),%edx
+ movq TD_PCB(%rdi),%rdx
- movl (%esp),%eax /* Hardware registers */
- movl %eax,PCB_EIP(%edx)
- movl %ebx,PCB_EBX(%edx)
- movl %esp,PCB_ESP(%edx)
- movl %ebp,PCB_EBP(%edx)
- movl %esi,PCB_ESI(%edx)
- movl %edi,PCB_EDI(%edx)
- movl %gs,PCB_GS(%edx)
- pushfl /* PSL */
- popl PCB_PSL(%edx)
+ movq (%rsp),%rax /* Hardware registers */
+ movq %rax,PCB_RIP(%rdx)
+ movq %rbx,PCB_RBX(%rdx)
+ movq %rsp,PCB_RSP(%rdx)
+ movq %rbp,PCB_RBP(%rdx)
+ movq %r12,PCB_R12(%rdx)
+ movq %r13,PCB_R13(%rdx)
+ movq %r14,PCB_R14(%rdx)
+ movq %r15,PCB_R15(%rdx)
+ pushfq /* PSL */
+ popq PCB_RFLAGS(%rdx)
- /* Test if debug registers should be saved. */
- testl $PCB_DBREGS,PCB_FLAGS(%edx)
- jz 1f /* no, skip over */
- movl %dr7,%eax /* yes, do the save */
- movl %eax,PCB_DR7(%edx)
- andl $0x0000fc00, %eax /* disable all watchpoints */
- movl %eax,%dr7
- movl %dr6,%eax
- movl %eax,PCB_DR6(%edx)
- movl %dr3,%eax
- movl %eax,PCB_DR3(%edx)
- movl %dr2,%eax
- movl %eax,PCB_DR2(%edx)
- movl %dr1,%eax
- movl %eax,PCB_DR1(%edx)
- movl %dr0,%eax
- movl %eax,PCB_DR0(%edx)
-1:
-
-#ifdef DEV_NPX
/* have we used fp, and need a save? */
- cmpl %ecx,PCPU(FPCURTHREAD)
+ cmpq %rdi,PCPU(FPCURTHREAD)
jne 1f
- addl $PCB_SAVEFPU,%edx /* h/w bugs make saving complicated */
- pushl %edx
+ pushq %rdi
+ pushq %rsi
+ addq $PCB_SAVEFPU,%rdx /* h/w bugs make saving complicated */
+ movq %rdx, %rdi
call npxsave /* do it in a big C function */
- popl %eax
+ popq %rsi
+ popq %rdi
1:
-#endif
/* Save is done. Now fire up new thread. Leave old vmspace. */
- movl %ecx,%edi
- movl 8(%esp),%ecx /* New thread */
#ifdef INVARIANTS
- testl %ecx,%ecx /* no thread? */
+ testq %rsi,%rsi /* no thread? */
jz badsw3 /* no, panic */
#endif
- movl TD_PCB(%ecx),%edx
- movl PCPU(CPUID), %esi
+ movq TD_PCB(%rsi),%rdx
+ xorq %rax, %rax
+ movl PCPU(CPUID), %eax
/* switch address space */
- movl PCB_CR3(%edx),%eax
-#ifdef LAZY_SWITCH
- cmpl $0,lazy_flush_enable
- je 1f
- cmpl %eax,IdlePTD /* Kernel address space? */
-#ifdef SWTCH_OPTIM_STATS
- je 3f
-#else
- je sw1
-#endif
-1:
-#endif
- movl %cr3,%ebx /* The same address space? */
- cmpl %ebx,%eax
-#ifdef SWTCH_OPTIM_STATS
- je 2f /* Yes, skip all that cruft */
-#else
- je sw1
-#endif
-#ifdef SWTCH_OPTIM_STATS
- incl tlb_flush_count
-#endif
- movl %eax,%cr3 /* new address space */
+ movq PCB_CR3(%rdx),%rdx
+ movq %rdx,%cr3 /* new address space */
/* Release bit from old pmap->pm_active */
- movl TD_PROC(%edi), %eax /* oldproc */
- movl P_VMSPACE(%eax), %ebx
-#ifdef SMP
- lock
-#endif
- btrl %esi, VM_PMAP+PM_ACTIVE(%ebx) /* clear old */
+ movq TD_PROC(%rdi), %rdx /* oldproc */
+ movq P_VMSPACE(%rdx), %rdx
+ btrq %rax, VM_PMAP+PM_ACTIVE(%rdx) /* clear old */
/* Set bit in new pmap->pm_active */
- movl TD_PROC(%ecx),%eax /* newproc */
- movl P_VMSPACE(%eax), %ebx
-#ifdef SMP
- lock
-#endif
- btsl %esi, VM_PMAP+PM_ACTIVE(%ebx) /* set new */
-
-#ifdef LAZY_SWITCH
-#ifdef SWTCH_OPTIM_STATS
- jmp sw1
-
-2: /* same address space */
- incl swtch_optim_stats
- jmp sw1
-
-3: /* kernel address space */
- incl lazy_flush_count
-#endif
-#endif
+ movq TD_PROC(%rsi),%rdx /* newproc */
+ movq P_VMSPACE(%rdx), %rdx
+ btsq %rax, VM_PMAP+PM_ACTIVE(%rdx) /* set new */
sw1:
/*
* At this point, we've switched address spaces and are ready
* to load up the rest of the next context.
*/
- cmpl $0, PCB_EXT(%edx) /* has pcb extension? */
- je 1f /* If not, use the default */
- btsl %esi, private_tss /* mark use of private tss */
- movl PCB_EXT(%edx), %edi /* new tss descriptor */
- jmp 2f /* Load it up */
+ movq TD_PCB(%rsi),%rdx
-1: /*
- * Use the common default TSS instead of our own.
- * Set our stack pointer into the TSS, it's set to just
- * below the PCB. In C, common_tss.tss_esp0 = &pcb - 16;
- */
- leal -16(%edx), %ebx /* leave space for vm86 */
- movl %ebx, PCPU(COMMON_TSS) + TSS_ESP0
-
- /*
- * Test this CPU's bit in the bitmap to see if this
- * CPU was using a private TSS.
- */
- btrl %esi, private_tss /* Already using the common? */
- jae 3f /* if so, skip reloading */
- PCPU_ADDR(COMMON_TSSD, %edi)
-2:
- /* Move correct tss descriptor into GDT slot, then reload tr. */
- movl PCPU(TSS_GDT), %ebx /* entry in GDT */
- movl 0(%edi), %eax
- movl %eax, 0(%ebx)
- movl 4(%edi), %eax
- movl %eax, 4(%ebx)
- movl $GPROC0_SEL*8, %esi /* GSEL(entry, SEL_KPL) */
- ltr %si
-3:
+ /* Update the TSS_RSP0 pointer for the next interrupt */
+ leaq -16(%rdx), %rbx
+ movq %rbx, common_tss + COMMON_TSS_RSP0
/* Restore context. */
- movl PCB_EBX(%edx),%ebx
- movl PCB_ESP(%edx),%esp
- movl PCB_EBP(%edx),%ebp
- movl PCB_ESI(%edx),%esi
- movl PCB_EDI(%edx),%edi
- movl PCB_EIP(%edx),%eax
- movl %eax,(%esp)
- pushl PCB_PSL(%edx)
- popfl
-
- movl %edx, PCPU(CURPCB)
- movl %ecx, PCPU(CURTHREAD) /* into next thread */
+ movq PCB_RBX(%rdx),%rbx
+ movq PCB_RSP(%rdx),%rsp
+ movq PCB_RBP(%rdx),%rbp
+ movq PCB_R12(%rdx),%r12
+ movq PCB_R13(%rdx),%r13
+ movq PCB_R14(%rdx),%r14
+ movq PCB_R15(%rdx),%r15
+ movq PCB_RIP(%rdx),%rax
+ movq %rax,(%rsp)
+ pushq PCB_RFLAGS(%rdx)
+ popfq
+
+ movq %rdx, PCPU(CURPCB)
+ movq %rsi, PCPU(CURTHREAD) /* into next thread */
- /*
- * Determine the LDT to use and load it if is the default one and
- * that is not the current one.
- */
- movl TD_PROC(%ecx),%eax
- cmpl $0,P_MD+MD_LDT(%eax)
- jnz 1f
- movl _default_ldt,%eax
- cmpl PCPU(CURRENTLDT),%eax
- je 2f
- lldt _default_ldt
- movl %eax,PCPU(CURRENTLDT)
- jmp 2f
-1:
- /* Load the LDT when it is not the default one. */
- pushl %edx /* Preserve pointer to pcb. */
- addl $P_MD,%eax /* Pointer to mdproc is arg. */
- pushl %eax
- call set_user_ldt
- addl $4,%esp
- popl %edx
-2:
-
- /* This must be done after loading the user LDT. */
- .globl cpu_switch_load_gs
-cpu_switch_load_gs:
- movl PCB_GS(%edx),%gs
-
- /* Test if debug registers should be restored. */
- testl $PCB_DBREGS,PCB_FLAGS(%edx)
- jz 1f
-
- /*
- * Restore debug registers. The special code for dr7 is to
- * preserve the current values of its reserved bits.
- */
- movl PCB_DR6(%edx),%eax
- movl %eax,%dr6
- movl PCB_DR3(%edx),%eax
- movl %eax,%dr3
- movl PCB_DR2(%edx),%eax
- movl %eax,%dr2
- movl PCB_DR1(%edx),%eax
- movl %eax,%dr1
- movl PCB_DR0(%edx),%eax
- movl %eax,%dr0
- movl %dr7,%eax
- andl $0x0000fc00,%eax
- movl PCB_DR7(%edx),%ecx
- andl $~0x0000fc00,%ecx
- orl %ecx,%eax
- movl %eax,%dr7
-1:
ret
#ifdef INVARIANTS
badsw1:
- pushal
- pushl $sw0_1
+ pushq %rax
+ pushq %rcx
+ pushq %rdx
+ pushq %rbx
+ pushq %rbp
+ pushq %rsi
+ pushq %rdi
+ pushq %r8
+ pushq %r9
+ pushq %r10
+ pushq %r11
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ pushq $sw0_1
call panic
sw0_1: .asciz "cpu_throw: no newthread supplied"
badsw2:
- pushal
- pushl $sw0_2
+ pushq %rax
+ pushq %rcx
+ pushq %rdx
+ pushq %rbx
+ pushq %rbp
+ pushq %rsi
+ pushq %rdi
+ pushq %r8
+ pushq %r9
+ pushq %r10
+ pushq %r11
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ pushq $sw0_2
call panic
sw0_2: .asciz "cpu_switch: no curthread supplied"
badsw3:
- pushal
- pushl $sw0_3
+ pushq %rax
+ pushq %rcx
+ pushq %rdx
+ pushq %rbx
+ pushq %rbp
+ pushq %rsi
+ pushq %rdi
+ pushq %r8
+ pushq %r9
+ pushq %r10
+ pushq %r11
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ pushq $sw0_3
call panic
sw0_3: .asciz "cpu_switch: no newthread supplied"
#endif
+noswitch: .asciz "cpu_switch: called!"
+nothrow: .asciz "cpu_throw: called!"
/*
* savectx(pcb)
* Update pcb, saving current processor state.
*/
ENTRY(savectx)
/* Fetch PCB. */
- movl 4(%esp),%ecx
+ movq %rdi,%rcx
- /* Save caller's return address. Child won't execute this routine. */
- movl (%esp),%eax
- movl %eax,PCB_EIP(%ecx)
+ /* Save caller's return address. */
+ movq (%rsp),%rax
+ movq %rax,PCB_RIP(%rcx)
- movl %cr3,%eax
- movl %eax,PCB_CR3(%ecx)
+ movq %cr3,%rax
+ movq %rax,PCB_CR3(%rcx)
- movl %ebx,PCB_EBX(%ecx)
- movl %esp,PCB_ESP(%ecx)
- movl %ebp,PCB_EBP(%ecx)
- movl %esi,PCB_ESI(%ecx)
- movl %edi,PCB_EDI(%ecx)
- movl %gs,PCB_GS(%ecx)
- pushfl
- popl PCB_PSL(%ecx)
+ movq %rbx,PCB_RBX(%rcx)
+ movq %rsp,PCB_RSP(%rcx)
+ movq %rbp,PCB_RBP(%rcx)
+ movq %r12,PCB_R12(%rcx)
+ movq %r13,PCB_R13(%rcx)
+ movq %r14,PCB_R14(%rcx)
+ movq %r15,PCB_R15(%rcx)
+ pushfq
+ popq PCB_RFLAGS(%rcx)
-#ifdef DEV_NPX
/*
* If fpcurthread == NULL, then the npx h/w state is irrelevant and the
* state had better already be in the pcb. This is true for forks
@@ -379,30 +271,25 @@ ENTRY(savectx)
* have to handle h/w bugs for reloading. We used to lose the
* parent's npx state for forks by forgetting to reload.
*/
- pushfl
+ pushfq
cli
- movl PCPU(FPCURTHREAD),%eax
- testl %eax,%eax
+ movq PCPU(FPCURTHREAD),%rax
+ testq %rax,%rax
je 1f
- pushl %ecx
- movl TD_PCB(%eax),%eax
- leal PCB_SAVEFPU(%eax),%eax
- pushl %eax
- pushl %eax
+ pushq %rcx
+ pushq %rax
+ movq TD_PCB(%rax),%rdi
+ leaq PCB_SAVEFPU(%rdi),%rdi
call npxsave
- addl $4,%esp
- popl %eax
- popl %ecx
+ popq %rax
+ popq %rcx
- pushl $PCB_SAVEFPU_SIZE
- leal PCB_SAVEFPU(%ecx),%ecx
- pushl %ecx
- pushl %eax
+ movq $PCB_SAVEFPU_SIZE,%rdx /* arg 3 */
+ leaq PCB_SAVEFPU(%rcx),%rsi /* arg 2 */
+ movq %rax,%rdi /* arg 1 */
call bcopy
- addl $12,%esp
1:
- popfl
-#endif /* DEV_NPX */
+ popfq
ret
diff --git a/sys/amd64/amd64/sys_machdep.c b/sys/amd64/amd64/sys_machdep.c
index e1ed61780e50..c815a59bc085 100644
--- a/sys/amd64/amd64/sys_machdep.c
+++ b/sys/amd64/amd64/sys_machdep.c
@@ -35,46 +35,11 @@
*
*/
-#include "opt_kstack_pages.h"
-#include "opt_mac.h"
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/lock.h>
-#include <sys/mac.h>
-#include <sys/malloc.h>
-#include <sys/mutex.h>
#include <sys/proc.h>
-#include <sys/smp.h>
#include <sys/sysproto.h>
-#include <sys/user.h>
-
-#include <vm/vm.h>
-#include <vm/pmap.h>
-#include <vm/vm_map.h>
-#include <vm/vm_extern.h>
-
-#include <machine/cpu.h>
-#include <machine/pcb_ext.h> /* pcb.h included by sys/user.h */
-#include <machine/proc.h>
-#include <machine/sysarch.h>
-
-#include <vm/vm_kern.h> /* for kernel_map */
-
-#define MAX_LD 8192
-#define LD_PER_PAGE 512
-#define NEW_MAX_LD(num) ((num + LD_PER_PAGE) & ~(LD_PER_PAGE-1))
-#define SIZE_FROM_LARGEST_LD(num) (NEW_MAX_LD(num) << 3)
-
-
-
-static int i386_get_ldt(struct thread *, char *);
-static int i386_set_ldt(struct thread *, char *);
-static int i386_get_ioperm(struct thread *, char *);
-static int i386_set_ioperm(struct thread *, char *);
-#ifdef SMP
-static void set_user_ldt_rv(struct thread *);
-#endif
#ifndef _SYS_SYSPROTO_H_
struct sysarch_args {
@@ -90,476 +55,10 @@ sysarch(td, uap)
{
int error;
- mtx_lock(&Giant);
switch(uap->op) {
- case I386_GET_LDT:
- error = i386_get_ldt(td, uap->parms);
- break;
-
- case I386_SET_LDT:
- error = i386_set_ldt(td, uap->parms);
- break;
- case I386_GET_IOPERM:
- error = i386_get_ioperm(td, uap->parms);
- break;
- case I386_SET_IOPERM:
- error = i386_set_ioperm(td, uap->parms);
- break;
- case I386_VM86:
- error = vm86_sysarch(td, uap->parms);
- break;
default:
error = EINVAL;
break;
}
- mtx_unlock(&Giant);
- return (error);
-}
-
-int
-i386_extend_pcb(struct thread *td)
-{
- int i, offset;
- u_long *addr;
- struct pcb_ext *ext;
- struct soft_segment_descriptor ssd = {
- 0, /* segment base address (overwritten) */
- ctob(IOPAGES + 1) - 1, /* length */
- SDT_SYS386TSS, /* segment type */
- 0, /* priority level */
- 1, /* descriptor present */
- 0, 0,
- 0, /* default 32 size */
- 0 /* granularity */
- };
-
- if (td->td_proc->p_flag & P_THREADED)
- return (EINVAL); /* XXXKSE */
-/* XXXKSE All the code below only works in 1:1 needs changing */
- ext = (struct pcb_ext *)kmem_alloc(kernel_map, ctob(IOPAGES+1));
- if (ext == 0)
- return (ENOMEM);
- bzero(ext, sizeof(struct pcb_ext));
- /* -16 is so we can convert a trapframe into vm86trapframe inplace */
- ext->ext_tss.tss_esp0 = td->td_kstack + ctob(KSTACK_PAGES) -
- sizeof(struct pcb) - 16;
- ext->ext_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL);
- /*
- * The last byte of the i/o map must be followed by an 0xff byte.
- * We arbitrarily allocate 16 bytes here, to keep the starting
- * address on a doubleword boundary.
- */
- offset = PAGE_SIZE - 16;
- ext->ext_tss.tss_ioopt =
- (offset - ((unsigned)&ext->ext_tss - (unsigned)ext)) << 16;
- ext->ext_iomap = (caddr_t)ext + offset;
- ext->ext_vm86.vm86_intmap = (caddr_t)ext + offset - 32;
-
- addr = (u_long *)ext->ext_vm86.vm86_intmap;
- for (i = 0; i < (ctob(IOPAGES) + 32 + 16) / sizeof(u_long); i++)
- *addr++ = ~0;
-
- ssd.ssd_base = (unsigned)&ext->ext_tss;
- ssd.ssd_limit -= ((unsigned)&ext->ext_tss - (unsigned)ext);
- ssdtosd(&ssd, &ext->ext_tssd);
-
- KASSERT(td->td_proc == curthread->td_proc, ("giving TSS to !curproc"));
- KASSERT(td->td_pcb->pcb_ext == 0, ("already have a TSS!"));
- mtx_lock_spin(&sched_lock);
- td->td_pcb->pcb_ext = ext;
-
- /* switch to the new TSS after syscall completes */
- td->td_flags |= TDF_NEEDRESCHED;
- mtx_unlock_spin(&sched_lock);
-
- return 0;
-}
-
-static int
-i386_set_ioperm(td, args)
- struct thread *td;
- char *args;
-{
- int i, error;
- struct i386_ioperm_args ua;
- char *iomap;
-
- if ((error = copyin(args, &ua, sizeof(struct i386_ioperm_args))) != 0)
- return (error);
-
-#ifdef MAC
- if ((error = mac_check_sysarch_ioperm(td->td_ucred)) != 0)
- return (error);
-#endif
- if ((error = suser(td)) != 0)
- return (error);
- if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
- return (error);
- /*
- * XXX
- * While this is restricted to root, we should probably figure out
- * whether any other driver is using this i/o address, as so not to
- * cause confusion. This probably requires a global 'usage registry'.
- */
-
- if (td->td_pcb->pcb_ext == 0)
- if ((error = i386_extend_pcb(td)) != 0)
- return (error);
- iomap = (char *)td->td_pcb->pcb_ext->ext_iomap;
-
- if (ua.start + ua.length > IOPAGES * PAGE_SIZE * NBBY)
- return (EINVAL);
-
- for (i = ua.start; i < ua.start + ua.length; i++) {
- if (ua.enable)
- iomap[i >> 3] &= ~(1 << (i & 7));
- else
- iomap[i >> 3] |= (1 << (i & 7));
- }
- return (error);
-}
-
-static int
-i386_get_ioperm(td, args)
- struct thread *td;
- char *args;
-{
- int i, state, error;
- struct i386_ioperm_args ua;
- char *iomap;
-
- if ((error = copyin(args, &ua, sizeof(struct i386_ioperm_args))) != 0)
- return (error);
- if (ua.start >= IOPAGES * PAGE_SIZE * NBBY)
- return (EINVAL);
-
- if (td->td_pcb->pcb_ext == 0) {
- ua.length = 0;
- goto done;
- }
-
- iomap = (char *)td->td_pcb->pcb_ext->ext_iomap;
-
- i = ua.start;
- state = (iomap[i >> 3] >> (i & 7)) & 1;
- ua.enable = !state;
- ua.length = 1;
-
- for (i = ua.start + 1; i < IOPAGES * PAGE_SIZE * NBBY; i++) {
- if (state != ((iomap[i >> 3] >> (i & 7)) & 1))
- break;
- ua.length++;
- }
-
-done:
- error = copyout(&ua, args, sizeof(struct i386_ioperm_args));
return (error);
}
-
-/*
- * Update the GDT entry pointing to the LDT to point to the LDT of the
- * current process.
- *
- * This must be called with sched_lock held. Unfortunately, we can't use a
- * mtx_assert() here because cpu_switch() calls this function after changing
- * curproc but before sched_lock's owner is updated in mi_switch().
- */
-void
-set_user_ldt(struct mdproc *mdp)
-{
- struct proc_ldt *pldt;
-
- pldt = mdp->md_ldt;
-#ifdef SMP
- gdt[PCPU_GET(cpuid) * NGDT + GUSERLDT_SEL].sd = pldt->ldt_sd;
-#else
- gdt[GUSERLDT_SEL].sd = pldt->ldt_sd;
-#endif
- lldt(GSEL(GUSERLDT_SEL, SEL_KPL));
- PCPU_SET(currentldt, GSEL(GUSERLDT_SEL, SEL_KPL));
-}
-
-#ifdef SMP
-static void
-set_user_ldt_rv(struct thread *td)
-{
-
- if (td->td_proc != curthread->td_proc)
- return;
-
- mtx_lock_spin(&sched_lock);
- set_user_ldt(&td->td_proc->p_md);
- mtx_unlock_spin(&sched_lock);
-}
-#endif
-
-/*
- * Must be called with either sched_lock free or held but not recursed.
- * If it does not return NULL, it will return with it owned.
- */
-struct proc_ldt *
-user_ldt_alloc(struct mdproc *mdp, int len)
-{
- struct proc_ldt *pldt, *new_ldt;
-
- if (mtx_owned(&sched_lock))
- mtx_unlock_spin(&sched_lock);
- mtx_assert(&sched_lock, MA_NOTOWNED);
- MALLOC(new_ldt, struct proc_ldt *, sizeof(struct proc_ldt),
- M_SUBPROC, M_WAITOK);
-
- new_ldt->ldt_len = len = NEW_MAX_LD(len);
- new_ldt->ldt_base = (caddr_t)kmem_alloc(kernel_map,
- len * sizeof(union descriptor));
- if (new_ldt->ldt_base == NULL) {
- FREE(new_ldt, M_SUBPROC);
- return NULL;
- }
- new_ldt->ldt_refcnt = 1;
- new_ldt->ldt_active = 0;
-
- mtx_lock_spin(&sched_lock);
- gdt_segs[GUSERLDT_SEL].ssd_base = (unsigned)new_ldt->ldt_base;
- gdt_segs[GUSERLDT_SEL].ssd_limit = len * sizeof(union descriptor) - 1;
- ssdtosd(&gdt_segs[GUSERLDT_SEL], &new_ldt->ldt_sd);
-
- if ((pldt = mdp->md_ldt)) {
- if (len > pldt->ldt_len)
- len = pldt->ldt_len;
- bcopy(pldt->ldt_base, new_ldt->ldt_base,
- len * sizeof(union descriptor));
- } else {
- bcopy(ldt, new_ldt->ldt_base, sizeof(ldt));
- }
- return new_ldt;
-}
-
-/*
- * Must be called either with sched_lock free or held but not recursed.
- * If md_ldt is not NULL, it will return with sched_lock released.
- */
-void
-user_ldt_free(struct thread *td)
-{
- struct mdproc *mdp = &td->td_proc->p_md;
- struct proc_ldt *pldt = mdp->md_ldt;
-
- if (pldt == NULL)
- return;
-
- if (!mtx_owned(&sched_lock))
- mtx_lock_spin(&sched_lock);
- mtx_assert(&sched_lock, MA_OWNED | MA_NOTRECURSED);
- if (td == PCPU_GET(curthread)) {
- lldt(_default_ldt);
- PCPU_SET(currentldt, _default_ldt);
- }
-
- mdp->md_ldt = NULL;
- if (--pldt->ldt_refcnt == 0) {
- mtx_unlock_spin(&sched_lock);
- kmem_free(kernel_map, (vm_offset_t)pldt->ldt_base,
- pldt->ldt_len * sizeof(union descriptor));
- FREE(pldt, M_SUBPROC);
- } else
- mtx_unlock_spin(&sched_lock);
-}
-
-static int
-i386_get_ldt(td, args)
- struct thread *td;
- char *args;
-{
- int error = 0;
- struct proc_ldt *pldt = td->td_proc->p_md.md_ldt;
- int nldt, num;
- union descriptor *lp;
- struct i386_ldt_args ua, *uap = &ua;
-
- if ((error = copyin(args, uap, sizeof(struct i386_ldt_args))) < 0)
- return(error);
-
-#ifdef DEBUG
- printf("i386_get_ldt: start=%d num=%d descs=%p\n",
- uap->start, uap->num, (void *)uap->descs);
-#endif
-
- /* verify range of LDTs exist */
- if ((uap->start < 0) || (uap->num <= 0))
- return(EINVAL);
-
- if (pldt) {
- nldt = pldt->ldt_len;
- num = min(uap->num, nldt);
- lp = &((union descriptor *)(pldt->ldt_base))[uap->start];
- } else {
- nldt = sizeof(ldt)/sizeof(ldt[0]);
- num = min(uap->num, nldt);
- lp = &ldt[uap->start];
- }
- if (uap->start + num > nldt)
- return(EINVAL);
-
- error = copyout(lp, uap->descs, num * sizeof(union descriptor));
- if (!error)
- td->td_retval[0] = num;
-
- return(error);
-}
-
-static int
-i386_set_ldt(td, args)
- struct thread *td;
- char *args;
-{
- int error = 0, i, n;
- int largest_ld;
- struct mdproc *mdp = &td->td_proc->p_md;
- struct proc_ldt *pldt = mdp->md_ldt;
- struct i386_ldt_args ua, *uap = &ua;
- union descriptor *descs;
- caddr_t old_ldt_base;
- int descs_size, old_ldt_len;
- register_t savecrit;
-
- if ((error = copyin(args, uap, sizeof(struct i386_ldt_args))) < 0)
- return(error);
-
-#ifdef DEBUG
- printf("i386_set_ldt: start=%d num=%d descs=%p\n",
- uap->start, uap->num, (void *)uap->descs);
-#endif
-
- /* verify range of descriptors to modify */
- if ((uap->start < 0) || (uap->start >= MAX_LD) || (uap->num < 0) ||
- (uap->num > MAX_LD))
- {
- return(EINVAL);
- }
- largest_ld = uap->start + uap->num - 1;
- if (largest_ld >= MAX_LD)
- return(EINVAL);
-
- /* allocate user ldt */
- if (!pldt || largest_ld >= pldt->ldt_len) {
- struct proc_ldt *new_ldt = user_ldt_alloc(mdp, largest_ld);
- if (new_ldt == NULL)
- return ENOMEM;
- if (pldt) {
- old_ldt_base = pldt->ldt_base;
- old_ldt_len = pldt->ldt_len;
- pldt->ldt_sd = new_ldt->ldt_sd;
- pldt->ldt_base = new_ldt->ldt_base;
- pldt->ldt_len = new_ldt->ldt_len;
- mtx_unlock_spin(&sched_lock);
- kmem_free(kernel_map, (vm_offset_t)old_ldt_base,
- old_ldt_len * sizeof(union descriptor));
- FREE(new_ldt, M_SUBPROC);
-#ifndef SMP
- mtx_lock_spin(&sched_lock);
-#endif
- } else {
- mdp->md_ldt = pldt = new_ldt;
-#ifdef SMP
- mtx_unlock_spin(&sched_lock);
-#endif
- }
-#ifdef SMP
- /* signal other cpus to reload ldt */
- smp_rendezvous(NULL, (void (*)(void *))set_user_ldt_rv,
- NULL, td);
-#else
- set_user_ldt(mdp);
- mtx_unlock_spin(&sched_lock);
-#endif
- }
-
- descs_size = uap->num * sizeof(union descriptor);
- descs = (union descriptor *)kmem_alloc(kernel_map, descs_size);
- if (descs == NULL)
- return (ENOMEM);
- error = copyin(&uap->descs[0], descs, descs_size);
- if (error) {
- kmem_free(kernel_map, (vm_offset_t)descs, descs_size);
- return (error);
- }
- /* Check descriptors for access violations */
- for (i = 0, n = uap->start; i < uap->num; i++, n++) {
- union descriptor *dp;
- dp = &descs[i];
-
- switch (dp->sd.sd_type) {
- case SDT_SYSNULL: /* system null */
- dp->sd.sd_p = 0;
- break;
- case SDT_SYS286TSS: /* system 286 TSS available */
- case SDT_SYSLDT: /* system local descriptor table */
- case SDT_SYS286BSY: /* system 286 TSS busy */
- case SDT_SYSTASKGT: /* system task gate */
- case SDT_SYS286IGT: /* system 286 interrupt gate */
- case SDT_SYS286TGT: /* system 286 trap gate */
- case SDT_SYSNULL2: /* undefined by Intel */
- case SDT_SYS386TSS: /* system 386 TSS available */
- case SDT_SYSNULL3: /* undefined by Intel */
- case SDT_SYS386BSY: /* system 386 TSS busy */
- case SDT_SYSNULL4: /* undefined by Intel */
- case SDT_SYS386IGT: /* system 386 interrupt gate */
- case SDT_SYS386TGT: /* system 386 trap gate */
- case SDT_SYS286CGT: /* system 286 call gate */
- case SDT_SYS386CGT: /* system 386 call gate */
- /* I can't think of any reason to allow a user proc
- * to create a segment of these types. They are
- * for OS use only.
- */
- kmem_free(kernel_map, (vm_offset_t)descs, descs_size);
- return EACCES;
- /*NOTREACHED*/
-
- /* memory segment types */
- case SDT_MEMEC: /* memory execute only conforming */
- case SDT_MEMEAC: /* memory execute only accessed conforming */
- case SDT_MEMERC: /* memory execute read conforming */
- case SDT_MEMERAC: /* memory execute read accessed conforming */
- /* Must be "present" if executable and conforming. */
- if (dp->sd.sd_p == 0) {
- kmem_free(kernel_map, (vm_offset_t)descs,
- descs_size);
- return (EACCES);
- }
- break;
- case SDT_MEMRO: /* memory read only */
- case SDT_MEMROA: /* memory read only accessed */
- case SDT_MEMRW: /* memory read write */
- case SDT_MEMRWA: /* memory read write accessed */
- case SDT_MEMROD: /* memory read only expand dwn limit */
- case SDT_MEMRODA: /* memory read only expand dwn lim accessed */
- case SDT_MEMRWD: /* memory read write expand dwn limit */
- case SDT_MEMRWDA: /* memory read write expand dwn lim acessed */
- case SDT_MEME: /* memory execute only */
- case SDT_MEMEA: /* memory execute only accessed */
- case SDT_MEMER: /* memory execute read */
- case SDT_MEMERA: /* memory execute read accessed */
- break;
- default:
- kmem_free(kernel_map, (vm_offset_t)descs, descs_size);
- return(EINVAL);
- /*NOTREACHED*/
- }
-
- /* Only user (ring-3) descriptors may be present. */
- if ((dp->sd.sd_p != 0) && (dp->sd.sd_dpl != SEL_UPL)) {
- kmem_free(kernel_map, (vm_offset_t)descs, descs_size);
- return (EACCES);
- }
- }
-
- /* Fill in range */
- savecrit = intr_disable();
- bcopy(descs,
- &((union descriptor *)(pldt->ldt_base))[uap->start],
- uap->num * sizeof(union descriptor));
- td->td_retval[0] = uap->start;
- intr_restore(savecrit);
- kmem_free(kernel_map, (vm_offset_t)descs, descs_size);
- return (0);
-}
diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index 2884b86ffcb8..980e95f606aa 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -47,8 +47,6 @@
#include "opt_ddb.h"
#include "opt_isa.h"
#include "opt_ktrace.h"
-#include "opt_npx.h"
-#include "opt_trap.h"
#include <sys/param.h>
#include <sys/bus.h>
@@ -81,39 +79,22 @@
#include <machine/cpu.h>
#include <machine/md_var.h>
#include <machine/pcb.h>
-#ifdef SMP
-#include <machine/smp.h>
-#endif
#include <machine/tss.h>
-#include <i386/isa/icu.h>
-#include <i386/isa/intr_machdep.h>
-
-#ifdef POWERFAIL_NMI
-#include <sys/syslog.h>
-#include <machine/clock.h>
-#endif
-
-#include <machine/vm86.h>
+#include <amd64/isa/icu.h>
+#include <amd64/isa/intr_machdep.h>
#include <ddb/ddb.h>
#include <sys/sysctl.h>
-int (*pmath_emulate)(struct trapframe *);
-
extern void trap(struct trapframe frame);
-#ifdef I386_CPU
-extern int trapwrite(unsigned addr);
-#endif
extern void syscall(struct trapframe frame);
static int trap_pfault(struct trapframe *, int, vm_offset_t);
static void trap_fatal(struct trapframe *, vm_offset_t);
void dblfault_handler(void);
-extern inthand_t IDTVEC(lcall_syscall);
-
#define MAX_TRAP_MSG 28
static char *trap_msg[] = {
"", /* 0 unused */
@@ -147,10 +128,6 @@ static char *trap_msg[] = {
"machine check trap", /* 28 T_MCHK */
};
-#if defined(I586_CPU) && !defined(NO_F00F_HACK)
-extern int has_f00f_bug;
-#endif
-
#ifdef DDB
static int ddb_on_nmi = 1;
SYSCTL_INT(_machdep, OID_AUTO, ddb_on_nmi, CTLFLAG_RW,
@@ -185,9 +162,6 @@ trap(frame)
u_int sticks = 0;
int i = 0, ucode = 0, type, code;
vm_offset_t eva;
-#ifdef POWERFAIL_NMI
- static int lastalert = 0;
-#endif
atomic_add_int(&cnt.v_trap, 1);
type = frame.tf_trapno;
@@ -200,7 +174,7 @@ trap(frame)
}
#endif
- if ((frame.tf_eflags & PSL_I) == 0) {
+ if ((frame.tf_rflags & PSL_I) == 0) {
/*
* Buggy application or kernel code has disabled
* interrupts and then trapped. Enabling interrupts
@@ -208,12 +182,11 @@ trap(frame)
* interrupts disabled until they are accidentally
* enabled later.
*/
- if (ISPL(frame.tf_cs) == SEL_UPL || (frame.tf_eflags & PSL_VM))
+ 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);
- else if (type != T_BPTFLT && type != T_TRCTRAP &&
- frame.tf_eip != (int)cpu_switch_load_gs) {
+ else if (type != T_BPTFLT && type != T_TRCTRAP) {
/*
* XXX not quite right, since this may be for a
* multiple fault in user mode.
@@ -234,12 +207,6 @@ trap(frame)
code = frame.tf_err;
if (type == T_PAGEFLT) {
/*
- * For some Cyrix CPUs, %cr2 is clobbered by
- * interrupts. This problem is worked around by using
- * an interrupt gate for the pagefault handler. We
- * are finally ready to read %cr2 and then must
- * reenable interrupts.
- *
* If we get a page fault while holding a spin lock, then
* it is most likely a fatal kernel page fault. The kernel
* is already going to panic trying to get a sleep lock to
@@ -248,9 +215,7 @@ trap(frame)
* to the debugger.
*/
eva = rcr2();
- if (PCPU_GET(spinlocks) == NULL)
- enable_intr();
- else
+ if (PCPU_GET(spinlocks) != NULL)
trap_fatal(&frame, eva);
}
@@ -259,9 +224,7 @@ trap(frame)
ether_poll(poll_in_trap);
#endif /* DEVICE_POLLING */
- if ((ISPL(frame.tf_cs) == SEL_UPL) ||
- ((frame.tf_eflags & PSL_VM) &&
- !(PCPU_GET(curpcb)->pcb_flags & PCB_VM86CALL))) {
+ if (ISPL(frame.tf_cs) == SEL_UPL) {
/* user trap */
sticks = td->td_sticks;
@@ -277,36 +240,19 @@ trap(frame)
case T_BPTFLT: /* bpt instruction fault */
case T_TRCTRAP: /* trace trap */
- frame.tf_eflags &= ~PSL_T;
+ frame.tf_rflags &= ~PSL_T;
i = SIGTRAP;
break;
case T_ARITHTRAP: /* arithmetic trap */
-#ifdef DEV_NPX
ucode = npxtrap();
if (ucode == -1)
goto userout;
-#else
- ucode = code;
-#endif
i = SIGFPE;
break;
- /*
- * The following two traps can happen in
- * vm86 mode, and, if so, we want to handle
- * them specially.
- */
case T_PROTFLT: /* general protection fault */
case T_STKFLT: /* stack fault */
- if (frame.tf_eflags & PSL_VM) {
- i = vm86_emulate((struct vm86frame *)&frame);
- if (i == 0)
- goto user;
- break;
- }
- /* FALLTHROUGH */
-
case T_SEGNPFLT: /* segment not present fault */
case T_TSSFLT: /* invalid TSS fault */
case T_DOUBLEFLT: /* double fault */
@@ -317,21 +263,6 @@ trap(frame)
case T_PAGEFLT: /* page fault */
i = trap_pfault(&frame, TRUE, eva);
-#if defined(I586_CPU) && !defined(NO_F00F_HACK)
- if (i == -2) {
- /*
- * The f00f hack workaround has triggered, so
- * treat the fault as an illegal instruction
- * (T_PRIVINFLT) instead of a page fault.
- */
- type = frame.tf_trapno = T_PRIVINFLT;
-
- /* Proceed as in that case. */
- ucode = type;
- i = SIGILL;
- break;
- }
-#endif
if (i == -1)
goto userout;
if (i == 0)
@@ -347,19 +278,6 @@ trap(frame)
#ifdef DEV_ISA
case T_NMI:
-#ifdef POWERFAIL_NMI
-#ifndef TIMER_FREQ
-# define TIMER_FREQ 1193182
-#endif
- mtx_lock(&Giant);
- if (time_second - lastalert > 10) {
- log(LOG_WARNING, "NMI: power fail\n");
- sysbeep(TIMER_FREQ/880, hz);
- lastalert = time_second;
- }
- mtx_unlock(&Giant);
- goto userout;
-#else /* !POWERFAIL_NMI */
/* machine/parity/power fail/"kitchen sink" faults */
/* XXX Giant */
if (isa_nmi(code) == 0) {
@@ -377,7 +295,6 @@ trap(frame)
} else if (panic_on_nmi)
panic("NMI indicates hardware failure");
break;
-#endif /* POWERFAIL_NMI */
#endif /* DEV_ISA */
case T_OFLOW: /* integer overflow fault */
@@ -391,26 +308,11 @@ trap(frame)
break;
case T_DNA:
-#ifdef DEV_NPX
/* transparent fault (due to context switch "late") */
if (npxdna())
goto userout;
-#endif
- if (!pmath_emulate) {
- i = SIGFPE;
- ucode = FPE_FPU_NP_TRAP;
- break;
- }
- mtx_lock(&Giant);
- i = (*pmath_emulate)(&frame);
- mtx_unlock(&Giant);
- if (i == 0) {
- if (!(frame.tf_eflags & PSL_T))
- goto userout;
- frame.tf_eflags &= ~PSL_T;
- i = SIGTRAP;
- }
- /* else ucode = emulator_only_knows() XXX */
+ i = SIGFPE;
+ ucode = FPE_FPU_NP_TRAP;
break;
case T_FPOPFLT: /* FPU operand fetch fault */
@@ -434,61 +336,22 @@ trap(frame)
goto out;
case T_DNA:
-#ifdef DEV_NPX
/*
* The kernel is apparently using npx for copying.
* XXX this should be fatal unless the kernel has
* registered such use.
*/
- if (npxdna())
+ if (npxdna()) {
+ printf("npxdna in kernel mode!\n");
goto out;
-#endif
+ }
break;
- /*
- * The following two traps can happen in
- * vm86 mode, and, if so, we want to handle
- * them specially.
- */
- case T_PROTFLT: /* general protection fault */
case T_STKFLT: /* stack fault */
- if (frame.tf_eflags & PSL_VM) {
- i = vm86_emulate((struct vm86frame *)&frame);
- if (i != 0)
- /*
- * returns to original process
- */
- vm86_trap((struct vm86frame *)&frame);
- goto out;
- }
- if (type == T_STKFLT)
- break;
-
- /* FALL THROUGH */
+ break;
+ case T_PROTFLT: /* general protection fault */
case T_SEGNPFLT: /* segment not present fault */
- if (PCPU_GET(curpcb)->pcb_flags & PCB_VM86CALL)
- break;
-
- /*
- * Invalid %fs's and %gs's can be created using
- * procfs or PT_SETREGS or by invalidating the
- * underlying LDT entry. This causes a fault
- * in kernel mode when the kernel attempts to
- * switch contexts. Lose the bad context
- * (XXX) so that we can continue, and generate
- * a signal.
- */
- if (frame.tf_eip == (int)cpu_switch_load_gs) {
- PCPU_GET(curpcb)->pcb_gs = 0;
-#if 0
- PROC_LOCK(p);
- psignal(p, SIGBUS);
- PROC_UNLOCK(p);
-#endif
- goto out;
- }
-
if (td->td_intr_nesting_level != 0)
break;
@@ -502,26 +365,14 @@ trap(frame)
* selectors and pointers when the user changes
* them.
*/
- if (frame.tf_eip == (int)doreti_iret) {
- frame.tf_eip = (int)doreti_iret_fault;
- goto out;
- }
- if (frame.tf_eip == (int)doreti_popl_ds) {
- frame.tf_eip = (int)doreti_popl_ds_fault;
- goto out;
- }
- if (frame.tf_eip == (int)doreti_popl_es) {
- frame.tf_eip = (int)doreti_popl_es_fault;
- goto out;
- }
- if (frame.tf_eip == (int)doreti_popl_fs) {
- frame.tf_eip = (int)doreti_popl_fs_fault;
+ if (frame.tf_rip == (long)doreti_iret) {
+ frame.tf_rip = (long)doreti_iret_fault;
goto out;
}
if (PCPU_GET(curpcb) != NULL &&
PCPU_GET(curpcb)->pcb_onfault != NULL) {
- frame.tf_eip =
- (int)PCPU_GET(curpcb)->pcb_onfault;
+ frame.tf_rip =
+ (long)PCPU_GET(curpcb)->pcb_onfault;
goto out;
}
break;
@@ -536,50 +387,13 @@ trap(frame)
* problem here and not every time the kernel is
* entered.
*/
- if (frame.tf_eflags & PSL_NT) {
- frame.tf_eflags &= ~PSL_NT;
+ if (frame.tf_rflags & PSL_NT) {
+ frame.tf_rflags &= ~PSL_NT;
goto out;
}
break;
case T_TRCTRAP: /* trace trap */
- if (frame.tf_eip == (int)IDTVEC(lcall_syscall)) {
- /*
- * We've just entered system mode via the
- * syscall lcall. Continue single stepping
- * silently until the syscall handler has
- * saved the flags.
- */
- goto out;
- }
- if (frame.tf_eip == (int)IDTVEC(lcall_syscall) + 1) {
- /*
- * The syscall handler has now saved the
- * flags. Stop single stepping it.
- */
- frame.tf_eflags &= ~PSL_T;
- goto out;
- }
- /*
- * Ignore debug register trace traps due to
- * accesses in the user's address space, which
- * can happen under several conditions such as
- * if a user sets a watchpoint on a buffer and
- * then passes that buffer to a system call.
- * We still want to get TRCTRAPS for addresses
- * in kernel space because that is useful when
- * debugging the kernel.
- */
- /* XXX Giant */
- if (user_dbreg_trap() &&
- !(PCPU_GET(curpcb)->pcb_flags & PCB_VM86CALL)) {
- /*
- * Reset breakpoint bits because the
- * processor doesn't
- */
- load_dr6(rdr6() & 0xfffffff0);
- goto out;
- }
/*
* FALLTHROUGH (TRCTRAP kernel mode, kernel address)
*/
@@ -597,16 +411,6 @@ trap(frame)
#ifdef DEV_ISA
case T_NMI:
-#ifdef POWERFAIL_NMI
- mtx_lock(&Giant);
- if (time_second - lastalert > 10) {
- log(LOG_WARNING, "NMI: power fail\n");
- sysbeep(TIMER_FREQ/880, hz);
- lastalert = time_second;
- }
- mtx_unlock(&Giant);
- goto out;
-#else /* !POWERFAIL_NMI */
/* XXX Giant */
/* machine/parity/power fail/"kitchen sink" faults */
if (isa_nmi(code) == 0) {
@@ -624,7 +428,6 @@ trap(frame)
} else if (panic_on_nmi == 0)
goto out;
/* FALLTHROUGH */
-#endif /* POWERFAIL_NMI */
#endif /* DEV_ISA */
}
@@ -677,16 +480,7 @@ trap_pfault(frame, usermode, eva)
if (va >= KERNBASE) {
/*
* Don't allow user-mode faults in kernel address space.
- * An exception: if the faulting address is the invalid
- * instruction entry in the IDT, then the Intel Pentium
- * F00F bug workaround was triggered, and we need to
- * treat it is as an illegal instruction, and not a page
- * fault.
*/
-#if defined(I586_CPU) && !defined(NO_F00F_HACK)
- if ((eva == (unsigned int)&idt[6]) && has_f00f_bug)
- return -2;
-#endif
if (usermode)
goto nogo;
@@ -742,7 +536,7 @@ nogo:
if (td->td_intr_nesting_level == 0 &&
PCPU_GET(curpcb) != NULL &&
PCPU_GET(curpcb)->pcb_onfault != NULL) {
- frame->tf_eip = (int)PCPU_GET(curpcb)->pcb_onfault;
+ frame->tf_rip = (long)PCPU_GET(curpcb)->pcb_onfault;
return (0);
}
trap_fatal(frame, eva);
@@ -765,18 +559,12 @@ trap_fatal(frame, eva)
code = frame->tf_err;
type = frame->tf_trapno;
- sdtossd(&gdt[IDXSEL(frame->tf_cs & 0xffff)].sd, &softseg);
+ sdtossd(&gdt[IDXSEL(frame->tf_cs & 0xffff)], &softseg);
if (type <= MAX_TRAP_MSG)
printf("\n\nFatal trap %d: %s while in %s mode\n",
type, trap_msg[type],
- frame->tf_eflags & PSL_VM ? "vm86" :
ISPL(frame->tf_cs) == SEL_UPL ? "user" : "kernel");
-#ifdef SMP
- /* two separate prints in case of a trap on an unmapped page */
- printf("cpuid = %d; ", PCPU_GET(cpuid));
- printf("lapic.id = %08x\n", lapic.id);
-#endif
if (type == T_PAGEFLT) {
printf("fault virtual address = 0x%x\n", eva);
printf("fault code = %s %s, %s\n",
@@ -785,33 +573,31 @@ trap_fatal(frame, eva)
code & PGEX_P ? "protection violation" : "page not present");
}
printf("instruction pointer = 0x%x:0x%x\n",
- frame->tf_cs & 0xffff, frame->tf_eip);
- if ((ISPL(frame->tf_cs) == SEL_UPL) || (frame->tf_eflags & PSL_VM)) {
+ frame->tf_cs & 0xffff, frame->tf_rip);
+ if (ISPL(frame->tf_cs) == SEL_UPL) {
ss = frame->tf_ss & 0xffff;
- esp = frame->tf_esp;
+ esp = frame->tf_rsp;
} else {
ss = GSEL(GDATA_SEL, SEL_KPL);
- esp = (int)&frame->tf_esp;
+ esp = (long)&frame->tf_rsp;
}
printf("stack pointer = 0x%x:0x%x\n", ss, esp);
- printf("frame pointer = 0x%x:0x%x\n", ss, frame->tf_ebp);
+ printf("frame pointer = 0x%x:0x%x\n", ss, frame->tf_rbp);
printf("code segment = base 0x%x, limit 0x%x, type 0x%x\n",
softseg.ssd_base, softseg.ssd_limit, softseg.ssd_type);
- printf(" = DPL %d, pres %d, def32 %d, gran %d\n",
- softseg.ssd_dpl, softseg.ssd_p, softseg.ssd_def32,
+ printf(" = DPL %d, pres %d, long %d, def32 %d, gran %d\n",
+ softseg.ssd_dpl, softseg.ssd_p, softseg.ssd_long, softseg.ssd_def32,
softseg.ssd_gran);
printf("processor eflags = ");
- if (frame->tf_eflags & PSL_T)
+ if (frame->tf_rflags & PSL_T)
printf("trace trap, ");
- if (frame->tf_eflags & PSL_I)
+ if (frame->tf_rflags & PSL_I)
printf("interrupt enabled, ");
- if (frame->tf_eflags & PSL_NT)
+ if (frame->tf_rflags & PSL_NT)
printf("nested task, ");
- if (frame->tf_eflags & PSL_RF)
+ if (frame->tf_rflags & PSL_RF)
printf("resume, ");
- if (frame->tf_eflags & PSL_VM)
- printf("vm86, ");
- printf("IOPL = %d\n", (frame->tf_eflags & PSL_IOPL) >> 12);
+ printf("IOPL = %d\n", (frame->tf_rflags & PSL_IOPL) >> 12);
printf("current process = ");
if (curproc) {
printf("%lu (%s)\n",
@@ -841,75 +627,14 @@ trap_fatal(frame, eva)
* a frame for a trap/exception onto the stack. This usually occurs
* when the stack overflows (such is the case with infinite recursion,
* for example).
- *
- * XXX Note that the current PTD gets replaced by IdlePTD when the
- * task switch occurs. This means that the stack that was active at
- * the time of the double fault is not available at <kstack> unless
- * the machine was idle when the double fault occurred. The downside
- * of this is that "trace <ebp>" in ddb won't work.
*/
void
dblfault_handler()
{
- printf("\nFatal double fault:\n");
- printf("eip = 0x%x\n", PCPU_GET(common_tss.tss_eip));
- printf("esp = 0x%x\n", PCPU_GET(common_tss.tss_esp));
- printf("ebp = 0x%x\n", PCPU_GET(common_tss.tss_ebp));
-#ifdef SMP
- /* two separate prints in case of a trap on an unmapped page */
- printf("cpuid = %d; ", PCPU_GET(cpuid));
- printf("lapic.id = %08x\n", lapic.id);
-#endif
+ printf("\nFatal double fault\n");
panic("double fault");
}
-#ifdef I386_CPU
-/*
- * Compensate for 386 brain damage (missing URKR).
- * This is a little simpler than the pagefault handler in trap() because
- * it the page tables have already been faulted in and high addresses
- * are thrown out early for other reasons.
- */
-int trapwrite(addr)
- unsigned addr;
-{
- struct thread *td;
- struct proc *p;
- vm_offset_t va;
- struct vmspace *vm;
- int rv;
-
- va = trunc_page((vm_offset_t)addr);
- /*
- * XXX - MAX is END. Changed > to >= for temp. fix.
- */
- if (va >= VM_MAXUSER_ADDRESS)
- return (1);
-
- td = curthread;
- p = td->td_proc;
- vm = p->p_vmspace;
-
- PROC_LOCK(p);
- ++p->p_lock;
- PROC_UNLOCK(p);
-
- /*
- * fault the data page
- */
- rv = vm_fault(&vm->vm_map, va, VM_PROT_WRITE, VM_FAULT_DIRTY);
-
- PROC_LOCK(p);
- --p->p_lock;
- PROC_UNLOCK(p);
-
- if (rv != KERN_SUCCESS)
- return 1;
-
- return (0);
-}
-#endif
-
/*
* syscall - system call request C handler
*
@@ -923,12 +648,14 @@ syscall(frame)
struct sysent *callp;
struct thread *td = curthread;
struct proc *p = td->td_proc;
- register_t orig_tf_eflags;
+ register_t orig_tf_rflags;
u_int sticks;
int error;
int narg;
- int args[8];
+ register_t args[8];
+ register_t *argp;
u_int code;
+ int reg, regcnt;
/*
* note: PCPU_LAZY_INC() can only be used if we can afford
@@ -945,39 +672,28 @@ syscall(frame)
}
#endif
+ reg = 0;
+ regcnt = 6;
sticks = td->td_sticks;
td->td_frame = &frame;
if (td->td_ucred != p->p_ucred)
cred_update_thread(td);
if (p->p_flag & P_THREADED)
thread_user_enter(p, td);
- params = (caddr_t)frame.tf_esp + sizeof(int);
- code = frame.tf_eax;
- orig_tf_eflags = frame.tf_eflags;
+ 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, args, &code, &params);
+ (*p->p_sysent->sv_prepsyscall)(&frame, (int *)args, &code, &params);
} else {
- /*
- * Need to check if this is a 32 bit or 64 bit syscall.
- * fuword is MP aware.
- */
- if (code == SYS_syscall) {
- /*
- * Code is first argument, followed by actual args.
- */
- code = fuword(params);
- params += sizeof(int);
- } else if (code == SYS___syscall) {
- /*
- * Like syscall, but code is a quad, so as to maintain
- * quad alignment for the rest of the arguments.
- */
- code = fuword(params);
- params += sizeof(quad_t);
+ if (code == SYS_syscall || code == SYS___syscall) {
+ code = frame.tf_rdi;
+ reg++;
+ regcnt--;
}
}
@@ -994,15 +710,25 @@ syscall(frame)
/*
* copyin and the ktrsyscall()/ktrsysret() code is MP-aware
*/
- if (params != NULL && narg != 0)
- error = copyin(params, (caddr_t)args,
- (u_int)(narg * sizeof(int)));
- else
+ if (narg <= regcnt) {
+ argp = &frame.tf_rdi;
+ argp += reg;
error = 0;
-
+ } else {
+ KASSERT(narg <= sizeof(args) / sizeof(args[0]),
+ ("Too many syscall arguments!"));
+ KASSERT(params != NULL, ("copyin args with no params!"));
+ argp = &frame.tf_rdi;
+ argp += reg;
+ bcopy(argp, args, sizeof(args[0]) * regcnt);
+ error = copyin(params, &args[regcnt],
+ (narg - regcnt) * sizeof(args[0]));
+ argp = &args[0];
+ }
+
#ifdef KTRACE
if (KTRPOINT(td, KTR_SYSCALL))
- ktrsyscall(code, narg, args);
+ ktrsyscall(code, narg, argp);
#endif
/*
@@ -1014,18 +740,18 @@ syscall(frame)
if (error == 0) {
td->td_retval[0] = 0;
- td->td_retval[1] = frame.tf_edx;
+ td->td_retval[1] = frame.tf_rdx;
STOPEVENT(p, S_SCE, narg);
- error = (*callp->sy_call)(td, args);
+ error = (*callp->sy_call)(td, argp);
}
switch (error) {
case 0:
- frame.tf_eax = td->td_retval[0];
- frame.tf_edx = td->td_retval[1];
- frame.tf_eflags &= ~PSL_C;
+ frame.tf_rax = td->td_retval[0];
+ frame.tf_rdx = td->td_retval[1];
+ frame.tf_rflags &= ~PSL_C;
break;
case ERESTART:
@@ -1033,7 +759,7 @@ syscall(frame)
* Reconstruct pc, assuming lcall $X,y is 7 bytes,
* int 0x80 is 2 bytes. We saved this in tf_err.
*/
- frame.tf_eip -= frame.tf_err;
+ frame.tf_rip -= frame.tf_err;
break;
case EJUSTRETURN:
@@ -1046,8 +772,8 @@ syscall(frame)
else
error = p->p_sysent->sv_errtbl[error];
}
- frame.tf_eax = error;
- frame.tf_eflags |= PSL_C;
+ frame.tf_rax = error;
+ frame.tf_rflags |= PSL_C;
break;
}
@@ -1060,8 +786,8 @@ syscall(frame)
/*
* Traced syscall.
*/
- if ((orig_tf_eflags & PSL_T) && !(orig_tf_eflags & PSL_VM)) {
- frame.tf_eflags &= ~PSL_T;
+ if (orig_tf_rflags & PSL_T) {
+ frame.tf_rflags &= ~PSL_T;
trapsignal(td, SIGTRAP, 0);
}
diff --git a/sys/amd64/amd64/tsc.c b/sys/amd64/amd64/tsc.c
index 36ae1b9e134c..e3757181fccc 100644
--- a/sys/amd64/amd64/tsc.c
+++ b/sys/amd64/amd64/tsc.c
@@ -42,7 +42,7 @@
uint64_t tsc_freq;
int tsc_is_broken;
-u_int tsc_present;
+u_int tsc_present = 1;
#ifdef SMP
static int smp_tsc;
@@ -66,14 +66,6 @@ init_TSC(void)
{
u_int64_t tscval[2];
- if (cpu_feature & CPUID_TSC)
- tsc_present = 1;
- else
- tsc_present = 0;
-
- if (!tsc_present)
- return;
-
if (bootverbose)
printf("Calibrating TSC clock ... ");
@@ -83,38 +75,9 @@ init_TSC(void)
tsc_freq = tscval[1] - tscval[0];
if (bootverbose)
- printf("TSC clock: %ju Hz\n", (intmax_t)tsc_freq);
-
-#ifdef SMP
- /*
- * We can not use the TSC in SMP mode unless the TSCs on all CPUs
- * are somehow synchronized. Some hardware configurations do
- * this, but we have no way of determining whether this is the
- * case, so we do not use the TSC in multi-processor systems
- * unless the user indicated (by setting kern.timecounter.smp_tsc
- * to 1) that he believes that his TSCs are synchronized.
- */
- if (mp_ncpus > 1 && !smp_tsc)
- return;
-#endif
-
- /*
- * We can not use the TSC if we support APM. Precise timekeeping
- * on an APM'ed machine is at best a fools pursuit, since
- * any and all of the time spent in various SMM code can't
- * be reliably accounted for. Reading the RTC is your only
- * source of reliable time info. The i8254 looses too of course
- * but we need to have some kind of time...
- * We don't know at this point whether APM is going to be used
- * or not, nor when it might be activated. Play it safe.
- */
- if (power_pm_get_type() == POWER_PM_TYPE_APM) {
- if (bootverbose)
- printf("TSC timecounter disabled: APM enabled.\n");
- return;
- }
+ printf("TSC clock: %lu Hz\n", tsc_freq);
- if (tsc_present && tsc_freq != 0 && !tsc_is_broken) {
+ if (tsc_freq != 0 && !tsc_is_broken) {
tsc_timecounter.tc_frequency = tsc_freq;
tc_init(&tsc_timecounter);
}
@@ -139,7 +102,7 @@ sysctl_machdep_tsc_freq(SYSCTL_HANDLER_ARGS)
return (error);
}
-SYSCTL_PROC(_machdep, OID_AUTO, tsc_freq, CTLTYPE_QUAD | CTLFLAG_RW,
+SYSCTL_PROC(_machdep, OID_AUTO, tsc_freq, CTLTYPE_LONG | CTLFLAG_RW,
0, sizeof(u_int), sysctl_machdep_tsc_freq, "IU", "");
static unsigned
diff --git a/sys/amd64/amd64/vm_machdep.c b/sys/amd64/amd64/vm_machdep.c
index bdb189fa4dd1..a4ebe9c41264 100644
--- a/sys/amd64/amd64/vm_machdep.c
+++ b/sys/amd64/amd64/vm_machdep.c
@@ -41,11 +41,6 @@
* $FreeBSD$
*/
-#include "opt_npx.h"
-#ifdef PC98
-#include "opt_pc98.h"
-#endif
-#include "opt_reset.h"
#include "opt_isa.h"
#include "opt_kstack_pages.h"
@@ -61,15 +56,12 @@
#include <sys/kernel.h>
#include <sys/ktr.h>
#include <sys/mutex.h>
-#include <sys/smp.h>
#include <sys/sysctl.h>
#include <sys/unistd.h>
#include <machine/cpu.h>
#include <machine/md_var.h>
#include <machine/pcb.h>
-#include <machine/pcb_ext.h>
-#include <machine/vm86.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
@@ -81,18 +73,9 @@
#include <sys/user.h>
-#ifdef PC98
-#include <pc98/pc98/pc98.h>
-#else
-#include <i386/isa/isa.h>
-#endif
+#include <amd64/isa/isa.h>
static void cpu_reset_real(void);
-#ifdef SMP
-static void cpu_reset_proxy(void);
-static u_int cpu_reset_proxyid;
-static volatile u_int cpu_reset_proxy_active;
-#endif
extern int _ucodesel, _udatasel;
/*
@@ -110,37 +93,17 @@ cpu_fork(td1, p2, td2, flags)
register struct proc *p1;
struct pcb *pcb2;
struct mdproc *mdp2;
-#ifdef DEV_NPX
register_t savecrit;
-#endif
p1 = td1->td_proc;
- if ((flags & RFPROC) == 0) {
- if ((flags & RFMEM) == 0) {
- /* unshare user LDT */
- struct mdproc *mdp1 = &p1->p_md;
- struct proc_ldt *pldt = mdp1->md_ldt;
- if (pldt && pldt->ldt_refcnt > 1) {
- pldt = user_ldt_alloc(mdp1, pldt->ldt_len);
- if (pldt == NULL)
- panic("could not copy LDT");
- mdp1->md_ldt = pldt;
- set_user_ldt(mdp1);
- user_ldt_free(td1);
- }
- }
+ if ((flags & RFPROC) == 0)
return;
- }
/* Ensure that p1's pcb is up to date. */
-#ifdef DEV_NPX
- if (td1 == curthread)
- td1->td_pcb->pcb_gs = rgs();
savecrit = intr_disable();
if (PCPU_GET(fpcurthread) == td1)
npxsave(&td1->td_pcb->pcb_save);
intr_restore(savecrit);
-#endif
/* Point the pcb to the top of the stack */
pcb2 = (struct pcb *)(td2->td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1;
@@ -157,63 +120,34 @@ cpu_fork(td1, p2, td2, flags)
* Create a new fresh stack for the new process.
* Copy the trap frame for the return to user mode as if from a
* syscall. This copies most of the user mode register values.
- * The -16 is so we can expand the trapframe if we go to vm86.
*/
- td2->td_frame = (struct trapframe *)((caddr_t)td2->td_pcb - 16) - 1;
+ td2->td_frame = (struct trapframe *)td2->td_pcb - 1;
bcopy(td1->td_frame, td2->td_frame, sizeof(struct trapframe));
- td2->td_frame->tf_eax = 0; /* Child returns zero */
- td2->td_frame->tf_eflags &= ~PSL_C; /* success */
- td2->td_frame->tf_edx = 1;
+ td2->td_frame->tf_rax = 0; /* Child returns zero */
+ td2->td_frame->tf_rflags &= ~PSL_C; /* success */
+ td2->td_frame->tf_rdx = 1;
/*
* Set registers for trampoline to user mode. Leave space for the
* return address on stack. These are the kernel mode register values.
*/
-#ifdef PAE
- pcb2->pcb_cr3 = vtophys(vmspace_pmap(p2->p_vmspace)->pm_pdpt);
-#else
- pcb2->pcb_cr3 = vtophys(vmspace_pmap(p2->p_vmspace)->pm_pdir);
-#endif
- pcb2->pcb_edi = 0;
- pcb2->pcb_esi = (int)fork_return; /* fork_trampoline argument */
- pcb2->pcb_ebp = 0;
- pcb2->pcb_esp = (int)td2->td_frame - sizeof(void *);
- pcb2->pcb_ebx = (int)td2; /* fork_trampoline argument */
- pcb2->pcb_eip = (int)fork_trampoline;
- pcb2->pcb_psl = td2->td_frame->tf_eflags & ~PSL_I; /* ints disabled */
- pcb2->pcb_gs = rgs();
+ pcb2->pcb_cr3 = vtophys(vmspace_pmap(p2->p_vmspace)->pm_pml4);
+ pcb2->pcb_r12 = (register_t)fork_return; /* fork_trampoline argument */
+ pcb2->pcb_rbp = 0;
+ pcb2->pcb_rsp = (register_t)td2->td_frame - sizeof(void *);
+ pcb2->pcb_rbx = (register_t)td2; /* fork_trampoline argument */
+ pcb2->pcb_rip = (register_t)fork_trampoline;
+ pcb2->pcb_rflags = td2->td_frame->tf_rflags & ~PSL_I; /* ints disabled */
/*-
- * pcb2->pcb_dr*: cloned above.
* pcb2->pcb_savefpu: cloned above.
* pcb2->pcb_flags: cloned above.
* pcb2->pcb_onfault: cloned above (always NULL here?).
- * pcb2->pcb_gs: cloned above.
- * pcb2->pcb_ext: cleared below.
- */
-
- /*
- * XXX don't copy the i/o pages. this should probably be fixed.
*/
- pcb2->pcb_ext = 0;
-
- /* Copy the LDT, if necessary. */
- mtx_lock_spin(&sched_lock);
- if (mdp2->md_ldt != 0) {
- if (flags & RFMEM) {
- mdp2->md_ldt->ldt_refcnt++;
- } else {
- mdp2->md_ldt = user_ldt_alloc(mdp2,
- mdp2->md_ldt->ldt_len);
- if (mdp2->md_ldt == NULL)
- panic("could not copy LDT");
- }
- }
- mtx_unlock_spin(&sched_lock);
/*
* Now, cpu_switch() can schedule the new process.
- * pcb_esp is loaded pointing to the cpu_switch() stack frame
+ * pcb_rsp is loaded pointing to the cpu_switch() stack frame
* containing the return address when exiting cpu_switch.
* This will normally be to fork_trampoline(), which will have
* %ebx loaded with the new proc's pointer. fork_trampoline()
@@ -238,8 +172,8 @@ cpu_set_fork_handler(td, func, arg)
* Note that the trap frame follows the args, so the function
* is really called like this: func(arg, frame);
*/
- td->td_pcb->pcb_esi = (int) func; /* function */
- td->td_pcb->pcb_ebx = (int) arg; /* first arg */
+ td->td_pcb->pcb_r12 = (long) func; /* function */
+ td->td_pcb->pcb_rbx = (long) arg; /* first arg */
}
void
@@ -247,51 +181,19 @@ cpu_exit(struct thread *td)
{
struct mdproc *mdp;
- /* Reset pc->pcb_gs and %gs before possibly invalidating it. */
mdp = &td->td_proc->p_md;
- if (mdp->md_ldt) {
- td->td_pcb->pcb_gs = _udatasel;
- load_gs(_udatasel);
- user_ldt_free(td);
- }
- reset_dbregs();
}
void
cpu_thread_exit(struct thread *td)
{
- struct pcb *pcb = td->td_pcb;
-#ifdef DEV_NPX
+
npxexit(td);
-#endif
- if (pcb->pcb_flags & PCB_DBREGS) {
- /*
- * disable all hardware breakpoints
- */
- reset_dbregs();
- pcb->pcb_flags &= ~PCB_DBREGS;
- }
}
void
cpu_thread_clean(struct thread *td)
{
- struct pcb *pcb;
-
- pcb = td->td_pcb;
- if (pcb->pcb_ext != 0) {
- /* XXXKSE XXXSMP not SMP SAFE.. what locks do we have? */
- /* if (pcb->pcb_ext->ext_refcount-- == 1) ?? */
- /*
- * XXX do we need to move the TSS off the allocated pages
- * before freeing them? (not done here)
- */
- mtx_lock(&Giant);
- kmem_free(kernel_map, (vm_offset_t)pcb->pcb_ext,
- ctob(IOPAGES + 1));
- mtx_unlock(&Giant);
- pcb->pcb_ext = 0;
- }
}
void
@@ -306,7 +208,7 @@ cpu_thread_setup(struct thread *td)
td->td_pcb =
(struct pcb *)(td->td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1;
- td->td_frame = (struct trapframe *)((caddr_t)td->td_pcb - 16) - 1;
+ td->td_frame = (struct trapframe *)td->td_pcb - 1;
}
/*
@@ -319,61 +221,6 @@ cpu_thread_setup(struct thread *td)
void
cpu_set_upcall(struct thread *td, void *pcb)
{
- struct pcb *pcb2;
-
- /* Point the pcb to the top of the stack. */
- pcb2 = td->td_pcb;
-
- /*
- * Copy the upcall pcb. This loads kernel regs.
- * Those not loaded individually below get their default
- * values here.
- *
- * XXXKSE It might be a good idea to simply skip this as
- * the values of the other registers may be unimportant.
- * This would remove any requirement for knowing the KSE
- * at this time (see the matching comment below for
- * more analysis) (need a good safe default).
- */
- bcopy(pcb, pcb2, sizeof(*pcb2));
-
- /*
- * Create a new fresh stack for the new thread.
- * The -16 is so we can expand the trapframe if we go to vm86.
- * Don't forget to set this stack value into whatever supplies
- * the address for the fault handlers.
- * The contexts are filled in at the time we actually DO the
- * upcall as only then do we know which KSE we got.
- */
- td->td_frame = (struct trapframe *)((caddr_t)pcb2 - 16) - 1;
-
- /*
- * Set registers for trampoline to user mode. Leave space for the
- * return address on stack. These are the kernel mode register values.
- */
-#ifdef PAE
- pcb2->pcb_cr3 = vtophys(vmspace_pmap(td->td_proc->p_vmspace)->pm_pdpt);
-#else
- pcb2->pcb_cr3 = vtophys(vmspace_pmap(td->td_proc->p_vmspace)->pm_pdir);
-#endif
- pcb2->pcb_edi = 0;
- pcb2->pcb_esi = (int)fork_return; /* trampoline arg */
- pcb2->pcb_ebp = 0;
- pcb2->pcb_esp = (int)td->td_frame - sizeof(void *); /* trampoline arg */
- pcb2->pcb_ebx = (int)td; /* trampoline arg */
- pcb2->pcb_eip = (int)fork_trampoline;
- pcb2->pcb_psl &= ~(PSL_I); /* interrupts must be disabled */
- pcb2->pcb_gs = rgs();
- /*
- * If we didn't copy the pcb, we'd need to do the following registers:
- * pcb2->pcb_dr*: cloned above.
- * pcb2->pcb_savefpu: cloned above.
- * pcb2->pcb_flags: cloned above.
- * pcb2->pcb_onfault: cloned above (always NULL here?).
- * pcb2->pcb_gs: cloned above. XXXKSE ???
- * pcb2->pcb_ext: cleared below.
- */
- pcb2->pcb_ext = NULL;
}
/*
@@ -384,30 +231,6 @@ cpu_set_upcall(struct thread *td, void *pcb)
void
cpu_set_upcall_kse(struct thread *td, struct kse_upcall *ku)
{
-
- /*
- * Do any extra cleaning that needs to be done.
- * The thread may have optional components
- * that are not present in a fresh thread.
- * This may be a recycled thread so make it look
- * as though it's newly allocated.
- */
- cpu_thread_clean(td);
-
- /*
- * Set the trap frame to point at the beginning of the uts
- * function.
- */
- td->td_frame->tf_esp =
- (int)ku->ku_stack.ss_sp + ku->ku_stack.ss_size - 16;
- td->td_frame->tf_eip = (int)ku->ku_func;
-
- /*
- * Pass the address of the mailbox for this kse to the uts
- * function as a parameter on the stack.
- */
- suword((void *)(td->td_frame->tf_esp + sizeof(void *)),
- (int)ku->ku_mailbox);
}
void
@@ -417,116 +240,29 @@ cpu_wait(p)
}
/*
- * Convert kernel VA to physical address
- */
-vm_paddr_t
-kvtop(void *addr)
-{
- vm_paddr_t pa;
-
- pa = pmap_kextract((vm_offset_t)addr);
- if (pa == 0)
- panic("kvtop: zero page frame");
- return (pa);
-}
-
-/*
* Force reset the processor by invalidating the entire address space!
*/
-#ifdef SMP
-static void
-cpu_reset_proxy()
-{
-
- cpu_reset_proxy_active = 1;
- while (cpu_reset_proxy_active == 1)
- ; /* Wait for other cpu to see that we've started */
- stop_cpus((1<<cpu_reset_proxyid));
- printf("cpu_reset_proxy: Stopped CPU %d\n", cpu_reset_proxyid);
- DELAY(1000000);
- cpu_reset_real();
-}
-#endif
-
void
cpu_reset()
{
-#ifdef SMP
- if (smp_active == 0) {
- cpu_reset_real();
- /* NOTREACHED */
- } else {
-
- u_int map;
- int cnt;
- printf("cpu_reset called on cpu#%d\n", PCPU_GET(cpuid));
-
- map = PCPU_GET(other_cpus) & ~ stopped_cpus;
-
- if (map != 0) {
- printf("cpu_reset: Stopping other CPUs\n");
- stop_cpus(map); /* Stop all other CPUs */
- }
-
- if (PCPU_GET(cpuid) == 0) {
- DELAY(1000000);
- cpu_reset_real();
- /* NOTREACHED */
- } else {
- /* We are not BSP (CPU #0) */
-
- cpu_reset_proxyid = PCPU_GET(cpuid);
- cpustop_restartfunc = cpu_reset_proxy;
- cpu_reset_proxy_active = 0;
- printf("cpu_reset: Restarting BSP\n");
- started_cpus = (1<<0); /* Restart CPU #0 */
-
- cnt = 0;
- while (cpu_reset_proxy_active == 0 && cnt < 10000000)
- cnt++; /* Wait for BSP to announce restart */
- if (cpu_reset_proxy_active == 0)
- printf("cpu_reset: Failed to restart BSP\n");
- enable_intr();
- cpu_reset_proxy_active = 2;
-
- while (1);
- /* NOTREACHED */
- }
- }
-#else
cpu_reset_real();
-#endif
}
static void
cpu_reset_real()
{
-#ifdef PC98
- /*
- * Attempt to do a CPU reset via CPU reset port.
- */
- disable_intr();
- if ((inb(0x35) & 0xa0) != 0xa0) {
- outb(0x37, 0x0f); /* SHUT0 = 0. */
- outb(0x37, 0x0b); /* SHUT1 = 0. */
- }
- outb(0xf0, 0x00); /* Reset. */
-#else
/*
* Attempt to do a CPU reset via the keyboard controller,
* do not turn of the GateA20, as any machine that fails
* to do the reset here would then end up in no man's land.
*/
-#if !defined(BROKEN_KEYBOARD_RESET)
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");
DELAY(1000000); /* wait 1 sec for printf to complete */
-#endif
-#endif /* PC98 */
/* force a shutdown by unmapping entire address space ! */
bzero((caddr_t)PTD, NBPTD);
diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC
index 5d615eedd385..bfa88a62e142 100644
--- a/sys/amd64/conf/GENERIC
+++ b/sys/amd64/conf/GENERIC
@@ -1,5 +1,5 @@
-#
-# GENERIC -- Generic kernel configuration file for FreeBSD/i386
+# ex:ts=8
+# GENERIC -- Generic kernel configuration file for FreeBSD/amd64
#
# For more information on this file, please read the handbook section on
# Kernel Configuration Files:
@@ -18,245 +18,80 @@
#
# $FreeBSD$
-machine i386
-cpu I486_CPU
-cpu I586_CPU
-cpu I686_CPU
+machine amd64
+cpu HAMMER
ident GENERIC
+maxusers 0
+
+makeoptions NO_MODULES=not_yet
#To statically compile in device wiring instead of /boot/device.hints
#hints "GENERIC.hints" #Default places to look for devices.
-makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols
-
options SCHED_4BSD #4BSD scheduler
options INET #InterNETworking
-options INET6 #IPv6 communications protocols
options FFS #Berkeley Fast Filesystem
options SOFTUPDATES #Enable FFS soft updates support
-options UFS_ACL #Support for access control lists
-options UFS_DIRHASH #Improve performance on big directories
options MD_ROOT #MD is a potential root device
options NFSCLIENT #Network Filesystem Client
-options NFSSERVER #Network Filesystem Server
+options NFSSERVER
options NFS_ROOT #NFS usable as root device, requires NFSCLIENT
-options MSDOSFS #MSDOS Filesystem
-options CD9660 #ISO 9660 Filesystem
-options PROCFS #Process filesystem (requires PSEUDOFS)
-options PSEUDOFS #Pseudo-filesystem framework
-options COMPAT_43 #Compatible with BSD 4.3 [KEEP THIS!]
-options COMPAT_FREEBSD4 #Compatible with FreeBSD4
-options SCSI_DELAY=15000 #Delay (in ms) before probing SCSI
-options KTRACE #ktrace(1) support
-options SYSVSHM #SYSV-style shared memory
-options SYSVMSG #SYSV-style message queues
-options SYSVSEM #SYSV-style semaphores
-options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions
-options KBD_INSTALL_CDEV # install a CDEV entry in /dev
-options AHC_REG_PRETTY_PRINT # Print register bitfields in debug
- # output. Adds ~128k to driver.
-options AHD_REG_PRETTY_PRINT # Print register bitfields in debug
- # output. Adds ~215k to driver.
# Debugging for use in -current
-options DDB #Enable the kernel debugger
options INVARIANTS #Enable calls of extra sanity checking
options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required by INVARIANTS
-options WITNESS #Enable checks to detect deadlocks and cycles
-options WITNESS_SKIPSPIN #Don't run witness on spinlocks for speed
-
-# To make an SMP kernel, the next two are needed
-#options SMP # Symmetric MultiProcessor Kernel
-#options APIC_IO # Symmetric (APIC) I/O
device isa
-device eisa
device pci
-# Floppy drives
-device fdc
-
# ATA and ATAPI devices
device ata
device atadisk # ATA disk drives
device atapicd # ATAPI CDROM drives
-device atapifd # ATAPI floppy drives
-device atapist # ATAPI tape drives
-options ATA_STATIC_ID #Static device numbering
-
-# SCSI Controllers
-device ahb # EISA AHA1742 family
-device ahc # AHA2940 and onboard AIC7xxx devices
-device ahd # AHA39320/29320 and onboard AIC79xx devices
-device amd # AMD 53C974 (Tekram DC-390(T))
-device isp # Qlogic family
-device mpt # LSI-Logic MPT-Fusion
-#device ncr # NCR/Symbios Logic
-device sym # NCR/Symbios Logic (newer chipsets + those of `ncr')
-device trm # Tekram DC395U/UW/F DC315U adapters
-device adv # Advansys SCSI adapters
-device adw # Advansys wide SCSI adapters
-device aha # Adaptec 154x SCSI adapters
-device aic # Adaptec 15[012]x SCSI adapters, AIC-6[23]60.
-device bt # Buslogic/Mylex MultiMaster SCSI adapters
-
-device ncv # NCR 53C500
-device nsp # Workbit Ninja SCSI-3
-device stg # TMC 18C30/18C50
-
-# RAID controllers interfaced to the SCSI subsystem
-device asr # DPT SmartRAID V, VI and Adaptec SCSI RAID
-device ciss # Compaq Smart RAID 5*
-device dpt # DPT Smartcache III, IV - See NOTES for options!
-device iir # Intel Integrated RAID
-device mly # Mylex AcceleRAID/eXtremeRAID
-
-# SCSI peripherals
-device scbus # SCSI bus (required)
-device ch # SCSI media changers
-device da # Direct Access (disks)
-device sa # Sequential Access (tape etc)
-device cd # CD
-device pass # Passthrough device (direct SCSI access)
-device ses # SCSI Environmental Services (and SAF-TE)
-
-# RAID controllers
-device aac # Adaptec FSA RAID
-device aacp # SCSI passthrough for aac (requires CAM)
-device amr # AMI MegaRAID
-device ida # Compaq Smart RAID
-device mlx # Mylex DAC960 family
-device pst # Promise Supertrak SX6000
-device twe # 3ware ATA RAID
+options KTRACE
# atkbdc0 controls both the keyboard and the PS/2 mouse
-device atkbdc # AT keyboard controller
-device atkbd # AT keyboard
-device psm # PS/2 mouse
+#device atkbdc # AT keyboard controller
+#device atkbd # AT keyboard
+#device psm # PS/2 mouse
-device vga # VGA video card driver
+#device vga # VGA video card driver
-device splash # Splash screen and screen saver support
+#device splash # Splash screen and screen saver support
# syscons is the default console driver, resembling an SCO console
-device sc
-
-# Enable this for the pcvt (VT220 compatible) console driver
-#device vt
-#options XSERVER # support for X server on a vt console
-#options FAT_CURSOR # start with block cursor
+#device sc
-device agp # support several AGP chipsets
-
-# Floating point support - do not disable.
-device npx
-
-# Power management support (see NOTES for more options)
-#device apm
-# Add suspend/resume support for the i8254.
-device pmtimer
-
-# PCCARD (PCMCIA) support
-# Pcmcia and cardbus bridge support
-device cbb # cardbus (yenta) bridge
-#device pcic # ExCA ISA and PCI bridges
-device pccard # PC Card (16-bit) bus
-device cardbus # CardBus (32-bit) bus
+#device agp # support several AGP chipsets
# Serial (COM) ports
device sio # 8250, 16[45]50 based serial ports
# Parallel port
-device ppc
-device ppbus # Parallel port bus (required)
-device lpt # Printer
-device plip # TCP/IP over parallel
-device ppi # Parallel port interface device
-#device vpo # Requires scbus and da
-
-
-# PCI Ethernet NICs.
-device de # DEC/Intel DC21x4x (``Tulip'')
-device em # Intel PRO/1000 adapter Gigabit Ethernet Card
-device txp # 3Com 3cR990 (``Typhoon'')
-device vx # 3Com 3c590, 3c595 (``Vortex'')
+#device ppc
+#device ppbus # Parallel port bus (required)
+#device lpt # Printer
# PCI Ethernet NICs that use the common MII bus controller code.
# NOTE: Be sure to keep the 'device miibus' line in order to use these NICs!
device miibus # MII bus support
-device dc # DEC/Intel 21143 and various workalikes
device fxp # Intel EtherExpress PRO/100B (82557, 82558)
-device pcn # AMD Am79C97x PCI 10/100 (precedence over 'lnc')
-device rl # RealTek 8129/8139
-device sf # Adaptec AIC-6915 (``Starfire'')
-device sis # Silicon Integrated Systems SiS 900/SiS 7016
-device ste # Sundance ST201 (D-Link DFE-550TX)
-device tl # Texas Instruments ThunderLAN
-device tx # SMC EtherPower II (83c170 ``EPIC'')
-device vr # VIA Rhine, Rhine II
-device wb # Winbond W89C840F
device xl # 3Com 3c90x (``Boomerang'', ``Cyclone'')
device bge # Broadcom BCM570xx Gigabit Ethernet
-# ISA Ethernet NICs. pccard nics included.
-device cs # Crystal Semiconductor CS89x0 NIC
-# 'device ed' requires 'device miibus'
-device ed # NE[12]000, SMC Ultra, 3c503, DS8390 cards
-device ex # Intel EtherExpress Pro/10 and Pro/10+
-device ep # Etherlink III based cards
-device fe # Fujitsu MB8696x based cards
-device ie # EtherExpress 8/16, 3C507, StarLAN 10 etc.
-device lnc # NE2100, NE32-VL Lance Ethernet cards
-device sn # SMC's 9000 series of ethernet chips
-device xe # Xircom pccard ethernet
-
-# ISA devices that use the old ISA shims
-#device le
-
-# Wireless NIC cards
-device wlan # 802.11 support
-device an # Aironet 4500/4800 802.11 wireless NICs.
-device awi # BayStack 660 and others
-device wi # WaveLAN/Intersil/Symbol 802.11 wireless NICs.
-#device wl # Older non 802.11 Wavelan wireless NIC.
-
# Pseudo devices - the number indicates how many units to allocate.
device random # Entropy device
device loop # Network loopback
device ether # Ethernet support
-device sl # Kernel SLIP
-device ppp # Kernel PPP
-device tun # Packet tunnel.
-device pty # Pseudo-ttys (telnet etc)
device md # Memory "disks"
-device gif # IPv6 and IPv4 tunneling
-device faith # IPv6-to-IPv4 relaying (translation)
-
-# The `bpf' device enables the Berkeley Packet Filter.
-# Be aware of the administrative consequences of enabling this!
-device bpf # Berkeley packet filter
+device pty
+device bpf
# USB support
-device uhci # UHCI PCI->USB interface
-device ohci # OHCI PCI->USB interface
-device usb # USB Bus (required)
-#device udbp # USB Double Bulk Pipe devices
-device ugen # Generic
-device uhid # "Human Interface Devices"
-device ukbd # Keyboard
-device ulpt # Printer
-device umass # Disks/Mass storage - Requires scbus and da
-device ums # Mouse
-device urio # Diamond Rio 500 MP3 player
-device uscanner # Scanners
-# USB Ethernet, requires mii
-device aue # ADMtek USB ethernet
-device axe # ASIX Electronics USB ethernet
-device cue # CATC USB ethernet
-device kue # Kawasaki LSI USB ethernet
-
-# FireWire support
-device firewire # FireWire bus code
-device sbp # SCSI over FireWire (Requires scbus and da)
-device fwe # Ethernet over FireWire (non-standard!)
+#device uhci # UHCI PCI->USB interface
+#device ohci # OHCI PCI->USB interface
+#device usb # USB Bus (required)
+#device ugen # Generic
+#device uhid # "Human Interface Devices"
+#device ukbd # Keyboard
diff --git a/sys/amd64/conf/GENERIC.hints b/sys/amd64/conf/GENERIC.hints
index 958f32956a66..6f63de4a71ec 100644
--- a/sys/amd64/conf/GENERIC.hints
+++ b/sys/amd64/conf/GENERIC.hints
@@ -33,8 +33,6 @@ hint.sc.0.at="isa"
hint.sc.0.flags="0x100"
hint.vt.0.at="isa"
hint.vt.0.disabled="1"
-hint.apm.0.disabled="1"
-hint.apm.0.flags="0x20"
hint.pcic.0.at="isa"
# hint.pcic.0.irq="10" # Default to polling
hint.pcic.0.port="0x3e0"
diff --git a/sys/amd64/include/_inttypes.h b/sys/amd64/include/_inttypes.h
index 7da589d8a771..e6b2536ff379 100644
--- a/sys/amd64/include/_inttypes.h
+++ b/sys/amd64/include/_inttypes.h
@@ -49,172 +49,172 @@
#define PRId8 "d" /* int8_t */
#define PRId16 "d" /* int16_t */
#define PRId32 "d" /* int32_t */
-#define PRId64 "lld" /* int64_t */
+#define PRId64 "ld" /* int64_t */
#define PRIdLEAST8 "d" /* int_least8_t */
#define PRIdLEAST16 "d" /* int_least16_t */
#define PRIdLEAST32 "d" /* int_least32_t */
-#define PRIdLEAST64 "lld" /* int_least64_t */
+#define PRIdLEAST64 "ld" /* int_least64_t */
#define PRIdFAST8 "d" /* int_fast8_t */
#define PRIdFAST16 "d" /* int_fast16_t */
#define PRIdFAST32 "d" /* int_fast32_t */
-#define PRIdFAST64 "lld" /* int_fast64_t */
+#define PRIdFAST64 "ld" /* int_fast64_t */
#define PRIdMAX "jd" /* intmax_t */
-#define PRIdPTR "d" /* intptr_t */
+#define PRIdPTR "ld" /* intptr_t */
#define PRIi8 "i" /* int8_t */
#define PRIi16 "i" /* int16_t */
#define PRIi32 "i" /* int32_t */
-#define PRIi64 "lli" /* int64_t */
+#define PRIi64 "li" /* int64_t */
#define PRIiLEAST8 "i" /* int_least8_t */
#define PRIiLEAST16 "i" /* int_least16_t */
#define PRIiLEAST32 "i" /* int_least32_t */
-#define PRIiLEAST64 "lli" /* int_least64_t */
+#define PRIiLEAST64 "li" /* int_least64_t */
#define PRIiFAST8 "i" /* int_fast8_t */
#define PRIiFAST16 "i" /* int_fast16_t */
#define PRIiFAST32 "i" /* int_fast32_t */
-#define PRIiFAST64 "lli" /* int_fast64_t */
+#define PRIiFAST64 "li" /* int_fast64_t */
#define PRIiMAX "ji" /* intmax_t */
-#define PRIiPTR "i" /* intptr_t */
+#define PRIiPTR "li" /* intptr_t */
/* fprintf(3) macros for unsigned integers. */
#define PRIo8 "o" /* uint8_t */
#define PRIo16 "o" /* uint16_t */
#define PRIo32 "o" /* uint32_t */
-#define PRIo64 "llo" /* uint64_t */
+#define PRIo64 "lo" /* uint64_t */
#define PRIoLEAST8 "o" /* uint_least8_t */
#define PRIoLEAST16 "o" /* uint_least16_t */
#define PRIoLEAST32 "o" /* uint_least32_t */
-#define PRIoLEAST64 "llo" /* uint_least64_t */
+#define PRIoLEAST64 "lo" /* uint_least64_t */
#define PRIoFAST8 "o" /* uint_fast8_t */
#define PRIoFAST16 "o" /* uint_fast16_t */
#define PRIoFAST32 "o" /* uint_fast32_t */
-#define PRIoFAST64 "llo" /* uint_fast64_t */
+#define PRIoFAST64 "lo" /* uint_fast64_t */
#define PRIoMAX "jo" /* uintmax_t */
-#define PRIoPTR "o" /* uintptr_t */
+#define PRIoPTR "lo" /* uintptr_t */
#define PRIu8 "u" /* uint8_t */
#define PRIu16 "u" /* uint16_t */
#define PRIu32 "u" /* uint32_t */
-#define PRIu64 "llu" /* uint64_t */
+#define PRIu64 "lu" /* uint64_t */
#define PRIuLEAST8 "u" /* uint_least8_t */
#define PRIuLEAST16 "u" /* uint_least16_t */
#define PRIuLEAST32 "u" /* uint_least32_t */
-#define PRIuLEAST64 "llu" /* uint_least64_t */
+#define PRIuLEAST64 "lu" /* uint_least64_t */
#define PRIuFAST8 "u" /* uint_fast8_t */
#define PRIuFAST16 "u" /* uint_fast16_t */
#define PRIuFAST32 "u" /* uint_fast32_t */
-#define PRIuFAST64 "llu" /* uint_fast64_t */
+#define PRIuFAST64 "lu" /* uint_fast64_t */
#define PRIuMAX "ju" /* uintmax_t */
-#define PRIuPTR "u" /* uintptr_t */
+#define PRIuPTR "lu" /* uintptr_t */
#define PRIx8 "x" /* uint8_t */
#define PRIx16 "x" /* uint16_t */
#define PRIx32 "x" /* uint32_t */
-#define PRIx64 "llx" /* uint64_t */
+#define PRIx64 "lx" /* uint64_t */
#define PRIxLEAST8 "x" /* uint_least8_t */
#define PRIxLEAST16 "x" /* uint_least16_t */
#define PRIxLEAST32 "x" /* uint_least32_t */
-#define PRIxLEAST64 "llx" /* uint_least64_t */
+#define PRIxLEAST64 "lx" /* uint_least64_t */
#define PRIxFAST8 "x" /* uint_fast8_t */
#define PRIxFAST16 "x" /* uint_fast16_t */
#define PRIxFAST32 "x" /* uint_fast32_t */
-#define PRIxFAST64 "llx" /* uint_fast64_t */
+#define PRIxFAST64 "lx" /* uint_fast64_t */
#define PRIxMAX "jx" /* uintmax_t */
-#define PRIxPTR "x" /* uintptr_t */
+#define PRIxPTR "lx" /* uintptr_t */
#define PRIX8 "X" /* uint8_t */
#define PRIX16 "X" /* uint16_t */
#define PRIX32 "X" /* uint32_t */
-#define PRIX64 "llX" /* uint64_t */
+#define PRIX64 "lX" /* uint64_t */
#define PRIXLEAST8 "X" /* uint_least8_t */
#define PRIXLEAST16 "X" /* uint_least16_t */
#define PRIXLEAST32 "X" /* uint_least32_t */
-#define PRIXLEAST64 "llX" /* uint_least64_t */
+#define PRIXLEAST64 "lX" /* uint_least64_t */
#define PRIXFAST8 "X" /* uint_fast8_t */
#define PRIXFAST16 "X" /* uint_fast16_t */
#define PRIXFAST32 "X" /* uint_fast32_t */
-#define PRIXFAST64 "llX" /* uint_fast64_t */
+#define PRIXFAST64 "lX" /* uint_fast64_t */
#define PRIXMAX "jX" /* uintmax_t */
-#define PRIXPTR "X" /* uintptr_t */
+#define PRIXPTR "lX" /* uintptr_t */
/* fscanf(3) macros for signed integers. */
#define SCNd8 "hhd" /* int8_t */
#define SCNd16 "hd" /* int16_t */
#define SCNd32 "d" /* int32_t */
-#define SCNd64 "lld" /* int64_t */
+#define SCNd64 "ld" /* int64_t */
#define SCNdLEAST8 "hhd" /* int_least8_t */
#define SCNdLEAST16 "hd" /* int_least16_t */
#define SCNdLEAST32 "d" /* int_least32_t */
-#define SCNdLEAST64 "lld" /* int_least64_t */
+#define SCNdLEAST64 "ld" /* int_least64_t */
#define SCNdFAST8 "d" /* int_fast8_t */
#define SCNdFAST16 "d" /* int_fast16_t */
#define SCNdFAST32 "d" /* int_fast32_t */
-#define SCNdFAST64 "lld" /* int_fast64_t */
+#define SCNdFAST64 "ld" /* int_fast64_t */
#define SCNdMAX "jd" /* intmax_t */
-#define SCNdPTR "d" /* intptr_t */
+#define SCNdPTR "ld" /* intptr_t */
#define SCNi8 "hhi" /* int8_t */
#define SCNi16 "hi" /* int16_t */
#define SCNi32 "i" /* int32_t */
-#define SCNi64 "lli" /* int64_t */
+#define SCNi64 "li" /* int64_t */
#define SCNiLEAST8 "hhi" /* int_least8_t */
#define SCNiLEAST16 "hi" /* int_least16_t */
#define SCNiLEAST32 "i" /* int_least32_t */
-#define SCNiLEAST64 "lli" /* int_least64_t */
+#define SCNiLEAST64 "li" /* int_least64_t */
#define SCNiFAST8 "i" /* int_fast8_t */
#define SCNiFAST16 "i" /* int_fast16_t */
#define SCNiFAST32 "i" /* int_fast32_t */
-#define SCNiFAST64 "lli" /* int_fast64_t */
+#define SCNiFAST64 "li" /* int_fast64_t */
#define SCNiMAX "ji" /* intmax_t */
-#define SCNiPTR "i" /* intptr_t */
+#define SCNiPTR "li" /* intptr_t */
/* fscanf(3) macros for unsigned integers. */
#define SCNo8 "hho" /* uint8_t */
#define SCNo16 "ho" /* uint16_t */
#define SCNo32 "o" /* uint32_t */
-#define SCNo64 "llo" /* uint64_t */
+#define SCNo64 "lo" /* uint64_t */
#define SCNoLEAST8 "hho" /* uint_least8_t */
#define SCNoLEAST16 "ho" /* uint_least16_t */
#define SCNoLEAST32 "o" /* uint_least32_t */
-#define SCNoLEAST64 "llo" /* uint_least64_t */
+#define SCNoLEAST64 "lo" /* uint_least64_t */
#define SCNoFAST8 "o" /* uint_fast8_t */
#define SCNoFAST16 "o" /* uint_fast16_t */
#define SCNoFAST32 "o" /* uint_fast32_t */
-#define SCNoFAST64 "llo" /* uint_fast64_t */
+#define SCNoFAST64 "lo" /* uint_fast64_t */
#define SCNoMAX "jo" /* uintmax_t */
-#define SCNoPTR "o" /* uintptr_t */
+#define SCNoPTR "lo" /* uintptr_t */
#define SCNu8 "hhu" /* uint8_t */
#define SCNu16 "hu" /* uint16_t */
#define SCNu32 "u" /* uint32_t */
-#define SCNu64 "llu" /* uint64_t */
+#define SCNu64 "lu" /* uint64_t */
#define SCNuLEAST8 "hhu" /* uint_least8_t */
#define SCNuLEAST16 "hu" /* uint_least16_t */
#define SCNuLEAST32 "u" /* uint_least32_t */
-#define SCNuLEAST64 "llu" /* uint_least64_t */
+#define SCNuLEAST64 "lu" /* uint_least64_t */
#define SCNuFAST8 "u" /* uint_fast8_t */
#define SCNuFAST16 "u" /* uint_fast16_t */
#define SCNuFAST32 "u" /* uint_fast32_t */
-#define SCNuFAST64 "llu" /* uint_fast64_t */
+#define SCNuFAST64 "lu" /* uint_fast64_t */
#define SCNuMAX "ju" /* uintmax_t */
-#define SCNuPTR "u" /* uintptr_t */
+#define SCNuPTR "lu" /* uintptr_t */
#define SCNx8 "hhx" /* uint8_t */
#define SCNx16 "hx" /* uint16_t */
#define SCNx32 "x" /* uint32_t */
-#define SCNx64 "llx" /* uint64_t */
+#define SCNx64 "lx" /* uint64_t */
#define SCNxLEAST8 "hhx" /* uint_least8_t */
#define SCNxLEAST16 "hx" /* uint_least16_t */
#define SCNxLEAST32 "x" /* uint_least32_t */
-#define SCNxLEAST64 "llx" /* uint_least64_t */
+#define SCNxLEAST64 "lx" /* uint_least64_t */
#define SCNxFAST8 "x" /* uint_fast8_t */
#define SCNxFAST16 "x" /* uint_fast16_t */
#define SCNxFAST32 "x" /* uint_fast32_t */
-#define SCNxFAST64 "llx" /* uint_fast64_t */
+#define SCNxFAST64 "lx" /* uint_fast64_t */
#define SCNxMAX "jx" /* uintmax_t */
-#define SCNxPTR "x" /* uintptr_t */
+#define SCNxPTR "lx" /* uintptr_t */
#endif /* !_MACHINE_INTTYPES_H_ */
diff --git a/sys/amd64/include/_types.h b/sys/amd64/include/_types.h
index 69b6a0dd955a..f61842c57246 100644
--- a/sys/amd64/include/_types.h
+++ b/sys/amd64/include/_types.h
@@ -56,6 +56,8 @@ typedef unsigned long __uint64_t;
*/
typedef __int32_t __clock_t; /* clock()... */
typedef __int64_t __critical_t;
+typedef double __double_t;
+typedef double __float_t;
typedef __int64_t __intfptr_t;
typedef __int64_t __intmax_t;
typedef __int64_t __intptr_t;
@@ -72,7 +74,7 @@ typedef __int64_t __register_t;
typedef __int64_t __segsz_t; /* segment size (in pages) */
typedef __uint64_t __size_t; /* sizeof() */
typedef __int64_t __ssize_t; /* byte count or error */
-typedef __int32_t __time_t; /* time()... */
+typedef __int64_t __time_t; /* time()... */
typedef __uint64_t __uintfptr_t;
typedef __uint64_t __uintmax_t;
typedef __uint64_t __uintptr_t;
diff --git a/sys/amd64/include/asm.h b/sys/amd64/include/asm.h
index 30008a26d482..8ea4122061d2 100644
--- a/sys/amd64/include/asm.h
+++ b/sys/amd64/include/asm.h
@@ -43,19 +43,9 @@
#include <sys/cdefs.h>
#ifdef PIC
-#define PIC_PROLOGUE \
- pushl %ebx; \
- call 1f; \
-1: \
- popl %ebx; \
- addl $_GLOBAL_OFFSET_TABLE_+[.-1b],%ebx
-#define PIC_EPILOGUE \
- popl %ebx
#define PIC_PLT(x) x@PLT
-#define PIC_GOT(x) x@GOT(%ebx)
+#define PIC_GOT(x) x@GOTPCREL(%rip)
#else
-#define PIC_PROLOGUE
-#define PIC_EPILOGUE
#define PIC_PLT(x) x
#define PIC_GOT(x) x
#endif
@@ -78,14 +68,14 @@
#ifdef PROF
#define ALTENTRY(x) _ENTRY(x); \
- pushl %ebp; movl %esp,%ebp; \
+ pushl %rbp; movl %rsp,%rbp; \
call PIC_PLT(HIDENAME(mcount)); \
- popl %ebp; \
+ popl %rbp; \
jmp 9f
#define ENTRY(x) _ENTRY(x); \
- pushl %ebp; movl %esp,%ebp; \
+ pushl %rbp; movl %rsp,%rbp; \
call PIC_PLT(HIDENAME(mcount)); \
- popl %ebp; \
+ popl %rbp; \
9:
#else
#define ALTENTRY(x) _ENTRY(x)
@@ -117,42 +107,38 @@
#define ARCH_DISPATCH(x) \
_START_ENTRY; \
.globl CNAME(x); .type CNAME(x),@function; CNAME(x): ; \
- PIC_PROLOGUE; \
- movl PIC_GOT(AVECNAME(x)),%eax; \
- PIC_EPILOGUE; \
- jmpl *(%eax)
+ movq PIC_GOT(AVECNAME(x)),%rax; \
+ jmpq *(%rax)
#define ARCH_SELECT(x) _START_ENTRY; \
.type ASELNAME(x),@function; \
ASELNAME(x): \
- PIC_PROLOGUE; \
call PIC_PLT(CNAME(__get_hw_float)); \
- testl %eax,%eax; \
- movl PIC_GOT(ANAME(x)),%eax; \
+ testq %rax,%rax; \
+ movq PIC_GOT(ANAME(x)),%rax; \
jne 8f; \
- movl PIC_GOT(GNAME(x)),%eax; \
+ movq PIC_GOT(GNAME(x)),%rax; \
8: \
- movl PIC_GOT(AVECNAME(x)),%edx; \
- movl %eax,(%edx); \
- PIC_EPILOGUE; \
- jmpl *%eax
+ movq PIC_GOT(AVECNAME(x)),%rdx; \
+ movq %rax,(%rdx); \
+ jmpq *%rax
#else /* !PIC */
#define ARCH_DISPATCH(x) \
_START_ENTRY; \
.globl CNAME(x); .type CNAME(x),@function; CNAME(x): ; \
- jmpl *AVECNAME(x)
+ jmpw *AVECNAME(x)
#define ARCH_SELECT(x) _START_ENTRY; \
.type ASELNAME(x),@function; \
ASELNAME(x): \
call CNAME(__get_hw_float); \
- testl %eax,%eax; \
- movl $ANAME(x),%eax; \
+ testw %rax,%rax; \
+ movw $ANAME(x),%rax; \
jne 8f; \
- movl $GNAME(x),%eax; \
+ movw $GNAME(x),%rax; \
8: \
- movl %eax,AVECNAME(x); \
- jmpl *%eax
+ movw %rax,AVECNAME(x); \
+ jmpw *%rax
#endif /* PIC */
#define ARCH_VECTOR(x) .data; .p2align 2; \
diff --git a/sys/amd64/include/asmacros.h b/sys/amd64/include/asmacros.h
index 07035ca23c1f..9893e5f9d031 100644
--- a/sys/amd64/include/asmacros.h
+++ b/sys/amd64/include/asmacros.h
@@ -50,11 +50,11 @@
#define CNAME(csym) csym
#define HIDENAME(asmsym) .asmsym
-#define ALIGN_DATA .p2align 2 /* 4 byte alignment, zero filled */
+#define ALIGN_DATA .p2align 3 /* 8 byte alignment, zero filled */
#ifdef GPROF
#define ALIGN_TEXT .p2align 4,0x90 /* 16-byte alignment, nop filled */
#else
-#define ALIGN_TEXT .p2align 2,0x90 /* 4-byte alignment, nop filled */
+#define ALIGN_TEXT .p2align 4,0x90 /* 16-byte alignment, nop filled */
#endif
#define SUPERALIGN_TEXT .p2align 4,0x90 /* 16-byte alignment, nop filled */
@@ -64,9 +64,9 @@
#define NON_GPROF_RET .byte 0xc3 /* opcode for `ret' */
#ifdef LOCORE
-#define PCPU(member) %fs:PC_ ## member
-#define PCPU_ADDR(member, reg) movl %fs:PC_PRVSPACE,reg; \
- addl $PC_ ## member,reg
+#define PCPU(member) %gs:PC_ ## member
+#define PCPU_ADDR(member, reg) movq %gs:PC_PRVSPACE,reg; \
+ addq $PC_ ## member,reg
#endif
#ifdef GPROF
@@ -115,7 +115,7 @@
#define CROSSJUMPTARGET(label) \
ALIGN_TEXT; __CONCAT(to,label): ; MCOUNT; jmp label
#define ENTRY(name) GEN_ENTRY(name) ; 9: ; MCOUNT
-#define FAKE_MCOUNT(caller) pushl caller ; call __mcount ; popl %ecx
+#define FAKE_MCOUNT(caller) pushq caller ; call __mcount ; popl %ecx
#define MCOUNT call __mcount
#define MCOUNT_LABEL(name) GEN_ENTRY(name) ; nop ; ALIGN_TEXT
#define MEXITCOUNT call HIDENAME(mexitcount)
diff --git a/sys/amd64/include/atomic.h b/sys/amd64/include/atomic.h
index 919bd5aab63f..0c4d9b027f55 100644
--- a/sys/amd64/include/atomic.h
+++ b/sys/amd64/include/atomic.h
@@ -68,6 +68,7 @@
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);
#define ATOMIC_STORE_LOAD(TYPE, LOP, SOP) \
u_##TYPE atomic_load_acq_##TYPE(volatile u_##TYPE *p); \
@@ -81,7 +82,7 @@ void atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v)
* For userland, assume the SMP case and use lock prefixes so that
* the binaries will run on both types of systems.
*/
-#if defined(SMP) || !defined(_KERNEL)
+#if !defined(_KERNEL)
#define MPLOCKED lock ;
#else
#define MPLOCKED
@@ -117,84 +118,49 @@ extern void atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v)
#if defined(__GNUC__)
-#if defined(I386_CPU) || defined(CPU_DISABLE_CMPXCHG)
-
static __inline int
atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src)
{
int res = exp;
- __asm __volatile(
- " pushfl ; "
- " cli ; "
- " cmpl %0,%2 ; "
- " jne 1f ; "
- " movl %1,%2 ; "
- "1: "
- " sete %%al; "
+ __asm __volatile (
+ " " __XSTRING(MPLOCKED) " "
+ " cmpxchgl %1,%2 ; "
+ " setz %%al ; "
" movzbl %%al,%0 ; "
- " popfl ; "
+ "1: "
"# atomic_cmpset_int"
: "+a" (res) /* 0 (result) */
: "r" (src), /* 1 */
"m" (*(dst)) /* 2 */
- : "memory");
+ : "memory");
return (res);
}
-#else /* defined(I386_CPU) */
-
static __inline int
-atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src)
+atomic_cmpset_long(volatile u_long *dst, u_long exp, u_long src)
{
- int res = exp;
+ long res = exp;
__asm __volatile (
" " __XSTRING(MPLOCKED) " "
- " cmpxchgl %1,%2 ; "
+ " cmpxchgq %1,%2 ; "
" setz %%al ; "
- " movzbl %%al,%0 ; "
+ " movzbq %%al,%0 ; "
"1: "
- "# atomic_cmpset_int"
- : "+a" (res) /* 0 (result) */
+ "# atomic_cmpset_long"
+ : "+a" (res) /* 0 (result) %rax, XXX check */
: "r" (src), /* 1 */
"m" (*(dst)) /* 2 */
: "memory");
return (res);
}
-
-#endif /* defined(I386_CPU) */
-
#endif /* defined(__GNUC__) */
#if defined(__GNUC__)
-#if defined(I386_CPU)
-
-/*
- * We assume that a = b will do atomic loads and stores.
- *
- * XXX: This is _NOT_ safe on a P6 or higher because it does not guarantee
- * memory ordering. These should only be used on a 386.
- */
-#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; \
- __asm __volatile("" : : : "memory"); \
-}
-
-#else /* !defined(I386_CPU) */
-
#define ATOMIC_STORE_LOAD(TYPE, LOP, SOP) \
static __inline u_##TYPE \
atomic_load_acq_##TYPE(volatile u_##TYPE *p) \
@@ -221,11 +187,10 @@ atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\
: : "memory"); \
}
-#endif /* defined(I386_CPU) */
-
#else /* !defined(__GNUC__) */
extern int atomic_cmpset_int(volatile u_int *, u_int, u_int);
+extern int atomic_cmpset_long(volatile u_long *, u_long, u_long);
#define ATOMIC_STORE_LOAD(TYPE, LOP, SOP) \
extern u_##TYPE atomic_load_acq_##TYPE(volatile u_##TYPE *p); \
@@ -250,15 +215,15 @@ ATOMIC_ASM(clear, int, "andl %1,%0", "ir", ~v);
ATOMIC_ASM(add, int, "addl %1,%0", "ir", v);
ATOMIC_ASM(subtract, int, "subl %1,%0", "ir", v);
-ATOMIC_ASM(set, long, "orl %1,%0", "ir", v);
-ATOMIC_ASM(clear, long, "andl %1,%0", "ir", ~v);
-ATOMIC_ASM(add, long, "addl %1,%0", "ir", v);
-ATOMIC_ASM(subtract, long, "subl %1,%0", "ir", v);
+ATOMIC_ASM(set, long, "orq %1,%0", "ir", v);
+ATOMIC_ASM(clear, long, "andq %1,%0", "ir", ~v);
+ATOMIC_ASM(add, long, "addq %1,%0", "ir", v);
+ATOMIC_ASM(subtract, long, "subq %1,%0", "ir", v);
ATOMIC_STORE_LOAD(char, "cmpxchgb %b0,%1", "xchgb %b1,%0");
ATOMIC_STORE_LOAD(short,"cmpxchgw %w0,%1", "xchgw %w1,%0");
ATOMIC_STORE_LOAD(int, "cmpxchgl %0,%1", "xchgl %1,%0");
-ATOMIC_STORE_LOAD(long, "cmpxchgl %0,%1", "xchgl %1,%0");
+ATOMIC_STORE_LOAD(long, "cmpxchgq %0,%1", "xchgq %1,%0");
#undef ATOMIC_ASM
#undef ATOMIC_STORE_LOAD
@@ -300,9 +265,6 @@ ATOMIC_STORE_LOAD(long, "cmpxchgl %0,%1", "xchgl %1,%0");
#define atomic_add_rel_long atomic_add_long
#define atomic_subtract_acq_long atomic_subtract_long
#define atomic_subtract_rel_long atomic_subtract_long
-#define atomic_cmpset_long atomic_cmpset_int
-#define atomic_cmpset_acq_long atomic_cmpset_acq_int
-#define atomic_cmpset_rel_long atomic_cmpset_rel_int
#define atomic_cmpset_acq_ptr atomic_cmpset_ptr
#define atomic_cmpset_rel_ptr atomic_cmpset_ptr
@@ -361,39 +323,39 @@ static __inline int
atomic_cmpset_ptr(volatile void *dst, void *exp, void *src)
{
- return (atomic_cmpset_int((volatile u_int *)dst, (u_int)exp,
- (u_int)src));
+ return (atomic_cmpset_long((volatile u_long *)dst,
+ (u_long)exp, (u_long)src));
}
static __inline void *
atomic_load_acq_ptr(volatile void *p)
{
- return (void *)atomic_load_acq_int((volatile u_int *)p);
+ return (void *)atomic_load_acq_long((volatile u_long *)p);
}
static __inline void
atomic_store_rel_ptr(volatile void *p, void *v)
{
- atomic_store_rel_int((volatile u_int *)p, (u_int)v);
+ atomic_store_rel_long((volatile u_long *)p, (u_long)v);
}
#define ATOMIC_PTR(NAME) \
static __inline void \
atomic_##NAME##_ptr(volatile void *p, uintptr_t v) \
{ \
- atomic_##NAME##_int((volatile u_int *)p, v); \
+ atomic_##NAME##_long((volatile u_long *)p, v); \
} \
\
static __inline void \
atomic_##NAME##_acq_ptr(volatile void *p, uintptr_t v) \
{ \
- atomic_##NAME##_acq_int((volatile u_int *)p, v);\
+ atomic_##NAME##_acq_long((volatile u_long *)p, v);\
} \
\
static __inline void \
atomic_##NAME##_rel_ptr(volatile void *p, uintptr_t v) \
{ \
- atomic_##NAME##_rel_int((volatile u_int *)p, v);\
+ atomic_##NAME##_rel_long((volatile u_long *)p, v);\
}
ATOMIC_PTR(set)
@@ -426,8 +388,8 @@ atomic_readandclear_long(volatile u_long *addr)
u_long result;
__asm __volatile (
- " xorl %0,%0 ; "
- " xchgl %1,%0 ; "
+ " xorq %0,%0 ; "
+ " xchgq %1,%0 ; "
"# atomic_readandclear_int"
: "=&r" (result) /* 0 (result) */
: "m" (*addr)); /* 1 (addr) */
diff --git a/sys/amd64/include/bus.h b/sys/amd64/include/bus.h
index a33569f5b22d..9aa93366cc95 100644
--- a/sys/amd64/include/bus.h
+++ b/sys/amd64/include/bus.h
@@ -34,17 +34,11 @@
#ifndef _I386_BUS_H_
#define _I386_BUS_H_
-#ifdef PC98
-/* NEC PC-98 */
-#include <machine/bus_pc98.h>
-#else
-/* IBM-PC */
#include <machine/bus_at386.h>
-#endif
#include <machine/bus_dma.h>
/*
- * Stream accesses are the same as normal accesses on i386/pc98; there are no
+ * Stream accesses are the same as normal accesses on i386; there are no
* supported bus systems with an endianess different from the host one.
*/
#define bus_space_read_stream_1(t, h, o) bus_space_read_1((t), (h), (o))
diff --git a/sys/amd64/include/bus_amd64.h b/sys/amd64/include/bus_amd64.h
index e1f6e8e3a9a0..d8ae035bd6e1 100644
--- a/sys/amd64/include/bus_amd64.h
+++ b/sys/amd64/include/bus_amd64.h
@@ -92,31 +92,23 @@
/*
* Bus address and size types
*/
-#ifdef PAE
typedef uint64_t bus_addr_t;
-#else
-typedef uint32_t bus_addr_t;
-#endif
-typedef uint32_t bus_size_t;
+typedef uint64_t bus_size_t;
#define BUS_SPACE_MAXSIZE_24BIT 0xFFFFFF
#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF
#define BUS_SPACE_MAXSIZE 0xFFFFFFFF
#define BUS_SPACE_MAXADDR_24BIT 0xFFFFFF
#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF
-#ifdef PAE
#define BUS_SPACE_MAXADDR 0xFFFFFFFFFFFFFFFFULL
-#else
-#define BUS_SPACE_MAXADDR 0xFFFFFFFF
-#endif
#define BUS_SPACE_UNRESTRICTED (~0)
/*
* Access methods for bus resources and address space.
*/
-typedef int bus_space_tag_t;
-typedef u_int bus_space_handle_t;
+typedef uint64_t bus_space_tag_t;
+typedef uint64_t bus_space_handle_t;
/*
* Map a region of device bus space into CPU virtual address space.
@@ -1215,7 +1207,7 @@ bus_space_barrier(bus_space_tag_t tag __unused, bus_space_handle_t bsh __unused,
{
#ifdef __GNUC__
if (flags & BUS_SPACE_BARRIER_READ)
- __asm __volatile("lock; addl $0,0(%%esp)" : : : "memory");
+ __asm __volatile("lock; addl $0,0(%%rsp)" : : : "memory");
else
__asm __volatile("" : : : "memory");
#endif
diff --git a/sys/amd64/include/bus_at386.h b/sys/amd64/include/bus_at386.h
index e1f6e8e3a9a0..d8ae035bd6e1 100644
--- a/sys/amd64/include/bus_at386.h
+++ b/sys/amd64/include/bus_at386.h
@@ -92,31 +92,23 @@
/*
* Bus address and size types
*/
-#ifdef PAE
typedef uint64_t bus_addr_t;
-#else
-typedef uint32_t bus_addr_t;
-#endif
-typedef uint32_t bus_size_t;
+typedef uint64_t bus_size_t;
#define BUS_SPACE_MAXSIZE_24BIT 0xFFFFFF
#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF
#define BUS_SPACE_MAXSIZE 0xFFFFFFFF
#define BUS_SPACE_MAXADDR_24BIT 0xFFFFFF
#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF
-#ifdef PAE
#define BUS_SPACE_MAXADDR 0xFFFFFFFFFFFFFFFFULL
-#else
-#define BUS_SPACE_MAXADDR 0xFFFFFFFF
-#endif
#define BUS_SPACE_UNRESTRICTED (~0)
/*
* Access methods for bus resources and address space.
*/
-typedef int bus_space_tag_t;
-typedef u_int bus_space_handle_t;
+typedef uint64_t bus_space_tag_t;
+typedef uint64_t bus_space_handle_t;
/*
* Map a region of device bus space into CPU virtual address space.
@@ -1215,7 +1207,7 @@ bus_space_barrier(bus_space_tag_t tag __unused, bus_space_handle_t bsh __unused,
{
#ifdef __GNUC__
if (flags & BUS_SPACE_BARRIER_READ)
- __asm __volatile("lock; addl $0,0(%%esp)" : : : "memory");
+ __asm __volatile("lock; addl $0,0(%%rsp)" : : : "memory");
else
__asm __volatile("" : : : "memory");
#endif
diff --git a/sys/amd64/include/clock.h b/sys/amd64/include/clock.h
index 5ae4fb2c409f..511780f837c3 100644
--- a/sys/amd64/include/clock.h
+++ b/sys/amd64/include/clock.h
@@ -24,9 +24,6 @@ extern int timer0_max_count;
extern uint64_t tsc_freq;
extern int tsc_is_broken;
extern int wall_cmos_clock;
-#ifdef APIC_IO
-extern int apic_8254_intr;
-#endif
/*
* Driver to clock driver interface.
@@ -37,14 +34,8 @@ int acquire_timer0(int rate, void (*function)(struct clockframe *frame));
int acquire_timer2(int mode);
int release_timer0(void);
int release_timer2(void);
-#ifndef PC98
int rtcin(int val);
-#else
-int acquire_timer1(int mode);
-int release_timer1(void);
-#endif
int sysbeep(int pitch, int period);
-void timer_restore(void);
void init_TSC(void);
#endif /* _KERNEL */
diff --git a/sys/amd64/include/cpu.h b/sys/amd64/include/cpu.h
index d4e72bb593ea..e9b7fff4cfd5 100644
--- a/sys/amd64/include/cpu.h
+++ b/sys/amd64/include/cpu.h
@@ -55,16 +55,16 @@
#define cpu_exec(p) /* nothing */
#define cpu_swapin(p) /* nothing */
-#define cpu_getstack(td) ((td)->td_frame->tf_esp)
-#define cpu_setstack(td, ap) ((td)->td_frame->tf_esp = (ap))
+#define cpu_getstack(td) ((td)->td_frame->tf_rsp)
+#define cpu_setstack(td, ap) ((td)->td_frame->tf_rsp = (ap))
#define TRAPF_USERMODE(framep) \
- ((ISPL((framep)->tf_cs) == SEL_UPL) || ((framep)->tf_eflags & PSL_VM))
-#define TRAPF_PC(framep) ((framep)->tf_eip)
+ (ISPL((framep)->tf_cs) == SEL_UPL)
+#define TRAPF_PC(framep) ((framep)->tf_rip)
#define CLKF_USERMODE(framep) \
- ((ISPL((framep)->cf_cs) == SEL_UPL) || ((framep)->cf_eflags & PSL_VM))
-#define CLKF_PC(framep) ((framep)->cf_eip)
+ (ISPL((framep)->cf_cs) == SEL_UPL)
+#define CLKF_PC(framep) ((framep)->cf_rip)
/*
* CTL_MACHDEP definitions.
@@ -72,19 +72,9 @@
#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_BOOTINFO 4 /* struct: bootinfo */
#define CPU_WALLCLOCK 5 /* int: indicates wall CMOS clock */
#define CPU_MAXID 6 /* number of valid machdep ids */
-#define CTL_MACHDEP_NAMES { \
- { 0, 0 }, \
- { "console_device", CTLTYPE_STRUCT }, \
- { "adjkerntz", CTLTYPE_INT }, \
- { "disable_rtc_set", CTLTYPE_INT }, \
- { "bootinfo", CTLTYPE_STRUCT }, \
- { "wall_cmos_clock", CTLTYPE_INT }, \
-}
-
#ifdef _KERNEL
extern char btext[];
extern char etext[];
@@ -99,14 +89,7 @@ void fork_trampoline(void);
static __inline u_int64_t
get_cyclecount(void)
{
-#if defined(I386_CPU) || defined(I486_CPU)
- struct bintime bt;
- if (!tsc_present) {
- binuptime(&bt);
- return (bt.frac ^ bt.sec);
- }
-#endif
return (rdtsc());
}
diff --git a/sys/amd64/include/cpufunc.h b/sys/amd64/include/cpufunc.h
index c7f9ace695f0..1e1df330e841 100644
--- a/sys/amd64/include/cpufunc.h
+++ b/sys/amd64/include/cpufunc.h
@@ -52,10 +52,12 @@ __BEGIN_DECLS
#define readb(va) (*(volatile u_int8_t *) (va))
#define readw(va) (*(volatile u_int16_t *) (va))
#define readl(va) (*(volatile u_int32_t *) (va))
+#define readq(va) (*(volatile u_int64_t *) (va))
#define writeb(va, d) (*(volatile u_int8_t *) (va) = (d))
#define writew(va, d) (*(volatile u_int16_t *) (va) = (d))
#define writel(va, d) (*(volatile u_int32_t *) (va) = (d))
+#define writeq(va, d) (*(volatile u_int64_t *) (va) = (d))
#ifdef __GNUC__
@@ -310,40 +312,40 @@ ia32_pause(void)
__asm __volatile("pause");
}
-static __inline u_int
-read_eflags(void)
+static __inline u_long
+read_rflags(void)
{
- u_int ef;
+ u_long rf;
- __asm __volatile("pushfl; popl %0" : "=r" (ef));
- return (ef);
+ __asm __volatile("pushfq; popq %0" : "=r" (rf));
+ return (rf);
}
static __inline u_int64_t
rdmsr(u_int msr)
{
- u_int64_t rv;
+ u_int32_t low, high;
- __asm __volatile("rdmsr" : "=A" (rv) : "c" (msr));
- return (rv);
+ __asm __volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr));
+ return (low | ((u_int64_t)high << 32));
}
static __inline u_int64_t
rdpmc(u_int pmc)
{
- u_int64_t rv;
+ u_int32_t low, high;
- __asm __volatile("rdpmc" : "=A" (rv) : "c" (pmc));
- return (rv);
+ __asm __volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (pmc));
+ return (low | ((u_int64_t)high << 32));
}
static __inline u_int64_t
rdtsc(void)
{
- u_int64_t rv;
+ u_int32_t low, high;
- __asm __volatile("rdtsc" : "=A" (rv));
- return (rv);
+ __asm __volatile("rdtsc" : "=a" (low), "=d" (high));
+ return (low | ((u_int64_t)high << 32));
}
static __inline void
@@ -353,70 +355,74 @@ wbinvd(void)
}
static __inline void
-write_eflags(u_int ef)
+write_rflags(u_long rf)
{
- __asm __volatile("pushl %0; popfl" : : "r" (ef));
+ __asm __volatile("pushq %0; popfq" : : "r" (rf));
}
static __inline void
wrmsr(u_int msr, u_int64_t newval)
{
- __asm __volatile("wrmsr" : : "A" (newval), "c" (msr));
+ u_int32_t low, high;
+
+ low = newval;
+ high = newval >> 32;
+ __asm __volatile("wrmsr" : : "a" (low), "d" (high), "c" (msr));
}
static __inline void
-load_cr0(u_int data)
+load_cr0(u_long data)
{
- __asm __volatile("movl %0,%%cr0" : : "r" (data));
+ __asm __volatile("movq %0,%%cr0" : : "r" (data));
}
-static __inline u_int
+static __inline u_long
rcr0(void)
{
- u_int data;
+ u_long data;
- __asm __volatile("movl %%cr0,%0" : "=r" (data));
+ __asm __volatile("movq %%cr0,%0" : "=r" (data));
return (data);
}
-static __inline u_int
+static __inline u_long
rcr2(void)
{
- u_int data;
+ u_long data;
- __asm __volatile("movl %%cr2,%0" : "=r" (data));
+ __asm __volatile("movq %%cr2,%0" : "=r" (data));
return (data);
}
static __inline void
-load_cr3(u_int data)
+load_cr3(u_long data)
{
- __asm __volatile("movl %0,%%cr3" : : "r" (data) : "memory");
+ __asm __volatile("movq %0,%%cr3" : : "r" (data) : "memory");
}
-static __inline u_int
+static __inline u_long
rcr3(void)
{
- u_int data;
+ u_long data;
- __asm __volatile("movl %%cr3,%0" : "=r" (data));
+ __asm __volatile("movq %%cr3,%0" : "=r" (data));
return (data);
}
static __inline void
-load_cr4(u_int data)
+load_cr4(u_long data)
{
- __asm __volatile("movl %0,%%cr4" : : "r" (data));
+ __asm __volatile("movq %0,%%cr4" : : "r" (data));
}
-static __inline u_int
+static __inline u_long
rcr4(void)
{
- u_int data;
+ u_long data;
- __asm __volatile("movl %%cr4,%0" : "=r" (data));
+ __asm __volatile("movq %%cr4,%0" : "=r" (data));
return (data);
}
@@ -435,12 +441,13 @@ invltlb(void)
* Only works on 486+ CPUs (i386 does not have PG_G).
*/
static __inline void
-invlpg(u_int addr)
+invlpg(u_long addr)
{
__asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
}
+/* XXX these are replaced with rdmsr/wrmsr */
static __inline u_int
rfs(void)
{
@@ -490,132 +497,20 @@ ltr(u_short sel)
__asm __volatile("ltr %0" : : "r" (sel));
}
-static __inline u_int
-rdr0(void)
-{
- u_int data;
- __asm __volatile("movl %%dr0,%0" : "=r" (data));
- return (data);
-}
-
-static __inline void
-load_dr0(u_int dr0)
-{
- __asm __volatile("movl %0,%%dr0" : : "r" (dr0));
-}
-
-static __inline u_int
-rdr1(void)
-{
- u_int data;
- __asm __volatile("movl %%dr1,%0" : "=r" (data));
- return (data);
-}
-
-static __inline void
-load_dr1(u_int dr1)
-{
- __asm __volatile("movl %0,%%dr1" : : "r" (dr1));
-}
-
-static __inline u_int
-rdr2(void)
-{
- u_int data;
- __asm __volatile("movl %%dr2,%0" : "=r" (data));
- return (data);
-}
-
-static __inline void
-load_dr2(u_int dr2)
-{
- __asm __volatile("movl %0,%%dr2" : : "r" (dr2));
-}
-
-static __inline u_int
-rdr3(void)
-{
- u_int data;
- __asm __volatile("movl %%dr3,%0" : "=r" (data));
- return (data);
-}
-
-static __inline void
-load_dr3(u_int dr3)
-{
- __asm __volatile("movl %0,%%dr3" : : "r" (dr3));
-}
-
-static __inline u_int
-rdr4(void)
-{
- u_int data;
- __asm __volatile("movl %%dr4,%0" : "=r" (data));
- return (data);
-}
-
-static __inline void
-load_dr4(u_int dr4)
-{
- __asm __volatile("movl %0,%%dr4" : : "r" (dr4));
-}
-
-static __inline u_int
-rdr5(void)
-{
- u_int data;
- __asm __volatile("movl %%dr5,%0" : "=r" (data));
- return (data);
-}
-
-static __inline void
-load_dr5(u_int dr5)
-{
- __asm __volatile("movl %0,%%dr5" : : "r" (dr5));
-}
-
-static __inline u_int
-rdr6(void)
-{
- u_int data;
- __asm __volatile("movl %%dr6,%0" : "=r" (data));
- return (data);
-}
-
-static __inline void
-load_dr6(u_int dr6)
-{
- __asm __volatile("movl %0,%%dr6" : : "r" (dr6));
-}
-
-static __inline u_int
-rdr7(void)
-{
- u_int data;
- __asm __volatile("movl %%dr7,%0" : "=r" (data));
- return (data);
-}
-
-static __inline void
-load_dr7(u_int dr7)
-{
- __asm __volatile("movl %0,%%dr7" : : "r" (dr7));
-}
-
static __inline register_t
intr_disable(void)
{
- register_t eflags;
+ register_t rflags;
- eflags = read_eflags();
+ rflags = read_rflags();
disable_intr();
- return (eflags);
+ return (rflags);
}
static __inline void
-intr_restore(register_t eflags)
+intr_restore(register_t rflags)
{
- write_eflags(eflags);
+ write_rflags(rflags);
}
#else /* !__GNUC__ */
@@ -623,8 +518,8 @@ intr_restore(register_t eflags)
int breakpoint(void);
u_int bsfl(u_int mask);
u_int bsrl(u_int mask);
-void cpu_invlpg(u_int addr);
-void cpu_invlpg_range(u_int start, u_int end);
+void cpu_invlpg(u_long addr);
+void cpu_invlpg_range(u_long start, u_long end);
void disable_intr(void);
void do_cpuid(u_int ax, u_int *p);
void enable_intr(void);
@@ -664,28 +559,13 @@ u_int rgs(void);
u_int64_t rdmsr(u_int msr);
u_int64_t rdpmc(u_int pmc);
u_int64_t rdtsc(void);
-u_int read_eflags(void);
+u_int read_rflags(void);
void wbinvd(void);
-void write_eflags(u_int ef);
+void write_rflags(u_int rf);
void wrmsr(u_int msr, u_int64_t newval);
-u_int rdr0(void);
-void load_dr0(u_int dr0);
-u_int rdr1(void);
-void load_dr1(u_int dr1);
-u_int rdr2(void);
-void load_dr2(u_int dr2);
-u_int rdr3(void);
-void load_dr3(u_int dr3);
-u_int rdr4(void);
-void load_dr4(u_int dr4);
-u_int rdr5(void);
-void load_dr5(u_int dr5);
-u_int rdr6(void);
-void load_dr6(u_int dr6);
-u_int rdr7(void);
void load_dr7(u_int dr7);
register_t intr_disable(void);
-void intr_restore(register_t ef);
+void intr_restore(register_t rf);
#endif /* __GNUC__ */
diff --git a/sys/amd64/include/cputypes.h b/sys/amd64/include/cputypes.h
index 585df6753a21..2048458bfa3c 100644
--- a/sys/amd64/include/cputypes.h
+++ b/sys/amd64/include/cputypes.h
@@ -33,32 +33,15 @@
/*
* Classes of processor.
*/
-#define CPUCLASS_286 0
-#define CPUCLASS_386 1
-#define CPUCLASS_486 2
-#define CPUCLASS_586 3
-#define CPUCLASS_686 4
+#define CPUCLASS_X86 0 /* X86 */
+#define CPUCLASS_K8 1 /* K8 AMD64 class */
/*
* Kinds of processor.
*/
-#define CPU_286 0 /* Intel 80286 */
-#define CPU_386SX 1 /* Intel 80386SX */
-#define CPU_386 2 /* Intel 80386DX */
-#define CPU_486SX 3 /* Intel 80486SX */
-#define CPU_486 4 /* Intel 80486DX */
-#define CPU_586 5 /* Intel P.....m (I hate lawyers; it's TM) */
-#define CPU_486DLC 6 /* Cyrix 486DLC */
-#define CPU_686 7 /* Pentium Pro */
-#define CPU_M1SC 8 /* Cyrix M1sc (aka 5x86) */
-#define CPU_M1 9 /* Cyrix M1 (aka 6x86) */
-#define CPU_BLUE 10 /* IBM BlueLighting CPU */
-#define CPU_M2 11 /* Cyrix M2 (aka enhanced 6x86 with MMX */
-#define CPU_NX586 12 /* NexGen (now AMD) 586 */
-#define CPU_CY486DX 13 /* Cyrix 486S/DX/DX2/DX4 */
-#define CPU_PII 14 /* Intel Pentium II */
-#define CPU_PIII 15 /* Intel Pentium III */
-#define CPU_P4 16 /* Intel Pentium 4 */
+#define CPU_X86 0 /* Intel */
+#define CPU_CLAWHAMMER 1 /* AMD Clawhammer */
+#define CPU_SLEDGEHAMMER 2 /* AMD Sledgehammer */
#ifndef LOCORE
struct cpu_nameclass {
diff --git a/sys/amd64/include/critical.h b/sys/amd64/include/critical.h
index 7cc7ff2b26cb..dc5119ce47d7 100644
--- a/sys/amd64/include/critical.h
+++ b/sys/amd64/include/critical.h
@@ -23,7 +23,6 @@ __BEGIN_DECLS
/*
* Prototypes - see <arch>/<arch>/critical.c
*/
-void cpu_unpend(void);
void cpu_critical_fork_exit(void);
void cpu_thread_link(struct thread *td);
@@ -34,12 +33,15 @@ void cpu_thread_link(struct thread *td);
*
* This routine is called from critical_enter() on the 0->1 transition
* of td_critnest, prior to it being incremented to 1.
- *
- * If new-style critical section handling we do not have to do anything.
- * However, as a side effect any interrupts occuring while td_critnest
- * is non-zero will be deferred.
*/
-#define cpu_critical_enter()
+static __inline void
+cpu_critical_enter(void)
+{
+ struct thread *td;
+
+ td = curthread;
+ td->td_md.md_savecrit = intr_disable();
+}
/*
* cpu_critical_exit:
@@ -47,27 +49,14 @@ void cpu_thread_link(struct thread *td);
* This routine is called from critical_exit() on a 1->0 transition
* of td_critnest, after it has been decremented to 0. We are
* exiting the last critical section.
- *
- * Note that the td->critnest (1->0) transition interrupt race against
- * our int_pending/unpend() check below is handled by the interrupt
- * code for us, so we do not have to do anything fancy.
*/
static __inline void
cpu_critical_exit(void)
{
- /*
- * We may have to schedule pending interrupts. Create
- * conditions similar to an interrupt context and call
- * unpend().
- *
- * note: we do this even if we are in an interrupt
- * nesting level. Deep nesting is protected by
- * critical_*() and if we conditionalized it then we
- * would have to check int_pending again whenever
- * we decrement td_intr_nesting_level to 0.
- */
- if (PCPU_GET(int_pending))
- cpu_unpend();
+ struct thread *td;
+
+ td = curthread;
+ intr_restore(td->td_md.md_savecrit);
}
#else /* !__GNUC__ */
diff --git a/sys/amd64/include/db_machdep.h b/sys/amd64/include/db_machdep.h
index ba84fc6834e8..5a2e65d208b5 100644
--- a/sys/amd64/include/db_machdep.h
+++ b/sys/amd64/include/db_machdep.h
@@ -36,13 +36,13 @@
#define i386_saved_state trapframe
typedef vm_offset_t db_addr_t; /* address - unsigned */
-typedef int db_expr_t; /* expression - signed */
+typedef long db_expr_t; /* expression - signed */
typedef struct i386_saved_state db_regs_t;
extern db_regs_t ddb_regs; /* register state */
#define DDB_REGS (&ddb_regs)
-#define PC_REGS(regs) ((db_addr_t)(regs)->tf_eip)
+#define PC_REGS(regs) ((db_addr_t)(regs)->tf_rip)
#define BKPT_INST 0xcc /* breakpoint instruction */
#define BKPT_SIZE (1) /* size of breakpoint inst */
diff --git a/sys/amd64/include/elf.h b/sys/amd64/include/elf.h
index 46d512c05929..3883d49302c0 100644
--- a/sys/amd64/include/elf.h
+++ b/sys/amd64/include/elf.h
@@ -30,17 +30,17 @@
#define _MACHINE_ELF_H_ 1
/*
- * ELF definitions for the i386 architecture.
+ * ELF definitions for the AMD64 architecture.
*/
-#include <sys/elf32.h> /* Definitions common to all 32 bit architectures. */
+#include <sys/elf64.h> /* Definitions common to all 64 bit architectures. */
-#define __ELF_WORD_SIZE 32 /* Used by <sys/elf_generic.h> */
+#define __ELF_WORD_SIZE 64 /* Used by <sys/elf_generic.h> */
#include <sys/elf_generic.h>
-#define ELF_ARCH EM_386
+#define ELF_ARCH EM_X86_64
-#define ELF_MACHINE_OK(x) ((x) == EM_386 || (x) == EM_486)
+#define ELF_MACHINE_OK(x) ((x) == EM_X86_64)
/*
* Auxiliary vector entries for passing information to the interpreter.
@@ -50,13 +50,13 @@
*/
typedef struct { /* Auxiliary vector entry on initial stack */
- int a_type; /* Entry type. */
+ long a_type; /* Entry type. */
union {
long a_val; /* Integer value. */
void *a_ptr; /* Address. */
void (*a_fcn)(void); /* Function pointer (not used). */
} a_un;
-} Elf32_Auxinfo;
+} Elf64_Auxinfo;
__ElfType(Auxinfo);
@@ -98,24 +98,29 @@ __ElfType(Auxinfo);
* Relocation types.
*/
-#define R_386_NONE 0 /* No relocation. */
-#define R_386_32 1 /* Add symbol value. */
-#define R_386_PC32 2 /* Add PC-relative symbol value. */
-#define R_386_GOT32 3 /* Add PC-relative GOT offset. */
-#define R_386_PLT32 4 /* Add PC-relative PLT offset. */
-#define R_386_COPY 5 /* Copy data from shared object. */
-#define R_386_GLOB_DAT 6 /* Set GOT entry to data address. */
-#define R_386_JMP_SLOT 7 /* Set GOT entry to code address. */
-#define R_386_RELATIVE 8 /* Add load address of shared object. */
-#define R_386_GOTOFF 9 /* Add GOT-relative symbol address. */
-#define R_386_GOTPC 10 /* Add PC-relative GOT table address. */
-
-#define R_386_COUNT 11 /* Count of defined 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_COUNT 16 /* Count of defined relocation types. */
/* Define "machine" characteristics */
-#define ELF_TARG_CLASS ELFCLASS32
+#define ELF_TARG_CLASS ELFCLASS64
#define ELF_TARG_DATA ELFDATA2LSB
-#define ELF_TARG_MACH EM_386
+#define ELF_TARG_MACH EM_X86_64
#define ELF_TARG_VER 1
#ifdef _KERNEL
diff --git a/sys/amd64/include/endian.h b/sys/amd64/include/endian.h
index 723a5f3d4fea..1766866b62ca 100644
--- a/sys/amd64/include/endian.h
+++ b/sys/amd64/include/endian.h
@@ -74,25 +74,26 @@ __extension__ ({ register __uint32_t __X = (x); \
__asm ("rorl $16, %0" : "+r" (__X)); \
__X; })
-#if defined(_KERNEL)
#define __byte_swap_int(x) \
__extension__ ({ register __uint32_t __X = (x); \
__asm ("bswap %0" : "+r" (__X)); \
__X; })
-#endif
+
+#define __byte_swap_long(x) \
+__extension__ ({ register __uint64_t __X = (x); \
+ __asm ("bswap %0" : "+r" (__X)); \
+ __X; })
#define __byte_swap_word(x) \
__extension__ ({ register __uint16_t __X = (x); \
- __asm ("xchgb %h0, %b0" : "+q" (__X)); \
+ __asm ("xchgb %h0, %b0" : "+Q" (__X)); \
__X; })
static __inline __uint64_t
__bswap64(__uint64_t _x)
{
- return ((_x >> 56) | ((_x >> 40) & 0xff00) | ((_x >> 24) & 0xff0000) |
- ((_x >> 8) & 0xff000000) | ((_x << 8) & ((__uint64_t)0xff << 32)) |
- ((_x << 24) & ((__uint64_t)0xff << 40)) |
- ((_x << 40) & ((__uint64_t)0xff << 48)) | ((_x << 56)));
+
+ return (__byte_swap_long(_x));
}
static __inline __uint32_t
diff --git a/sys/amd64/include/fpu.h b/sys/amd64/include/fpu.h
index 8e0f9bc0036e..db1fe40089fb 100644
--- a/sys/amd64/include/fpu.h
+++ b/sys/amd64/include/fpu.h
@@ -45,81 +45,38 @@
#ifndef _MACHINE_NPX_H_
#define _MACHINE_NPX_H_
-/* Environment information of floating point unit */
-struct env87 {
- long en_cw; /* control word (16bits) */
- long en_sw; /* status word (16bits) */
- long en_tw; /* tag word (16bits) */
- long en_fip; /* floating point instruction pointer */
- u_short en_fcs; /* floating code segment selector */
- u_short en_opcode; /* opcode last executed (11 bits ) */
- long en_foo; /* floating operand offset */
- long en_fos; /* floating operand segment selector */
-};
-
-/* Contents of each floating point accumulator */
+/* Contents of each x87 floating point accumulator */
struct fpacc87 {
-#ifdef dontdef /* too unportable */
- u_long fp_mantlo; /* mantissa low (31:0) */
- u_long fp_manthi; /* mantissa high (63:32) */
- int fp_exp:15; /* exponent */
- int fp_sgn:1; /* mantissa sign */
-#else
u_char fp_bytes[10];
-#endif
};
-/* Floating point context */
-struct save87 {
- struct env87 sv_env; /* floating point control/status */
- struct fpacc87 sv_ac[8]; /* accumulator contents, 0-7 */
- u_char sv_pad0[4]; /* padding for (now unused) saved status word */
- /*
- * Bogus padding for emulators. Emulators should use their own
- * struct and arrange to store into this struct (ending here)
- * before it is inspected for ptracing or for core dumps. Some
- * emulators overwrite the whole struct. We have no good way of
- * knowing how much padding to leave. Leave just enough for the
- * GPL emulator's i387_union (176 bytes total).
- */
- u_char sv_pad[64]; /* padding; used by emulators */
+/* Contents of each SSE extended accumulator */
+struct xmmacc {
+ u_char xmm_bytes[16];
};
struct envxmm {
u_int16_t en_cw; /* control word (16bits) */
u_int16_t en_sw; /* status word (16bits) */
- u_int16_t en_tw; /* tag word (16bits) */
+ u_int8_t en_tw; /* tag word (8bits) */
+ u_int8_t en_zero;
u_int16_t en_opcode; /* opcode last executed (11 bits ) */
- u_int32_t en_fip; /* floating point instruction pointer */
- u_int16_t en_fcs; /* floating code segment selector */
- u_int16_t en_pad0; /* padding */
- u_int32_t en_foo; /* floating operand offset */
- u_int16_t en_fos; /* floating operand segment selector */
- u_int16_t en_pad1; /* padding */
+ u_int64_t en_rip; /* floating point instruction pointer */
+ u_int64_t en_rdp; /* floating operand pointer */
u_int32_t en_mxcsr; /* SSE sontorol/status register */
- u_int32_t en_pad2; /* padding */
+ u_int32_t en_mxcsr_mask; /* valid bits in mxcsr */
};
-/* Contents of each SSE extended accumulator */
-struct xmmacc {
- u_char xmm_bytes[16];
-};
-
-struct savexmm {
+struct savefpu {
struct envxmm sv_env;
struct {
struct fpacc87 fp_acc;
u_char fp_pad[6]; /* padding */
} sv_fp[8];
- struct xmmacc sv_xmm[8];
- u_char sv_pad[224];
+ struct xmmacc sv_xmm[16];
+ u_char sv_pad[96];
} __aligned(16);
-union savefpu {
- struct save87 sv_87;
- struct savexmm sv_xmm;
-};
-
/*
* The hardware default control word for i387's and later coprocessors is
* 0x37F, giving:
@@ -144,10 +101,10 @@ int npxdna(void);
void npxdrop(void);
void npxexit(struct thread *td);
int npxformat(void);
-int npxgetregs(struct thread *td, union savefpu *addr);
+int npxgetregs(struct thread *td, struct savefpu *addr);
void npxinit(u_short control);
-void npxsave(union savefpu *addr);
-void npxsetregs(struct thread *td, union savefpu *addr);
+void npxsave(struct savefpu *addr);
+void npxsetregs(struct thread *td, struct savefpu *addr);
int npxtrap(void);
#endif
diff --git a/sys/amd64/include/frame.h b/sys/amd64/include/frame.h
index c32afc4b8a7f..8f9652820534 100644
--- a/sys/amd64/include/frame.h
+++ b/sys/amd64/include/frame.h
@@ -46,116 +46,93 @@
/*
* Exception/Trap Stack Frame
+ *
+ * The ordering of this is specifically so that we can take first 6
+ * the syscall arguments directly from the beginning of the frame.
*/
struct trapframe {
- int tf_fs;
- int tf_es;
- int tf_ds;
- int tf_edi;
- int tf_esi;
- int tf_ebp;
- int tf_isp;
- int tf_ebx;
- int tf_edx;
- int tf_ecx;
- int tf_eax;
- int tf_trapno;
- /* below portion defined in 386 hardware */
- int tf_err;
- int tf_eip;
- int tf_cs;
- int tf_eflags;
- /* below only when crossing rings (e.g. user to kernel) */
- int tf_esp;
- int tf_ss;
-};
-
-/* Superset of trap frame, for traps from virtual-8086 mode */
-
-struct trapframe_vm86 {
- int tf_fs;
- int tf_es;
- int tf_ds;
- int tf_edi;
- int tf_esi;
- int tf_ebp;
- int tf_isp;
- int tf_ebx;
- int tf_edx;
- int tf_ecx;
- int tf_eax;
- int tf_trapno;
- /* below portion defined in 386 hardware */
- int tf_err;
- int tf_eip;
- int tf_cs;
- int tf_eflags;
- /* below only when crossing rings (e.g. user to kernel) */
- int tf_esp;
- int tf_ss;
- /* below only when switching out of VM86 mode */
- int tf_vm86_es;
- int tf_vm86_ds;
- int tf_vm86_fs;
- int tf_vm86_gs;
+ register_t tf_rdi;
+ register_t tf_rsi;
+ register_t tf_rdx;
+ register_t tf_rcx;
+ register_t tf_r8;
+ register_t tf_r9;
+ register_t tf_rax;
+ register_t tf_rbx;
+ register_t tf_rbp;
+ register_t tf_r10;
+ register_t tf_r11;
+ register_t tf_r12;
+ register_t tf_r13;
+ register_t tf_r14;
+ register_t tf_r15;
+ register_t tf_trapno;
+ /* below portion defined in hardware */
+ register_t tf_err;
+ register_t tf_rip;
+ register_t tf_cs;
+ register_t tf_rflags;
+ register_t tf_rsp;
+ register_t tf_ss;
};
/* Interrupt stack frame */
struct intrframe {
- int if_vec;
- int if_fs;
- int if_es;
- int if_ds;
- int if_edi;
- int if_esi;
- int if_ebp;
- int :32;
- int if_ebx;
- int if_edx;
- int if_ecx;
- int if_eax;
- int :32; /* for compat with trap frame - trapno */
- int :32; /* for compat with trap frame - err */
- /* below portion defined in 386 hardware */
- int if_eip;
- int if_cs;
- int if_eflags;
- /* below only when crossing rings (e.g. user to kernel) */
- int if_esp;
- int if_ss;
+ 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 - 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 {
- int cf_vec;
- int cf_fs;
- int cf_es;
- int cf_ds;
- int cf_edi;
- int cf_esi;
- int cf_ebp;
- int :32;
- int cf_ebx;
- int cf_edx;
- int cf_ecx;
- int cf_eax;
- int :32; /* for compat with trap frame - trapno */
- int :32; /* for compat with trap frame - err */
- /* below portion defined in 386 hardware */
- int cf_eip;
- int cf_cs;
- int cf_eflags;
- /* below only when crossing rings (e.g. user to kernel) */
- int cf_esp;
- int cf_ss;
+ 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 - 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;
};
int kdb_trap(int, int, struct trapframe *);
-extern int (*pmath_emulate)(struct trapframe *);
-
-#define INTR_TO_TRAPFRAME(frame) ((struct trapframe *)&(frame)->if_fs)
#endif /* _MACHINE_FRAME_H_ */
diff --git a/sys/amd64/include/kse.h b/sys/amd64/include/kse.h
index feaf535126d2..c96e4f5d4d50 100644
--- a/sys/amd64/include/kse.h
+++ b/sys/amd64/include/kse.h
@@ -36,14 +36,7 @@
#include <machine/ucontext.h>
union kse_td_ctx {
-#ifdef _KERNEL
- struct {
- int tf_onstack;
- int tf_gs;
- struct trapframe tf_tf;
- } tfrm;
-#endif
- mcontext_t mcontext;
+ int teh_stuff;
};
#endif /* MACHINE_KSE_H */
diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h
index bf3eca4a20b4..c5f0e458dfc6 100644
--- a/sys/amd64/include/md_var.h
+++ b/sys/amd64/include/md_var.h
@@ -36,11 +36,6 @@
* Miscellaneous machine-dependent declarations.
*/
-extern void (*bcopy_vector)(const void *from, void *to, size_t len);
-extern void (*bzero_vector)(void *buf, size_t len);
-extern int (*copyin_vector)(const void *udaddr, void *kaddr, size_t len);
-extern int (*copyout_vector)(const void *kaddr, void *udaddr, size_t len);
-
extern long Maxmem;
extern u_int atdevbase; /* offset in virtual memory of ISA io mem */
extern int busdma_swi_pending;
@@ -51,37 +46,10 @@ extern u_int cpu_high;
extern u_int cpu_id;
extern u_int cpu_procinfo;
extern char cpu_vendor[];
-extern u_int cyrix_did;
extern uint16_t *elan_mmcr;
extern char kstack[];
-#ifdef PC98
-extern int need_pre_dma_flush;
-extern int need_post_dma_flush;
-#endif
extern char sigcode[];
extern int szsigcode;
-#ifdef COMPAT_FREEBSD4
-extern int szfreebsd4_sigcode;
-#endif
-#ifdef COMPAT_43
-extern int szosigcode;
-#endif
-#ifdef SWTCH_OPTIM_STATS
-extern int stupid_switch;
-extern int swtch_optim_stats;
-extern int tlb_flush_count;
-extern int lazy_flush_count;
-extern int lazy_flush_fixup;
-#ifdef SMP
-extern int lazy_flush_smpfixup;
-extern int lazy_flush_smpipi;
-extern int lazy_flush_smpbadcr3;
-extern int lazy_flush_smpmiss;
-#endif
-#endif
-#ifdef LAZY_SWITCH
-extern int lazy_flush_enable;
-#endif
typedef void alias_for_inthand_t(u_int cs, u_int ef, u_int esp, u_int ss);
struct thread;
@@ -94,28 +62,13 @@ void busdma_swi(void);
void cpu_halt(void);
void cpu_reset(void);
void cpu_setregs(void);
-void cpu_switch_load_gs(void) __asm(__STRING(cpu_switch_load_gs));
void doreti_iret(void) __asm(__STRING(doreti_iret));
void doreti_iret_fault(void) __asm(__STRING(doreti_iret_fault));
-void doreti_popl_ds(void) __asm(__STRING(doreti_popl_ds));
-void doreti_popl_ds_fault(void) __asm(__STRING(doreti_popl_ds_fault));
-void doreti_popl_es(void) __asm(__STRING(doreti_popl_es));
-void doreti_popl_es_fault(void) __asm(__STRING(doreti_popl_es_fault));
-void doreti_popl_fs(void) __asm(__STRING(doreti_popl_fs));
-void doreti_popl_fs_fault(void) __asm(__STRING(doreti_popl_fs_fault));
void enable_sse(void);
void fillw(int /*u_short*/ pat, void *base, size_t cnt);
-void i486_bzero(void *buf, size_t len);
-void i586_bcopy(const void *from, void *to, size_t len);
-void i586_bzero(void *buf, size_t len);
-int i586_copyin(const void *udaddr, void *kaddr, size_t len);
-int i586_copyout(const void *kaddr, void *udaddr, size_t len);
-void i686_pagezero(void *addr);
-void init_AMD_Elan_sc520(void);
+void pagezero(void *addr);
int is_physical_memory(vm_offset_t addr);
-vm_paddr_t kvtop(void *addr);
-void setidt(int idx, alias_for_inthand_t *func, int typ, int dpl, int selec);
+void setidt(int idx, alias_for_inthand_t *func, int typ, int dpl, int ist);
void swi_vm(void *);
-int user_dbreg_trap(void);
#endif /* !_MACHINE_MD_VAR_H_ */
diff --git a/sys/amd64/include/mutex.h b/sys/amd64/include/mutex.h
index 87d47e511ffc..eb13945419e6 100644
--- a/sys/amd64/include/mutex.h
+++ b/sys/amd64/include/mutex.h
@@ -56,20 +56,20 @@ extern struct mtx clock_lock;
* locks) in the near future, however.
*/
#define MTX_LOCK_SPIN(lck, flags) \
- pushl $0 ; \
- pushl $0 ; \
- pushl $flags ; \
- pushl $lck ; \
+ pushq $0 ; \
+ pushq $0 ; \
+ pushq $flags ; \
+ pushq $lck ; \
call _mtx_lock_spin_flags ; \
- addl $0x10, %esp ; \
+ addq $0x20, %rsp ; \
#define MTX_UNLOCK_SPIN(lck) \
- pushl $0 ; \
- pushl $0 ; \
- pushl $0 ; \
- pushl $lck ; \
+ pushq $0 ; \
+ pushq $0 ; \
+ pushq $0 ; \
+ pushq $lck ; \
call _mtx_unlock_spin_flags ; \
- addl $0x10, %esp ; \
+ addq $0x20, %rsp ; \
#endif /* !LOCORE */
#endif /* __MACHINE_MUTEX_H */
diff --git a/sys/amd64/include/npx.h b/sys/amd64/include/npx.h
index 8e0f9bc0036e..db1fe40089fb 100644
--- a/sys/amd64/include/npx.h
+++ b/sys/amd64/include/npx.h
@@ -45,81 +45,38 @@
#ifndef _MACHINE_NPX_H_
#define _MACHINE_NPX_H_
-/* Environment information of floating point unit */
-struct env87 {
- long en_cw; /* control word (16bits) */
- long en_sw; /* status word (16bits) */
- long en_tw; /* tag word (16bits) */
- long en_fip; /* floating point instruction pointer */
- u_short en_fcs; /* floating code segment selector */
- u_short en_opcode; /* opcode last executed (11 bits ) */
- long en_foo; /* floating operand offset */
- long en_fos; /* floating operand segment selector */
-};
-
-/* Contents of each floating point accumulator */
+/* Contents of each x87 floating point accumulator */
struct fpacc87 {
-#ifdef dontdef /* too unportable */
- u_long fp_mantlo; /* mantissa low (31:0) */
- u_long fp_manthi; /* mantissa high (63:32) */
- int fp_exp:15; /* exponent */
- int fp_sgn:1; /* mantissa sign */
-#else
u_char fp_bytes[10];
-#endif
};
-/* Floating point context */
-struct save87 {
- struct env87 sv_env; /* floating point control/status */
- struct fpacc87 sv_ac[8]; /* accumulator contents, 0-7 */
- u_char sv_pad0[4]; /* padding for (now unused) saved status word */
- /*
- * Bogus padding for emulators. Emulators should use their own
- * struct and arrange to store into this struct (ending here)
- * before it is inspected for ptracing or for core dumps. Some
- * emulators overwrite the whole struct. We have no good way of
- * knowing how much padding to leave. Leave just enough for the
- * GPL emulator's i387_union (176 bytes total).
- */
- u_char sv_pad[64]; /* padding; used by emulators */
+/* Contents of each SSE extended accumulator */
+struct xmmacc {
+ u_char xmm_bytes[16];
};
struct envxmm {
u_int16_t en_cw; /* control word (16bits) */
u_int16_t en_sw; /* status word (16bits) */
- u_int16_t en_tw; /* tag word (16bits) */
+ u_int8_t en_tw; /* tag word (8bits) */
+ u_int8_t en_zero;
u_int16_t en_opcode; /* opcode last executed (11 bits ) */
- u_int32_t en_fip; /* floating point instruction pointer */
- u_int16_t en_fcs; /* floating code segment selector */
- u_int16_t en_pad0; /* padding */
- u_int32_t en_foo; /* floating operand offset */
- u_int16_t en_fos; /* floating operand segment selector */
- u_int16_t en_pad1; /* padding */
+ u_int64_t en_rip; /* floating point instruction pointer */
+ u_int64_t en_rdp; /* floating operand pointer */
u_int32_t en_mxcsr; /* SSE sontorol/status register */
- u_int32_t en_pad2; /* padding */
+ u_int32_t en_mxcsr_mask; /* valid bits in mxcsr */
};
-/* Contents of each SSE extended accumulator */
-struct xmmacc {
- u_char xmm_bytes[16];
-};
-
-struct savexmm {
+struct savefpu {
struct envxmm sv_env;
struct {
struct fpacc87 fp_acc;
u_char fp_pad[6]; /* padding */
} sv_fp[8];
- struct xmmacc sv_xmm[8];
- u_char sv_pad[224];
+ struct xmmacc sv_xmm[16];
+ u_char sv_pad[96];
} __aligned(16);
-union savefpu {
- struct save87 sv_87;
- struct savexmm sv_xmm;
-};
-
/*
* The hardware default control word for i387's and later coprocessors is
* 0x37F, giving:
@@ -144,10 +101,10 @@ int npxdna(void);
void npxdrop(void);
void npxexit(struct thread *td);
int npxformat(void);
-int npxgetregs(struct thread *td, union savefpu *addr);
+int npxgetregs(struct thread *td, struct savefpu *addr);
void npxinit(u_short control);
-void npxsave(union savefpu *addr);
-void npxsetregs(struct thread *td, union savefpu *addr);
+void npxsave(struct savefpu *addr);
+void npxsetregs(struct thread *td, struct savefpu *addr);
int npxtrap(void);
#endif
diff --git a/sys/amd64/include/param.h b/sys/amd64/include/param.h
index 595502228c32..355e95de5d0f 100644
--- a/sys/amd64/include/param.h
+++ b/sys/amd64/include/param.h
@@ -40,7 +40,7 @@
*/
/*
- * Machine dependent constants for the AMD64.
+ * Machine dependent constants for AMD64.
*/
/*
@@ -55,7 +55,7 @@
*
*/
#ifndef _ALIGNBYTES
-#define _ALIGNBYTES (sizeof(int) - 1)
+#define _ALIGNBYTES (sizeof(long) - 1)
#endif
#ifndef _ALIGN
#define _ALIGN(p) (((u_long)(p) + _ALIGNBYTES) &~ _ALIGNBYTES)
@@ -83,40 +83,71 @@
#define MACHINE_ARCH "amd64"
#endif
-#ifdef SMP
-#define MAXCPU 16
-#else
#define MAXCPU 1
-#endif /* SMP */
#define ALIGNBYTES _ALIGNBYTES
#define ALIGN(p) _ALIGN(p)
#define ALIGNED_POINTER(p,t) _ALIGNED_POINTER((p),(t))
+/* Size of the level 1 page table units */
+#define NPTEPG (PAGE_SIZE/(sizeof (pt_entry_t)))
#define PAGE_SHIFT 12 /* LOG2(PAGE_SIZE) */
#define PAGE_SIZE (1<<PAGE_SHIFT) /* bytes/page */
#define PAGE_MASK (PAGE_SIZE-1)
-#define NPTEPG (PAGE_SIZE/(sizeof (pt_entry_t)))
-
-#define KERNBASE 0x0000000000000000LL /* start of kernel virtual */
-#define BTOPKERNBASE ((u_long)KERNBASE >> PGSHIFT)
+/* Size of the level 2 page directory units */
+#define NPDEPG (PAGE_SIZE/(sizeof (pd_entry_t)))
+#define PDRSHIFT 21 /* LOG2(NBPDR) */
+#define NBPDR (1<<PDRSHIFT) /* bytes/page dir */
+#define PDRMASK (NBPDR-1)
+/* Size of the level 3 page directory pointer table units */
+#define NPDPEPG (PAGE_SIZE/(sizeof (pdp_entry_t)))
+#define PDPSHIFT 30 /* LOG2(NBPDP) */
+#define NBPDP (1<<PDPSHIFT) /* bytes/page dir ptr table */
+#define PDPMASK (NBPDP-1)
+/* Size of the level 4 page-map level-4 table units */
+#define NPML4EPG (PAGE_SIZE/(sizeof (pml4_entry_t)))
+#define PML4SHIFT 39 /* LOG2(NBPML4T) */
+#define NBPML4T (1ul<<PML4SHIFT)/* bytes/page map lev4 table */
+#define PML4MASK (NBPML4T-1)
+
+#define NKPML4E 1 /* addressable number of page tables/pde's */
+#define NKPDPE 1 /* addressable number of page tables/pde's */
+#define NPGPTD 4
+
+#define NBPTD (NPGPTD<<PAGE_SHIFT)
+#define NPDEPTD (NBPTD/(sizeof (pd_entry_t)))
#define IOPAGES 2 /* pages of i/o permission bitmap */
-#ifndef KSTACK_PAGES
-#define KSTACK_PAGES 2 /* pages of kstack (with pcb) */
-#endif
+#define KSTACK_PAGES 4 /* pages of kstack (with pcb) */
#define UAREA_PAGES 1 /* holds struct user WITHOUT PCB (see def.) */
-#define KSTACK_GUARD 1 /* compile in the kstack guard page */
+#define KSTACK_GUARD 1 /* compile in the kstack guard page */
+
+/*
+ * Ceiling on amount of swblock kva space, can be changed via
+ * the kern.maxswzone /boot/loader.conf variable.
+ */
+#ifndef VM_SWZONE_SIZE_MAX
+#define VM_SWZONE_SIZE_MAX (32 * 1024 * 1024)
+#endif
+
+/*
+ * Ceiling on size of buffer cache (really only effects write queueing,
+ * the VM page cache is not effected), can be changed via
+ * the kern.maxbcache /boot/loader.conf variable.
+ */
+#ifndef VM_BCACHE_SIZE_MAX
+#define VM_BCACHE_SIZE_MAX (200 * 1024 * 1024)
+#endif
/*
* Mach derived conversion macros
*/
#define round_page(x) ((((unsigned long)(x)) + PAGE_MASK) & ~(PAGE_MASK))
#define trunc_page(x) ((unsigned long)(x) & ~(PAGE_MASK))
-#define trunc_4mpage(x) ((unsigned)(x) & ~PDRMASK)
-#define round_4mpage(x) ((((unsigned)(x)) + PDRMASK) & ~PDRMASK)
+#define trunc_2mpage(x) ((unsigned long)(x) & ~PDRMASK)
+#define round_2mpage(x) ((((unsigned long)(x)) + PDRMASK) & ~PDRMASK)
#define atop(x) ((unsigned long)(x) >> PAGE_SHIFT)
#define ptoa(x) ((unsigned long)(x) << PAGE_SHIFT)
@@ -124,7 +155,7 @@
#define amd64_btop(x) ((unsigned long)(x) >> PAGE_SHIFT)
#define amd64_ptob(x) ((unsigned long)(x) << PAGE_SHIFT)
-#define pgtok(x) ((x) * (PAGE_SIZE / 1024))
+#define pgtok(x) ((unsigned long)(x) * (PAGE_SIZE / 1024))
#endif /* !_MACHINE_PARAM_H_ */
#endif /* !_NO_NAMESPACE_POLLUTION */
diff --git a/sys/amd64/include/pcb.h b/sys/amd64/include/pcb.h
index c7a837b08782..551bf8fd22a8 100644
--- a/sys/amd64/include/pcb.h
+++ b/sys/amd64/include/pcb.h
@@ -46,34 +46,25 @@
#include <machine/npx.h>
struct pcb {
- int pcb_cr3;
- int pcb_edi;
- int pcb_esi;
- int pcb_ebp;
- int pcb_esp;
- int pcb_ebx;
- int pcb_eip;
+ register_t padxx[8];
+ register_t pcb_cr3;
+ register_t pcb_r15;
+ register_t pcb_r14;
+ register_t pcb_r13;
+ register_t pcb_r12;
+ register_t pcb_rbp;
+ register_t pcb_rsp;
+ register_t pcb_rbx;
+ register_t pcb_rip;
+ register_t pcb_rflags;
- int pcb_dr0;
- int pcb_dr1;
- int pcb_dr2;
- int pcb_dr3;
- int pcb_dr6;
- int pcb_dr7;
-
- union savefpu pcb_save;
- u_int pcb_flags;
-#define FP_SOFTFP 0x01 /* process using software fltng pnt emulator */
-#define PCB_DBREGS 0x02 /* process using debug registers */
-#define PCB_NPXTRAP 0x04 /* npx trap pending */
-#define PCB_NPXINITDONE 0x08 /* fpu state is initialized */
-#define PCB_VM86CALL 0x10 /* in vm86 call */
+ struct savefpu pcb_save;
+ u_long pcb_flags;
+#define PCB_NPXTRAP 0x01 /* npx trap pending */
+#define PCB_NPXINITDONE 0x02 /* fpu state is initialized */
+#define PCB_FULLCTX 0x04 /* full context restore on sysret */
caddr_t pcb_onfault; /* copyin/out fault recovery */
- int pcb_gs;
- struct pcb_ext *pcb_ext; /* optional pcb extension */
- int pcb_psl; /* process status long */
- u_long __pcb_spare[2]; /* adjust to avoid core dump size changes */
};
#ifdef _KERNEL
diff --git a/sys/amd64/include/pcb_ext.h b/sys/amd64/include/pcb_ext.h
index cf5a9119416c..6d1bde2d5f84 100644
--- a/sys/amd64/include/pcb_ext.h
+++ b/sys/amd64/include/pcb_ext.h
@@ -29,24 +29,4 @@
#ifndef _I386_PCB_EXT_H_
#define _I386_PCB_EXT_H_
-/*
- * Extension to the 386 process control block
- */
-#include <machine/tss.h>
-#include <machine/vm86.h>
-#include <machine/segments.h>
-
-struct pcb_ext {
- struct segment_descriptor ext_tssd; /* tss descriptor */
- struct i386tss ext_tss; /* per-process i386tss */
- caddr_t ext_iomap; /* i/o permission bitmap */
- struct vm86_kernel ext_vm86; /* vm86 area */
-};
-
-#ifdef _KERNEL
-
-int i386_extend_pcb(struct thread *);
-
-#endif
-
#endif /* _I386_PCB_EXT_H_ */
diff --git a/sys/amd64/include/pci_cfgreg.h b/sys/amd64/include/pci_cfgreg.h
index b17353179c51..75840aa3d7f5 100644
--- a/sys/amd64/include/pci_cfgreg.h
+++ b/sys/amd64/include/pci_cfgreg.h
@@ -38,12 +38,7 @@
#define CONF1_ENABLE_RES1 0x80000000ul
#define CONF2_ENABLE_PORT 0x0cf8
-#ifdef PC98
-#define CONF2_FORWARD_PORT 0x0cf9
-#else
#define CONF2_FORWARD_PORT 0x0cfa
-#endif
-
#define CONF2_ENABLE_CHK 0x0e
#define CONF2_ENABLE_RES 0x0e
@@ -51,4 +46,3 @@ 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);
int pci_cfgintr(int bus, int device, int pin, int oldirq);
-int pci_probe_route_table(int bus);
diff --git a/sys/amd64/include/pcpu.h b/sys/amd64/include/pcpu.h
index a680645ae75e..9543b2383b81 100644
--- a/sys/amd64/include/pcpu.h
+++ b/sys/amd64/include/pcpu.h
@@ -31,9 +31,6 @@
#ifdef _KERNEL
-#include <machine/segments.h>
-#include <machine/tss.h>
-
/*
* The SMP parts are setup in pmap.c and locore.s for the BSP, and
* mp_machdep.c sets up the data for the AP's to "see" when they awake.
@@ -42,15 +39,8 @@
* other processors"
*/
#define PCPU_MD_FIELDS \
- struct pcpu *pc_prvspace; /* Self-reference */ \
- struct i386tss pc_common_tss; \
- struct segment_descriptor pc_common_tssd; \
- struct segment_descriptor *pc_tss_gdt; \
- int pc_currentldt; \
- u_int32_t pc_int_pending; /* master int pending flag */ \
- u_int32_t pc_ipending; /* pending slow interrupts */ \
- u_int32_t pc_fpending; /* pending fast interrupts */ \
- u_int32_t pc_spending /* pending soft interrupts */
+ struct pcpu *pc_prvspace; /* Self-reference */ \
+ register_t pc_scratch_rsp; /* User %rsp in syscall */
#if defined(lint)
@@ -80,7 +70,7 @@ extern struct pcpu *pcpup;
#define __PCPU_PTR(name) ({ \
__pcpu_type(name) *__p; \
\
- __asm __volatile("movl %%fs:%1,%0; addl %2,%0" \
+ __asm __volatile("movq %%gs:%1,%0; addq %2,%0" \
: "=r" (__p) \
: "m" (*(struct pcpu *)(__pcpu_offset(pc_prvspace))), \
"i" (__pcpu_offset(name))); \
@@ -96,22 +86,28 @@ extern struct pcpu *pcpup;
\
if (sizeof(__result) == 1) { \
u_char __b; \
- __asm __volatile("movb %%fs:%1,%0" \
+ __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 %%fs:%1,%0" \
+ __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 %%fs:%1,%0" \
+ __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; \
} else { \
__result = *__PCPU_PTR(name); \
} \
@@ -128,21 +124,27 @@ extern struct pcpu *pcpup;
if (sizeof(__val) == 1) { \
u_char __b; \
__b = *(u_char *)&__val; \
- __asm __volatile("movb %1,%%fs:%0" \
+ __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,%%fs:%0" \
+ __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,%%fs:%0" \
+ __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)); \
} else { \
*__PCPU_PTR(name) = __val; \
} \
diff --git a/sys/amd64/include/pmap.h b/sys/amd64/include/pmap.h
index 58e9182e22cf..d3e2104c3bec 100644
--- a/sys/amd64/include/pmap.h
+++ b/sys/amd64/include/pmap.h
@@ -83,52 +83,36 @@
#define PGEX_U 0x04 /* access from User mode (UPL) */
/*
- * Size of Kernel address space. This is the number of page table pages
- * (4MB each) to use for the kernel. 256 pages == 1 Gigabyte.
- * This **MUST** be a multiple of 4 (eg: 252, 256, 260, etc).
+ * Size of Kernel address space. This is the number of level 4 (top)
+ * entries. We use half of them for the kernel due to the 48 bit
+ * virtual address sign extension.
*/
-#ifndef KVA_PAGES
-#ifdef PAE
-#define KVA_PAGES 512
-#else
-#define KVA_PAGES 256
-#endif
-#endif
-
+#define KVA_PAGES 1536
+
/*
- * Pte related macros
+ * Pte related macros. This is complicated by having to deal with
+ * the sign extension of the 48th bit.
*/
-#define VADDR(pdi, pti) ((vm_offset_t)(((pdi)<<PDRSHIFT)|((pti)<<PAGE_SHIFT)))
+#define VADDR_SIGN(l4) \
+ ((l4) >= NPML4EPG/2 ? ((unsigned long)-1 << 47) : 0ul)
+#define VADDR(l4, l3, l2, l1) ( \
+ ((unsigned long)(l4) << PML4SHIFT) | VADDR_SIGN(l4) | \
+ ((unsigned long)(l3) << PDPSHIFT) | \
+ ((unsigned long)(l2) << PDRSHIFT) | \
+ ((unsigned long)(l1) << PAGE_SHIFT))
+
#ifndef NKPT
-#ifdef PAE
-#define NKPT 120 /* actual number of kernel page tables */
-#else
-#define NKPT 30 /* actual number of kernel page tables */
-#endif
-#endif
-#ifndef NKPDE
-#ifdef SMP
-#define NKPDE (KVA_PAGES - 1) /* number of page tables/pde's */
-#else
-#define NKPDE (KVA_PAGES) /* number of page tables/pde's */
+#define NKPT 120 /* initial number of kernel page tables */
#endif
+#ifndef NKPDE
+#define NKPDE (KVA_PAGES) /* number of page tables/pde's */
#endif
/*
* The *PTDI values control the layout of virtual memory
- *
- * XXX This works for now, but I am not real happy with it, I'll fix it
- * right after I fix locore.s and the magic 28K hole
- *
- * SMP_PRIVPAGES: The per-cpu address space is 0xff80000 -> 0xffbfffff
*/
-#ifdef SMP
-#define MPPTDI (NPDEPTD-1) /* per cpu ptd entry */
-#define KPTDI (MPPTDI-NKPDE) /* start of kernel virtual pde's */
-#else
-#define KPTDI (NPDEPTD-NKPDE)/* start of kernel virtual pde's */
-#endif /* SMP */
+#define KPTDI (NPDEPTD-NKPDE) /* start of kernel virtual pde's */
#define PTDPTDI (KPTDI-NPGPTD) /* ptd entry that points to ptd! */
/*
@@ -141,38 +125,37 @@
#include <sys/queue.h>
-#ifdef PAE
-
-typedef uint64_t pdpt_entry_t;
-typedef uint64_t pd_entry_t;
-typedef uint64_t pt_entry_t;
+typedef u_int64_t pd_entry_t;
+typedef u_int64_t pt_entry_t;
+typedef u_int64_t pdp_entry_t;
+typedef u_int64_t pml4_entry_t;
+#define PML4ESHIFT (3)
+#define PDPESHIFT (3)
#define PTESHIFT (3)
#define PDESHIFT (3)
-#else
-
-typedef uint32_t pd_entry_t;
-typedef uint32_t pt_entry_t;
-
-#define PTESHIFT (2)
-#define PDESHIFT (2)
-
-#endif
-
/*
* Address of current and alternate address space page table maps
* and directories.
+ * XXX it might be saner to just direct map all of physical memory
+ * into the kernel using 2MB pages. We have enough space to do
+ * it (2^47 bits of KVM, while current max physical addressability
+ * is 2^40 physical bits). Then we can get rid of the evil hole
+ * in the page tables and the evil overlapping.
*/
#ifdef _KERNEL
-extern pt_entry_t PTmap[];
-extern pd_entry_t PTD[];
-extern pd_entry_t PTDpde[];
-
-#ifdef PAE
-extern pdpt_entry_t *IdlePDPT;
-#endif
-extern pd_entry_t *IdlePTD; /* physical address of "Idle" state directory */
+extern pt_entry_t PTmap[];
+extern pd_entry_t PDmap[];
+extern pdp_entry_t PDPmap[];
+extern pml4_entry_t PML4[];
+extern pdp_entry_t PDP[];
+extern pd_entry_t PTD[];
+extern pd_entry_t PTDpde[];
+
+extern u_int64_t IdlePML4; /* physical address of "Idle" state directory */
+extern u_int64_t IdlePDP; /* physical address of "Idle" state directory */
+extern u_int64_t IdlePTD; /* physical address of "Idle" state directory */
#endif
#ifdef _KERNEL
@@ -182,7 +165,7 @@ extern pd_entry_t *IdlePTD; /* physical address of "Idle" state directory */
* Note: these work recursively, thus vtopte of a pte will give
* the corresponding pde that in turn maps it.
*/
-#define vtopte(va) (PTmap + i386_btop(va))
+#define vtopte(va) (PTmap + amd64_btop(va))
/*
* Routine: pmap_kextract
@@ -195,7 +178,8 @@ pmap_kextract(vm_offset_t va)
{
vm_paddr_t pa;
- if ((pa = PTD[va >> PDRSHIFT]) & PG_PS) {
+ pa = PTD[va >> PDRSHIFT];
+ if (pa & PG_PS) {
pa = (pa & ~(NBPDR - 1)) | (va & (NBPDR - 1));
} else {
pa = *vtopte(va);
@@ -206,39 +190,6 @@ pmap_kextract(vm_offset_t va)
#define vtophys(va) pmap_kextract(((vm_offset_t) (va)))
-#ifdef PAE
-
-static __inline pt_entry_t
-pte_load(pt_entry_t *ptep)
-{
- pt_entry_t r;
-
- __asm __volatile(
- "lock; cmpxchg8b %1"
- : "=A" (r)
- : "m" (*ptep), "a" (0), "d" (0), "b" (0), "c" (0));
- return (r);
-}
-
-static __inline pt_entry_t
-pte_load_store(pt_entry_t *ptep, pt_entry_t v)
-{
- pt_entry_t r;
-
- r = *ptep;
- __asm __volatile(
- "1:\n"
- "\tlock; cmpxchg8b %1\n"
- "\tjnz 1b"
- : "+A" (r)
- : "m" (*ptep), "b" ((uint32_t)v), "c" ((uint32_t)(v >> 32)));
- return (r);
-}
-
-#define pte_load_clear(ptep) pte_load_store((ptep), (pt_entry_t)0ULL)
-
-#else /* PAE */
-
static __inline pt_entry_t
pte_load(pt_entry_t *ptep)
{
@@ -258,9 +209,7 @@ pte_load_store(pt_entry_t *ptep, pt_entry_t pte)
return (r);
}
-#define pte_load_clear(pte) atomic_readandclear_int(pte)
-
-#endif /* PAE */
+#define pte_load_clear(pte) atomic_readandclear_long(pte)
#define pte_clear(ptep) pte_load_store((ptep), (pt_entry_t)0ULL)
#define pte_store(ptep, pte) pte_load_store((ptep), (pt_entry_t)pte)
@@ -283,13 +232,11 @@ struct pmap {
pd_entry_t *pm_pdir; /* KVA of page directory */
vm_object_t pm_pteobj; /* Container for pte's */
TAILQ_HEAD(,pv_entry) pm_pvlist; /* list of mappings in pmap */
- u_int pm_active; /* active on cpus */
+ u_long pm_active; /* active on cpus */
struct pmap_statistics pm_stats; /* pmap statistics */
LIST_ENTRY(pmap) pm_list; /* List of all pmaps */
-#ifdef PAE
- pdpt_entry_t *pm_pdpt; /* KVA of page director pointer
- table */
-#endif
+ pdp_entry_t *pm_pdp; /* KVA of level 3 page table */
+ pml4_entry_t *pm_pml4; /* KVA of level 4 page table */
};
#define pmap_page_is_mapped(m) (!TAILQ_EMPTY(&(m)->md.pv_list))
@@ -341,7 +288,6 @@ void pmap_kremove(vm_offset_t);
void *pmap_mapdev(vm_paddr_t, vm_size_t);
void pmap_unmapdev(vm_offset_t, vm_size_t);
pt_entry_t *pmap_pte_quick(pmap_t, vm_offset_t) __pure2;
-void pmap_set_opt(void);
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);
diff --git a/sys/amd64/include/proc.h b/sys/amd64/include/proc.h
index bff037aba034..cd54c244f1af 100644
--- a/sys/amd64/include/proc.h
+++ b/sys/amd64/include/proc.h
@@ -37,35 +37,14 @@
#ifndef _MACHINE_PROC_H_
#define _MACHINE_PROC_H_
-#include <machine/segments.h>
-
-struct proc_ldt {
- caddr_t ldt_base;
- int ldt_len;
- int ldt_refcnt;
- u_long ldt_active;
- struct segment_descriptor ldt_sd;
-};
-
/*
- * Machine-dependent part of the proc structure for i386.
+ * Machine-dependent part of the proc structure for AMD64.
*/
struct mdthread {
-#ifdef lint
- int dummy;
-#endif
+ register_t md_savecrit;
};
struct mdproc {
- struct proc_ldt *md_ldt; /* (j) per-process ldt */
};
-#ifdef _KERNEL
-
-void set_user_ldt(struct mdproc *);
-struct proc_ldt *user_ldt_alloc(struct mdproc *, int);
-void user_ldt_free(struct thread *);
-
-#endif /* _KERNEL */
-
#endif /* !_MACHINE_PROC_H_ */
diff --git a/sys/amd64/include/profile.h b/sys/amd64/include/profile.h
index 0df319543489..7330ae080c1c 100644
--- a/sys/amd64/include/profile.h
+++ b/sys/amd64/include/profile.h
@@ -65,14 +65,14 @@
#define MCOUNT_DECL(s) u_long s;
#ifdef SMP
extern int mcount_lock;
-#define MCOUNT_ENTER(s) { s = read_eflags(); disable_intr(); \
+#define MCOUNT_ENTER(s) { s = read_rflags(); disable_intr(); \
while (!atomic_cmpset_acq_int(&mcount_lock, 0, 1)) \
/* nothing */ ; }
#define MCOUNT_EXIT(s) { atomic_store_rel_int(&mcount_lock, 0); \
- write_eflags(s); }
+ write_rflags(s); }
#else
-#define MCOUNT_ENTER(s) { s = read_eflags(); disable_intr(); }
-#define MCOUNT_EXIT(s) (write_eflags(s))
+#define MCOUNT_ENTER(s) { s = read_rflags(); disable_intr(); }
+#define MCOUNT_EXIT(s) (write_rflags(s))
#endif
#endif /* GUPROF */
@@ -94,14 +94,14 @@ mcount() \
* \
* selfpc = pc pushed by call to mcount \
*/ \
- asm("movl 4(%%ebp),%0" : "=r" (selfpc)); \
+ asm("movq 8(%%rbp),%0" : "=r" (selfpc)); \
/* \
* frompc = pc pushed by call to mcount's caller. \
* The caller's stack frame has already been built, so %ebp is \
* the caller's frame pointer. The caller's raddr is in the \
* caller's frame following the caller's caller's frame pointer.\
*/ \
- asm("movl (%%ebp),%0" : "=r" (frompc)); \
+ asm("movq (%%rbp),%0" : "=r" (frompc)); \
frompc = ((uintfptr_t *)frompc)[1]; \
_mcount(frompc, selfpc); \
}
@@ -113,7 +113,7 @@ mcount() \
}
#endif /* __GNUC__ */
-typedef unsigned int uintfptr_t;
+typedef unsigned long uintfptr_t;
#endif /* _KERNEL */
diff --git a/sys/amd64/include/psl.h b/sys/amd64/include/psl.h
index 302d46990885..04d83ff79764 100644
--- a/sys/amd64/include/psl.h
+++ b/sys/amd64/include/psl.h
@@ -55,10 +55,10 @@
#define PSL_IOPL 0x00003000 /* i/o privilege level */
#define PSL_NT 0x00004000 /* nested task bit */
#define PSL_RF 0x00010000 /* resume flag bit */
-#define PSL_VM 0x00020000 /* virtual 8086 mode bit */
+/* #define PSL_VM 0x00020000 */ /* virtual 8086 mode bit */
#define PSL_AC 0x00040000 /* alignment checking */
-#define PSL_VIF 0x00080000 /* virtual interrupt enable */
-#define PSL_VIP 0x00100000 /* virtual interrupt pending */
+/* #define PSL_VIF 0x00080000 */ /* virtual interrupt enable */
+/* #define PSL_VIP 0x00100000 */ /* virtual interrupt pending */
#define PSL_ID 0x00200000 /* identification bit */
/*
diff --git a/sys/amd64/include/reg.h b/sys/amd64/include/reg.h
index 56f0f913293d..334dd376883a 100644
--- a/sys/amd64/include/reg.h
+++ b/sys/amd64/include/reg.h
@@ -41,66 +41,31 @@
#define _MACHINE_REG_H_
/*
- * Indices for registers in `struct trapframe' and `struct regs'.
- *
- * This interface is deprecated. In the kernel, it is only used in FPU
- * emulators to convert from register numbers encoded in instructions to
- * register values. Everything else just accesses the relevant struct
- * members. In userland, debuggers tend to abuse this interface since
- * they don't understand that `struct regs' is a struct. I hope they have
- * stopped accessing the registers in the trap frame via PT_{READ,WRITE}_U
- * and we can stop supporting the user area soon.
- */
-#define tFS (0)
-#define tES (1)
-#define tDS (2)
-#define tEDI (3)
-#define tESI (4)
-#define tEBP (5)
-#define tISP (6)
-#define tEBX (7)
-#define tEDX (8)
-#define tECX (9)
-#define tEAX (10)
-#define tERR (12)
-#define tEIP (13)
-#define tCS (14)
-#define tEFLAGS (15)
-#define tESP (16)
-#define tSS (17)
-
-/*
- * Indices for registers in `struct regs' only.
- *
- * Some registers live in the pcb and are only in an "array" with the
- * other registers in application interfaces that copy all the registers
- * to or from a `struct regs'.
- */
-#define tGS (18)
-
-/*
* Register set accessible via /proc/$pid/regs and PT_{SET,GET}REGS.
*/
struct reg {
- unsigned int r_fs;
- unsigned int r_es;
- unsigned int r_ds;
- unsigned int r_edi;
- unsigned int r_esi;
- unsigned int r_ebp;
- unsigned int r_isp;
- unsigned int r_ebx;
- unsigned int r_edx;
- unsigned int r_ecx;
- unsigned int r_eax;
- unsigned int r_trapno;
- unsigned int r_err;
- unsigned int r_eip;
- unsigned int r_cs;
- unsigned int r_eflags;
- unsigned int r_esp;
- unsigned int r_ss;
- unsigned int r_gs;
+ register_t r_r15;
+ register_t r_r14;
+ register_t r_r13;
+ register_t r_r12;
+ register_t r_r11;
+ register_t r_r10;
+ register_t r_r9;
+ register_t r_r8;
+ register_t r_rdi;
+ register_t r_rsi;
+ register_t r_rbp;
+ register_t r_rbx;
+ register_t r_rdx;
+ register_t r_rcx;
+ register_t r_rax;
+ register_t r_trapno;
+ register_t r_err;
+ register_t r_rip;
+ register_t r_cs;
+ register_t r_rflags;
+ register_t r_rsp;
+ register_t r_ss;
};
/*
@@ -112,30 +77,15 @@ struct fpreg {
* simplified struct. This may be too much detail. Perhaps
* an array of unsigned longs is best.
*/
- unsigned long fpr_env[7];
- unsigned char fpr_acc[8][10];
- unsigned long fpr_ex_sw;
- unsigned char fpr_pad[64];
+ unsigned long fpr_env[4];
+ unsigned char fpr_acc[8][16];
+ unsigned char fpr_xacc[16][16];
};
-/*
- * Register set accessible via /proc/$pid/dbregs.
- */
struct dbreg {
- unsigned int dr[8]; /* debug registers */
- /* Index 0-3: debug address registers */
- /* Index 4-5: reserved */
- /* Index 6: debug status */
- /* Index 7: debug control */
+ unsigned long grrr;
};
-#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 - dr7 by
- register number */
-
-
#ifdef _KERNEL
/*
* XXX these interfaces are MI, so they should be declared in a MI place.
diff --git a/sys/amd64/include/segments.h b/sys/amd64/include/segments.h
index 95117daaf6b0..0f9a59bd5f75 100644
--- a/sys/amd64/include/segments.h
+++ b/sys/amd64/include/segments.h
@@ -42,8 +42,7 @@
#define _MACHINE_SEGMENTS_H_
/*
- * 386 Segmentation Data Structures and definitions
- * William F. Jolitz (william@ernie.berkeley.edu) 6/20/1989
+ * AMD64 Segmentation Data Structures and definitions
*/
/*
@@ -60,60 +59,66 @@
#define GSEL(s,r) (((s)<<3) | r) /* a global selector */
/*
- * Memory and System segment descriptors
+ * User segment descriptors (%cs, %ds etc for compatability apps. 64 bit wide)
+ * For long-mode apps, %cs only has the conforming bit in sd_type, the sd_dpl,
+ * sd_p, sd_l and sd_def32 which must be zero). %ds only has sd_p.
*/
-struct segment_descriptor {
- unsigned sd_lolimit:16 ; /* segment extent (lsb) */
- unsigned sd_lobase:24 __packed; /* segment base address (lsb) */
- unsigned sd_type:5 ; /* segment type */
- unsigned sd_dpl:2 ; /* segment descriptor priority level */
- unsigned sd_p:1 ; /* segment descriptor present */
- unsigned sd_hilimit:4 ; /* segment extent (msb) */
- unsigned sd_xx:2 ; /* unused */
- unsigned sd_def32:1 ; /* default 32 vs 16 bit size */
- unsigned sd_gran:1 ; /* limit granularity (byte/page units)*/
- unsigned sd_hibase:8 ; /* segment base address (msb) */
-} ;
+struct user_segment_descriptor {
+ u_int64_t sd_lolimit:16; /* segment extent (lsb) */
+ u_int64_t sd_lobase:24; /* segment base address (lsb) */
+ u_int64_t sd_type:5; /* segment type */
+ u_int64_t sd_dpl:2; /* segment descriptor priority level */
+ u_int64_t sd_p:1; /* segment descriptor present */
+ u_int64_t sd_hilimit:4; /* segment extent (msb) */
+ u_int64_t sd_xx:1; /* unused */
+ u_int64_t sd_long:1; /* long mode (cs only) */
+ u_int64_t sd_def32:1; /* default 32 vs 16 bit size */
+ u_int64_t sd_gran:1; /* limit granularity (byte/page units)*/
+ u_int64_t sd_hibase:8; /* segment base address (msb) */
+} __packed;
/*
- * Gate descriptors (e.g. indirect descriptors)
+ * System segment descriptors (128 bit wide)
*/
-struct gate_descriptor {
- unsigned gd_looffset:16 ; /* gate offset (lsb) */
- unsigned gd_selector:16 ; /* gate segment selector */
- unsigned gd_stkcpy:5 ; /* number of stack wds to cpy */
- unsigned gd_xx:3 ; /* unused */
- unsigned gd_type:5 ; /* segment type */
- unsigned gd_dpl:2 ; /* segment descriptor priority level */
- unsigned gd_p:1 ; /* segment descriptor present */
- unsigned gd_hioffset:16 ; /* gate offset (msb) */
-} ;
+struct system_segment_descriptor {
+ u_int64_t sd_lolimit:16; /* segment extent (lsb) */
+ u_int64_t sd_lobase:24; /* segment base address (lsb) */
+ u_int64_t sd_type:5; /* segment type */
+ u_int64_t sd_dpl:2; /* segment descriptor priority level */
+ u_int64_t sd_p:1; /* segment descriptor present */
+ u_int64_t sd_hilimit:4; /* segment extent (msb) */
+ u_int64_t sd_xx0:3; /* unused */
+ u_int64_t sd_gran:1; /* limit granularity (byte/page units)*/
+ u_int64_t sd_hibase:40 __packed;/* segment base address (msb) */
+ u_int64_t sd_xx1:8;
+ u_int64_t sd_mbz:5; /* MUST be zero */
+ u_int64_t sd_xx2:19;
+} __packed;
/*
- * Generic descriptor
+ * Gate descriptors (e.g. indirect descriptors, trap, interrupt etc. 128 bit)
+ * Only interrupt and trap gates have gd_ist.
*/
-union descriptor {
- struct segment_descriptor sd;
- struct gate_descriptor gd;
-};
+struct gate_descriptor {
+ u_int64_t gd_looffset:16; /* gate offset (lsb) */
+ u_int64_t gd_selector:16; /* gate segment selector */
+ u_int64_t gd_ist:3; /* IST table index */
+ u_int64_t gd_xx:5; /* unused */
+ u_int64_t gd_type:5; /* segment type */
+ u_int64_t gd_dpl:2; /* segment descriptor priority level */
+ u_int64_t gd_p:1; /* segment descriptor present */
+ u_int64_t gd_hioffset:48 __packed; /* gate offset (msb) */
+ u_int64_t sd_xx1:32;
+} __packed;
/* system segments and gate types */
#define SDT_SYSNULL 0 /* system null */
-#define SDT_SYS286TSS 1 /* system 286 TSS available */
-#define SDT_SYSLDT 2 /* system local descriptor table */
-#define SDT_SYS286BSY 3 /* system 286 TSS busy */
-#define SDT_SYS286CGT 4 /* system 286 call gate */
-#define SDT_SYSTASKGT 5 /* system task gate */
-#define SDT_SYS286IGT 6 /* system 286 interrupt gate */
-#define SDT_SYS286TGT 7 /* system 286 trap gate */
-#define SDT_SYSNULL2 8 /* system null again */
-#define SDT_SYS386TSS 9 /* system 386 TSS available */
-#define SDT_SYSNULL3 10 /* system null again */
-#define SDT_SYS386BSY 11 /* system 386 TSS busy */
-#define SDT_SYS386CGT 12 /* system 386 call gate */
-#define SDT_SYSNULL4 13 /* system null again */
-#define SDT_SYS386IGT 14 /* system 386 interrupt gate */
-#define SDT_SYS386TGT 15 /* system 386 trap gate */
+#define SDT_SYSLDT 2 /* system 64 bit local descriptor table */
+#define SDT_SYSTSS 9 /* system available 64 bit TSS */
+#define SDT_SYSBSY 11 /* system busy 64 bit TSS */
+#define SDT_SYSCGT 12 /* system 64 bit call gate */
+#define SDT_SYSIGT 14 /* system 64 bit interrupt gate */
+#define SDT_SYSTGT 15 /* system 64 bit trap gate */
/* memory segment types */
#define SDT_MEMRO 16 /* memory read only */
@@ -139,45 +144,29 @@ union descriptor {
* when needed to be used by the 386 hardware
*/
-struct soft_segment_descriptor {
- unsigned ssd_base ; /* segment base address */
- unsigned ssd_limit ; /* segment extent */
- unsigned ssd_type:5 ; /* segment type */
- unsigned ssd_dpl:2 ; /* segment descriptor priority level */
- unsigned ssd_p:1 ; /* segment descriptor present */
- unsigned ssd_xx:4 ; /* unused */
- unsigned ssd_xx1:2 ; /* unused */
- unsigned ssd_def32:1 ; /* default 32 vs 16 bit size */
- unsigned ssd_gran:1 ; /* limit granularity (byte/page units)*/
-};
+struct soft_segment_descriptor {
+ unsigned long ssd_base; /* segment base address */
+ unsigned long ssd_limit; /* segment extent */
+ unsigned long ssd_type:5; /* segment type */
+ unsigned long ssd_dpl:2; /* segment descriptor priority level */
+ unsigned long ssd_p:1; /* segment descriptor present */
+ unsigned long ssd_long:1; /* long mode (for %cs) */
+ unsigned long ssd_def32:1; /* default 32 vs 16 bit size */
+ unsigned long ssd_gran:1; /* limit granularity (byte/page units)*/
+} __packed;
/*
* region descriptors, used to load gdt/idt tables before segments yet exist.
*/
struct region_descriptor {
- unsigned rd_limit:16; /* segment extent */
- unsigned rd_base:32 __packed; /* base address */
-};
-
-/*
- * Segment Protection Exception code bits
- */
-
-#define SEGEX_EXT 0x01 /* recursive or externally induced */
-#define SEGEX_IDT 0x02 /* interrupt descriptor table */
-#define SEGEX_TI 0x04 /* local descriptor table */
- /* other bits are affected descriptor index */
-#define SEGEX_IDX(s) (((s)>>3)&0x1fff)
+ unsigned long rd_limit:16; /* segment extent */
+ unsigned long rd_base:64 __packed; /* base address */
+} __packed;
/*
* Size of IDT table
*/
-
-#if defined(SMP) || defined(APIC_IO)
-#define NIDT 256 /* we use them all */
-#else
#define NIDT 129 /* 32 reserved, 16 h/w, 0 s/w, linux's 0x80 */
-#endif /* SMP || APIC_IO */
#define NRSVIDT 32 /* reserved entries for cpu exceptions */
/*
@@ -186,47 +175,25 @@ struct region_descriptor {
#define GNULL_SEL 0 /* Null Descriptor */
#define GCODE_SEL 1 /* Kernel Code Descriptor */
#define GDATA_SEL 2 /* Kernel Data Descriptor */
-#define GPRIV_SEL 3 /* SMP Per-Processor Private Data */
-#define GPROC0_SEL 4 /* Task state process slot zero and up */
-#define GLDT_SEL 5 /* LDT - eventually one per process */
-#define GUSERLDT_SEL 6 /* User LDT */
-#define GTGATE_SEL 7 /* Process task switch gate */
-#define GBIOSLOWMEM_SEL 8 /* BIOS low memory access (must be entry 8) */
-#define GPANIC_SEL 9 /* Task state to consider panic from */
-#define GBIOSCODE32_SEL 10 /* BIOS interface (32bit Code) */
-#define GBIOSCODE16_SEL 11 /* BIOS interface (16bit Code) */
-#define GBIOSDATA_SEL 12 /* BIOS interface (Data) */
-#define GBIOSUTIL_SEL 13 /* BIOS interface (Utility) */
-#define GBIOSARGS_SEL 14 /* BIOS interface (Arguments) */
-
-#define NGDT 15
-
-/*
- * Entries in the Local Descriptor Table (LDT)
- */
-#define LSYS5CALLS_SEL 0 /* forced by intel BCS */
-#define LSYS5SIGR_SEL 1
-#define L43BSDCALLS_SEL 2 /* notyet */
-#define LUCODE_SEL 3
-#define LSOL26CALLS_SEL 4 /* Solaris >= 2.6 system call gate */
-#define LUDATA_SEL 5
-/* separate stack, es,fs,gs sels ? */
-/* #define LPOSIXCALLS_SEL 5*/ /* notyet */
-#define LBSDICALLS_SEL 16 /* BSDI system call gate */
-#define NLDT (LBSDICALLS_SEL + 1)
+#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 */
+/* slot 6 is second half of GPROC0_SEL */
+#define NGDT 8
#ifdef _KERNEL
-extern int _default_ldt;
-extern union descriptor gdt[];
+extern struct user_segment_descriptor gdt[];
extern struct soft_segment_descriptor gdt_segs[];
extern struct gate_descriptor *idt;
-extern union descriptor ldt[NLDT];
void lgdt(struct region_descriptor *rdp);
-void sdtossd(struct segment_descriptor *sdp,
+void sdtossd(struct user_segment_descriptor *sdp,
struct soft_segment_descriptor *ssdp);
void ssdtosd(struct soft_segment_descriptor *ssdp,
- struct segment_descriptor *sdp);
+ struct user_segment_descriptor *sdp);
+void ssdtosyssd(struct soft_segment_descriptor *ssdp,
+ struct system_segment_descriptor *sdp);
#endif /* _KERNEL */
#endif /* !_MACHINE_SEGMENTS_H_ */
diff --git a/sys/amd64/include/setjmp.h b/sys/amd64/include/setjmp.h
index e6e0371d5d1b..a6a9399a75c9 100644
--- a/sys/amd64/include/setjmp.h
+++ b/sys/amd64/include/setjmp.h
@@ -37,7 +37,7 @@
#include <sys/cdefs.h>
-#define _JBLEN 11 /* Size of the jmp_buf on x86. */
+#define _JBLEN 22 /* Size of the jmp_buf on x86. */
/*
* jmp_buf and sigjmp_buf are encapsulated in different structs to force
diff --git a/sys/amd64/include/sigframe.h b/sys/amd64/include/sigframe.h
index 98be731d8f10..d104507d52f8 100644
--- a/sys/amd64/include/sigframe.h
+++ b/sys/amd64/include/sigframe.h
@@ -34,74 +34,7 @@
/*
* Signal frames, arguments passed to application signal handlers.
*/
-#ifdef _KERNEL
-#ifdef COMPAT_43
-struct osigframe {
- /*
- * The first four members may be used by applications.
- */
-
- register_t sf_signum;
-
- /*
- * Either 'int' for old-style FreeBSD handler or 'siginfo_t *'
- * pointing to sf_siginfo for SA_SIGINFO handlers.
- */
- register_t sf_arg2;
-
- /* Points to sf_siginfo.si_sc. */
- register_t sf_scp;
-
- register_t sf_addr;
-
- /*
- * The following arguments are not constrained by the
- * function call protocol.
- * Applications are not supposed to access these members,
- * except using the pointers we provide in the first three
- * arguments.
- */
-
- union {
- __osiginfohandler_t *sf_action;
- __sighandler_t *sf_handler;
- } sf_ahu;
-
- /* In the SA_SIGINFO case, sf_arg2 points here. */
- osiginfo_t sf_siginfo;
-};
-#endif
-#ifdef COMPAT_FREEBSD4
-/* FreeBSD 4.x */
-struct sigframe4 {
- register_t sf_signum;
- register_t sf_siginfo; /* code or pointer to sf_si */
- register_t sf_ucontext; /* points to sf_uc */
- register_t sf_addr; /* undocumented 4th arg */
-
- union {
- __siginfohandler_t *sf_action;
- __sighandler_t *sf_handler;
- } sf_ahu;
- struct ucontext4 sf_uc; /* = *sf_ucontext */
- siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case) */
-};
-#endif
-#endif
-
struct sigframe {
- /*
- * The first four members may be used by applications.
- *
- * NOTE: The 4th argument is undocumented, ill commented
- * on and seems to be somewhat BSD "standard". Handlers
- * installed with sigvec may be using it.
- */
- register_t sf_signum;
- register_t sf_siginfo; /* code or pointer to sf_si */
- register_t sf_ucontext; /* points to sf_uc */
- register_t sf_addr; /* undocumented 4th arg */
-
union {
__siginfohandler_t *sf_action;
__sighandler_t *sf_handler;
diff --git a/sys/amd64/include/signal.h b/sys/amd64/include/signal.h
index fb2d82c4d489..baa0c4e01369 100644
--- a/sys/amd64/include/signal.h
+++ b/sys/amd64/include/signal.h
@@ -44,7 +44,7 @@
* Machine-dependent signal definitions
*/
-typedef int sig_atomic_t;
+typedef long sig_atomic_t;
#if __XSI_VISIBLE
/*
@@ -60,7 +60,6 @@ typedef int sig_atomic_t;
/*
* Only the kernel should need these old type definitions.
*/
-#if defined(_KERNEL) && defined(COMPAT_43)
/*
* Information pushed on stack when a signal is delivered.
* This is used by the kernel to restore state following
@@ -68,75 +67,46 @@ typedef int sig_atomic_t;
* to the handler to allow it to restore state properly if
* a non-standard exit is performed.
*/
-struct osigcontext {
- int sc_onstack; /* sigstack state to restore */
- osigset_t sc_mask; /* signal mask to restore */
- int sc_esp; /* machine state follows: */
- int sc_ebp;
- int sc_isp;
- int sc_eip;
- int sc_efl;
- int sc_es;
- int sc_ds;
- int sc_cs;
- int sc_ss;
- int sc_edi;
- int sc_esi;
- int sc_ebx;
- int sc_edx;
- int sc_ecx;
- int sc_eax;
- int sc_gs;
- int sc_fs;
- int sc_trapno;
- int sc_err;
-};
-#endif
-
/*
* The sequence of the fields/registers in struct sigcontext should match
* those in mcontext_t.
*/
struct sigcontext {
struct __sigset sc_mask; /* signal mask to restore */
- int sc_onstack; /* sigstack state to restore */
- int sc_gs; /* machine state (struct trapframe) */
- int sc_fs;
- int sc_es;
- int sc_ds;
- int sc_edi;
- int sc_esi;
- int sc_ebp;
- int sc_isp;
- int sc_ebx;
- int sc_edx;
- int sc_ecx;
- int sc_eax;
- int sc_trapno;
- int sc_err;
- int sc_eip;
- int sc_cs;
- int sc_efl;
- int sc_esp;
- int sc_ss;
- int sc_len; /* sizeof(mcontext_t) */
+ long sc_onstack; /* sigstack state to restore */
+ long sc_r15; /* machine state (struct trapframe) */
+ long sc_r14;
+ long sc_r13;
+ long sc_r12;
+ long sc_r11;
+ long sc_r10;
+ long sc_r9;
+ long sc_r8;
+ long sc_rdi;
+ long sc_rsi;
+ long sc_rbp;
+ long sc_rbx;
+ long sc_rdx;
+ long sc_rcx;
+ long sc_rax;
+ long sc_trapno;
+ long sc_err;
+ long sc_rip;
+ long sc_cs;
+ long sc_rflags;
+ long sc_rsp;
+ long sc_ss;
+ long sc_len; /* sizeof(mcontext_t) */
/*
* XXX - See <machine/ucontext.h> and <machine/npx.h> for
* the following fields.
*/
- int sc_fpformat;
- int sc_ownedfp;
- int sc_spare1[1];
- int sc_fpstate[128] __aligned(16);
- int sc_spare2[8];
+ long sc_fpformat;
+ long sc_ownedfp;
+ long sc_spare1[1];
+ long sc_fpstate[128] __aligned(16);
+ long sc_spare2[8];
};
-
-#define sc_sp sc_esp
-#define sc_fp sc_ebp
-#define sc_pc sc_eip
-#define sc_ps sc_efl
-#define sc_eflags sc_efl
-
#endif /* __BSD_VISIBLE */
#endif /* !_MACHINE_SIGNAL_H_ */
diff --git a/sys/amd64/include/smp.h b/sys/amd64/include/smp.h
index 6467365cc8e0..3d8d11734db5 100644
--- a/sys/amd64/include/smp.h
+++ b/sys/amd64/include/smp.h
@@ -13,150 +13,4 @@
#ifndef _MACHINE_SMP_H_
#define _MACHINE_SMP_H_
-#ifdef _KERNEL
-
-#if defined(SMP) && defined(I386_CPU) && !defined(COMPILING_LINT)
-#error SMP not supported with I386_CPU
-#endif
-#if defined(SMP) && !defined(APIC_IO)
-# error APIC_IO required for SMP, add "options APIC_IO" to your config file.
-#endif /* SMP && !APIC_IO */
-#if defined(SMP) && defined(CPU_DISABLE_CMPXCHG) && !defined(COMPILING_LINT)
-#error SMP not supported with CPU_DISABLE_CMPXCHG
-#endif
-
-#if defined(SMP) || defined(APIC_IO)
-
-#ifndef LOCORE
-
-/*
- * For sending values to POST displays.
- * XXX FIXME: where does this really belong, isa.h/isa.c perhaps?
- */
-extern int current_postcode; /** XXX currently in mp_machdep.c */
-#define POSTCODE(X) current_postcode = (X), \
- outb(0x80, current_postcode)
-#define POSTCODE_LO(X) current_postcode &= 0xf0, \
- current_postcode |= ((X) & 0x0f), \
- outb(0x80, current_postcode)
-#define POSTCODE_HI(X) current_postcode &= 0x0f, \
- current_postcode |= (((X) << 4) & 0xf0), \
- outb(0x80, current_postcode)
-
-
-#include <sys/bus.h> /* XXX */
-#include <machine/apic.h>
-#include <machine/frame.h>
-#include <i386/isa/icu.h>
-#include <i386/isa/intr_machdep.h>
-
-/*
- * Interprocessor interrupts for SMP.
- */
-#define IPI_INVLTLB XINVLTLB_OFFSET
-#define IPI_INVLPG XINVLPG_OFFSET
-#define IPI_INVLRNG XINVLRNG_OFFSET
-#define IPI_LAZYPMAP XLAZYPMAP_OFFSET
-#define IPI_RENDEZVOUS XRENDEZVOUS_OFFSET
-#define IPI_AST XCPUAST_OFFSET
-#define IPI_STOP XCPUSTOP_OFFSET
-#define IPI_HARDCLOCK XHARDCLOCK_OFFSET
-#define IPI_STATCLOCK XSTATCLOCK_OFFSET
-
-/* global data in mpboot.s */
-extern int bootMP_size;
-
-/* functions in mpboot.s */
-void bootMP(void);
-
-/* global data in mp_machdep.c */
-extern int bsp_apic_ready;
-extern int mp_naps;
-extern int mp_nbusses;
-extern int mp_napics;
-extern int mp_picmode;
-extern int boot_cpu_id;
-extern vm_offset_t cpu_apic_address;
-extern vm_offset_t io_apic_address[];
-extern u_int32_t cpu_apic_versions[];
-extern u_int32_t *io_apic_versions;
-extern int cpu_num_to_apic_id[];
-extern int io_num_to_apic_id[];
-extern int apic_id_to_logical[];
-#define APIC_INTMAPSIZE 32
-struct apic_intmapinfo {
- int ioapic;
- int int_pin;
- volatile void *apic_address;
- int redirindex;
-};
-extern struct apic_intmapinfo int_to_apicintpin[];
-extern struct pcb stoppcbs[];
-
-/* functions in mp_machdep.c */
-void i386_mp_probe(void);
-u_int mp_bootaddress(u_int);
-u_int isa_apic_mask(u_int);
-int isa_apic_irq(int);
-int pci_apic_irq(int, int, int);
-int apic_irq(int, int);
-int next_apic_irq(int);
-int undirect_isa_irq(int);
-int undirect_pci_irq(int);
-int apic_bus_type(int);
-int apic_src_bus_id(int, int);
-int apic_src_bus_irq(int, int);
-int apic_int_type(int, int);
-int apic_trigger(int, int);
-int apic_polarity(int, int);
-int mp_grab_cpu_hlt(void);
-void assign_apic_irq(int apic, int intpin, int irq);
-void revoke_apic_irq(int irq);
-void bsp_apic_configure(void);
-void init_secondary(void);
-void forward_statclock(void);
-void forwarded_statclock(struct clockframe frame);
-void forward_hardclock(void);
-void forwarded_hardclock(struct clockframe frame);
-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);
-#ifdef APIC_INTR_REORDER
-void set_lapic_isrloc(int, int);
-#endif /* APIC_INTR_REORDER */
-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);
-void smp_masked_invlpg_range(u_int mask, vm_offset_t startva,
- vm_offset_t endva);
-void smp_invltlb(void);
-void smp_masked_invltlb(u_int mask);
-
-/* global data in mpapic.c */
-extern volatile lapic_t lapic;
-extern volatile ioapic_t **ioapic;
-
-/* functions in mpapic.c */
-void apic_dump(char*);
-void apic_initialize(void);
-void imen_dump(void);
-int apic_ipi(int, int, int);
-int selected_apic_ipi(u_int, int, int);
-int io_apic_setup(int);
-void io_apic_setup_intpin(int, int);
-void io_apic_set_id(int, int);
-int io_apic_get_id(int);
-int ext_int_setup(int, int);
-
-void set_apic_timer(int);
-int read_apic_timer(void);
-void u_sleep(int);
-u_int io_apic_read(int, int);
-void io_apic_write(int, int, u_int);
-
-#endif /* !LOCORE */
-#endif /* SMP && !APIC_IO */
-
-#endif /* _KERNEL */
#endif /* _MACHINE_SMP_H_ */
diff --git a/sys/amd64/include/specialreg.h b/sys/amd64/include/specialreg.h
index 1c6ebe103c64..d66238c257bb 100644
--- a/sys/amd64/include/specialreg.h
+++ b/sys/amd64/include/specialreg.h
@@ -75,6 +75,14 @@
#define CR4_XMM 0x00000400 /* enable SIMD/MMX2 to use except 16 */
/*
+ * Bits in AMD64 special registers. EFER is 64 bits wide.
+ */
+#define EFER_SCE 0x000000001 /* System Call Extensions (R/W) */
+#define EFER_LME 0x000000100 /* Long mode enable (R/W) */
+#define EFER_LMA 0x000000400 /* Long mode active (R) */
+#define EFER_NXE 0x000000800 /* PTE No-Execute bit enable (R/W) */
+
+/*
* CPUID instruction features register
*/
#define CPUID_FPU 0x00000001
@@ -132,6 +140,9 @@
#define MSR_PERFCTR0 0x0c1
#define MSR_PERFCTR1 0x0c2
#define MSR_MTRRcap 0x0fe
+#define MSR_SYSENTER_CS 0x174
+#define MSR_SYSENTER_ESP 0x175
+#define MSR_SYSENTER_EIP 0x176
#define MSR_MCG_CAP 0x179
#define MSR_MCG_STATUS 0x17a
#define MSR_MCG_CTL 0x17b
@@ -147,6 +158,7 @@
#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
@@ -176,69 +188,6 @@
#define MTRR_N16K 16
#define MTRR_N4K 64
-/*
- * Cyrix configuration registers, accessible as IO ports.
- */
-#define CCR0 0xc0 /* Configuration control register 0 */
-#define CCR0_NC0 0x01 /* First 64K of each 1M memory region is
- non-cacheable */
-#define CCR0_NC1 0x02 /* 640K-1M region is non-cacheable */
-#define CCR0_A20M 0x04 /* Enables A20M# input pin */
-#define CCR0_KEN 0x08 /* Enables KEN# input pin */
-#define CCR0_FLUSH 0x10 /* Enables FLUSH# input pin */
-#define CCR0_BARB 0x20 /* Flushes internal cache when entering hold
- state */
-#define CCR0_CO 0x40 /* Cache org: 1=direct mapped, 0=2x set
- assoc */
-#define CCR0_SUSPEND 0x80 /* Enables SUSP# and SUSPA# pins */
-
-#define CCR1 0xc1 /* Configuration control register 1 */
-#define CCR1_RPL 0x01 /* Enables RPLSET and RPLVAL# pins */
-#define CCR1_SMI 0x02 /* Enables SMM pins */
-#define CCR1_SMAC 0x04 /* System management memory access */
-#define CCR1_MMAC 0x08 /* Main memory access */
-#define CCR1_NO_LOCK 0x10 /* Negate LOCK# */
-#define CCR1_SM3 0x80 /* SMM address space address region 3 */
-
-#define CCR2 0xc2
-#define CCR2_WB 0x02 /* Enables WB cache interface pins */
-#define CCR2_SADS 0x02 /* Slow ADS */
-#define CCR2_LOCK_NW 0x04 /* LOCK NW Bit */
-#define CCR2_SUSP_HLT 0x08 /* Suspend on HALT */
-#define CCR2_WT1 0x10 /* WT region 1 */
-#define CCR2_WPR1 0x10 /* Write-protect region 1 */
-#define CCR2_BARB 0x20 /* Flushes write-back cache when entering
- hold state. */
-#define CCR2_BWRT 0x40 /* Enables burst write cycles */
-#define CCR2_USE_SUSP 0x80 /* Enables suspend pins */
-
-#define CCR3 0xc3
-#define CCR3_SMILOCK 0x01 /* SMM register lock */
-#define CCR3_NMI 0x02 /* Enables NMI during SMM */
-#define CCR3_LINBRST 0x04 /* Linear address burst cycles */
-#define CCR3_SMMMODE 0x08 /* SMM Mode */
-#define CCR3_MAPEN0 0x10 /* Enables Map0 */
-#define CCR3_MAPEN1 0x20 /* Enables Map1 */
-#define CCR3_MAPEN2 0x40 /* Enables Map2 */
-#define CCR3_MAPEN3 0x80 /* Enables Map3 */
-
-#define CCR4 0xe8
-#define CCR4_IOMASK 0x07
-#define CCR4_MEM 0x08 /* Enables momory bypassing */
-#define CCR4_DTE 0x10 /* Enables directory table entry cache */
-#define CCR4_FASTFPE 0x20 /* Fast FPU exception */
-#define CCR4_CPUID 0x80 /* Enables CPUID instruction */
-
-#define CCR5 0xe9
-#define CCR5_WT_ALLOC 0x01 /* Write-through allocate */
-#define CCR5_SLOP 0x02 /* LOOP instruction slowed down */
-#define CCR5_LBR1 0x10 /* Local bus region 1 */
-#define CCR5_ARREN 0x20 /* Enables ARR region */
-
-#define CCR6 0xea
-
-#define CCR7 0xeb
-
/* Performance Control Register (5x86 only). */
#define PCR0 0x20
#define PCR0_RSTK 0x01 /* Enables return stack */
@@ -347,21 +296,31 @@
#define AMD_WT_ALLOC_PRE 0x20000 /* programmable range enable */
#define AMD_WT_ALLOC_FRE 0x10000 /* fixed (A0000-FFFFF) range enable */
-
-#ifndef LOCORE
-static __inline u_char
-read_cyrix_reg(u_char reg)
-{
- outb(0x22, reg);
- return inb(0x23);
-}
-
-static __inline void
-write_cyrix_reg(u_char reg, u_char data)
-{
- outb(0x22, reg);
- outb(0x23, data);
-}
-#endif
+/* X86-64 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 */
+#define MSR_CSTAR 0xc0000083 /* compat mode SYSCALL target rip */
+#define MSR_SF_MASK 0xc0000084 /* syscall flags mask */
+#define MSR_FSBASE 0xc0000100 /* base address of the %fs "segment" */
+#define MSR_GSBASE 0xc0000101 /* base address of the %gs "segment" */
+#define MSR_KGSBASE 0xc0000102 /* base address of the kernel %gs */
+#define MSR_PERFEVSEL0 0xc0010000
+#define MSR_PERFEVSEL1 0xc0010001
+#define MSR_PERFEVSEL2 0xc0010002
+#define MSR_PERFEVSEL3 0xc0010003
+#undef MSR_PERFCTR0
+#undef MSR_PERFCTR1
+#define MSR_PERFCTR0 0xc0010004
+#define MSR_PERFCTR1 0xc0010005
+#define MSR_PERFCTR2 0xc0010006
+#define MSR_PERFCTR3 0xc0010007
+#define MSR_SYSCFG 0xc0010010
+#define MSR_IORRBASE0 0xc0010016
+#define MSR_IORRMASK0 0xc0010017
+#define MSR_IORRBASE1 0xc0010018
+#define MSR_IORRMASK1 0xc0010019
+#define MSR_TOP_MEM 0xc001001a /* boundary for ram below 4G */
+#define MSR_TOP_MEM2 0xc001001d /* boundary for ram above 4G */
#endif /* !_MACHINE_SPECIALREG_H_ */
diff --git a/sys/amd64/include/sysarch.h b/sys/amd64/include/sysarch.h
index c5574ff8157a..c33f7b836eb3 100644
--- a/sys/amd64/include/sysarch.h
+++ b/sys/amd64/include/sysarch.h
@@ -39,46 +39,4 @@
#ifndef _MACHINE_SYSARCH_H_
#define _MACHINE_SYSARCH_H_
-#define I386_GET_LDT 0
-#define I386_SET_LDT 1
- /* I386_IOPL */
-#define I386_GET_IOPERM 3
-#define I386_SET_IOPERM 4
- /* xxxxx */
-#define I386_VM86 6
-
-struct i386_ldt_args {
- unsigned int start;
- union descriptor *descs;
- unsigned int num;
-};
-
-struct i386_ioperm_args {
- unsigned int start;
- unsigned int length;
- int enable;
-};
-
-struct i386_vm86_args {
- int sub_op; /* sub-operation to perform */
- char *sub_args; /* args */
-};
-
-#ifndef _KERNEL
-#include <sys/cdefs.h>
-
-union descriptor;
-struct dbreg;
-
-__BEGIN_DECLS
-int i386_get_ldt(int, union descriptor *, int);
-int i386_set_ldt(int, union descriptor *, int);
-int i386_get_ioperm(unsigned int, unsigned int *, int *);
-int i386_set_ioperm(unsigned int, unsigned int, int);
-int i386_vm86(int, void *);
-int i386_set_watch(int, unsigned int, int, int, struct dbreg *);
-int i386_clr_watch(int, struct dbreg *);
-__END_DECLS
-#endif
-
#endif /* !_MACHINE_SYSARCH_H_ */
diff --git a/sys/amd64/include/tss.h b/sys/amd64/include/tss.h
index fb2e7a59491d..aa60ba0c0362 100644
--- a/sys/amd64/include/tss.h
+++ b/sys/amd64/include/tss.h
@@ -41,37 +41,35 @@
#define _MACHINE_TSS_H_ 1
/*
- * Intel 386 Context Data Type
+ * amd64 Context Data Type
+ *
+ * The alignment is pretty messed up here due to reuse of the original 32 bit
+ * fields. It might be worth trying to set the tss on a +4 byte offset to
+ * make the 64 bit fields aligned in practice.
*/
-
-struct i386tss {
- int tss_link; /* actually 16 bits: top 16 bits must be zero */
- int tss_esp0; /* kernel stack pointer privilege level 0 */
- int tss_ss0; /* actually 16 bits: top 16 bits must be zero */
- int tss_esp1; /* kernel stack pointer privilege level 1 */
- int tss_ss1; /* actually 16 bits: top 16 bits must be zero */
- int tss_esp2; /* kernel stack pointer privilege level 2 */
- int tss_ss2; /* actually 16 bits: top 16 bits must be zero */
- int tss_cr3; /* page table directory */
- int tss_eip; /* program counter */
- int tss_eflags; /* program status longword */
- int tss_eax;
- int tss_ecx;
- int tss_edx;
- int tss_ebx;
- int tss_esp; /* user stack pointer */
- int tss_ebp; /* user frame pointer */
- int tss_esi;
- int tss_edi;
- int tss_es; /* actually 16 bits: top 16 bits must be zero */
- int tss_cs; /* actually 16 bits: top 16 bits must be zero */
- int tss_ss; /* actually 16 bits: top 16 bits must be zero */
- int tss_ds; /* actually 16 bits: top 16 bits must be zero */
- int tss_fs; /* actually 16 bits: top 16 bits must be zero */
- int tss_gs; /* actually 16 bits: top 16 bits must be zero */
- int tss_ldt; /* actually 16 bits: top 16 bits must be zero */
- int tss_ioopt; /* options & io offset bitmap: currently zero */
- /* XXX unimplemented .. i/o permission bitmap */
+struct amd64tss {
+ u_int32_t tss_rsvd0;
+ u_int64_t tss_rsp0 __packed; /* kernel stack pointer ring 0 */
+ u_int64_t tss_rsp1 __packed; /* kernel stack pointer ring 1 */
+ u_int64_t tss_rsp2 __packed; /* kernel stack pointer ring 2 */
+ u_int32_t tss_rsvd1;
+ u_int32_t tss_rsvd2;
+ u_int32_t tss_rsvd3;
+ u_int64_t tss_ist1 __packed; /* Interrupt stack table 1 */
+ u_int64_t tss_ist2 __packed; /* Interrupt stack table 2 */
+ u_int64_t tss_ist3 __packed; /* Interrupt stack table 3 */
+ u_int64_t tss_ist4 __packed; /* Interrupt stack table 4 */
+ u_int64_t tss_ist5 __packed; /* Interrupt stack table 5 */
+ u_int64_t tss_ist6 __packed; /* Interrupt stack table 6 */
+ u_int64_t tss_ist7 __packed; /* Interrupt stack table 7 */
+ u_int32_t tss_rsvd4;
+ u_int32_t tss_rsvd5;
+ u_int16_t tss_rsvd6;
+ u_int16_t tss_iobase; /* io bitmap offset */
};
+#ifdef _KERNEL
+extern struct amd64tss common_tss;
+#endif
+
#endif /* _MACHINE_TSS_H_ */
diff --git a/sys/amd64/include/ucontext.h b/sys/amd64/include/ucontext.h
index ec3e0eefaea2..1938707021cf 100644
--- a/sys/amd64/include/ucontext.h
+++ b/sys/amd64/include/ucontext.h
@@ -37,69 +37,44 @@ typedef struct __mcontext {
* sigcontext. So that we can support sigcontext
* and ucontext_t at the same time.
*/
- int mc_onstack; /* XXX - sigcontext compat. */
- int mc_gs; /* machine state (struct trapframe) */
- int mc_fs;
- int mc_es;
- int mc_ds;
- int mc_edi;
- int mc_esi;
- int mc_ebp;
- int mc_isp;
- int mc_ebx;
- int mc_edx;
- int mc_ecx;
- int mc_eax;
- int mc_trapno;
- int mc_err;
- int mc_eip;
- int mc_cs;
- int mc_eflags;
- int mc_esp;
- int mc_ss;
+ register_t mc_onstack; /* XXX - sigcontext compat. */
+ register_t mc_r15; /* machine state (struct trapframe) */
+ register_t mc_r14;
+ register_t mc_r13;
+ register_t mc_r12;
+ register_t mc_r11;
+ register_t mc_r10;
+ register_t mc_r9;
+ register_t mc_r8;
+ register_t mc_rdi;
+ register_t mc_rsi;
+ register_t mc_rbp;
+ register_t mc_rbx;
+ register_t mc_rdx;
+ register_t mc_rcx;
+ register_t mc_rax;
+ register_t mc_trapno;
+ register_t mc_err;
+ register_t mc_rip;
+ register_t mc_cs;
+ register_t mc_rflags;
+ register_t mc_rsp;
+ register_t mc_ss;
- int mc_len; /* sizeof(mcontext_t) */
+ long mc_len; /* sizeof(mcontext_t) */
#define _MC_FPFMT_NODEV 0x10000 /* device not present or configured */
-#define _MC_FPFMT_387 0x10001
#define _MC_FPFMT_XMM 0x10002
- int mc_fpformat;
+ long mc_fpformat;
#define _MC_FPOWNED_NONE 0x20000 /* FP state not used */
#define _MC_FPOWNED_FPU 0x20001 /* FP state came from FPU */
#define _MC_FPOWNED_PCB 0x20002 /* FP state came from PCB */
- int mc_ownedfp;
- int mc_spare1[1]; /* align next field to 16 bytes */
+ long mc_ownedfp;
+ long mc_spare1[1]; /* align next field to 16 bytes */
/*
* See <machine/npx.h> for the internals of mc_fpstate[].
*/
- int mc_fpstate[128] __aligned(16);
- int mc_spare2[8];
+ long mc_fpstate[128] __aligned(16);
+ long mc_spare2[8];
} mcontext_t;
-#if defined(_KERNEL) && defined(COMPAT_FREEBSD4)
-struct mcontext4 {
- int mc_onstack; /* XXX - sigcontext compat. */
- int mc_gs; /* machine state (struct trapframe) */
- int mc_fs;
- int mc_es;
- int mc_ds;
- int mc_edi;
- int mc_esi;
- int mc_ebp;
- int mc_isp;
- int mc_ebx;
- int mc_edx;
- int mc_ecx;
- int mc_eax;
- int mc_trapno;
- int mc_err;
- int mc_eip;
- int mc_cs;
- int mc_eflags;
- int mc_esp; /* machine state */
- int mc_ss;
- int mc_fpregs[28]; /* env87 + fpacc87 + u_long */
- int __spare__[17];
-};
-#endif
-
#endif /* !_MACHINE_UCONTEXT_H_ */
diff --git a/sys/amd64/include/vmparam.h b/sys/amd64/include/vmparam.h
index bb7c7e13bc1f..0e9697d2680b 100644
--- a/sys/amd64/include/vmparam.h
+++ b/sys/amd64/include/vmparam.h
@@ -44,11 +44,9 @@
#define _MACHINE_VMPARAM_H_ 1
/*
- * Machine dependent constants for 386.
+ * Machine dependent constants for AMD64.
*/
-#define VM_PROT_READ_IS_EXEC /* if you can read -- then you can exec */
-
/*
* Virtual memory related constants, all in bytes
*/
@@ -69,8 +67,6 @@
#define SGROWSIZ (128UL*1024) /* amount to grow stack */
#endif
-#define USRTEXT (1*PAGE_SIZE) /* base of user text XXX bogus */
-
/*
* The time for a process to be blocked before being very swappable.
* This is a number of seconds which the system takes as being a non-trivial
@@ -90,23 +86,20 @@
* messy at times, but hey, we'll do anything to save a page :-)
*/
-#define VM_MAX_KERNEL_ADDRESS VADDR(KPTDI+NKPDE-1, NPTEPG-1)
-#define VM_MIN_KERNEL_ADDRESS VADDR(PTDPTDI, PTDPTDI)
-
-#define KERNBASE VADDR(KPTDI, 0)
+#define VM_MAX_KERNEL_ADDRESS VADDR(0, 0, KPTDI+NKPDE-1, NPTEPG-1)
+#define VM_MIN_KERNEL_ADDRESS VADDR(0, 0, PTDPTDI, PTDPTDI)
-#define KPT_MAX_ADDRESS VADDR(PTDPTDI, KPTDI+NKPT)
-#define KPT_MIN_ADDRESS VADDR(PTDPTDI, KPTDI)
+#define KERNBASE VADDR(0, 0, KPTDI, 0)
-#define UPT_MAX_ADDRESS VADDR(PTDPTDI, PTDPTDI)
-#define UPT_MIN_ADDRESS VADDR(PTDPTDI, 0)
+#define UPT_MAX_ADDRESS VADDR(0, 0, PTDPTDI, PTDPTDI)
+#define UPT_MIN_ADDRESS VADDR(0, 0, PTDPTDI, 0)
-#define VM_MAXUSER_ADDRESS VADDR(PTDPTDI, 0)
+#define VM_MAXUSER_ADDRESS UPT_MIN_ADDRESS
#define USRSTACK VM_MAXUSER_ADDRESS
-#define VM_MAX_ADDRESS VADDR(PTDPTDI, PTDPTDI)
-#define VM_MIN_ADDRESS ((vm_offset_t)0)
+#define VM_MAX_ADDRESS UPT_MAX_ADDRESS
+#define VM_MIN_ADDRESS (0)
/* virtual sizes (bytes) for various kernel submaps */
#ifndef VM_KMEM_SIZE
diff --git a/sys/amd64/isa/clock.c b/sys/amd64/isa/clock.c
index 9e6c489637e3..dbf974e1c3b0 100644
--- a/sys/amd64/isa/clock.c
+++ b/sys/amd64/isa/clock.c
@@ -50,7 +50,6 @@
#include "opt_clock.h"
#include "opt_isa.h"
-#include "opt_mca.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -67,39 +66,20 @@
#include <sys/power.h>
#include <machine/clock.h>
-#include <machine/cputypes.h>
#include <machine/frame.h>
#include <machine/md_var.h>
#include <machine/psl.h>
-#ifdef APIC_IO
-#include <machine/segments.h>
-#endif
-#if defined(SMP) || defined(APIC_IO)
-#include <machine/smp.h>
-#endif /* SMP || APIC_IO */
#include <machine/specialreg.h>
-#include <i386/isa/icu.h>
-#include <i386/isa/isa.h>
+#include <amd64/isa/icu.h>
+#include <amd64/isa/isa.h>
#include <isa/rtc.h>
#ifdef DEV_ISA
#include <isa/isavar.h>
#endif
-#include <i386/isa/timerreg.h>
-
-#include <i386/isa/intr_machdep.h>
+#include <amd64/isa/timerreg.h>
-#ifdef DEV_MCA
-#include <i386/bios/mca_machdep.h>
-#endif
-
-#ifdef APIC_IO
-#include <i386/isa/intr_machdep.h>
-/* The interrupt triggered by the 8254 (timer) chip */
-int apic_8254_intr;
-static u_long read_intr_count(int vec);
-static void setup_8254_mixed_mode(void);
-#endif
+#include <amd64/isa/intr_machdep.h>
/*
* 32-bit time_t's can't reach leap years before 1904 or after 2036, so we
@@ -195,10 +175,6 @@ clkintr(struct clockframe frame)
mtx_unlock_spin(&clock_lock);
}
timer_func(&frame);
-#ifdef SMP
- if (timer_func == hardclock)
- forward_hardclock();
-#endif
switch (timer0_state) {
case RELEASED:
@@ -209,9 +185,6 @@ clkintr(struct clockframe frame)
>= hardclock_max_count) {
timer0_prescaler_count -= hardclock_max_count;
hardclock(&frame);
-#ifdef SMP
- forward_hardclock();
-#endif
}
break;
@@ -244,17 +217,9 @@ clkintr(struct clockframe frame)
timer_func = hardclock;
timer0_state = RELEASED;
hardclock(&frame);
-#ifdef SMP
- forward_hardclock();
-#endif
}
break;
}
-#ifdef DEV_MCA
- /* Reset clock interrupt by asserting bit 7 of port 0x61 */
- if (MCA_system)
- outb(0x61, inb(0x61) | 0x80);
-#endif
}
/*
@@ -376,9 +341,6 @@ rtcintr(struct clockframe frame)
}
if (pscnt == psdiv)
statclock(&frame);
-#ifdef SMP
- forward_statclock();
-#endif
}
}
@@ -673,43 +635,6 @@ set_timer_freq(u_int freq, int intr_freq)
mtx_unlock_spin(&clock_lock);
}
-static void
-i8254_restore(void)
-{
-
- mtx_lock_spin(&clock_lock);
- outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
- outb(TIMER_CNTR0, timer0_max_count & 0xff);
- outb(TIMER_CNTR0, timer0_max_count >> 8);
- mtx_unlock_spin(&clock_lock);
-}
-
-static void
-rtc_restore(void)
-{
-
- /* Restore all of the RTC's "status" (actually, control) registers. */
- /* XXX locking is needed for RTC access. */
- writertc(RTC_STATUSB, RTCSB_24HR);
- writertc(RTC_STATUSA, rtc_statusa);
- writertc(RTC_STATUSB, rtc_statusb);
-}
-
-/*
- * Restore all the timers non-atomically (XXX: should be atomically).
- *
- * This function is called from pmtimer_resume() to restore all the timers.
- * This should not be necessary, but there are broken laptops that do not
- * restore all the timers on resume.
- */
-void
-timer_restore(void)
-{
-
- i8254_restore(); /* restore timer_freq and hz */
- rtc_restore(); /* reenable RTC interrupts */
-}
-
/*
* Initialize 8254 timer 0 early so that it can be used in DELAY().
* XXX initialization of other timers is unintentionally left blank.
@@ -902,10 +827,6 @@ void
cpu_initclocks()
{
int diag;
-#ifdef APIC_IO
- int apic_8254_trial;
- void *clkdesc;
-#endif /* APIC_IO */
register_t crit;
if (statclock_disable) {
@@ -923,32 +844,6 @@ cpu_initclocks()
}
/* Finish initializing 8253 timer 0. */
-#ifdef APIC_IO
-
- apic_8254_intr = isa_apic_irq(0);
- apic_8254_trial = 0;
- if (apic_8254_intr >= 0 ) {
- if (apic_int_type(0, 0) == 3)
- apic_8254_trial = 1;
- } else {
- /* look for ExtInt on pin 0 */
- if (apic_int_type(0, 0) == 3) {
- apic_8254_intr = apic_irq(0, 0);
- setup_8254_mixed_mode();
- } else
- panic("APIC_IO: Cannot route 8254 interrupt to CPU");
- }
-
- inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, NULL,
- INTR_TYPE_CLK | INTR_FAST, &clkdesc);
- crit = intr_disable();
- mtx_lock_spin(&icu_lock);
- INTREN(1 << apic_8254_intr);
- mtx_unlock_spin(&icu_lock);
- intr_restore(crit);
-
-#else /* APIC_IO */
-
/*
* XXX Check the priority of this interrupt handler. I
* couldn't find anything suitable in the BSD/OS code (grog,
@@ -962,8 +857,6 @@ cpu_initclocks()
mtx_unlock_spin(&icu_lock);
intr_restore(crit);
-#endif /* APIC_IO */
-
/* Initialize RTC. */
writertc(RTC_STATUSA, rtc_statusa);
writertc(RTC_STATUSB, RTCSB_24HR);
@@ -975,118 +868,17 @@ cpu_initclocks()
if (diag != 0)
printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS);
-#ifdef APIC_IO
- if (isa_apic_irq(8) != 8)
- panic("APIC RTC != 8");
-#endif /* APIC_IO */
-
inthand_add("rtc", 8, (driver_intr_t *)rtcintr, NULL,
INTR_TYPE_CLK | INTR_FAST, NULL);
crit = intr_disable();
mtx_lock_spin(&icu_lock);
-#ifdef APIC_IO
- INTREN(APIC_IRQ8);
-#else
INTREN(IRQ8);
-#endif /* APIC_IO */
mtx_unlock_spin(&icu_lock);
intr_restore(crit);
writertc(RTC_STATUSB, rtc_statusb);
-
-#ifdef APIC_IO
- if (apic_8254_trial) {
-
- printf("APIC_IO: Testing 8254 interrupt delivery\n");
- while (read_intr_count(8) < 6)
- ; /* nothing */
- if (read_intr_count(apic_8254_intr) < 3) {
- /*
- * The MP table is broken.
- * The 8254 was not connected to the specified pin
- * on the IO APIC.
- * Workaround: Limited variant of mixed mode.
- */
-
- crit = intr_disable();
- mtx_lock_spin(&icu_lock);
- INTRDIS(1 << apic_8254_intr);
- mtx_unlock_spin(&icu_lock);
- intr_restore(crit);
- inthand_remove(clkdesc);
- printf("APIC_IO: Broken MP table detected: "
- "8254 is not connected to "
- "IOAPIC #%d intpin %d\n",
- int_to_apicintpin[apic_8254_intr].ioapic,
- int_to_apicintpin[apic_8254_intr].int_pin);
- /*
- * Revoke current ISA IRQ 0 assignment and
- * configure a fallback interrupt routing from
- * the 8254 Timer via the 8259 PIC to the
- * an ExtInt interrupt line on IOAPIC #0 intpin 0.
- * We reuse the low level interrupt handler number.
- */
- if (apic_irq(0, 0) < 0) {
- revoke_apic_irq(apic_8254_intr);
- assign_apic_irq(0, 0, apic_8254_intr);
- }
- apic_8254_intr = apic_irq(0, 0);
- setup_8254_mixed_mode();
- inthand_add("clk", apic_8254_intr,
- (driver_intr_t *)clkintr, NULL,
- INTR_TYPE_CLK | INTR_FAST, NULL);
- crit = intr_disable();
- mtx_lock_spin(&icu_lock);
- INTREN(1 << apic_8254_intr);
- mtx_unlock_spin(&icu_lock);
- intr_restore(crit);
- }
-
- }
- if (apic_int_type(0, 0) != 3 ||
- int_to_apicintpin[apic_8254_intr].ioapic != 0 ||
- int_to_apicintpin[apic_8254_intr].int_pin != 0)
- printf("APIC_IO: routing 8254 via IOAPIC #%d intpin %d\n",
- int_to_apicintpin[apic_8254_intr].ioapic,
- int_to_apicintpin[apic_8254_intr].int_pin);
- else
- printf("APIC_IO: "
- "routing 8254 via 8259 and IOAPIC #0 intpin 0\n");
-#endif
-
-}
-
-#ifdef APIC_IO
-static u_long
-read_intr_count(int vec)
-{
- u_long *up;
- up = intr_countp[vec];
- if (up)
- return *up;
- return 0UL;
-}
-
-static void
-setup_8254_mixed_mode()
-{
- /*
- * Allow 8254 timer to INTerrupt 8259:
- * re-initialize master 8259:
- * reset; prog 4 bytes, single ICU, edge triggered
- */
- outb(IO_ICU1, 0x13);
- outb(IO_ICU1 + 1, NRSVIDT); /* start vector (unused) */
- outb(IO_ICU1 + 1, 0x00); /* ignore slave */
- outb(IO_ICU1 + 1, 0x03); /* auto EOI, 8086 */
- outb(IO_ICU1 + 1, 0xfe); /* unmask INT0 */
-
- /* program IO APIC for type 3 INT on INT0 */
- if (ext_int_setup(0, 0) < 0)
- panic("8254 redirect via APIC pin0 impossible!");
}
-#endif
void
cpu_startprofclock(void)
@@ -1135,9 +927,9 @@ i8254_get_timecount(struct timecounter *tc)
{
u_int count;
u_int high, low;
- u_int eflags;
+ u_long rflags;
- eflags = read_eflags();
+ rflags = read_rflags();
mtx_lock_spin(&clock_lock);
/* Select timer0 and latch counter value. */
@@ -1148,14 +940,8 @@ i8254_get_timecount(struct timecounter *tc)
count = timer0_max_count - ((high << 8) | low);
if (count < i8254_lastcount ||
(!i8254_ticked && (clkintr_pending ||
- ((count < 20 || (!(eflags & PSL_I) && count < timer0_max_count / 2u)) &&
-#ifdef APIC_IO
-#define lapic_irr1 ((volatile u_int *)&lapic)[0x210 / 4] /* XXX XXX */
- /* XXX this assumes that apic_8254_intr is < 24. */
- (lapic_irr1 & (1 << apic_8254_intr))))
-#else
+ ((count < 20 || (!(rflags & PSL_I) && count < timer0_max_count / 2u)) &&
(inb(IO_ICU1) & 1)))
-#endif
)) {
i8254_ticked = 1;
i8254_offset += timer0_max_count;
diff --git a/sys/amd64/isa/icu.h b/sys/amd64/isa/icu.h
index 82e084f467b7..06b8955f7269 100644
--- a/sys/amd64/isa/icu.h
+++ b/sys/amd64/isa/icu.h
@@ -58,47 +58,14 @@
void INTREN(u_int);
void INTRDIS(u_int);
-#ifdef APIC_IO
-extern unsigned apic_imen; /* APIC interrupt mask enable */
-#else
extern unsigned imen; /* interrupt mask enable */
-#endif
#endif /* LOCORE */
-#ifdef APIC_IO
-/*
- * Note: The APIC uses different values for IRQxxx.
- * Unfortunately many drivers use the 8259 values as indexes
- * into tables, etc. The APIC equivilants are kept as APIC_IRQxxx.
- * The 8259 versions have to be used in SMP for legacy operation
- * of the drivers.
- */
-#endif /* APIC_IO */
-
/*
* Interrupt enable bits - in normal order of priority (which we change)
*/
-#ifdef PC98
-#define IRQ0 0x0001
-#define IRQ1 0x0002
-#define IRQ2 0x0004
-#define IRQ3 0x0008
-#define IRQ4 0x0010
-#define IRQ5 0x0020
-#define IRQ6 0x0040
-#define IRQ7 0x0080
-#define IRQ_SLAVE 0x0080
-#define IRQ8 0x0100
-#define IRQ9 0x0200
-#define IRQ10 0x0400
-#define IRQ11 0x0800
-#define IRQ12 0x1000
-#define IRQ13 0x2000
-#define IRQ14 0x4000
-#define IRQ15 0x8000
-#else
#define IRQ0 0x0001 /* highest priority - timer */
#define IRQ1 0x0002
#define IRQ_SLAVE 0x0004
@@ -116,36 +83,69 @@ extern unsigned imen; /* interrupt mask enable */
#define IRQ5 0x0020
#define IRQ6 0x0040
#define IRQ7 0x0080 /* lowest - parallel printer */
-#endif
-/*
- * Interrupt Control offset into Interrupt descriptor table (IDT)
- */
-#define ICU_OFFSET 32 /* 0-31 are processor exceptions */
+/* Initialization control word 1. Written to even address. */
+#define ICW1_IC4 0x01 /* ICW4 present */
+#define ICW1_SNGL 0x02 /* 1 = single, 0 = cascaded */
+#define ICW1_ADI 0x04 /* 1 = 4, 0 = 8 byte vectors */
+#define ICW1_LTIM 0x08 /* 1 = level trigger, 0 = edge */
+#define ICW1_RESET 0x10 /* must be 1 */
+/* 0x20 - 0x80 - in 8080/8085 mode only */
-#ifdef PC98
-#define ICU_IMR_OFFSET 2
-#define ICU_SLAVEID 7
-#else
-#define ICU_IMR_OFFSET 1
-#define ICU_SLAVEID 2
-#endif
-#define ICU_EOI 0x20
+/* Initialization control word 2. Written to the odd address. */
+/* No definitions, it is the base vector of the IDT for 8086 mode */
+
+/* Initialization control word 3. Written to the odd address. */
+/* For a master PIC, bitfield indicating a slave 8259 on given input */
+/* For slave, lower 3 bits are the slave's ID binary id on master */
-#ifdef APIC_IO
+/* Initialization control word 4. Written to the odd address. */
+#define ICW4_8086 0x01 /* 1 = 8086, 0 = 8080 */
+#define ICW4_AEOI 0x02 /* 1 = Auto EOI */
+#define ICW4_MS 0x04 /* 1 = buffered master, 0 = slave */
+#define ICW4_BUF 0x08 /* 1 = enable buffer mode */
+#define ICW4_SFNM 0x10 /* 1 = special fully nested mode */
-/* 32-47: ISA IRQ0-IRQ15, 48-63: IO APIC IRQ16-IRQ31 */
-#define ICU_LEN 32
-#define HWI_MASK 0xffffffff /* bits for h/w interrupts */
-#define NHWI 32
+/* Operation control words. Written after initialization. */
-#else
+/* Operation control word type 1 */
+/*
+ * No definitions. Written to the odd address. Bitmask for interrupts.
+ * 1 = disabled.
+ */
+/* Operation control word type 2. Bit 3 (0x08) must be zero. Even address. */
+#define OCW2_L0 0x01 /* Level */
+#define OCW2_L1 0x02
+#define OCW2_L2 0x04
+/* 0x08 must be 0 to select OCW2 vs OCW3 */
+/* 0x10 must be 0 to select OCW2 vs ICW1 */
+#define OCW2_EOI 0x20 /* 1 = EOI */
+#define OCW2_SL 0x40 /* EOI mode */
+#define OCW2_R 0x80 /* EOI mode */
+
+/* Operation control word type 3. Bit 3 (0x08) must be set. Even address. */
+#define OCW3_RIS 0x01
+#define OCW3_RR 0x02
+#define OCW3_P 0x04
+/* 0x08 must be 1 to select OCW3 vs OCW2 */
+#define OCW3_SEL 0x08 /* must be 1 */
+/* 0x10 must be 0 to select OCW3 vs ICW1 */
+#define OCW3_SMM 0x20 /* special mode mask */
+#define OCW3_ESMM 0x40 /* enable SMM */
+
+/*
+ * Interrupt Control offset into Interrupt descriptor table (IDT)
+ */
+#define ICU_OFFSET 32 /* 0-31 are processor exceptions */
#define ICU_LEN 16 /* 32-47 are ISA interrupts */
#define HWI_MASK 0xffff /* bits for h/w interrupts */
#define NHWI 16
-#endif /* APIC_IO */
+#define ICU_IMR_OFFSET 1
+#define ICU_SLAVEID 2
+#define ICU_EOI (OCW2_EOI) /* non-specific EOI */
+#define ICU_SETPRI (OCW2_R | OCW2_SL) /* set rotation priority */
#define INTRCNT_COUNT (1 + ICU_LEN + 2 * ICU_LEN)
diff --git a/sys/amd64/isa/icu_ipl.S b/sys/amd64/isa/icu_ipl.S
index 8cedbb4f4a6c..ad883fea34a3 100644
--- a/sys/amd64/isa/icu_ipl.S
+++ b/sys/amd64/isa/icu_ipl.S
@@ -48,7 +48,7 @@ imen: .long HWI_MASK
SUPERALIGN_TEXT
ENTRY(INTREN)
- movl 4(%esp), %eax
+ movq %rdi, %rax
movl %eax, %ecx
notl %eax
andl %eax, imen
@@ -65,7 +65,7 @@ ENTRY(INTREN)
ret
ENTRY(INTRDIS)
- movl 4(%esp), %eax
+ movq %rdi, %rax
movl %eax, %ecx
orl %eax, imen
movl imen, %eax
diff --git a/sys/amd64/isa/icu_ipl.s b/sys/amd64/isa/icu_ipl.s
index 8cedbb4f4a6c..ad883fea34a3 100644
--- a/sys/amd64/isa/icu_ipl.s
+++ b/sys/amd64/isa/icu_ipl.s
@@ -48,7 +48,7 @@ imen: .long HWI_MASK
SUPERALIGN_TEXT
ENTRY(INTREN)
- movl 4(%esp), %eax
+ movq %rdi, %rax
movl %eax, %ecx
notl %eax
andl %eax, imen
@@ -65,7 +65,7 @@ ENTRY(INTREN)
ret
ENTRY(INTRDIS)
- movl 4(%esp), %eax
+ movq %rdi, %rax
movl %eax, %ecx
orl %eax, imen
movl imen, %eax
diff --git a/sys/amd64/isa/icu_vector.S b/sys/amd64/isa/icu_vector.S
index 1023635b2ae0..c9fea1a0106f 100644
--- a/sys/amd64/isa/icu_vector.S
+++ b/sys/amd64/isa/icu_vector.S
@@ -4,151 +4,57 @@
*/
#define IRQ_BIT(irq_num) (1 << ((irq_num) % 8))
-#define IRQ_LBIT(irq_num) (1 << (irq_num))
#define IRQ_BYTE(irq_num) ((irq_num) >> 3)
-#ifdef AUTO_EOI_1
-
-#define ENABLE_ICU1 /* use auto-EOI to reduce i/o */
-#define OUTB_ICU1
-
-#else
-
#define ENABLE_ICU1 \
movb $ICU_EOI,%al ; /* as soon as possible send EOI ... */ \
- OUTB_ICU1 /* ... to clear in service bit */
-
-#define OUTB_ICU1 \
- outb %al,$IO_ICU1
-
-#endif
-
-#ifdef AUTO_EOI_2
-/*
- * The data sheet says no auto-EOI on slave, but it sometimes works.
- */
-#define ENABLE_ICU1_AND_2 ENABLE_ICU1
-
-#else
+ outb %al,$IO_ICU1 /* ... to clear in service bit */
#define ENABLE_ICU1_AND_2 \
movb $ICU_EOI,%al ; /* as above */ \
outb %al,$IO_ICU2 ; /* but do second icu first ... */ \
- OUTB_ICU1 /* ... then first icu (if !AUTO_EOI_1) */
-
-#endif
-
-#define PUSH_FRAME \
- pushl $0 ; /* dummy error code */ \
- pushl $0 ; /* dummy trap type */ \
- pushal ; /* 8 ints */ \
- pushl %ds ; /* save data and extra segments ... */ \
- pushl %es ; \
- pushl %fs
-
-#define PUSH_DUMMY \
- pushfl ; /* eflags */ \
- pushl %cs ; /* cs */ \
- pushl 12(%esp) ; /* original caller eip */ \
- pushl $0 ; /* dummy error code */ \
- pushl $0 ; /* dummy trap type */ \
- subl $11*4,%esp
+ outb %al,$IO_ICU1 /* ... then first icu */
-#define POP_FRAME \
- popl %fs ; \
- popl %es ; \
- popl %ds ; \
- popal ; \
- addl $4+4,%esp
-
-#define POP_DUMMY \
- addl $16*4,%esp
-
-#define MASK_IRQ(icu, irq_num) \
- movb imen + IRQ_BYTE(irq_num),%al ; \
- orb $IRQ_BIT(irq_num),%al ; \
- movb %al,imen + IRQ_BYTE(irq_num) ; \
- outb %al,$icu+ICU_IMR_OFFSET
-#define UNMASK_IRQ(icu, irq_num) \
- movb imen + IRQ_BYTE(irq_num),%al ; \
- andb $~IRQ_BIT(irq_num),%al ; \
- movb %al,imen + IRQ_BYTE(irq_num) ; \
- outb %al,$icu+ICU_IMR_OFFSET
/*
* Macros for interrupt interrupt entry, call to handler, and exit.
*/
-#define FAST_INTR(irq_num, vec_name, icu, enable_icus) \
+#define FAST_INTR(irq_num, vec_name, enable_icus) \
.text ; \
SUPERALIGN_TEXT ; \
IDTVEC(vec_name) ; \
- PUSH_FRAME ; \
- mov $KDSEL,%ax ; \
- mov %ax,%ds ; \
- mov %ax,%es ; \
- mov $KPSEL,%ax ; \
- mov %ax,%fs ; \
- FAKE_MCOUNT((12+ACTUALLY_PUSHED)*4(%esp)) ; \
- movl PCPU(CURTHREAD),%ebx ; \
- cmpl $0,TD_CRITNEST(%ebx) ; \
- je 1f ; \
-; \
- movl $1,PCPU(INT_PENDING) ; \
- orl $IRQ_LBIT(irq_num),PCPU(FPENDING) ; \
- MASK_IRQ(icu, irq_num) ; \
- enable_icus ; \
- jmp 10f ; \
-1: ; \
- incl TD_CRITNEST(%ebx) ; \
- incl TD_INTR_NESTING_LEVEL(%ebx) ; \
- pushl intr_unit + (irq_num) * 4 ; \
- call *intr_handler + (irq_num) * 4 ; \
- addl $4,%esp ; \
- enable_icus ; \
+ subq $TF_RIP,%rsp ; /* skip dummy tf_err and tf_trapno */ \
+ 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) ; \
+ FAKE_MCOUNT((12)*4(%rsp)) ; \
+ call critical_enter ; \
+ movq PCPU(CURTHREAD),%rbx ; \
+ incl TD_INTR_NESTING_LEVEL(%rbx) ; \
+ movq intr_unit + (irq_num) * 8, %rdi ; \
+ call *intr_handler + (irq_num) * 8 ; /* do the work ASAP */ \
+ enable_icus ; /* (re)enable ASAP (helps edge trigger?) */ \
incl cnt+V_INTR ; /* book-keeping can wait */ \
- movl intr_countp + (irq_num) * 4,%eax ; \
- incl (%eax) ; \
- decl TD_CRITNEST(%ebx) ; \
- cmpl $0,PCPU(INT_PENDING) ; \
- je 2f ; \
-; \
- call i386_unpend ; \
-2: ; \
- decl TD_INTR_NESTING_LEVEL(%ebx) ; \
-10: ; \
+ movq intr_countp + (irq_num) * 8,%rax ; \
+ incq (%rax) ; \
+ decl TD_INTR_NESTING_LEVEL(%rbx) ; \
+ call critical_exit ; \
MEXITCOUNT ; \
jmp doreti
-/*
- * Restart a fast interrupt that was held up by a critical section.
- * This routine is called from unpend(). unpend() ensures we are
- * in a critical section and deals with the interrupt nesting level
- * for us. If we previously masked the irq, we have to unmask it.
- *
- * We have a choice. We can regenerate the irq using the 'int'
- * instruction or we can create a dummy frame and call the interrupt
- * handler directly. I've chosen to use the dummy-frame method.
- */
-#define FAST_UNPEND(irq_num, vec_name, icu) \
- .text ; \
- SUPERALIGN_TEXT ; \
-IDTVEC(vec_name) ; \
-; \
- pushl %ebp ; \
- movl %esp, %ebp ; \
- PUSH_DUMMY ; \
- pushl intr_unit + (irq_num) * 4 ; \
- call *intr_handler + (irq_num) * 4 ; /* do the work ASAP */ \
- addl $4, %esp ; \
- incl cnt+V_INTR ; /* book-keeping can wait */ \
- movl intr_countp + (irq_num) * 4,%eax ; \
- incl (%eax) ; \
- UNMASK_IRQ(icu, irq_num) ; \
- POP_DUMMY ; \
- popl %ebp ; \
- ret
-
/*
* Slow, threaded interrupts.
*
@@ -162,57 +68,56 @@ IDTVEC(vec_name) ; \
.text ; \
SUPERALIGN_TEXT ; \
IDTVEC(vec_name) ; \
- PUSH_FRAME ; \
- mov $KDSEL,%ax ; /* load kernel ds, es and fs */ \
- mov %ax,%ds ; \
- mov %ax,%es ; \
- mov $KPSEL,%ax ; \
- mov %ax,%fs ; \
-; \
+ subq $TF_RIP,%rsp ; /* skip dummy tf_err and tf_trapno */ \
+ 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) ; \
maybe_extra_ipending ; \
- MASK_IRQ(icu, irq_num) ; \
+ movb imen + IRQ_BYTE(irq_num),%al ; \
+ orb $IRQ_BIT(irq_num),%al ; \
+ movb %al,imen + IRQ_BYTE(irq_num) ; \
+ outb %al,$icu+ICU_IMR_OFFSET ; \
enable_icus ; \
-; \
- movl PCPU(CURTHREAD),%ebx ; \
- cmpl $0,TD_CRITNEST(%ebx) ; \
- je 1f ; \
- movl $1,PCPU(INT_PENDING); \
- orl $IRQ_LBIT(irq_num),PCPU(IPENDING) ; \
- jmp 10f ; \
-1: ; \
- incl TD_INTR_NESTING_LEVEL(%ebx) ; \
-; \
- FAKE_MCOUNT(13*4(%esp)) ; /* XXX late to avoid double count */ \
- cmpl $0,PCPU(INT_PENDING) ; \
- je 9f ; \
- call i386_unpend ; \
-9: ; \
- pushl $irq_num; /* pass the IRQ */ \
+ movq PCPU(CURTHREAD),%rbx ; \
+ incl TD_INTR_NESTING_LEVEL(%rbx) ; \
+ FAKE_MCOUNT(13*4(%rsp)) ; /* XXX late to avoid double count */ \
+ movq $irq_num, %rdi; /* pass the IRQ */ \
call sched_ithd ; \
- addl $4, %esp ; /* discard the parameter */ \
-; \
- decl TD_INTR_NESTING_LEVEL(%ebx) ; \
-10: ; \
+ decl TD_INTR_NESTING_LEVEL(%rbx) ; \
MEXITCOUNT ; \
+ /* We could usually avoid the following jmp by inlining some of */ \
+ /* doreti, but it's probably better to use less cache. */ \
jmp doreti
MCOUNT_LABEL(bintr)
- FAST_INTR(0,fastintr0, IO_ICU1, ENABLE_ICU1)
- FAST_INTR(1,fastintr1, IO_ICU1, ENABLE_ICU1)
- FAST_INTR(2,fastintr2, IO_ICU1, ENABLE_ICU1)
- FAST_INTR(3,fastintr3, IO_ICU1, ENABLE_ICU1)
- FAST_INTR(4,fastintr4, IO_ICU1, ENABLE_ICU1)
- FAST_INTR(5,fastintr5, IO_ICU1, ENABLE_ICU1)
- FAST_INTR(6,fastintr6, IO_ICU1, ENABLE_ICU1)
- FAST_INTR(7,fastintr7, IO_ICU1, ENABLE_ICU1)
- FAST_INTR(8,fastintr8, IO_ICU2, ENABLE_ICU1_AND_2)
- FAST_INTR(9,fastintr9, IO_ICU2, ENABLE_ICU1_AND_2)
- FAST_INTR(10,fastintr10, IO_ICU2, ENABLE_ICU1_AND_2)
- FAST_INTR(11,fastintr11, IO_ICU2, ENABLE_ICU1_AND_2)
- FAST_INTR(12,fastintr12, IO_ICU2, ENABLE_ICU1_AND_2)
- FAST_INTR(13,fastintr13, IO_ICU2, ENABLE_ICU1_AND_2)
- FAST_INTR(14,fastintr14, IO_ICU2, ENABLE_ICU1_AND_2)
- FAST_INTR(15,fastintr15, IO_ICU2, ENABLE_ICU1_AND_2)
+ FAST_INTR(0,fastintr0, ENABLE_ICU1)
+ FAST_INTR(1,fastintr1, ENABLE_ICU1)
+ FAST_INTR(2,fastintr2, ENABLE_ICU1)
+ FAST_INTR(3,fastintr3, ENABLE_ICU1)
+ FAST_INTR(4,fastintr4, ENABLE_ICU1)
+ FAST_INTR(5,fastintr5, ENABLE_ICU1)
+ FAST_INTR(6,fastintr6, ENABLE_ICU1)
+ FAST_INTR(7,fastintr7, ENABLE_ICU1)
+ FAST_INTR(8,fastintr8, ENABLE_ICU1_AND_2)
+ FAST_INTR(9,fastintr9, ENABLE_ICU1_AND_2)
+ FAST_INTR(10,fastintr10, ENABLE_ICU1_AND_2)
+ FAST_INTR(11,fastintr11, ENABLE_ICU1_AND_2)
+ FAST_INTR(12,fastintr12, ENABLE_ICU1_AND_2)
+ FAST_INTR(13,fastintr13, ENABLE_ICU1_AND_2)
+ FAST_INTR(14,fastintr14, ENABLE_ICU1_AND_2)
+ FAST_INTR(15,fastintr15, ENABLE_ICU1_AND_2)
#define CLKINTR_PENDING movl $1,CNAME(clkintr_pending)
/* Threaded interrupts */
@@ -233,21 +138,5 @@ MCOUNT_LABEL(bintr)
INTR(14,intr14, IO_ICU2, ENABLE_ICU1_AND_2,)
INTR(15,intr15, IO_ICU2, ENABLE_ICU1_AND_2,)
- FAST_UNPEND(0,fastunpend0, IO_ICU1)
- FAST_UNPEND(1,fastunpend1, IO_ICU1)
- FAST_UNPEND(2,fastunpend2, IO_ICU1)
- FAST_UNPEND(3,fastunpend3, IO_ICU1)
- FAST_UNPEND(4,fastunpend4, IO_ICU1)
- FAST_UNPEND(5,fastunpend5, IO_ICU1)
- FAST_UNPEND(6,fastunpend6, IO_ICU1)
- FAST_UNPEND(7,fastunpend7, IO_ICU1)
- FAST_UNPEND(8,fastunpend8, IO_ICU2)
- FAST_UNPEND(9,fastunpend9, IO_ICU2)
- FAST_UNPEND(10,fastunpend10, IO_ICU2)
- FAST_UNPEND(11,fastunpend11, IO_ICU2)
- FAST_UNPEND(12,fastunpend12, IO_ICU2)
- FAST_UNPEND(13,fastunpend13, IO_ICU2)
- FAST_UNPEND(14,fastunpend14, IO_ICU2)
- FAST_UNPEND(15,fastunpend15, IO_ICU2)
MCOUNT_LABEL(eintr)
diff --git a/sys/amd64/isa/icu_vector.s b/sys/amd64/isa/icu_vector.s
index 1023635b2ae0..c9fea1a0106f 100644
--- a/sys/amd64/isa/icu_vector.s
+++ b/sys/amd64/isa/icu_vector.s
@@ -4,151 +4,57 @@
*/
#define IRQ_BIT(irq_num) (1 << ((irq_num) % 8))
-#define IRQ_LBIT(irq_num) (1 << (irq_num))
#define IRQ_BYTE(irq_num) ((irq_num) >> 3)
-#ifdef AUTO_EOI_1
-
-#define ENABLE_ICU1 /* use auto-EOI to reduce i/o */
-#define OUTB_ICU1
-
-#else
-
#define ENABLE_ICU1 \
movb $ICU_EOI,%al ; /* as soon as possible send EOI ... */ \
- OUTB_ICU1 /* ... to clear in service bit */
-
-#define OUTB_ICU1 \
- outb %al,$IO_ICU1
-
-#endif
-
-#ifdef AUTO_EOI_2
-/*
- * The data sheet says no auto-EOI on slave, but it sometimes works.
- */
-#define ENABLE_ICU1_AND_2 ENABLE_ICU1
-
-#else
+ outb %al,$IO_ICU1 /* ... to clear in service bit */
#define ENABLE_ICU1_AND_2 \
movb $ICU_EOI,%al ; /* as above */ \
outb %al,$IO_ICU2 ; /* but do second icu first ... */ \
- OUTB_ICU1 /* ... then first icu (if !AUTO_EOI_1) */
-
-#endif
-
-#define PUSH_FRAME \
- pushl $0 ; /* dummy error code */ \
- pushl $0 ; /* dummy trap type */ \
- pushal ; /* 8 ints */ \
- pushl %ds ; /* save data and extra segments ... */ \
- pushl %es ; \
- pushl %fs
-
-#define PUSH_DUMMY \
- pushfl ; /* eflags */ \
- pushl %cs ; /* cs */ \
- pushl 12(%esp) ; /* original caller eip */ \
- pushl $0 ; /* dummy error code */ \
- pushl $0 ; /* dummy trap type */ \
- subl $11*4,%esp
+ outb %al,$IO_ICU1 /* ... then first icu */
-#define POP_FRAME \
- popl %fs ; \
- popl %es ; \
- popl %ds ; \
- popal ; \
- addl $4+4,%esp
-
-#define POP_DUMMY \
- addl $16*4,%esp
-
-#define MASK_IRQ(icu, irq_num) \
- movb imen + IRQ_BYTE(irq_num),%al ; \
- orb $IRQ_BIT(irq_num),%al ; \
- movb %al,imen + IRQ_BYTE(irq_num) ; \
- outb %al,$icu+ICU_IMR_OFFSET
-#define UNMASK_IRQ(icu, irq_num) \
- movb imen + IRQ_BYTE(irq_num),%al ; \
- andb $~IRQ_BIT(irq_num),%al ; \
- movb %al,imen + IRQ_BYTE(irq_num) ; \
- outb %al,$icu+ICU_IMR_OFFSET
/*
* Macros for interrupt interrupt entry, call to handler, and exit.
*/
-#define FAST_INTR(irq_num, vec_name, icu, enable_icus) \
+#define FAST_INTR(irq_num, vec_name, enable_icus) \
.text ; \
SUPERALIGN_TEXT ; \
IDTVEC(vec_name) ; \
- PUSH_FRAME ; \
- mov $KDSEL,%ax ; \
- mov %ax,%ds ; \
- mov %ax,%es ; \
- mov $KPSEL,%ax ; \
- mov %ax,%fs ; \
- FAKE_MCOUNT((12+ACTUALLY_PUSHED)*4(%esp)) ; \
- movl PCPU(CURTHREAD),%ebx ; \
- cmpl $0,TD_CRITNEST(%ebx) ; \
- je 1f ; \
-; \
- movl $1,PCPU(INT_PENDING) ; \
- orl $IRQ_LBIT(irq_num),PCPU(FPENDING) ; \
- MASK_IRQ(icu, irq_num) ; \
- enable_icus ; \
- jmp 10f ; \
-1: ; \
- incl TD_CRITNEST(%ebx) ; \
- incl TD_INTR_NESTING_LEVEL(%ebx) ; \
- pushl intr_unit + (irq_num) * 4 ; \
- call *intr_handler + (irq_num) * 4 ; \
- addl $4,%esp ; \
- enable_icus ; \
+ subq $TF_RIP,%rsp ; /* skip dummy tf_err and tf_trapno */ \
+ 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) ; \
+ FAKE_MCOUNT((12)*4(%rsp)) ; \
+ call critical_enter ; \
+ movq PCPU(CURTHREAD),%rbx ; \
+ incl TD_INTR_NESTING_LEVEL(%rbx) ; \
+ movq intr_unit + (irq_num) * 8, %rdi ; \
+ call *intr_handler + (irq_num) * 8 ; /* do the work ASAP */ \
+ enable_icus ; /* (re)enable ASAP (helps edge trigger?) */ \
incl cnt+V_INTR ; /* book-keeping can wait */ \
- movl intr_countp + (irq_num) * 4,%eax ; \
- incl (%eax) ; \
- decl TD_CRITNEST(%ebx) ; \
- cmpl $0,PCPU(INT_PENDING) ; \
- je 2f ; \
-; \
- call i386_unpend ; \
-2: ; \
- decl TD_INTR_NESTING_LEVEL(%ebx) ; \
-10: ; \
+ movq intr_countp + (irq_num) * 8,%rax ; \
+ incq (%rax) ; \
+ decl TD_INTR_NESTING_LEVEL(%rbx) ; \
+ call critical_exit ; \
MEXITCOUNT ; \
jmp doreti
-/*
- * Restart a fast interrupt that was held up by a critical section.
- * This routine is called from unpend(). unpend() ensures we are
- * in a critical section and deals with the interrupt nesting level
- * for us. If we previously masked the irq, we have to unmask it.
- *
- * We have a choice. We can regenerate the irq using the 'int'
- * instruction or we can create a dummy frame and call the interrupt
- * handler directly. I've chosen to use the dummy-frame method.
- */
-#define FAST_UNPEND(irq_num, vec_name, icu) \
- .text ; \
- SUPERALIGN_TEXT ; \
-IDTVEC(vec_name) ; \
-; \
- pushl %ebp ; \
- movl %esp, %ebp ; \
- PUSH_DUMMY ; \
- pushl intr_unit + (irq_num) * 4 ; \
- call *intr_handler + (irq_num) * 4 ; /* do the work ASAP */ \
- addl $4, %esp ; \
- incl cnt+V_INTR ; /* book-keeping can wait */ \
- movl intr_countp + (irq_num) * 4,%eax ; \
- incl (%eax) ; \
- UNMASK_IRQ(icu, irq_num) ; \
- POP_DUMMY ; \
- popl %ebp ; \
- ret
-
/*
* Slow, threaded interrupts.
*
@@ -162,57 +68,56 @@ IDTVEC(vec_name) ; \
.text ; \
SUPERALIGN_TEXT ; \
IDTVEC(vec_name) ; \
- PUSH_FRAME ; \
- mov $KDSEL,%ax ; /* load kernel ds, es and fs */ \
- mov %ax,%ds ; \
- mov %ax,%es ; \
- mov $KPSEL,%ax ; \
- mov %ax,%fs ; \
-; \
+ subq $TF_RIP,%rsp ; /* skip dummy tf_err and tf_trapno */ \
+ 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) ; \
maybe_extra_ipending ; \
- MASK_IRQ(icu, irq_num) ; \
+ movb imen + IRQ_BYTE(irq_num),%al ; \
+ orb $IRQ_BIT(irq_num),%al ; \
+ movb %al,imen + IRQ_BYTE(irq_num) ; \
+ outb %al,$icu+ICU_IMR_OFFSET ; \
enable_icus ; \
-; \
- movl PCPU(CURTHREAD),%ebx ; \
- cmpl $0,TD_CRITNEST(%ebx) ; \
- je 1f ; \
- movl $1,PCPU(INT_PENDING); \
- orl $IRQ_LBIT(irq_num),PCPU(IPENDING) ; \
- jmp 10f ; \
-1: ; \
- incl TD_INTR_NESTING_LEVEL(%ebx) ; \
-; \
- FAKE_MCOUNT(13*4(%esp)) ; /* XXX late to avoid double count */ \
- cmpl $0,PCPU(INT_PENDING) ; \
- je 9f ; \
- call i386_unpend ; \
-9: ; \
- pushl $irq_num; /* pass the IRQ */ \
+ movq PCPU(CURTHREAD),%rbx ; \
+ incl TD_INTR_NESTING_LEVEL(%rbx) ; \
+ FAKE_MCOUNT(13*4(%rsp)) ; /* XXX late to avoid double count */ \
+ movq $irq_num, %rdi; /* pass the IRQ */ \
call sched_ithd ; \
- addl $4, %esp ; /* discard the parameter */ \
-; \
- decl TD_INTR_NESTING_LEVEL(%ebx) ; \
-10: ; \
+ decl TD_INTR_NESTING_LEVEL(%rbx) ; \
MEXITCOUNT ; \
+ /* We could usually avoid the following jmp by inlining some of */ \
+ /* doreti, but it's probably better to use less cache. */ \
jmp doreti
MCOUNT_LABEL(bintr)
- FAST_INTR(0,fastintr0, IO_ICU1, ENABLE_ICU1)
- FAST_INTR(1,fastintr1, IO_ICU1, ENABLE_ICU1)
- FAST_INTR(2,fastintr2, IO_ICU1, ENABLE_ICU1)
- FAST_INTR(3,fastintr3, IO_ICU1, ENABLE_ICU1)
- FAST_INTR(4,fastintr4, IO_ICU1, ENABLE_ICU1)
- FAST_INTR(5,fastintr5, IO_ICU1, ENABLE_ICU1)
- FAST_INTR(6,fastintr6, IO_ICU1, ENABLE_ICU1)
- FAST_INTR(7,fastintr7, IO_ICU1, ENABLE_ICU1)
- FAST_INTR(8,fastintr8, IO_ICU2, ENABLE_ICU1_AND_2)
- FAST_INTR(9,fastintr9, IO_ICU2, ENABLE_ICU1_AND_2)
- FAST_INTR(10,fastintr10, IO_ICU2, ENABLE_ICU1_AND_2)
- FAST_INTR(11,fastintr11, IO_ICU2, ENABLE_ICU1_AND_2)
- FAST_INTR(12,fastintr12, IO_ICU2, ENABLE_ICU1_AND_2)
- FAST_INTR(13,fastintr13, IO_ICU2, ENABLE_ICU1_AND_2)
- FAST_INTR(14,fastintr14, IO_ICU2, ENABLE_ICU1_AND_2)
- FAST_INTR(15,fastintr15, IO_ICU2, ENABLE_ICU1_AND_2)
+ FAST_INTR(0,fastintr0, ENABLE_ICU1)
+ FAST_INTR(1,fastintr1, ENABLE_ICU1)
+ FAST_INTR(2,fastintr2, ENABLE_ICU1)
+ FAST_INTR(3,fastintr3, ENABLE_ICU1)
+ FAST_INTR(4,fastintr4, ENABLE_ICU1)
+ FAST_INTR(5,fastintr5, ENABLE_ICU1)
+ FAST_INTR(6,fastintr6, ENABLE_ICU1)
+ FAST_INTR(7,fastintr7, ENABLE_ICU1)
+ FAST_INTR(8,fastintr8, ENABLE_ICU1_AND_2)
+ FAST_INTR(9,fastintr9, ENABLE_ICU1_AND_2)
+ FAST_INTR(10,fastintr10, ENABLE_ICU1_AND_2)
+ FAST_INTR(11,fastintr11, ENABLE_ICU1_AND_2)
+ FAST_INTR(12,fastintr12, ENABLE_ICU1_AND_2)
+ FAST_INTR(13,fastintr13, ENABLE_ICU1_AND_2)
+ FAST_INTR(14,fastintr14, ENABLE_ICU1_AND_2)
+ FAST_INTR(15,fastintr15, ENABLE_ICU1_AND_2)
#define CLKINTR_PENDING movl $1,CNAME(clkintr_pending)
/* Threaded interrupts */
@@ -233,21 +138,5 @@ MCOUNT_LABEL(bintr)
INTR(14,intr14, IO_ICU2, ENABLE_ICU1_AND_2,)
INTR(15,intr15, IO_ICU2, ENABLE_ICU1_AND_2,)
- FAST_UNPEND(0,fastunpend0, IO_ICU1)
- FAST_UNPEND(1,fastunpend1, IO_ICU1)
- FAST_UNPEND(2,fastunpend2, IO_ICU1)
- FAST_UNPEND(3,fastunpend3, IO_ICU1)
- FAST_UNPEND(4,fastunpend4, IO_ICU1)
- FAST_UNPEND(5,fastunpend5, IO_ICU1)
- FAST_UNPEND(6,fastunpend6, IO_ICU1)
- FAST_UNPEND(7,fastunpend7, IO_ICU1)
- FAST_UNPEND(8,fastunpend8, IO_ICU2)
- FAST_UNPEND(9,fastunpend9, IO_ICU2)
- FAST_UNPEND(10,fastunpend10, IO_ICU2)
- FAST_UNPEND(11,fastunpend11, IO_ICU2)
- FAST_UNPEND(12,fastunpend12, IO_ICU2)
- FAST_UNPEND(13,fastunpend13, IO_ICU2)
- FAST_UNPEND(14,fastunpend14, IO_ICU2)
- FAST_UNPEND(15,fastunpend15, IO_ICU2)
MCOUNT_LABEL(eintr)
diff --git a/sys/amd64/isa/intr_machdep.c b/sys/amd64/isa/intr_machdep.c
index 67b5deafd587..c1482285ab1f 100644
--- a/sys/amd64/isa/intr_machdep.c
+++ b/sys/amd64/isa/intr_machdep.c
@@ -37,9 +37,7 @@
* $FreeBSD$
*/
-#include "opt_auto_eoi.h"
#include "opt_isa.h"
-#include "opt_mca.h"
#include <sys/param.h>
#include <sys/bus.h>
@@ -59,32 +57,14 @@
#include <machine/md_var.h>
#include <machine/segments.h>
-#if defined(APIC_IO)
-#include <machine/smptests.h> /** FAST_HI */
-#include <machine/smp.h>
-#include <machine/resource.h>
-#endif /* APIC_IO */
-#ifdef PC98
-#include <pc98/pc98/pc98.h>
-#include <pc98/pc98/pc98_machdep.h>
-#include <pc98/pc98/epsonio.h>
-#else
-#include <i386/isa/isa.h>
-#endif
-#include <i386/isa/icu.h>
+#include <amd64/isa/isa.h>
+#include <amd64/isa/icu.h>
#ifdef DEV_ISA
#include <isa/isavar.h>
#endif
-#include <i386/isa/intr_machdep.h>
+#include <amd64/isa/intr_machdep.h>
#include <sys/interrupt.h>
-#ifdef APIC_IO
-#include <machine/clock.h>
-#endif
-
-#ifdef DEV_MCA
-#include <i386/bios/mca_machdep.h>
-#endif
/*
* Per-interrupt data.
@@ -105,37 +85,6 @@ static inthand_t *fastintr[ICU_LEN] = {
IDTVEC(fastintr10), IDTVEC(fastintr11),
IDTVEC(fastintr12), IDTVEC(fastintr13),
IDTVEC(fastintr14), IDTVEC(fastintr15),
-#if defined(APIC_IO)
- IDTVEC(fastintr16), IDTVEC(fastintr17),
- IDTVEC(fastintr18), IDTVEC(fastintr19),
- IDTVEC(fastintr20), IDTVEC(fastintr21),
- IDTVEC(fastintr22), IDTVEC(fastintr23),
- IDTVEC(fastintr24), IDTVEC(fastintr25),
- IDTVEC(fastintr26), IDTVEC(fastintr27),
- IDTVEC(fastintr28), IDTVEC(fastintr29),
- IDTVEC(fastintr30), IDTVEC(fastintr31),
-#endif /* APIC_IO */
-};
-
-static unpendhand_t *fastunpend[ICU_LEN] = {
- IDTVEC(fastunpend0), IDTVEC(fastunpend1),
- IDTVEC(fastunpend2), IDTVEC(fastunpend3),
- IDTVEC(fastunpend4), IDTVEC(fastunpend5),
- IDTVEC(fastunpend6), IDTVEC(fastunpend7),
- IDTVEC(fastunpend8), IDTVEC(fastunpend9),
- IDTVEC(fastunpend10), IDTVEC(fastunpend11),
- IDTVEC(fastunpend12), IDTVEC(fastunpend13),
- IDTVEC(fastunpend14), IDTVEC(fastunpend15),
-#if defined(APIC_IO)
- IDTVEC(fastunpend16), IDTVEC(fastunpend17),
- IDTVEC(fastunpend18), IDTVEC(fastunpend19),
- IDTVEC(fastunpend20), IDTVEC(fastunpend21),
- IDTVEC(fastunpend22), IDTVEC(fastunpend23),
- IDTVEC(fastunpend24), IDTVEC(fastunpend25),
- IDTVEC(fastunpend26), IDTVEC(fastunpend27),
- IDTVEC(fastunpend28), IDTVEC(fastunpend29),
- IDTVEC(fastunpend30), IDTVEC(fastunpend31),
-#endif /* APIC_IO */
};
static inthand_t *slowintr[ICU_LEN] = {
@@ -143,12 +92,6 @@ static inthand_t *slowintr[ICU_LEN] = {
IDTVEC(intr4), IDTVEC(intr5), IDTVEC(intr6), IDTVEC(intr7),
IDTVEC(intr8), IDTVEC(intr9), IDTVEC(intr10), IDTVEC(intr11),
IDTVEC(intr12), IDTVEC(intr13), IDTVEC(intr14), IDTVEC(intr15),
-#if defined(APIC_IO)
- IDTVEC(intr16), IDTVEC(intr17), IDTVEC(intr18), IDTVEC(intr19),
- IDTVEC(intr20), IDTVEC(intr21), IDTVEC(intr22), IDTVEC(intr23),
- IDTVEC(intr24), IDTVEC(intr25), IDTVEC(intr26), IDTVEC(intr27),
- IDTVEC(intr28), IDTVEC(intr29), IDTVEC(intr30), IDTVEC(intr31),
-#endif /* APIC_IO */
};
static driver_intr_t isa_strayintr;
@@ -158,16 +101,11 @@ static void ithread_enable(int vector);
static void ithread_disable(int vector);
static void init_i8259(void);
-#ifdef PC98
-#define NMI_PARITY 0x04
-#define NMI_EPARITY 0x02
-#else
#define NMI_PARITY (1 << 7)
#define NMI_IOCHAN (1 << 6)
#define ENMI_WATCHDOG (1 << 7)
#define ENMI_BUSTIMER (1 << 6)
#define ENMI_IOSTATUS (1 << 5)
-#endif
#ifdef DEV_ISA
/*
@@ -189,27 +127,12 @@ atpic_probe(device_t dev)
}
/*
- * In the APIC_IO case we might be granted IRQ 2, as this is typically
- * consumed by chaining between the two PIC components. If we're using
- * the APIC, however, this may not be the case, and as such we should
- * free the resource. (XXX untested)
- *
* The generic ISA attachment code will handle allocating any other resources
* that we don't explicitly claim here.
*/
static int
atpic_attach(device_t dev)
{
-#ifdef APIC_IO
- int rid;
- struct resource *res;
-
- /* try to allocate our IRQ and then free it */
- rid = 0;
- res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 0);
- if (res != NULL)
- bus_release_resource(dev, SYS_RES_IRQ, rid, res);
-#endif
return(0);
}
@@ -245,30 +168,9 @@ isa_nmi(cd)
int cd;
{
int retval = 0;
-#ifdef PC98
- int port = inb(0x33);
-
- log(LOG_CRIT, "NMI PC98 port = %x\n", port);
- if (epson_machine_id == 0x20)
- epson_outb(0xc16, epson_inb(0xc16) | 0x1);
- if (port & NMI_PARITY) {
- log(LOG_CRIT, "BASE RAM parity error, likely hardware failure.");
- retval = 1;
- } else if (port & NMI_EPARITY) {
- log(LOG_CRIT, "EXTENDED RAM parity error, likely hardware failure.");
- retval = 1;
- } else {
- log(LOG_CRIT, "\nNMI Resume ??\n");
- }
-#else /* IBM-PC */
int isa_port = inb(0x61);
- int eisa_port = inb(0x461);
- log(LOG_CRIT, "NMI ISA %x, EISA %x\n", isa_port, eisa_port);
-#ifdef DEV_MCA
- if (MCA_system && mca_bus_nmi())
- return(0);
-#endif
+ log(LOG_CRIT, "NMI ISA STATUS 0x%02x", isa_port);
if (isa_port & NMI_PARITY) {
log(LOG_CRIT, "RAM parity error, likely hardware failure.");
@@ -280,30 +182,7 @@ isa_nmi(cd)
retval = 1;
}
- /*
- * On a real EISA machine, this will never happen. However it can
- * happen on ISA machines which implement XT style floating point
- * error handling (very rare). Save them from a meaningless panic.
- */
- if (eisa_port == 0xff)
- return(retval);
-
- if (eisa_port & ENMI_WATCHDOG) {
- log(LOG_CRIT, "EISA watchdog timer expired, likely hardware failure.");
- retval = 1;
- }
-
- if (eisa_port & ENMI_BUSTIMER) {
- log(LOG_CRIT, "EISA bus timeout, likely hardware failure.");
- retval = 1;
- }
-
- if (eisa_port & ENMI_IOSTATUS) {
- log(LOG_CRIT, "EISA I/O port status error.");
- retval = 1;
- }
-#endif
- return(retval);
+ return (retval);
}
/*
@@ -352,72 +231,56 @@ isa_defaultirq()
static void init_i8259()
{
-#ifdef DEV_MCA
- if (MCA_system)
- outb(IO_ICU1, 0x19); /* reset; program device, four bytes */
- else
-#endif
- outb(IO_ICU1, 0x11); /* reset; program device, four bytes */
+ outb(IO_ICU1, ICW1_RESET | ICW1_IC4); /* reset; program device, four bytes */
outb(IO_ICU1+ICU_IMR_OFFSET, NRSVIDT); /* starting at this vector index */
- outb(IO_ICU1+ICU_IMR_OFFSET, IRQ_SLAVE); /* slave on line 7 */
-#ifdef PC98
-#ifdef AUTO_EOI_1
- outb(IO_ICU1+ICU_IMR_OFFSET, 0x1f); /* (master) auto EOI, 8086 mode */
-#else
- outb(IO_ICU1+ICU_IMR_OFFSET, 0x1d); /* (master) 8086 mode */
-#endif
-#else /* IBM-PC */
-#ifdef AUTO_EOI_1
- outb(IO_ICU1+ICU_IMR_OFFSET, 2 | 1); /* auto EOI, 8086 mode */
-#else
- outb(IO_ICU1+ICU_IMR_OFFSET, 1); /* 8086 mode */
-#endif
-#endif /* PC98 */
- outb(IO_ICU1+ICU_IMR_OFFSET, 0xff); /* leave interrupts masked */
- outb(IO_ICU1, 0x0a); /* default to IRR on read */
-#ifndef PC98
- outb(IO_ICU1, 0xc0 | (3 - 1)); /* pri order 3-7, 0-2 (com2 first) */
-#endif /* !PC98 */
-
-#ifdef DEV_MCA
- if (MCA_system)
- outb(IO_ICU2, 0x19); /* reset; program device, four bytes */
- else
-#endif
- outb(IO_ICU2, 0x11); /* reset; program device, four bytes */
+ outb(IO_ICU1+ICU_IMR_OFFSET, IRQ_SLAVE);/* slave on line 2 */
+ outb(IO_ICU1+ICU_IMR_OFFSET, ICW4_8086);/* 8086 mode */
+ outb(IO_ICU1+ICU_IMR_OFFSET, 0xff); /* leave interrupts masked */
+ outb(IO_ICU1, OCW3_SEL | OCW3_RIS); /* default to IRR on read */
+ outb(IO_ICU1, ICU_SETPRI | 0x2);/* pri order 3-7, 0-2 (com2 first) */
+
+ outb(IO_ICU2, ICW1_RESET | ICW1_IC4); /* reset; program device, four bytes */
outb(IO_ICU2+ICU_IMR_OFFSET, NRSVIDT+8); /* staring at this vector index */
- outb(IO_ICU2+ICU_IMR_OFFSET, ICU_SLAVEID); /* my slave id is 7 */
-#ifdef PC98
- outb(IO_ICU2+ICU_IMR_OFFSET,9); /* 8086 mode */
-#else /* IBM-PC */
-#ifdef AUTO_EOI_2
- outb(IO_ICU2+ICU_IMR_OFFSET, 2 | 1); /* auto EOI, 8086 mode */
-#else
- outb(IO_ICU2+ICU_IMR_OFFSET,1); /* 8086 mode */
-#endif
-#endif /* PC98 */
- outb(IO_ICU2+ICU_IMR_OFFSET, 0xff); /* leave interrupts masked */
- outb(IO_ICU2, 0x0a); /* default to IRR on read */
+ outb(IO_ICU2+ICU_IMR_OFFSET, ICU_SLAVEID); /* my slave id is 2 */
+ outb(IO_ICU2+ICU_IMR_OFFSET, ICW4_8086); /* 8086 mode */
+ outb(IO_ICU2+ICU_IMR_OFFSET, 0xff); /* leave interrupts masked */
+ outb(IO_ICU2, OCW3_SEL | OCW3_RIS); /* default to IRR on read */
}
/*
* Caught a stray interrupt, notify
*/
+static int isaglitch7;
+static int isaglitch15;
+
static void
isa_strayintr(vcookiep)
void *vcookiep;
{
int intr = (void **)vcookiep - &intr_unit[0];
-
- /*
- * XXX TODO print a different message for #7 if it is for a
- * glitch. Glitches can be distinguished from real #7's by
- * testing that the in-service bit is _not_ set. The test
- * must be done before sending an EOI so it can't be done if
- * we are using AUTO_EOI_1.
- */
+ int isr;
+
+ /* Determine if it is a stray interrupt or simply a glitch */
+ if (intr == 7) {
+ outb(IO_ICU1, OCW3_SEL); /* select IS register */
+ isr = inb(IO_ICU1);
+ outb(IO_ICU1, OCW3_SEL | OCW3_RIS); /* reselect IIR */
+ if ((isr & 0x80) == 0) {
+ isaglitch7++;
+ return;
+ }
+ }
+ if (intr == 15) {
+ outb(IO_ICU2, OCW3_SEL); /* select IS register */
+ isr = inb(IO_ICU2);
+ outb(IO_ICU2, OCW3_SEL | OCW3_RIS); /* reselect IIR */
+ if ((isr & 0x80) == 0) {
+ isaglitch15++;
+ return;
+ }
+ }
if (intrcnt[1 + intr] <= 5)
log(LOG_ERR, "stray irq %d\n", intr);
if (intrcnt[1 + intr] == 5)
@@ -498,18 +361,9 @@ found:
int
icu_setup(int intr, driver_intr_t *handler, void *arg, int flags)
{
-#ifdef FAST_HI
- int select; /* the select register is 8 bits */
- int vector;
- u_int32_t value; /* the window register is 32 bits */
-#endif /* FAST_HI */
register_t crit;
-#if defined(APIC_IO)
- if ((u_int)intr >= ICU_LEN) /* no 8259 SLAVE to ignore */
-#else
if ((u_int)intr >= ICU_LEN || intr == ICU_SLAVEID)
-#endif /* APIC_IO */
return (EINVAL);
#if 0
if (intr_handler[intr] != isa_strayintr)
@@ -520,35 +374,9 @@ icu_setup(int intr, driver_intr_t *handler, void *arg, int flags)
mtx_lock_spin(&icu_lock);
intr_handler[intr] = handler;
intr_unit[intr] = arg;
-#ifdef FAST_HI
- if (flags & INTR_FAST) {
- vector = TPR_FAST_INTS + intr;
- setidt(vector, fastintr[intr],
- SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
- }
- else {
- vector = TPR_SLOW_INTS + intr;
- setidt(vector, slowintr[intr],
- SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
- }
-#ifdef APIC_INTR_REORDER
- set_lapic_isrloc(intr, vector);
-#endif
- /*
- * Reprogram the vector in the IO APIC.
- */
- if (int_to_apicintpin[intr].ioapic >= 0) {
- select = int_to_apicintpin[intr].redirindex;
- value = io_apic_read(int_to_apicintpin[intr].ioapic,
- select) & ~IOART_INTVEC;
- io_apic_write(int_to_apicintpin[intr].ioapic,
- select, value | vector);
- }
-#else
setidt(ICU_OFFSET + intr,
flags & INTR_FAST ? fastintr[intr] : slowintr[intr],
- SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
-#endif /* FAST_HI */
+ SDT_SYSIGT, SEL_KPL, 0);
INTREN(1 << intr);
mtx_unlock_spin(&icu_lock);
intr_restore(crit);
@@ -576,17 +404,7 @@ icu_unset(intr, handler)
intr_countp[intr] = &intrcnt[1 + intr];
intr_handler[intr] = isa_strayintr;
intr_unit[intr] = &intr_unit[intr];
-#ifdef FAST_HI_XXX
- /* XXX how do I re-create dvp here? */
- setidt(flags & INTR_FAST ? TPR_FAST_INTS + intr : TPR_SLOW_INTS + intr,
- slowintr[intr], SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
-#else /* FAST_HI */
-#ifdef APIC_INTR_REORDER
- set_lapic_isrloc(intr, ICU_OFFSET + intr);
-#endif
- setidt(ICU_OFFSET + intr, slowintr[intr], SDT_SYS386IGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
-#endif /* FAST_HI */
+ setidt(ICU_OFFSET + intr, slowintr[intr], SDT_SYSIGT, SEL_KPL, 0);
mtx_unlock_spin(&icu_lock);
intr_restore(crit);
return (0);
@@ -703,10 +521,3 @@ inthand_remove(void *cookie)
return (ithread_remove_handler(cookie));
}
-
-void
-call_fast_unpend(int irq)
-{
- fastunpend[irq]();
-}
-
diff --git a/sys/amd64/isa/intr_machdep.h b/sys/amd64/isa/intr_machdep.h
index 4cfecb5d24d6..26f500e32ba9 100644
--- a/sys/amd64/isa/intr_machdep.h
+++ b/sys/amd64/isa/intr_machdep.h
@@ -42,97 +42,6 @@
#ifdef _KERNEL
-#if defined(SMP) || defined(APIC_IO)
-/*
- * XXX FIXME: rethink location for all IPI vectors.
- */
-
-/*
- APIC TPR priority vector levels:
-
- 0xff (255) +-------------+
- | | 15 (IPIs: Xspuriousint)
- 0xf0 (240) +-------------+
- | | 14
- 0xe0 (224) +-------------+
- | | 13
- 0xd0 (208) +-------------+
- | | 12
- 0xc0 (192) +-------------+
- | | 11
- 0xb0 (176) +-------------+
- | | 10 (IPIs: Xcpustop)
- 0xa0 (160) +-------------+
- | | 9 (IPIs: Xinvltlb)
- 0x90 (144) +-------------+
- | | 8 (linux/BSD syscall, IGNORE FAST HW INTS)
- 0x80 (128) +-------------+
- | | 7 (FAST_INTR 16-23)
- 0x70 (112) +-------------+
- | | 6 (FAST_INTR 0-15)
- 0x60 (96) +-------------+
- | | 5 (IGNORE HW INTS)
- 0x50 (80) +-------------+
- | | 4 (2nd IO APIC)
- 0x40 (64) +------+------+
- | | | 3 (upper APIC hardware INTs: PCI)
- 0x30 (48) +------+------+
- | | 2 (start of hardware INTs: ISA)
- 0x20 (32) +-------------+
- | | 1 (exceptions, traps, etc.)
- 0x10 (16) +-------------+
- | | 0 (exceptions, traps, etc.)
- 0x00 (0) +-------------+
- */
-
-/* IDT vector base for regular (aka. slow) and fast interrupts */
-#define TPR_SLOW_INTS 0x20
-#define TPR_FAST_INTS 0x60
-/* XXX note that the AST interrupt is at 0x50 */
-
-/* blocking values for local APIC Task Priority Register */
-#define TPR_BLOCK_HWI 0x4f /* hardware INTs */
-#define TPR_IGNORE_HWI 0x5f /* ignore INTs */
-#define TPR_BLOCK_FHWI 0x7f /* hardware FAST INTs */
-#define TPR_IGNORE_FHWI 0x8f /* ignore FAST INTs */
-#define TPR_BLOCK_XINVLTLB 0x9f /* */
-#define TPR_BLOCK_XCPUSTOP 0xaf /* */
-#define TPR_BLOCK_ALL 0xff /* all INTs */
-
-#ifdef TEST_TEST1
-/* put a 'fake' HWI in top of APIC prio 0x3x, 32 + 31 = 63 = 0x3f */
-#define XTEST1_OFFSET (ICU_OFFSET + 31)
-#endif /** TEST_TEST1 */
-
-/* TLB shootdowns */
-#define XINVLTLB_OFFSET (ICU_OFFSET + 112) /* 0x90 */
-#define XINVLPG_OFFSET (ICU_OFFSET + 113) /* 0x91 */
-#define XINVLRNG_OFFSET (ICU_OFFSET + 114) /* 0x92 */
-
-/* inter-cpu clock handling */
-#define XHARDCLOCK_OFFSET (ICU_OFFSET + 120) /* 0x98 */
-#define XSTATCLOCK_OFFSET (ICU_OFFSET + 121) /* 0x99 */
-
-/* inter-CPU rendezvous */
-#define XRENDEZVOUS_OFFSET (ICU_OFFSET + 122) /* 0x9A */
-
-/* lazy pmap release */
-#define XLAZYPMAP_OFFSET (ICU_OFFSET + 123) /* 0x9B */
-
-/* IPI to generate an additional software trap at the target CPU */
-/* XXX in the middle of the interrupt range, overlapping IRQ48 */
-#define XCPUAST_OFFSET (ICU_OFFSET + 48) /* 0x50 */
-
-/* IPI to signal CPUs to stop and wait for another CPU to restart them */
-#define XCPUSTOP_OFFSET (ICU_OFFSET + 128) /* 0xA0 */
-
-/*
- * Note: this vector MUST be xxxx1111, 32 + 223 = 255 = 0xff:
- */
-#define XSPURIOUSINT_OFFSET (ICU_OFFSET + 223)
-
-#endif /* SMP || APIC_IO */
-
#ifdef LOCORE
/*
@@ -184,48 +93,6 @@ unpendhand_t
IDTVEC(fastunpend27), IDTVEC(fastunpend28), IDTVEC(fastunpend29),
IDTVEC(fastunpend30), IDTVEC(fastunpend31);
-#if defined(SMP) || defined(APIC_IO)
-inthand_t
- IDTVEC(fastintr16), IDTVEC(fastintr17),
- IDTVEC(fastintr18), IDTVEC(fastintr19),
- IDTVEC(fastintr20), IDTVEC(fastintr21),
- IDTVEC(fastintr22), IDTVEC(fastintr23),
- IDTVEC(fastintr24), IDTVEC(fastintr25),
- IDTVEC(fastintr26), IDTVEC(fastintr27),
- IDTVEC(fastintr28), IDTVEC(fastintr29),
- IDTVEC(fastintr30), IDTVEC(fastintr31);
-inthand_t
- IDTVEC(intr16), IDTVEC(intr17), IDTVEC(intr18), IDTVEC(intr19),
- IDTVEC(intr20), IDTVEC(intr21), IDTVEC(intr22), IDTVEC(intr23),
- IDTVEC(intr24), IDTVEC(intr25), IDTVEC(intr26), IDTVEC(intr27),
- IDTVEC(intr28), IDTVEC(intr29), IDTVEC(intr30), IDTVEC(intr31);
-
-inthand_t
- Xinvltlb, /* TLB shootdowns - global */
- Xinvlpg, /* TLB shootdowns - 1 page */
- Xinvlrng, /* TLB shootdowns - page range */
- Xhardclock, /* Forward hardclock() */
- Xstatclock, /* Forward statclock() */
- Xcpuast, /* Additional software trap on other cpu */
- Xcpustop, /* CPU stops & waits for another CPU to restart it */
- Xspuriousint, /* handle APIC "spurious INTs" */
- Xrendezvous, /* handle CPU rendezvous */
- Xlazypmap; /* handle lazy pmap release */
-
-#ifdef TEST_TEST1
-inthand_t
- Xtest1; /* 'fake' HWI at top of APIC prio 0x3x, 32+31 = 0x3f */
-#endif /** TEST_TEST1 */
-#endif /* SMP || APIC_IO */
-
-#ifdef APIC_IO
-/*
- * This is to accommodate "mixed-mode" programming for
- * motherboards that don't connect the 8254 to the IO APIC.
- */
-#define AUTO_EOI_1 1
-#endif
-
#define NR_INTRNAMES (1 + ICU_LEN + 2 * ICU_LEN)
void isa_defaultirq(void);
diff --git a/sys/amd64/isa/isa.c b/sys/amd64/isa/isa.c
index bd1df3229b92..3a2def3ecb18 100644
--- a/sys/amd64/isa/isa.c
+++ b/sys/amd64/isa/isa.c
@@ -61,9 +61,6 @@
#include <sys/malloc.h>
#include <machine/bus.h>
#include <sys/rman.h>
-#ifdef PC98
-#include <sys/systm.h>
-#endif
#include <machine/resource.h>
@@ -131,119 +128,13 @@ isa_alloc_resource(device_t bus, device_t child, int type, int *rid,
start, end, count, flags);
}
-#ifdef PC98
-/*
- * Indirection support. The type of bus_space_handle_t is
- * defined in sys/i386/include/bus_pc98.h.
- */
-struct resource *
-isa_alloc_resourcev(device_t child, int type, int *rid,
- bus_addr_t *res, bus_size_t count, u_int flags)
-{
- struct isa_device* idev = DEVTOISA(child);
- struct resource_list *rl = &idev->id_resources;
-
- device_t bus = device_get_parent(child);
- bus_addr_t start;
- struct resource *re;
- struct resource **bsre;
- int i, j, k, linear_cnt, ressz, bsrid;
-
- start = bus_get_resource_start(child, type, *rid);
-
- linear_cnt = count;
- ressz = 1;
- for (i = 1; i < count; ++i) {
- if (res[i] != res[i - 1] + 1) {
- if (i < linear_cnt)
- linear_cnt = i;
- ++ressz;
- }
- }
-
- re = isa_alloc_resource(bus, child, type, rid,
- start + res[0], start + res[linear_cnt - 1],
- linear_cnt, flags);
- if (re == NULL)
- return NULL;
-
- bsre = malloc(sizeof (struct resource *) * ressz, M_DEVBUF, M_NOWAIT);
- if (bsre == NULL) {
- resource_list_release(rl, bus, child, type, *rid, re);
- return NULL;
- }
- bsre[0] = re;
-
- for (i = linear_cnt, k = 1; i < count; i = j, k++) {
- for (j = i + 1; j < count; j++) {
- if (res[j] != res[j - 1] + 1)
- break;
- }
- bsrid = *rid + k;
- bsre[k] = isa_alloc_resource(bus, child, type, &bsrid,
- start + res[i], start + res[j - 1], j - i, flags);
- if (bsre[k] == NULL) {
- for (k--; k >= 0; k--)
- resource_list_release(rl, bus, child, type,
- *rid + k, bsre[k]);
- free(bsre, M_DEVBUF);
- return NULL;
- }
- }
-
- re->r_bushandle->bsh_res = bsre;
- re->r_bushandle->bsh_ressz = ressz;
-
- return re;
-}
-
-int
-isa_load_resourcev(struct resource *re, bus_addr_t *res, bus_size_t count)
-{
- bus_addr_t start;
- int i;
-
- if (count > re->r_bushandle->bsh_maxiatsz) {
- printf("isa_load_resourcev: map size too large\n");
- return EINVAL;
- }
-
- start = rman_get_start(re);
- for (i = 0; i < re->r_bushandle->bsh_maxiatsz; i++) {
- if (i < count)
- re->r_bushandle->bsh_iat[i] = start + res[i];
- else
- re->r_bushandle->bsh_iat[i] = start;
- }
-
- re->r_bushandle->bsh_iatsz = count;
- re->r_bushandle->bsh_bam = re->r_bustag->bs_ra; /* relocate access */
-
- return 0;
-}
-#endif /* PC98 */
-
int
isa_release_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
struct isa_device* idev = DEVTOISA(child);
struct resource_list *rl = &idev->id_resources;
-#ifdef PC98
- /*
- * Indirection support. The type of bus_space_handle_t is
- * defined in sys/i386/include/bus_pc98.h.
- */
- int i;
- if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
- for (i = 1; i < r->r_bushandle->bsh_ressz; i++)
- resource_list_release(rl, bus, child, type, rid + i,
- r->r_bushandle->bsh_res[i]);
- if (r->r_bushandle->bsh_res != NULL)
- free(r->r_bushandle->bsh_res, M_DEVBUF);
- }
-#endif
return resource_list_release(rl, bus, child, type, rid, r);
}
diff --git a/sys/amd64/isa/isa.h b/sys/amd64/isa/isa.h
index cc66da9be045..0b965fbaaea7 100644
--- a/sys/amd64/isa/isa.h
+++ b/sys/amd64/isa/isa.h
@@ -37,10 +37,6 @@
* $FreeBSD$
*/
-#ifdef PC98
-#error isa.h is included from PC-9801 source
-#endif
-
#ifndef _I386_ISA_ISA_H_
#define _I386_ISA_ISA_H_
@@ -151,7 +147,6 @@
#define IO_COMSIZE 8 /* 8250, 16x50 com controllers */
#define IO_DMASIZE 16 /* 8237 DMA controllers */
#define IO_DPGSIZE 32 /* 74LS612 DMA page registers */
-#define IO_EISASIZE 256 /* EISA controllers */
#define IO_FDCSIZE 8 /* Nec765 floppy controllers */
#define IO_GAMSIZE 16 /* AT compatible game controllers */
#define IO_GSCSIZE 8 /* GeniScan GS-4500G hand scanner */
@@ -169,32 +164,4 @@
#endif /* !IO_ISASIZES */
-/*
- * Input / Output Memory Physical Addresses
- */
-#ifndef IOM_BEGIN
-#define IOM_BEGIN 0x0A0000 /* Start of I/O Memory "hole" */
-#define IOM_END 0x100000 /* End of I/O Memory "hole" */
-#define IOM_SIZE (IOM_END - IOM_BEGIN)
-#endif /* !IOM_BEGIN */
-
-/*
- * RAM Physical Address Space (ignoring the above mentioned "hole")
- */
-#ifndef RAM_BEGIN
-#define RAM_BEGIN 0x0000000 /* Start of RAM Memory */
-#define RAM_END 0x1000000 /* End of RAM Memory */
-#define RAM_SIZE (RAM_END - RAM_BEGIN)
-#endif /* !RAM_BEGIN */
-
-/*
- * Oddball Physical Memory Addresses
- */
-#ifndef COMPAQ_RAMRELOC
-#define COMPAQ_RAMRELOC 0x80C00000 /* Compaq RAM relocation/diag */
-#define COMPAQ_RAMSETUP 0x80C00002 /* Compaq RAM setup */
-#define WEITEK_FPU 0xC0000000 /* WTL 2167 */
-#define CYRIX_EMC 0xC0000000 /* Cyrix EMC */
-#endif /* !COMPAQ_RAMRELOC */
-
#endif /* !_I386_ISA_ISA_H_ */
diff --git a/sys/amd64/isa/isa_dma.c b/sys/amd64/isa/isa_dma.c
index 381bd7547461..6be4ae00ffab 100644
--- a/sys/amd64/isa/isa_dma.c
+++ b/sys/amd64/isa/isa_dma.c
@@ -59,7 +59,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/pmap.h>
-#include <i386/isa/isa.h>
+#include <amd64/isa/isa.h>
#include <dev/ic/i8237.h>
#include <isa/isavar.h>
@@ -79,6 +79,8 @@
#define DMA2_MODE (IO_DMA2 + 2*11) /* mode register */
#define DMA2_FFC (IO_DMA2 + 2*12) /* clear first/last FF */
+#define ISARAM_END 0x1000000
+
static int isa_dmarangecheck(caddr_t va, u_int length, int chan);
static caddr_t dma_bouncebuf[8];
@@ -382,7 +384,6 @@ isa_dmarangecheck(caddr_t va, u_int length, int chan)
endva = (vm_offset_t)round_page((vm_offset_t)va + length);
for (; va < (caddr_t) endva ; va += PAGE_SIZE) {
phys = trunc_page(pmap_extract(kernel_pmap, (vm_offset_t)va));
-#define ISARAM_END RAM_END
if (phys == 0)
panic("isa_dmacheck: no physical page present");
if (phys >= ISARAM_END)
diff --git a/sys/amd64/isa/ithread.c b/sys/amd64/isa/ithread.c
index ee619845092b..6455776a4fcc 100644
--- a/sys/amd64/isa/ithread.c
+++ b/sys/amd64/isa/ithread.c
@@ -37,8 +37,9 @@
#include <sys/systm.h>
#include <sys/vmmeter.h>
-#include <i386/isa/icu.h>
-#include <i386/isa/intr_machdep.h>
+#include <amd64/isa/icu.h>
+#include <amd64/isa/intr_machdep.h>
+#include <amd64/isa/isa.h>
struct int_entropy {
struct proc *p;
@@ -46,6 +47,8 @@ struct int_entropy {
};
static u_int straycount[ICU_LEN];
+static u_int glitchcount7;
+static u_int glitchcount15;
#define MAX_STRAY_LOG 5
@@ -56,9 +59,9 @@ static u_int straycount[ICU_LEN];
void
sched_ithd(void *cookie)
{
- int irq = (int) cookie; /* IRQ we're handling */
+ int irq = (uintptr_t) cookie; /* IRQ we're handling */
struct ithd *ithd = ithds[irq]; /* and the process that does it */
- int error;
+ int error, isr;
/* This used to be in icu_vector.s */
/*
@@ -79,7 +82,26 @@ sched_ithd(void *cookie)
/*
* Log stray interrupts.
*/
- if (error == EINVAL)
+ if (error == EINVAL) {
+ /* Determine if it is a stray interrupt or simply a glitch */
+ if (irq == 7) {
+ outb(IO_ICU1, OCW3_SEL); /* select IS register */
+ isr = inb(IO_ICU1);
+ outb(IO_ICU1, OCW3_SEL | OCW3_RIS); /* reselect IIR */
+ if ((isr & 0x80) == 0) {
+ glitchcount7++;
+ return;
+ }
+ }
+ if (irq == 15) {
+ outb(IO_ICU2, OCW3_SEL); /* select IS register */
+ isr = inb(IO_ICU2);
+ outb(IO_ICU2, OCW3_SEL | OCW3_RIS); /* reselect IIR */
+ if ((isr & 0x80) == 0) {
+ glitchcount15++;
+ return;
+ }
+ }
if (straycount[irq] < MAX_STRAY_LOG) {
printf("stray irq %d\n", irq);
if (++straycount[irq] == MAX_STRAY_LOG)
@@ -87,4 +109,5 @@ sched_ithd(void *cookie)
"got %d stray irq %d's: not logging anymore\n",
MAX_STRAY_LOG, irq);
}
+ }
}
diff --git a/sys/amd64/isa/npx.c b/sys/amd64/isa/npx.c
index 8dadb6bcc9c3..2116701c696a 100644
--- a/sys/amd64/isa/npx.c
+++ b/sys/amd64/isa/npx.c
@@ -35,11 +35,8 @@
* $FreeBSD$
*/
-#include "opt_cpu.h"
#include "opt_debug_npx.h"
#include "opt_isa.h"
-#include "opt_math_emulate.h"
-#include "opt_npx.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -60,66 +57,34 @@
#include <sys/signalvar.h>
#include <sys/user.h>
-#ifndef SMP
-#include <machine/asmacros.h>
-#endif
#include <machine/cputypes.h>
#include <machine/frame.h>
#include <machine/md_var.h>
#include <machine/pcb.h>
#include <machine/psl.h>
-#ifndef SMP
-#include <machine/clock.h>
-#endif
#include <machine/resource.h>
#include <machine/specialreg.h>
#include <machine/segments.h>
#include <machine/ucontext.h>
-#ifndef SMP
-#include <i386/isa/icu.h>
-#ifdef PC98
-#include <pc98/pc98/pc98.h>
-#else
-#include <i386/isa/isa.h>
-#endif
-#endif
-#include <i386/isa/intr_machdep.h>
+#include <amd64/isa/intr_machdep.h>
#ifdef DEV_ISA
#include <isa/isavar.h>
#endif
-#if !defined(CPU_ENABLE_SSE) && defined(I686_CPU)
-#define CPU_ENABLE_SSE
-#endif
-#if defined(CPU_DISABLE_SSE)
-#undef CPU_ENABLE_SSE
-#endif
-
/*
* 387 and 287 Numeric Coprocessor Extension (NPX) Driver.
*/
-/* Configuration flags. */
-#define NPX_DISABLE_I586_OPTIMIZED_BCOPY (1 << 0)
-#define NPX_DISABLE_I586_OPTIMIZED_BZERO (1 << 1)
-#define NPX_DISABLE_I586_OPTIMIZED_COPYIO (1 << 2)
-#define NPX_PREFER_EMULATOR (1 << 3)
-
#if defined(__GNUC__) && !defined(lint)
#define fldcw(addr) __asm("fldcw %0" : : "m" (*(addr)))
#define fnclex() __asm("fnclex")
#define fninit() __asm("fninit")
-#define fnsave(addr) __asm __volatile("fnsave %0" : "=m" (*(addr)))
#define fnstcw(addr) __asm __volatile("fnstcw %0" : "=m" (*(addr)))
#define fnstsw(addr) __asm __volatile("fnstsw %0" : "=m" (*(addr)))
-#define fp_divide_by_0() __asm("fldz; fld1; fdiv %st,%st(1); fnop")
-#define frstor(addr) __asm("frstor %0" : : "m" (*(addr)))
-#ifdef CPU_ENABLE_SSE
#define fxrstor(addr) __asm("fxrstor %0" : : "m" (*(addr)))
#define fxsave(addr) __asm __volatile("fxsave %0" : "=m" (*(addr)))
-#endif
#define start_emulating() __asm("smsw %%ax; orb %0,%%al; lmsw %%ax" \
: : "n" (CR0_TS) : "ax")
#define stop_emulating() __asm("clts")
@@ -129,81 +94,31 @@
void fldcw(caddr_t addr);
void fnclex(void);
void fninit(void);
-void fnsave(caddr_t addr);
void fnstcw(caddr_t addr);
void fnstsw(caddr_t addr);
-void fp_divide_by_0(void);
-void frstor(caddr_t addr);
-#ifdef CPU_ENABLE_SSE
void fxsave(caddr_t addr);
void fxrstor(caddr_t addr);
-#endif
void start_emulating(void);
void stop_emulating(void);
#endif /* __GNUC__ */
-#ifdef CPU_ENABLE_SSE
-#define GET_FPU_CW(thread) \
- (cpu_fxsr ? \
- (thread)->td_pcb->pcb_save.sv_xmm.sv_env.en_cw : \
- (thread)->td_pcb->pcb_save.sv_87.sv_env.en_cw)
-#define GET_FPU_SW(thread) \
- (cpu_fxsr ? \
- (thread)->td_pcb->pcb_save.sv_xmm.sv_env.en_sw : \
- (thread)->td_pcb->pcb_save.sv_87.sv_env.en_sw)
-#else /* CPU_ENABLE_SSE */
-#define GET_FPU_CW(thread) \
- (thread->td_pcb->pcb_save.sv_87.sv_env.en_cw)
-#define GET_FPU_SW(thread) \
- (thread->td_pcb->pcb_save.sv_87.sv_env.en_sw)
-#endif /* CPU_ENABLE_SSE */
+#define GET_FPU_CW(thread) ((thread)->td_pcb->pcb_save.sv_env.en_cw)
+#define GET_FPU_SW(thread) ((thread)->td_pcb->pcb_save.sv_env.en_sw)
typedef u_char bool_t;
-static void fpusave(union savefpu *);
-static void fpurstor(union savefpu *);
static int npx_attach(device_t dev);
static void npx_identify(driver_t *driver, device_t parent);
-#ifndef SMP
-static void npx_intr(void *);
-#endif
static int npx_probe(device_t dev);
-#ifdef I586_CPU_XXX
-static long timezero(const char *funcname,
- void (*func)(void *buf, size_t len));
-#endif /* I586_CPU */
-
-int hw_float; /* XXX currently just alias for npx_exists */
+int hw_float = 1;
SYSCTL_INT(_hw,HW_FLOATINGPT, floatingpoint,
CTLFLAG_RD, &hw_float, 0,
"Floatingpoint instructions executed in hardware");
-#ifndef SMP
-static volatile u_int npx_intrs_while_probing;
-static volatile u_int npx_traps_while_probing;
-#endif
-
-static union savefpu npx_cleanstate;
+static struct savefpu npx_cleanstate;
static bool_t npx_cleanstate_ready;
-static bool_t npx_ex16;
-static bool_t npx_exists;
-static bool_t npx_irq13;
-
-#ifndef SMP
-alias_for_inthand_t probetrap;
-__asm(" \n\
- .text \n\
- .p2align 2,0x90 \n\
- .type " __XSTRING(CNAME(probetrap)) ",@function \n\
-" __XSTRING(CNAME(probetrap)) ": \n\
- ss \n\
- incl " __XSTRING(CNAME(npx_traps_while_probing)) " \n\
- fnclex \n\
- iret \n\
-");
-#endif /* SMP */
/*
* Identify routine. Create a connection point on our parent for probing.
@@ -220,104 +135,23 @@ npx_identify(driver, parent)
panic("npx_identify");
}
-#ifndef SMP
-/*
- * Do minimal handling of npx interrupts to convert them to traps.
- */
-static void
-npx_intr(dummy)
- void *dummy;
-{
- struct thread *td;
-
-#ifndef SMP
- npx_intrs_while_probing++;
-#endif
-
- /*
- * The BUSY# latch must be cleared in all cases so that the next
- * unmasked npx exception causes an interrupt.
- */
-#ifdef PC98
- outb(0xf8, 0);
-#else
- outb(0xf0, 0);
-#endif
-
- /*
- * fpcurthread is normally non-null here. In that case, schedule an
- * AST to finish the exception handling in the correct context
- * (this interrupt may occur after the thread has entered the
- * kernel via a syscall or an interrupt). Otherwise, the npx
- * state of the thread that caused this interrupt must have been
- * pushed to the thread's pcb, and clearing of the busy latch
- * above has finished the (essentially null) handling of this
- * interrupt. Control will eventually return to the instruction
- * that caused it and it will repeat. We will eventually (usually
- * soon) win the race to handle the interrupt properly.
- */
- td = PCPU_GET(fpcurthread);
- if (td != NULL) {
- td->td_pcb->pcb_flags |= PCB_NPXTRAP;
- mtx_lock_spin(&sched_lock);
- td->td_flags |= TDF_ASTPENDING;
- mtx_unlock_spin(&sched_lock);
- }
-}
-#endif /* !SMP */
-
/*
* Probe routine. Initialize cr0 to give correct behaviour for [f]wait
- * whether the device exists or not (XXX should be elsewhere). Set flags
- * to tell npxattach() what to do. Modify device struct if npx doesn't
- * need to use interrupts. Return 0 if device exists.
+ * whether the device exists or not (XXX should be elsewhere).
+ * Modify device struct if npx doesn't need to use interrupts.
+ * Return 0 if device exists.
*/
static int
npx_probe(dev)
device_t dev;
{
-#ifndef SMP
- struct gate_descriptor save_idt_npxtrap;
- struct resource *ioport_res, *irq_res;
- void *irq_cookie;
- int ioport_rid, irq_num, irq_rid;
- u_short control;
- u_short status;
-
- save_idt_npxtrap = idt[16];
- setidt(16, probetrap, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
- ioport_rid = 0;
- ioport_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &ioport_rid,
- IO_NPX, IO_NPX, IO_NPXSIZE, RF_ACTIVE);
- if (ioport_res == NULL)
- panic("npx: can't get ports");
-#ifdef PC98
- if (resource_int_value("npx", 0, "irq", &irq_num) != 0)
- irq_num = 8;
-#else
- if (resource_int_value("npx", 0, "irq", &irq_num) != 0)
- irq_num = 13;
-#endif
- irq_rid = 0;
- irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &irq_rid, irq_num,
- irq_num, 1, RF_ACTIVE);
- if (irq_res == NULL)
- panic("npx: can't get IRQ");
- if (bus_setup_intr(dev, irq_res, INTR_TYPE_MISC | INTR_FAST, npx_intr,
- NULL, &irq_cookie) != 0)
- panic("npx: can't create intr");
-#endif /* !SMP */
/*
* Partially reset the coprocessor, if any. Some BIOS's don't reset
* it after a warm boot.
*/
-#ifdef PC98
- outb(0xf8,0);
-#else
outb(0xf1, 0); /* full reset on some systems, NOP on others */
outb(0xf0, 0); /* clear BUSY# latch */
-#endif
/*
* Prepare to trap all ESC (i.e., NPX) instructions and all WAIT
* instructions. We must set the CR0_MP bit and use the CR0_TS
@@ -338,116 +172,13 @@ npx_probe(dev)
*/
stop_emulating();
/*
- * Finish resetting the coprocessor, if any. If there is an error
- * pending, then we may get a bogus IRQ13, but npx_intr() will handle
- * it OK. Bogus halts have never been observed, but we enabled
- * IRQ13 and cleared the BUSY# latch early to handle them anyway.
+ * Finish resetting the coprocessor.
*/
fninit();
device_set_desc(dev, "math processor");
-#ifdef SMP
-
- /*
- * Exception 16 MUST work for SMP.
- */
- npx_ex16 = hw_float = npx_exists = 1;
- return (0);
-
-#else /* !SMP */
-
- /*
- * Don't use fwait here because it might hang.
- * Don't use fnop here because it usually hangs if there is no FPU.
- */
- DELAY(1000); /* wait for any IRQ13 */
-#ifdef DIAGNOSTIC
- if (npx_intrs_while_probing != 0)
- printf("fninit caused %u bogus npx interrupt(s)\n",
- npx_intrs_while_probing);
- if (npx_traps_while_probing != 0)
- printf("fninit caused %u bogus npx trap(s)\n",
- npx_traps_while_probing);
-#endif
- /*
- * Check for a status of mostly zero.
- */
- status = 0x5a5a;
- fnstsw(&status);
- if ((status & 0xb8ff) == 0) {
- /*
- * Good, now check for a proper control word.
- */
- control = 0x5a5a;
- fnstcw(&control);
- if ((control & 0x1f3f) == 0x033f) {
- hw_float = npx_exists = 1;
- /*
- * We have an npx, now divide by 0 to see if exception
- * 16 works.
- */
- control &= ~(1 << 2); /* enable divide by 0 trap */
- fldcw(&control);
-#ifdef FPU_ERROR_BROKEN
- /*
- * FPU error signal doesn't work on some CPU
- * accelerator board.
- */
- npx_ex16 = 1;
- return (0);
-#endif
- npx_traps_while_probing = npx_intrs_while_probing = 0;
- fp_divide_by_0();
- if (npx_traps_while_probing != 0) {
- /*
- * Good, exception 16 works.
- */
- npx_ex16 = 1;
- goto no_irq13;
- }
- if (npx_intrs_while_probing != 0) {
- /*
- * Bad, we are stuck with IRQ13.
- */
- npx_irq13 = 1;
- idt[16] = save_idt_npxtrap;
- return (0);
- }
- /*
- * Worse, even IRQ13 is broken. Use emulator.
- */
- }
- }
- /*
- * Probe failed, but we want to get to npxattach to initialize the
- * emulator and say that it has been installed. XXX handle devices
- * that aren't really devices better.
- */
- /* FALLTHROUGH */
-no_irq13:
- idt[16] = save_idt_npxtrap;
- bus_teardown_intr(dev, irq_res, irq_cookie);
-
- /*
- * XXX hack around brokenness of bus_teardown_intr(). If we left the
- * irq active then we would get it instead of exception 16.
- */
- {
- register_t crit;
-
- crit = intr_disable();
- mtx_lock_spin(&icu_lock);
- INTRDIS(1 << irq_num);
- mtx_unlock_spin(&icu_lock);
- intr_restore(crit);
- }
-
- bus_release_resource(dev, SYS_RES_IRQ, irq_rid, irq_res);
- bus_release_resource(dev, SYS_RES_IOPORT, ioport_rid, ioport_res);
return (0);
-
-#endif /* SMP */
}
/*
@@ -457,67 +188,19 @@ static int
npx_attach(dev)
device_t dev;
{
- int flags;
register_t s;
- if (resource_int_value("npx", 0, "flags", &flags) != 0)
- flags = 0;
-
- if (flags)
- device_printf(dev, "flags 0x%x ", flags);
- if (npx_irq13) {
- device_printf(dev, "using IRQ 13 interface\n");
- } else {
-#if defined(MATH_EMULATE) || defined(GPL_MATH_EMULATE)
- if (npx_ex16) {
- if (!(flags & NPX_PREFER_EMULATOR))
- device_printf(dev, "INT 16 interface\n");
- else {
- device_printf(dev, "FPU exists, but flags request "
- "emulator\n");
- hw_float = npx_exists = 0;
- }
- } else if (npx_exists) {
- device_printf(dev, "error reporting broken; using 387 emulator\n");
- hw_float = npx_exists = 0;
- } else
- device_printf(dev, "387 emulator\n");
-#else
- if (npx_ex16) {
- device_printf(dev, "INT 16 interface\n");
- if (flags & NPX_PREFER_EMULATOR) {
- device_printf(dev, "emulator requested, but none compiled "
- "into kernel, using FPU\n");
- }
- } else
- device_printf(dev, "no 387 emulator in kernel and no FPU!\n");
-#endif
- }
+ device_printf(dev, "INT 16 interface\n");
npxinit(__INITIAL_NPXCW__);
if (npx_cleanstate_ready == 0) {
s = intr_disable();
stop_emulating();
- fpusave(&npx_cleanstate);
+ fxsave(&npx_cleanstate);
start_emulating();
npx_cleanstate_ready = 1;
intr_restore(s);
}
-#ifdef I586_CPU_XXX
- if (cpu_class == CPUCLASS_586 && npx_ex16 && npx_exists &&
- timezero("i586_bzero()", i586_bzero) <
- timezero("bzero()", bzero) * 4 / 5) {
- if (!(flags & NPX_DISABLE_I586_OPTIMIZED_BCOPY))
- bcopy_vector = i586_bcopy;
- if (!(flags & NPX_DISABLE_I586_OPTIMIZED_BZERO))
- bzero_vector = i586_bzero;
- if (!(flags & NPX_DISABLE_I586_OPTIMIZED_COPYIO)) {
- copyin_vector = i586_copyin;
- copyout_vector = i586_copyout;
- }
- }
-#endif
-
return (0); /* XXX unused */
}
@@ -528,11 +211,9 @@ void
npxinit(control)
u_short control;
{
- static union savefpu dummy;
+ static struct savefpu dummy;
register_t savecrit;
- if (!npx_exists)
- return;
/*
* fninit has the same h/w bugs as fnsave. Use the detoxified
* fnsave to throw away any junk in the fpu. npxsave() initializes
@@ -541,11 +222,8 @@ npxinit(control)
savecrit = intr_disable();
npxsave(&dummy);
stop_emulating();
-#ifdef CPU_ENABLE_SSE
/* XXX npxsave() doesn't actually initialize the fpu in the SSE case. */
- if (cpu_fxsr)
- fninit();
-#endif
+ fninit();
fldcw(&control);
start_emulating();
intr_restore(savecrit);
@@ -558,6 +236,9 @@ void
npxexit(td)
struct thread *td;
{
+#ifdef NPX_DEBUG
+ u_int masked_exceptions;
+#endif
register_t savecrit;
savecrit = intr_disable();
@@ -565,20 +246,16 @@ npxexit(td)
npxsave(&PCPU_GET(curpcb)->pcb_save);
intr_restore(savecrit);
#ifdef NPX_DEBUG
- if (npx_exists) {
- u_int masked_exceptions;
-
- masked_exceptions = GET_FPU_CW(td) & GET_FPU_SW(td) & 0x7f;
- /*
- * Log exceptions that would have trapped with the old
- * control word (overflow, divide by 0, and invalid operand).
- */
- if (masked_exceptions & 0x0d)
- log(LOG_ERR,
- "pid %d (%s) exited with masked floating point exceptions 0x%02x\n",
- td->td_proc->p_pid, td->td_proc->p_comm,
- masked_exceptions);
- }
+ masked_exceptions = GET_FPU_CW(td) & GET_FPU_SW(td) & 0x7f;
+ /*
+ * Log exceptions that would have trapped with the old
+ * control word (overflow, divide by 0, and invalid operand).
+ */
+ if (masked_exceptions & 0x0d)
+ log(LOG_ERR,
+"pid %d (%s) exited with masked floating point exceptions 0x%02x\n",
+ td->td_proc->p_pid, td->td_proc->p_comm,
+ masked_exceptions);
#endif
}
@@ -586,13 +263,7 @@ int
npxformat()
{
- if (!npx_exists)
- return (_MC_FPFMT_NODEV);
-#ifdef CPU_ENABLE_SSE
- if (cpu_fxsr)
- return (_MC_FPFMT_XMM);
-#endif
- return (_MC_FPFMT_387);
+ return (_MC_FPFMT_XMM);
}
/*
@@ -789,11 +460,6 @@ npxtrap()
register_t savecrit;
u_short control, status;
- if (!npx_exists) {
- printf("npxtrap: fpcurthread = %p, curthread = %p, npx_exists = %d\n",
- PCPU_GET(fpcurthread), curthread, npx_exists);
- panic("npxtrap from nowhere");
- }
savecrit = intr_disable();
/*
@@ -832,8 +498,6 @@ npxdna()
register_t s;
u_short control;
- if (!npx_exists)
- return (0);
if (PCPU_GET(fpcurthread) == curthread) {
printf("npxdna: fpcurthread == curthread %d times\n",
++err_count);
@@ -867,20 +531,15 @@ npxdna()
pcb->pcb_flags |= PCB_NPXINITDONE;
} else {
/*
- * The following frstor may cause an IRQ13 when the state
+ * The following frstor may cause a trap when the state
* being restored has a pending error. The error will
* appear to have been triggered by the current (npx) user
* instruction even when that instruction is a no-wait
* instruction that should not trigger an error (e.g.,
- * fnclex). On at least one 486 system all of the no-wait
* instructions are broken the same as frstor, so our
- * treatment does not amplify the breakage. On at least
- * one 386/Cyrix 387 system, fnclex works correctly while
- * frstor and fnsave are broken, so our treatment breaks
- * fnclex if it is the first FPU instruction after a context
- * switch.
+ * treatment does not amplify the breakage.
*/
- fpurstor(&pcb->pcb_save);
+ fxrstor(&pcb->pcb_save);
}
intr_restore(s);
@@ -912,11 +571,11 @@ npxdna()
*/
void
npxsave(addr)
- union savefpu *addr;
+ struct savefpu *addr;
{
stop_emulating();
- fpusave(addr);
+ fxsave(addr);
start_emulating();
PCPU_SET(fpcurthread, NULL);
@@ -944,13 +603,10 @@ npxdrop()
int
npxgetregs(td, addr)
struct thread *td;
- union savefpu *addr;
+ struct savefpu *addr;
{
register_t s;
- if (!npx_exists)
- return (_MC_FPOWNED_NONE);
-
if ((td->td_pcb->pcb_flags & PCB_NPXINITDONE) == 0) {
if (npx_cleanstate_ready)
bcopy(&npx_cleanstate, addr, sizeof(npx_cleanstate));
@@ -960,16 +616,7 @@ npxgetregs(td, addr)
}
s = intr_disable();
if (td == PCPU_GET(fpcurthread)) {
- fpusave(addr);
-#ifdef CPU_ENABLE_SSE
- if (!cpu_fxsr)
-#endif
- /*
- * fnsave initializes the FPU and destroys whatever
- * context it contains. Make sure the FPU owner
- * starts with a clean state next time.
- */
- npxdrop();
+ fxsave(addr);
intr_restore(s);
return (_MC_FPOWNED_FPU);
} else {
@@ -985,16 +632,13 @@ npxgetregs(td, addr)
void
npxsetregs(td, addr)
struct thread *td;
- union savefpu *addr;
+ struct savefpu *addr;
{
register_t s;
- if (!npx_exists)
- return;
-
s = intr_disable();
if (td == PCPU_GET(fpcurthread)) {
- fpurstor(addr);
+ fxrstor(addr);
intr_restore(s);
} else {
intr_restore(s);
@@ -1003,62 +647,6 @@ npxsetregs(td, addr)
curthread->td_pcb->pcb_flags |= PCB_NPXINITDONE;
}
-static void
-fpusave(addr)
- union savefpu *addr;
-{
-
-#ifdef CPU_ENABLE_SSE
- if (cpu_fxsr)
- fxsave(addr);
- else
-#endif
- fnsave(addr);
-}
-
-static void
-fpurstor(addr)
- union savefpu *addr;
-{
-
-#ifdef CPU_ENABLE_SSE
- if (cpu_fxsr)
- fxrstor(addr);
- else
-#endif
- frstor(addr);
-}
-
-#ifdef I586_CPU_XXX
-static long
-timezero(funcname, func)
- const char *funcname;
- void (*func)(void *buf, size_t len);
-
-{
- void *buf;
-#define BUFSIZE 1048576
- long usec;
- struct timeval finish, start;
-
- buf = malloc(BUFSIZE, M_TEMP, M_NOWAIT);
- if (buf == NULL)
- return (BUFSIZE);
- microtime(&start);
- (*func)(buf, BUFSIZE);
- microtime(&finish);
- usec = 1000000 * (finish.tv_sec - start.tv_sec) +
- finish.tv_usec - start.tv_usec;
- if (usec <= 0)
- usec = 1;
- if (bootverbose)
- printf("%s bandwidth = %u kBps\n", funcname,
- (u_int32_t)(((BUFSIZE >> 10) * 1000000) / usec));
- free(buf, M_TEMP);
- return (usec);
-}
-#endif /* I586_CPU */
-
static device_method_t npx_methods[] = {
/* Device interface */
DEVMETHOD(device_identify, npx_identify),
@@ -1080,13 +668,13 @@ static driver_t npx_driver = {
static devclass_t npx_devclass;
-#ifdef DEV_ISA
/*
* We prefer to attach to the root nexus so that the usual case (exception 16)
* doesn't describe the processor as being `on isa'.
*/
DRIVER_MODULE(npx, nexus, npx_driver, npx_devclass, 0, 0);
+#ifdef DEV_ISA
/*
* This sucks up the legacy ISA support assignments from PNPBIOS/ACPI.
*/
@@ -1132,7 +720,5 @@ static driver_t npxisa_driver = {
static devclass_t npxisa_devclass;
DRIVER_MODULE(npxisa, isa, npxisa_driver, npxisa_devclass, 0, 0);
-#ifndef PC98
DRIVER_MODULE(npxisa, acpi, npxisa_driver, npxisa_devclass, 0, 0);
-#endif
#endif /* DEV_ISA */
diff --git a/sys/amd64/isa/timerreg.h b/sys/amd64/isa/timerreg.h
index 0bfd7fc8cd63..981082629e7c 100644
--- a/sys/amd64/isa/timerreg.h
+++ b/sys/amd64/isa/timerreg.h
@@ -84,15 +84,9 @@
* Macros for specifying values to be written into a mode register.
*/
#define TIMER_CNTR0 (IO_TIMER1 + 0) /* timer 0 counter port */
-#ifdef PC98
-#define TIMER_CNTR1 0x3fdb /* timer 1 counter port */
-#define TIMER_CNTR2 (IO_TIMER1 + 4) /* timer 2 counter port */
-#define TIMER_MODE (IO_TIMER1 + 6) /* timer mode port */
-#else
#define TIMER_CNTR1 (IO_TIMER1 + 1) /* timer 1 counter port */
#define TIMER_CNTR2 (IO_TIMER1 + 2) /* timer 2 counter port */
#define TIMER_MODE (IO_TIMER1 + 3) /* timer mode port */
-#endif
#define TIMER_SEL0 0x00 /* select counter 0 */
#define TIMER_SEL1 0x40 /* select counter 1 */
#define TIMER_SEL2 0x80 /* select counter 2 */
diff --git a/sys/amd64/isa/vector.S b/sys/amd64/isa/vector.S
index 0bed76fdb083..0fc5334adedc 100644
--- a/sys/amd64/isa/vector.S
+++ b/sys/amd64/isa/vector.S
@@ -3,37 +3,9 @@
* $FreeBSD$
*/
-/*
- * modified for PC98 by Kakefuda
- */
-
-#include "opt_auto_eoi.h"
-
-#include <i386/isa/icu.h>
-#ifdef PC98
-#include <pc98/pc98/pc98.h>
-#else
-#include <i386/isa/isa.h>
-#endif
-#include <i386/isa/intr_machdep.h>
-
-#define FAST_INTR_HANDLER_USES_ES 1
-#ifdef FAST_INTR_HANDLER_USES_ES
-#define ACTUALLY_PUSHED 1
-#define MAYBE_MOVW_AX_ES movw %ax,%es
-#define MAYBE_POPL_ES popl %es
-#define MAYBE_PUSHL_ES pushl %es
-#else
-/*
- * We can usually skip loading %es for fastintr handlers. %es should
- * only be used for string instructions, and fastintr handlers shouldn't
- * do anything slow enough to justify using a string instruction.
- */
-#define ACTUALLY_PUSHED 0
-#define MAYBE_MOVW_AX_ES
-#define MAYBE_POPL_ES
-#define MAYBE_PUSHL_ES
-#endif
+#include <amd64/isa/icu.h>
+#include <amd64/isa/isa.h>
+#include <amd64/isa/intr_machdep.h>
.data
ALIGN_DATA
@@ -47,12 +19,12 @@
.globl intrcnt, eintrcnt
intrcnt:
- .space INTRCNT_COUNT * 4
+ .space INTRCNT_COUNT * 8
eintrcnt:
.globl intrnames, eintrnames
intrnames:
- .space INTRCNT_COUNT * 16
+ .space INTRCNT_COUNT * 32
eintrnames:
.text
@@ -101,8 +73,4 @@ eintrnames:
* loading segregs.
*/
-#ifdef APIC_IO
-#include "i386/isa/apic_vector.s"
-#else
-#include "i386/isa/icu_vector.s"
-#endif /* APIC_IO */
+#include "amd64/isa/icu_vector.s"
diff --git a/sys/amd64/isa/vector.s b/sys/amd64/isa/vector.s
index 0bed76fdb083..0fc5334adedc 100644
--- a/sys/amd64/isa/vector.s
+++ b/sys/amd64/isa/vector.s
@@ -3,37 +3,9 @@
* $FreeBSD$
*/
-/*
- * modified for PC98 by Kakefuda
- */
-
-#include "opt_auto_eoi.h"
-
-#include <i386/isa/icu.h>
-#ifdef PC98
-#include <pc98/pc98/pc98.h>
-#else
-#include <i386/isa/isa.h>
-#endif
-#include <i386/isa/intr_machdep.h>
-
-#define FAST_INTR_HANDLER_USES_ES 1
-#ifdef FAST_INTR_HANDLER_USES_ES
-#define ACTUALLY_PUSHED 1
-#define MAYBE_MOVW_AX_ES movw %ax,%es
-#define MAYBE_POPL_ES popl %es
-#define MAYBE_PUSHL_ES pushl %es
-#else
-/*
- * We can usually skip loading %es for fastintr handlers. %es should
- * only be used for string instructions, and fastintr handlers shouldn't
- * do anything slow enough to justify using a string instruction.
- */
-#define ACTUALLY_PUSHED 0
-#define MAYBE_MOVW_AX_ES
-#define MAYBE_POPL_ES
-#define MAYBE_PUSHL_ES
-#endif
+#include <amd64/isa/icu.h>
+#include <amd64/isa/isa.h>
+#include <amd64/isa/intr_machdep.h>
.data
ALIGN_DATA
@@ -47,12 +19,12 @@
.globl intrcnt, eintrcnt
intrcnt:
- .space INTRCNT_COUNT * 4
+ .space INTRCNT_COUNT * 8
eintrcnt:
.globl intrnames, eintrnames
intrnames:
- .space INTRCNT_COUNT * 16
+ .space INTRCNT_COUNT * 32
eintrnames:
.text
@@ -101,8 +73,4 @@ eintrnames:
* loading segregs.
*/
-#ifdef APIC_IO
-#include "i386/isa/apic_vector.s"
-#else
-#include "i386/isa/icu_vector.s"
-#endif /* APIC_IO */
+#include "amd64/isa/icu_vector.s"
diff --git a/sys/amd64/pci/pci_bus.c b/sys/amd64/pci/pci_bus.c
index 9e288686e883..4465e7ad952f 100644
--- a/sys/amd64/pci/pci_bus.c
+++ b/sys/amd64/pci/pci_bus.c
@@ -44,14 +44,10 @@
#include <machine/pci_cfgreg.h>
#include <machine/segments.h>
#include <machine/cputypes.h>
-#include <machine/pc/bios.h>
#include <machine/md_var.h>
#include "pcib_if.h"
-static int pcibios_pcib_route_interrupt(device_t pcib, device_t dev,
- int pin);
-
static int
nexus_pcib_maxslots(device_t dev)
{
@@ -81,7 +77,9 @@ nexus_pcib_write_config(device_t dev, int bus, int slot, int func,
static int
nexus_pcib_route_interrupt(device_t pcib, device_t dev, int pin)
{
- return (pcibios_pcib_route_interrupt(pcib, dev, pin));
+
+ /* No routing possible */
+ return (PCI_INVALID_IRQ);
}
static const char *
@@ -605,67 +603,3 @@ static driver_t pcibus_pnp_driver = {
static devclass_t pcibus_pnp_devclass;
DRIVER_MODULE(pcibus_pnp, isa, pcibus_pnp_driver, pcibus_pnp_devclass, 0, 0);
-
-
-/*
- * Provide a PCI-PCI bridge driver for PCI busses behind PCI-PCI bridges
- * that appear in the PCIBIOS Interrupt Routing Table to use the routing
- * table for interrupt routing when possible.
- */
-static int pcibios_pcib_probe(device_t bus);
-
-static device_method_t pcibios_pcib_pci_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, pcibios_pcib_probe),
- DEVMETHOD(device_attach, pcib_attach),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
- DEVMETHOD(device_suspend, bus_generic_suspend),
- DEVMETHOD(device_resume, bus_generic_resume),
-
- /* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
- DEVMETHOD(bus_read_ivar, pcib_read_ivar),
- DEVMETHOD(bus_write_ivar, pcib_write_ivar),
- DEVMETHOD(bus_alloc_resource, pcib_alloc_resource),
- DEVMETHOD(bus_release_resource, bus_generic_release_resource),
- DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
- DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
- DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
- DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
-
- /* pcib interface */
- DEVMETHOD(pcib_maxslots, pcib_maxslots),
- DEVMETHOD(pcib_read_config, pcib_read_config),
- DEVMETHOD(pcib_write_config, pcib_write_config),
- DEVMETHOD(pcib_route_interrupt, pcibios_pcib_route_interrupt),
-
- {0, 0}
-};
-
-static driver_t pcibios_pcib_driver = {
- "pcib",
- pcibios_pcib_pci_methods,
- sizeof(struct pcib_softc),
-};
-
-DRIVER_MODULE(pcibios_pcib, pci, pcibios_pcib_driver, pcib_devclass, 0, 0);
-
-static int
-pcibios_pcib_probe(device_t dev)
-{
-
- if ((pci_get_class(dev) != PCIC_BRIDGE) ||
- (pci_get_subclass(dev) != PCIS_BRIDGE_PCI))
- return (ENXIO);
- if (pci_probe_route_table(pcib_get_bus(dev)) == 0)
- return (ENXIO);
- device_set_desc(dev, "PCIBIOS PCI-PCI bridge");
- return (-2000);
-}
-
-static int
-pcibios_pcib_route_interrupt(device_t pcib, device_t dev, int pin)
-{
- return(pci_cfgintr(pci_get_bus(dev), pci_get_slot(dev), pin,
- pci_get_irq(dev)));
-}
diff --git a/sys/amd64/pci/pci_cfgreg.c b/sys/amd64/pci/pci_cfgreg.c
index 4a174bd1fd73..2352c3004107 100644
--- a/sys/amd64/pci/pci_cfgreg.c
+++ b/sys/amd64/pci/pci_cfgreg.c
@@ -44,76 +44,18 @@
#include <dev/pci/pcireg.h>
#include <isa/isavar.h>
#include <machine/pci_cfgreg.h>
-#include <machine/segments.h>
-#include <machine/pc/bios.h>
-
-#ifdef APIC_IO
-#include <machine/smp.h>
-#endif /* APIC_IO */
#include "pcib_if.h"
-#define PRVERB(a) do { \
- if (bootverbose) \
- printf a ; \
-} while(0)
-
static int cfgmech;
static int devmax;
-static int pci_cfgintr_valid(struct PIR_entry *pe, int pin, int irq);
-static int pci_cfgintr_unique(struct PIR_entry *pe, int pin);
-static int pci_cfgintr_linked(struct PIR_entry *pe, int pin);
-static int pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int pin);
-static int pci_cfgintr_virgin(struct PIR_entry *pe, int pin);
-
-static void pci_print_irqmask(u_int16_t irqs);
-static void pci_print_route_table(struct PIR_table *prt, int size);
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 PIR_table *pci_route_table;
-static int pci_route_count;
-
static struct mtx pcicfg_mtx;
-/*
- * Some BIOS writers seem to want to ignore the spec and put
- * 0 in the intline rather than 255 to indicate none. Some use
- * numbers in the range 128-254 to indicate something strange and
- * apparently undocumented anywhere. Assume these are completely bogus
- * and map them to 255, which means "none".
- */
-static __inline__ int
-pci_i386_map_intline(int line)
-{
- if (line == 0 || line >= 128)
- return (PCI_INVALID_IRQ);
- return (line);
-}
-
-static u_int16_t
-pcibios_get_version(void)
-{
- struct bios_regs args;
-
- if (PCIbios.ventry == 0) {
- PRVERB(("pcibios: No call entry point\n"));
- return (0);
- }
- args.eax = PCIBIOS_BIOS_PRESENT;
- if (bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL))) {
- PRVERB(("pcibios: BIOS_PRESENT call failed\n"));
- return (0);
- }
- if (args.edx != 0x20494350) {
- PRVERB(("pcibios: BIOS_PRESENT didn't return 'PCI ' in edx\n"));
- return (0);
- }
- return (args.ebx & 0xffff);
-}
-
/*
* Initialise access to PCI configuration space
*/
@@ -121,59 +63,14 @@ int
pci_cfgregopen(void)
{
static int opened = 0;
- u_long sigaddr;
- static struct PIR_table *pt;
- u_int16_t v;
- u_int8_t ck, *cv;
- int i;
if (opened)
- return(1);
-
+ return (1);
if (pcireg_cfgopen() == 0)
- return(0);
-
- v = pcibios_get_version();
- if (v > 0)
- printf("pcibios: BIOS version %x.%02x\n", (v & 0xff00) >> 8,
- v & 0xff);
-
- /*
- * Look for the interrupt routing table.
- *
- * We use PCI BIOS's PIR table if it's available $PIR is the
- * standard way to do this. Sadly, some machines are not
- * standards conforming and have _PIR instead. We shrug and cope
- * by looking for both.
- */
- if (pcibios_get_version() >= 0x0210 && pt == NULL) {
- sigaddr = bios_sigsearch(0, "$PIR", 4, 16, 0);
- if (sigaddr == 0)
- sigaddr = bios_sigsearch(0, "_PIR", 4, 16, 0);
- if (sigaddr != 0) {
- pt = (struct PIR_table *)(uintptr_t)
- BIOS_PADDRTOVADDR(sigaddr);
- for (cv = (u_int8_t *)pt, ck = 0, i = 0;
- i < (pt->pt_header.ph_length); i++) {
- ck += cv[i];
- }
- if (ck == 0 && pt->pt_header.ph_length >
- sizeof(struct PIR_header)) {
- pci_route_table = pt;
- pci_route_count = (pt->pt_header.ph_length -
- sizeof(struct PIR_header)) /
- sizeof(struct PIR_entry);
- printf("Using $PIR table, %d entries at %p\n",
- pci_route_count, pci_route_table);
- if (bootverbose)
- pci_print_route_table(pci_route_table,
- pci_route_count);
- }
- }
- }
+ return (0);
mtx_init(&pcicfg_mtx, "pcicfg", NULL, MTX_SPIN);
opened = 1;
- return(1);
+ return (1);
}
/*
@@ -183,60 +80,22 @@ u_int32_t
pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
{
uint32_t line;
-#ifdef APIC_IO
- uint32_t pin;
-
- /*
- * If we are using the APIC, the contents of the intline
- * register will probably be wrong (since they are set up for
- * use with the PIC. Rather than rewrite these registers
- * (maybe that would be smarter) we trap attempts to read them
- * and translate to our private vector numbers.
- */
- if ((reg == PCIR_INTLINE) && (bytes == 1)) {
-
- pin = pcireg_cfgread(bus, slot, func, PCIR_INTPIN, 1);
- line = pcireg_cfgread(bus, slot, func, PCIR_INTLINE, 1);
- if (pin != 0) {
- int airq;
-
- airq = pci_apic_irq(bus, slot, pin);
- if (airq >= 0) {
- /* PCI specific entry found in MP table */
- if (airq != line)
- undirect_pci_irq(line);
- return(airq);
- } else {
- /*
- * PCI interrupts might be redirected
- * to the ISA bus according to some MP
- * tables. Use the same methods as
- * used by the ISA devices devices to
- * find the proper IOAPIC int pin.
- */
- airq = isa_apic_irq(line);
- if ((airq >= 0) && (airq != line)) {
- /* XXX: undirect_pci_irq() ? */
- undirect_isa_irq(line);
- return(airq);
- }
- }
- }
- return(line);
- }
-#else
/*
* Some BIOS writers seem to want to ignore the spec and put
- * 0 in the intline rather than 255 to indicate none. The rest of
- * the code uses 255 as an invalid IRQ.
+ * 0 in the intline rather than 255 to indicate none. Some use
+ * numbers in the range 128-254 to indicate something strange and
+ * apparently undocumented anywhere. Assume these are completely bogus
+ * and map them to 255, which the rest of the PCI code recognizes as
+ * as an invalid IRQ.
*/
if (reg == PCIR_INTLINE && bytes == 1) {
line = pcireg_cfgread(bus, slot, func, PCIR_INTLINE, 1);
- return pci_i386_map_intline(line);
+ if (line == 0 || line >= 128)
+ line = PCI_INVALID_IRQ;
+ return (line);
}
-#endif /* APIC_IO */
- return(pcireg_cfgread(bus, slot, func, reg, bytes));
+ return (pcireg_cfgread(bus, slot, func, reg, bytes));
}
/*
@@ -255,342 +114,10 @@ pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes)
int
pci_cfgintr(int bus, int device, int pin, int oldirq)
{
- struct PIR_entry *pe;
- int i, irq;
- struct bios_regs args;
- u_int16_t v;
- int already = 0;
- int errok = 0;
-
- v = pcibios_get_version();
- if (v < 0x0210) {
- PRVERB((
- "pci_cfgintr: BIOS %x.%02x doesn't support interrupt routing\n",
- (v & 0xff00) >> 8, v & 0xff));
- return (PCI_INVALID_IRQ);
- }
- if ((bus < 0) || (bus > 255) || (device < 0) || (device > 255) ||
- (pin < 1) || (pin > 4))
- return(PCI_INVALID_IRQ);
-
- /*
- * Scan the entry table for a contender
- */
- for (i = 0, pe = &pci_route_table->pt_entry[0]; i < pci_route_count;
- i++, pe++) {
- if ((bus != pe->pe_bus) || (device != pe->pe_device))
- continue;
- /*
- * A link of 0 means that this intpin is not connected to
- * any other device's interrupt pins and is not connected to
- * any of the Interrupt Router's interrupt pins, so we can't
- * route it.
- */
- if (pe->pe_intpin[pin - 1].link == 0)
- continue;
-
- if (pci_cfgintr_valid(pe, pin, oldirq)) {
- printf("pci_cfgintr: %d:%d INT%c BIOS irq %d\n", bus,
- device, 'A' + pin - 1, oldirq);
- return (oldirq);
- }
-
- /*
- * We try to find a linked interrupt, then we look to see
- * if the interrupt is uniquely routed, then we look for
- * a virgin interrupt. The virgin interrupt should return
- * an interrupt we can route, but if that fails, maybe we
- * should try harder to route a different interrupt.
- * However, experience has shown that that's rarely the
- * failure mode we see.
- */
- irq = pci_cfgintr_linked(pe, pin);
- if (irq != PCI_INVALID_IRQ)
- already = 1;
- if (irq == PCI_INVALID_IRQ) {
- irq = pci_cfgintr_unique(pe, pin);
- if (irq != PCI_INVALID_IRQ)
- errok = 1;
- }
- if (irq == PCI_INVALID_IRQ)
- irq = pci_cfgintr_virgin(pe, pin);
- if (irq == PCI_INVALID_IRQ)
- break;
-
- /*
- * Ask the BIOS to route the interrupt. If we picked an
- * interrupt that failed, we should really try other
- * choices that the BIOS offers us.
- *
- * For uniquely routed interrupts, we need to try
- * to route them on some machines. Yet other machines
- * fail to route, so we have to pretend that in that
- * case it worked. Isn't pc hardware fun?
- *
- * NOTE: if we want to whack hardware to do this, then
- * I think the right way to do that would be to have
- * bridge drivers that do this. I'm not sure that the
- * $PIR table would be valid for those interrupt
- * routers.
- */
- args.eax = PCIBIOS_ROUTE_INTERRUPT;
- args.ebx = (bus << 8) | (device << 3);
- /* pin value is 0xa - 0xd */
- args.ecx = (irq << 8) | (0xa + pin - 1);
- if (!already &&
- bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL)) &&
- !errok) {
- PRVERB(("pci_cfgintr: ROUTE_INTERRUPT failed.\n"));
- return(PCI_INVALID_IRQ);
- }
- printf("pci_cfgintr: %d:%d INT%c routed to irq %d\n", bus,
- device, 'A' + pin - 1, irq);
- return(irq);
- }
-
- PRVERB(("pci_cfgintr: can't route an interrupt to %d:%d INT%c\n", bus,
- device, 'A' + pin - 1));
- return(PCI_INVALID_IRQ);
-}
-
-/*
- * Check to see if an existing IRQ setting is valid.
- */
-static int
-pci_cfgintr_valid(struct PIR_entry *pe, int pin, int irq)
-{
- uint32_t irqmask;
- if (!PCI_INTERRUPT_VALID(irq))
- return (0);
- irqmask = pe->pe_intpin[pin - 1].irqs;
- if (irqmask & (1 << irq)) {
- PRVERB(("pci_cfgintr_valid: BIOS irq %d is valid\n", irq));
- return (1);
- }
- return (0);
-}
-
-/*
- * Look to see if the routing table claims this pin is uniquely routed.
- */
-static int
-pci_cfgintr_unique(struct PIR_entry *pe, int pin)
-{
- int irq;
- uint32_t irqmask;
-
- irqmask = pe->pe_intpin[pin - 1].irqs;
- if (irqmask != 0 && powerof2(irqmask)) {
- irq = ffs(irqmask) - 1;
- PRVERB(("pci_cfgintr_unique: hard-routed to irq %d\n", irq));
- return(irq);
- }
- return(PCI_INVALID_IRQ);
-}
-
-/*
- * Look for another device which shares the same link byte and
- * already has a unique IRQ, or which has had one routed already.
- */
-static int
-pci_cfgintr_linked(struct PIR_entry *pe, int pin)
-{
- struct PIR_entry *oe;
- struct PIR_intpin *pi;
- int i, j, irq;
-
- /*
- * Scan table slots.
- */
- for (i = 0, oe = &pci_route_table->pt_entry[0]; i < pci_route_count;
- i++, oe++) {
- /* scan interrupt pins */
- for (j = 0, pi = &oe->pe_intpin[0]; j < 4; j++, pi++) {
-
- /* don't look at the entry we're trying to match */
- if ((pe == oe) && (i == (pin - 1)))
- continue;
- /* compare link bytes */
- if (pi->link != pe->pe_intpin[pin - 1].link)
- continue;
- /* link destination mapped to a unique interrupt? */
- if (pi->irqs != 0 && powerof2(pi->irqs)) {
- irq = ffs(pi->irqs) - 1;
- PRVERB(("pci_cfgintr_linked: linked (%x) to hard-routed irq %d\n",
- pi->link, irq));
- return(irq);
- }
-
- /*
- * look for the real PCI device that matches this
- * table entry
- */
- irq = pci_cfgintr_search(pe, oe->pe_bus, oe->pe_device,
- j, pin);
- if (irq != PCI_INVALID_IRQ)
- return(irq);
- }
- }
- return(PCI_INVALID_IRQ);
-}
-
-/*
- * Scan for the real PCI device at (bus)/(device) using intpin (matchpin) and
- * see if it has already been assigned an interrupt.
- */
-static int
-pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int pin)
-{
- devclass_t pci_devclass;
- device_t *pci_devices;
- int pci_count;
- device_t *pci_children;
- int pci_childcount;
- device_t *busp, *childp;
- int i, j, irq;
-
- /*
- * Find all the PCI busses.
- */
- pci_count = 0;
- if ((pci_devclass = devclass_find("pci")) != NULL)
- devclass_get_devices(pci_devclass, &pci_devices, &pci_count);
-
- /*
- * Scan all the PCI busses/devices looking for this one.
- */
- irq = PCI_INVALID_IRQ;
- for (i = 0, busp = pci_devices; (i < pci_count) && (irq == PCI_INVALID_IRQ);
- i++, busp++) {
- pci_childcount = 0;
- device_get_children(*busp, &pci_children, &pci_childcount);
-
- for (j = 0, childp = pci_children; j < pci_childcount; j++,
- childp++) {
- if ((pci_get_bus(*childp) == bus) &&
- (pci_get_slot(*childp) == device) &&
- (pci_get_intpin(*childp) == matchpin)) {
- irq = pci_i386_map_intline(pci_get_irq(*childp));
- if (irq != PCI_INVALID_IRQ)
- PRVERB(("pci_cfgintr_search: linked (%x) to configured irq %d at %d:%d:%d\n",
- pe->pe_intpin[pin - 1].link, irq,
- pci_get_bus(*childp),
- pci_get_slot(*childp),
- pci_get_function(*childp)));
- break;
- }
- }
- if (pci_children != NULL)
- free(pci_children, M_TEMP);
- }
- if (pci_devices != NULL)
- free(pci_devices, M_TEMP);
- return(irq);
-}
-
-/*
- * Pick a suitable IRQ from those listed as routable to this device.
- */
-static int
-pci_cfgintr_virgin(struct PIR_entry *pe, int pin)
-{
- int irq, ibit;
-
- /*
- * first scan the set of PCI-only interrupts and see if any of these
- * are routable
- */
- for (irq = 0; irq < 16; irq++) {
- ibit = (1 << irq);
-
- /* can we use this interrupt? */
- if ((pci_route_table->pt_header.ph_pci_irqs & ibit) &&
- (pe->pe_intpin[pin - 1].irqs & ibit)) {
- PRVERB(("pci_cfgintr_virgin: using routable PCI-only interrupt %d\n", irq));
- return(irq);
- }
- }
-
- /* life is tough, so just pick an interrupt */
- for (irq = 0; irq < 16; irq++) {
- ibit = (1 << irq);
- if (pe->pe_intpin[pin - 1].irqs & ibit) {
- PRVERB(("pci_cfgintr_virgin: using routable interrupt %d\n", irq));
- return(irq);
- }
- }
- return(PCI_INVALID_IRQ);
-}
-
-static void
-pci_print_irqmask(u_int16_t irqs)
-{
- int i, first;
-
- if (irqs == 0) {
- printf("none");
- return;
- }
- first = 1;
- for (i = 0; i < 16; i++, irqs >>= 1)
- if (irqs & 1) {
- if (!first)
- printf(" ");
- else
- first = 0;
- printf("%d", i);
- }
-}
-
-/*
- * Dump the contents of a PCI BIOS Interrupt Routing Table to the console.
- */
-static void
-pci_print_route_table(struct PIR_table *prt, int size)
-{
- struct PIR_entry *entry;
- struct PIR_intpin *intpin;
- int i, pin;
-
- printf("PCI-Only Interrupts: ");
- pci_print_irqmask(prt->pt_header.ph_pci_irqs);
- printf("\nLocation Bus Device Pin Link IRQs\n");
- entry = &prt->pt_entry[0];
- for (i = 0; i < size; i++, entry++) {
- intpin = &entry->pe_intpin[0];
- for (pin = 0; pin < 4; pin++, intpin++)
- if (intpin->link != 0) {
- if (entry->pe_slot == 0)
- printf("embedded ");
- else
- printf("slot %-3d ", entry->pe_slot);
- printf(" %3d %3d %c 0x%02x ",
- entry->pe_bus, entry->pe_device,
- 'A' + pin, intpin->link);
- pci_print_irqmask(intpin->irqs);
- printf("\n");
- }
- }
-}
-
-/*
- * See if any interrupts for a given PCI bus are routed in the PIR. Don't
- * even bother looking if the BIOS doesn't support routing anyways.
- */
-int
-pci_probe_route_table(int bus)
-{
- int i;
- u_int16_t v;
-
- v = pcibios_get_version();
- if (v < 0x0210)
- return (0);
- for (i = 0; i < pci_route_count; i++)
- if (pci_route_table->pt_entry[i].pe_bus == bus)
- return (1);
- return (0);
+ printf("pci_cfgintr: can't route an interrupt to %d:%d INT%c without ACPI\n", bus,
+ device, 'A' + pin - 1);
+ return (PCI_INVALID_IRQ);
}
/*
@@ -819,4 +346,3 @@ pcireg_cfgopen(void)
devmax = 0;
return (cfgmech);
}
-